0025418: Debug output to be limited to OCC development environment
[occt.git] / src / ShapeFix / ShapeFix_FixSmallFace.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
b311480e 13
7fd59977 14#include <ShapeFix_FixSmallFace.ixx>
15#include <TopoDS.hxx>
16#include <TopoDS_Shell.hxx>
17#include <TopoDS_Edge.hxx>
18#include <TopoDS_Vertex.hxx>
19#include <TopoDS_Iterator.hxx>
20#include <TopExp_Explorer.hxx>
21#include <TopExp.hxx>
22#include <BRep_Tool.hxx>
23
24#include <Geom_Curve.hxx>
25#include <Geom_Surface.hxx>
26#include <Geom_BSplineSurface.hxx>
27#include <Geom_BezierSurface.hxx>
28
29#include <ShapeAnalysis_Curve.hxx>
30//#include <GeomLProp_SLProps.hxx>
31#include <GeomAdaptor_Surface.hxx>
32#include <Geom_ElementarySurface.hxx>
33//#include <TColStd_Array2OfReal.hxx>
34#include <gp_Dir.hxx>
35#include <gp_Vec.hxx>
36//#include <TColStd_Array1OfReal.hxx>
37#include <TColgp_Array1OfPnt.hxx>
38#include <TopTools_Array1OfShape.hxx>
39
40#include <TColgp_Array2OfPnt.hxx>
41
42#include <TColgp_SequenceOfXYZ.hxx>
43#include <BRep_Builder.hxx>
44#include <ShapeBuild_ReShape.hxx>
45#include <BRepTools.hxx>
46#include <ShapeFix_Edge.hxx>
47#include <Precision.hxx>
48#include <TopoDS_Wire.hxx>
49#include <ShapeFix_Wire.hxx>
50#include <Geom_Line.hxx>
51#include <TopExp.hxx>
52#include <ElCLib.hxx>
53#include <TopoDS_Builder.hxx>
54#include <TopoDS_Compound.hxx>
55#include <Poly_Polygon3D.hxx>
56#include <Geom2d_Curve.hxx>
57#include <BRepLib.hxx>
58#include <GeomLib.hxx>
59#include <ShapeFix_Face.hxx>
60#include <ShapeFix_Wire.hxx>
61#include <Geom_TrimmedCurve.hxx>
62#include <GeomAdaptor_Curve.hxx>
63#include <ShapeFix_Shape.hxx>
64#include <Precision.hxx>
65#include <TopExp_Explorer.hxx>
66#include <TopTools_DataMapOfShapeListOfShape.hxx>
67#include <ShapeAnalysis_DataMapOfShapeListOfReal.hxx>
68#include <TopoDS_Compound.hxx>
69#include <TopoDS_Iterator.hxx>
b311480e 70
7fd59977 71ShapeFix_FixSmallFace::ShapeFix_FixSmallFace()
72{
73 myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
74 SetPrecision(Precision::Confusion());
75
76}
77
78 void ShapeFix_FixSmallFace::Init(const TopoDS_Shape& S)
79{
80 myShape = S;
81 if ( Context().IsNull() )
82 SetContext ( new ShapeBuild_ReShape );
83 myResult = myShape;
84 Context()->Apply(myShape);
85}
86
87
88 void ShapeFix_FixSmallFace::Perform()
89{
90 FixSpotFace();
91 FixStripFace();
92}
93
94 TopoDS_Shape ShapeFix_FixSmallFace::FixSpotFace()
95{
96
97 // gp_Pnt spot;
98 // Standard_Real spotol;
99 Standard_Boolean done = Standard_False;
100 TopAbs_ShapeEnum st = myShape.ShapeType();
101 if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID || st == TopAbs_SOLID || st == TopAbs_SHELL || st == TopAbs_FACE) {
102 for (TopExp_Explorer itf (myShape,TopAbs_FACE); itf.More(); itf.Next()) {
103//smh#8
104 TopoDS_Shape tmpFace = Context()->Apply(itf.Current());
105 TopoDS_Face F = TopoDS::Face (tmpFace);
106 if(F.IsNull()) continue;
107 if (myAnalyzer.CheckSpotFace (F,Precision()))
108 {
109 ReplaceVerticesInCaseOfSpot(F,Precision());
110 RemoveFacesInCaseOfSpot(F);
111 myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
112 done = Standard_True;
113 }
114 }
115 myShape = Context()->Apply(myShape);
116 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
117 if (done)
118 {
119 if (myShape.IsNull()) return myShape;
120 /*ShapeFix_Wire sfw;
121 sfw.SetContext(Context());
122 sfw.SetPrecision(Precision::Confusion());
123 if (myShape.IsNull()) return myShape;
124 for (TopExp_Explorer itfw (myShape,TopAbs_FACE); itfw.More(); itfw.Next()) {
125 for (TopExp_Explorer itw (myShape,TopAbs_WIRE); itw.More(); itw.Next()) {
126 TopoDS_Wire w = TopoDS::Wire(itw.Current());
127 sfw.Init(w, TopoDS::Face(itfw.Current()), Precision::Confusion());
128 sfw->FixNotchedEdgesMode() = 0;
129 if(sfw.Perform())
130 Context()->Replace(w, sfw.Wire());
131 }
132 }*/
133 myShape = FixShape();
134 }
135
136 //myShape = Context()->Apply(myShape);
137 myResult = myShape;
138 }
139 return myShape;
140}
141
142 Standard_Boolean ShapeFix_FixSmallFace::ReplaceVerticesInCaseOfSpot(TopoDS_Face& F,const Standard_Real /*tol*/) const
143{
144
145 TColgp_SequenceOfXYZ thePositions;
146 gp_XYZ thePosition;
147 BRep_Builder theBuilder;
148 Standard_Real theMaxDev;
149 Standard_Real theMaxTol = 0.0;
150 thePositions.Clear();
151 gp_Pnt thePoint;
152//smh#8
153 TopoDS_Shape tmpFace = Context()->Apply(F);
154 F = TopoDS::Face(tmpFace);
155 // gka Mar2000 Protection against faces without wires
156 // but they occur due to bugs in the algorithm itself, it needs to be fixed
157 Standard_Boolean isWir = Standard_False;
158 for(TopoDS_Iterator itw(F,Standard_False) ; itw.More();itw.Next()) {
159 if(itw.Value().ShapeType() != TopAbs_WIRE)
160 continue;
161 TopoDS_Wire w1 = TopoDS::Wire(itw.Value());
162 if (!w1.IsNull()) {isWir = Standard_True; break;}
163 }
164 if(!isWir) return Standard_True;
165 //Accumulating positions and maximal vertex tolerance
166 for (TopExp_Explorer iter_vertex(F,TopAbs_VERTEX); iter_vertex.More(); iter_vertex.Next()) {
167 TopoDS_Vertex V = TopoDS::Vertex (iter_vertex.Current());
168 thePoint = BRep_Tool::Pnt(V);
169 if (theMaxTol <= (BRep_Tool::Tolerance(V))) theMaxTol = BRep_Tool::Tolerance(V);
170 thePositions.Append(thePoint.XYZ());
171 }
172 //Calculate common vertex position
173 thePosition = gp_XYZ(0.,0.,0.);
174 Standard_Integer theNbPos = thePositions.Length();
175 Standard_Integer i; // svv Jan11 2000 : porting on DEC
176 for ( i = 1; i <= theNbPos; i++ ) thePosition += thePositions.Value(i);
177 if ( theNbPos > 1 ) thePosition /= theNbPos;
178
179 // Calculate maximal deviation
180 theMaxDev = 0.;
181 for ( i = 1; i <= theNbPos; i++ ) {
182 Standard_Real theDeviation = (thePosition-thePositions.Value(i)).Modulus();
183 if ( theDeviation > theMaxDev ) theMaxDev = theDeviation;
184 }
185 theMaxDev *= 1.00001;
186
187 //Cretate new vertex with mean point
188 TopoDS_Vertex theSharedVertex;
189 theBuilder.MakeVertex(theSharedVertex);
190 theBuilder.UpdateVertex( theSharedVertex, gp_Pnt(thePosition), theMaxDev+theMaxTol/2 );
191 //Use external tolerance
192// if (tol!=-1.0) theBuilder.UpdateVertex( theSharedVertex, tol);
193 //Replacing all vertices in the face by new one
194 TopoDS_Vertex theNewVertex;
195 for ( TopExp_Explorer iter_vert(F,TopAbs_VERTEX); iter_vert.More(); iter_vert.Next()) {
196 TopoDS_Vertex V = TopoDS::Vertex (iter_vert.Current());
197 if (V.Orientation()==TopAbs_FORWARD)
198//smh#8
199 {
200 TopoDS_Shape tmpVertexFwd = theSharedVertex.Oriented(TopAbs_FORWARD);
201 theNewVertex = TopoDS::Vertex(tmpVertexFwd);
202 }
203 else
204//smh#8
205 {
206 TopoDS_Shape tmpVertexRev = theSharedVertex.Oriented(TopAbs_REVERSED);
207 theNewVertex = TopoDS::Vertex(tmpVertexRev);
208 }
209 Context()->Replace(V, theNewVertex);
210 }
211 return Standard_True;
212}
213
214 Standard_Boolean ShapeFix_FixSmallFace::RemoveFacesInCaseOfSpot(const TopoDS_Face& F) const
215{
216 for ( TopExp_Explorer iter_vert(F,TopAbs_EDGE); iter_vert.More(); iter_vert.Next()) {
217 TopoDS_Edge Ed = TopoDS::Edge (iter_vert.Current());
218 Context()->Remove(Ed);
219 }
220 Context()->Remove(F);
221 return Standard_True;
222
223
224}
225
226 TopoDS_Shape ShapeFix_FixSmallFace::FixStripFace(const Standard_Boolean wasdone)
227{
228 if(myShape.IsNull()) return myShape;
229 TopAbs_ShapeEnum st = myShape.ShapeType();
230 // BRep_Builder theBuilder;
231 Standard_Boolean done = wasdone;
232 if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID ||st == TopAbs_SOLID || st == TopAbs_SHELL || st == TopAbs_FACE) {
233 for (TopExp_Explorer itf (myShape,TopAbs_FACE); itf.More(); itf.Next()) {
234 TopoDS_Face F = TopoDS::Face (itf.Current());
235//smh#8
236 TopoDS_Shape tmpFace = Context()->Apply(F);
237 F= TopoDS::Face(tmpFace);
238 if(F.IsNull()) continue;
239 // Standard_Real dmax = 1;
240 TopoDS_Edge E1,E2;
241 if (myAnalyzer.CheckStripFace (F, E1,E2,Precision()))
242 {
243 if(ReplaceInCaseOfStrip(F,E1,E2, Precision()))
244 RemoveFacesInCaseOfStrip(F);
245 myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
246 done = Standard_True;
247 }
248 }
249 myShape = Context()->Apply(myShape);
250 //Particular case of empty shell
251 if (!myShape.IsNull())
252 {
253 for (TopExp_Explorer exp_s (myShape,TopAbs_SHELL); exp_s.More(); exp_s.Next()) {
254 TopoDS_Shell Sh = TopoDS::Shell (exp_s.Current());
255 TopExp_Explorer ex_sh(Sh,TopAbs_FACE);
256 if (!ex_sh.More()) { Context()->Remove(Sh);
257// cout << "Empty shell was removed" << endl;
258 }
259 }
260 myShape = Context()->Apply(myShape);
261 //Fixing of missing pcurves on new edges, if thay were inserted
262 if (done)
263 {
264 if (myShape.IsNull()) return myShape;
265 TopoDS_Shape theResult;
266 myShape = FixShape();
267 //myShape = Context()->Apply(myShape);
268 myResult = myShape;
269 }
270
271 }
272 }
273 return myShape;
274
275}
276
277 Standard_Boolean ShapeFix_FixSmallFace::ReplaceInCaseOfStrip(TopoDS_Face& F,TopoDS_Edge& E1,TopoDS_Edge& E2, const Standard_Real tol) const
278{
279 if(E1.IsNull() || E2.IsNull()) return Standard_False;
280 TopoDS_Edge theSharedEdge;
281 TopoDS_Face F1,F2;
282//smh#8
283 TopoDS_Shape tmpFace = Context()->Apply(F);
284 F= TopoDS::Face(tmpFace);
285 for(TopExp_Explorer expf(myShape,TopAbs_FACE); expf.More(); expf.Next()) {
286//smh#8
287 TopoDS_Shape tmpShape = Context()->Apply(expf.Current());
288 TopoDS_Face tempF = TopoDS::Face (tmpShape);
289 if(tempF.IsNull() || tempF.IsSame(F)) continue;
290 for(TopExp_Explorer expe(tempF,TopAbs_EDGE); expe.More(); expe.Next()) {
291 TopoDS_Edge tempE = TopoDS::Edge (expe.Current());
292 if(tempE.IsSame(E1)) F1 = tempF;
293 if(tempE.IsSame(E2)) F2 = tempF;
294 if(!F1.IsNull()) break; // && !F2.IsNull()) break;
295 }
296 }
297
298 //Compute shared edge for this face
299 if(F1.IsNull() && F2.IsNull()) return Standard_True;
300 TopoDS_Edge E1tmp = E1;
301 TopoDS_Edge E2tmp = E2;
302 if(F1.IsNull()) {
303 E1tmp = E2;
304 E2tmp = E1;
305 F1 = F2;
306 }
307 theSharedEdge = ComputeSharedEdgeForStripFace(F, E1tmp, E2tmp, F1, tol);
308 //Replace two long edges by new one
309 if (theSharedEdge.IsNull()) return Standard_False;
310 if (E1.Orientation()==TopAbs_REVERSED) {
311 Context()->Replace(E1tmp, theSharedEdge.Oriented(TopAbs_REVERSED));
312 if(F.Orientation() == F1.Orientation())
313 Context()->Replace(E2tmp, theSharedEdge);
314 else
315 Context()->Replace(E2tmp, theSharedEdge.Oriented(TopAbs_REVERSED));
316 }
317 else
318 {
319 Context()->Replace(E1tmp, theSharedEdge);
320 if(F.Orientation() == F1.Orientation())
321 Context()->Replace(E2tmp, theSharedEdge.Oriented(TopAbs_REVERSED));
322 else
323 Context()->Replace(E2tmp, theSharedEdge);
324 }
325
326 //Remove short edges
327 for (TopExp_Explorer exp_e (F,TopAbs_EDGE); exp_e.More(); exp_e.Next()) {
328 TopoDS_Edge shortedge = TopoDS::Edge (exp_e.Current());
329 if (!shortedge.IsSame(E1tmp) && !shortedge.IsSame(E2tmp)) Context()->Remove(shortedge);
330 }
331
332 return Standard_True;
333}
334
335 Standard_Boolean ShapeFix_FixSmallFace::RemoveFacesInCaseOfStrip(const TopoDS_Face& F) const
336{
337 Context()->Remove(F);
338 return Standard_True;
339}
340
341 TopoDS_Edge ShapeFix_FixSmallFace::ComputeSharedEdgeForStripFace(const TopoDS_Face& /*F*/,const TopoDS_Edge& E1,const TopoDS_Edge& E2,const TopoDS_Face& F1,const Standard_Real tol) const
342{
343
344 BRep_Builder theBuilder;
345 //Compute deviation between two vertices and create new vertices
346 TopoDS_Edge theNewEdge;
347 TopoDS_Vertex V1,V2, V3, V4;
348 TopExp::Vertices (E1,V1,V2);
349 TopExp::Vertices (E2,V3,V4);
350 gp_Pnt p1, p2;
351 Standard_Real dev;
352 p1 = BRep_Tool::Pnt(V1);
353 p2 = BRep_Tool::Pnt(V3);
354 dev = p1.Distance(p2);
355 TopoDS_Vertex theFirstVer;
356 TopoDS_Vertex theSecondVer;
357 theBuilder.MakeVertex(theFirstVer);
358 theBuilder.MakeVertex(theSecondVer);
359 gp_XYZ thePosition;
360 TopoDS_Shape temp;
361
362 if ((dev<=BRep_Tool::Tolerance (V1)) || (dev<=BRep_Tool::Tolerance (V3)) || (dev<=tol)) {
363 if (V1.IsSame(V3))
364// #ifdef AIX CKY : applies to all platforms
365 theFirstVer = V1;
366// theFirstVer = TopoDS::Vertex(V1);
367
368 else {
369 dev = (dev/2)*1.0001;
370 thePosition = (p1.XYZ()+p2.XYZ())/2;
371 theBuilder.UpdateVertex(theFirstVer, gp_Pnt(thePosition), dev );
372 //if(Context()->Status(V1, temp) != 0) theFirstVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
373 //else //take recorded vertex
374 // if(theRepVert->Status(V3, temp) != 0) theFirstVer = TopoDS::Vertex (temp);
375 if (V1.Orientation()==TopAbs_FORWARD) Context()->Replace(V1, theFirstVer.Oriented(TopAbs_FORWARD));
376 else Context()->Replace(V1, theFirstVer.Oriented(TopAbs_REVERSED));
377 if (V3.Orientation()==TopAbs_FORWARD) Context()->Replace(V3, theFirstVer.Oriented(TopAbs_FORWARD));
378 else Context()->Replace(V3, theFirstVer.Oriented(TopAbs_REVERSED));
379
380 }
381 if(V1.IsSame(V2) || V3.IsSame(V4))
382 theSecondVer = theFirstVer;
383 else {
384 if (!V2.IsSame(V4)) {
385 // #ifdef AIX CKY : applies to all platforms
386
387 p1 = BRep_Tool::Pnt(V2);
388 p2 = BRep_Tool::Pnt(V4);
389 dev = p1.Distance(p2);
390 thePosition = (p1.XYZ()+p2.XYZ())/2;
391 theBuilder.UpdateVertex(theSecondVer, gp_Pnt(thePosition), dev );
392 //if(theRepVert->Status(V2, temp) != 0) theSecondVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
393 //else
394 // if(theRepVert->Status(V4, temp) != 0) theSecondVer = TopoDS::Vertex (temp);
395 }
396 else theSecondVer = V2;
397
398 }
399 if (!V2.IsSame(theSecondVer)) {
400 if (V2.Orientation()==TopAbs_FORWARD) Context()->Replace(V2, theSecondVer.Oriented(TopAbs_FORWARD));
401 else Context()->Replace(V2, theSecondVer.Oriented(TopAbs_REVERSED));
402 if (V4.Orientation()==TopAbs_FORWARD) Context()->Replace(V4, theSecondVer.Oriented(TopAbs_FORWARD));
403 else Context()->Replace(V4, theSecondVer.Oriented(TopAbs_REVERSED));
404 }
405 }
406 else {
407 p2 = BRep_Tool::Pnt(V4);
408 dev = p1.Distance(p2);
409 if ((dev<=BRep_Tool::Tolerance (V1)) || (dev<=BRep_Tool::Tolerance (V4)) || (dev<=tol)) {
410 if (V1.IsSame(V4))
411// #ifdef AIX CKY : applies to all platforms
412 theFirstVer = V1;
413// theFirstVer = TopoDS::Vertex(V1);
414
415 else {
416 dev = (dev/2)*1.0001;
417 thePosition = (p1.XYZ()+p2.XYZ())/2;
418 theBuilder.UpdateVertex(theFirstVer, gp_Pnt(thePosition), dev );
419 // if(theRepVert->Status(V1, temp) != 0) theFirstVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
420 // else
421 // if(theRepVert->Status(V4, temp) != 0) theFirstVer = TopoDS::Vertex (temp);
422 if (V1.Orientation()==TopAbs_FORWARD) Context()->Replace(V1, theFirstVer.Oriented(TopAbs_FORWARD));
423 else Context()->Replace(V1, theFirstVer.Oriented(TopAbs_REVERSED));
424 if (V4.Orientation()==TopAbs_FORWARD) Context()->Replace(V4, theFirstVer.Oriented(TopAbs_FORWARD));
425 else Context()->Replace(V4, theFirstVer.Oriented(TopAbs_REVERSED));
426 }
427 if(V1.IsSame(V2) || V3.IsSame(V4))
428 theSecondVer = theFirstVer;
429 else {
430
431 if (!V2.IsSame(V3)) {
432 p1 = BRep_Tool::Pnt(V2);
433 p2 = BRep_Tool::Pnt(V3);
434 dev = p1.Distance(p2);
435 thePosition = (p1.XYZ()+p2.XYZ())/2;
436 theBuilder.UpdateVertex(theSecondVer, gp_Pnt(thePosition), dev );
437 }
438 else theSecondVer = V2;
439 }
440 // if(theRepVert->Status(V2, temp) != 0) theSecondVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
441 // else
442 // if(theRepVert->Status(V3, temp) != 0) theSecondVer = TopoDS::Vertex (temp);
443 if (!V2.IsSame(theSecondVer)) {
444 if (V2.Orientation()==TopAbs_FORWARD) Context()->Replace(V2, theSecondVer.Oriented(TopAbs_FORWARD));
445 else Context()->Replace(V2, theSecondVer.Oriented(TopAbs_REVERSED));
446 if (V3.Orientation()==TopAbs_FORWARD) Context()->Replace(V3, theSecondVer.Oriented(TopAbs_FORWARD));
447 else Context()->Replace(V3, theSecondVer.Oriented(TopAbs_REVERSED));
448 }
449
450 }
451 else {
0797d9d3 452#ifdef OCCT_DEBUG
7fd59977 453 cout << "The face is not strip face" << endl;
454#endif
455 return theNewEdge;
456 }
457 }
458 if (theFirstVer.IsNull() || theSecondVer.IsNull()) return theNewEdge;
459 //Cretate new edge
460 theBuilder.MakeEdge(theNewEdge);
461 Standard_Real f, l, fp1, lp1/*, fp2, lp2*/;
462 TopLoc_Location loc;
463 Handle(Geom_Curve) the3dcurve;
464 the3dcurve = BRep_Tool::Curve(E1, f, l);
465 Handle(Geom2d_Curve) the2dcurve1, the2dcurve2, thenew1, thenew2;
466 if (!F1.IsNull())
467 {
468 the2dcurve1 = BRep_Tool::CurveOnSurface(E1, F1, fp1, lp1);
469 if(!the2dcurve1.IsNull() && fp1!=f && lp1!=l) GeomLib::SameRange(Precision::Confusion(), the2dcurve1, fp1, lp1, f, l, thenew1);
470 }
471
472 /* if (!F2.IsNull())
473 {
474 the2dcurve2 = BRep_Tool::CurveOnSurface(E2, F2, fp2, lp2);
475 if(!the2dcurve2.IsNull()) GeomLib::SameRange(Precision::Confusion(), the2dcurve2, fp2, lp2, f, l, thenew2);
476 }*/
477
478 Standard_Real maxdev;
479 if ((BRep_Tool::Tolerance(theFirstVer))<=(BRep_Tool::Tolerance(theSecondVer)))
480 maxdev = (BRep_Tool::Tolerance(theSecondVer));
481 else maxdev = (BRep_Tool::Tolerance(theFirstVer));
482 theBuilder.UpdateVertex(theFirstVer, maxdev);
483 theBuilder.UpdateVertex(theSecondVer, maxdev);
484 //Standard_Boolean IsFree = Standard_True;
485 theBuilder.SameParameter(theNewEdge, Standard_False);
486 the3dcurve = BRep_Tool::Curve(E1, f, l);
487 theBuilder.UpdateEdge(theNewEdge, the3dcurve, maxdev);
488 theBuilder.Range(theNewEdge, f, l);
489 if (!F1.IsNull() && !thenew1.IsNull())
490 {
491 theBuilder.UpdateEdge(theNewEdge, thenew1, F1, maxdev);
492 //IsFree = Standard_False;
493 }
494 /*if (!F2.IsNull() && !thenew2.IsNull())
495 {
496 theBuilder.UpdateEdge(theNewEdge, thenew2, F2, maxdev);
497 IsFree = Standard_False;
498 }*/
499 theBuilder.Add(theNewEdge, theFirstVer.Oriented(TopAbs_FORWARD));
500 theBuilder.Add(theNewEdge, theSecondVer.Oriented(TopAbs_REVERSED));
501 //Call fixsameparameter for computing distance between 3d and pcurves, if edge is not free
502// if (!IsFree)
503// {
504// ShapeFix_Edge sfe;
505// if (!F1.IsNull() && !thenew1.IsNull()) sfe.FixReversed2d(theNewEdge, F1);
506// if (!F2.IsNull() && !thenew2.IsNull()) sfe.FixReversed2d(theNewEdge, F2);
507// sfe.FixSameParameter(theNewEdge, maxdev);
508// }
509 return theNewEdge;
510
511
512}
513
514 TopoDS_Shape ShapeFix_FixSmallFace::FixSplitFace(const TopoDS_Shape& /*S*/)
515{
516 if (myShape.IsNull()) return myShape;
517 TopAbs_ShapeEnum st = myShape.ShapeType();
518 Standard_Boolean done = Standard_False;
519 TopoDS_Compound theSplittedFaces;
520 BRep_Builder theBuilder;
521 if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID ||
522 st == TopAbs_SOLID || st == TopAbs_SHELL || st == TopAbs_FACE) {
523 for (TopExp_Explorer itf (myShape,TopAbs_FACE); itf.More(); itf.Next()) {
524 TopoDS_Face F = TopoDS::Face (itf.Current());
525 TopoDS_Compound CompSplittedFaces;
526 theBuilder.MakeCompound(CompSplittedFaces);
527 if(SplitOneFace(F, CompSplittedFaces)) {
528 done = Standard_True;
529 Context()->Replace(F, CompSplittedFaces);
530 }
531 }
532 }
533 if(done) myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
534 myShape = Context()->Apply(myShape);
535 myResult = myShape;
536 return myShape;
537}
538
539 TopoDS_Shape ShapeFix_FixSmallFace::SplitFaces()
540{
541 myShape = RemoveSmallFaces();
542 myResult = myShape;
543 return myShape;
544
545}
546
547 Standard_Boolean ShapeFix_FixSmallFace::SplitOneFace(TopoDS_Face& F,TopoDS_Compound& theSplittedFaces)
548{
549 TopTools_DataMapOfShapeListOfShape MapEdges;
550 ShapeAnalysis_DataMapOfShapeListOfReal MapParam;
551 TopoDS_Compound theAllVert;
552 BRep_Builder theBuilder;
553 theBuilder.MakeCompound(theAllVert);
554//smh#8
555 TopoDS_Shape tmpShape = Context()->Apply(F);
556 F = TopoDS::Face(tmpShape);
557 if (myAnalyzer.CheckSplittingVertices(F,MapEdges,MapParam,theAllVert) != 0)
558 {
559 TopoDS_Wire tempwire;
560 //Take information about splitting vertices
561 if (theAllVert.IsNull()) return Standard_False;
562 //Standard_Integer i;
563 TopoDS_Vertex V;
564 TopExp_Explorer itc(theAllVert,TopAbs_VERTEX); V = TopoDS::Vertex (itc.Current());
565 if (V.IsNull()) return Standard_False;
566 gp_Pnt proj;
567 gp_Pnt vp = BRep_Tool::Pnt(V);
568 TopoDS_Vertex theNewVertex;
569 TopoDS_Edge E;
570 TopoDS_Edge theFirstEdge, theSecondEdge;
571
572 {
573 //If one vertex presents do splitting by two faces
574 ShapeAnalysis_Curve SAC;
575 for (TopExp_Explorer ite(F,TopAbs_EDGE); ite.More(); ite.Next()) {
576 E = TopoDS::Edge (ite.Current());
577 TopoDS_Vertex V1,V2;
578 TopExp::Vertices (E,V1,V2);
579 Standard_Real cf,cl;
580 Handle(Geom_Curve) C3D = BRep_Tool::Curve (E,cf,cl);
581 if (C3D.IsNull()) continue;
582 if (V.IsSame(V1) || V.IsSame(V2)) continue;
583 Standard_Real vt = BRep_Tool::Tolerance (V);
584 Standard_Real param;
585 Standard_Real dist = SAC.Project (C3D,vp,vt*10.,proj,param,cf,cl);
586 if (dist==0) continue; //Projection on same curve but on other edge ?
587 if ( dist <= vt )
588 {
589 theBuilder.MakeVertex(theNewVertex);
590 theBuilder.UpdateVertex(theNewVertex, proj, Precision::Confusion());
591 theBuilder.MakeEdge(theFirstEdge);
592 theBuilder.MakeEdge(theSecondEdge);
593 Standard_Real f, l;
594 Handle(Geom_Curve) the3dcurve = BRep_Tool::Curve(E, f, l);
595 theBuilder.UpdateEdge(theFirstEdge, the3dcurve,Precision::Confusion());
596 theBuilder.UpdateEdge(theSecondEdge, the3dcurve,Precision::Confusion());
597 if (V1.Orientation()==TopAbs_FORWARD)
598 {
599 theBuilder.Add(theFirstEdge, V1);
600 theBuilder.Add(theFirstEdge,theNewVertex.Oriented(TopAbs_REVERSED));
601 theBuilder.Add(theSecondEdge,theNewVertex.Oriented(TopAbs_FORWARD));
602 theBuilder.Add(theSecondEdge, V2);
603 }
604 else {
605 theBuilder.Add(theFirstEdge,V2);
606 theBuilder.Add(theFirstEdge,theNewVertex.Oriented(TopAbs_REVERSED));
607 theBuilder.Add(theSecondEdge,theNewVertex.Oriented(TopAbs_FORWARD));
608 theBuilder.Add(theSecondEdge, V1);
609 }
610 theBuilder.Range(theFirstEdge, cf, param);
611 theBuilder.Range(theSecondEdge, param, cl);
612 //Replace old edge by two new edges
613 TopoDS_Wire twoedges;
614 theBuilder.MakeWire(twoedges);
615 if (E.Orientation() == TopAbs_FORWARD)
616 {
617 theBuilder.Add(twoedges, theFirstEdge.Oriented(TopAbs_FORWARD));
618 theBuilder.Add(twoedges, theSecondEdge.Oriented(TopAbs_FORWARD));
619 }
620 else
621 {
622 theBuilder.Add(twoedges, theFirstEdge.Oriented(TopAbs_REVERSED));
623 theBuilder.Add(twoedges, theSecondEdge.Oriented(TopAbs_REVERSED));
624 }
625 Context()->Replace(E, twoedges);
626 break;
627 }
628 }
629 if (theNewVertex.IsNull()) return Standard_False;
630 //Create split edge
631 TopoDS_Edge theSplitEdge;
632 gp_Lin lin(vp, gp_Dir(gp_Vec( vp, proj)));
633 Standard_Real firstparam = ElCLib::Parameter(lin, vp);
634 Standard_Real lastparam = ElCLib::Parameter(lin, proj);
635 Handle(Geom_Line) L = new Geom_Line( vp, gp_Vec( vp, proj));
636 Handle(Geom_Curve) the3dc = L;
637 theBuilder.MakeEdge(theSplitEdge, the3dc, Precision::Confusion());
638 theBuilder.Add(theSplitEdge, V.Oriented(TopAbs_FORWARD));
639 theBuilder.Add(theSplitEdge, theNewVertex.Oriented(TopAbs_REVERSED));
640 theBuilder.Range(theSplitEdge, firstparam, lastparam);
641 //Add pcurve in new edge
642 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
643 sfe->FixAddPCurve(theSplitEdge, F, Standard_False);
644 //Reorder the wire
645 TopoDS_Wire wireonface;
646 //Inher loop is not support yet !!!
647 TopExp_Explorer itw(F,TopAbs_WIRE);
648 wireonface = TopoDS::Wire (itw.Current());
649 itw.Next();
650 if (itw.More()) return Standard_False; //if face contains more than one wire
651 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
652 sfw->Init(wireonface, F, Precision::Confusion());
653 sfw->FixReorder();
654 wireonface = sfw->Wire();
655
656 //Create two new wires
657 TopoDS_Wire w1, w2;
658 theBuilder.MakeWire(w1);
659 theBuilder.MakeWire(w2);
660 theBuilder.MakeWire(tempwire);
661 for (TopExp_Explorer itnew(wireonface, TopAbs_EDGE ); itnew.More(); itnew.Next())
662 {
663 TopoDS_Edge ce = TopoDS::Edge (itnew.Current());
664 if (ce.IsSame(E))
665 {
666 theBuilder.Remove(wireonface, ce);
667 theBuilder.Add(wireonface, theFirstEdge.Oriented(TopAbs_FORWARD));
668 theBuilder.Add(wireonface, theSecondEdge.Oriented(TopAbs_FORWARD));
669 }
670 }
671 sfw->Init(wireonface, F, Precision::Confusion());
672 sfw->FixReorder();
673 wireonface = sfw->Wire();
674
675 for (TopExp_Explorer itere(wireonface, TopAbs_EDGE); itere.More(); itere.Next())
676 {
677 TopoDS_Edge ce = TopoDS::Edge (itere.Current());
678 TopoDS_Vertex thecontrol;
679 if (ce.Orientation () == TopAbs_FORWARD) thecontrol = TopExp::LastVertex(ce);
680 else thecontrol = TopExp::FirstVertex(ce);
681 theBuilder.Add(w1, ce);
682 if (thecontrol.IsSame(V))
683 {
684 theBuilder.Add(w1, theSplitEdge.Oriented(TopAbs_FORWARD));
685 TopoDS_Wire wtemp = w1;
686 w1 = w2;
687 w2 = wtemp;
688 }
689 if (thecontrol.IsSame(theNewVertex))
690 {
691 theBuilder.Add(w1, theSplitEdge.Oriented(TopAbs_REVERSED));
692 TopoDS_Wire wtemp = w1;
693 w1 = w2;
694 w2 = wtemp;
695 }
696 }
697 if ( w1.IsNull()|| w2.IsNull() ) return Standard_False;
698 //Create two new faces and replace old one
699 TopoDS_Face F1;
700 TopoDS_Face F2;
701 theBuilder.MakeFace(F1, BRep_Tool::Surface(F), Precision::Confusion());
702 theBuilder.MakeFace(F2, BRep_Tool::Surface(F), Precision::Confusion());
703 theBuilder.Add(F1, w1);
704 theBuilder.Add(F2, w2);
705 TopoDS_Compound tf;
706 theBuilder.MakeCompound(tf);
707 theBuilder.Add(tf,F1);
708 theBuilder.Add(tf, F2);
709 //Call recursive spliteoneface() for each face
710 if(!SplitOneFace(F1, theSplittedFaces)) theBuilder.Add(theSplittedFaces, F1);
711 if(!SplitOneFace(F2, theSplittedFaces)) theBuilder.Add(theSplittedFaces, F2);
712 }
713 return Standard_True ;
714 }
715 return Standard_False ;
716}
717
718
719 TopoDS_Shape ShapeFix_FixSmallFace::RemoveSmallFaces()
720{
721 myShape = SplitFaces();
722 myShape = FixSpotFace();
723 myShape = FixStripFace ();
724 return myShape;
725
726}
727
728 TopoDS_Face ShapeFix_FixSmallFace::FixFace(const TopoDS_Face& F)
729{
730//smh#8
731 TopoDS_Shape emptyCopied = F.EmptyCopied();
732 TopoDS_Face theFixedFace = TopoDS::Face(emptyCopied);
733 // BRep_Builder theBuilder;
734
735 // Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
736 // sfw->SetContext(Context());
737 // for (TopExp_Explorer exp_w (F,TopAbs_WIRE); exp_w.More(); exp_w.Next()) {
738 // TopoDS_Wire theCurWire = TopoDS::Wire (exp_w.Current());
739
740 // sfw->Init(theCurWire, F, Precision::Confusion());
741 // if(sfw->NbEdges() == 0) continue;
742 // sfw->FixNotchedEdgesMode() = 0;
743 // sfw->Perform();
744 // theCurWire = sfw->Wire();
745 // theBuilder.Add(theFixedFace, theCurWire);
746 // }
747 Handle(ShapeFix_Face) sff = new ShapeFix_Face;
748 sff->SetContext(Context());
749 sff->Init(F);
750 sff->Perform();
751 //sff->Init(theFixedFace);
752 //sff->FixOrientation();
753 theFixedFace = sff->Face();
754 return theFixedFace;
755}
756
757 TopoDS_Shape ShapeFix_FixSmallFace::FixShape()
758{
759 TopoDS_Shape FixSh;
760 if(myShape.IsNull()) return FixSh;
761 /*ShapeFix_Shape sfs;
762 sfs.SetContext(Context());
763
764 sfs.SetPrecision(Precision::Confusion());
765 sfs.Init(myShape);
766 sfs.Perform();
767 FixSh = sfs.Shape();*/
768 for(TopExp_Explorer expf(myShape,TopAbs_FACE) ; expf.More(); expf.Next()) {
769 TopoDS_Face F = TopoDS::Face(expf.Current());
770//smh#8
771 TopoDS_Shape tmpFace = Context()->Apply(F);
772 F= TopoDS::Face(tmpFace);
773 TopoDS_Face newF = FixFace(F);
774 Context()->Replace(F,newF);
775 }
776 FixSh = Context()->Apply(myShape);
777 return FixSh;
778
779}
780 TopoDS_Shape ShapeFix_FixSmallFace::Shape()
781{
782 return myShape;
783}
784
785Standard_Boolean ShapeFix_FixSmallFace::FixPinFace (TopoDS_Face& /*F*/)
786{
787 return Standard_True;
788}