1 // File: BRepBuilderAPI_Sewing.cxx
2 // Created: Fri Mar 24 09:45:44 1995
3 // Author: Jing Cheng MEI
5 // dcl CCI60011 : Correction of degeneratedSection
6 // Improvement of SameParameter Edge to treat case of failure in BRepLib::SameParameter
7 // dcl Thu Aug 20 09:24:49 1998
8 // Suppression of little faces.
9 // dcl Fri Aug 7 15:27:46 1998
10 // Refection of function SameParameter Edge.
11 // Merge on the edge which has the less of poles.
12 // Suppression of the Connected Edge function.
13 // dcl Tue Jun 9 14:21:53 1998
14 // Do not merge edge if they belong the same face
15 // Tolerance management in VerticesAssembling
16 // Tolerance management in Cutting
17 // dcl Thu May 14 15:51:46 1998
18 // optimization of cutting
19 // dcl Thu May 7 15:51:46 1998
20 // Add of cutting option
21 // Add of SameParameter call
25 //-- dpf December 10 1997 Processing of pcurve collections
27 //rln 02.02.99 BUC60449 Making compilable on NT in DEB mode
28 //rln 02.02.99 BUC60449 Protection against exception on NT
32 #include <BRepBuilderAPI_Sewing.ixx>
34 #include <Bnd_Box.hxx>
35 #include <Bnd_Box2d.hxx>
36 #include <Bnd_HArray1OfBox.hxx>
37 #include <BndLib_Add2dCurve.hxx>
38 #include <BndLib_Add3dCurve.hxx>
39 #include <BRep_Builder.hxx>
40 #include <BRep_Tool.hxx>
41 #include <BRepLib.hxx>
42 #include <BRepTools_Quilt.hxx>
43 #include <BSplCLib.hxx>
44 #include <Extrema_ExtPC.hxx>
45 #include <GCPnts_AbscissaPoint.hxx>
46 #include <GCPnts_UniformAbscissa.hxx>
47 #include <GCPnts_UniformDeflection.hxx>
48 #include <Geom2d_BezierCurve.hxx>
49 #include <Geom2d_BSplineCurve.hxx>
50 #include <Geom2d_Curve.hxx>
51 #include <Geom2d_Line.hxx>
52 #include <Geom2d_TrimmedCurve.hxx>
53 #include <Geom2dAdaptor_Curve.hxx>
54 #include <Geom2dConvert.hxx>
55 #include <Geom_BezierCurve.hxx>
56 #include <Geom_BSplineCurve.hxx>
57 #include <Geom_Curve.hxx>
58 #include <Geom_Line.hxx>
59 #include <Geom_Surface.hxx>
60 #include <GeomAdaptor_Curve.hxx>
61 #include <GeomAdaptor_Surface.hxx>
62 #include <GeomLib.hxx>
65 //#include <LocalAnalysis_SurfaceContinuity.hxx>
66 #include <Precision.hxx>
67 #include <Standard_ErrorHandler.hxx>
68 #include <Standard_Failure.hxx>
69 #include <TColgp_Array1OfVec.hxx>
70 #include <TColgp_SequenceOfPnt.hxx>
71 #include <TColStd_Array1OfInteger.hxx>
72 #include <TColStd_Array1OfReal.hxx>
73 #include <TColStd_DataMapIteratorOfDataMapOfIntegerListOfInteger.hxx>
74 #include <TColStd_DataMapOfIntegerListOfInteger.hxx>
75 #include <TColStd_IndexedMapOfInteger.hxx>
76 #include <TColStd_ListIteratorOfListOfInteger.hxx>
77 #include <TColStd_ListOfInteger.hxx>
78 #include <TColStd_MapOfInteger.hxx>
79 #include <TColStd_SequenceOfReal.hxx>
82 #include <TopExp_Explorer.hxx>
83 #include <TopLoc_Location.hxx>
85 #include <TopoDS_Edge.hxx>
86 #include <TopoDS_Iterator.hxx>
87 #include <TopoDS_Shape.hxx>
88 #include <TopoDS_Vertex.hxx>
89 #include <TopoDS_Wire.hxx>
90 #include <TopoDS_Shell.hxx>
91 #include <TopTools_Array1OfShape.hxx>
92 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
93 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
94 #include <TopTools_DataMapOfShapeInteger.hxx>
95 #include <TopTools_DataMapOfShapeListOfShape.hxx>
96 #include <TopTools_ListIteratorOfListOfShape.hxx>
97 #include <TopTools_ListOfShape.hxx>
98 #include <TopTools_MapIteratorOfMapOfShape.hxx>
99 #include <TopTools_MapOfShape.hxx>
100 #include <TopTools_SequenceOfShape.hxx>
101 #include <TopoDS_Compound.hxx>
102 #include <TColStd_Array2OfReal.hxx>
103 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
104 #include <BRepTools.hxx>
105 #include <Geom_RectangularTrimmedSurface.hxx>
106 #include <Geom_OffsetSurface.hxx>
107 #include <BRep_PointOnCurve.hxx>
108 #include <BRep_ListOfPointRepresentation.hxx>
109 #include <BRep_TVertex.hxx>
110 #include <Message_ProgressSentry.hxx>
111 #include <BRepBuilderAPI_VertexInspector.hxx>
112 #include <BRepBuilderAPI_CellFilter.hxx>
113 #include <BRepBuilderAPI_BndBoxTreeSelector.hxx>
114 #include <NCollection_UBTreeFiller.hxx>
116 static void SortBox (const Handle(Bnd_HArray1OfBox) hSetBoxes,
118 TColStd_ListOfInteger& listIndex)
120 Standard_Integer i, nbBoxes = hSetBoxes->Length();
121 for (i = 1; i <= nbBoxes; i++)
122 if (!aBox.IsOut(hSetBoxes->Value(i)))
126 //=======================================================================
127 //function : SameRange
129 //=======================================================================
131 Handle(Geom2d_Curve) BRepBuilderAPI_Sewing::SameRange(const Handle(Geom2d_Curve)& CurvePtr,
132 const Standard_Real FirstOnCurve,
133 const Standard_Real LastOnCurve,
134 const Standard_Real RequestedFirst,
135 const Standard_Real RequestedLast) const
137 Handle(Geom2d_Curve) NewCurvePtr;
140 GeomLib::SameRange(Precision::PConfusion(),CurvePtr,FirstOnCurve,LastOnCurve,
141 RequestedFirst,RequestedLast,NewCurvePtr);
143 catch (Standard_Failure) {
145 cout << "Exception in BRepBuilderAPI_Sewing::SameRange: ";
146 Standard_Failure::Caught()->Print(cout); cout << endl;
152 //=======================================================================
153 //function : WhichFace
154 //purpose : Give the face whose edge is the border
155 //=======================================================================
157 TopoDS_Face BRepBuilderAPI_Sewing::WhichFace(const TopoDS_Edge& theEdg, const Standard_Integer index) const
159 TopoDS_Shape bound = theEdg;
160 if (mySectionBound.IsBound(bound)) bound = mySectionBound(bound);
161 if (myBoundFaces.Contains(bound)) {
162 Standard_Integer i = 1;
163 TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bound));
164 for (; itf.More(); itf.Next(), i++)
165 if (i == index) return TopoDS::Face(itf.Value());
167 return TopoDS_Face();
170 //=======================================================================
171 //function : IsClosedShape
173 //=======================================================================
175 static Standard_Boolean IsClosedShape(const TopoDS_Shape& theshape,
176 const TopoDS_Shape& v1, const TopoDS_Shape& v2)
178 Standard_Real TotLength = 0.0;
179 TopExp_Explorer aexp;
180 for (aexp.Init(theshape,TopAbs_EDGE); aexp.More(); aexp.Next()) {
181 TopoDS_Edge aedge = TopoDS::Edge(aexp.Current());
182 if (aedge.IsNull()) continue;
183 TopoDS_Vertex ve1,ve2;
184 TopExp::Vertices(aedge,ve1,ve2);
185 if (!ve1.IsSame(v1) && !ve1.IsSame(v2)) continue;
186 if (BRep_Tool::Degenerated(aedge)) continue;
187 Standard_Real first,last;
188 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aedge), first, last);
190 GeomAdaptor_Curve cAdapt(c3d);
191 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
193 if (ve2.IsSame(v1) || ve2.IsSame(v2)) break;
196 if (TotLength > 0.0) {
197 gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(v1));
198 gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(v2));
199 return (p1.Distance(p2) < TotLength/(1.2 * M_PI));
201 return Standard_False;
204 //=======================================================================
205 //function : IsClosedByIsos
207 //=======================================================================
208 static Standard_Boolean IsClosedByIsos(const Handle(Geom_Surface)& thesurf,
209 const Handle(Geom2d_Curve)& acrv2d,
210 const Standard_Real f2d,
211 const Standard_Real l2d,
212 const Standard_Boolean isUIsos)
214 Standard_Boolean isClosed = Standard_False;
216 gp_Pnt2d psurf1 = (acrv2d->IsPeriodic() ?
217 acrv2d->Value(f2d) : acrv2d->Value(Max(f2d,acrv2d->FirstParameter())));
218 gp_Pnt2d psurf2 = (acrv2d->IsPeriodic() ?
219 acrv2d->Value(l2d) : acrv2d->Value(Min(l2d,acrv2d->LastParameter())));
220 Handle(Geom_Curve) aCrv1;
221 Handle(Geom_Curve) aCrv2;
223 aCrv1 = thesurf->UIso(psurf1.X());
224 aCrv2 = thesurf->UIso(psurf2.X());
227 aCrv1 = thesurf->VIso(psurf1.Y());
228 aCrv2 = thesurf->VIso(psurf2.Y());
230 gp_Pnt p11,p1m,p12,p21,p2m,p22;
231 Standard_Real af1 = aCrv1->FirstParameter();
232 Standard_Real al1 = aCrv1->LastParameter();
233 Standard_Real af2 = aCrv2->FirstParameter();
234 Standard_Real al2 = aCrv2->LastParameter();
236 aCrv1->D0((af1+al1)*0.5,p1m);
239 aCrv2->D0((af2+al2)*0.5,p2m);
241 isClosed = (((p11.XYZ() - p12.XYZ()).Modulus() <
242 (p11.XYZ() - p1m.XYZ()).Modulus() - Precision::Confusion()) &&
243 ((p21.XYZ() - p22.XYZ()).Modulus() <
244 (p21.XYZ() - p2m.XYZ()).Modulus() - Precision::Confusion())) ;
247 //=======================================================================
248 //function : IsUClosedSurface
250 //=======================================================================
252 Standard_Boolean BRepBuilderAPI_Sewing::IsUClosedSurface(const Handle(Geom_Surface)& surf,
253 const TopoDS_Shape& theEdge,
254 const TopLoc_Location& theloc) const
256 Handle(Geom_Surface) tmpsurf = surf;
257 if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
258 tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
259 else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
260 tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
262 Standard_Boolean isClosed = tmpsurf->IsUClosed();
264 Standard_Real f2d, l2d;
265 Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
267 isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_False );
272 return IsUClosedSurface(tmpsurf,theEdge,theloc);
273 //return surf->IsUClosed();
276 //=======================================================================
277 //function : IsVClosedSurface
279 //=======================================================================
281 Standard_Boolean BRepBuilderAPI_Sewing::IsVClosedSurface(const Handle(Geom_Surface)& surf,
282 const TopoDS_Shape& theEdge,
283 const TopLoc_Location& theloc) const
285 Handle(Geom_Surface) tmpsurf = surf;
286 if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
287 tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
288 else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
289 tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
291 Standard_Boolean isClosed = tmpsurf->IsVClosed();
293 Standard_Real f2d, l2d;
294 Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
296 isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_True );
300 return IsVClosedSurface(tmpsurf,theEdge,theloc);
301 //return surf->IsVClosed();
304 //=======================================================================
305 //function : SameParameter
306 //purpose : internal use
307 //=======================================================================
309 void BRepBuilderAPI_Sewing::SameParameter(const TopoDS_Edge& edge) const
313 BRepLib::SameParameter(edge);
315 catch (Standard_Failure) {
317 cout << "Exception in BRepBuilderAPI_Sewing::SameParameter: ";
318 Standard_Failure::Caught()->Print(cout); cout << endl;
323 //=======================================================================
324 //function : SameParameterEdge
325 //purpose : internal use
326 // Merge the Sequence Of Section on one edge.
327 // This function keep the curve3d,curve2d,range and parametrization
328 // from the first section, and report and made sameparameter the
329 // pcurves of the other function.
330 // This function works when the are not more than two Pcurves
332 //=======================================================================
334 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Shape& edge,
335 const TopTools_SequenceOfShape& seqEdges,
336 const TColStd_SequenceOfInteger& seqForward,
337 TopTools_MapOfShape& mapMerged,
338 const Handle(BRepTools_ReShape)& locReShape)
340 // Retrieve reference section
341 TopoDS_Shape aTmpShape = myReShape->Apply(edge); //for porting
342 TopoDS_Edge Edge1 = TopoDS::Edge(aTmpShape);
343 aTmpShape = locReShape->Apply(Edge1);
344 if (locReShape != myReShape) Edge1 = TopoDS::Edge(aTmpShape);
345 Standard_Boolean isDone = Standard_False;
347 // Create data structures for temporary merged edges
348 TopTools_ListOfShape listFaces1;
349 TopTools_MapOfShape MergedFaces;
353 // Fill MergedFaces with faces of Edge1
354 TopoDS_Shape bnd1 = edge;
355 if (mySectionBound.IsBound(bnd1)) bnd1 = mySectionBound(bnd1);
356 if (myBoundFaces.Contains(bnd1)) {
357 TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bnd1));
358 for (; itf.More(); itf.Next())
359 if (MergedFaces.Add(itf.Value()))
360 listFaces1.Append(itf.Value());
365 // Create presentation edge
366 TopoDS_Vertex V1, V2;
367 TopExp::Vertices(Edge1,V1,V2);
368 if (myVertexNode.Contains(V1)) V1 = TopoDS::Vertex(myVertexNode.FindFromKey(V1));
369 if (myVertexNode.Contains(V2)) V2 = TopoDS::Vertex(myVertexNode.FindFromKey(V2));
371 TopoDS_Edge NewEdge = Edge1;
375 BRep_Builder aBuilder;
376 TopoDS_Shape anEdge = NewEdge.Oriented(TopAbs_FORWARD);
377 aBuilder.Add(anEdge,V1.Oriented(TopAbs_FORWARD));
378 aBuilder.Add(anEdge,V2.Oriented(TopAbs_REVERSED));
383 Standard_Boolean isForward = Standard_True;
385 // Merge candidate sections
386 for (Standard_Integer i = 1; i <= seqEdges.Length(); i++) {
388 // Retrieve candidate section
389 TopoDS_Shape oedge2 = seqEdges(i);
393 aTmpShape = myReShape->Apply(oedge2); //for porting
394 TopoDS_Edge Edge2 = TopoDS::Edge(aTmpShape);
395 aTmpShape = locReShape->Apply(Edge2);
396 if (locReShape != myReShape) Edge2 = TopoDS::Edge(aTmpShape);
398 // Calculate relative orientation
399 Standard_Integer Orientation = seqForward(i);
400 if (!isForward) Orientation = (Orientation? 0 : 1);
402 // Retrieve faces information for the second edge
403 TopoDS_Shape bnd2 = oedge2;
404 if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
405 if (!myBoundFaces.Contains(bnd2)) continue; // Skip floating edge
406 const TopTools_ListOfShape& listFaces2 = myBoundFaces.FindFromKey(bnd2);
408 Standard_Integer whichSec = 1; // Indicates on which edge the pCurve has been reported
409 TopoDS_Edge NewEdge = SameParameterEdge(Edge1,Edge2,listFaces1,listFaces2,Orientation,whichSec);
410 if (NewEdge.IsNull()) continue;
412 // Record faces information for the temporary merged edge
413 TopTools_ListIteratorOfListOfShape itf(listFaces2);
414 for (; itf.More(); itf.Next())
415 if (MergedFaces.Add(itf.Value()))
416 listFaces1.Append(itf.Value());
418 // Record merged section orientation
419 if (!Orientation && whichSec != 1)
420 isForward = isForward? Standard_False : Standard_True;
424 // Append actually merged edge
425 mapMerged.Add(oedge2);
426 isDone = Standard_True;
428 if (!myNonmanifold) break;
432 // Change result orientation
433 Edge1.Orientation(isForward? TopAbs_FORWARD : TopAbs_REVERSED);
435 else Edge1.Nullify();
440 //=======================================================================
441 //function : SameParameterEdge
442 //purpose : internal use
443 //=======================================================================
444 static Standard_Boolean findNMVertices(const TopoDS_Edge& theEdge,
445 TopTools_SequenceOfShape& theSeqNMVert,
446 TColStd_SequenceOfReal& theSeqPars)
448 TopoDS_Iterator aItV(theEdge,Standard_False);
449 for( ; aItV.More(); aItV.Next()) {
450 if(aItV.Value().Orientation() == TopAbs_INTERNAL ||
451 aItV.Value().Orientation() == TopAbs_EXTERNAL)
452 theSeqNMVert.Append(aItV.Value());
454 Standard_Integer nbV = theSeqNMVert.Length();
456 return Standard_False;
457 Standard_Real first, last;
458 Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,first, last);
459 GeomAdaptor_Curve GAC(c3d);
460 Extrema_ExtPC locProj;
461 locProj.Initialize(GAC, first, last);
462 gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
465 for (Standard_Integer i = 1; i <= nbV; i++) {
466 TopoDS_Vertex aV = TopoDS::Vertex(theSeqNMVert.Value(i));
467 gp_Pnt pt = BRep_Tool::Pnt(aV);
469 Standard_Real distF2 = pfirst.SquareDistance(pt);
470 Standard_Real distL2 = plast.SquareDistance(pt);
471 Standard_Real apar = (distF2 > distL2 ? last : first);
472 // Project current point on curve
474 if (locProj.IsDone() && locProj.NbExt() > 0) {
475 Standard_Real dist2Min = Min(distF2,distL2);
476 Standard_Integer ind, indMin = 0;
477 for (ind = 1; ind <= locProj.NbExt(); ind++) {
478 Standard_Real dProj2 = locProj.SquareDistance(ind);
479 if (dProj2 < dist2Min) {
480 indMin = ind; dist2Min = dProj2;
484 apar = locProj.Point(indMin).Parameter();
486 theSeqPars.Append(apar);
490 return Standard_True;
493 static inline Standard_Real ComputeToleranceVertex(const Standard_Real dist, const Standard_Real Tol1, const Standard_Real Tol2)
495 return (dist * 0.5 + Tol1 + Tol2);
497 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirst,
498 const TopoDS_Edge& edgeLast,
499 const TopTools_ListOfShape& listFacesFirst,
500 const TopTools_ListOfShape& listFacesLast,
501 const Standard_Boolean secForward,
502 Standard_Integer& whichSec,
503 const Standard_Boolean firstCall)
505 // Do not process floating edges
506 if (!listFacesFirst.Extent() || !listFacesLast.Extent()) return TopoDS_Edge();
509 TopoDS_Edge edge1, edge2;
511 // Take the longest edge as first
513 Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(TopoDS::Edge(edgeFirst), f, l);
514 GeomAdaptor_Curve cAdapt1(c3d1);
515 Standard_Real len1 = GCPnts_AbscissaPoint::Length(cAdapt1, f, l);
516 Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(TopoDS::Edge(edgeLast), f, l);
517 GeomAdaptor_Curve cAdapt2(c3d2);
518 Standard_Real len2 = GCPnts_AbscissaPoint::Length(cAdapt2, f, l);
543 Standard_Real first, last;
544 BRep_Tool::Range(edge1, first, last);
545 BRep_Builder aBuilder;
547 //To keep NM vertices on edge
548 TopTools_SequenceOfShape aSeqNMVert;
549 TColStd_SequenceOfReal aSeqNMPars;
550 findNMVertices(edge1,aSeqNMVert,aSeqNMPars);
551 findNMVertices(edge2,aSeqNMVert,aSeqNMPars);
555 aBuilder.MakeEdge(edge);
556 edge.Orientation( edge1.Orientation());
559 // Retrieve edge curve
560 TopLoc_Location loc3d;
561 Standard_Real first3d, last3d;
562 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge1, loc3d, first3d, last3d);
563 if (!loc3d.IsIdentity()) {
564 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
565 c3d->Transform(loc3d.Transformation());
567 aBuilder.UpdateEdge(edge,c3d,BRep_Tool::Tolerance(edge1));
568 aBuilder.Range(edge, first, last);
569 aBuilder.SameRange(edge, Standard_False); //Standard_True
570 aBuilder.SameParameter(edge, Standard_False);
571 // Create and add new vertices
573 TopoDS_Vertex V1New, V2New;
575 // Retrieve original vertices from edges
576 TopoDS_Vertex V11,V12,V21,V22;
577 TopExp::Vertices(edge1,V11,V12);
578 TopExp::Vertices(edge2,V21,V22);
580 //check that edges merged valid way (for edges having length less than specified
582 // Check if edges are closed
583 Standard_Boolean isClosed1 = V11.IsSame(V12);
584 Standard_Boolean isClosed2 = V21.IsSame(V22);
585 if(!isClosed1 && !isClosed2)
589 if( V11.IsSame(V22) || V12.IsSame(V21) )
590 return TopoDS_Edge();
594 if( V11.IsSame(V21) || V12.IsSame(V22) )
595 return TopoDS_Edge();
599 //szv: do not reshape here!!!
600 //V11 = TopoDS::Vertex(myReShape->Apply(V11));
601 //V12 = TopoDS::Vertex(myReShape->Apply(V12));
602 //V21 = TopoDS::Vertex(myReShape->Apply(V21));
603 //V22 = TopoDS::Vertex(myReShape->Apply(V22));
605 gp_Pnt p11 = BRep_Tool::Pnt(V11);
606 gp_Pnt p12 = BRep_Tool::Pnt(V12);
607 gp_Pnt p21 = BRep_Tool::Pnt(V21);
608 gp_Pnt p22 = BRep_Tool::Pnt(V22);
612 //Standard_Boolean isRev = Standard_False;
614 Standard_Real Tol1 = 0.;
615 if (isClosed1 || isClosed2) {
616 // at least one of the edges is closed
617 if (isClosed1 && isClosed2) {
618 // both edges are closed
619 pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ()));
620 gp_Vec v1 = p21.XYZ() - p11.XYZ();
621 Standard_Real d1 = v1.Magnitude();
622 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21));
623 //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p21));
625 else if (isClosed1) {
626 // only first edge is closed
627 gp_XYZ pt =0.5*(p21.XYZ()+ p22.XYZ());
628 pfirst.SetXYZ(0.5*(p11.XYZ() + pt));
629 gp_Vec v1 = p22.XYZ() - p21.XYZ();
630 Standard_Real d1 = v1.Magnitude();
631 Tol1= ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V22),BRep_Tool::Tolerance(V21));
632 gp_Vec v2 = p11.XYZ() - pt;
633 Standard_Real d2 = v2.Magnitude();
634 Tol1= ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V11));
635 //Tol1 = Max(pfirst.Distance(p21),pfirst.Distance(p22));
636 //Tol1 = Max(pfirst.Distance(p11),Tol1);
639 // only second edge is closed
640 gp_XYZ pt = 0.5*(p11.XYZ()+ p12.XYZ());
641 pfirst.SetXYZ(0.5*(p21.XYZ() + pt));
642 gp_Vec v1 = p11.XYZ() - p12.XYZ();
643 Standard_Real d1 = v1.Magnitude();
644 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V12));
645 gp_Vec v2 = p21.XYZ() - pt;
646 Standard_Real d2 = v2.Magnitude();
647 Tol1 = ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V21));
648 //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p12));
649 //Tol1 = Max(pfirst.Distance(p21),Tol1);
651 aBuilder.MakeVertex(V1New,pfirst,Tol1);
655 // both edges are open
657 Standard_Real Tol2 = 0.;
658 Standard_Boolean isOldFirst = ( secForward ? V11.IsSame(V21) : V11.IsSame(V22) );
659 Standard_Boolean isOldLast = ( secForward ? V12.IsSame(V22) : V12.IsSame(V21)) ;
661 //case if vertices already sewed
664 pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ()));
665 gp_Vec v1 = p21.XYZ() - p11.XYZ();
666 Standard_Real d1 = v1.Magnitude();
667 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21));
671 plast.SetXYZ(0.5*(p12.XYZ() + p22.XYZ()));
673 gp_Vec v2 = p22.XYZ() - p12.XYZ();
674 Standard_Real d2 = v2.Magnitude();
676 Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V22));
683 pfirst.SetXYZ(0.5*(p11.XYZ() + p22.XYZ()));
684 gp_Vec v1 = p22.XYZ() - p11.XYZ();
685 Standard_Real d1 = v1.Magnitude();
686 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V22));
690 plast.SetXYZ(0.5*(p12.XYZ() + p21.XYZ()));
691 gp_Vec v2 = p21.XYZ() - p12.XYZ();
692 Standard_Real d2 = v2.Magnitude();
693 Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V21));
698 aBuilder.MakeVertex(V1New,pfirst,Tol1);
704 aBuilder.MakeVertex(V2New,plast,Tol2);
710 // Add the vertices in the good sense
711 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
712 TopoDS_Shape aLocalEdge = V1New.Oriented(TopAbs_FORWARD); //(listNode.First()).Oriented(TopAbs_FORWARD);
713 aBuilder.Add(anEdge,aLocalEdge);
714 aLocalEdge = V2New.Oriented(TopAbs_REVERSED); //(listNode.Last()).Oriented(TopAbs_REVERSED);
715 aBuilder.Add(anEdge,aLocalEdge);
717 Standard_Integer k =1;
718 for( ; k <= aSeqNMVert.Length(); k++)
719 aBuilder.Add(anEdge,aSeqNMVert.Value(k));
723 // Retrieve second PCurves
724 TopLoc_Location loc2;
725 Handle(Geom_Surface) surf2;
726 //Handle(Geom2d_Curve) c2d2, c2d21;
727 // Standard_Real firstOld, lastOld;
729 TopTools_ListIteratorOfListOfShape itf2;
730 if (whichSec == 1) itf2.Initialize(listFacesLast);
731 else itf2.Initialize(listFacesFirst);
732 Standard_Boolean isResEdge = Standard_False;
733 for (; itf2.More(); itf2.Next()) {
734 Handle(Geom2d_Curve) c2d2, c2d21;
735 Standard_Real firstOld, lastOld;
736 const TopoDS_Face& fac2 = TopoDS::Face(itf2.Value());
738 surf2 = BRep_Tool::Surface(fac2, loc2);
739 Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) &&
740 BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2));
742 if (!myNonmanifold) return TopoDS_Edge();
743 TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting
744 c2d21 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac2, firstOld, lastOld);
746 c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld);
747 if (c2d2.IsNull() && c2d21.IsNull()) continue;
749 if (!c2d21.IsNull()) {
750 c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy());
752 if (c2d21->IsKind(STANDARD_TYPE(Geom2d_Line)))
753 c2d21 = new Geom2d_TrimmedCurve(c2d21, firstOld, lastOld);
754 Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
755 Standard_Real last2d = lastOld; //c2dTmp->LastParameter();
756 firstOld = c2d21->ReversedParameter(last2d);
757 lastOld = c2d21->ReversedParameter(first2d);
760 c2d21 = SameRange(c2d21,firstOld,lastOld,first,last);
763 // Make second PCurve sameRange with the 3d curve
764 c2d2 = Handle(Geom2d_Curve)::DownCast(c2d2->Copy());
767 if (c2d2->IsKind(STANDARD_TYPE(Geom2d_Line)))
768 c2d2 = new Geom2d_TrimmedCurve(c2d2, firstOld, lastOld);
769 Standard_Real first2d = firstOld;
770 Standard_Real last2d = lastOld;
771 firstOld = c2d2->ReversedParameter(last2d);
772 lastOld = c2d2->ReversedParameter(first2d);
776 c2d2 = SameRange(c2d2,firstOld,lastOld,first,last);
777 if (c2d2.IsNull()) continue;
780 Standard_Boolean isSeam = Standard_False;
781 TopAbs_Orientation Ori = TopAbs_FORWARD;
782 //Handle(Geom2d_Curve) c2d1, c2d11;
784 TopTools_ListIteratorOfListOfShape itf1;
785 if (whichSec == 1) itf1.Initialize(listFacesFirst);
786 else itf1.Initialize(listFacesLast);
787 for (; itf1.More() && !isSeam; itf1.Next()) {
788 Handle(Geom2d_Curve) c2d1, c2d11;
789 const TopoDS_Face& fac1 = TopoDS::Face(itf1.Value());
791 TopLoc_Location loc1;
792 Handle(Geom_Surface) surf1 = BRep_Tool::Surface(fac1, loc1);
793 Standard_Real first2d, last2d;
794 Standard_Boolean isSeam1 = ((IsUClosedSurface(surf1,edge1,loc1) || IsVClosedSurface(surf1,edge1,loc1)) &&
795 BRep_Tool::IsClosed(TopoDS::Edge(edge1),fac1));
796 c2d1 = BRep_Tool::CurveOnSurface(edge1, fac1, first2d, last2d);
797 Ori = edge1.Orientation();
798 if (fac1.Orientation() == TopAbs_REVERSED)
799 Ori = TopAbs::Reverse(Ori);
802 if (!myNonmanifold) return TopoDS_Edge();
803 TopoDS_Shape aTmpShape = edge1.Reversed(); //for porting
804 c2d11 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac1, first2d, last2d);
805 //if(fac1.Orientation() == TopAbs_REVERSED) //
806 if(Ori == TopAbs_FORWARD)
807 aBuilder.UpdateEdge(edge,c2d1,c2d11,fac1,0);
809 aBuilder.UpdateEdge(edge,c2d11,c2d1,fac1,0);
811 else aBuilder.UpdateEdge(edge,c2d1,fac1,0);
813 if (c2d1.IsNull() && c2d11.IsNull()) continue;
815 if (surf2 == surf1) {
816 // Merge sections which are on the same face
817 if (!loc2.IsDifferent(loc1)) {
818 Standard_Boolean uclosed = IsUClosedSurface(surf2,edge2,loc2);
819 Standard_Boolean vclosed = IsVClosedSurface(surf2,edge2,loc2);
820 if (uclosed || vclosed) {
821 Standard_Real pf = c2d1->FirstParameter();
822 // Standard_Real pl = c2d1->LastParameter();
823 gp_Pnt2d p1n = c2d1->Value(Max(first,pf));
824 // gp_Pnt2d p2n = c2d1->Value(Min(pl,last));
825 gp_Pnt2d p21n = c2d2->Value(Max(first,c2d2->FirstParameter()));
826 gp_Pnt2d p22n = c2d2->Value(Min(last,c2d2->LastParameter()));
827 Standard_Real aDist = Min(p1n.Distance(p21n), p1n.Distance(p22n));
828 Standard_Real U1, U2, V1, V2;
829 surf2->Bounds(U1, U2, V1, V2);
830 isSeam = ((uclosed && aDist > 0.75*(fabs(U2-U1))) ||
831 (vclosed && aDist > 0.75*(fabs(V2-V1))));
832 if( !isSeam && BRep_Tool::IsClosed(TopoDS::Edge(edge),fac1)) continue;
837 isResEdge = Standard_True;
839 if (Ori == TopAbs_FORWARD)
840 aBuilder.UpdateEdge(edge, c2d1, c2d2, surf2, loc2, Precision::Confusion());
842 aBuilder.UpdateEdge(edge, c2d2, c2d1, surf2, loc2, Precision::Confusion());
845 TopAbs_Orientation InitOri = edge2.Orientation();
846 TopAbs_Orientation SecOri = edge.Orientation();
847 if (fac2.Orientation() == TopAbs_REVERSED) {
849 InitOri = TopAbs::Reverse(InitOri);
850 SecOri = TopAbs::Reverse(SecOri);
853 InitOri = TopAbs::Reverse(InitOri);
855 if (InitOri == TopAbs_FORWARD)
856 aBuilder.UpdateEdge(edge, c2d2,c2d21, surf2, loc2, Precision::Confusion());
858 aBuilder.UpdateEdge(edge, c2d21,c2d2, surf2, loc2, Precision::Confusion());
861 aBuilder.UpdateEdge(edge, c2d2, surf2, loc2, Precision::Confusion());
867 // Try to make the edge sameparameter
870 // Standard_Real tolReached = BRep_Tool::Tolerance(edge);
871 //if (!BRep_Tool::SameParameter(edge)) return edge; //gka ????????
873 if (firstCall && (!BRep_Tool::SameParameter(edge) || !isResEdge)) {
874 Standard_Integer whichSecn = whichSec;
875 // Try to merge on the second section
876 Standard_Boolean second_ok = Standard_True;
877 TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast,
878 secForward,whichSecn,Standard_False);
879 //if (s_edge.IsNull()) return s_edge; // gka version for free edges
880 if (s_edge.IsNull()) second_ok = Standard_False;
881 else if (!BRep_Tool::SameParameter(s_edge)) second_ok = Standard_False;
884 whichSec = whichSecn;
889 GeomAdaptor_Curve c3dAdapt(c3d);
891 // Discretize edge curve
892 Standard_Integer i, j, nbp = 15;
893 Standard_Real deltaT = (last3d - first3d) / (nbp + 1);
894 TColgp_Array1OfPnt c3dpnt(1,nbp);
895 for (i = 1; i <= nbp; i++) c3dpnt(i) = c3dAdapt.Value(first3d + i*deltaT);
897 Standard_Real u, v, dist, maxTol = -1.0;
898 Standard_Boolean more = Standard_True;
900 for (j = 1; more; j++) {
901 Handle(Geom2d_Curve) c2d2;
902 BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j);
903 more = !c2d2.IsNull();
906 deltaT = (last - first) / (nbp + 1);
907 for (i = 1; i <= nbp; i++) {
908 c2d2->Value(first + i*deltaT).Coord(u,v);
909 dist = surf2->Value(u,v).Distance(c3dpnt(i));
910 if (dist > maxTol) maxTol = dist;
915 if (maxTol >= 0.) aBuilder.UpdateEdge(edge, maxTol);
916 aBuilder.SameParameter(edge,Standard_True);
920 BRepLib::EncodeRegularity(edge,0.01);
921 Standard_Real tolEdge1 = BRep_Tool::Tolerance(edge);
922 if (tolEdge1 > MaxTolerance()) edge.Nullify();
926 //=======================================================================
927 // function : EvaluateAngulars
928 // purpose : internal use
929 //=======================================================================
931 void BRepBuilderAPI_Sewing::EvaluateAngulars(TopTools_SequenceOfShape& sequenceSec,
932 TColStd_Array1OfBoolean& secForward,
933 TColStd_Array1OfReal& tabAng,
934 const Standard_Integer indRef) const
938 Standard_Integer i, j, npt = 4, lengSec = sequenceSec.Length();
943 Standard_Real first, last;
944 Handle(Geom_Curve) c3d;
945 Handle(Geom2d_Curve) c2d;
946 Handle(Geom_Surface) surf;
947 TColgp_Array1OfVec normRef(1,npt);
949 for (i = indRef; i <= lengSec; i++) {
951 edge = TopoDS::Edge(sequenceSec(i));
953 TopoDS_Shape bnd = edge;
954 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
955 if (myBoundFaces.Contains(bnd)) {
956 face = TopoDS::Face(myBoundFaces.FindFromKey(bnd).First());
957 surf = BRep_Tool::Surface(face,loc);
958 if (!loc.IsIdentity()) {
959 surf = Handle(Geom_Surface)::DownCast(surf->Copy());
960 surf->Transform(loc.Transformation());
962 c2d = BRep_Tool::CurveOnSurface(edge, face, first, last);
964 else if (i == indRef) return;
967 c3d = BRep_Tool::Curve(edge, loc, first, last);
968 if (!loc.IsIdentity()) {
969 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
970 c3d->Transform(loc.Transformation());
973 GeomAdaptor_Curve adapt(c3d);
974 GCPnts_UniformAbscissa uniAbs(adapt, npt, first, last);
976 Standard_Real cumulateAngular = 0.0;
977 Standard_Integer nbComputedAngle = 0;
979 for (j = 1; j <= npt; j++) {
981 c2d->D0(uniAbs.Parameter((secForward(i) || i == indRef)? j : npt-j+1),P);
984 surf->D1(P.X(), P.Y(), unused, w1, w2);
985 gp_Vec n = w1^w2; // Compute the normal vector
986 if (i == indRef) normRef(j) = n;
987 else if ((n.Magnitude()>gp::Resolution()) && (normRef(j).Magnitude()>gp::Resolution())) {
989 Standard_Real angular = n.Angle(normRef(j));
990 if (angular > M_PI/2.) angular = M_PI - angular;
991 cumulateAngular += angular;
996 tabAng(i) = cumulateAngular/((Standard_Real)nbComputedAngle);
1000 //=======================================================================
1001 // function : EvaluateDistances
1002 // purpose : internal use
1003 // Evaluate distance beetween edges with indice indRef and the following edges in the list
1004 // Remarks (lengSec - indRef) must be >= 1
1005 //=======================================================================
1006 void BRepBuilderAPI_Sewing::EvaluateDistances(TopTools_SequenceOfShape& sequenceSec,
1007 TColStd_Array1OfBoolean& secForward,
1008 TColStd_Array1OfReal& tabDst,
1009 TColStd_Array1OfReal& arrLen,
1010 TColStd_Array1OfReal& tabMinDist,
1011 const Standard_Integer indRef) const
1013 secForward.Init(Standard_True);
1016 tabMinDist.Init(Precision::Infinite());
1017 const Standard_Integer npt = 8; // Number of points for curve discretization
1018 TColgp_Array1OfPnt ptsRef(1, npt), ptsSec(1, npt);
1020 Standard_Integer i, j, lengSec = sequenceSec.Length();
1021 TColgp_SequenceOfPnt seqSec;
1023 Handle(Geom_Curve) c3dRef;
1024 Standard_Real firstRef=0., lastRef=0.;
1026 for (i = indRef; i <= lengSec; i++) {
1028 // reading of the edge (attention for the first one: reference)
1029 const TopoDS_Edge& sec = TopoDS::Edge(sequenceSec(i));
1031 TopLoc_Location loc;
1032 Standard_Real first, last;
1033 Handle(Geom_Curve) c3d = BRep_Tool::Curve(sec, loc, first, last);
1034 if (!loc.IsIdentity()) {
1035 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1036 c3d->Transform(loc.Transformation());
1040 c3dRef = c3d; firstRef = first; lastRef = last;
1043 Standard_Real dist = Precision::Infinite(), distFor = -1.0, distRev = -1.0;
1044 Standard_Real aMinDist = Precision::Infinite();
1046 Standard_Real T, deltaT = (last - first) / (npt - 1);
1047 Standard_Real aLenSec2 = 0.;
1049 Standard_Integer nbFound = 0;
1050 for (j = 1; j <= npt; j++) {
1052 // Uniform parameter on curve
1053 if (j == 1) T = first;
1054 else if (j == npt) T = last;
1055 else T = first + (j - 1) * deltaT;
1057 // Take point on curve
1058 gp_Pnt pt = c3d->Value(T);
1063 aLenSec2 += pt.SquareDistance(ptsRef(j-1));
1067 //protection to avoid merging with small sections
1069 aLenSec2 += pt.SquareDistance(ptsSec(j-1));
1070 // To evaluate mutual orientation and distance
1071 dist = pt.Distance(ptsRef(j));
1074 if (distFor < dist) distFor = dist;
1075 dist = pt.Distance(ptsRef(npt-j+1));
1079 if (distRev < dist) distRev = dist;
1081 // Check that point lays between vertices of reference curve
1082 const gp_Pnt &p11 = ptsRef(1);
1083 const gp_Pnt &p12 = ptsRef(npt);
1084 const gp_Vec aVec1(pt,p11);
1085 const gp_Vec aVec2(pt,p12);
1086 const gp_Vec aVecRef(p11,p12);
1087 if((aVecRef * aVec1) * (aVecRef * aVec2) < 0.)
1092 Standard_Real aLenSec = sqrt(aLenSec2);
1094 //if(aLenSec < myMinTolerance )
1096 arrLen.SetValue(i,aLenSec);
1097 // Record mutual orientation
1098 Standard_Boolean isForward = (distFor < distRev); //szv debug: <=
1099 secForward(i) = isForward;
1101 dist = (isForward? distFor : distRev);
1102 if(i == indRef || (dist < myTolerance && nbFound >= npt * 0.5) )
1105 tabMinDist(i) = aMinDist;
1109 nbFound = 0, aMinDist = Precision::Infinite(), dist = -1;
1110 TColgp_Array1OfPnt arrProj(1, npt);
1111 TColStd_Array1OfReal arrDist(1, npt), arrPara(1, npt);
1112 if( arrLen(indRef) >= arrLen(i))
1113 ProjectPointsOnCurve(ptsSec,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1115 ProjectPointsOnCurve(ptsRef,c3d,first,last,arrDist,arrPara,arrProj,Standard_False);
1116 for( j = 1; j <= npt; j++ )
1118 if(arrDist(j) < 0. || arrDist(j) > myTolerance)
1120 if(dist < arrDist(j))
1122 if( aMinDist > arrDist(j))
1123 aMinDist = arrDist(j);
1129 tabMinDist(i) = aMinDist;
1135 // Project distant points
1136 Standard_Integer nbFailed = seqSec.Length();
1137 if (!nbFailed) return;
1139 TColgp_Array1OfPnt arrPnt(1, nbFailed), arrProj(1, nbFailed);
1140 for (i = 1; i <= nbFailed; i++) arrPnt(i) = seqSec(i); seqSec.Clear();
1141 TColStd_Array1OfReal arrDist(1, nbFailed), arrPara(1, nbFailed);
1143 ProjectPointsOnCurve(arrPnt,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1145 // Process distant sections
1146 Standard_Integer idx1 = 1;
1147 for (i = indRef + 1; i <= lengSec; i++) {
1149 // Skip section if already evaluated
1150 if (tabDst(i) >= 0.0) continue;
1152 Standard_Real dist, distMax = -1.0, aMinDist = Precision::Infinite();
1154 Standard_Integer idx2 = (idx1 - 1)*npt;
1156 for (j = 1; j <= npt; j++) {
1158 dist = arrDist(idx2 + j);
1159 // If point is not projected - stop evaluation
1160 if (dist < 0.0) { distMax = -1.0; break; }
1161 if (distMax < dist) distMax = dist;
1162 if(aMinDist > dist) aMinDist = dist;
1165 // If section is close - record distance
1166 if (distMax >= 0.0) {
1167 if (secForward(i)) {
1168 dist = arrPnt(idx2+1).Distance(ptsRef(1));
1169 if (distMax < dist) distMax = dist;
1170 if(aMinDist > dist) aMinDist = dist;
1171 dist = arrPnt(idx2+npt).Distance(ptsRef(npt));
1172 if (distMax < dist) distMax = dist;
1173 if(aMinDist > dist) aMinDist = dist;
1176 dist = arrPnt(idx2+1).Distance(ptsRef(npt));
1177 if (distMax < dist) distMax = dist;
1178 if(aMinDist > dist) aMinDist = dist;
1179 dist = arrPnt(idx2+npt).Distance(ptsRef(1));
1180 if (distMax < dist) distMax = dist;
1181 if(aMinDist > dist) aMinDist = dist;
1184 if (distMax < myTolerance)
1186 tabDst(i) = distMax;
1187 tabMinDist(i) = aMinDist;
1191 idx1++; // To the next distant curve
1195 //=======================================================================
1196 //function : IsMergedClosed
1197 //purpose : internal use
1198 //=======================================================================
1200 Standard_Boolean BRepBuilderAPI_Sewing::IsMergedClosed(const TopoDS_Edge& Edge1,
1201 const TopoDS_Edge& Edge2,
1202 const TopoDS_Face& face) const
1204 // Check for closed surface
1205 TopLoc_Location loc;
1206 Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc);
1207 Standard_Boolean isUClosed = IsUClosedSurface(surf,Edge1,loc);
1208 Standard_Boolean isVClosed = IsVClosedSurface(surf,Edge1,loc);
1209 if (!isUClosed && !isVClosed) return Standard_False;
1210 // Check condition on closed surface
1212 Standard_Real first1,last1,first2,last2;
1213 Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(Edge1,first1,last1);
1214 Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(Edge2,first2,last2);
1215 if (C3d1.IsNull() || C3d2.IsNull()) return Standard_False;
1217 Standard_Real first2d1,last2d1,first2d2,last2d2;
1218 Handle(Geom2d_Curve) C2d1 = BRep_Tool::CurveOnSurface(Edge1,face,first2d1,last2d1);
1219 Handle(Geom2d_Curve) C2d2 = BRep_Tool::CurveOnSurface(Edge2,face,first2d2,last2d2);
1220 if (C2d1.IsNull() || C2d2.IsNull()) return Standard_False;
1222 gp_Pnt p1 = C3d1->Value(0.5*(first1 + last1));
1223 gp_Pnt p2 = C3d1->Value(0.5*(first2 + last2));
1224 Standard_Real dist = p1.Distance(p2);
1225 gp_Pnt2d p12d = C2d1->Value(0.5*(first2d1 + last2d1));
1226 gp_Pnt2d p22d = C2d1->Value(0.5*(first2d2 + last2d2));
1227 Standard_Real dist2d = p12d.Distance(p22d);
1228 GeomAdaptor_Surface Ads(BRep_Tool::Surface(face));
1229 Standard_Real distSurf = Max(Ads.UResolution(dist), Ads.VResolution(dist));
1230 return (dist2d*0.2 >= distSurf);
1232 Standard_Integer isULongC1, isULongC2, isVLongC1, isVLongC2;
1233 Standard_Real SUmin, SUmax, SVmin, SVmax;
1234 Standard_Real C1Umin, C1Vmin, C1Umax, C1Vmax;
1235 Standard_Real C2Umin, C2Vmin, C2Umax, C2Vmax;
1236 { //szv: Use brackets to destroy local variables
1238 Geom2dAdaptor_Curve aC2d1(C2d1), aC2d2(C2d2);
1239 BndLib_Add2dCurve::Add(aC2d1,first2d1,last2d1,Precision::PConfusion(),B1);
1240 BndLib_Add2dCurve::Add(aC2d2,first2d2,last2d2,Precision::PConfusion(),B2);
1241 B1.Get(C1Umin,C1Vmin,C1Umax,C1Vmax);
1242 B2.Get(C2Umin,C2Vmin,C2Umax,C2Vmax);
1243 Standard_Real du, dv;
1244 du = (C1Umax - C1Umin); dv = (C1Vmax - C1Vmin);
1245 isULongC1 = (dv <= du); isVLongC1 = (du <= dv);
1246 du = (C2Umax - C2Umin); dv = (C2Vmax - C2Vmin);
1247 isULongC2 = (dv <= du); isVLongC2 = (du <= dv);
1248 surf->Bounds(SUmin,SUmax,SVmin,SVmax);
1250 if (isUClosed && isVLongC1 && isVLongC2) {
1251 // Do not merge if not overlapped by V
1252 Standard_Real dist = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1254 Standard_Real distInner = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1255 Standard_Real distOuter = (SUmax - SUmin) - Max((C2Umax - C1Umin),(C1Umax - C2Umin));
1256 if (distOuter <= distInner) return Standard_True;
1259 if (isVClosed && isULongC1 && isULongC2) {
1260 // Do not merge if not overlapped by U
1261 Standard_Real dist = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1263 Standard_Real distInner = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1264 Standard_Real distOuter = (SVmax - SVmin) - Max((C2Vmax - C1Vmin),(C1Vmax - C2Vmin));
1265 if (distOuter <= distInner) return Standard_True;
1268 return Standard_False;
1271 //=======================================================================
1272 //function : AnalysisNearestEdges
1274 //=======================================================================
1276 void BRepBuilderAPI_Sewing::AnalysisNearestEdges(const TopTools_SequenceOfShape& sequenceSec,
1277 TColStd_SequenceOfInteger& seqIndCandidate,
1278 TColStd_SequenceOfInteger& seqOrientations,
1279 const Standard_Boolean evalDist)
1282 Standard_Integer workIndex = seqIndCandidate.First();
1283 TopoDS_Shape workedge = sequenceSec.Value(workIndex);
1284 TopoDS_Shape bnd = workedge;
1285 TopTools_ListOfShape workfaces;
1286 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1287 if (myBoundFaces.Contains(bnd))
1288 workfaces = myBoundFaces.FindFromKey(bnd);
1289 if(workfaces.IsEmpty()) return;
1290 TopTools_MapOfShape mapFaces;
1291 TopTools_ListIteratorOfListOfShape lIt;
1292 for (lIt.Initialize(workfaces); lIt.More(); lIt.Next())
1293 mapFaces.Add(lIt.Value());
1294 TColStd_SequenceOfInteger seqNotCandidate;
1295 TColStd_SequenceOfInteger seqNewForward;
1296 // Separates edges belonging the same face as work edge
1297 // for exception of edges belonging closed faces
1299 seqNotCandidate.Append(workIndex);
1300 for(Standard_Integer i = 1; i<= seqIndCandidate.Length(); ) {
1301 Standard_Integer index = seqIndCandidate.Value(i);
1302 Standard_Boolean isRemove = Standard_False;
1303 if(index == workIndex) {
1304 seqIndCandidate.Remove(i);
1305 seqOrientations.Remove(i);
1306 isRemove = Standard_True;
1309 TopoDS_Shape bnd2 = sequenceSec.Value(index);
1310 if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
1312 if(myBoundFaces.Contains(bnd2)) {
1313 const TopTools_ListOfShape& listfaces = myBoundFaces.FindFromKey(bnd2);
1314 Standard_Boolean isMerged = Standard_True;
1315 for (lIt.Initialize(listfaces); lIt.More() && isMerged; lIt.Next()) {
1316 if(mapFaces.Contains(lIt.Value())) {
1317 TopLoc_Location loc;
1318 Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(lIt.Value()),loc);
1319 isMerged = ((IsUClosedSurface(surf,bnd2,loc) || IsVClosedSurface(surf,bnd2,loc)) &&
1320 IsMergedClosed(TopoDS::Edge(sequenceSec.Value(index)),TopoDS::Edge(workedge),TopoDS::Face(lIt.Value())));
1324 seqNotCandidate.Append(index);
1325 seqIndCandidate.Remove(i);
1326 seqOrientations.Remove(i);
1327 isRemove = Standard_True;
1331 seqIndCandidate.Remove(i);
1332 seqOrientations.Remove(i);
1333 isRemove = Standard_True;
1338 if(seqIndCandidate.Length() == 0 || seqNotCandidate.Length() == 1) return;
1339 if(!evalDist) return;
1340 TColStd_Array2OfReal TotTabDist(1,seqNotCandidate.Length(),1,seqIndCandidate.Length());
1341 TColStd_MapOfInteger MapIndex;
1342 TColStd_SequenceOfInteger seqForward;
1344 // Definition and removing edges wich are not candidate for work edge
1345 // ( they have other nearest edges belonging to the work face)
1346 for(Standard_Integer k = 1; k<= seqNotCandidate.Length(); k++) {
1347 Standard_Integer index1 = seqNotCandidate.Value(k);
1348 TopoDS_Shape edge = sequenceSec.Value(index1);
1349 TopTools_SequenceOfShape tmpSeq;
1350 tmpSeq.Append(edge);
1351 for(Standard_Integer kk = 1; kk <= seqIndCandidate.Length();kk++)
1352 tmpSeq.Append(sequenceSec.Value(seqIndCandidate.Value(kk)));
1354 Standard_Integer lengSec = tmpSeq.Length();
1355 TColStd_Array1OfBoolean tabForward(1,lengSec);
1356 TColStd_Array1OfReal tabDist(1,lengSec);
1357 TColStd_Array1OfReal arrLen(1,lengSec);
1358 TColStd_Array1OfReal tabMinDist(1,lengSec);
1359 for (Standard_Integer i1 = 1 ; i1 <= lengSec; i1++)
1362 EvaluateDistances(tmpSeq,tabForward, tabDist,arrLen,tabMinDist,1 );
1364 for(Standard_Integer n = 1; n < lengSec; n++) {
1365 if(tabDist(n+1) == -1 || tabDist(n+1) > myTolerance) {
1369 TotTabDist(k,n) = tabDist(n+1 );
1370 seqForward.Append(tabForward(n+1) ? 1:0);
1374 for(Standard_Integer n = 1; n < lengSec; n++) {
1375 if(tabDist(n) == -1 || tabDist(n) > myTolerance) continue;
1376 if(tabDist(n+1) < TotTabDist(1,n)) {
1384 Standard_Integer i2 = seqIndCandidate.Length();
1385 for( ; i2 >=1 ; i2--)
1387 if(MapIndex.Contains(i2))
1389 seqIndCandidate.Remove(i2);
1390 seqOrientations.Remove(i2);
1394 //for(TColStd_MapIteratorOfMapOfInteger IMap(MapIndex); IMap.More(); IMap.Next()) {
1395 // seqIndCandidate.Remove(IMap.Key());
1396 // seqOrientations.Remove(IMap.Key());
1400 //=======================================================================
1401 //function : FindCandidates
1402 //purpose : internal use
1403 //=======================================================================
1405 Standard_Boolean BRepBuilderAPI_Sewing::FindCandidates(TopTools_SequenceOfShape& seqSections,
1406 TColStd_IndexedMapOfInteger& mapReference,
1407 TColStd_SequenceOfInteger& seqCandidates,
1408 TColStd_SequenceOfInteger& seqOrientations)
1410 Standard_Integer i, nbSections = seqSections.Length();
1412 return Standard_False;
1413 // Retrieve last reference index
1414 Standard_Integer indReference = mapReference(mapReference.Extent());
1415 Standard_Integer nbCandidates = 0;
1416 TopTools_MapOfShape Faces1;
1417 //if (nbSections > 1) {
1419 TopoDS_Edge Edge1 = TopoDS::Edge(seqSections(indReference));
1421 // Retrieve faces for reference section
1423 { //szv: Use brackets to destroy local variables
1424 TopoDS_Shape bnd = Edge1;
1425 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1426 if (myBoundFaces.Contains(bnd)) {
1427 TopTools_ListIteratorOfListOfShape itf1(myBoundFaces.FindFromKey(bnd));
1428 for (; itf1.More(); itf1.Next()) Faces1.Add(itf1.Value());
1432 // Check merging conditions for candidates and remove unsatisfactory
1433 TopTools_SequenceOfShape seqSectionsNew;
1434 TColStd_SequenceOfInteger seqCandidatesNew;
1435 for (i = 1; i <= nbSections; i++) {
1436 if (i == indReference) {
1437 seqSectionsNew.Prepend(Edge1);
1438 seqCandidatesNew.Prepend(i);
1441 const TopoDS_Edge& Edge2 = TopoDS::Edge(seqSections(i));
1443 seqSectionsNew.Append(Edge2);
1444 seqCandidatesNew.Append(i);
1445 /*TopoDS_Shape bnd = Edge2;
1446 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1448 if (myBoundFaces.Contains(bnd)) {
1449 Standard_Boolean isOK = Standard_True;
1450 TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1451 for (; itf2.More() && isOK; itf2.Next()) {
1452 const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1453 // Check whether condition is satisfied
1454 isOK = !Faces1.Contains(Face2);
1455 if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1458 seqSectionsNew.Append(Edge2);
1459 seqCandidatesNew.Append(i);
1465 Standard_Integer nbSectionsNew = seqSectionsNew.Length();
1466 if (nbSectionsNew > 1) {
1468 // Evaluate distances between reference and other sections
1469 TColStd_Array1OfBoolean arrForward(1,nbSectionsNew);
1470 TColStd_Array1OfReal arrDistance(1,nbSectionsNew);
1471 TColStd_Array1OfReal arrLen(1,nbSectionsNew);
1472 TColStd_Array1OfReal arrMinDist(1,nbSectionsNew);
1473 EvaluateDistances(seqSectionsNew,arrForward,arrDistance,arrLen,arrMinDist,1);
1475 // Fill sequence of candidate indices sorted by distance
1476 for (i = 2; i <= nbSectionsNew; i++) {
1477 if (arrDistance(i) >= 0.0 && arrLen(i) > myMinTolerance) {
1478 // Reference section is connected to section #i
1479 Standard_Boolean isInserted = Standard_False;
1480 Standard_Integer j, ori = (arrForward(i)? 1 : 0);
1481 for (j = 1; (j <= seqCandidates.Length()) && !isInserted; j++) {
1482 Standard_Integer aInd = seqCandidates.Value(j);//debug
1483 Standard_Real aDelta = arrDistance(i) - arrDistance(seqCandidates.Value(j));
1484 //if (arrDistance(i) <= arrDistance(seqCandidates.Value(j))) {
1485 if( aDelta < Precision::Confusion()) {
1487 if(fabs(aDelta) > RealSmall() ||
1488 arrMinDist(i) < arrMinDist(seqCandidates.Value(j)))
1490 seqCandidates.InsertBefore(j,i);
1491 seqOrientations.InsertBefore(j,ori);
1492 isInserted = Standard_True;
1497 seqCandidates.Append(i);
1498 seqOrientations.Append(ori);
1503 // Replace candidate indices
1504 nbCandidates = seqCandidates.Length();
1505 for (i = 1; i <= nbCandidates; i++)
1506 seqCandidates(i) = seqCandidatesNew(seqCandidates(i));
1510 if (!nbCandidates) return Standard_False; // Section has no candidates to merge
1512 if (myNonmanifold && nbCandidates >1) {
1513 TColStd_SequenceOfInteger seqNewCandidates;
1514 TColStd_SequenceOfInteger seqOrientationsNew;
1515 seqCandidates.Prepend(1);
1516 seqOrientations.Prepend(1);
1517 for(Standard_Integer k = 1; k <= seqSections.Length() && seqCandidates.Length() > 1 ; k++) {
1518 AnalysisNearestEdges(seqSections,seqCandidates,seqOrientations,(k==1));
1519 if(k == 1 && !seqCandidates.Length()) return Standard_False;
1520 if(seqCandidates.Length()) {
1521 seqNewCandidates.Append(seqCandidates.First());
1522 seqOrientationsNew.Append(seqOrientations.First());
1525 seqCandidates.Prepend(seqNewCandidates);
1526 seqOrientations.Prepend(seqOrientationsNew);
1527 return Standard_True;
1531 // For manifold case leave only one candidate from equidistant candidates
1532 /*Standard_Integer minIndex = seqCandidateIndex.First();
1533 Standard_Real minDistance = arrDistance(minIndex);
1535 // Find equidistant candidates
1536 TColStd_SequenceOfInteger seqEqDistantIndex; seqEqDistantIndex.Append(1);
1537 for (i = 2; i <= nbCandidates; i++) {
1538 Standard_Integer index = seqCandidateIndex(i);
1539 if (Abs(minDistance - arrDistance(index)) <= Precision::Confusion())
1540 seqEqDistantIndex.Append(index);
1543 Standard_Integer eqLen = seqEqDistantIndex.Length();
1546 // Fill map of faces which equidistant sections belong to
1547 TopTools_MapOfShape mapFace;
1548 for (i = 1; i <= eqLen; i++) {
1549 Standard_Integer index = seqEqDistantIndex.Value(i);
1550 if (isCandidate(index)) {
1551 mapFace.Add(arrFace(index));
1555 // Non Manifold case
1556 // Edges are merged by pair among a face continuity C1 criterion
1557 if (mapFace.Extent() == eqLen) {
1563 Standard_Integer indMin = -1;// To check if the edge can be merged.
1564 // Computation of distances between the edges.
1565 TopTools_SequenceOfShape seqSh;
1566 Standard_Integer nbInd = EqDistSeq.Length();
1567 TColStd_Array1OfBoolean tmptabForward(1,nbInd);
1568 seqSh.Append(sequenceSec.Value(1));
1569 for (j = 2; j <= EqDistSeq.Length(); j++) {
1570 Standard_Integer index = EqDistSeq.Value(j);
1571 tmptabForward(j) = tabForward(index);
1572 seqSh.Append(sequenceSec.Value(index));
1575 EvaluateAngulars(seqSh, tmptabForward, tabDist,1);
1577 for(j=2; j <= seqSh.Length(); j++) {
1578 if (tabDist(j) > -1.) { // if edge(j) is connected to edge(i)
1579 if (min > tabDist(j)) {
1586 // Construct minDist, tabMinInd , tabMinForward(i) = tabForward(j);
1588 seqSh.Remove(indMin);
1589 for(j =2; j <= tmpSeq.Length(); ) {
1590 TopoDS_Shape sh = tmpSeq.Value(j);
1591 Standard_Boolean isRem = Standard_False;
1592 for(Standard_Integer k = 1; k<= seqSh.Length();k++) {
1593 if(seqSh.Value(k) == sh) {
1594 isRem = Standard_True;
1600 tabMinForward.Remove(j); // = -1;
1608 // Find the best approved candidate
1609 while (nbCandidates) {
1610 // Retrieve first candidate
1611 Standard_Integer indCandidate = seqCandidates.First();
1612 // Candidate is approved if it is in the map
1613 if (mapReference.Contains(indCandidate)) break;
1614 // Find candidates for candidate #indCandidate
1615 mapReference.Add(indCandidate); // Push candidate in the map
1616 TColStd_SequenceOfInteger seqCandidates1, seqOrientations1;
1617 Standard_Boolean isFound =
1618 FindCandidates(seqSections,mapReference,seqCandidates1,seqOrientations1);
1619 mapReference.RemoveLast(); // Pop candidate from the map
1620 if (isFound) isFound = (seqCandidates1.Length() > 0);
1622 Standard_Integer indCandidate1 = seqCandidates1.First();
1623 // If indReference is the best candidate for indCandidate
1624 // then indCandidate is the best candidate for indReference
1625 if (indCandidate1 == indReference) break;
1626 // If some other reference in the map is the best candidate for indCandidate
1627 // then assume that reference is the best candidate for indReference
1628 if (mapReference.Contains(indCandidate1)) {
1629 seqCandidates.Prepend(indCandidate1);
1633 isFound = Standard_False;
1636 // Remove candidate #1
1637 seqCandidates.Remove(1);
1638 seqOrientations.Remove(1);
1644 if(nbCandidates > 0)
1646 Standard_Integer anInd = seqCandidates.Value(1);
1647 TopoDS_Edge Edge2 = TopoDS::Edge(seqSections(anInd));
1648 TopoDS_Shape bnd = Edge2;
1649 if (mySectionBound.IsBound(bnd))
1650 bnd = mySectionBound(bnd);
1652 if (myBoundFaces.Contains(bnd)) {
1653 Standard_Boolean isOK = Standard_True;
1654 TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1655 for (; itf2.More() && isOK; itf2.Next()) {
1656 const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1657 // Check whether condition is satisfied
1658 isOK = !Faces1.Contains(Face2);
1659 if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1662 return Standard_False;
1665 return (nbCandidates > 0);
1668 //=======================================================================
1669 //function : Constructor
1671 //=======================================================================
1673 BRepBuilderAPI_Sewing::BRepBuilderAPI_Sewing(const Standard_Real tolerance,
1674 const Standard_Boolean optionSewing,
1675 const Standard_Boolean optionAnalysis,
1676 const Standard_Boolean optionCutting,
1677 const Standard_Boolean optionNonmanifold)
1679 myReShape = new BRepTools_ReShape;
1680 Init(tolerance, optionSewing, optionAnalysis, optionCutting, optionNonmanifold);
1683 //=======================================================================
1685 //purpose : Initialise Talerance, and options sewing, faceAnalysis and cutting
1686 //=======================================================================
1688 void BRepBuilderAPI_Sewing::Init(const Standard_Real tolerance,
1689 const Standard_Boolean optionSewing,
1690 const Standard_Boolean optionAnalysis,
1691 const Standard_Boolean optionCutting,
1692 const Standard_Boolean optionNonmanifold)
1694 // Set tolerance and Perform options
1695 myTolerance = tolerance;
1696 mySewing = optionSewing;
1697 myAnalysis = optionAnalysis;
1698 myCutting = optionCutting;
1699 myNonmanifold = optionNonmanifold;
1700 // Set min and max tolerances
1701 myMinTolerance = tolerance*1e-4; //szv: proposal
1702 if (myMinTolerance < Precision::Confusion()) myMinTolerance = Precision::Confusion();
1703 myMaxTolerance = Precision::Infinite();
1705 myFaceMode = Standard_True;
1706 myFloatingEdgesMode = Standard_False;
1707 //myCuttingFloatingEdgesMode = Standard_False; //gka
1708 mySameParameterMode = Standard_True;
1709 myLocalToleranceMode = Standard_False;
1710 mySewedShape.Nullify();
1712 Load(TopoDS_Shape());
1715 //=======================================================================
1717 //purpose : Loads the context shape
1718 //=======================================================================
1720 void BRepBuilderAPI_Sewing::Load(const TopoDS_Shape& theShape)
1723 if (theShape.IsNull()) myShape.Nullify();
1724 else myShape = myReShape->Apply(theShape);
1725 mySewedShape.Nullify();
1726 // Nullify flags and counters
1727 myNbShapes = myNbEdges = myNbVertices = 0;
1729 myOldShapes.Clear();
1730 //myOldFaces.Clear();
1731 myDegenerated.Clear();
1732 myFreeEdges.Clear();
1733 myMultipleEdges.Clear();
1734 myContigousEdges.Clear();
1735 myContigSecBound.Clear();
1736 myBoundFaces.Clear();
1737 myBoundSections.Clear();
1738 myVertexNode.Clear();
1739 myVertexNodeFree.Clear();
1740 myNodeSections.Clear();
1741 myCuttingNode.Clear();
1742 mySectionBound.Clear();
1743 myLittleFace.Clear();
1746 //=======================================================================
1749 //=======================================================================
1751 void BRepBuilderAPI_Sewing::Add(const TopoDS_Shape& aShape)
1753 if (aShape.IsNull()) return;
1754 TopoDS_Shape oShape = myReShape->Apply(aShape);
1755 myOldShapes.Add(aShape,oShape);
1756 myNbShapes = myOldShapes.Extent();
1759 //=======================================================================
1760 //function : Perform
1762 //=======================================================================
1765 #include <OSD_Timer.hxx>
1768 void BRepBuilderAPI_Sewing::Perform(const Handle(Message_ProgressIndicator)& thePI)
1770 const Standard_Integer aNumberOfStages = myAnalysis + myCutting + mySewing + 2;
1771 Message_ProgressSentry aPS (thePI, "Sewing", 0, aNumberOfStages, 1);
1773 Standard_Real t_total = 0., t_analysis = 0., t_assembling = 0., t_cutting = 0., t_merging = 0.;
1774 OSD_Chronometer chr_total, chr_local;
1783 cout << "Begin face analysis..." << endl;
1787 FaceAnalysis (thePI);
1793 chr_local.Show(t_analysis);
1794 cout << "Face analysis finished after " << t_analysis << " s" << endl;
1798 if (myNbShapes || !myShape.IsNull())
1801 FindFreeBoundaries();
1803 if (myBoundFaces.Extent())
1807 cout << "Begin vertices assembling..." << endl;
1811 VerticesAssembling (thePI);
1817 chr_local.Show(t_assembling);
1818 cout << "Vertices assembling finished after " << t_assembling << " s" << endl;
1823 cout << "Begin cutting..." << endl;
1833 chr_local.Show(t_cutting);
1834 cout << "Cutting finished after " << t_cutting << " s" << endl;
1838 cout << "Begin merging..." << endl;
1842 Merging (Standard_True, thePI);
1848 chr_local.Show(t_merging);
1849 cout << "Merging finished after " << t_merging << " s" << endl;
1854 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1856 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1857 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1866 cout << "Creating sewed shape..." << endl;
1868 // examine the multiple edges if any and process sameparameter for edges if necessary
1869 EdgeProcessing (thePI);
1875 mySewedShape.Nullify();
1878 if (mySameParameterMode && myFaceMode)
1879 SameParameterShape();
1882 mySewedShape.Nullify();
1886 cout << "Sewed shape created" << endl;
1890 // create edge informations for output
1891 CreateOutputInformations();
1894 mySewedShape.Nullify();
1900 chr_total.Show(t_total);
1901 cout << "Sewing finished!" << endl;
1902 cout << " analysis time : " << t_analysis << " s" << endl;
1903 cout << " assembling time : " << t_assembling << " s" << endl;
1904 cout << " cutting time : " << t_cutting << " s" << endl;
1905 cout << " merging time : " << t_merging << " s" << endl;
1906 cout << "Total time : " << t_total << " s" << endl;
1910 //=======================================================================
1911 //function : SewedShape
1912 //purpose : give the sewed shape
1913 // if a null shape, reasons:
1914 // -- no useable input shapes : all input shapes are degenerated
1915 // -- has multiple edges
1916 //=======================================================================
1918 const TopoDS_Shape& BRepBuilderAPI_Sewing::SewedShape() const
1920 return mySewedShape;
1923 //=======================================================================
1924 //function : NbFreeEdges
1926 //=======================================================================
1928 Standard_Integer BRepBuilderAPI_Sewing::NbFreeEdges() const
1930 return myFreeEdges.Extent();
1933 //=======================================================================
1934 //function : FreeEdge
1936 //=======================================================================
1938 const TopoDS_Edge& BRepBuilderAPI_Sewing::FreeEdge(const Standard_Integer index) const
1940 Standard_OutOfRange_Raise_if(index < 0 || index > NbFreeEdges(), "BRepBuilderAPI_Sewing::FreeEdge");
1941 return TopoDS::Edge(myFreeEdges(index));
1944 //=======================================================================
1945 //function : NbMultipleEdges
1947 //=======================================================================
1949 Standard_Integer BRepBuilderAPI_Sewing::NbMultipleEdges() const
1951 return myMultipleEdges.Extent();
1954 //=======================================================================
1955 //function : MultipleEdge
1957 //=======================================================================
1959 const TopoDS_Edge& BRepBuilderAPI_Sewing::MultipleEdge(const Standard_Integer index) const
1961 Standard_OutOfRange_Raise_if(index < 0 || index > NbMultipleEdges(), "BRepBuilderAPI_Sewing::MultipleEdge");
1962 return TopoDS::Edge(myMultipleEdges(index));
1965 //=======================================================================
1966 //function : NbContigousEdges
1968 //=======================================================================
1970 Standard_Integer BRepBuilderAPI_Sewing::NbContigousEdges() const
1972 return myContigousEdges.Extent();
1975 //=======================================================================
1976 //function : ContigousEdge
1978 //=======================================================================
1980 const TopoDS_Edge& BRepBuilderAPI_Sewing::ContigousEdge(const Standard_Integer index) const
1982 Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdge");
1983 return TopoDS::Edge(myContigousEdges.FindKey(index));
1986 //=======================================================================
1987 //function : ContigousEdgeCouple
1989 //=======================================================================
1991 const TopTools_ListOfShape& BRepBuilderAPI_Sewing::ContigousEdgeCouple(const Standard_Integer index) const
1993 Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdgeCouple");
1994 return myContigousEdges(index);
1997 //=======================================================================
1998 //function : IsSectionBound
2000 //=======================================================================
2002 Standard_Boolean BRepBuilderAPI_Sewing::IsSectionBound(const TopoDS_Edge& section) const
2004 if(myContigSecBound.IsBound(section)) {
2005 return Standard_True;
2008 return Standard_False;
2012 //=======================================================================
2013 //function : SectionToBoundary
2015 //=======================================================================
2017 const TopoDS_Edge& BRepBuilderAPI_Sewing::SectionToBoundary(const TopoDS_Edge& section) const
2019 Standard_NoSuchObject_Raise_if(!IsSectionBound(section), "BRepBuilderAPI_Sewing::SectionToBoundary");
2020 return TopoDS::Edge(myContigSecBound(section));
2022 //=======================================================================
2023 //function : NbDeletedFaces
2025 //=======================================================================
2026 Standard_Integer BRepBuilderAPI_Sewing::NbDeletedFaces() const
2028 return myLittleFace.Extent();
2031 //=======================================================================
2032 //function : DeletedFace
2034 //=======================================================================
2035 const TopoDS_Face& BRepBuilderAPI_Sewing::DeletedFace(const Standard_Integer index) const
2037 Standard_OutOfRange_Raise_if(index < 0 || index > NbDeletedFaces(), "BRepBuilderAPI_Sewing::DeletedFace");
2038 return TopoDS::Face(myLittleFace(index));
2041 //=======================================================================
2042 //function : NbDegeneratedShapes
2044 //=======================================================================
2046 Standard_Integer BRepBuilderAPI_Sewing::NbDegeneratedShapes() const
2048 return myDegenerated.Extent();
2051 //=======================================================================
2052 //function : DegeneratedShape
2054 //=======================================================================
2056 const TopoDS_Shape& BRepBuilderAPI_Sewing::DegeneratedShape(const Standard_Integer index) const
2058 Standard_OutOfRange_Raise_if(index < 0 || index > NbDegeneratedShapes(), "BRepBuilderAPI_Sewing::DegereratedShape");
2059 return myDegenerated(index);
2062 //=======================================================================
2063 //function : IsDegenerated
2065 //=======================================================================
2067 Standard_Boolean BRepBuilderAPI_Sewing::IsDegenerated(const TopoDS_Shape& aShape) const
2069 TopoDS_Shape NewShape = myReShape->Apply(aShape);
2071 if (aShape.ShapeType() == TopAbs_FACE)
2072 return NewShape.IsNull();
2073 if (NewShape.IsNull()) return Standard_False;
2075 if (NewShape.ShapeType() == TopAbs_EDGE)
2076 return BRep_Tool::Degenerated(TopoDS::Edge(NewShape));
2078 if (NewShape.ShapeType() == TopAbs_WIRE) {
2079 Standard_Boolean isDegenerated = Standard_True;
2080 for (TopoDS_Iterator aIt(NewShape); aIt.More() && isDegenerated; aIt.Next())
2081 isDegenerated = BRep_Tool::Degenerated(TopoDS::Edge(aIt.Value()));
2082 return isDegenerated;
2084 return Standard_False;
2087 //=======================================================================
2088 //function : IsModified
2090 //=======================================================================
2092 Standard_Boolean BRepBuilderAPI_Sewing::IsModified(const TopoDS_Shape& aShape) const
2094 TopoDS_Shape NewShape = aShape;
2095 if (myOldShapes.Contains(aShape))
2096 NewShape = myOldShapes.FindFromKey(aShape);
2097 if(!NewShape.IsSame(aShape)) return Standard_True;
2098 return Standard_False;
2101 //=======================================================================
2102 //function : Modified
2104 //=======================================================================
2106 const TopoDS_Shape& BRepBuilderAPI_Sewing::Modified(const TopoDS_Shape& aShape) const
2108 if (myOldShapes.Contains(aShape)) return myOldShapes.FindFromKey(aShape);
2109 //if (myOldFaces.Contains(aShape)) return myOldFaces.FindFromKey(aShape);
2113 //=======================================================================
2114 //function : IsModifiedSubShape
2116 //=======================================================================
2118 Standard_Boolean BRepBuilderAPI_Sewing::IsModifiedSubShape(const TopoDS_Shape& aShape) const
2120 TopoDS_Shape NewShape = myReShape->Apply(aShape);
2121 if(!NewShape.IsSame(aShape)) return Standard_True;
2122 return Standard_False;
2125 //=======================================================================
2126 //function : ModifiedSubShape
2128 //=======================================================================
2130 TopoDS_Shape BRepBuilderAPI_Sewing::ModifiedSubShape(const TopoDS_Shape& aShape) const
2132 return myReShape->Apply(aShape);
2135 //=======================================================================
2138 //=======================================================================
2140 void BRepBuilderAPI_Sewing::Dump() const
2142 Standard_Integer i, NbBounds = myBoundFaces.Extent(), NbSections = 0;
2143 TopTools_MapOfShape mapVertices, mapEdges;
2144 for (i = 1; i <= NbBounds; i++) {
2145 TopoDS_Shape bound = myBoundFaces.FindKey(i);
2146 if (myBoundSections.IsBound(bound)) NbSections += myBoundSections(bound).Extent();
2148 TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
2149 for (; aExp.More(); aExp.Next()) {
2150 TopoDS_Edge E = TopoDS::Edge(aExp.Current());
2152 TopoDS_Vertex V1, V2;
2153 TopExp::Vertices(E,V1,V2);
2154 mapVertices.Add(V1);
2155 mapVertices.Add(V2);
2158 cout << " " << endl;
2159 cout << " Informations " << endl;
2160 cout << " ===========================================================" << endl;
2161 cout << " " << endl;
2162 cout << " Number of input shapes : " << myOldShapes.Extent() << endl;
2163 cout << " Number of actual shapes : " << myNbShapes << endl;
2164 cout << " Number of Bounds : " << NbBounds << endl;
2165 cout << " Number of Sections : " << NbSections << endl;
2166 cout << " Number of Edges : " << mapEdges.Extent() << endl;
2167 cout << " Number of Vertices : " << myNbVertices << endl;
2168 cout << " Number of Nodes : " << mapVertices.Extent() << endl;
2169 cout << " Number of Free Edges : " << myFreeEdges.Extent() << endl;
2170 cout << " Number of Contigous Edges : " << myContigousEdges.Extent() << endl;
2171 cout << " Number of Multiple Edges : " << myMultipleEdges.Extent() << endl;
2172 cout << " Number of Degenerated Edges : " << myDegenerated.Extent() << endl;
2173 cout << " ===========================================================" << endl;
2174 cout << " " << endl;
2177 //=======================================================================
2178 //function : FaceAnalysis
2186 //=======================================================================
2188 void BRepBuilderAPI_Sewing::FaceAnalysis(const Handle(Message_ProgressIndicator)& thePI)
2190 if (!myShape.IsNull() && myOldShapes.IsEmpty()) {
2196 TopTools_MapOfShape SmallEdges;
2197 TopTools_DataMapOfShapeListOfShape GluedVertices;
2198 Standard_Integer i = 1;
2199 Message_ProgressSentry aPS (thePI, "Shape analysis", 0, myOldShapes.Extent(), 1);
2200 for (i = 1; i <= myOldShapes.Extent() && aPS.More(); i++, aPS.Next()) {
2201 for (TopExp_Explorer fexp(myOldShapes(i),TopAbs_FACE); fexp.More(); fexp.Next()) {
2203 // Retrieve current face
2204 TopoDS_Shape aTmpShape = fexp.Current(); //for porting
2205 TopoDS_Face face = TopoDS::Face(aTmpShape);
2206 Standard_Integer nbEdges = 0, nbSmall = 0;
2208 // Build replacing face
2209 aTmpShape = face.EmptyCopied().Oriented(TopAbs_FORWARD); //for porting
2210 TopoDS_Face nface = TopoDS::Face(aTmpShape);
2211 Standard_Boolean isFaceChanged = Standard_False;
2213 TopoDS_Iterator witer(face.Oriented(TopAbs_FORWARD));
2214 for (; witer.More(); witer.Next()) {
2216 // Retrieve current wire
2217 aTmpShape = witer.Value(); //for porting
2218 if( aTmpShape.ShapeType() != TopAbs_WIRE) continue;
2219 TopoDS_Wire wire = TopoDS::Wire(aTmpShape);
2221 // Build replacing wire
2222 aTmpShape = wire.EmptyCopied().Oriented(TopAbs_FORWARD);
2223 TopoDS_Wire nwire = TopoDS::Wire(aTmpShape);
2224 Standard_Boolean isWireChanged = Standard_False;
2226 TopoDS_Iterator eiter(wire.Oriented(TopAbs_FORWARD));
2227 for (; eiter.More(); eiter.Next()) {
2229 // Retrieve current edge
2230 aTmpShape = eiter.Value(); //for porting
2231 TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
2234 // Process degenerated edge
2235 if (BRep_Tool::Degenerated(edge)) {
2236 B.Add(nwire,edge); // Old edge kept
2237 myDegenerated.Add(edge);
2242 Standard_Boolean isSmall = SmallEdges.Contains(edge);
2245 // Check for small edge
2246 Standard_Real first, last;
2247 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,first,last);
2250 cout << "Warning: Possibly small edge can be sewed: No 3D curve" << endl;
2254 // Evaluate curve compactness
2255 const Standard_Integer npt = 5;
2256 gp_Pnt cp((c3d->Value(first).XYZ()+c3d->Value(last).XYZ())*0.5);
2257 Standard_Real dist, maxdist = 0.0;
2258 Standard_Real delta = (last - first)/(npt - 1);
2259 for (Standard_Integer idx = 0; idx < npt; idx++) {
2260 dist = cp.Distance(c3d->Value(first + idx*delta));
2261 if (maxdist < dist) maxdist = dist;
2263 isSmall = (2.*maxdist <= MinTolerance());
2265 GeomAdaptor_Curve cAdapt(c3d);
2266 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt,first,last);
2267 isSmall = (length <= MinTolerance());
2269 catch (Standard_Failure) {
2271 cout << "Warning: Possibly small edge can be sewed: ";
2272 Standard_Failure::Caught()->Print(cout); cout << endl;
2279 // Store small edge in the map
2280 SmallEdges.Add(edge);
2282 TopoDS_Vertex v1, v2;
2283 TopExp::Vertices(edge,v1,v2);
2284 TopoDS_Shape nv1 = myReShape->Apply(v1), nv2 = myReShape->Apply(v2);
2286 // Store glued vertices
2287 if (!nv1.IsSame(v1)) {
2288 TopTools_ListOfShape& vlist1 = GluedVertices(nv1);
2289 // First vertex was already glued
2290 if (!nv2.IsSame(v2)) {
2291 // Merge lists of glued vertices
2292 if (!nv1.IsSame(nv2)) {
2293 TopTools_ListIteratorOfListOfShape liter(GluedVertices(nv2));
2294 for (; liter.More(); liter.Next()) {
2295 TopoDS_Shape v = liter.Value();
2296 myReShape->Replace(v,nv1.Oriented(v.Orientation()));
2299 GluedVertices.UnBind(nv2);
2303 // Add second vertex to the existing list
2305 myReShape->Replace(v2,nv1.Oriented(v2.Orientation()));
2308 else if (!nv2.IsSame(v2)) {
2309 // Add first vertex to the existing list
2310 GluedVertices(nv2).Append(v1);
2311 myReShape->Replace(v1,nv2.Oriented(v1.Orientation()));
2313 else if (!v1.IsSame(v2)) {
2314 // Record new glued vertices
2317 TopTools_ListOfShape vlist;
2320 GluedVertices.Bind(nv,vlist);
2321 myReShape->Replace(v1,nv.Oriented(v1.Orientation()));
2322 myReShape->Replace(v2,nv.Oriented(v2.Orientation()));
2327 // Replace small edge
2330 cout << "Warning: Small edge made degenerated by FaceAnalysis" << endl;
2333 // Create new degenerated edge
2334 aTmpShape = edge.Oriented(TopAbs_FORWARD);
2335 TopoDS_Edge fedge = TopoDS::Edge(aTmpShape);
2336 Standard_Real pfirst, plast;
2337 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(fedge,face,pfirst,plast);
2338 if (!c2d.IsNull()) {
2341 B.UpdateEdge(nedge,c2d,face,Precision::Confusion());
2342 B.Range(nedge,pfirst,plast);
2343 B.Degenerated(nedge,Standard_True);
2344 TopoDS_Vertex v1, v2;
2345 TopExp::Vertices(fedge,v1,v2);
2346 B.Add(nedge,myReShape->Apply(v1).Oriented(v1.Orientation()));
2347 B.Add(nedge,myReShape->Apply(v2).Oriented(v2.Orientation()));
2348 B.Add(nwire,nedge.Oriented(edge.Orientation()));
2349 myDegenerated.Add(nedge);
2351 isWireChanged = Standard_True;
2353 else B.Add(nwire,edge); // Old edge kept
2356 // Record wire in the new face
2357 if (isWireChanged) {
2358 B.Add(nface,nwire.Oriented(wire.Orientation()));
2359 isFaceChanged = Standard_True;
2361 else B.Add(nface,wire);
2364 // Remove small face
2365 if (nbSmall == nbEdges) {
2367 cout << "Warning: Small face removed by FaceAnalysis" << endl;
2369 myLittleFace.Add(face);
2370 myReShape->Remove(face);
2372 else if (isFaceChanged) {
2374 myReShape->Replace(face,nface.Oriented(face.Orientation()));
2379 // Update glued vertices
2380 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape miter(GluedVertices);
2381 for (; miter.More(); miter.Next()) {
2382 TopoDS_Vertex vnew = TopoDS::Vertex(miter.Key());
2383 gp_XYZ coord(0.,0.,0.);
2384 Standard_Integer nbPoints = 0;
2385 const TopTools_ListOfShape& vlist = miter.Value();
2386 TopTools_ListIteratorOfListOfShape liter1(vlist);
2387 for (; liter1.More(); liter1.Next()) {
2388 coord += BRep_Tool::Pnt(TopoDS::Vertex(liter1.Value())).XYZ();
2392 gp_Pnt vp(coord / nbPoints);
2393 Standard_Real tol = 0.0, mtol = 0.0;
2394 TopTools_ListIteratorOfListOfShape liter2(vlist);
2395 for (; liter2.More(); liter2.Next()) {
2396 Standard_Real vtol = BRep_Tool::Tolerance(TopoDS::Vertex(liter2.Value()));
2397 if (mtol < vtol) mtol = vtol;
2398 vtol = vp.Distance(BRep_Tool::Pnt(TopoDS::Vertex(liter2.Value())));
2399 if (tol < vtol) tol = vtol;
2401 B.UpdateVertex(vnew,vp,tol+mtol);
2405 // Update input shapes
2406 for (i = 1; i <= myOldShapes.Extent(); i++)
2407 myOldShapes(i) = myReShape->Apply(myOldShapes(i));
2410 //=======================================================================
2411 //function : FindFreeBoundaries
2412 //purpose : Constructs :
2413 // myBoundFaces (bound = list of faces) - REFERENCE
2414 // myVertexNode (vertex = node)
2415 // myVertexNodeFree (floating vertex = node)
2417 //=======================================================================
2419 void BRepBuilderAPI_Sewing::FindFreeBoundaries()
2421 // Take into account the context shape if needed
2422 TopTools_IndexedMapOfShape NewShapes;
2423 if (!myShape.IsNull()) {
2424 if (myOldShapes.IsEmpty()) {
2429 TopoDS_Shape newShape = myReShape->Apply(myShape);
2430 if (!newShape.IsNull()) NewShapes.Add(newShape);
2433 // Create map Edge -> Faces
2434 TopTools_IndexedDataMapOfShapeListOfShape EdgeFaces;
2435 Standard_Integer i, nbShapes = myOldShapes.Extent();
2436 for (i = 1; i <= nbShapes; i++) {
2437 // Retrieve new shape
2438 TopoDS_Shape shape = myOldShapes(i);
2439 if (shape.IsNull()) continue;
2440 NewShapes.Add(shape);
2441 // Explore shape to find all boundaries
2442 for (TopExp_Explorer eExp(shape,TopAbs_EDGE); eExp.More(); eExp.Next()) {
2443 TopoDS_Shape edge = eExp.Current();
2444 if (!EdgeFaces.Contains(edge)) {
2445 TopTools_ListOfShape listFaces;
2446 EdgeFaces.Add(edge,listFaces);
2450 // Fill map Edge -> Faces
2451 nbShapes = NewShapes.Extent();
2452 TopTools_MapOfShape mapFaces;
2453 for (i = 1; i <= nbShapes; i++) {
2454 // Explore shape to find all faces
2455 TopExp_Explorer fExp(NewShapes.FindKey(i),TopAbs_FACE);
2456 for (; fExp.More(); fExp.Next()) {
2457 TopoDS_Shape face = fExp.Current();
2458 if(mapFaces.Contains(face)) continue;
2461 // Explore face to find all boundaries
2462 for (TopoDS_Iterator aIw(face); aIw.More(); aIw.Next()) {
2463 if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
2464 for (TopoDS_Iterator aIIe(aIw.Value()); aIIe.More(); aIIe.Next()) {
2466 TopoDS_Shape edge = aIIe.Value();
2468 if (EdgeFaces.Contains(edge)) {
2469 EdgeFaces.ChangeFromKey(edge).Append(face);
2470 //TopTools_ListOfShape& listFaces = EdgeFaces.ChangeFromKey(edge);
2471 //Standard_Boolean isContained = Standard_False;
2472 //TopTools_ListIteratorOfListOfShape itf(listFaces);
2473 //for (; itf.More() && !isContained; itf.Next())
2474 // isContained = face.IsSame(itf.Value());
2475 //if (!isContained) listFaces.Append(face);
2481 // Find free boundaries
2482 nbShapes = EdgeFaces.Extent();
2483 for (i = 1; i <= nbShapes; i++) {
2484 TopTools_ListOfShape& listFaces = EdgeFaces(i);
2485 Standard_Integer nbFaces = listFaces.Extent();
2486 TopoDS_Shape edge = EdgeFaces.FindKey(i);
2487 if(edge.Orientation() == TopAbs_INTERNAL)
2489 Standard_Boolean isSeam = Standard_False;
2491 TopoDS_Face face = TopoDS::Face(listFaces.First());
2492 isSeam = BRep_Tool::IsClosed(TopoDS::Edge(edge),face);
2494 ///Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
2495 //isSeam = (IsUClosedSurface(surf) || IsVClosedSurface(surf));
2498 TopoDS_Shape anewEdge = edge.EmptyCopied();
2499 TopoDS_Iterator aItV(edge);
2500 for( ; aItV.More() ; aItV.Next())
2501 aB.Add(anewEdge,aItV.Value());
2505 Standard_Real first2d,last2d;
2506 Handle(Geom2d_Curve) c2dold =
2507 BRep_Tool::CurveOnSurface(TopoDS::Edge(edge),TopoDS::Face(listFaces.First()),first2d,last2d);
2509 Handle(Geom2d_Curve) c2d;
2511 B.UpdateEdge(TopoDS::Edge(anewEdge),c2d,c2d,TopoDS::Face(listFaces.First()),0);
2512 B.UpdateEdge(TopoDS::Edge(anewEdge),c2dold,TopoDS::Face(listFaces.First()),0);
2514 Standard_Real aFirst, aLast;
2515 BRep_Tool::Range(TopoDS::Edge(edge),aFirst, aLast);
2516 aB.Range(TopoDS::Edge(anewEdge),aFirst, aLast);
2517 aB.Range(TopoDS::Edge(anewEdge),TopoDS::Face(listFaces.First()),first2d,last2d);
2518 myReShape->Replace(edge,anewEdge);
2522 isSeam = Standard_False;
2525 Standard_Boolean isBoundFloat = (myFloatingEdgesMode && !nbFaces);
2526 Standard_Boolean isBound = (myFaceMode && ((myNonmanifold && nbFaces) || (nbFaces == 1 && !isSeam)));
2527 if (isBound || isBoundFloat) {
2528 // Ignore degenerated edge
2529 if (BRep_Tool::Degenerated(TopoDS::Edge(edge))) continue;
2530 // Ignore edge with internal vertices
2531 // Standard_Integer nbVtx = 0;
2532 // for (TopExp_Explorer vExp(edge,TopAbs_VERTEX); vExp.More(); vExp.Next()) nbVtx++;
2533 // if (nbVtx != 2) continue;
2534 // Add to BoundFaces
2535 TopTools_ListOfShape listFacesCopy;
2536 listFacesCopy.Append(listFaces);
2537 myBoundFaces.Add(edge,listFacesCopy);
2538 // Process edge vertices
2539 TopoDS_Vertex vFirst, vLast;
2540 TopExp::Vertices(TopoDS::Edge(edge), vFirst, vLast);
2541 if(vFirst.IsNull() || vLast.IsNull()) continue;
2542 if(vFirst.Orientation() == TopAbs_INTERNAL || vLast.Orientation() == TopAbs_INTERNAL)
2545 // Add to VertexNode
2546 if (!myVertexNode.Contains(vFirst))
2547 myVertexNode.Add(vFirst,vFirst);
2548 if (!myVertexNode.Contains(vLast))
2549 myVertexNode.Add(vLast,vLast);
2552 // Add to VertexNodeFree
2553 if (!myVertexNodeFree.Contains(vFirst))
2554 myVertexNodeFree.Add(vFirst,vFirst);
2555 if (!myVertexNodeFree.Contains(vLast))
2556 myVertexNodeFree.Add(vLast,vLast);
2562 //=======================================================================
2563 //function : VerticesAssembling
2564 //purpose : Modifies :
2565 // myVertexNode (nodes glued)
2566 // myVertexNodeFree (nodes glued)
2567 // myNodeSections (lists of sections merged for glued nodes)
2569 //=======================================================================
2571 static Standard_Boolean CreateNewNodes(const TopTools_IndexedDataMapOfShapeShape& NodeNearestNode,
2572 const TopTools_IndexedDataMapOfShapeListOfShape& NodeVertices,
2573 TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2574 TopTools_DataMapOfShapeListOfShape& aNodeEdges)
2576 Standard_Integer i, nbNearest = NodeNearestNode.Extent();
2580 TopTools_DataMapOfShapeShape OldNodeNewNode;
2581 TopTools_DataMapOfShapeListOfShape NewNodeOldNodes;
2582 for (i = 1; i <= nbNearest; i++) {
2583 // Retrieve a pair of nodes to merge
2584 TopoDS_Shape oldnode1 = NodeNearestNode.FindKey(i);
2585 TopoDS_Shape oldnode2 = NodeNearestNode(i);
2586 // Second node should also be in the map
2587 if (!NodeNearestNode.Contains(oldnode2)) continue;
2588 // Get new node for old node #1
2589 if (OldNodeNewNode.IsBound(oldnode1)) {
2590 TopoDS_Shape newnode1 = OldNodeNewNode(oldnode1);
2591 if (OldNodeNewNode.IsBound(oldnode2)) {
2592 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2593 if (!newnode1.IsSame(newnode2)) {
2594 // Change data for new node #2
2595 TopTools_ListOfShape& lnode1 = NewNodeOldNodes(newnode1);
2596 TopTools_ListIteratorOfListOfShape itn(NewNodeOldNodes(newnode2));
2597 for (; itn.More(); itn.Next()) {
2598 TopoDS_Shape node2 = itn.Value();
2599 lnode1.Append(node2);
2600 OldNodeNewNode(node2) = newnode1;
2602 NewNodeOldNodes.UnBind(newnode2);
2606 // Old node #2 is not bound - add to old node #1
2607 OldNodeNewNode.Bind(oldnode2,newnode1);
2608 NewNodeOldNodes(newnode1).Append(oldnode2);
2612 if (OldNodeNewNode.IsBound(oldnode2)) {
2613 // Old node #1 is not bound - add to old node #2
2614 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2615 OldNodeNewNode.Bind(oldnode1,newnode2);
2616 NewNodeOldNodes(newnode2).Append(oldnode1);
2619 // Nodes are not bound - create new node
2620 TopoDS_Vertex newnode;
2621 B.MakeVertex(newnode);
2622 OldNodeNewNode.Bind(oldnode1,newnode);
2623 OldNodeNewNode.Bind(oldnode2,newnode);
2624 TopTools_ListOfShape lnodes;
2625 lnodes.Append(oldnode1);
2626 lnodes.Append(oldnode2);
2627 NewNodeOldNodes.Bind(newnode,lnodes);
2632 // Stop if no new nodes created
2633 if (!NewNodeOldNodes.Extent()) return Standard_False;
2635 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter1(NewNodeOldNodes);
2636 for (; iter1.More(); iter1.Next()) {
2637 const TopoDS_Vertex& newnode = TopoDS::Vertex(iter1.Key());
2638 // Calculate new node center point
2639 gp_XYZ theCoordinates(0.,0.,0.);
2640 TopTools_ListOfShape lvert; // Accumulate node vertices
2641 TopTools_MapOfShape medge;
2642 TopTools_ListOfShape ledge; // Accumulate node edges
2643 // Iterate on old nodes
2644 TopTools_ListIteratorOfListOfShape itn(iter1.Value());
2645 for (; itn.More(); itn.Next()) {
2646 const TopoDS_Shape& oldnode = itn.Value();
2647 // Iterate on node vertices
2648 TopTools_ListIteratorOfListOfShape itv(NodeVertices.FindFromKey(oldnode));
2649 for (; itv.More(); itv.Next()) {
2650 TopoDS_Vertex vertex = TopoDS::Vertex(itv.Value());
2651 // Change node for vertex
2652 aVertexNode.ChangeFromKey(vertex) = newnode;
2653 // Accumulate coordinates
2654 theCoordinates += BRep_Tool::Pnt(vertex).XYZ();
2655 lvert.Append(vertex);
2657 // Iterate on node edges
2658 const TopTools_ListOfShape& edges = aNodeEdges(oldnode);
2659 TopTools_ListIteratorOfListOfShape ite(edges);
2660 for (; ite.More(); ite.Next()) {
2661 TopoDS_Shape edge = ite.Value();
2662 if (!medge.Contains(edge)) { medge.Add(edge); ledge.Append(edge); }
2664 // Unbind old node edges
2665 aNodeEdges.UnBind(oldnode);
2667 // Bind new node edges
2668 aNodeEdges.Bind(newnode,ledge);
2669 gp_Pnt center(theCoordinates / lvert.Extent());
2670 // Calculate new node tolerance
2671 Standard_Real toler = 0.0;
2672 TopTools_ListIteratorOfListOfShape itv(lvert);
2673 for (; itv.More(); itv.Next()) {
2674 const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value());
2675 Standard_Real t = center.Distance(BRep_Tool::Pnt(vertex)) + BRep_Tool::Tolerance(vertex);
2676 if (toler < t) toler = t;
2678 // Update new node parameters
2679 B.UpdateVertex(newnode,center,toler);
2682 return Standard_True;
2685 static Standard_Integer IsMergedVertices(const TopoDS_Shape& face1,
2686 const TopoDS_Shape& e1, const TopoDS_Shape& e2,
2687 const TopoDS_Shape& vtx1, const TopoDS_Shape& vtx2)
2689 //Case of floating edges
2691 return (!IsClosedShape(e1,vtx1,vtx2));
2693 // Find wires containing given edges
2694 TopoDS_Shape wire1, wire2;
2695 TopExp_Explorer itw(face1,TopAbs_WIRE);
2696 for (; itw.More() && (wire1.IsNull() || wire2.IsNull()); itw.Next()) {
2697 TopoDS_Iterator ite(itw.Current(),Standard_False);
2698 for (; ite.More() && (wire1.IsNull() || wire2.IsNull()); ite.Next()) {
2699 if (wire1.IsNull() && e1.IsSame(ite.Value())) wire1 = itw.Current();
2700 if (wire2.IsNull() && e2.IsSame(ite.Value())) wire2 = itw.Current();
2703 Standard_Integer Status = 0;
2704 if (!wire1.IsNull() && !wire2.IsNull()) {
2705 if (wire1.IsSame(wire2)) {
2706 for (TopoDS_Iterator aIte(wire1,Standard_False); aIte.More(); aIte.Next()) {
2707 TopoDS_Vertex ve1,ve2;
2708 TopExp::Vertices(TopoDS::Edge(aIte.Value()),ve1,ve2);
2709 if ((ve1.IsSame(vtx1) && ve2.IsSame(vtx2)) ||
2710 (ve2.IsSame(vtx1) && ve1.IsSame(vtx2)))
2711 return (IsClosedShape(aIte.Value(),vtx1,vtx2)? 0 : 1);
2713 if (IsClosedShape(wire1,vtx1,vtx2)) {
2714 TopoDS_Vertex V1, V2;
2715 TopExp::Vertices(TopoDS::Wire(wire1),V1,V2);
2716 Standard_Boolean isEndVertex = ((V1.IsSame(vtx1) && V2.IsSame(vtx2)) ||
2717 (V2.IsSame(vtx1) && V1.IsSame(vtx2)));
2718 if (!isEndVertex) Status = 1;
2727 static Standard_Boolean GlueVertices(TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2728 TopTools_DataMapOfShapeListOfShape& aNodeEdges,
2729 const TopTools_IndexedDataMapOfShapeListOfShape& aBoundFaces,
2730 const Standard_Real Tolerance,
2731 const Handle(Message_ProgressIndicator)& theProgress)
2733 Standard_Integer i, nbVertices = aVertexNode.Extent();
2734 // Create map of node -> vertices
2735 TopTools_IndexedDataMapOfShapeListOfShape NodeVertices;
2736 BRepBuilderAPI_CellFilter aFilter (Tolerance);
2737 BRepBuilderAPI_VertexInspector anInspector (Tolerance);
2738 for (i = 1; i <= nbVertices; i++) {
2739 TopoDS_Shape vertex = aVertexNode.FindKey(i);
2740 TopoDS_Vertex node = TopoDS::Vertex(aVertexNode(i));
2741 if (NodeVertices.Contains(node)) {
2742 NodeVertices.ChangeFromKey(node).Append(vertex);
2745 TopTools_ListOfShape vlist;
2746 vlist.Append(vertex);
2747 NodeVertices.Add(node,vlist);
2748 gp_Pnt aPnt = BRep_Tool::Pnt (TopoDS::Vertex (node));
2749 aFilter.Add (NodeVertices.FindIndex (node), aPnt.XYZ());
2750 anInspector.Add (aPnt.XYZ());
2753 Standard_Integer nbNodes = NodeVertices.Extent();
2755 cout << "Glueing " << nbNodes << " nodes..." << endl;
2757 // Merge nearest nodes
2758 TopTools_IndexedDataMapOfShapeShape NodeNearestNode;
2759 Message_ProgressSentry aPS (theProgress, "Glueing nodes", 0, nbNodes, 1, Standard_True);
2760 for (i = 1; i <= nbNodes && aPS.More(); i++, aPS.Next()) {
2761 TopoDS_Vertex node1 = TopoDS::Vertex(NodeVertices.FindKey(i));
2763 gp_Pnt pt1 = BRep_Tool::Pnt (node1);
2764 anInspector.SetCurrent (pt1.XYZ());
2765 gp_XYZ aPntMin = anInspector.Shift (pt1.XYZ(), -Tolerance);
2766 gp_XYZ aPntMax = anInspector.Shift (pt1.XYZ(), Tolerance);
2767 aFilter.Inspect (aPntMin, aPntMax, anInspector);
2768 if (anInspector.ResInd().IsEmpty()) continue;
2769 // Retrieve list of edges for the first node
2770 const TopTools_ListOfShape& ledges1 = aNodeEdges(node1);
2771 // Explore list of near nodes and fill the sequence of glued nodes
2772 TopTools_SequenceOfShape SeqNodes;
2773 TopTools_ListOfShape listNodesSameEdge;
2774 //gp_Pnt pt1 = BRep_Tool::Pnt(node1);
2775 TColStd_ListIteratorOfListOfInteger iter1(anInspector.ResInd());
2776 for (; iter1.More(); iter1.Next()) {
2777 TopoDS_Vertex node2 = TopoDS::Vertex(NodeVertices.FindKey(iter1.Value()));
2778 if (node1 == node2) continue;
2779 // Retrieve list of edges for the second node
2780 const TopTools_ListOfShape& ledges2 = aNodeEdges(node2);
2781 // Check merging condition for the pair of nodes
2782 Standard_Integer Status = 0, isSameEdge = Standard_False;
2783 // Explore edges of the first node
2784 TopTools_ListIteratorOfListOfShape Ie1(ledges1);
2785 for (; Ie1.More() && !Status && !isSameEdge; Ie1.Next()) {
2786 const TopoDS_Shape& e1 = Ie1.Value();
2787 // Obtain real vertex from edge
2788 TopoDS_Shape v1 = node1;
2789 { //szv: Use brackets to destroy local variables
2790 TopoDS_Vertex ov1, ov2;
2791 TopExp::Vertices(TopoDS::Edge(e1),ov1,ov2);
2792 if (aVertexNode.Contains(ov1)) {
2793 if (node1.IsSame(aVertexNode.FindFromKey(ov1))) v1 = ov1;
2795 if (aVertexNode.Contains(ov2)) {
2796 if (node1.IsSame(aVertexNode.FindFromKey(ov2))) v1 = ov2;
2799 // Create map of faces for e1
2800 TopTools_MapOfShape Faces1;
2801 const TopTools_ListOfShape& lfac1 = aBoundFaces.FindFromKey(e1);
2802 if (lfac1.Extent()) {
2803 TopTools_ListIteratorOfListOfShape itf(lfac1);
2804 for (; itf.More(); itf.Next())
2805 if (!itf.Value().IsNull())
2806 Faces1.Add(itf.Value());
2808 // Explore edges of the second node
2809 TopTools_ListIteratorOfListOfShape Ie2(ledges2);
2810 for (; Ie2.More() && !Status && !isSameEdge; Ie2.Next()) {
2811 const TopoDS_Shape& e2 = Ie2.Value();
2812 // Obtain real vertex from edge
2813 TopoDS_Shape v2 = node2;
2814 { //szv: Use brackets to destroy local variables
2815 TopoDS_Vertex ov1, ov2;
2816 TopExp::Vertices(TopoDS::Edge(e2),ov1,ov2);
2817 if (aVertexNode.Contains(ov1)) {
2818 if (node2.IsSame(aVertexNode.FindFromKey(ov1))) v2 = ov1;
2820 if (aVertexNode.Contains(ov2)) {
2821 if (node2.IsSame(aVertexNode.FindFromKey(ov2))) v2 = ov2;
2824 // Explore faces for e2
2825 const TopTools_ListOfShape& lfac2 = aBoundFaces.FindFromKey(e2);
2826 if (lfac2.Extent()) {
2827 TopTools_ListIteratorOfListOfShape itf(lfac2);
2828 for (; itf.More() && !Status && !isSameEdge; itf.Next()) {
2829 // Check merging conditions for the same face
2830 if (Faces1.Contains(itf.Value())) {
2831 Standard_Integer stat = IsMergedVertices(itf.Value(),e1,e2,v1,v2);
2832 if (stat == 1) isSameEdge = Standard_True;
2837 else if (Faces1.IsEmpty() && e1 == e2) {
2838 Standard_Integer stat = IsMergedVertices(TopoDS_Face(),e1,e1,v1,v2);
2839 if (stat == 1) isSameEdge = Standard_True;
2845 if (Status) continue;
2846 if (isSameEdge) listNodesSameEdge.Append(node2);
2847 // Append near node to the sequence
2848 gp_Pnt pt2 = BRep_Tool::Pnt(node2);
2849 Standard_Real dist = pt1.Distance(pt2);
2850 if (dist < Tolerance) {
2851 Standard_Boolean isIns = Standard_False;
2852 for (Standard_Integer kk = 1; kk <= SeqNodes.Length() && !isIns; kk++) {
2853 gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(SeqNodes.Value(kk)));
2854 if (dist < pt1.Distance(pt)) {
2855 SeqNodes.InsertBefore(kk,node2);
2856 isIns = Standard_True;
2859 if (!isIns) SeqNodes.Append(node2);
2862 if (SeqNodes.Length()) {
2863 // Remove nodes near to some other from the same edge
2864 if (listNodesSameEdge.Extent()) {
2865 TopTools_ListIteratorOfListOfShape lInt(listNodesSameEdge);
2866 for (; lInt.More(); lInt.Next()) {
2867 const TopoDS_Vertex& n2 = TopoDS::Vertex(lInt.Value());
2868 gp_Pnt p2 = BRep_Tool::Pnt(n2);
2869 for (Standard_Integer k = 1; k <= SeqNodes.Length(); ) {
2870 const TopoDS_Vertex& n1 = TopoDS::Vertex(SeqNodes.Value(k));
2872 gp_Pnt p1 = BRep_Tool::Pnt(n1);
2873 if (p2.Distance(p1) >= pt1.Distance(p1)) { k++; continue; }
2879 // Bind nearest node if at least one exists
2880 if (SeqNodes.Length())
2881 NodeNearestNode.Add(node1,SeqNodes.First());
2883 anInspector.ClearResList();
2886 // Create new nodes for chained nearest nodes
2887 if (NodeNearestNode.IsEmpty()) return Standard_False;
2889 return CreateNewNodes(NodeNearestNode,NodeVertices,aVertexNode,aNodeEdges);
2892 void BRepBuilderAPI_Sewing::VerticesAssembling(const Handle(Message_ProgressIndicator)& thePI)
2894 Standard_Integer nbVert = myVertexNode.Extent();
2895 Standard_Integer nbVertFree = myVertexNodeFree.Extent();
2896 Message_ProgressSentry aPS (thePI, "Vertices assembling", 0, 2, 1);
2897 if (nbVert || nbVertFree) {
2898 // Fill map node -> sections
2900 for (i = 1; i <= myBoundFaces.Extent(); i++) {
2901 TopoDS_Shape bound = myBoundFaces.FindKey(i);
2902 for (TopoDS_Iterator itv(bound,Standard_False); itv.More(); itv.Next()) {
2903 TopoDS_Shape node = itv.Value();
2904 if (myNodeSections.IsBound(node))
2905 myNodeSections(node).Append(bound);
2907 TopTools_ListOfShape lbnd;
2909 myNodeSections.Bind(node,lbnd);
2916 cout << "Assemble " << nbVert << " vertices on faces..." << endl;
2918 while (GlueVertices(myVertexNode,myNodeSections,myBoundFaces,myTolerance, thePI));
2925 cout << "Assemble " << nbVertFree << " vertices on floating edges..." << endl;
2927 while (GlueVertices(myVertexNodeFree,myNodeSections,myBoundFaces,myTolerance, thePI));
2932 //=======================================================================
2933 //function : replaceNMVertices
2934 //purpose : internal use (static)
2935 //=======================================================================
2936 static void replaceNMVertices(const TopoDS_Edge& theEdge,
2937 const TopoDS_Vertex& theV1,
2938 const TopoDS_Vertex& theV2,
2939 const Handle(BRepTools_ReShape)& theReShape)
2941 //To keep NM vertices on edge
2942 TopTools_SequenceOfShape aSeqNMVert;
2943 TColStd_SequenceOfReal aSeqNMPars;
2944 Standard_Boolean hasNMVert = findNMVertices(theEdge,aSeqNMVert,aSeqNMPars);
2947 Standard_Real first, last;
2948 BRep_Tool::Range(theEdge, first, last);
2949 TopLoc_Location aLoc;
2950 Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,aLoc,first, last);
2953 TopTools_SequenceOfShape aEdVert;
2954 TColStd_SequenceOfReal aEdParams;
2955 Standard_Integer i =1, nb = aSeqNMPars.Length();
2957 for( ; i <= nb;i++) {
2958 Standard_Real apar = aSeqNMPars.Value(i);
2959 if(fabs(apar - first) <= Precision::PConfusion()) {
2960 theReShape->Replace(aSeqNMVert.Value(i),theV1);
2963 if(fabs(apar - last) <= Precision::PConfusion()) {
2964 theReShape->Replace(aSeqNMVert.Value(i),theV2);
2967 TopoDS_Shape aV = aSeqNMVert.Value(i);
2968 Standard_Integer j =1;
2969 for( ; j <= aEdParams.Length();j++) {
2970 Standard_Real apar2 = aEdParams.Value(j);
2971 if(fabs(apar - apar2) <= Precision::PConfusion()) {
2972 theReShape->Replace(aV,aEdVert.Value(j));
2975 else if(apar < apar2) {
2976 TopoDS_Shape anewV = aV.EmptyCopied();
2977 aEdVert.InsertBefore(j,anewV);
2978 aEdParams.InsertBefore(j,apar);
2979 BRep_ListOfPointRepresentation& alistrep =
2980 (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints();
2981 Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
2982 alistrep.Append(aPRep);
2983 theReShape->Replace(aV,anewV);
2987 if (j > aEdParams.Length()) {
2988 TopoDS_Shape anewV = aV.EmptyCopied();
2989 aEdVert.Append(anewV);
2990 aEdParams.Append(apar);
2991 BRep_ListOfPointRepresentation& alistrep =
2992 (*((Handle(BRep_TVertex)*) &anewV.TShape()))->ChangePoints();
2993 Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
2994 alistrep.Append(aPRep);
2995 theReShape->Replace(aV,anewV);
2999 Standard_Integer newnb = aEdParams.Length();
3002 TopoDS_Shape anewEdge = theEdge.EmptyCopied();
3003 TopAbs_Orientation anOri = theEdge.Orientation();
3004 anewEdge.Orientation(TopAbs_FORWARD);
3006 aB.Add(anewEdge,theV1);
3007 aB.Add(anewEdge,theV2);
3009 for( i =1; i <= aEdVert.Length();i++)
3010 aB.Add(anewEdge,aEdVert.Value(i));
3011 anewEdge.Orientation(anOri);
3012 theReShape->Replace(theEdge,anewEdge);
3017 //=======================================================================
3018 //function : ReplaceEdge
3019 //purpose : internal use (static)
3020 //=======================================================================
3022 static void ReplaceEdge(const TopoDS_Shape& oldEdge,
3023 const TopoDS_Shape& theNewShape,
3024 const Handle(BRepTools_ReShape)& aReShape)
3026 TopoDS_Shape oldShape = aReShape->Apply(oldEdge);
3027 TopoDS_Shape newShape = aReShape->Apply(theNewShape);
3028 if (oldShape.IsSame(newShape)|| aReShape->IsRecorded(newShape)) return;
3031 aReShape->Replace(oldShape,newShape);
3032 TopoDS_Vertex V1old,V2old,V1new,V2new;
3033 TopExp::Vertices(TopoDS::Edge(oldShape),V1old,V2old);
3034 TopAbs_Orientation Orold = oldShape.Orientation();
3035 TopAbs_Orientation Ornew = Orold;
3036 if (newShape.ShapeType() == TopAbs_EDGE) {
3037 TopoDS_Edge aEn = TopoDS::Edge(newShape);
3038 TopExp::Vertices(aEn,V1new,V2new);
3039 Ornew = aEn.Orientation();
3040 replaceNMVertices(aEn,V1new,V2new,aReShape);
3042 else if (newShape.ShapeType() == TopAbs_WIRE) {
3043 for (TopExp_Explorer aex(newShape,TopAbs_EDGE); aex.More(); aex.Next()) {
3044 TopoDS_Edge ed = TopoDS::Edge(aex.Current());
3045 Ornew = ed.Orientation();
3046 TopoDS_Vertex aV1,aV2;
3047 TopExp::Vertices(ed,aV1,aV2);
3048 replaceNMVertices(ed,aV1,aV2,aReShape);
3055 V1new.Orientation(V1old.Orientation());
3056 V2new.Orientation(V2old.Orientation());
3057 if (V1old.IsSame(V2old) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) {
3058 aReShape->Replace(V1old,V1new);
3061 if (Orold == Ornew) {
3062 V1new.Orientation(V1old.Orientation());
3063 V2new.Orientation(V2old.Orientation());
3064 if (!V1old.IsSame(V1new) && !V1old.IsSame(V2new)&& !aReShape->IsRecorded(V1new))
3065 aReShape->Replace(V1old,V1new);
3066 if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3067 aReShape->Replace(V2old,V2new);
3070 V1new.Orientation(V2old.Orientation());
3071 V2new.Orientation(V1old.Orientation());
3072 if (!V1old.IsSame(V2new) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3073 aReShape->Replace(V1old,V2new);
3074 if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V1new))
3075 aReShape->Replace(V2old,V1new);
3079 //=======================================================================
3080 //function : Merging
3081 //purpose : Modifies :
3084 //=======================================================================
3086 void BRepBuilderAPI_Sewing::Merging(const Standard_Boolean /* firstTime */,
3087 const Handle(Message_ProgressIndicator)& thePI)
3090 // TopTools_MapOfShape MergedEdges;
3091 Message_ProgressSentry aPS (thePI, "Merging bounds", 0, myBoundFaces.Extent(), 1);
3092 for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
3094 TopoDS_Shape bound = myBoundFaces.FindKey(i);
3096 // If bound was already merged - continue
3097 if (myMergedEdges.Contains(bound)) continue;
3099 if (!myBoundFaces(i).Extent()) {
3100 // Merge free edge - only vertices
3101 TopoDS_Vertex no1, no2;
3102 TopExp::Vertices(TopoDS::Edge(bound),no1,no2);
3103 TopoDS_Shape nno1 = no1, nno2 = no2;
3104 if (myVertexNodeFree.Contains(no1))
3105 nno1 = myVertexNodeFree.FindFromKey(no1);
3106 if (myVertexNodeFree.Contains(no2))
3107 nno2 = myVertexNodeFree.FindFromKey(no2);
3108 if (!no1.IsSame(nno1)) {
3109 nno1.Orientation(no1.Orientation());
3110 myReShape->Replace(no1,nno1);
3112 if (!no2.IsSame(nno2)) {
3113 nno2.Orientation(no2.Orientation());
3114 myReShape->Replace(no2,nno2);
3116 myMergedEdges.Add(bound);
3120 // Check for previous splitting, build replacing wire
3121 TopoDS_Wire BoundWire;
3122 Standard_Boolean isPrevSplit = Standard_False;
3123 Standard_Boolean hasCuttingSections = myBoundSections.IsBound(bound);
3124 if (hasCuttingSections) {
3125 B.MakeWire(BoundWire);
3126 BoundWire.Orientation(bound.Orientation());
3127 // Iterate on cutting sections
3128 TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3129 for (; its.More(); its.Next()) {
3130 TopoDS_Shape section = its.Value();
3131 B.Add(BoundWire,section);
3132 if (myMergedEdges.Contains(section)) isPrevSplit = Standard_True;
3137 TopTools_DataMapOfShapeShape MergedWithBound;
3139 // Obtain sequence of edges merged with bound
3140 TopTools_SequenceOfShape seqMergedWithBound;
3141 TColStd_SequenceOfInteger seqMergedWithBoundOri;
3142 if (MergedNearestEdges(bound,seqMergedWithBound,seqMergedWithBoundOri)) {
3143 // Store bound in the map
3144 MergedWithBound.Bind(bound,bound);
3145 // Iterate on edges merged with bound
3146 Standard_Integer ii = 1;
3147 while (ii <= seqMergedWithBound.Length()) {
3148 TopoDS_Shape iedge = seqMergedWithBound.Value(ii);
3149 // Remove edge if recorded as merged
3150 Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) ||
3151 MergedWithBound.IsBound(iedge));
3153 if (myBoundSections.IsBound(iedge)) {
3154 // Edge is splitted - check sections
3155 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3156 for (; lit.More() && !isRejected; lit.Next()) {
3157 const TopoDS_Shape& sec = lit.Value();
3158 // Remove edge (bound) if at least one of its sections already merged
3159 isRejected = (myMergedEdges.Contains(sec) || MergedWithBound.IsBound(sec));
3163 if (mySectionBound.IsBound(iedge)) {
3164 // Edge is a section - check bound
3165 const TopoDS_Shape& bnd = mySectionBound(iedge);
3166 // Remove edge (section) if its bound already merged
3167 isRejected = (myMergedEdges.Contains(bnd) || MergedWithBound.IsBound(bnd));
3171 // To the next merged edge
3173 // Remove rejected edge
3174 seqMergedWithBound.Remove(ii);
3175 seqMergedWithBoundOri.Remove(ii);
3178 // Process accepted edge
3179 MergedWithBound.Bind(iedge,iedge);
3183 Standard_Integer nbMerged = seqMergedWithBound.Length();
3185 // Create same parameter edge
3186 TopTools_MapOfShape ActuallyMerged;
3187 TopoDS_Edge MergedEdge = SameParameterEdge(bound,seqMergedWithBound,
3188 seqMergedWithBoundOri,
3189 ActuallyMerged,myReShape);
3190 Standard_Boolean isForward = Standard_False;
3191 if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3192 // Process actually merged edges
3193 Standard_Integer nbActuallyMerged = 0;
3194 for (ii = 1; ii <= nbMerged; ii++) {
3195 TopoDS_Shape iedge = seqMergedWithBound(ii);
3196 if (ActuallyMerged.Contains(iedge)) {
3198 // Record merged edge in the map
3199 TopAbs_Orientation orient = iedge.Orientation();
3200 if (!isForward) orient = TopAbs::Reverse(orient);
3201 if (!seqMergedWithBoundOri(ii)) orient = TopAbs::Reverse(orient);
3202 MergedWithBound.ChangeFind(iedge) = MergedEdge.Oriented(orient);
3204 else MergedWithBound.UnBind(iedge);
3206 if (nbActuallyMerged) {
3207 // Record merged bound in the map
3208 TopAbs_Orientation orient = bound.Orientation();
3209 if (!isForward) orient = TopAbs::Reverse(orient);
3210 MergedWithBound.ChangeFind(bound) = MergedEdge.Oriented(orient);
3212 nbMerged = nbActuallyMerged;
3214 // Remove bound from the map if not finally merged
3215 if (!nbMerged) MergedWithBound.UnBind(bound);
3218 Standard_Boolean isMerged = MergedWithBound.Extent();
3220 // Merge with cutting sections
3221 Handle(BRepTools_ReShape) SectionsReShape = new BRepTools_ReShape;
3222 TopTools_DataMapOfShapeShape MergedWithSections;
3223 if (hasCuttingSections) {
3224 // Iterate on cutting sections
3225 TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3226 for (; its.More(); its.Next()) {
3227 // Retrieve cutting section
3228 TopoDS_Shape section = its.Value();
3229 // Skip section if already merged
3230 if (myMergedEdges.Contains(section)) continue;
3231 // Merge cutting section
3232 TopTools_SequenceOfShape seqMergedWithSection;
3233 TColStd_SequenceOfInteger seqMergedWithSectionOri;
3234 if (MergedNearestEdges(section,seqMergedWithSection,seqMergedWithSectionOri)) {
3235 // Store section in the map
3236 MergedWithSections.Bind(section,section);
3237 // Iterate on edges merged with section
3238 Standard_Integer ii = 1;
3239 while (ii <= seqMergedWithSection.Length()) {
3240 TopoDS_Shape iedge = seqMergedWithSection.Value(ii);
3241 // Remove edge if recorded as merged
3242 Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || MergedWithSections.IsBound(iedge));
3244 if (myBoundSections.IsBound(iedge)) {
3245 // Edge is splitted - check sections
3246 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3247 for (; lit.More() && !isRejected; lit.Next()) {
3248 const TopoDS_Shape& sec = lit.Value();
3249 // Remove edge (bound) if at least one of its sections already merged
3250 isRejected = (myMergedEdges.Contains(sec) || MergedWithSections.IsBound(sec));
3254 if (mySectionBound.IsBound(iedge)) {
3255 // Edge is a section - check bound
3256 const TopoDS_Shape& bnd = mySectionBound(iedge);
3257 // Remove edge (section) if its bound already merged
3258 isRejected = (myMergedEdges.Contains(bnd) || MergedWithSections.IsBound(bnd));
3262 // To the next merged edge
3264 // Remove rejected edge
3265 seqMergedWithSection.Remove(ii);
3266 seqMergedWithSectionOri.Remove(ii);
3269 // Process accepted edge
3270 MergedWithSections.Bind(iedge,iedge);
3274 Standard_Integer nbMerged = seqMergedWithSection.Length();
3276 // Create same parameter edge
3277 TopTools_MapOfShape ActuallyMerged;
3278 TopoDS_Edge MergedEdge = SameParameterEdge(section,seqMergedWithSection,
3279 seqMergedWithSectionOri,
3280 ActuallyMerged,SectionsReShape);
3281 Standard_Boolean isForward = Standard_False;
3282 if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3283 // Process actually merged edges
3284 Standard_Integer nbActuallyMerged = 0;
3285 for (ii = 1; ii <= nbMerged; ii++) {
3286 TopoDS_Shape iedge = seqMergedWithSection(ii);
3287 if (ActuallyMerged.Contains(iedge)) {
3289 // Record merged edge in the map
3290 TopAbs_Orientation orient = iedge.Orientation();
3291 if (!isForward) orient = TopAbs::Reverse(orient);
3292 if (!seqMergedWithSectionOri(ii)) orient = TopAbs::Reverse(orient);
3293 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3294 MergedWithSections.ChangeFind(iedge) = oedge;
3295 ReplaceEdge(myReShape->Apply(iedge),oedge,SectionsReShape);
3297 else MergedWithSections.UnBind(iedge);
3299 if (nbActuallyMerged) {
3300 // Record merged section in the map
3301 TopAbs_Orientation orient = section.Orientation();
3302 if (!isForward) orient = TopAbs::Reverse(orient);
3303 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3304 MergedWithSections.ChangeFind(section) = oedge;
3305 ReplaceEdge(myReShape->Apply(section),oedge,SectionsReShape);
3307 nbMerged = nbActuallyMerged;
3309 // Remove section from the map if not finally merged
3310 if (!nbMerged) MergedWithSections.UnBind(section);
3312 else if (isMerged) {
3313 // Reject merging of sections
3314 MergedWithSections.Clear();
3319 Standard_Boolean isMergedSplit = MergedWithSections.Extent();
3321 if (!isMerged && !isMergedSplit) {
3322 // Nothing was merged in this iteration
3324 // Replace previously splitted bound
3325 myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3327 // else if (hasCuttingSections) {
3328 // myBoundSections.UnBind(bound); //szv: are you sure ???
3333 // Set splitting flag
3334 Standard_Boolean isSplitted = ((!isMerged && isMergedSplit) || isPrevSplit);
3336 // Choose between bound and sections merging
3337 if (isMerged && isMergedSplit && !isPrevSplit) {
3338 // Fill map of merged cutting sections
3339 TopTools_MapOfShape MapSplitEdges;
3340 TopTools_DataMapIteratorOfDataMapOfShapeShape itm;
3341 for (itm.Initialize(MergedWithSections); itm.More(); itm.Next()) {
3342 TopoDS_Shape edge = itm.Key();
3343 MapSplitEdges.Add(edge);
3345 // Iterate on edges merged with bound
3346 for (itm.Initialize(MergedWithBound); itm.More(); itm.Next()) {
3347 // Retrieve edge merged with bound
3348 TopoDS_Shape edge = itm.Key();
3349 // Remove edge from the map
3350 if (MapSplitEdges.Contains(edge)) MapSplitEdges.Remove(edge);
3351 if (myBoundSections.IsBound(edge)) {
3352 // Edge has cutting sections
3353 TopTools_ListIteratorOfListOfShape its(myBoundSections(edge));
3354 for (; its.More(); its.Next()) {
3355 TopoDS_Shape sec = its.Value();
3356 // Remove section from the map
3357 if (MapSplitEdges.Contains(sec)) MapSplitEdges.Remove(sec);
3361 // Calculate section merging tolerance
3362 Standard_Real MinSplitTol = RealLast();
3363 TopTools_MapIteratorOfMapOfShape im(MapSplitEdges);
3364 for (; im.More(); im.Next()) {
3365 TopoDS_Edge edge = TopoDS::Edge(MergedWithSections(im.Key()));
3366 MinSplitTol = Min(MinSplitTol,BRep_Tool::Tolerance(edge));
3368 // Calculate bound merging tolerance
3369 TopoDS_Edge BoundEdge = TopoDS::Edge(MergedWithBound(bound));
3370 Standard_Real BoundEdgeTol = BRep_Tool::Tolerance(BoundEdge);
3371 isSplitted = ((MinSplitTol < BoundEdgeTol+MinTolerance()) || myNonmanifold);
3372 isSplitted = (!MapSplitEdges.IsEmpty() && isSplitted);
3376 // Merging of cutting sections
3377 //myMergedEdges.Add(bound);
3378 myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3379 TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithSections);
3380 for (; itm.More(); itm.Next()) {
3381 TopoDS_Shape oldedge = itm.Key();
3382 TopoDS_Shape newedge = SectionsReShape->Apply(itm.Value());
3383 ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3384 myMergedEdges.Add(oldedge);
3385 if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3390 // Merging of initial bound
3391 TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithBound);
3392 //myMergedEdges.Add(bound);
3393 for (; itm.More(); itm.Next()) {
3394 TopoDS_Shape oldedge = itm.Key();
3395 TopoDS_Shape newedge = itm.Value();
3396 ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3397 myMergedEdges.Add(oldedge);
3398 if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3400 if (myBoundSections.IsBound(bound)) myBoundSections.UnBind(bound);
3401 if(!myMergedEdges.Contains(bound))
3402 myMergedEdges.Add(bound);
3406 myNbVertices = myVertexNode.Extent() + myVertexNodeFree.Extent();
3407 myNodeSections.Clear();
3408 myVertexNode.Clear();
3409 myVertexNodeFree.Clear();
3410 myCuttingNode.Clear();
3413 //=======================================================================
3414 //function : MergedNearestEdges
3416 //=======================================================================
3418 Standard_Boolean BRepBuilderAPI_Sewing::MergedNearestEdges(const TopoDS_Shape& edge,
3419 TopTools_SequenceOfShape& SeqMergedEdge,
3420 TColStd_SequenceOfInteger& SeqMergedOri)
3422 // Retrieve edge nodes
3423 TopoDS_Vertex no1, no2;
3424 TopExp::Vertices(TopoDS::Edge(edge),no1,no2);
3425 TopoDS_Shape nno1 = no1, nno2 = no2;
3426 Standard_Boolean isNode1 = myVertexNode.Contains(no1);
3427 Standard_Boolean isNode2 = myVertexNode.Contains(no2);
3428 if (isNode1) nno1 = myVertexNode.FindFromKey(no1);
3429 if (isNode2) nno2 = myVertexNode.FindFromKey(no2);
3431 // Fill map of nodes connected to the node #1
3432 TopTools_MapOfShape mapVert1;
3434 if (myCuttingNode.IsBound(nno1)) {
3435 TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno1));
3436 for (; ilv.More(); ilv.Next()) {
3437 TopoDS_Shape v1 = ilv.Value();
3439 if (!isNode1 && myCuttingNode.IsBound(v1)) {
3440 TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3441 for (; ilvn.More(); ilvn.Next()) {
3442 TopoDS_Shape vn = ilvn.Value();
3449 // Fill map of nodes connected to the node #2
3450 TopTools_MapOfShape mapVert2;
3452 if (myCuttingNode.IsBound(nno2)) {
3453 TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno2));
3454 for (; ilv.More(); ilv.Next()) {
3455 TopoDS_Shape v1 = ilv.Value();
3457 if (!isNode2 && myCuttingNode.IsBound(v1)) {
3458 TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3459 for (; ilvn.More(); ilvn.Next()) {
3460 TopoDS_Shape vn = ilvn.Value();
3467 // Find all possible contigous edges
3468 TopTools_SequenceOfShape seqEdges;
3469 seqEdges.Append(edge);
3470 TopTools_MapOfShape mapEdges;
3472 for (TopTools_MapIteratorOfMapOfShape imv1(mapVert1); imv1.More(); imv1.Next()) {
3473 TopoDS_Shape node1 = imv1.Key();
3474 if (!myNodeSections.IsBound(node1)) continue;
3475 TopTools_ListIteratorOfListOfShape ilsec(myNodeSections(node1));
3476 for (; ilsec.More(); ilsec.Next()) {
3477 TopoDS_Shape sec = ilsec.Value();
3478 if (sec.IsSame(edge)) continue;
3479 // Retrieve section nodes
3480 TopoDS_Vertex vs1, vs2;
3481 TopExp::Vertices(TopoDS::Edge(sec),vs1,vs2);
3482 TopoDS_Shape vs1n = vs1, vs2n = vs2;
3483 if (myVertexNode.Contains(vs1)) vs1n = myVertexNode.FindFromKey(vs1);
3484 if (myVertexNode.Contains(vs2)) vs2n = myVertexNode.FindFromKey(vs2);
3485 if ((mapVert1.Contains(vs1n) && mapVert2.Contains(vs2n)) ||
3486 (mapVert1.Contains(vs2n) && mapVert2.Contains(vs1n)))
3487 if (mapEdges.Add(sec)) {
3488 // Check for rejected cutting
3489 Standard_Boolean isRejected = myMergedEdges.Contains(sec);
3490 if(!isRejected && myBoundSections.IsBound(sec))
3492 TopTools_ListIteratorOfListOfShape its(myBoundSections(sec));
3493 for (; its.More() && !isRejected; its.Next()) {
3494 TopoDS_Shape section = its.Value();
3496 if (myMergedEdges.Contains(section))
3497 isRejected = Standard_True;
3500 if( !isRejected && mySectionBound.IsBound(sec)) {
3501 const TopoDS_Shape& bnd = mySectionBound(sec);
3502 isRejected = (!myBoundSections.IsBound(bnd) ||
3503 myMergedEdges.Contains(bnd));
3506 if (!isRejected) seqEdges.Append(sec);
3513 Standard_Boolean success = Standard_False;
3515 Standard_Integer nbSection = seqEdges.Length();
3516 if (nbSection > 1) {
3517 // Find the longest edge CCI60011
3518 Standard_Integer i, indRef = 1;
3519 if (myNonmanifold) {
3520 Standard_Real lenRef = 0.;
3521 for (i = 1; i <= nbSection; i++) {
3523 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(seqEdges(i)), f, l);
3524 GeomAdaptor_Curve cAdapt(c3d);
3525 Standard_Real len = GCPnts_AbscissaPoint::Length(cAdapt, f, l);
3526 if (len > lenRef) { indRef = i; lenRef = len; }
3529 TopoDS_Shape longEdge = seqEdges(indRef);
3530 seqEdges(indRef) = seqEdges(1);
3531 seqEdges(1) = longEdge;
3535 // Find merging candidates
3536 TColStd_SequenceOfInteger seqForward;
3537 TColStd_SequenceOfInteger seqCandidates;
3538 TColStd_IndexedMapOfInteger mapReference;
3539 mapReference.Add(1); // Add index of reference section
3540 if (FindCandidates(seqEdges,mapReference,seqCandidates,seqForward)) {
3541 Standard_Integer nbCandidates = seqCandidates.Length();
3542 // Check if reference section is merged reversed
3543 Standard_Boolean toReverse = Standard_False;
3545 // Find reference edge in candidates
3546 Standard_Boolean isFound = Standard_False;
3547 for (i = 1; i <= nbCandidates && !isFound; i++) {
3548 isFound = (seqCandidates(i) == indRef);
3550 // Record orientation
3551 toReverse = !seqForward(i);
3552 // Restore first edge
3553 seqCandidates(i) = 1;
3557 // Fail if reference is not in candidates
3558 if (!isFound) return Standard_False;
3560 // Record candidate sections
3561 for (i = 1; i <= nbCandidates; i++) {
3562 // Retrieve merged edge
3563 TopoDS_Shape iedge = seqEdges(seqCandidates(i));
3564 Standard_Integer ori =
3565 ((seqForward(i) && toReverse) || (!seqForward(i) && !toReverse))? 0 : 1;
3566 SeqMergedEdge.Append(iedge);
3567 SeqMergedOri.Append(ori);
3568 if (!myNonmanifold) break;
3570 success = nbCandidates;
3577 //=======================================================================
3578 //function : Cutting
3579 //purpose : Modifies :
3583 //=======================================================================
3585 void BRepBuilderAPI_Sewing::Cutting(const Handle(Message_ProgressIndicator)& thePI)
3587 Standard_Integer i, nbVertices = myVertexNode.Extent();
3588 if (!nbVertices) return;
3589 // Create a box tree with vertices
3590 Standard_Real eps = myTolerance*0.5;
3591 BRepBuilderAPI_BndBoxTree aTree;
3592 NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller (aTree);
3593 BRepBuilderAPI_BndBoxTreeSelector aSelector;
3594 for (i = 1; i <= nbVertices; i++) {
3595 gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(myVertexNode.FindKey(i)));
3599 aTreeFiller.Add (i, aBox);
3603 Handle(Geom_Curve) c3d;
3604 TopLoc_Location loc;
3605 Standard_Real first, last;
3606 // Iterate on all boundaries
3607 Standard_Integer nbBounds = myBoundFaces.Extent();
3608 Message_ProgressSentry aPS (thePI, "Cutting bounds", 0, nbBounds, 1);
3609 for (i = 1; i <= nbBounds && aPS.More(); i++, aPS.Next()) {
3610 const TopoDS_Edge& bound = TopoDS::Edge(myBoundFaces.FindKey(i));
3611 // Do not cut floating edges
3612 if (!myBoundFaces(i).Extent()) continue;
3613 // Create cutting sections
3614 TopTools_ListOfShape listSections;
3615 { //szv: Use brackets to destroy local variables
3616 // Obtain bound curve
3617 c3d = BRep_Tool::Curve(bound, loc, first, last);
3618 if (!loc.IsIdentity()) {
3619 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3620 c3d->Transform(loc.Transformation());
3622 // Obtain candidate vertices
3623 TopoDS_Vertex V1, V2;
3624 TopTools_IndexedMapOfShape CandidateVertices;
3625 { //szv: Use brackets to destroy local variables
3626 // Create bounding box around curve
3628 GeomAdaptor_Curve adptC(c3d,first,last);
3629 BndLib_Add3dCurve::Add(adptC,myTolerance,aGlobalBox);
3630 // Sort vertices to find candidates
3631 aSelector.SetCurrent (aGlobalBox);
3632 aTree.Select (aSelector);
3633 // Skip bound if no node is in the boundind box
3634 if (!aSelector.ResInd().Extent()) continue;
3635 // Retrieve bound nodes
3636 TopExp::Vertices(bound,V1,V2);
3637 const TopoDS_Shape& Node1 = myVertexNode.FindFromKey(V1);
3638 const TopoDS_Shape& Node2 = myVertexNode.FindFromKey(V2);
3639 // Fill map of candidate vertices
3640 TColStd_ListIteratorOfListOfInteger itl(aSelector.ResInd());
3641 for (; itl.More(); itl.Next()) {
3642 const Standard_Integer index = itl.Value();
3643 const TopoDS_Shape& Node = myVertexNode.FindFromIndex(index);
3644 if (!Node.IsSame(Node1) && !Node.IsSame(Node2)) {
3645 TopoDS_Shape vertex = myVertexNode.FindKey(index);
3646 CandidateVertices.Add(vertex);
3649 aSelector.ClearResList();
3651 Standard_Integer nbCandidates = CandidateVertices.Extent();
3652 if (!nbCandidates) continue;
3653 // Project vertices on curve
3654 TColStd_Array1OfReal arrPara(1,nbCandidates), arrDist(1,nbCandidates);
3655 TColgp_Array1OfPnt arrPnt(1,nbCandidates), arrProj(1,nbCandidates);
3656 for (Standard_Integer j = 1; j <= nbCandidates; j++)
3657 arrPnt(j) = BRep_Tool::Pnt(TopoDS::Vertex(CandidateVertices(j)));
3658 ProjectPointsOnCurve(arrPnt,c3d,first,last,arrDist,arrPara,arrProj,Standard_True);
3659 // Create cutting nodes
3660 TopTools_SequenceOfShape seqNode;
3661 TColStd_SequenceOfReal seqPara;
3662 CreateCuttingNodes(CandidateVertices,bound,
3663 V1,V2,arrDist,arrPara,arrProj,seqNode,seqPara);
3664 if (!seqPara.Length()) continue;
3665 // Create cutting sections
3666 CreateSections(bound, seqNode, seqPara, listSections);
3668 if (listSections.Extent() > 1) {
3669 // modification of maps:
3671 TopTools_ListIteratorOfListOfShape its(listSections);
3672 for (; its.More(); its.Next()) {
3673 TopoDS_Shape section = its.Value();
3674 // Iterate on section vertices
3675 for (TopoDS_Iterator itv(section); itv.More(); itv.Next()) {
3676 TopoDS_Shape vertex = itv.Value();
3677 // Convert vertex to node
3678 if (myVertexNode.Contains(vertex))
3679 vertex = TopoDS::Vertex(myVertexNode.FindFromKey(vertex));
3680 // Update node sections
3681 if (myNodeSections.IsBound(vertex))
3682 myNodeSections.ChangeFind(vertex).Append(section);
3684 TopTools_ListOfShape lsec;
3685 lsec.Append(section);
3686 myNodeSections.Bind(vertex,lsec);
3689 // Store bound for section
3690 mySectionBound.Bind(section,bound);
3692 // Store splitted bound
3693 myBoundSections.Bind(bound,listSections);
3697 cout << "From " << nbBounds << " bounds " << myBoundSections.Extent()
3698 << " were cut into " << mySectionBound.Extent() << " sections" << endl;
3702 //=======================================================================
3703 //function : GetSeqEdges
3705 //=======================================================================
3707 static void GetSeqEdges(const TopoDS_Shape& edge,
3708 TopTools_SequenceOfShape& seqEdges,
3709 TopTools_DataMapOfShapeListOfShape& VertEdge)
3711 Standard_Integer numV = 0;
3712 for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3713 TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3715 if (VertEdge.IsBound(V1)) {
3716 const TopTools_ListOfShape& listEdges = VertEdge.Find(V1);
3717 for (TopTools_ListIteratorOfListOfShape lIt(listEdges); lIt.More(); lIt.Next()) {
3718 TopoDS_Shape edge1 = lIt.Value();
3719 if (edge1.IsSame(edge)) continue;
3720 Standard_Boolean isContained = Standard_False;
3721 Standard_Integer i, index = 1;
3722 for (i = 1; i <= seqEdges.Length() && !isContained; i++) {
3723 isContained = seqEdges.Value(i).IsSame(edge1);
3724 if (!isContained && seqEdges.Value(i).IsSame(edge)) index = i;
3727 if (numV == 1) seqEdges.InsertBefore(index,edge1);
3728 else seqEdges.InsertAfter(index,edge1);
3729 GetSeqEdges(edge1,seqEdges,VertEdge);
3736 //=======================================================================
3737 //function : GetFreeWires
3739 //=======================================================================
3741 void BRepBuilderAPI_Sewing::GetFreeWires(TopTools_MapOfShape& MapFreeEdges, TopTools_SequenceOfShape& seqWires)
3743 TopTools_DataMapOfShapeListOfShape VertEdge;
3744 TopTools_MapIteratorOfMapOfShape itMap(MapFreeEdges);
3745 TopTools_SequenceOfShape seqFreeEdges;
3746 for (; itMap.More(); itMap.Next()) {
3747 TopoDS_Shape edge = itMap.Key();
3748 seqFreeEdges.Append(edge);
3749 for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3750 TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3751 if (VertEdge.IsBound(V1))
3752 VertEdge.ChangeFind(V1).Append(edge);
3754 TopTools_ListOfShape ls;
3756 VertEdge.Bind(V1,ls);
3761 Standard_Integer i, j;
3762 for (i = 1; i <= seqFreeEdges.Length(); i++) {
3763 TopTools_SequenceOfShape seqEdges;
3764 TopoDS_Shape edge = seqFreeEdges.Value(i);
3765 if (!MapFreeEdges.Contains(edge)) continue;
3766 seqEdges.Append(edge);
3767 GetSeqEdges(edge,seqEdges,VertEdge);
3770 for (j = 1; j <= seqEdges.Length(); j++) {
3771 B.Add(wire,seqEdges.Value(j));
3772 MapFreeEdges.Remove(seqEdges.Value(j));
3774 seqWires.Append(wire);
3775 if (MapFreeEdges.IsEmpty()) break;
3779 //=======================================================================
3780 //function : IsDegeneratedWire
3781 //purpose : internal use
3782 //=======================================================================
3784 static Standard_Boolean IsDegeneratedWire(const TopoDS_Shape& wire)
3786 if (wire.ShapeType() != TopAbs_WIRE) return Standard_False;
3787 // Get maximal vertices tolerance
3788 TopoDS_Vertex V1,V2;
3789 //TopExp::Vertices(TopoDS::Wire(wire),V1,V2);
3790 //Standard_Real tol = Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3791 Standard_Real wireLength = 0.0;
3792 TopLoc_Location loc;
3793 Standard_Real first, last;
3794 Standard_Integer nume = 0;
3795 Standard_Integer isSmall = 0;
3796 for (TopoDS_Iterator aIt(wire,Standard_False); aIt.More(); aIt.Next()) {
3798 TopoDS_Shape edge = aIt.Value();
3799 TopoDS_Vertex Ve1,Ve2;
3800 TopExp::Vertices(TopoDS::Edge(edge),Ve1,Ve2);
3808 else if(Ve1.IsSame(V2))
3812 else if(Ve2.IsSame(V2))
3815 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aIt.Value()),loc,first,last);
3816 if (!c3d.IsNull()) {
3817 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3818 if (!loc.IsIdentity()) {
3819 //c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3820 c3d->Transform(loc.Transformation());
3822 gp_Pnt pfirst = c3d->Value(first);
3823 gp_Pnt plast = c3d->Value(last);
3824 gp_Pnt pmid = c3d->Value((first +last)*0.5);
3825 Standard_Real length =0;
3826 if(pfirst.Distance(plast) > pfirst.Distance(pmid)) {
3827 length = pfirst.Distance(plast);
3830 GeomAdaptor_Curve cAdapt(c3d);
3831 length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3833 Standard_Real tole = BRep_Tool::Tolerance(Ve1)+BRep_Tool::Tolerance(Ve2);
3834 if(length <= tole) isSmall++;
3835 wireLength += length;
3838 if(isSmall == nume) return Standard_True;
3839 Standard_Real tol = BRep_Tool::Tolerance(V1)+BRep_Tool::Tolerance(V2);//Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3840 if (wireLength > tol) return Standard_False;
3841 return Standard_True;
3844 //=======================================================================
3845 //function : DegeneratedSection
3846 //purpose : internal use
3847 // create a new degenerated edge if the section is degenerated
3848 //=======================================================================
3850 static TopoDS_Edge DegeneratedSection(const TopoDS_Shape& section, const TopoDS_Shape& face)
3852 // Return if section is already degenerated
3853 if (BRep_Tool::Degenerated(TopoDS::Edge(section))) return TopoDS::Edge(section);
3855 // Retrieve edge curve
3856 TopLoc_Location loc;
3857 Standard_Real first, last;
3858 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(section), loc, first, last);
3859 if (c3d.IsNull()) { //gka
3861 TopoDS_Edge edge1 = TopoDS::Edge(section);
3862 aB.Degenerated(edge1, Standard_True);
3865 if (!loc.IsIdentity()) {
3866 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3867 c3d->Transform(loc.Transformation());
3870 // Test if the new edge is degenerated
3871 TopoDS_Vertex v1,v2;
3872 TopExp::Vertices(TopoDS::Edge(section),v1,v2);
3873 //Standard_Real tol = Max(BRep_Tool::Tolerance(v1),BRep_Tool::Tolerance(v2));
3874 //tol = Max(tolerance,tol);
3877 p1 = BRep_Tool::Pnt(v1);
3878 p3 = BRep_Tool::Pnt(v2);
3879 c3d->D0(0.5*(first + last),p2);
3881 //Standard_Boolean isDegenerated = Standard_False;
3882 //if (p1.Distance(p3) < tol) {
3883 //GeomAdaptor_Curve cAdapt(c3d);
3884 //Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3885 //isDegenerated = Standard_True; //(length < tol);
3889 //if (!isDegenerated) return edge;
3892 BRep_Builder aBuilder;
3893 edge = TopoDS::Edge(section);
3895 if (v1.IsSame(v2)) {
3896 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3897 aBuilder.Add(anEdge, v1.Oriented(TopAbs_FORWARD));
3898 aBuilder.Add(anEdge, v2.Oriented(TopAbs_REVERSED));
3901 TopoDS_Vertex newVertex;
3902 if (p1.Distance(p3) < BRep_Tool::Tolerance(v1))
3904 else if (p1.Distance(p3) < BRep_Tool::Tolerance(v2))
3907 Standard_Real d1 = BRep_Tool::Tolerance(v1) + p2.Distance(p1);
3908 Standard_Real d2 = BRep_Tool::Tolerance(v2) + p2.Distance(p3);
3909 Standard_Real newTolerance = Max(d1,d2);
3910 aBuilder.MakeVertex(newVertex, p2, newTolerance);
3912 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3913 aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_FORWARD));
3914 aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_REVERSED));
3917 BRep_Tool::Range(TopoDS::Edge(section), first, last);
3918 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3919 aBuilder.Range(TopoDS::Edge(anEdge), first, last);
3920 aBuilder.Degenerated(edge, Standard_True);
3921 Handle(Geom_Curve) aC3dNew;
3922 if (!face.IsNull()) {
3923 Standard_Real af,al;
3924 Handle(Geom2d_Curve) aC2dt = BRep_Tool::CurveOnSurface(TopoDS::Edge(section),TopoDS::Face(face),af,al);
3925 aBuilder.UpdateEdge(edge,aC3dNew,0);
3926 Handle(Geom2d_Curve) aC2dn = BRep_Tool::CurveOnSurface(edge,TopoDS::Face(face),af,al);
3928 aBuilder.UpdateEdge(edge,aC2dt,TopoDS::Face(face),0);
3934 //=======================================================================
3935 //function : EdgeProcessing
3936 //purpose : modifies :
3938 // myHasMultipleEdge
3940 // . if multiple edge
3941 // - length < 100.*myTolerance -> several free edge
3942 // . if no multiple edge
3943 // - make the contigous edges sameparameter
3944 //=======================================================================
3946 void BRepBuilderAPI_Sewing::EdgeProcessing(const Handle(Message_ProgressIndicator)& thePI)
3948 // constructs sectionEdge
3949 TopTools_MapOfShape MapFreeEdges;
3950 TopTools_DataMapOfShapeShape EdgeFace;
3951 Message_ProgressSentry aPS (thePI, "Edge processing", 0, myBoundFaces.Extent(), 1);
3952 for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
3953 const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
3954 const TopTools_ListOfShape& listFaces = myBoundFaces(i);
3955 if (listFaces.Extent() == 1) {
3956 if (myBoundSections.IsBound(bound)) {
3957 TopTools_ListIteratorOfListOfShape liter(myBoundSections(bound));
3958 for (; liter.More(); liter.Next()) {
3959 if (!myMergedEdges.Contains(liter.Value())) { //myReShape->IsRecorded(liter.Value())) {
3960 TopoDS_Shape edge = myReShape->Apply(liter.Value());
3961 if (!MapFreeEdges.Contains(edge)) {
3962 TopoDS_Shape face = listFaces.First();
3963 EdgeFace.Bind(edge,face);
3964 MapFreeEdges.Add(edge);
3970 if (!myMergedEdges.Contains(bound)) {
3971 TopoDS_Shape edge = myReShape->Apply(bound);
3972 if (!MapFreeEdges.Contains(edge)) {
3973 TopoDS_Shape face = listFaces.First();
3974 EdgeFace.Bind(edge,face);
3975 MapFreeEdges.Add(edge);
3982 if (!MapFreeEdges.IsEmpty()) {
3983 TopTools_SequenceOfShape seqWires;
3984 GetFreeWires(MapFreeEdges,seqWires);
3985 for (Standard_Integer j = 1; j <= seqWires.Length(); j++) {
3986 TopoDS_Wire wire = TopoDS::Wire(seqWires.Value(j));
3987 if (!IsDegeneratedWire(wire)) continue;
3988 for (TopoDS_Iterator Ie(wire,Standard_False); Ie.More(); Ie.Next()) {
3989 TopoDS_Shape aTmpShape = myReShape->Apply(Ie.Value()); //for porting
3990 TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
3992 if (EdgeFace.IsBound(edge))
3993 face = EdgeFace.Find(edge);
3994 TopoDS_Shape degedge = DegeneratedSection(edge,face);
3995 if (degedge.IsNull()) continue;
3996 if (!degedge.IsSame(edge))
3997 ReplaceEdge(edge,degedge,myReShape);
3998 if (BRep_Tool::Degenerated(TopoDS::Edge(degedge)))
3999 myDegenerated.Add(degedge);
4003 myMergedEdges.Clear();
4006 //=======================================================================
4007 //function : CreateSewedShape
4009 //=======================================================================
4011 void BRepBuilderAPI_Sewing::CreateSewedShape()
4013 // ---------------------
4014 // create the new shapes
4015 // ---------------------
4016 BRepTools_Quilt aQuilt;
4017 Standard_Boolean isLocal = !myShape.IsNull();
4020 TopoDS_Shape ns = myReShape->Apply(myShape);
4024 for (i = 1; i <= myOldShapes.Extent(); i++) {
4025 TopoDS_Shape sh = myOldShapes(i);
4027 sh = myReShape->Apply(sh);
4028 myOldShapes(i) = sh;
4029 if (!isLocal) aQuilt.Add(sh);
4032 TopoDS_Shape aNewShape = aQuilt.Shells();
4033 Standard_Integer numsh = 0;
4035 TopTools_IndexedMapOfShape OldShells;
4038 TopoDS_Compound aComp;
4039 aB.MakeCompound(aComp);
4040 for (TopoDS_Iterator aExpSh(aNewShape,Standard_False); aExpSh.More(); aExpSh.Next()) {
4041 TopoDS_Shape sh = aExpSh.Value();
4042 Standard_Boolean hasEdges = Standard_False;
4043 if (sh.ShapeType() == TopAbs_SHELL) {
4045 hasEdges = !OldShells.Contains(sh);
4048 Standard_Integer numf = 0;
4049 for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
4050 face = aExpF.Current();
4053 if (numf == 1) aB.Add(aComp,face);
4054 else if (numf > 1) aB.Add(aComp,sh);
4058 else if (sh.ShapeType() == TopAbs_FACE) {
4059 if (myNonmanifold) {
4064 hasEdges = Standard_True;
4066 else { aB.Add(aComp,sh); numsh++; }
4068 else { aB.Add(aComp,sh); numsh++; }
4069 if (hasEdges) OldShells.Add(sh);
4071 // Process collected shells
4072 if (myNonmanifold) {
4073 Standard_Integer nbOldShells = OldShells.Extent();
4074 if (nbOldShells == 1) {
4075 // Single shell - check for single face
4076 TopoDS_Shape sh = OldShells.FindKey(1);
4078 Standard_Integer numf = 0;
4079 for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
4080 face = aExpF.Current();
4083 if (numf == 1) aB.Add(aComp,face);
4084 else if (numf > 1) aB.Add(aComp,sh);
4087 else if (nbOldShells) {
4088 // Several shells should be merged
4089 TColStd_MapOfInteger IndexMerged;
4090 while (IndexMerged.Extent() < nbOldShells) {
4091 TopoDS_Shell NewShell;
4092 TopTools_MapOfShape NewEdges;
4093 for (i = 1; i <= nbOldShells; i++) {
4094 if (IndexMerged.Contains(i)) continue;
4095 TopoDS_Shell shell = TopoDS::Shell(OldShells.FindKey(i));
4096 if (NewShell.IsNull()) {
4098 aB.MakeShell(NewShell);
4099 TopoDS_Iterator aItSS(shell) ;
4100 for( ; aItSS.More(); aItSS.Next())
4101 aB.Add(NewShell,aItSS.Value())
4103 // Fill map of edges
4104 for (TopExp_Explorer eexp(shell,TopAbs_EDGE); eexp.More(); eexp.Next()) {
4105 TopoDS_Shape edge = eexp.Current();
4111 Standard_Boolean hasSharedEdge = Standard_False;
4112 TopExp_Explorer eexp(shell,TopAbs_EDGE);
4113 for (; eexp.More() && !hasSharedEdge; eexp.Next())
4114 hasSharedEdge = NewEdges.Contains(eexp.Current());
4115 if (hasSharedEdge) {
4116 // Add edges to the map
4117 for (TopExp_Explorer eexp1(shell,TopAbs_EDGE); eexp1.More(); eexp1.Next()) {
4118 TopoDS_Shape edge = eexp1.Current();
4121 // Add faces to the shell
4122 for (TopExp_Explorer fexp(shell,TopAbs_FACE); fexp.More(); fexp.Next()) {
4123 TopoDS_Shape face = fexp.Current();
4124 aB.Add(NewShell,face);
4130 // Process new shell
4132 Standard_Integer numf = 0;
4133 TopExp_Explorer aExpF(NewShell,TopAbs_FACE);
4134 for (; aExpF.More() && (numf < 2); aExpF.Next()) {
4135 face = aExpF.Current();
4138 if (numf == 1) aB.Add(aComp,face);
4139 else if (numf > 1) aB.Add(aComp,NewShell);
4145 // Extract single component
4146 TopoDS_Iterator aIt(aComp,Standard_False);
4147 mySewedShape = aIt.Value();
4150 mySewedShape = aComp;
4153 //=======================================================================
4154 //function : CreateOutputInformations
4155 //purpose : constructs :
4159 // myNbContigousEdges
4160 // myNbMultipleEdges
4162 //=======================================================================
4164 void BRepBuilderAPI_Sewing::CreateOutputInformations()
4166 // Construct edgeSections
4168 //TopTools_DataMapOfShapeListOfShape edgeSections;
4169 TopTools_IndexedDataMapOfShapeListOfShape edgeSections; //use index map for regulating free edges
4170 for (i = 1; i <= myBoundFaces.Extent(); i++) {
4171 const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
4172 TopTools_ListOfShape lsect;
4173 if (myBoundSections.IsBound(bound)) lsect = myBoundSections(bound);
4174 TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
4175 for (; aExp.More(); aExp.Next()) {
4176 TopoDS_Shape sec = bound, edge = aExp.Current();
4177 TopTools_ListIteratorOfListOfShape aI(lsect);
4178 for (; aI.More(); aI.Next()) {
4179 const TopoDS_Shape& section = aI.Value();
4180 if (edge.IsSame(myReShape->Apply(section))) { sec = section; break; }
4182 if (edgeSections.Contains(edge))
4183 edgeSections.ChangeFromKey(edge).Append(sec);
4185 TopTools_ListOfShape listSec;
4186 listSec.Append(sec);
4187 edgeSections.Add(edge,listSec);
4192 // Fill maps of Free, Contigous and Multiple edges
4193 //TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter2(edgeSections);
4194 for (i = 1; i <= edgeSections.Extent(); i++) {
4195 const TopoDS_Shape& edge = edgeSections.FindKey(i);
4196 const TopTools_ListOfShape& listSection = edgeSections(i);
4197 if (listSection.Extent() == 1) {
4198 if (BRep_Tool::Degenerated(TopoDS::Edge(edge)))
4199 myDegenerated.Add(edge);
4201 myFreeEdges.Add(edge);
4203 else if (listSection.Extent() == 2) {
4204 myContigousEdges.Add(edge,listSection);
4207 myMultipleEdges.Add(edge);
4211 // constructs myContigSectBound
4212 TopTools_DataMapOfShapeListOfShape aEdgeMap; //gka
4213 for (i = 1; i <= myBoundFaces.Extent(); i++) {
4214 TopoDS_Shape bound = myBoundFaces.FindKey(i);
4215 if (myBoundSections.IsBound(bound)) {
4216 TopTools_ListIteratorOfListOfShape iter(myBoundSections(bound));
4217 for (; iter.More(); iter.Next()) {
4218 TopoDS_Shape section = iter.Value();
4219 if(!myMergedEdges.Contains(section)) continue;
4220 //if (!myReShape->IsRecorded(section)) continue; // section is free
4221 TopoDS_Shape nedge = myReShape->Apply(section);
4222 if (nedge.IsNull()) continue; //szv debug
4223 if (!bound.IsSame(section))
4224 if (myContigousEdges.Contains(nedge))
4225 myContigSecBound.Bind(section, bound);
4231 //=======================================================================
4232 //function : ProjectPointsOnCurve
4233 //purpose : internal use
4234 //=======================================================================
4236 void BRepBuilderAPI_Sewing::ProjectPointsOnCurve(const TColgp_Array1OfPnt& arrPnt,
4237 const Handle(Geom_Curve)& c3d,
4238 const Standard_Real first,
4239 const Standard_Real last,
4240 TColStd_Array1OfReal& arrDist,
4241 TColStd_Array1OfReal& arrPara,
4242 TColgp_Array1OfPnt& arrProj,
4243 const Standard_Boolean isConsiderEnds) const
4247 GeomAdaptor_Curve GAC(c3d);
4248 Extrema_ExtPC locProj;
4249 locProj.Initialize(GAC, first, last);
4250 gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
4252 for (Standard_Integer i1 = 1; i1 <= arrPnt.Length(); i1++) {
4253 gp_Pnt pt = arrPnt(i1);
4254 Standard_Real worktol = myTolerance;
4255 Standard_Real distF2 = pfirst.SquareDistance(pt);
4256 Standard_Real distL2 = plast.SquareDistance(pt);
4257 Standard_Boolean isProjected = Standard_False;
4260 // Project current point on curve
4261 locProj.Perform(pt);
4262 if (locProj.IsDone() && locProj.NbExt() > 0) {
4263 Standard_Real dist2Min = Min(distF2,distL2);
4264 Standard_Integer ind, indMin = 0;
4265 for (ind = 1; ind <= locProj.NbExt(); ind++) {
4266 Standard_Real dProj2 = locProj.SquareDistance(ind);
4267 if (dProj2 < dist2Min) { indMin = ind; dist2Min = dProj2; }
4270 isProjected = Standard_True;
4271 Extrema_POnCurv pOnC = locProj.Point(indMin);
4272 Standard_Real paramProj = pOnC.Parameter();
4273 gp_Pnt ptProj = GAC.Value(paramProj);
4274 Standard_Real distProj2 = ptProj.SquareDistance(pt);
4275 if (!locProj.IsMin(indMin)) {
4276 if (Min(distF2,distL2) < dist2Min) {
4277 if (distF2 < distL2) {
4289 if (distProj2 < worktol * worktol) {
4290 arrDist(i1) = sqrt (distProj2);
4291 arrPara(i1) = paramProj;
4292 arrProj(i1) = ptProj;
4297 catch (Standard_Failure) {
4298 worktol = MinTolerance();
4300 cout << "Exception in BRepBuilderAPI_Sewing::ProjectPointsOnCurve: ";
4301 Standard_Failure::Caught()->Print(cout); cout << endl;
4304 if (!isProjected && isConsiderEnds) {
4305 if (Min(distF2,distL2) < worktol * worktol) {
4306 if (distF2 < distL2) {
4307 arrDist(i1) = sqrt (distF2);
4308 arrPara(i1) = first;
4309 arrProj(i1) = pfirst;
4312 arrDist(i1) = sqrt (distL2);
4314 arrProj(i1) = plast;
4321 //=======================================================================
4322 //function : CreateCuttingNodes
4323 //purpose : internal use
4324 //=======================================================================
4326 void BRepBuilderAPI_Sewing::CreateCuttingNodes(const TopTools_IndexedMapOfShape& MapVert,
4327 const TopoDS_Shape& bound,
4328 const TopoDS_Shape& vfirst,
4329 const TopoDS_Shape& vlast,
4330 const TColStd_Array1OfReal& arrDist,
4331 const TColStd_Array1OfReal& arrPara,
4332 const TColgp_Array1OfPnt& arrPnt,
4333 TopTools_SequenceOfShape& seqVert,
4334 TColStd_SequenceOfReal& seqPara)
4336 Standard_Integer i, j, nbProj = MapVert.Extent();
4338 // Reorder projections by distance
4339 TColStd_SequenceOfInteger seqOrderedIndex;
4340 { //szv: Use brackets to destroy local variables
4341 TColStd_SequenceOfReal seqOrderedDistance;
4342 for (i = 1; i <= nbProj; i++) {
4343 Standard_Real distProj = arrDist(i);
4344 if (distProj < 0.0) continue; // Skip vertex if not projected
4345 Standard_Boolean isInserted = Standard_False;
4346 for (j = 1; j <= seqOrderedIndex.Length() && !isInserted; j++) {
4347 isInserted = (distProj < seqOrderedDistance(j));
4349 seqOrderedIndex.InsertBefore(j,i);
4350 seqOrderedDistance.InsertBefore(j,distProj);
4354 seqOrderedIndex.Append(i);
4355 seqOrderedDistance.Append(distProj);
4359 nbProj = seqOrderedIndex.Length();
4360 if (!nbProj) return;
4362 BRep_Builder aBuilder;
4364 // Insert two initial vertices (to be removed later)
4365 TColStd_SequenceOfReal seqDist;
4366 TColgp_SequenceOfPnt seqPnt;
4367 { //szv: Use brackets to destroy local variables
4368 // Retrieve bound curve
4369 TopLoc_Location loc;
4370 Standard_Real first,last;
4371 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(bound), loc, first, last);
4372 if (!loc.IsIdentity()) {
4373 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
4374 c3d->Transform(loc.Transformation());
4376 GeomAdaptor_Curve GAC(c3d);
4377 seqVert.Prepend(vfirst); seqVert.Append(vlast);
4378 seqPara.Prepend(first); seqPara.Append(last);
4379 seqDist.Prepend(-1.0); seqDist.Append(-1.0);
4380 seqPnt.Prepend(GAC.Value(first)); seqPnt.Append(GAC.Value(last));
4383 TopTools_DataMapOfShapeShape NodeCuttingVertex;
4384 for (i = 1; i <= nbProj; i++) {
4386 const Standard_Integer index = seqOrderedIndex(i);
4387 Standard_Real disProj = arrDist(index);
4388 gp_Pnt pntProj = arrPnt(index);
4390 // Skip node if already bound to cutting vertex
4391 TopoDS_Shape node = myVertexNode.FindFromKey(MapVert(index));
4392 if (NodeCuttingVertex.IsBound(node)) continue;
4394 // Find the closest vertex
4395 Standard_Integer indexMin = 1;
4396 Standard_Real dist, distMin = pntProj.Distance(seqPnt(1));
4397 for (j = 2; j <= seqPnt.Length(); j++) {
4398 dist = pntProj.Distance(seqPnt(j));
4399 if (dist < distMin) { distMin = dist; indexMin = j; }
4402 // Check if current point is close to one of the existent
4403 if (distMin <= Max(disProj*0.1,MinTolerance())) {
4404 // Check distance if close
4405 Standard_Real jdist = seqDist.Value(indexMin);
4407 // Bind new cutting node (end vertex only)
4408 seqDist.SetValue(indexMin,disProj);
4409 TopoDS_Shape cvertex = seqVert.Value(indexMin);
4410 NodeCuttingVertex.Bind(node,cvertex);
4413 // Bind secondary cutting nodes
4414 NodeCuttingVertex.Bind(node,TopoDS_Vertex());
4418 // Build new cutting vertex
4419 TopoDS_Vertex cvertex;
4420 aBuilder.MakeVertex(cvertex, pntProj, Precision::Confusion());
4421 // Bind new cutting vertex
4422 NodeCuttingVertex.Bind(node,cvertex);
4423 // Insert cutting vertex in the sequences
4424 Standard_Real parProj = arrPara(index);
4425 for (j = 2; j <= seqPara.Length(); j++) {
4426 if (parProj <= seqPara.Value(j)) {
4427 seqVert.InsertBefore(j,cvertex);
4428 seqPara.InsertBefore(j,parProj);
4429 seqDist.InsertBefore(j,disProj);
4430 seqPnt.InsertBefore (j,pntProj);
4437 // filling map for cutting nodes
4438 TopTools_DataMapIteratorOfDataMapOfShapeShape mit(NodeCuttingVertex);
4439 for (; mit.More(); mit.Next()) {
4440 TopoDS_Shape cnode = mit.Value();
4441 // Skip secondary nodes
4442 if (cnode.IsNull()) continue;
4443 // Obtain vertex node
4444 TopoDS_Shape node = mit.Key();
4445 if (myVertexNode.Contains(cnode)) {
4446 // This is an end vertex
4447 cnode = myVertexNode.FindFromKey(cnode);
4450 // Create link: cutting vertex -> node
4451 TopTools_ListOfShape ls;
4453 myCuttingNode.Bind(cnode,ls);
4455 // Create link: node -> cutting vertex
4456 if (myCuttingNode.IsBound(node)) {
4457 myCuttingNode.ChangeFind(node).Append(cnode);
4460 TopTools_ListOfShape ls;
4462 myCuttingNode.Bind(node,ls);
4466 // Remove two initial vertices
4467 seqVert.Remove(1); seqVert.Remove(seqVert.Length());
4468 seqPara.Remove(1); seqPara.Remove(seqPara.Length());
4471 //=======================================================================
4472 //function : CreateSections
4473 //purpose : internal use
4474 //=======================================================================
4476 void BRepBuilderAPI_Sewing::CreateSections(const TopoDS_Shape& section,
4477 const TopTools_SequenceOfShape& seqNode,
4478 const TColStd_SequenceOfReal& seqPara,
4479 TopTools_ListOfShape& listEdge)
4481 const TopoDS_Edge& sec = TopoDS::Edge(section);
4482 // TopAbs_Orientation aInitOr = sec.Orientation();
4485 //To keep NM vertices on edge
4486 TopTools_SequenceOfShape aSeqNMVert;
4487 TColStd_SequenceOfReal aSeqNMPars;
4488 findNMVertices(sec,aSeqNMVert,aSeqNMPars);
4490 BRep_Builder aBuilder;
4492 Standard_Real first, last;
4493 BRep_Tool::Range(sec, first, last);
4495 // Create cutting sections
4496 Standard_Real par1, par2;
4497 TopoDS_Shape V1, V2;
4498 Standard_Integer i, len = seqPara.Length() + 1;
4499 for (i = 1; i <= len; i++) {
4501 TopoDS_Edge edge = sec;
4507 V1 = TopExp::FirstVertex(sec);
4510 else if (i == len) {
4511 par1 = seqPara(i-1);
4514 V2 = TopExp::LastVertex(sec);
4517 par1 = seqPara(i-1);
4523 TopoDS_Shape aTmpShape = edge.Oriented(TopAbs_FORWARD);
4524 TopoDS_Edge aTmpEdge = TopoDS::Edge (aTmpShape); // for porting
4525 aTmpShape = V1.Oriented(TopAbs_FORWARD);
4526 aBuilder.Add(aTmpEdge, aTmpShape);
4527 aTmpShape = V2.Oriented(TopAbs_REVERSED);
4528 aBuilder.Add(aTmpEdge, aTmpShape);
4529 aBuilder.Range(aTmpEdge, par1, par2);
4530 // if(aInitOr == TopAbs_REVERSED)
4531 // listEdge.Prepend(edge);
4534 Standard_Integer k =1;
4535 for( ; k <= aSeqNMPars.Length() ; k++) {
4536 Standard_Real apar = aSeqNMPars.Value(k);
4537 if(apar >= par1 && apar <= par2) {
4538 aBuilder.Add(aTmpEdge,aSeqNMVert.Value(k));
4539 aSeqNMVert.Remove(k);
4540 aSeqNMPars.Remove(k);
4544 listEdge.Append(edge);
4547 const TopTools_ListOfShape& listFaces = myBoundFaces.FindFromKey(sec);
4548 if (!listFaces.Extent()) return;
4550 Standard_Real tolEdge = BRep_Tool::Tolerance(sec);
4552 // Add cutting pcurves
4553 TopTools_ListIteratorOfListOfShape itf(listFaces);
4554 for (; itf.More(); itf.Next()) {
4556 const TopoDS_Face& fac = TopoDS::Face(itf.Value());
4558 // Retrieve curve on surface
4559 Standard_Real first2d=0., last2d=0.,first2d1=0,last2d1=0.;
4560 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(sec, fac, first2d, last2d);
4561 if (c2d.IsNull()) continue;
4562 Handle(Geom2d_Curve) c2d1;
4563 Standard_Boolean isSeam = BRep_Tool::IsClosed(sec,fac);
4565 //gka - Convert to BSpline was commented because
4566 //it is not necessary to create BSpline instead of Lines or cIrcles.
4567 //Besides after conversion circles to BSpline
4568 //it is necessary to recompute parameters of cutting because paramerization of created
4569 //BSpline curve differs from parametrization of circle.
4571 // Convert pcurve to BSpline
4572 /*Handle(Geom2d_BSplineCurve) c2dBSP,c2dBSP1;
4573 if (c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
4574 c2dBSP = Handle(Geom2d_BSplineCurve)::DownCast(c2d);
4577 if (first > (c2d->FirstParameter() + Precision::PConfusion()) ||
4578 last < (c2d->LastParameter() - Precision::PConfusion())) {
4579 Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d, first, last);
4580 c2dBSP = Geom2dConvert::CurveToBSplineCurve(TC);
4582 else c2dBSP = Geom2dConvert::CurveToBSplineCurve(c2d);
4584 if (c2dBSP.IsNull()) continue;*/
4585 //gka fix for bug OCC12203 21.04.06 addition second curve for seam edges
4589 TopoDS_Edge secRev = TopoDS::Edge(sec.Reversed());
4591 c2d1 = BRep_Tool::CurveOnSurface(secRev, fac, first2d1, last2d1);
4592 if (c2d1.IsNull()) continue;
4594 /*if (c2d1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
4595 c2dBSP1 = Handle(Geom2d_BSplineCurve)::DownCast(c2d1);
4598 if (first > (c2d1->FirstParameter() + Precision::PConfusion()) ||
4599 last < (c2d1->LastParameter() - Precision::PConfusion())) {
4600 Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d1, first, last);
4601 //c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(TC);
4603 //else c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(c2d);
4608 /*first2d = c2dBSP->FirstParameter();
4609 last2d = c2dBSP->LastParameter();
4611 if(!c2dBSP1.IsNull()) {
4612 first2d1 = c2dBSP1->FirstParameter();
4613 last2d1 = c2dBSP1->LastParameter();
4616 // Update cutting sections
4617 Handle(Geom2d_Curve) c2dNew,c2d1New;
4618 TopTools_ListIteratorOfListOfShape ite(listEdge);
4619 for (; ite.More(); ite.Next()) {
4621 // Retrieve cutting section
4622 const TopoDS_Edge& edge = TopoDS::Edge(ite.Value());
4623 BRep_Tool::Range(edge, par1, par2);
4625 // Cut BSpline pcurve
4627 c2dNew = Handle(Geom2d_Curve)::DownCast(c2d->Copy());
4628 //c2dNew = Handle(Geom2d_Curve)::DownCast(c2dBSP->Copy());
4629 //Handle(Geom2d_BSplineCurve)::DownCast(c2dNew)->Segment(Max(first2d,par1),Min(par2,last2d));
4630 if(!c2d1.IsNull()) { //if(!c2dBSP1.IsNull()) {
4631 c2d1New = Handle(Geom2d_Curve)::DownCast(c2d1->Copy());
4632 //c2d1New = Handle(Geom2d_Curve)::DownCast(c2dBSP1->Copy());
4633 //Handle(Geom2d_BSplineCurve)::DownCast(c2d1New)->Segment(Max(first2d1,par1),Min(par2,last2d1));
4636 /*catch (Standard_Failure) {
4638 cout << "Exception in CreateSections: segment [" << par1 << "," << par2 << "]: ";
4639 Standard_Failure::Caught()->Print(cout); cout << endl;
4641 Handle(Geom2d_TrimmedCurve) c2dT = new Geom2d_TrimmedCurve(c2dNew,Max(first2d,par1),Min(par2,last2d));
4646 if(!isSeam && c2d1New.IsNull())
4647 aBuilder.UpdateEdge(edge, c2dNew, fac, tolEdge);
4649 TopAbs_Orientation Ori = edge.Orientation();
4650 if(fac.Orientation() == TopAbs_REVERSED)
4651 Ori = TopAbs::Reverse(Ori);
4653 if(Ori == TopAbs_FORWARD)
4654 aBuilder.UpdateEdge(edge, c2dNew,c2d1New ,fac, tolEdge);
4656 aBuilder.UpdateEdge(edge, c2d1New,c2dNew ,fac, tolEdge);
4662 //=======================================================================
4663 //function : SameParameterShape
4665 //=======================================================================
4667 void BRepBuilderAPI_Sewing::SameParameterShape()
4669 if (!mySameParameterMode) return;
4670 TopExp_Explorer exp(mySewedShape, TopAbs_EDGE);
4671 // Le flag sameparameter est a false pour chaque edge cousue
4672 for (; exp.More(); exp.Next()) {
4673 const TopoDS_Edge& sec = TopoDS::Edge(exp.Current());
4676 BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec));
4678 catch (Standard_Failure) {
4680 cout << "Fail: BRepBuilderAPI_Sewing::SameParameterShape exception in BRepLib::SameParameter" << endl;
4687 //=======================================================================
4688 //function : Inspect
4689 //purpose : Used for selection and storage of coinciding points
4690 //=======================================================================
4692 NCollection_CellFilter_Action BRepBuilderAPI_VertexInspector::Inspect (const Standard_Integer theTarget)
4694 /*gp_Pnt aPnt = gp_Pnt (myPoints.Value (theTarget - 1));
4695 if (aPnt.SquareDistance (gp_Pnt (myCurrent)) <= myTol)
4696 myResInd.Append (theTarget);*/
4698 const gp_XYZ& aPnt = myPoints.Value (theTarget - 1);
4699 Standard_Real aDx, aDy, aDz;
4700 aDx = myCurrent.X() - aPnt.X();
4701 aDy = myCurrent.Y() - aPnt.Y();
4702 aDz = myCurrent.Z() - aPnt.Z();
4704 if ((aDx*aDx <= myTol) && (aDy*aDy <= myTol) && (aDz*aDz <= myTol))
4705 myResInd.Append (theTarget);
4706 return CellFilter_Keep;