1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: BlockFix_UnionEdges.cxx
24 // Created: 07.12.04 15:27:30
25 // Author: Sergey KUUL
27 #include <BlockFix_UnionEdges.hxx>
29 #include <ShapeAnalysis_Edge.hxx>
31 #include <ShapeBuild_ReShape.hxx>
33 #include <ShapeFix_Edge.hxx>
34 #include <ShapeFix_Face.hxx>
35 #include <ShapeFix_Shell.hxx>
37 #include <BRep_Builder.hxx>
38 #include <BRep_CurveRepresentation.hxx>
39 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
40 #include <BRep_TEdge.hxx>
41 #include <BRep_Tool.hxx>
42 #include <BRepAdaptor_HCompCurve.hxx>
43 #include <BRepLib.hxx>
44 #include <BRepLib_MakeEdge.hxx>
47 #include <TopExp_Explorer.hxx>
49 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
50 #include <TopTools_IndexedMapOfShape.hxx>
51 #include <TopTools_ListOfShape.hxx>
52 #include <TopTools_MapOfShape.hxx>
53 #include <TopTools_ListIteratorOfListOfShape.hxx>
54 #include <TopTools_SequenceOfShape.hxx>
57 #include <TopoDS_Edge.hxx>
58 #include <TopoDS_Face.hxx>
59 #include <TopoDS_Shell.hxx>
60 #include <TopoDS_Solid.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <TopoDS_Iterator.hxx>
63 #include <TopoDS_Shape.hxx>
65 #include <Approx_Curve3d.hxx>
67 #include <GC_MakeCircle.hxx>
69 #include <Geom_BSplineCurve.hxx>
70 #include <Geom_Circle.hxx>
71 #include <Geom_Curve.hxx>
72 #include <Geom_Line.hxx>
73 #include <Geom_TrimmedCurve.hxx>
74 #include <GeomConvert.hxx>
75 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
77 #include <Geom2dConvert.hxx>
78 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
79 #include <Geom2d_TrimmedCurve.hxx>
80 #include <Geom2d_BSplineCurve.hxx>
82 #include <TColGeom_SequenceOfSurface.hxx>
83 #include <TColGeom_Array1OfBSplineCurve.hxx>
84 #include <TColGeom_HArray1OfBSplineCurve.hxx>
85 #include <TColGeom2d_Array1OfBSplineCurve.hxx>
86 #include <TColGeom2d_HArray1OfBSplineCurve.hxx>
87 #include <TColGeom2d_SequenceOfBoundedCurve.hxx>
88 #include <TColgp_SequenceOfPnt.hxx>
89 #include <TColStd_Array1OfReal.hxx>
90 #include <TColStd_MapOfInteger.hxx>
92 #include "utilities.h"
94 //=======================================================================
95 //function : BlockFix_UnionEdges()
96 //purpose : Constructor
97 //=======================================================================
98 BlockFix_UnionEdges::BlockFix_UnionEdges ( )
102 //=======================================================================
103 //function : GlueEdgesWithPCurves
104 //purpose : Glues the pcurves of the sequence of edges
105 // and glues their 3d curves
106 //=======================================================================
107 static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain,
108 const TopoDS_Vertex& FirstVertex,
109 const TopoDS_Vertex& LastVertex)
111 Standard_Integer i, j;
113 TopoDS_Edge FirstEdge = TopoDS::Edge(aChain(1));
114 //TColGeom2d_SequenceOfCurve PCurveSeq;
115 TColGeom_SequenceOfSurface SurfSeq;
116 //TopTools_SequenceOfShape LocSeq;
118 BRep_ListIteratorOfListOfCurveRepresentation itr( (Handle(BRep_TEdge)::DownCast(FirstEdge.TShape()))->Curves() );
119 for (; itr.More(); itr.Next())
121 Handle(BRep_CurveRepresentation) CurveRep = itr.Value();
122 if (CurveRep->IsCurveOnSurface())
124 //PCurveSeq.Append(CurveRep->PCurve());
125 SurfSeq.Append(CurveRep->Surface());
127 TopoDS_Shape aLocShape;
128 aLocShape.Location(CurveRep->Location());
129 LocSeq.Append(aLocShape);
134 Standard_Real fpar, lpar;
135 BRep_Tool::Range(FirstEdge, fpar, lpar);
136 TopoDS_Edge PrevEdge = FirstEdge;
138 Standard_Real MaxTol = 0.;
143 Standard_Integer nb_curve = aChain.Length(); //number of curves
144 TColGeom_Array1OfBSplineCurve tab_c3d(0,nb_curve-1); //array of the curves
145 TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2); //array of the tolerances
147 TopoDS_Vertex PrevVertex = FirstVertex;
148 for (i = 1; i <= nb_curve; i++)
150 TopoDS_Edge anEdge = TopoDS::Edge(aChain(i));
151 TopoDS_Vertex VF, VL;
152 TopExp::Vertices(anEdge, VF, VL);
153 Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex));
155 Standard_Real Tol1 = BRep_Tool::Tolerance(VF);
156 Standard_Real Tol2 = BRep_Tool::Tolerance(VL);
164 TopExp::CommonVertex(PrevEdge, anEdge, CV);
165 Standard_Real Tol = BRep_Tool::Tolerance(CV);
166 tabtolvertex(i-2) = Tol;
169 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
170 Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, fpar, lpar);
171 tab_c3d(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
172 GeomConvert::C0BSplineToC1BSplineCurve(tab_c3d(i-1), Precision::Confusion());
174 tab_c3d(i-1)->Reverse();
175 PrevVertex = (ToReverse)? VF : VL;
178 Handle(TColGeom_HArray1OfBSplineCurve) concatcurve; //array of the concatenated curves
179 Handle(TColStd_HArray1OfInteger) ArrayOfIndices; //array of the remining Vertex
180 GeomConvert::ConcatC1(tab_c3d,
185 Precision::Confusion()); //C1 concatenation
187 if (concatcurve->Length() > 1)
189 GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
191 for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
192 Concat.Add( concatcurve->Value(i), MaxTol, Standard_True );
194 concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
196 Handle(Geom_BSplineCurve) ResCurve = concatcurve->Value(concatcurve->Lower());
198 TColGeom2d_SequenceOfBoundedCurve ResPCurves;
199 TopLoc_Location aLoc;
200 for (j = 1; j <= SurfSeq.Length(); j++)
202 TColGeom2d_Array1OfBSplineCurve tab_c2d(0,nb_curve-1); //array of the pcurves
204 PrevVertex = FirstVertex;
205 PrevEdge = FirstEdge;
206 //TopLoc_Location theLoc = LocSeq(j).Location();
207 for (i = 1; i <= nb_curve; i++)
209 TopoDS_Edge anEdge = TopoDS::Edge(aChain(i));
210 TopoDS_Vertex VF, VL;
211 TopExp::Vertices(anEdge, VF, VL);
212 Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex));
215 Handle(Geom2d_Curve) aPCurve =
216 BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), anEdge.Location()*theLoc, fpar, lpar);
218 Handle(Geom2d_Curve) aPCurve =
219 BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), aLoc, fpar, lpar);
220 Handle(Geom2d_TrimmedCurve) aTrPCurve = new Geom2d_TrimmedCurve(aPCurve, fpar, lpar);
221 tab_c2d(i-1) = Geom2dConvert::CurveToBSplineCurve(aTrPCurve);
222 Geom2dConvert::C0BSplineToC1BSplineCurve(tab_c2d(i-1), Precision::Confusion());
224 tab_c2d(i-1)->Reverse();
225 PrevVertex = (ToReverse)? VF : VL;
228 Handle(TColGeom2d_HArray1OfBSplineCurve) concatc2d; //array of the concatenated curves
229 Handle(TColStd_HArray1OfInteger) ArrayOfInd2d; //array of the remining Vertex
230 Geom2dConvert::ConcatC1(tab_c2d,
235 Precision::Confusion()); //C1 concatenation
237 if (concatc2d->Length() > 1)
239 Geom2dConvert_CompCurveToBSplineCurve Concat2d(concatc2d->Value(concatc2d->Lower()));
241 for (i = concatc2d->Lower()+1; i <= concatc2d->Upper(); i++)
242 Concat2d.Add( concatc2d->Value(i), MaxTol, Standard_True );
244 concatc2d->SetValue(concatc2d->Lower(), Concat2d.BSplineCurve());
246 Handle(Geom2d_BSplineCurve) aResPCurve = concatc2d->Value(concatc2d->Lower());
247 ResPCurves.Append(aResPCurve);
250 ResEdge = BRepLib_MakeEdge(ResCurve,
251 FirstVertex, LastVertex,
252 ResCurve->FirstParameter(), ResCurve->LastParameter());
253 BB.SameRange(ResEdge, Standard_False);
254 BB.SameParameter(ResEdge, Standard_False);
255 for (j = 1; j <= ResPCurves.Length(); j++)
257 BB.UpdateEdge(ResEdge, ResPCurves(j), SurfSeq(j), aLoc, MaxTol);
258 BB.Range(ResEdge, SurfSeq(j), aLoc, ResPCurves(j)->FirstParameter(), ResPCurves(j)->LastParameter());
261 BRepLib::SameParameter(ResEdge, MaxTol, Standard_True);
266 //=======================================================================
268 //purpose : Returns true if this vertex should be kept in the result.
269 //=======================================================================
270 static Standard_Boolean IsFixed
271 (const TopoDS_Vertex &theVtx,
272 const TopoDS_Face &theFace,
273 const TopTools_IndexedDataMapOfShapeListOfShape &theMapVtxEdgeOnFace)
275 Standard_Boolean aResult = Standard_False;
277 if (theMapVtxEdgeOnFace.Contains(theVtx)) {
278 const TopTools_ListOfShape& aList = theMapVtxEdgeOnFace.FindFromKey(theVtx);
279 TopTools_ListIteratorOfListOfShape anIter(aList);
280 Standard_Boolean isFirst = Standard_True;
281 Standard_Boolean isSeam = Standard_False;
283 for ( ; anIter.More(); anIter.Next()) {
284 TopoDS_Edge anEdge = TopoDS::Edge(anIter.Value());
287 // This is the first treated edge.
288 isFirst = Standard_False;
289 isSeam = BRep_Tool::IsClosed(anEdge, theFace);
290 } else if (BRep_Tool::IsClosed(anEdge, theFace)) {
293 // The previous one was not seam.
294 aResult = Standard_True;
298 // This is not a seam edge however the previous one was seam.
299 aResult = Standard_True;
308 //=======================================================================
309 //function : MergeEdges
311 //=======================================================================
312 static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges,
313 const TopoDS_Face& theFace1,
314 const TopoDS_Face& theFace2,
315 const Standard_Real Tol,
318 // make chain for union
320 ShapeAnalysis_Edge sae;
321 TopoDS_Edge FirstE = TopoDS::Edge(SeqEdges.Value(1));
322 TopoDS_Edge LastE = FirstE;
323 TopoDS_Vertex VF = sae.FirstVertex(FirstE);
324 TopoDS_Vertex VL = sae.LastVertex(LastE);
325 TopTools_SequenceOfShape aChain;
326 aChain.Append(FirstE);
327 TColStd_MapOfInteger IndUsedEdges;
330 for(j=2; j<=SeqEdges.Length(); j++) {
331 for(Standard_Integer k=2; k<=SeqEdges.Length(); k++) {
332 if(IndUsedEdges.Contains(k)) continue;
333 TopoDS_Edge edge = TopoDS::Edge(SeqEdges.Value(k));
334 TopoDS_Vertex VF2 = sae.FirstVertex(edge);
335 TopoDS_Vertex VL2 = sae.LastVertex(edge);
336 if(sae.FirstVertex(edge).IsSame(VL)) {
339 VL = sae.LastVertex(LastE);
342 else if(sae.LastVertex(edge).IsSame(VF)) {
343 aChain.Prepend(edge);
345 VF = sae.FirstVertex(FirstE);
350 if(aChain.Length()<SeqEdges.Length()) {
351 MESSAGE ("can not create correct chain...");
352 return Standard_False;
355 // Check if there are vertices that should be kept in the result.
356 const Standard_Boolean isClosed = VF.IsSame(VL);
357 TopTools_IndexedDataMapOfShapeListOfShape theMapVtxEdge1;
358 TopTools_IndexedDataMapOfShapeListOfShape theMapVtxEdge2;
359 Standard_Integer jSplit = -1;
361 TopExp::MapShapesAndAncestors(theFace1, TopAbs_VERTEX, TopAbs_EDGE, theMapVtxEdge1);
362 TopExp::MapShapesAndAncestors(theFace2, TopAbs_VERTEX, TopAbs_EDGE, theMapVtxEdge2);
364 // Check if intermediate vertices should be in the result.
365 for(j = 1; j < aChain.Length(); j++) {
366 TopoDS_Edge anEdge = TopoDS::Edge(aChain.Value(j));
367 TopoDS_Vertex aVtx = sae.LastVertex(anEdge);
369 if (IsFixed(aVtx, theFace1, theMapVtxEdge1) ||
370 IsFixed(aVtx, theFace2, theMapVtxEdge2)) {
371 // This vertex should be kept.
373 // There is already split vertex detected.
374 // It means that these edges can't be merged.
375 MESSAGE ("Two edges on closed contour can't be merged.");
376 return Standard_False;
377 } else if (isClosed) {
378 // This is a closed contour.
379 // It is possible to merge it starting from the next edge.
382 // The contour is not closed, this vertex sould be kept.
383 // It means that these edges can't be merged.
384 MESSAGE ("Two edges on not closed contour can't be merged.");
385 return Standard_False;
391 // This is closed contour. Check the last (it is first as well) vertex,
392 // as it becomes intermediate after reordering.
393 TopoDS_Edge anEdge = TopoDS::Edge(aChain.Last());
394 TopoDS_Vertex aVtx = sae.LastVertex(anEdge);
396 if (IsFixed(aVtx, theFace1, theMapVtxEdge1) ||
397 IsFixed(aVtx, theFace2, theMapVtxEdge2)) {
398 // This vertex should be kept. So we can't merge this contour.
399 MESSAGE ("Two edges on closed contour can't be merged.");
400 return Standard_False;
403 // Reorder edges in the sequence to have jSplit-th edge last.
404 for(j = 1; j <= jSplit; j++) {
405 aChain.Append(aChain.First());
410 // union edges in chain
411 // first step: union lines and circles
413 Standard_Real fp1,lp1,fp2,lp2;
414 for(j=1; j<aChain.Length(); j++) {
415 TopoDS_Edge edge1 = TopoDS::Edge(aChain.Value(j));
416 Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(edge1,Loc,fp1,lp1);
417 if(c3d1.IsNull()) break;
418 while(c3d1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
419 Handle(Geom_TrimmedCurve) tc =
420 Handle(Geom_TrimmedCurve)::DownCast(c3d1);
421 c3d1 = tc->BasisCurve();
423 TopoDS_Edge edge2 = TopoDS::Edge(aChain.Value(j+1));
424 Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(edge2,Loc,fp2,lp2);
425 if(c3d2.IsNull()) break;
426 while(c3d2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
427 Handle(Geom_TrimmedCurve) tc =
428 Handle(Geom_TrimmedCurve)::DownCast(c3d2);
429 c3d2 = tc->BasisCurve();
431 if( c3d1->IsKind(STANDARD_TYPE(Geom_Line)) && c3d2->IsKind(STANDARD_TYPE(Geom_Line)) ) {
433 Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(c3d1);
434 Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(c3d2);
435 gp_Dir Dir1 = L1->Position().Direction();
436 gp_Dir Dir2 = L2->Position().Direction();
437 //if(!Dir1.IsEqual(Dir2,Precision::Angular())) {
438 //if(!Dir1.IsParallel(Dir2,Precision::Angular())) {
439 if(!Dir1.IsParallel(Dir2,Tol)) {
442 // can union lines => create new edge
443 TopoDS_Vertex V1 = sae.FirstVertex(edge1);
444 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
445 TopoDS_Vertex V2 = sae.LastVertex(edge2);
446 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
448 Handle(Geom_Line) L = new Geom_Line(gp_Ax1(PV1,Vec));
449 Standard_Real dist = PV1.Distance(PV2);
450 Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(L,0.0,dist);
452 B.MakeEdge (E,tc,Precision::Confusion());
453 B.Add (E,V1); B.Add (E,V2);
454 B.UpdateVertex(V1, 0., E, 0.);
455 B.UpdateVertex(V2, dist, E, 0.);
457 //sfe.FixAddPCurve(E,aFace,Standard_False);
458 //sfe.FixSameParameter(E);
460 aChain.SetValue(j,E);
463 if( c3d1->IsKind(STANDARD_TYPE(Geom_Circle)) && c3d2->IsKind(STANDARD_TYPE(Geom_Circle)) ) {
465 Handle(Geom_Circle) C1 = Handle(Geom_Circle)::DownCast(c3d1);
466 Handle(Geom_Circle) C2 = Handle(Geom_Circle)::DownCast(c3d2);
467 gp_Pnt P01 = C1->Location();
468 gp_Pnt P02 = C2->Location();
469 if (P01.Distance(P02) > Precision::Confusion()) continue;
470 // can union circles => create new edge
471 TopoDS_Vertex V1 = sae.FirstVertex(edge1);
472 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
473 TopoDS_Vertex V2 = sae.LastVertex(edge2);
474 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
475 TopoDS_Vertex VM = sae.LastVertex(edge1);
476 gp_Pnt PVM = BRep_Tool::Pnt(VM);
477 GC_MakeCircle MC (PV1,PVM,PV2);
478 Handle(Geom_Circle) C;
486 // jfa for Mantis issue 0020228
487 if (PV1.Distance(PV2) > Precision::Confusion()) continue;
489 if (edge1.Orientation() == TopAbs_FORWARD) {
492 C = Handle(Geom_Circle)::DownCast(C1->Reversed());
495 B.MakeEdge (E,C,Precision::Confusion());
500 gp_Pnt P0 = C->Location();
501 gp_Dir D1(gp_Vec(P0,PV1));
502 gp_Dir D2(gp_Vec(P0,PV2));
503 Standard_Real fpar = C->XAxis().Direction().Angle(D1);
504 if(fabs(fpar)>Precision::Confusion()) {
506 gp_Dir ND = C->XAxis().Direction().Crossed(D1);
507 if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
511 Standard_Real lpar = C->XAxis().Direction().Angle(D2);
512 if(fabs(lpar)>Precision::Confusion()) {
514 gp_Dir ND = C->XAxis().Direction().Crossed(D2);
515 if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
519 if (lpar < fpar) lpar += 2*M_PI;
520 Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(C,fpar,lpar);
521 B.MakeEdge (E,tc,Precision::Confusion());
524 B.UpdateVertex(V1, fpar, E, 0.);
525 B.UpdateVertex(V2, lpar, E, 0.);
528 aChain.SetValue(j,E);
532 if (j < aChain.Length()) {
533 MESSAGE ("null curve3d in edge...");
534 return Standard_False;
536 if (aChain.Length() > 1) {
537 // second step: union edges with various curves
538 // skl for bug 0020052 from Mantis: perform such unions
539 // only if curves are bspline or bezier
540 bool NeedUnion = true;
541 for(j=1; j<=aChain.Length(); j++) {
542 TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j));
543 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,Loc,fp1,lp1);
544 if(c3d.IsNull()) continue;
545 while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
546 Handle(Geom_TrimmedCurve) tc =
547 Handle(Geom_TrimmedCurve)::DownCast(c3d);
548 c3d = tc->BasisCurve();
550 if( ( c3d->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
551 c3d->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ) ) continue;
556 MESSAGE ("can not make analitical union => make approximation");
557 TopoDS_Edge E = GlueEdgesWithPCurves(aChain, VF, VL);
561 for(j=1; j<=aChain.Length(); j++) {
562 TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j));
565 Handle(BRepAdaptor_HCompCurve) Adapt = new BRepAdaptor_HCompCurve(W);
566 Approx_Curve3d Conv(Adapt,Tol,GeomAbs_C1,9,1000);
567 Handle(Geom_BSplineCurve) bc = Conv.Curve();
569 B.MakeEdge (E,bc,Precision::Confusion());
573 aChain.SetValue(1,E);
576 MESSAGE ("can not make approximation for such types of curves");
577 return Standard_False;
581 anEdge = TopoDS::Edge(aChain.Value(1));
582 return Standard_True;
585 //=======================================================================
588 //=======================================================================
589 TopoDS_Shape BlockFix_UnionEdges::Perform(const TopoDS_Shape& Shape,
590 const Standard_Real Tol)
592 myContext = new ShapeBuild_ReShape;
594 TopoDS_Shape aResult = myContext->Apply(Shape);
596 // processing each solid
597 TopAbs_ShapeEnum aType = TopAbs_SOLID;
598 TopExp_Explorer exps (Shape, aType);
600 aType = TopAbs_SHELL;
601 exps.Init(Shape, aType);
603 for (; exps.More(); exps.Next()) {
604 //TopoDS_Solid aSolid = TopoDS::Solid(exps.Current());
605 TopoDS_Shape aSolid = exps.Current();
607 TopTools_IndexedMapOfShape ChangedFaces;
609 // creating map of edge faces
610 TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
611 TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
613 Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
614 TopoDS_Shape aRes = aSolid;
615 aRes = aContext->Apply(aSolid);
617 // processing each face
619 for (exp.Init(aRes, TopAbs_FACE); exp.More(); exp.Next()) {
621 TopoDS::Face(aContext->Apply(exp.Current().Oriented(TopAbs_FORWARD)));
622 TopTools_IndexedDataMapOfShapeListOfShape aMapFacesEdges;
624 for (TopExp_Explorer expe(aFace,TopAbs_EDGE); expe.More(); expe.Next()) {
625 TopoDS_Edge edge = TopoDS::Edge(expe.Current());
626 if (!aMapEdgeFaces.Contains(edge)) continue;
627 const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
628 TopTools_ListIteratorOfListOfShape anIter(aList);
629 for ( ; anIter.More(); anIter.Next()) {
630 TopoDS_Face face = TopoDS::Face(anIter.Value());
631 TopoDS_Face face1 = TopoDS::Face(aContext->Apply(anIter.Value()));
632 if (face1.IsSame(aFace)) continue;
633 if (aMapFacesEdges.Contains(face)) {
634 aMapFacesEdges.ChangeFromKey(face).Append(edge);
637 TopTools_ListOfShape ListEdges;
638 ListEdges.Append(edge);
639 aMapFacesEdges.Add(face,ListEdges);
644 for (Standard_Integer i=1; i<=aMapFacesEdges.Extent(); i++) {
645 const TopTools_ListOfShape& ListEdges = aMapFacesEdges.FindFromIndex(i);
646 TopTools_SequenceOfShape SeqEdges;
647 TopTools_ListIteratorOfListOfShape anIter(ListEdges);
648 for ( ; anIter.More(); anIter.Next()) {
649 SeqEdges.Append(anIter.Value());
651 if (SeqEdges.Length()==1) continue;
654 TopoDS::Face(aContext->Apply(aMapFacesEdges.FindKey(i)));
656 if ( MergeEdges(SeqEdges,aFace,aFace2,Tol,E) ) {
657 // now we have only one edge - aChain.Value(1)
658 // we have to replace old ListEdges with this new edge
659 aContext->Replace(SeqEdges(1),E);
660 for (Standard_Integer j=2; j<=SeqEdges.Length(); j++) {
661 aContext->Remove(SeqEdges(j));
663 TopoDS_Face tmpF = TopoDS::Face(exp.Current());
664 if ( !ChangedFaces.Contains(tmpF) )
665 ChangedFaces.Add(tmpF);
666 tmpF = TopoDS::Face(aMapFacesEdges.FindKey(i));
667 if ( !ChangedFaces.Contains(tmpF) )
668 ChangedFaces.Add(tmpF);
672 } // end processing each face
674 // fix changed faces and replace them in the local context
675 for (Standard_Integer i=1; i<=ChangedFaces.Extent(); i++) {
676 TopoDS_Face aFace = TopoDS::Face(aContext->Apply(ChangedFaces.FindKey(i)));
677 Handle(ShapeFix_Face) sff = new ShapeFix_Face(aFace);
678 sff->SetContext(myContext);
679 sff->SetPrecision(myTolerance);
680 sff->SetMinTolerance(myTolerance);
681 sff->SetMaxTolerance(Max(1.,myTolerance*1000.));
683 aContext->Replace(aFace,sff->Face());
686 if (ChangedFaces.Extent() > 0) {
687 // fix changed shell and replace it in the local context
688 TopoDS_Shape aRes1 = aContext->Apply(aRes);
689 TopExp_Explorer expsh;
690 for (expsh.Init(aRes1, TopAbs_SHELL); expsh.More(); expsh.Next()) {
691 TopoDS_Shell aShell = TopoDS::Shell(expsh.Current());
692 Handle(ShapeFix_Shell) sfsh = new ShapeFix_Shell;
693 sfsh->FixFaceOrientation(aShell);
694 aContext->Replace(aShell,sfsh->Shell());
696 TopoDS_Shape aRes2 = aContext->Apply(aRes1);
697 // put new solid into global context
698 myContext->Replace(aSolid,aRes2);
701 } // end processing each solid
703 aResult = myContext->Apply(Shape);