1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
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
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.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include <ShapeFix_FixSmallFace.ixx>
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>
22 #include <BRep_Tool.hxx>
24 #include <Geom_Curve.hxx>
25 #include <Geom_Surface.hxx>
26 #include <Geom_BSplineSurface.hxx>
27 #include <Geom_BezierSurface.hxx>
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>
36 //#include <TColStd_Array1OfReal.hxx>
37 #include <TColgp_Array1OfPnt.hxx>
38 #include <TopTools_Array1OfShape.hxx>
40 #include <TColgp_Array2OfPnt.hxx>
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>
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>
70 #include <Message_Msg.hxx>
72 ShapeFix_FixSmallFace::ShapeFix_FixSmallFace()
74 myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
75 SetPrecision(Precision::Confusion());
79 void ShapeFix_FixSmallFace::Init(const TopoDS_Shape& S)
82 if ( Context().IsNull() )
83 SetContext ( new ShapeBuild_ReShape );
85 Context()->Apply(myShape);
89 void ShapeFix_FixSmallFace::Perform()
95 TopoDS_Shape ShapeFix_FixSmallFace::FixSpotFace()
99 // Standard_Real spotol;
100 Standard_Boolean done = Standard_False;
101 TopAbs_ShapeEnum st = myShape.ShapeType();
102 if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID || st == TopAbs_SOLID || st == TopAbs_SHELL || st == TopAbs_FACE) {
103 for (TopExp_Explorer itf (myShape,TopAbs_FACE); itf.More(); itf.Next()) {
105 TopoDS_Shape tmpFace = Context()->Apply(itf.Current());
106 TopoDS_Face F = TopoDS::Face (tmpFace);
107 if(F.IsNull()) continue;
108 if (myAnalyzer.CheckSpotFace (F,Precision()))
110 ReplaceVerticesInCaseOfSpot(F,Precision());
111 RemoveFacesInCaseOfSpot(F);
112 myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
113 done = Standard_True;
116 myShape = Context()->Apply(myShape);
117 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
120 if (myShape.IsNull()) return myShape;
122 sfw.SetContext(Context());
123 sfw.SetPrecision(Precision::Confusion());
124 if (myShape.IsNull()) return myShape;
125 for (TopExp_Explorer itfw (myShape,TopAbs_FACE); itfw.More(); itfw.Next()) {
126 for (TopExp_Explorer itw (myShape,TopAbs_WIRE); itw.More(); itw.Next()) {
127 TopoDS_Wire w = TopoDS::Wire(itw.Current());
128 sfw.Init(w, TopoDS::Face(itfw.Current()), Precision::Confusion());
129 sfw->FixNotchedEdgesMode() = 0;
131 Context()->Replace(w, sfw.Wire());
134 myShape = FixShape();
137 //myShape = Context()->Apply(myShape);
143 Standard_Boolean ShapeFix_FixSmallFace::ReplaceVerticesInCaseOfSpot(TopoDS_Face& F,const Standard_Real /*tol*/) const
146 TColgp_SequenceOfXYZ thePositions;
148 BRep_Builder theBuilder;
149 Standard_Real theMaxDev;
150 Standard_Real theMaxTol = 0.0;
151 thePositions.Clear();
154 TopoDS_Shape tmpFace = Context()->Apply(F);
155 F = TopoDS::Face(tmpFace);
156 // gka Mar2000 Protection against faces without wires
157 // but they occur due to bugs in the algorithm itself, it needs to be fixed
158 Standard_Boolean isWir = Standard_False;
159 for(TopoDS_Iterator itw(F,Standard_False) ; itw.More();itw.Next()) {
160 if(itw.Value().ShapeType() != TopAbs_WIRE)
162 TopoDS_Wire w1 = TopoDS::Wire(itw.Value());
163 if (!w1.IsNull()) {isWir = Standard_True; break;}
165 if(!isWir) return Standard_True;
166 //Accumulating positions and maximal vertex tolerance
167 for (TopExp_Explorer iter_vertex(F,TopAbs_VERTEX); iter_vertex.More(); iter_vertex.Next()) {
168 TopoDS_Vertex V = TopoDS::Vertex (iter_vertex.Current());
169 thePoint = BRep_Tool::Pnt(V);
170 if (theMaxTol <= (BRep_Tool::Tolerance(V))) theMaxTol = BRep_Tool::Tolerance(V);
171 thePositions.Append(thePoint.XYZ());
173 //Calculate common vertex position
174 thePosition = gp_XYZ(0.,0.,0.);
175 Standard_Integer theNbPos = thePositions.Length();
176 Standard_Integer i; // svv Jan11 2000 : porting on DEC
177 for ( i = 1; i <= theNbPos; i++ ) thePosition += thePositions.Value(i);
178 if ( theNbPos > 1 ) thePosition /= theNbPos;
180 // Calculate maximal deviation
182 for ( i = 1; i <= theNbPos; i++ ) {
183 Standard_Real theDeviation = (thePosition-thePositions.Value(i)).Modulus();
184 if ( theDeviation > theMaxDev ) theMaxDev = theDeviation;
186 theMaxDev *= 1.00001;
188 //Cretate new vertex with mean point
189 TopoDS_Vertex theSharedVertex;
190 theBuilder.MakeVertex(theSharedVertex);
191 theBuilder.UpdateVertex( theSharedVertex, gp_Pnt(thePosition), theMaxDev+theMaxTol/2 );
192 //Use external tolerance
193 // if (tol!=-1.0) theBuilder.UpdateVertex( theSharedVertex, tol);
194 //Replacing all vertices in the face by new one
195 TopoDS_Vertex theNewVertex;
196 for ( TopExp_Explorer iter_vert(F,TopAbs_VERTEX); iter_vert.More(); iter_vert.Next()) {
197 TopoDS_Vertex V = TopoDS::Vertex (iter_vert.Current());
198 if (V.Orientation()==TopAbs_FORWARD)
201 TopoDS_Shape tmpVertexFwd = theSharedVertex.Oriented(TopAbs_FORWARD);
202 theNewVertex = TopoDS::Vertex(tmpVertexFwd);
207 TopoDS_Shape tmpVertexRev = theSharedVertex.Oriented(TopAbs_REVERSED);
208 theNewVertex = TopoDS::Vertex(tmpVertexRev);
210 Context()->Replace(V, theNewVertex);
212 return Standard_True;
215 Standard_Boolean ShapeFix_FixSmallFace::RemoveFacesInCaseOfSpot(const TopoDS_Face& F) const
217 for ( TopExp_Explorer iter_vert(F,TopAbs_EDGE); iter_vert.More(); iter_vert.Next()) {
218 TopoDS_Edge Ed = TopoDS::Edge (iter_vert.Current());
219 Context()->Remove(Ed);
221 Context()->Remove(F);
222 SendWarning( F, Message_Msg( "FixAdvFace.FixSpotFace.MSG0" ));
223 return Standard_True;
228 TopoDS_Shape ShapeFix_FixSmallFace::FixStripFace(const Standard_Boolean wasdone)
230 if(myShape.IsNull()) return myShape;
231 TopAbs_ShapeEnum st = myShape.ShapeType();
232 // BRep_Builder theBuilder;
233 Standard_Boolean done = wasdone;
234 if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID ||st == TopAbs_SOLID || st == TopAbs_SHELL || st == TopAbs_FACE) {
235 for (TopExp_Explorer itf (myShape,TopAbs_FACE); itf.More(); itf.Next()) {
236 TopoDS_Face F = TopoDS::Face (itf.Current());
238 TopoDS_Shape tmpFace = Context()->Apply(F);
239 F= TopoDS::Face(tmpFace);
240 if(F.IsNull()) continue;
241 // Standard_Real dmax = 1;
243 if (myAnalyzer.CheckStripFace (F, E1,E2,Precision()))
245 if(ReplaceInCaseOfStrip(F,E1,E2, Precision()))
246 RemoveFacesInCaseOfStrip(F);
247 myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
248 done = Standard_True;
251 myShape = Context()->Apply(myShape);
252 //Particular case of empty shell
253 if (!myShape.IsNull())
255 for (TopExp_Explorer exp_s (myShape,TopAbs_SHELL); exp_s.More(); exp_s.Next()) {
256 TopoDS_Shell Sh = TopoDS::Shell (exp_s.Current());
257 TopExp_Explorer ex_sh(Sh,TopAbs_FACE);
258 if (!ex_sh.More()) { Context()->Remove(Sh);
259 // cout << "Empty shell was removed" << endl;
262 myShape = Context()->Apply(myShape);
263 //Fixing of missing pcurves on new edges, if thay were inserted
266 if (myShape.IsNull()) return myShape;
267 TopoDS_Shape theResult;
268 myShape = FixShape();
269 //myShape = Context()->Apply(myShape);
279 Standard_Boolean ShapeFix_FixSmallFace::ReplaceInCaseOfStrip(TopoDS_Face& F,TopoDS_Edge& E1,TopoDS_Edge& E2, const Standard_Real tol) const
281 if(E1.IsNull() || E2.IsNull()) return Standard_False;
282 TopoDS_Edge theSharedEdge;
285 TopoDS_Shape tmpFace = Context()->Apply(F);
286 F= TopoDS::Face(tmpFace);
287 for(TopExp_Explorer expf(myShape,TopAbs_FACE); expf.More(); expf.Next()) {
289 TopoDS_Shape tmpShape = Context()->Apply(expf.Current());
290 TopoDS_Face tempF = TopoDS::Face (tmpShape);
291 if(tempF.IsNull() || tempF.IsSame(F)) continue;
292 for(TopExp_Explorer expe(tempF,TopAbs_EDGE); expe.More(); expe.Next()) {
293 TopoDS_Edge tempE = TopoDS::Edge (expe.Current());
294 if(tempE.IsSame(E1)) F1 = tempF;
295 if(tempE.IsSame(E2)) F2 = tempF;
296 if(!F1.IsNull()) break; // && !F2.IsNull()) break;
300 //Compute shared edge for this face
301 if(F1.IsNull() && F2.IsNull()) return Standard_True;
302 TopoDS_Edge E1tmp = E1;
303 TopoDS_Edge E2tmp = E2;
309 theSharedEdge = ComputeSharedEdgeForStripFace(F, E1tmp, E2tmp, F1, tol);
310 //Replace two long edges by new one
311 if (theSharedEdge.IsNull()) return Standard_False;
312 if (E1.Orientation()==TopAbs_REVERSED) {
313 Context()->Replace(E1tmp, theSharedEdge.Oriented(TopAbs_REVERSED));
314 if(F.Orientation() == F1.Orientation())
315 Context()->Replace(E2tmp, theSharedEdge);
317 Context()->Replace(E2tmp, theSharedEdge.Oriented(TopAbs_REVERSED));
321 Context()->Replace(E1tmp, theSharedEdge);
322 if(F.Orientation() == F1.Orientation())
323 Context()->Replace(E2tmp, theSharedEdge.Oriented(TopAbs_REVERSED));
325 Context()->Replace(E2tmp, theSharedEdge);
329 for (TopExp_Explorer exp_e (F,TopAbs_EDGE); exp_e.More(); exp_e.Next()) {
330 TopoDS_Edge shortedge = TopoDS::Edge (exp_e.Current());
331 if (!shortedge.IsSame(E1tmp) && !shortedge.IsSame(E2tmp)) Context()->Remove(shortedge);
334 return Standard_True;
337 Standard_Boolean ShapeFix_FixSmallFace::RemoveFacesInCaseOfStrip(const TopoDS_Face& F) const
339 Context()->Remove(F);
340 SendWarning( F, Message_Msg( "FixAdvFace.FixStripFace.MSG0" ));
341 return Standard_True;
344 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
347 BRep_Builder theBuilder;
348 //Compute deviation between two vertices and create new vertices
349 TopoDS_Edge theNewEdge;
350 TopoDS_Vertex V1,V2, V3, V4;
351 TopExp::Vertices (E1,V1,V2);
352 TopExp::Vertices (E2,V3,V4);
355 p1 = BRep_Tool::Pnt(V1);
356 p2 = BRep_Tool::Pnt(V3);
357 dev = p1.Distance(p2);
358 TopoDS_Vertex theFirstVer;
359 TopoDS_Vertex theSecondVer;
360 theBuilder.MakeVertex(theFirstVer);
361 theBuilder.MakeVertex(theSecondVer);
365 if ((dev<=BRep_Tool::Tolerance (V1)) || (dev<=BRep_Tool::Tolerance (V3)) || (dev<=tol)) {
367 // #ifdef AIX CKY : applies to all platforms
369 // theFirstVer = TopoDS::Vertex(V1);
372 dev = (dev/2)*1.0001;
373 thePosition = (p1.XYZ()+p2.XYZ())/2;
374 theBuilder.UpdateVertex(theFirstVer, gp_Pnt(thePosition), dev );
375 //if(Context()->Status(V1, temp) != 0) theFirstVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
376 //else //take recorded vertex
377 // if(theRepVert->Status(V3, temp) != 0) theFirstVer = TopoDS::Vertex (temp);
378 if (V1.Orientation()==TopAbs_FORWARD) Context()->Replace(V1, theFirstVer.Oriented(TopAbs_FORWARD));
379 else Context()->Replace(V1, theFirstVer.Oriented(TopAbs_REVERSED));
380 if (V3.Orientation()==TopAbs_FORWARD) Context()->Replace(V3, theFirstVer.Oriented(TopAbs_FORWARD));
381 else Context()->Replace(V3, theFirstVer.Oriented(TopAbs_REVERSED));
384 if(V1.IsSame(V2) || V3.IsSame(V4))
385 theSecondVer = theFirstVer;
387 if (!V2.IsSame(V4)) {
388 // #ifdef AIX CKY : applies to all platforms
390 p1 = BRep_Tool::Pnt(V2);
391 p2 = BRep_Tool::Pnt(V4);
392 dev = p1.Distance(p2);
393 thePosition = (p1.XYZ()+p2.XYZ())/2;
394 theBuilder.UpdateVertex(theSecondVer, gp_Pnt(thePosition), dev );
395 //if(theRepVert->Status(V2, temp) != 0) theSecondVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
397 // if(theRepVert->Status(V4, temp) != 0) theSecondVer = TopoDS::Vertex (temp);
399 else theSecondVer = V2;
402 if (!V2.IsSame(theSecondVer)) {
403 if (V2.Orientation()==TopAbs_FORWARD) Context()->Replace(V2, theSecondVer.Oriented(TopAbs_FORWARD));
404 else Context()->Replace(V2, theSecondVer.Oriented(TopAbs_REVERSED));
405 if (V4.Orientation()==TopAbs_FORWARD) Context()->Replace(V4, theSecondVer.Oriented(TopAbs_FORWARD));
406 else Context()->Replace(V4, theSecondVer.Oriented(TopAbs_REVERSED));
410 p2 = BRep_Tool::Pnt(V4);
411 dev = p1.Distance(p2);
412 if ((dev<=BRep_Tool::Tolerance (V1)) || (dev<=BRep_Tool::Tolerance (V4)) || (dev<=tol)) {
414 // #ifdef AIX CKY : applies to all platforms
416 // theFirstVer = TopoDS::Vertex(V1);
419 dev = (dev/2)*1.0001;
420 thePosition = (p1.XYZ()+p2.XYZ())/2;
421 theBuilder.UpdateVertex(theFirstVer, gp_Pnt(thePosition), dev );
422 // if(theRepVert->Status(V1, temp) != 0) theFirstVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
424 // if(theRepVert->Status(V4, temp) != 0) theFirstVer = TopoDS::Vertex (temp);
425 if (V1.Orientation()==TopAbs_FORWARD) Context()->Replace(V1, theFirstVer.Oriented(TopAbs_FORWARD));
426 else Context()->Replace(V1, theFirstVer.Oriented(TopAbs_REVERSED));
427 if (V4.Orientation()==TopAbs_FORWARD) Context()->Replace(V4, theFirstVer.Oriented(TopAbs_FORWARD));
428 else Context()->Replace(V4, theFirstVer.Oriented(TopAbs_REVERSED));
430 if(V1.IsSame(V2) || V3.IsSame(V4))
431 theSecondVer = theFirstVer;
434 if (!V2.IsSame(V3)) {
435 p1 = BRep_Tool::Pnt(V2);
436 p2 = BRep_Tool::Pnt(V3);
437 dev = p1.Distance(p2);
438 thePosition = (p1.XYZ()+p2.XYZ())/2;
439 theBuilder.UpdateVertex(theSecondVer, gp_Pnt(thePosition), dev );
441 else theSecondVer = V2;
443 // if(theRepVert->Status(V2, temp) != 0) theSecondVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
445 // if(theRepVert->Status(V3, temp) != 0) theSecondVer = TopoDS::Vertex (temp);
446 if (!V2.IsSame(theSecondVer)) {
447 if (V2.Orientation()==TopAbs_FORWARD) Context()->Replace(V2, theSecondVer.Oriented(TopAbs_FORWARD));
448 else Context()->Replace(V2, theSecondVer.Oriented(TopAbs_REVERSED));
449 if (V3.Orientation()==TopAbs_FORWARD) Context()->Replace(V3, theSecondVer.Oriented(TopAbs_FORWARD));
450 else Context()->Replace(V3, theSecondVer.Oriented(TopAbs_REVERSED));
456 cout << "The face is not strip face" << endl;
461 if (theFirstVer.IsNull() || theSecondVer.IsNull()) return theNewEdge;
463 theBuilder.MakeEdge(theNewEdge);
464 Standard_Real f, l, fp1, lp1/*, fp2, lp2*/;
466 Handle(Geom_Curve) the3dcurve;
467 the3dcurve = BRep_Tool::Curve(E1, f, l);
468 Handle(Geom2d_Curve) the2dcurve1, the2dcurve2, thenew1, thenew2;
471 the2dcurve1 = BRep_Tool::CurveOnSurface(E1, F1, fp1, lp1);
472 if(!the2dcurve1.IsNull() && fp1!=f && lp1!=l) GeomLib::SameRange(Precision::Confusion(), the2dcurve1, fp1, lp1, f, l, thenew1);
477 the2dcurve2 = BRep_Tool::CurveOnSurface(E2, F2, fp2, lp2);
478 if(!the2dcurve2.IsNull()) GeomLib::SameRange(Precision::Confusion(), the2dcurve2, fp2, lp2, f, l, thenew2);
481 Standard_Real maxdev;
482 if ((BRep_Tool::Tolerance(theFirstVer))<=(BRep_Tool::Tolerance(theSecondVer)))
483 maxdev = (BRep_Tool::Tolerance(theSecondVer));
484 else maxdev = (BRep_Tool::Tolerance(theFirstVer));
485 theBuilder.UpdateVertex(theFirstVer, maxdev);
486 theBuilder.UpdateVertex(theSecondVer, maxdev);
487 //Standard_Boolean IsFree = Standard_True;
488 theBuilder.SameParameter(theNewEdge, Standard_False);
489 the3dcurve = BRep_Tool::Curve(E1, f, l);
490 theBuilder.UpdateEdge(theNewEdge, the3dcurve, maxdev);
491 theBuilder.Range(theNewEdge, f, l);
492 if (!F1.IsNull() && !thenew1.IsNull())
494 theBuilder.UpdateEdge(theNewEdge, thenew1, F1, maxdev);
495 //IsFree = Standard_False;
497 /*if (!F2.IsNull() && !thenew2.IsNull())
499 theBuilder.UpdateEdge(theNewEdge, thenew2, F2, maxdev);
500 IsFree = Standard_False;
502 theBuilder.Add(theNewEdge, theFirstVer.Oriented(TopAbs_FORWARD));
503 theBuilder.Add(theNewEdge, theSecondVer.Oriented(TopAbs_REVERSED));
504 //Call fixsameparameter for computing distance between 3d and pcurves, if edge is not free
507 // ShapeFix_Edge sfe;
508 // if (!F1.IsNull() && !thenew1.IsNull()) sfe.FixReversed2d(theNewEdge, F1);
509 // if (!F2.IsNull() && !thenew2.IsNull()) sfe.FixReversed2d(theNewEdge, F2);
510 // sfe.FixSameParameter(theNewEdge, maxdev);
517 TopoDS_Shape ShapeFix_FixSmallFace::FixSplitFace(const TopoDS_Shape& /*S*/)
519 if (myShape.IsNull()) return myShape;
520 TopAbs_ShapeEnum st = myShape.ShapeType();
521 Standard_Boolean done = Standard_False;
522 TopoDS_Compound theSplittedFaces;
523 BRep_Builder theBuilder;
524 if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID ||
525 st == TopAbs_SOLID || st == TopAbs_SHELL || st == TopAbs_FACE) {
526 for (TopExp_Explorer itf (myShape,TopAbs_FACE); itf.More(); itf.Next()) {
527 TopoDS_Face F = TopoDS::Face (itf.Current());
528 TopoDS_Compound CompSplittedFaces;
529 theBuilder.MakeCompound(CompSplittedFaces);
530 if(SplitOneFace(F, CompSplittedFaces)) {
531 done = Standard_True;
532 Context()->Replace(F, CompSplittedFaces);
536 if(done) myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
537 myShape = Context()->Apply(myShape);
542 TopoDS_Shape ShapeFix_FixSmallFace::SplitFaces()
544 myShape = RemoveSmallFaces();
550 Standard_Boolean ShapeFix_FixSmallFace::SplitOneFace(TopoDS_Face& F,TopoDS_Compound& theSplittedFaces)
552 TopTools_DataMapOfShapeListOfShape MapEdges;
553 ShapeAnalysis_DataMapOfShapeListOfReal MapParam;
554 TopoDS_Compound theAllVert;
555 BRep_Builder theBuilder;
556 theBuilder.MakeCompound(theAllVert);
558 TopoDS_Shape tmpShape = Context()->Apply(F);
559 F = TopoDS::Face(tmpShape);
560 if (myAnalyzer.CheckSplittingVertices(F,MapEdges,MapParam,theAllVert) != 0)
562 TopoDS_Wire tempwire;
563 //Take information about splitting vertices
564 if (theAllVert.IsNull()) return Standard_False;
565 //Standard_Integer i;
567 TopExp_Explorer itc(theAllVert,TopAbs_VERTEX); V = TopoDS::Vertex (itc.Current());
568 if (V.IsNull()) return Standard_False;
570 gp_Pnt vp = BRep_Tool::Pnt(V);
571 TopoDS_Vertex theNewVertex;
573 TopoDS_Edge theFirstEdge, theSecondEdge;
576 //If one vertex presents do splitting by two faces
577 ShapeAnalysis_Curve SAC;
578 for (TopExp_Explorer ite(F,TopAbs_EDGE); ite.More(); ite.Next()) {
579 E = TopoDS::Edge (ite.Current());
581 TopExp::Vertices (E,V1,V2);
583 Handle(Geom_Curve) C3D = BRep_Tool::Curve (E,cf,cl);
584 if (C3D.IsNull()) continue;
585 if (V.IsSame(V1) || V.IsSame(V2)) continue;
586 Standard_Real vt = BRep_Tool::Tolerance (V);
588 Standard_Real dist = SAC.Project (C3D,vp,vt*10.,proj,param,cf,cl);
589 if (dist==0) continue; //Projection on same curve but on other edge ?
592 theBuilder.MakeVertex(theNewVertex);
593 theBuilder.UpdateVertex(theNewVertex, proj, Precision::Confusion());
594 theBuilder.MakeEdge(theFirstEdge);
595 theBuilder.MakeEdge(theSecondEdge);
597 Handle(Geom_Curve) the3dcurve = BRep_Tool::Curve(E, f, l);
598 theBuilder.UpdateEdge(theFirstEdge, the3dcurve,Precision::Confusion());
599 theBuilder.UpdateEdge(theSecondEdge, the3dcurve,Precision::Confusion());
600 if (V1.Orientation()==TopAbs_FORWARD)
602 theBuilder.Add(theFirstEdge, V1);
603 theBuilder.Add(theFirstEdge,theNewVertex.Oriented(TopAbs_REVERSED));
604 theBuilder.Add(theSecondEdge,theNewVertex.Oriented(TopAbs_FORWARD));
605 theBuilder.Add(theSecondEdge, V2);
608 theBuilder.Add(theFirstEdge,V2);
609 theBuilder.Add(theFirstEdge,theNewVertex.Oriented(TopAbs_REVERSED));
610 theBuilder.Add(theSecondEdge,theNewVertex.Oriented(TopAbs_FORWARD));
611 theBuilder.Add(theSecondEdge, V1);
613 theBuilder.Range(theFirstEdge, cf, param);
614 theBuilder.Range(theSecondEdge, param, cl);
615 //Replace old edge by two new edges
616 TopoDS_Wire twoedges;
617 theBuilder.MakeWire(twoedges);
618 if (E.Orientation() == TopAbs_FORWARD)
620 theBuilder.Add(twoedges, theFirstEdge.Oriented(TopAbs_FORWARD));
621 theBuilder.Add(twoedges, theSecondEdge.Oriented(TopAbs_FORWARD));
625 theBuilder.Add(twoedges, theFirstEdge.Oriented(TopAbs_REVERSED));
626 theBuilder.Add(twoedges, theSecondEdge.Oriented(TopAbs_REVERSED));
628 Context()->Replace(E, twoedges);
632 if (theNewVertex.IsNull()) return Standard_False;
634 TopoDS_Edge theSplitEdge;
635 gp_Lin lin(vp, gp_Dir(gp_Vec( vp, proj)));
636 Standard_Real firstparam = ElCLib::Parameter(lin, vp);
637 Standard_Real lastparam = ElCLib::Parameter(lin, proj);
638 Handle(Geom_Line) L = new Geom_Line( vp, gp_Vec( vp, proj));
639 Handle(Geom_Curve) the3dc = L;
640 theBuilder.MakeEdge(theSplitEdge, the3dc, Precision::Confusion());
641 theBuilder.Add(theSplitEdge, V.Oriented(TopAbs_FORWARD));
642 theBuilder.Add(theSplitEdge, theNewVertex.Oriented(TopAbs_REVERSED));
643 theBuilder.Range(theSplitEdge, firstparam, lastparam);
644 //Add pcurve in new edge
645 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
646 sfe->FixAddPCurve(theSplitEdge, F, Standard_False);
648 TopoDS_Wire wireonface;
649 //Inher loop is not support yet !!!
650 TopExp_Explorer itw(F,TopAbs_WIRE);
651 wireonface = TopoDS::Wire (itw.Current());
653 if (itw.More()) return Standard_False; //if face contains more than one wire
654 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
655 sfw->Init(wireonface, F, Precision::Confusion());
657 wireonface = sfw->Wire();
659 //Create two new wires
661 theBuilder.MakeWire(w1);
662 theBuilder.MakeWire(w2);
663 theBuilder.MakeWire(tempwire);
664 for (TopExp_Explorer itnew(wireonface, TopAbs_EDGE ); itnew.More(); itnew.Next())
666 TopoDS_Edge ce = TopoDS::Edge (itnew.Current());
669 theBuilder.Remove(wireonface, ce);
670 theBuilder.Add(wireonface, theFirstEdge.Oriented(TopAbs_FORWARD));
671 theBuilder.Add(wireonface, theSecondEdge.Oriented(TopAbs_FORWARD));
674 sfw->Init(wireonface, F, Precision::Confusion());
676 wireonface = sfw->Wire();
678 for (TopExp_Explorer itere(wireonface, TopAbs_EDGE); itere.More(); itere.Next())
680 TopoDS_Edge ce = TopoDS::Edge (itere.Current());
681 TopoDS_Vertex thecontrol;
682 if (ce.Orientation () == TopAbs_FORWARD) thecontrol = TopExp::LastVertex(ce);
683 else thecontrol = TopExp::FirstVertex(ce);
684 theBuilder.Add(w1, ce);
685 if (thecontrol.IsSame(V))
687 theBuilder.Add(w1, theSplitEdge.Oriented(TopAbs_FORWARD));
688 TopoDS_Wire wtemp = w1;
692 if (thecontrol.IsSame(theNewVertex))
694 theBuilder.Add(w1, theSplitEdge.Oriented(TopAbs_REVERSED));
695 TopoDS_Wire wtemp = w1;
700 if ( w1.IsNull()|| w2.IsNull() ) return Standard_False;
701 //Create two new faces and replace old one
704 theBuilder.MakeFace(F1, BRep_Tool::Surface(F), Precision::Confusion());
705 theBuilder.MakeFace(F2, BRep_Tool::Surface(F), Precision::Confusion());
706 theBuilder.Add(F1, w1);
707 theBuilder.Add(F2, w2);
709 theBuilder.MakeCompound(tf);
710 theBuilder.Add(tf,F1);
711 theBuilder.Add(tf, F2);
712 //Call recursive spliteoneface() for each face
713 if(!SplitOneFace(F1, theSplittedFaces)) theBuilder.Add(theSplittedFaces, F1);
714 if(!SplitOneFace(F2, theSplittedFaces)) theBuilder.Add(theSplittedFaces, F2);
716 return Standard_True ;
718 return Standard_False ;
722 TopoDS_Shape ShapeFix_FixSmallFace::RemoveSmallFaces()
724 myShape = SplitFaces();
725 myShape = FixSpotFace();
726 myShape = FixStripFace ();
731 TopoDS_Face ShapeFix_FixSmallFace::FixFace(const TopoDS_Face& F)
734 TopoDS_Shape emptyCopied = F.EmptyCopied();
735 TopoDS_Face theFixedFace = TopoDS::Face(emptyCopied);
736 // BRep_Builder theBuilder;
738 // Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
739 // sfw->SetContext(Context());
740 // for (TopExp_Explorer exp_w (F,TopAbs_WIRE); exp_w.More(); exp_w.Next()) {
741 // TopoDS_Wire theCurWire = TopoDS::Wire (exp_w.Current());
743 // sfw->Init(theCurWire, F, Precision::Confusion());
744 // if(sfw->NbEdges() == 0) continue;
745 // sfw->FixNotchedEdgesMode() = 0;
747 // theCurWire = sfw->Wire();
748 // theBuilder.Add(theFixedFace, theCurWire);
750 Handle(ShapeFix_Face) sff = new ShapeFix_Face;
751 sff->SetContext(Context());
754 //sff->Init(theFixedFace);
755 //sff->FixOrientation();
756 theFixedFace = sff->Face();
760 TopoDS_Shape ShapeFix_FixSmallFace::FixShape()
763 if(myShape.IsNull()) return FixSh;
764 /*ShapeFix_Shape sfs;
765 sfs.SetContext(Context());
767 sfs.SetPrecision(Precision::Confusion());
770 FixSh = sfs.Shape();*/
771 for(TopExp_Explorer expf(myShape,TopAbs_FACE) ; expf.More(); expf.Next()) {
772 TopoDS_Face F = TopoDS::Face(expf.Current());
774 TopoDS_Shape tmpFace = Context()->Apply(F);
775 F= TopoDS::Face(tmpFace);
776 TopoDS_Face newF = FixFace(F);
777 Context()->Replace(F,newF);
779 FixSh = Context()->Apply(myShape);
783 TopoDS_Shape ShapeFix_FixSmallFace::Shape()
788 Standard_Boolean ShapeFix_FixSmallFace::FixPinFace (TopoDS_Face& /*F*/)
790 return Standard_True;