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 // Reorder edges in the sequence to have jSplit-th edge last.
392 for(j = 1; j <= jSplit; j++) {
393 aChain.Append(aChain.First());
398 // union edges in chain
399 // first step: union lines and circles
401 Standard_Real fp1,lp1,fp2,lp2;
402 for(j=1; j<aChain.Length(); j++) {
403 TopoDS_Edge edge1 = TopoDS::Edge(aChain.Value(j));
404 Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(edge1,Loc,fp1,lp1);
405 if(c3d1.IsNull()) break;
406 while(c3d1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
407 Handle(Geom_TrimmedCurve) tc =
408 Handle(Geom_TrimmedCurve)::DownCast(c3d1);
409 c3d1 = tc->BasisCurve();
411 TopoDS_Edge edge2 = TopoDS::Edge(aChain.Value(j+1));
412 Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(edge2,Loc,fp2,lp2);
413 if(c3d2.IsNull()) break;
414 while(c3d2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
415 Handle(Geom_TrimmedCurve) tc =
416 Handle(Geom_TrimmedCurve)::DownCast(c3d2);
417 c3d2 = tc->BasisCurve();
419 if( c3d1->IsKind(STANDARD_TYPE(Geom_Line)) && c3d2->IsKind(STANDARD_TYPE(Geom_Line)) ) {
421 Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(c3d1);
422 Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(c3d2);
423 gp_Dir Dir1 = L1->Position().Direction();
424 gp_Dir Dir2 = L2->Position().Direction();
425 //if(!Dir1.IsEqual(Dir2,Precision::Angular())) {
426 //if(!Dir1.IsParallel(Dir2,Precision::Angular())) {
427 if(!Dir1.IsParallel(Dir2,Tol)) {
430 // can union lines => create new edge
431 TopoDS_Vertex V1 = sae.FirstVertex(edge1);
432 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
433 TopoDS_Vertex V2 = sae.LastVertex(edge2);
434 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
436 Handle(Geom_Line) L = new Geom_Line(gp_Ax1(PV1,Vec));
437 Standard_Real dist = PV1.Distance(PV2);
438 Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(L,0.0,dist);
440 B.MakeEdge (E,tc,Precision::Confusion());
441 B.Add (E,V1); B.Add (E,V2);
442 B.UpdateVertex(V1, 0., E, 0.);
443 B.UpdateVertex(V2, dist, E, 0.);
445 //sfe.FixAddPCurve(E,aFace,Standard_False);
446 //sfe.FixSameParameter(E);
448 aChain.SetValue(j,E);
451 if( c3d1->IsKind(STANDARD_TYPE(Geom_Circle)) && c3d2->IsKind(STANDARD_TYPE(Geom_Circle)) ) {
453 Handle(Geom_Circle) C1 = Handle(Geom_Circle)::DownCast(c3d1);
454 Handle(Geom_Circle) C2 = Handle(Geom_Circle)::DownCast(c3d2);
455 gp_Pnt P01 = C1->Location();
456 gp_Pnt P02 = C2->Location();
457 if (P01.Distance(P02) > Precision::Confusion()) continue;
458 // can union circles => create new edge
459 TopoDS_Vertex V1 = sae.FirstVertex(edge1);
460 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
461 TopoDS_Vertex V2 = sae.LastVertex(edge2);
462 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
463 TopoDS_Vertex VM = sae.LastVertex(edge1);
464 gp_Pnt PVM = BRep_Tool::Pnt(VM);
465 GC_MakeCircle MC (PV1,PVM,PV2);
466 Handle(Geom_Circle) C;
474 // jfa for Mantis issue 0020228
475 if (PV1.Distance(PV2) > Precision::Confusion()) continue;
477 if (edge1.Orientation() == TopAbs_FORWARD) {
480 C = Handle(Geom_Circle)::DownCast(C1->Reversed());
483 B.MakeEdge (E,C,Precision::Confusion());
488 gp_Pnt P0 = C->Location();
489 gp_Dir D1(gp_Vec(P0,PV1));
490 gp_Dir D2(gp_Vec(P0,PV2));
491 Standard_Real fpar = C->XAxis().Direction().Angle(D1);
492 if(fabs(fpar)>Precision::Confusion()) {
494 gp_Dir ND = C->XAxis().Direction().Crossed(D1);
495 if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
499 Standard_Real lpar = C->XAxis().Direction().Angle(D2);
500 if(fabs(lpar)>Precision::Confusion()) {
502 gp_Dir ND = C->XAxis().Direction().Crossed(D2);
503 if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
507 if (lpar < fpar) lpar += 2*M_PI;
508 Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(C,fpar,lpar);
509 B.MakeEdge (E,tc,Precision::Confusion());
512 B.UpdateVertex(V1, fpar, E, 0.);
513 B.UpdateVertex(V2, lpar, E, 0.);
516 aChain.SetValue(j,E);
520 if (j < aChain.Length()) {
521 MESSAGE ("null curve3d in edge...");
522 return Standard_False;
524 if (aChain.Length() > 1) {
525 // second step: union edges with various curves
526 // skl for bug 0020052 from Mantis: perform such unions
527 // only if curves are bspline or bezier
528 bool NeedUnion = true;
529 for(j=1; j<=aChain.Length(); j++) {
530 TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j));
531 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,Loc,fp1,lp1);
532 if(c3d.IsNull()) continue;
533 while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
534 Handle(Geom_TrimmedCurve) tc =
535 Handle(Geom_TrimmedCurve)::DownCast(c3d);
536 c3d = tc->BasisCurve();
538 if( ( c3d->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
539 c3d->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ) ) continue;
544 MESSAGE ("can not make analitical union => make approximation");
545 TopoDS_Edge E = GlueEdgesWithPCurves(aChain, VF, VL);
549 for(j=1; j<=aChain.Length(); j++) {
550 TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j));
553 Handle(BRepAdaptor_HCompCurve) Adapt = new BRepAdaptor_HCompCurve(W);
554 Approx_Curve3d Conv(Adapt,Tol,GeomAbs_C1,9,1000);
555 Handle(Geom_BSplineCurve) bc = Conv.Curve();
557 B.MakeEdge (E,bc,Precision::Confusion());
561 aChain.SetValue(1,E);
564 MESSAGE ("can not make approximation for such types of curves");
565 return Standard_False;
569 anEdge = TopoDS::Edge(aChain.Value(1));
570 return Standard_True;
573 //=======================================================================
576 //=======================================================================
577 TopoDS_Shape BlockFix_UnionEdges::Perform(const TopoDS_Shape& Shape,
578 const Standard_Real Tol)
580 myContext = new ShapeBuild_ReShape;
582 TopoDS_Shape aResult = myContext->Apply(Shape);
584 // processing each solid
585 TopAbs_ShapeEnum aType = TopAbs_SOLID;
586 TopExp_Explorer exps (Shape, aType);
588 aType = TopAbs_SHELL;
589 exps.Init(Shape, aType);
591 for (; exps.More(); exps.Next()) {
592 //TopoDS_Solid aSolid = TopoDS::Solid(exps.Current());
593 TopoDS_Shape aSolid = exps.Current();
595 TopTools_IndexedMapOfShape ChangedFaces;
597 // creating map of edge faces
598 TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
599 TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
601 Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
602 TopoDS_Shape aRes = aSolid;
603 aRes = aContext->Apply(aSolid);
605 // processing each face
607 for (exp.Init(aRes, TopAbs_FACE); exp.More(); exp.Next()) {
609 TopoDS::Face(aContext->Apply(exp.Current().Oriented(TopAbs_FORWARD)));
610 TopTools_IndexedDataMapOfShapeListOfShape aMapFacesEdges;
612 for (TopExp_Explorer expe(aFace,TopAbs_EDGE); expe.More(); expe.Next()) {
613 TopoDS_Edge edge = TopoDS::Edge(expe.Current());
614 if (!aMapEdgeFaces.Contains(edge)) continue;
615 const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
616 TopTools_ListIteratorOfListOfShape anIter(aList);
617 for ( ; anIter.More(); anIter.Next()) {
618 TopoDS_Face face = TopoDS::Face(anIter.Value());
619 TopoDS_Face face1 = TopoDS::Face(aContext->Apply(anIter.Value()));
620 if (face1.IsSame(aFace)) continue;
621 if (aMapFacesEdges.Contains(face)) {
622 aMapFacesEdges.ChangeFromKey(face).Append(edge);
625 TopTools_ListOfShape ListEdges;
626 ListEdges.Append(edge);
627 aMapFacesEdges.Add(face,ListEdges);
632 for (Standard_Integer i=1; i<=aMapFacesEdges.Extent(); i++) {
633 const TopTools_ListOfShape& ListEdges = aMapFacesEdges.FindFromIndex(i);
634 TopTools_SequenceOfShape SeqEdges;
635 TopTools_ListIteratorOfListOfShape anIter(ListEdges);
636 for ( ; anIter.More(); anIter.Next()) {
637 SeqEdges.Append(anIter.Value());
639 if (SeqEdges.Length()==1) continue;
642 TopoDS::Face(aContext->Apply(aMapFacesEdges.FindKey(i)));
644 if ( MergeEdges(SeqEdges,aFace,aFace2,Tol,E) ) {
645 // now we have only one edge - aChain.Value(1)
646 // we have to replace old ListEdges with this new edge
647 aContext->Replace(SeqEdges(1),E);
648 for (Standard_Integer j=2; j<=SeqEdges.Length(); j++) {
649 aContext->Remove(SeqEdges(j));
651 TopoDS_Face tmpF = TopoDS::Face(exp.Current());
652 if ( !ChangedFaces.Contains(tmpF) )
653 ChangedFaces.Add(tmpF);
654 tmpF = TopoDS::Face(aMapFacesEdges.FindKey(i));
655 if ( !ChangedFaces.Contains(tmpF) )
656 ChangedFaces.Add(tmpF);
660 } // end processing each face
662 // fix changed faces and replace them in the local context
663 for (Standard_Integer i=1; i<=ChangedFaces.Extent(); i++) {
664 TopoDS_Face aFace = TopoDS::Face(aContext->Apply(ChangedFaces.FindKey(i)));
665 Handle(ShapeFix_Face) sff = new ShapeFix_Face(aFace);
666 sff->SetContext(myContext);
667 sff->SetPrecision(myTolerance);
668 sff->SetMinTolerance(myTolerance);
669 sff->SetMaxTolerance(Max(1.,myTolerance*1000.));
671 aContext->Replace(aFace,sff->Face());
674 if (ChangedFaces.Extent() > 0) {
675 // fix changed shell and replace it in the local context
676 TopoDS_Shape aRes1 = aContext->Apply(aRes);
677 TopExp_Explorer expsh;
678 for (expsh.Init(aRes1, TopAbs_SHELL); expsh.More(); expsh.Next()) {
679 TopoDS_Shell aShell = TopoDS::Shell(expsh.Current());
680 Handle(ShapeFix_Shell) sfsh = new ShapeFix_Shell;
681 sfsh->FixFaceOrientation(aShell);
682 aContext->Replace(aShell,sfsh->Shell());
684 TopoDS_Shape aRes2 = aContext->Apply(aRes1);
685 // put new solid into global context
686 myContext->Replace(aSolid,aRes2);
689 } // end processing each solid
691 aResult = myContext->Apply(Shape);