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>
112 static void SortBox (const Handle(Bnd_HArray1OfBox) hSetBoxes,
114 TColStd_ListOfInteger& listIndex)
116 Standard_Integer i, nbBoxes = hSetBoxes->Length();
117 for (i = 1; i <= nbBoxes; i++)
118 if (!aBox.IsOut(hSetBoxes->Value(i)))
122 //=======================================================================
123 //function : SameRange
125 //=======================================================================
127 Handle(Geom2d_Curve) BRepBuilderAPI_Sewing::SameRange(const Handle(Geom2d_Curve)& CurvePtr,
128 const Standard_Real FirstOnCurve,
129 const Standard_Real LastOnCurve,
130 const Standard_Real RequestedFirst,
131 const Standard_Real RequestedLast) const
133 Handle(Geom2d_Curve) NewCurvePtr;
136 GeomLib::SameRange(Precision::PConfusion(),CurvePtr,FirstOnCurve,LastOnCurve,
137 RequestedFirst,RequestedLast,NewCurvePtr);
139 catch (Standard_Failure) {
141 cout << "Exception in BRepBuilderAPI_Sewing::SameRange: ";
142 Standard_Failure::Caught()->Print(cout); cout << endl;
148 //=======================================================================
149 //function : WhichFace
150 //purpose : Give the face whose edge is the border
151 //=======================================================================
153 TopoDS_Face BRepBuilderAPI_Sewing::WhichFace(const TopoDS_Edge& theEdg, const Standard_Integer index) const
155 TopoDS_Shape bound = theEdg;
156 if (mySectionBound.IsBound(bound)) bound = mySectionBound(bound);
157 if (myBoundFaces.Contains(bound)) {
158 Standard_Integer i = 1;
159 TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bound));
160 for (; itf.More(); itf.Next(), i++)
161 if (i == index) return TopoDS::Face(itf.Value());
163 return TopoDS_Face();
166 //=======================================================================
167 //function : IsClosedShape
169 //=======================================================================
171 static Standard_Boolean IsClosedShape(const TopoDS_Shape& theshape,
172 const TopoDS_Shape& v1, const TopoDS_Shape& v2)
174 Standard_Real TotLength = 0.0;
175 TopExp_Explorer aexp;
176 for (aexp.Init(theshape,TopAbs_EDGE); aexp.More(); aexp.Next()) {
177 TopoDS_Edge aedge = TopoDS::Edge(aexp.Current());
178 if (aedge.IsNull()) continue;
179 TopoDS_Vertex ve1,ve2;
180 TopExp::Vertices(aedge,ve1,ve2);
181 if (!ve1.IsSame(v1) && !ve1.IsSame(v2)) continue;
182 if (BRep_Tool::Degenerated(aedge)) continue;
183 Standard_Real first,last;
184 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aedge), first, last);
186 GeomAdaptor_Curve cAdapt(c3d);
187 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
189 if (ve2.IsSame(v1) || ve2.IsSame(v2)) break;
192 if (TotLength > 0.0) {
193 gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(v1));
194 gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(v2));
195 return (p1.Distance(p2) < TotLength/(1.2 * PI));
197 return Standard_False;
200 //=======================================================================
201 //function : IsClosedByIsos
203 //=======================================================================
204 static Standard_Boolean IsClosedByIsos(const Handle(Geom_Surface)& thesurf,
205 const Handle(Geom2d_Curve)& acrv2d,
206 const Standard_Real f2d,
207 const Standard_Real l2d,
208 const Standard_Boolean isUIsos)
210 Standard_Boolean isClosed = Standard_False;
212 gp_Pnt2d psurf1 = (acrv2d->IsPeriodic() ?
213 acrv2d->Value(f2d) : acrv2d->Value(Max(f2d,acrv2d->FirstParameter())));
214 gp_Pnt2d psurf2 = (acrv2d->IsPeriodic() ?
215 acrv2d->Value(l2d) : acrv2d->Value(Min(l2d,acrv2d->LastParameter())));
216 Handle(Geom_Curve) aCrv1;
217 Handle(Geom_Curve) aCrv2;
219 aCrv1 = thesurf->UIso(psurf1.X());
220 aCrv2 = thesurf->UIso(psurf2.X());
223 aCrv1 = thesurf->VIso(psurf1.Y());
224 aCrv2 = thesurf->VIso(psurf2.Y());
226 gp_Pnt p11,p1m,p12,p21,p2m,p22;
227 Standard_Real af1 = aCrv1->FirstParameter();
228 Standard_Real al1 = aCrv1->LastParameter();
229 Standard_Real af2 = aCrv2->FirstParameter();
230 Standard_Real al2 = aCrv2->LastParameter();
232 aCrv1->D0((af1+al1)*0.5,p1m);
235 aCrv2->D0((af2+al2)*0.5,p2m);
237 isClosed = (((p11.XYZ() - p12.XYZ()).Modulus() <
238 (p11.XYZ() - p1m.XYZ()).Modulus() - Precision::Confusion()) &&
239 ((p21.XYZ() - p22.XYZ()).Modulus() <
240 (p21.XYZ() - p2m.XYZ()).Modulus() - Precision::Confusion())) ;
243 //=======================================================================
244 //function : IsUClosedSurface
246 //=======================================================================
248 Standard_Boolean BRepBuilderAPI_Sewing::IsUClosedSurface(const Handle(Geom_Surface)& surf,
249 const TopoDS_Shape& theEdge,
250 const TopLoc_Location& theloc) const
252 Handle(Geom_Surface) tmpsurf = surf;
253 if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
254 tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
255 else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
256 tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
258 Standard_Boolean isClosed = tmpsurf->IsUClosed();
260 Standard_Real f2d, l2d;
261 Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
263 isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_False );
268 return IsUClosedSurface(tmpsurf,theEdge,theloc);
269 //return surf->IsUClosed();
272 //=======================================================================
273 //function : IsVClosedSurface
275 //=======================================================================
277 Standard_Boolean BRepBuilderAPI_Sewing::IsVClosedSurface(const Handle(Geom_Surface)& surf,
278 const TopoDS_Shape& theEdge,
279 const TopLoc_Location& theloc) const
281 Handle(Geom_Surface) tmpsurf = surf;
282 if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
283 tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
284 else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
285 tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
287 Standard_Boolean isClosed = tmpsurf->IsVClosed();
289 Standard_Real f2d, l2d;
290 Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
292 isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_True );
296 return IsVClosedSurface(tmpsurf,theEdge,theloc);
297 //return surf->IsVClosed();
300 //=======================================================================
301 //function : SameParameter
302 //purpose : internal use
303 //=======================================================================
305 void BRepBuilderAPI_Sewing::SameParameter(const TopoDS_Edge& edge) const
309 BRepLib::SameParameter(edge);
311 catch (Standard_Failure) {
313 cout << "Exception in BRepBuilderAPI_Sewing::SameParameter: ";
314 Standard_Failure::Caught()->Print(cout); cout << endl;
319 //=======================================================================
320 //function : SameParameterEdge
321 //purpose : internal use
322 // Merge the Sequence Of Section on one edge.
323 // This function keep the curve3d,curve2d,range and parametrization
324 // from the first section, and report and made sameparameter the
325 // pcurves of the other function.
326 // This function works when the are not more than two Pcurves
328 //=======================================================================
330 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Shape& edge,
331 const TopTools_SequenceOfShape& seqEdges,
332 const TColStd_SequenceOfInteger& seqForward,
333 TopTools_MapOfShape& mapMerged,
334 const Handle(BRepTools_ReShape)& locReShape)
336 // Retrieve reference section
337 TopoDS_Shape aTmpShape = myReShape->Apply(edge); //for porting
338 TopoDS_Edge Edge1 = TopoDS::Edge(aTmpShape);
339 aTmpShape = locReShape->Apply(Edge1);
340 if (locReShape != myReShape) Edge1 = TopoDS::Edge(aTmpShape);
341 Standard_Boolean isDone = Standard_False;
343 // Create data structures for temporary merged edges
344 TopTools_ListOfShape listFaces1;
345 TopTools_MapOfShape MergedFaces;
349 // Fill MergedFaces with faces of Edge1
350 TopoDS_Shape bnd1 = edge;
351 if (mySectionBound.IsBound(bnd1)) bnd1 = mySectionBound(bnd1);
352 if (myBoundFaces.Contains(bnd1)) {
353 TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bnd1));
354 for (; itf.More(); itf.Next())
355 if (MergedFaces.Add(itf.Value()))
356 listFaces1.Append(itf.Value());
361 // Create presentation edge
362 TopoDS_Vertex V1, V2;
363 TopExp::Vertices(Edge1,V1,V2);
364 if (myVertexNode.Contains(V1)) V1 = TopoDS::Vertex(myVertexNode.FindFromKey(V1));
365 if (myVertexNode.Contains(V2)) V2 = TopoDS::Vertex(myVertexNode.FindFromKey(V2));
367 TopoDS_Edge NewEdge = Edge1;
371 BRep_Builder aBuilder;
372 TopoDS_Shape anEdge = NewEdge.Oriented(TopAbs_FORWARD);
373 aBuilder.Add(anEdge,V1.Oriented(TopAbs_FORWARD));
374 aBuilder.Add(anEdge,V2.Oriented(TopAbs_REVERSED));
379 Standard_Boolean isForward = Standard_True;
381 // Merge candidate sections
382 for (Standard_Integer i = 1; i <= seqEdges.Length(); i++) {
384 // Retrieve candidate section
385 TopoDS_Shape oedge2 = seqEdges(i);
389 aTmpShape = myReShape->Apply(oedge2); //for porting
390 TopoDS_Edge Edge2 = TopoDS::Edge(aTmpShape);
391 aTmpShape = locReShape->Apply(Edge2);
392 if (locReShape != myReShape) Edge2 = TopoDS::Edge(aTmpShape);
394 // Calculate relative orientation
395 Standard_Integer Orientation = seqForward(i);
396 if (!isForward) Orientation = (Orientation? 0 : 1);
398 // Retrieve faces information for the second edge
399 TopoDS_Shape bnd2 = oedge2;
400 if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
401 if (!myBoundFaces.Contains(bnd2)) continue; // Skip floating edge
402 const TopTools_ListOfShape& listFaces2 = myBoundFaces.FindFromKey(bnd2);
404 Standard_Integer whichSec = 1; // Indicates on which edge the pCurve has been reported
405 TopoDS_Edge NewEdge = SameParameterEdge(Edge1,Edge2,listFaces1,listFaces2,Orientation,whichSec);
406 if (NewEdge.IsNull()) continue;
408 // Record faces information for the temporary merged edge
409 TopTools_ListIteratorOfListOfShape itf(listFaces2);
410 for (; itf.More(); itf.Next())
411 if (MergedFaces.Add(itf.Value()))
412 listFaces1.Append(itf.Value());
414 // Record merged section orientation
415 if (!Orientation && whichSec != 1)
416 isForward = isForward? Standard_False : Standard_True;
420 // Append actually merged edge
421 mapMerged.Add(oedge2);
422 isDone = Standard_True;
424 if (!myNonmanifold) break;
428 // Change result orientation
429 Edge1.Orientation(isForward? TopAbs_FORWARD : TopAbs_REVERSED);
431 else Edge1.Nullify();
436 //=======================================================================
437 //function : SameParameterEdge
438 //purpose : internal use
439 //=======================================================================
440 static Standard_Boolean findNMVertices(const TopoDS_Edge& theEdge,
441 TopTools_SequenceOfShape& theSeqNMVert,
442 TColStd_SequenceOfReal& theSeqPars)
444 TopoDS_Iterator aItV(theEdge,Standard_False);
445 for( ; aItV.More(); aItV.Next()) {
446 if(aItV.Value().Orientation() == TopAbs_INTERNAL ||
447 aItV.Value().Orientation() == TopAbs_EXTERNAL)
448 theSeqNMVert.Append(aItV.Value());
450 Standard_Integer nbV = theSeqNMVert.Length();
452 return Standard_False;
453 Standard_Real first, last;
454 Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,first, last);
455 GeomAdaptor_Curve GAC(c3d);
456 Extrema_ExtPC locProj;
457 locProj.Initialize(GAC, first, last);
458 gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
461 for (Standard_Integer i = 1; i <= nbV; i++) {
462 TopoDS_Vertex aV = TopoDS::Vertex(theSeqNMVert.Value(i));
463 gp_Pnt pt = BRep_Tool::Pnt(aV);
465 Standard_Real distF2 = pfirst.SquareDistance(pt);
466 Standard_Real distL2 = plast.SquareDistance(pt);
467 Standard_Real apar = (distF2 > distL2 ? last : first);
468 // Project current point on curve
470 if (locProj.IsDone() && locProj.NbExt() > 0) {
471 Standard_Real dist2Min = Min(distF2,distL2);
472 Standard_Integer ind, indMin = 0;
473 for (ind = 1; ind <= locProj.NbExt(); ind++) {
474 Standard_Real dProj2 = locProj.SquareDistance(ind);
475 if (dProj2 < dist2Min) {
476 indMin = ind; dist2Min = dProj2;
480 apar = locProj.Point(indMin).Parameter();
482 theSeqPars.Append(apar);
486 return Standard_True;
489 static inline Standard_Real ComputeToleranceVertex(const Standard_Real dist, const Standard_Real Tol1, const Standard_Real Tol2)
491 return (dist * 0.5 + Tol1 + Tol2);
494 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirst,
495 const TopoDS_Edge& edgeLast,
496 const TopTools_ListOfShape& listFacesFirst,
497 const TopTools_ListOfShape& listFacesLast,
498 const Standard_Boolean secForward,
499 Standard_Integer& whichSec,
500 const Standard_Boolean firstCall)
502 // Do not process floating edges
503 if (!listFacesFirst.Extent() || !listFacesLast.Extent()) return TopoDS_Edge();
506 TopoDS_Edge edge1, edge2;
508 // Take the longest edge as first
510 Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(TopoDS::Edge(edgeFirst), f, l);
511 GeomAdaptor_Curve cAdapt1(c3d1);
512 Standard_Real len1 = GCPnts_AbscissaPoint::Length(cAdapt1, f, l);
513 Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(TopoDS::Edge(edgeLast), f, l);
514 GeomAdaptor_Curve cAdapt2(c3d2);
515 Standard_Real len2 = GCPnts_AbscissaPoint::Length(cAdapt2, f, l);
540 Standard_Real first, last;
541 BRep_Tool::Range(edge1, first, last);
542 BRep_Builder aBuilder;
544 //To keep NM vertices on edge
545 TopTools_SequenceOfShape aSeqNMVert;
546 TColStd_SequenceOfReal aSeqNMPars;
547 findNMVertices(edge1,aSeqNMVert,aSeqNMPars);
548 findNMVertices(edge2,aSeqNMVert,aSeqNMPars);
552 aBuilder.MakeEdge(edge);
553 edge.Orientation( edge1.Orientation());
556 // Retrieve edge curve
557 TopLoc_Location loc3d;
558 Standard_Real first3d, last3d;
559 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge1, loc3d, first3d, last3d);
560 if (!loc3d.IsIdentity()) {
561 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
562 c3d->Transform(loc3d.Transformation());
564 aBuilder.UpdateEdge(edge,c3d,BRep_Tool::Tolerance(edge1));
565 aBuilder.Range(edge, first, last);
566 aBuilder.SameRange(edge, Standard_False); //Standard_True
567 aBuilder.SameParameter(edge, Standard_False);
568 // Create and add new vertices
570 TopoDS_Vertex V1New, V2New;
572 // Retrieve original vertices from edges
573 TopoDS_Vertex V11,V12,V21,V22;
574 TopExp::Vertices(edge1,V11,V12);
575 TopExp::Vertices(edge2,V21,V22);
577 // Check that edges are merged correctly (for edges having length less than specified tolerance)
580 if( V11.IsSame(V22) || V12.IsSame(V21) )
581 return TopoDS_Edge();
585 if( V11.IsSame(V21) || V12.IsSame(V22) )
586 return TopoDS_Edge();
589 //szv: do not reshape here!!!
590 //V11 = TopoDS::Vertex(myReShape->Apply(V11));
591 //V12 = TopoDS::Vertex(myReShape->Apply(V12));
592 //V21 = TopoDS::Vertex(myReShape->Apply(V21));
593 //V22 = TopoDS::Vertex(myReShape->Apply(V22));
595 gp_Pnt p11 = BRep_Tool::Pnt(V11);
596 gp_Pnt p12 = BRep_Tool::Pnt(V12);
597 gp_Pnt p21 = BRep_Tool::Pnt(V21);
598 gp_Pnt p22 = BRep_Tool::Pnt(V22);
600 // Check if edges are closed
601 Standard_Boolean isClosed1 = V11.IsSame(V12);
602 Standard_Boolean isClosed2 = V21.IsSame(V22);
604 //Standard_Boolean isRev = Standard_False;
606 Standard_Real Tol1 = 0.;
607 if (isClosed1 || isClosed2) {
608 // at least one of the edges is closed
609 if (isClosed1 && isClosed2) {
610 // both edges are closed
611 pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ()));
612 gp_Vec v1 = p21.XYZ() - p11.XYZ();
613 Standard_Real d1 = v1.Magnitude();
614 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21));
615 //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p21));
617 else if (isClosed1) {
618 // only first edge is closed
619 gp_XYZ pt =0.5*(p21.XYZ()+ p22.XYZ());
620 pfirst.SetXYZ(0.5*(p11.XYZ() + pt));
621 gp_Vec v1 = p22.XYZ() - p21.XYZ();
622 Standard_Real d1 = v1.Magnitude();
623 Tol1= ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V22),BRep_Tool::Tolerance(V21));
624 gp_Vec v2 = p11.XYZ() - pt;
625 Standard_Real d2 = v2.Magnitude();
626 Tol1= ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V11));
627 //Tol1 = Max(pfirst.Distance(p21),pfirst.Distance(p22));
628 //Tol1 = Max(pfirst.Distance(p11),Tol1);
631 // only second edge is closed
632 gp_XYZ pt = 0.5*(p11.XYZ()+ p12.XYZ());
633 pfirst.SetXYZ(0.5*(p21.XYZ() + pt));
634 gp_Vec v1 = p11.XYZ() - p12.XYZ();
635 Standard_Real d1 = v1.Magnitude();
636 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V12));
637 gp_Vec v2 = p21.XYZ() - pt;
638 Standard_Real d2 = v2.Magnitude();
639 Tol1 = ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V21));
640 //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p12));
641 //Tol1 = Max(pfirst.Distance(p21),Tol1);
643 aBuilder.MakeVertex(V1New,pfirst,Tol1);
647 // both edges are open
649 Standard_Real Tol2 = 0.;
651 pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ()));
652 plast.SetXYZ(0.5*(p12.XYZ() + p22.XYZ()));
653 gp_Vec v1 = p21.XYZ() - p11.XYZ();
654 Standard_Real d1 = v1.Magnitude();
655 gp_Vec v2 = p22.XYZ() - p12.XYZ();
656 Standard_Real d2 = v2.Magnitude();
657 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21));
658 Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V22));
660 // Tol1 = Max(Max(pfirst.Distance(p11),pfirst.Distance(p21)),
661 // Max(BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21)));
662 // Tol2 = Max(Max(plast.Distance(p12),plast.Distance(p22)),
663 // Max(BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V22)));
666 pfirst.SetXYZ(0.5*(p11.XYZ() + p22.XYZ()));
667 plast.SetXYZ(0.5*(p12.XYZ() + p21.XYZ()));
669 gp_Vec v1 = p22.XYZ() - p11.XYZ();
670 Standard_Real d1 = v1.Magnitude();
671 gp_Vec v2 = p21.XYZ() - p12.XYZ();
672 Standard_Real d2 = v2.Magnitude();
673 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V22));
674 Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V21));
675 // Tol1 = Max(Max(pfirst.Distance(p11),pfirst.Distance(p22)),
676 // Max(BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V22)));
677 // Tol2 = Max(Max(plast.Distance(p12),plast.Distance(p21)),
678 // Max(BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V21)));
681 ///c3d->D0(first3d,pcu);
682 //Tol1 = Max(pfirst.Distance(pcu) + Max(BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V22));
683 aBuilder.MakeVertex(V1New,pfirst,Tol1);
684 //c3d->D0(last3d,pcu);
685 //Tol2 = plast.Distance(pcu);
686 aBuilder.MakeVertex(V2New,plast,Tol2);
689 // Add the vertices in the good sense
690 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
691 TopoDS_Shape aLocalEdge = V1New.Oriented(TopAbs_FORWARD); //(listNode.First()).Oriented(TopAbs_FORWARD);
692 aBuilder.Add(anEdge,aLocalEdge);
693 aLocalEdge = V2New.Oriented(TopAbs_REVERSED); //(listNode.Last()).Oriented(TopAbs_REVERSED);
694 aBuilder.Add(anEdge,aLocalEdge);
696 Standard_Integer k =1;
697 for( ; k <= aSeqNMVert.Length(); k++)
698 aBuilder.Add(anEdge,aSeqNMVert.Value(k));
702 // Retrieve second PCurves
703 TopLoc_Location loc2;
704 Handle(Geom_Surface) surf2;
705 //Handle(Geom2d_Curve) c2d2, c2d21;
706 // Standard_Real firstOld, lastOld;
708 TopTools_ListIteratorOfListOfShape itf2;
709 if (whichSec == 1) itf2.Initialize(listFacesLast);
710 else itf2.Initialize(listFacesFirst);
711 Standard_Boolean isResEdge = Standard_False;
712 for (; itf2.More(); itf2.Next()) {
713 Handle(Geom2d_Curve) c2d2, c2d21;
714 Standard_Real firstOld, lastOld;
715 const TopoDS_Face& fac2 = TopoDS::Face(itf2.Value());
717 surf2 = BRep_Tool::Surface(fac2, loc2);
718 Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) &&
719 BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2));
721 if (!myNonmanifold) return TopoDS_Edge();
722 TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting
723 c2d21 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac2, firstOld, lastOld);
725 c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld);
726 if (c2d2.IsNull() && c2d21.IsNull()) continue;
728 if (!c2d21.IsNull()) {
729 c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy());
731 if (c2d21->IsKind(STANDARD_TYPE(Geom2d_Line)))
732 c2d21 = new Geom2d_TrimmedCurve(c2d21, firstOld, lastOld);
733 Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
734 Standard_Real last2d = lastOld; //c2dTmp->LastParameter();
735 firstOld = c2d21->ReversedParameter(last2d);
736 lastOld = c2d21->ReversedParameter(first2d);
739 c2d21 = SameRange(c2d21,firstOld,lastOld,first,last);
742 // Make second PCurve sameRange with the 3d curve
743 c2d2 = Handle(Geom2d_Curve)::DownCast(c2d2->Copy());
746 if (c2d2->IsKind(STANDARD_TYPE(Geom2d_Line)))
747 c2d2 = new Geom2d_TrimmedCurve(c2d2, firstOld, lastOld);
748 Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
749 Standard_Real last2d = lastOld; //c2dTmp->LastParameter();
750 firstOld = c2d2->ReversedParameter(last2d);
751 lastOld = c2d2->ReversedParameter(first2d);
755 c2d2 = SameRange(c2d2,firstOld,lastOld,first,last);
756 if (c2d2.IsNull()) continue;
759 Standard_Boolean isSeam = Standard_False;
760 TopAbs_Orientation Ori = TopAbs_FORWARD;
761 //Handle(Geom2d_Curve) c2d1, c2d11;
763 TopTools_ListIteratorOfListOfShape itf1;
764 if (whichSec == 1) itf1.Initialize(listFacesFirst);
765 else itf1.Initialize(listFacesLast);
766 for (; itf1.More() && !isSeam; itf1.Next()) {
767 Handle(Geom2d_Curve) c2d1, c2d11;
768 const TopoDS_Face& fac1 = TopoDS::Face(itf1.Value());
770 TopLoc_Location loc1;
771 Handle(Geom_Surface) surf1 = BRep_Tool::Surface(fac1, loc1);
772 Standard_Real first2d, last2d;
773 Standard_Boolean isSeam1 = ((IsUClosedSurface(surf1,edge1,loc1) || IsVClosedSurface(surf1,edge1,loc1)) &&
774 BRep_Tool::IsClosed(TopoDS::Edge(edge1),fac1));
775 c2d1 = BRep_Tool::CurveOnSurface(edge1, fac1, first2d, last2d);
776 Ori = edge1.Orientation();
777 if (fac1.Orientation() == TopAbs_REVERSED)
778 Ori = TopAbs::Reverse(Ori);
781 if (!myNonmanifold) return TopoDS_Edge();
782 TopoDS_Shape aTmpShape = edge1.Reversed(); //for porting
783 c2d11 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac1, first2d, last2d);
784 //if(fac1.Orientation() == TopAbs_REVERSED) //
785 if(Ori == TopAbs_FORWARD)
786 aBuilder.UpdateEdge(edge,c2d1,c2d11,fac1,0);
788 aBuilder.UpdateEdge(edge,c2d11,c2d1,fac1,0);
790 else aBuilder.UpdateEdge(edge,c2d1,fac1,0);
792 if (c2d1.IsNull() && c2d11.IsNull()) continue;
794 //Ori = edge1.Orientation();
795 //if (fac1.Orientation() == TopAbs_REVERSED) TopAbs::Reverse(Ori);
797 if (surf2 == surf1) {
798 // Merge sections which are on the same face
799 if (!loc2.IsDifferent(loc1)) {
800 Standard_Boolean uclosed = IsUClosedSurface(surf2,edge2,loc2);
801 Standard_Boolean vclosed = IsVClosedSurface(surf2,edge2,loc2);
802 if (uclosed || vclosed) {
803 Standard_Real pf = c2d1->FirstParameter();
804 // Standard_Real pl = c2d1->LastParameter();
805 gp_Pnt2d p1n = c2d1->Value(Max(first,pf));
806 // gp_Pnt2d p2n = c2d1->Value(Min(pl,last));
807 gp_Pnt2d p21n = c2d2->Value(Max(first,c2d2->FirstParameter()));
808 gp_Pnt2d p22n = c2d2->Value(Min(last,c2d2->LastParameter()));
809 Standard_Real aDist = Min(p1n.Distance(p21n), p1n.Distance(p22n));
810 Standard_Real U1, U2, V1, V2;
811 surf2->Bounds(U1, U2, V1, V2);
812 isSeam = ((uclosed && aDist > 0.75*(fabs(U2-U1))) ||
813 (vclosed && aDist > 0.75*(fabs(V2-V1))));
814 if( !isSeam && BRep_Tool::IsClosed(TopoDS::Edge(edge),fac1)) continue;
819 isResEdge = Standard_True;
821 if (Ori == TopAbs_FORWARD)
822 aBuilder.UpdateEdge(edge, c2d1, c2d2, surf2, loc2, Precision::Confusion());
824 aBuilder.UpdateEdge(edge, c2d2, c2d1, surf2, loc2, Precision::Confusion());
827 TopAbs_Orientation InitOri = edge2.Orientation();
828 TopAbs_Orientation SecOri = edge.Orientation();
829 if (fac2.Orientation() == TopAbs_REVERSED) {
831 InitOri = TopAbs::Reverse(InitOri);
832 SecOri = TopAbs::Reverse(SecOri);
835 InitOri = TopAbs::Reverse(InitOri);
837 if (InitOri == TopAbs_FORWARD)
838 aBuilder.UpdateEdge(edge, c2d2,c2d21, surf2, loc2, Precision::Confusion());
840 aBuilder.UpdateEdge(edge, c2d21,c2d2, surf2, loc2, Precision::Confusion());
843 aBuilder.UpdateEdge(edge, c2d2, surf2, loc2, Precision::Confusion());
849 // Try to make the edge sameparameter
852 // Standard_Real tolReached = BRep_Tool::Tolerance(edge);
853 //if (!BRep_Tool::SameParameter(edge)) return edge; //gka ????????
855 if (firstCall && (!BRep_Tool::SameParameter(edge) || !isResEdge)) {
856 Standard_Integer whichSecn = whichSec;
857 // Try to merge on the second section
858 Standard_Boolean second_ok = Standard_True;
859 TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast,
860 secForward,whichSecn,Standard_False);
861 //if (s_edge.IsNull()) return s_edge; // gka version for free edges
862 if (s_edge.IsNull()) second_ok = Standard_False;
863 else if (!BRep_Tool::SameParameter(s_edge)) second_ok = Standard_False;
866 whichSec = whichSecn;
871 GeomAdaptor_Curve c3dAdapt(c3d);
873 // Discretize edge curve
874 Standard_Integer i, j, nbp = 15;
875 Standard_Real deltaT = (last3d - first3d) / (nbp + 1);
876 TColgp_Array1OfPnt c3dpnt(1,nbp);
877 for (i = 1; i <= nbp; i++) c3dpnt(i) = c3dAdapt.Value(first3d + i*deltaT);
879 Standard_Real u, v, dist, maxTol = -1.0;
880 Standard_Boolean more = Standard_True;
882 for (j = 1; more; j++) {
883 Handle(Geom2d_Curve) c2d2;
884 BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j);
885 more = !c2d2.IsNull();
888 deltaT = (last - first) / (nbp + 1);
889 for (i = 1; i <= nbp; i++) {
890 c2d2->Value(first + i*deltaT).Coord(u,v);
891 dist = surf2->Value(u,v).Distance(c3dpnt(i));
892 if (dist > maxTol) maxTol = dist;
897 if (maxTol >= 0.) aBuilder.UpdateEdge(edge, maxTol);
898 aBuilder.SameParameter(edge,Standard_True);
902 BRepLib::EncodeRegularity(edge,0.01);
903 Standard_Real tolEdge1 = BRep_Tool::Tolerance(edge);
904 if (tolEdge1 > MaxTolerance()) edge.Nullify();
908 //=======================================================================
909 // function : EvaluateAngulars
910 // purpose : internal use
911 //=======================================================================
913 void BRepBuilderAPI_Sewing::EvaluateAngulars(TopTools_SequenceOfShape& sequenceSec,
914 TColStd_Array1OfBoolean& secForward,
915 TColStd_Array1OfReal& tabAng,
916 const Standard_Integer indRef) const
920 Standard_Integer i, j, npt = 4, lengSec = sequenceSec.Length();
925 Standard_Real first, last;
926 Handle(Geom_Curve) c3d;
927 Handle(Geom2d_Curve) c2d;
928 Handle(Geom_Surface) surf;
929 TColgp_Array1OfVec normRef(1,npt);
931 for (i = indRef; i <= lengSec; i++) {
933 edge = TopoDS::Edge(sequenceSec(i));
935 TopoDS_Shape bnd = edge;
936 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
937 if (myBoundFaces.Contains(bnd)) {
938 face = TopoDS::Face(myBoundFaces.FindFromKey(bnd).First());
939 surf = BRep_Tool::Surface(face,loc);
940 if (!loc.IsIdentity()) {
941 surf = Handle(Geom_Surface)::DownCast(surf->Copy());
942 surf->Transform(loc.Transformation());
944 c2d = BRep_Tool::CurveOnSurface(edge, face, first, last);
946 else if (i == indRef) return;
949 c3d = BRep_Tool::Curve(edge, loc, first, last);
950 if (!loc.IsIdentity()) {
951 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
952 c3d->Transform(loc.Transformation());
955 GeomAdaptor_Curve adapt(c3d);
956 GCPnts_UniformAbscissa uniAbs(adapt, npt, first, last);
958 Standard_Real cumulateAngular = 0.0;
959 Standard_Integer nbComputedAngle = 0;
961 for (j = 1; j <= npt; j++) {
963 c2d->D0(uniAbs.Parameter((secForward(i) || i == indRef)? j : npt-j+1),P);
966 surf->D1(P.X(), P.Y(), unused, w1, w2);
967 gp_Vec n = w1^w2; // Compute the normal vector
968 if (i == indRef) normRef(j) = n;
969 else if ((n.Magnitude()>gp::Resolution()) && (normRef(j).Magnitude()>gp::Resolution())) {
971 Standard_Real angular = n.Angle(normRef(j));
972 if (angular > PI/2.) angular = PI - angular;
973 cumulateAngular += angular;
978 tabAng(i) = cumulateAngular/((Standard_Real)nbComputedAngle);
982 //=======================================================================
983 // function : EvaluateDistances
984 // purpose : internal use
985 // Evaluate distance beetween edges with indice indRef and the following edges in the list
986 // Remarks (lengSec - indRef) must be >= 1
987 //=======================================================================
988 void BRepBuilderAPI_Sewing::EvaluateDistances(TopTools_SequenceOfShape& sequenceSec,
989 TColStd_Array1OfBoolean& secForward,
990 TColStd_Array1OfReal& tabDst,
991 TColStd_Array1OfReal& arrLen,
992 TColStd_Array1OfReal& tabMinDist,
993 const Standard_Integer indRef) const
995 secForward.Init(Standard_True);
998 tabMinDist.Init(Precision::Infinite());
999 const Standard_Integer npt = 8; // Number of points for curve discretization
1000 TColgp_Array1OfPnt ptsRef(1, npt), ptsSec(1, npt);
1002 Standard_Integer i, j, lengSec = sequenceSec.Length();
1003 TColgp_SequenceOfPnt seqSec;
1005 Handle(Geom_Curve) c3dRef;
1006 Standard_Real firstRef=0., lastRef=0.;
1007 Standard_Integer nbFound = 0;
1008 for (i = indRef; i <= lengSec; i++) {
1010 // reading of the edge (attention for the first one: reference)
1011 const TopoDS_Edge& sec = TopoDS::Edge(sequenceSec(i));
1013 TopLoc_Location loc;
1014 Standard_Real first, last;
1015 Handle(Geom_Curve) c3d = BRep_Tool::Curve(sec, loc, first, last);
1016 if (!loc.IsIdentity()) {
1017 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1018 c3d->Transform(loc.Transformation());
1022 c3dRef = c3d; firstRef = first; lastRef = last;
1025 Standard_Real dist = Precision::Infinite(), distFor = -1.0, distRev = -1.0;
1026 Standard_Real aMinDist = Precision::Infinite();
1028 Standard_Real T, deltaT = (last - first) / (npt - 1);
1029 Standard_Real aLenSec2 = 0.;
1030 Standard_Boolean isFound = (indRef == i);
1031 for (j = 1; j <= npt; j++) {
1033 // Uniform parameter on curve
1034 if (j == 1) T = first;
1035 else if (j == npt) T = last;
1036 else T = first + (j - 1) * deltaT;
1038 // Take point on curve
1039 gp_Pnt pt = c3d->Value(T);
1044 aLenSec2 += pt.SquareDistance(ptsRef(j-1));
1048 //protection to avoid merging with small sections
1050 aLenSec2 += pt.SquareDistance(ptsSec(j-1));
1051 // To evaluate mutual orientation and distance
1052 dist = pt.Distance(ptsRef(j));
1055 if (distFor < dist) distFor = dist;
1056 dist = pt.Distance(ptsRef(npt-j+1));
1060 if (distRev < dist) distRev = dist;
1062 // Check that point lays between vertices of reference curve
1063 const gp_Pnt &p11 = ptsRef(1);
1064 const gp_Pnt &p12 = ptsRef(npt);
1065 const gp_Vec aVec1(pt,p11);
1066 const gp_Vec aVec2(pt,p12);
1067 const gp_Vec aVecRef(p11,p12);
1068 if((aVecRef * aVec1) * (aVecRef * aVec2) < 0.)
1073 Standard_Real aLenSec = sqrt(aLenSec2);
1075 //if(aLenSec < myMinTolerance )
1077 arrLen.SetValue(i,aLenSec);
1078 // Record mutual orientation
1079 Standard_Boolean isForward = (distFor < distRev); //szv debug: <=
1080 secForward(i) = isForward;
1082 dist = (isForward? distFor : distRev);
1083 if(i == indRef || (dist < myTolerance && nbFound >= npt * 0.5) )
1086 tabMinDist(i) = aMinDist;
1090 nbFound = 0, aMinDist = Precision::Infinite(), dist = -1;
1091 TColgp_Array1OfPnt arrProj(1, npt);
1092 TColStd_Array1OfReal arrDist(1, npt), arrPara(1, npt);
1093 if( arrLen(indRef) >= arrLen(i))
1094 ProjectPointsOnCurve(ptsSec,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1096 ProjectPointsOnCurve(ptsRef,c3d,first,last,arrDist,arrPara,arrProj,Standard_False);
1097 for( j = 1; j <= npt; j++ )
1099 if(arrDist(j) < 0. || arrDist(j) > myTolerance)
1101 if(dist < arrDist(j))
1103 if( aMinDist > arrDist(j))
1104 aMinDist = arrDist(j);
1110 tabMinDist(i) = aMinDist;
1116 // Project distant points
1117 Standard_Integer nbFailed = seqSec.Length();
1118 if (!nbFailed) return;
1120 TColgp_Array1OfPnt arrPnt(1, nbFailed), arrProj(1, nbFailed);
1121 for (i = 1; i <= nbFailed; i++) arrPnt(i) = seqSec(i); seqSec.Clear();
1122 TColStd_Array1OfReal arrDist(1, nbFailed), arrPara(1, nbFailed);
1124 ProjectPointsOnCurve(arrPnt,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1126 // Process distant sections
1127 Standard_Integer idx1 = 1;
1128 for (i = indRef + 1; i <= lengSec; i++) {
1130 // Skip section if already evaluated
1131 if (tabDst(i) >= 0.0) continue;
1133 Standard_Real dist, distMax = -1.0, aMinDist = Precision::Infinite();
1135 Standard_Integer idx2 = (idx1 - 1)*npt;
1137 for (j = 1; j <= npt; j++) {
1139 dist = arrDist(idx2 + j);
1140 // If point is not projected - stop evaluation
1141 if (dist < 0.0) { distMax = -1.0; break; }
1142 if (distMax < dist) distMax = dist;
1143 if(aMinDist > dist) aMinDist = dist;
1146 // If section is close - record distance
1147 if (distMax >= 0.0) {
1148 if (secForward(i)) {
1149 dist = arrPnt(idx2+1).Distance(ptsRef(1));
1150 if (distMax < dist) distMax = dist;
1151 if(aMinDist > dist) aMinDist = dist;
1152 dist = arrPnt(idx2+npt).Distance(ptsRef(npt));
1153 if (distMax < dist) distMax = dist;
1154 if(aMinDist > dist) aMinDist = dist;
1157 dist = arrPnt(idx2+1).Distance(ptsRef(npt));
1158 if (distMax < dist) distMax = dist;
1159 if(aMinDist > dist) aMinDist = dist;
1160 dist = arrPnt(idx2+npt).Distance(ptsRef(1));
1161 if (distMax < dist) distMax = dist;
1162 if(aMinDist > dist) aMinDist = dist;
1165 if (distMax < myTolerance)
1167 tabDst(i) = distMax;
1168 tabMinDist(i) = aMinDist;
1172 idx1++; // To the next distant curve
1176 //=======================================================================
1177 //function : IsMergedClosed
1178 //purpose : internal use
1179 //=======================================================================
1181 Standard_Boolean BRepBuilderAPI_Sewing::IsMergedClosed(const TopoDS_Edge& Edge1,
1182 const TopoDS_Edge& Edge2,
1183 const TopoDS_Face& face) const
1185 // Check for closed surface
1186 TopLoc_Location loc;
1187 Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc);
1188 Standard_Boolean isUClosed = IsUClosedSurface(surf,Edge1,loc);
1189 Standard_Boolean isVClosed = IsVClosedSurface(surf,Edge1,loc);
1190 if (!isUClosed && !isVClosed) return Standard_False;
1191 // Check condition on closed surface
1193 Standard_Real first1,last1,first2,last2;
1194 Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(Edge1,first1,last1);
1195 Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(Edge2,first2,last2);
1196 if (C3d1.IsNull() || C3d2.IsNull()) return Standard_False;
1198 Standard_Real first2d1,last2d1,first2d2,last2d2;
1199 Handle(Geom2d_Curve) C2d1 = BRep_Tool::CurveOnSurface(Edge1,face,first2d1,last2d1);
1200 Handle(Geom2d_Curve) C2d2 = BRep_Tool::CurveOnSurface(Edge2,face,first2d2,last2d2);
1201 if (C2d1.IsNull() || C2d2.IsNull()) return Standard_False;
1203 gp_Pnt p1 = C3d1->Value(0.5*(first1 + last1));
1204 gp_Pnt p2 = C3d1->Value(0.5*(first2 + last2));
1205 Standard_Real dist = p1.Distance(p2);
1206 gp_Pnt2d p12d = C2d1->Value(0.5*(first2d1 + last2d1));
1207 gp_Pnt2d p22d = C2d1->Value(0.5*(first2d2 + last2d2));
1208 Standard_Real dist2d = p12d.Distance(p22d);
1209 GeomAdaptor_Surface Ads(BRep_Tool::Surface(face));
1210 Standard_Real distSurf = Max(Ads.UResolution(dist), Ads.VResolution(dist));
1211 return (dist2d*0.2 >= distSurf);
1213 Standard_Integer isULongC1, isULongC2, isVLongC1, isVLongC2;
1214 Standard_Real SUmin, SUmax, SVmin, SVmax;
1215 Standard_Real C1Umin, C1Vmin, C1Umax, C1Vmax;
1216 Standard_Real C2Umin, C2Vmin, C2Umax, C2Vmax;
1217 { //szv: Use brackets to destroy local variables
1219 Geom2dAdaptor_Curve aC2d1(C2d1), aC2d2(C2d2);
1220 BndLib_Add2dCurve::Add(aC2d1,first2d1,last2d1,Precision::PConfusion(),B1);
1221 BndLib_Add2dCurve::Add(aC2d2,first2d2,last2d2,Precision::PConfusion(),B2);
1222 B1.Get(C1Umin,C1Vmin,C1Umax,C1Vmax);
1223 B2.Get(C2Umin,C2Vmin,C2Umax,C2Vmax);
1224 Standard_Real du, dv;
1225 du = (C1Umax - C1Umin); dv = (C1Vmax - C1Vmin);
1226 isULongC1 = (dv <= du); isVLongC1 = (du <= dv);
1227 du = (C2Umax - C2Umin); dv = (C2Vmax - C2Vmin);
1228 isULongC2 = (dv <= du); isVLongC2 = (du <= dv);
1229 surf->Bounds(SUmin,SUmax,SVmin,SVmax);
1231 if (isUClosed && isVLongC1 && isVLongC2) {
1232 // Do not merge if not overlapped by V
1233 Standard_Real dist = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1235 Standard_Real distInner = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1236 Standard_Real distOuter = (SUmax - SUmin) - Max((C2Umax - C1Umin),(C1Umax - C2Umin));
1237 if (distOuter <= distInner) return Standard_True;
1240 if (isVClosed && isULongC1 && isULongC2) {
1241 // Do not merge if not overlapped by U
1242 Standard_Real dist = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1244 Standard_Real distInner = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1245 Standard_Real distOuter = (SVmax - SVmin) - Max((C2Vmax - C1Vmin),(C1Vmax - C2Vmin));
1246 if (distOuter <= distInner) return Standard_True;
1249 return Standard_False;
1252 //=======================================================================
1253 //function : AnalysisNearestEdges
1255 //=======================================================================
1257 void BRepBuilderAPI_Sewing::AnalysisNearestEdges(const TopTools_SequenceOfShape& sequenceSec,
1258 TColStd_SequenceOfInteger& seqIndCandidate,
1259 TColStd_SequenceOfInteger& seqOrientations,
1260 const Standard_Boolean evalDist)
1263 Standard_Integer workIndex = seqIndCandidate.First();
1264 TopoDS_Shape workedge = sequenceSec.Value(workIndex);
1265 TopoDS_Shape bnd = workedge;
1266 TopTools_ListOfShape workfaces;
1267 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1268 if (myBoundFaces.Contains(bnd))
1269 workfaces = myBoundFaces.FindFromKey(bnd);
1270 if(workfaces.IsEmpty()) return;
1271 TopTools_MapOfShape mapFaces;
1272 TopTools_ListIteratorOfListOfShape lIt;
1273 for (lIt.Initialize(workfaces); lIt.More(); lIt.Next())
1274 mapFaces.Add(lIt.Value());
1275 TColStd_SequenceOfInteger seqNotCandidate;
1276 TColStd_SequenceOfInteger seqNewForward;
1277 // Separates edges belonging the same face as work edge
1278 // for exception of edges belonging closed faces
1280 seqNotCandidate.Append(workIndex);
1281 for(Standard_Integer i = 1; i<= seqIndCandidate.Length(); ) {
1282 Standard_Integer index = seqIndCandidate.Value(i);
1283 Standard_Boolean isRemove = Standard_False;
1284 if(index == workIndex) {
1285 seqIndCandidate.Remove(i);
1286 seqOrientations.Remove(i);
1287 isRemove = Standard_True;
1290 TopoDS_Shape bnd2 = sequenceSec.Value(index);
1291 if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
1293 if(myBoundFaces.Contains(bnd2)) {
1294 const TopTools_ListOfShape& listfaces = myBoundFaces.FindFromKey(bnd2);
1295 Standard_Boolean isMerged = Standard_True;
1296 for (lIt.Initialize(listfaces); lIt.More() && isMerged; lIt.Next()) {
1297 if(mapFaces.Contains(lIt.Value())) {
1298 TopLoc_Location loc;
1299 Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(lIt.Value()),loc);
1300 isMerged = ((IsUClosedSurface(surf,bnd2,loc) || IsVClosedSurface(surf,bnd2,loc)) &&
1301 IsMergedClosed(TopoDS::Edge(sequenceSec.Value(index)),TopoDS::Edge(workedge),TopoDS::Face(lIt.Value())));
1305 seqNotCandidate.Append(index);
1306 seqIndCandidate.Remove(i);
1307 seqOrientations.Remove(i);
1308 isRemove = Standard_True;
1312 seqIndCandidate.Remove(i);
1313 seqOrientations.Remove(i);
1314 isRemove = Standard_True;
1319 if(seqIndCandidate.Length() == 0 || seqNotCandidate.Length() == 1) return;
1320 if(!evalDist) return;
1321 TColStd_Array2OfReal TotTabDist(1,seqNotCandidate.Length(),1,seqIndCandidate.Length());
1322 TColStd_MapOfInteger MapIndex;
1323 TColStd_SequenceOfInteger seqForward;
1325 // Definition and removing edges wich are not candidate for work edge
1326 // ( they have other nearest edges belonging to the work face)
1327 for(Standard_Integer k = 1; k<= seqNotCandidate.Length(); k++) {
1328 Standard_Integer index1 = seqNotCandidate.Value(k);
1329 TopoDS_Shape edge = sequenceSec.Value(index1);
1330 TopTools_SequenceOfShape tmpSeq;
1331 tmpSeq.Append(edge);
1332 for(Standard_Integer kk = 1; kk <= seqIndCandidate.Length();kk++)
1333 tmpSeq.Append(sequenceSec.Value(seqIndCandidate.Value(kk)));
1335 Standard_Integer lengSec = tmpSeq.Length();
1336 TColStd_Array1OfBoolean tabForward(1,lengSec);
1337 TColStd_Array1OfReal tabDist(1,lengSec);
1338 TColStd_Array1OfReal arrLen(1,lengSec);
1339 TColStd_Array1OfReal tabMinDist(1,lengSec);
1340 for (Standard_Integer i1 = 1 ; i1 <= lengSec; i1++)
1343 EvaluateDistances(tmpSeq,tabForward, tabDist,arrLen,tabMinDist,1 );
1345 for(Standard_Integer n = 1; n < lengSec; n++) {
1346 if(tabDist(n+1) == -1 || tabDist(n+1) > myTolerance) {
1350 TotTabDist(k,n) = tabDist(n+1 );
1351 seqForward.Append(tabForward(n+1) ? 1:0);
1355 for(Standard_Integer n = 1; n < lengSec; n++) {
1356 if(tabDist(n) == -1 || tabDist(n) > myTolerance) continue;
1357 if(tabDist(n+1) < TotTabDist(1,n)) {
1365 Standard_Integer i2 = seqIndCandidate.Length();
1366 for( ; i2 >=1 ; i2--)
1368 if(MapIndex.Contains(i2))
1370 seqIndCandidate.Remove(i2);
1371 seqOrientations.Remove(i2);
1375 //for(TColStd_MapIteratorOfMapOfInteger IMap(MapIndex); IMap.More(); IMap.Next()) {
1376 // seqIndCandidate.Remove(IMap.Key());
1377 // seqOrientations.Remove(IMap.Key());
1381 //=======================================================================
1382 //function : FindCandidates
1383 //purpose : internal use
1384 //=======================================================================
1386 Standard_Boolean BRepBuilderAPI_Sewing::FindCandidates(TopTools_SequenceOfShape& seqSections,
1387 TColStd_IndexedMapOfInteger& mapReference,
1388 TColStd_SequenceOfInteger& seqCandidates,
1389 TColStd_SequenceOfInteger& seqOrientations)
1391 Standard_Integer i, nbSections = seqSections.Length();
1393 return Standard_False;
1394 // Retrieve last reference index
1395 Standard_Integer indReference = mapReference(mapReference.Extent());
1396 Standard_Integer nbCandidates = 0;
1397 TopTools_MapOfShape Faces1;
1398 //if (nbSections > 1) {
1400 TopoDS_Edge Edge1 = TopoDS::Edge(seqSections(indReference));
1402 // Retrieve faces for reference section
1404 { //szv: Use brackets to destroy local variables
1405 TopoDS_Shape bnd = Edge1;
1406 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1407 if (myBoundFaces.Contains(bnd)) {
1408 TopTools_ListIteratorOfListOfShape itf1(myBoundFaces.FindFromKey(bnd));
1409 for (; itf1.More(); itf1.Next()) Faces1.Add(itf1.Value());
1413 // Check merging conditions for candidates and remove unsatisfactory
1414 TopTools_SequenceOfShape seqSectionsNew;
1415 TColStd_SequenceOfInteger seqCandidatesNew;
1416 for (i = 1; i <= nbSections; i++) {
1417 if (i == indReference) {
1418 seqSectionsNew.Prepend(Edge1);
1419 seqCandidatesNew.Prepend(i);
1422 const TopoDS_Edge& Edge2 = TopoDS::Edge(seqSections(i));
1424 seqSectionsNew.Append(Edge2);
1425 seqCandidatesNew.Append(i);
1426 /*TopoDS_Shape bnd = Edge2;
1427 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1429 if (myBoundFaces.Contains(bnd)) {
1430 Standard_Boolean isOK = Standard_True;
1431 TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1432 for (; itf2.More() && isOK; itf2.Next()) {
1433 const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1434 // Check whether condition is satisfied
1435 isOK = !Faces1.Contains(Face2);
1436 if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1439 seqSectionsNew.Append(Edge2);
1440 seqCandidatesNew.Append(i);
1446 Standard_Integer nbSectionsNew = seqSectionsNew.Length();
1447 if (nbSectionsNew > 1) {
1449 // Evaluate distances between reference and other sections
1450 TColStd_Array1OfBoolean arrForward(1,nbSectionsNew);
1451 TColStd_Array1OfReal arrDistance(1,nbSectionsNew);
1452 TColStd_Array1OfReal arrLen(1,nbSectionsNew);
1453 TColStd_Array1OfReal arrMinDist(1,nbSectionsNew);
1454 EvaluateDistances(seqSectionsNew,arrForward,arrDistance,arrLen,arrMinDist,1);
1456 // Fill sequence of candidate indices sorted by distance
1457 for (i = 2; i <= nbSectionsNew; i++) {
1458 if (arrDistance(i) >= 0.0 && arrLen(i) > myMinTolerance) {
1459 // Reference section is connected to section #i
1460 Standard_Boolean isInserted = Standard_False;
1461 Standard_Integer j, ori = (arrForward(i)? 1 : 0);
1462 for (j = 1; (j <= seqCandidates.Length()) && !isInserted; j++) {
1463 Standard_Integer aInd = seqCandidates.Value(j);//debug
1464 Standard_Real aDelta = arrDistance(i) - arrDistance(seqCandidates.Value(j));
1465 //if (arrDistance(i) <= arrDistance(seqCandidates.Value(j))) {
1466 if( aDelta < Precision::Confusion()) {
1468 if(fabs(aDelta) > RealSmall() ||
1469 arrMinDist(i) < arrMinDist(seqCandidates.Value(j)))
1471 seqCandidates.InsertBefore(j,i);
1472 seqOrientations.InsertBefore(j,ori);
1473 isInserted = Standard_True;
1478 seqCandidates.Append(i);
1479 seqOrientations.Append(ori);
1484 // Replace candidate indices
1485 nbCandidates = seqCandidates.Length();
1486 for (i = 1; i <= nbCandidates; i++)
1487 seqCandidates(i) = seqCandidatesNew(seqCandidates(i));
1491 if (!nbCandidates) return Standard_False; // Section has no candidates to merge
1493 if (myNonmanifold && nbCandidates >1) {
1494 TColStd_SequenceOfInteger seqNewCandidates;
1495 TColStd_SequenceOfInteger seqOrientationsNew;
1496 seqCandidates.Prepend(1);
1497 seqOrientations.Prepend(1);
1498 for(Standard_Integer k = 1; k <= seqSections.Length() && seqCandidates.Length() > 1 ; k++) {
1499 AnalysisNearestEdges(seqSections,seqCandidates,seqOrientations,(k==1));
1500 if(k == 1 && !seqCandidates.Length()) return Standard_False;
1501 if(seqCandidates.Length()) {
1502 seqNewCandidates.Append(seqCandidates.First());
1503 seqOrientationsNew.Append(seqOrientations.First());
1506 seqCandidates.Prepend(seqNewCandidates);
1507 seqOrientations.Prepend(seqOrientationsNew);
1508 return Standard_True;
1512 // For manifold case leave only one candidate from equidistant candidates
1513 /*Standard_Integer minIndex = seqCandidateIndex.First();
1514 Standard_Real minDistance = arrDistance(minIndex);
1516 // Find equidistant candidates
1517 TColStd_SequenceOfInteger seqEqDistantIndex; seqEqDistantIndex.Append(1);
1518 for (i = 2; i <= nbCandidates; i++) {
1519 Standard_Integer index = seqCandidateIndex(i);
1520 if (Abs(minDistance - arrDistance(index)) <= Precision::Confusion())
1521 seqEqDistantIndex.Append(index);
1524 Standard_Integer eqLen = seqEqDistantIndex.Length();
1527 // Fill map of faces which equidistant sections belong to
1528 TopTools_MapOfShape mapFace;
1529 for (i = 1; i <= eqLen; i++) {
1530 Standard_Integer index = seqEqDistantIndex.Value(i);
1531 if (isCandidate(index)) {
1532 mapFace.Add(arrFace(index));
1536 // Non Manifold case
1537 // Edges are merged by pair among a face continuity C1 criterion
1538 if (mapFace.Extent() == eqLen) {
1544 Standard_Integer indMin = -1;// To check if the edge can be merged.
1545 // Computation of distances between the edges.
1546 TopTools_SequenceOfShape seqSh;
1547 Standard_Integer nbInd = EqDistSeq.Length();
1548 TColStd_Array1OfBoolean tmptabForward(1,nbInd);
1549 seqSh.Append(sequenceSec.Value(1));
1550 for (j = 2; j <= EqDistSeq.Length(); j++) {
1551 Standard_Integer index = EqDistSeq.Value(j);
1552 tmptabForward(j) = tabForward(index);
1553 seqSh.Append(sequenceSec.Value(index));
1556 EvaluateAngulars(seqSh, tmptabForward, tabDist,1);
1558 for(j=2; j <= seqSh.Length(); j++) {
1559 if (tabDist(j) > -1.) { // if edge(j) is connected to edge(i)
1560 if (min > tabDist(j)) {
1567 // Construct minDist, tabMinInd , tabMinForward(i) = tabForward(j);
1569 seqSh.Remove(indMin);
1570 for(j =2; j <= tmpSeq.Length(); ) {
1571 TopoDS_Shape sh = tmpSeq.Value(j);
1572 Standard_Boolean isRem = Standard_False;
1573 for(Standard_Integer k = 1; k<= seqSh.Length();k++) {
1574 if(seqSh.Value(k) == sh) {
1575 isRem = Standard_True;
1581 tabMinForward.Remove(j); // = -1;
1589 // Find the best approved candidate
1590 while (nbCandidates) {
1591 // Retrieve first candidate
1592 Standard_Integer indCandidate = seqCandidates.First();
1593 // Candidate is approved if it is in the map
1594 if (mapReference.Contains(indCandidate)) break;
1595 // Find candidates for candidate #indCandidate
1596 mapReference.Add(indCandidate); // Push candidate in the map
1597 TColStd_SequenceOfInteger seqCandidates1, seqOrientations1;
1598 Standard_Boolean isFound =
1599 FindCandidates(seqSections,mapReference,seqCandidates1,seqOrientations1);
1600 mapReference.RemoveLast(); // Pop candidate from the map
1601 if (isFound) isFound = (seqCandidates1.Length() > 0);
1603 Standard_Integer indCandidate1 = seqCandidates1.First();
1604 // If indReference is the best candidate for indCandidate
1605 // then indCandidate is the best candidate for indReference
1606 if (indCandidate1 == indReference) break;
1607 // If some other reference in the map is the best candidate for indCandidate
1608 // then assume that reference is the best candidate for indReference
1609 if (mapReference.Contains(indCandidate1)) {
1610 seqCandidates.Prepend(indCandidate1);
1614 isFound = Standard_False;
1617 // Remove candidate #1
1618 seqCandidates.Remove(1);
1619 seqOrientations.Remove(1);
1625 if(nbCandidates > 0)
1627 Standard_Integer anInd = seqCandidates.Value(1);
1628 TopoDS_Edge Edge2 = TopoDS::Edge(seqSections(anInd));
1629 TopoDS_Shape bnd = Edge2;
1630 if (mySectionBound.IsBound(bnd))
1631 bnd = mySectionBound(bnd);
1633 if (myBoundFaces.Contains(bnd)) {
1634 Standard_Boolean isOK = Standard_True;
1635 TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1636 for (; itf2.More() && isOK; itf2.Next()) {
1637 const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1638 // Check whether condition is satisfied
1639 isOK = !Faces1.Contains(Face2);
1640 if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1643 return Standard_False;
1646 return (nbCandidates > 0);
1649 //=======================================================================
1650 //function : Constructor
1652 //=======================================================================
1654 BRepBuilderAPI_Sewing::BRepBuilderAPI_Sewing(const Standard_Real tolerance,
1655 const Standard_Boolean optionSewing,
1656 const Standard_Boolean optionAnalysis,
1657 const Standard_Boolean optionCutting,
1658 const Standard_Boolean optionNonmanifold)
1660 myReShape = new BRepTools_ReShape;
1661 Init(tolerance, optionSewing, optionAnalysis, optionCutting, optionNonmanifold);
1664 //=======================================================================
1666 //purpose : Initialise Talerance, and options sewing, faceAnalysis and cutting
1667 //=======================================================================
1669 void BRepBuilderAPI_Sewing::Init(const Standard_Real tolerance,
1670 const Standard_Boolean optionSewing,
1671 const Standard_Boolean optionAnalysis,
1672 const Standard_Boolean optionCutting,
1673 const Standard_Boolean optionNonmanifold)
1675 // Set tolerance and Perform options
1676 myTolerance = tolerance;
1677 mySewing = optionSewing;
1678 myAnalysis = optionAnalysis;
1679 myCutting = optionCutting;
1680 myNonmanifold = optionNonmanifold;
1681 // Set min and max tolerances
1682 myMinTolerance = tolerance*1e-4; //szv: proposal
1683 if (myMinTolerance < Precision::Confusion()) myMinTolerance = Precision::Confusion();
1684 myMaxTolerance = Precision::Infinite();
1686 myFaceMode = Standard_True;
1687 myFloatingEdgesMode = Standard_False;
1688 //myCuttingFloatingEdgesMode = Standard_False; //gka
1689 mySameParameterMode = Standard_True;
1690 myLocalToleranceMode = Standard_False;
1691 mySewedShape.Nullify();
1693 Load(TopoDS_Shape());
1696 //=======================================================================
1698 //purpose : Loads the context shape
1699 //=======================================================================
1701 void BRepBuilderAPI_Sewing::Load(const TopoDS_Shape& theShape)
1704 if (theShape.IsNull()) myShape.Nullify();
1705 else myShape = myReShape->Apply(theShape);
1706 mySewedShape.Nullify();
1707 // Nullify flags and counters
1708 myNbShapes = myNbEdges = myNbVertices = 0;
1710 myOldShapes.Clear();
1711 //myOldFaces.Clear();
1712 myDegenerated.Clear();
1713 myFreeEdges.Clear();
1714 myMultipleEdges.Clear();
1715 myContigousEdges.Clear();
1716 myContigSecBound.Clear();
1717 myBoundFaces.Clear();
1718 myBoundSections.Clear();
1719 myVertexNode.Clear();
1720 myVertexNodeFree.Clear();
1721 myNodeSections.Clear();
1722 myCuttingNode.Clear();
1723 mySectionBound.Clear();
1724 myLittleFace.Clear();
1727 //=======================================================================
1730 //=======================================================================
1732 void BRepBuilderAPI_Sewing::Add(const TopoDS_Shape& aShape)
1734 if (aShape.IsNull()) return;
1735 TopoDS_Shape oShape = myReShape->Apply(aShape);
1736 myOldShapes.Add(aShape,oShape);
1737 myNbShapes = myOldShapes.Extent();
1740 //=======================================================================
1741 //function : Perform
1743 //=======================================================================
1746 #include <OSD_Timer.hxx>
1749 void BRepBuilderAPI_Sewing::Perform(const Handle(Message_ProgressIndicator)& thePI)
1751 const Standard_Integer aNumberOfStages = myAnalysis + myCutting + mySewing + 2;
1752 Message_ProgressSentry aPS (thePI, "Sewing", 0, aNumberOfStages, 1);
1754 Standard_Real t_total = 0., t_analysis = 0., t_assembling = 0., t_cutting = 0., t_merging = 0.;
1755 OSD_Chronometer chr_total, chr_local;
1764 cout << "Begin face analysis..." << endl;
1768 FaceAnalysis (thePI);
1774 chr_local.Show(t_analysis);
1775 cout << "Face analysis finished after " << t_analysis << " s" << endl;
1779 if (myNbShapes || !myShape.IsNull())
1782 FindFreeBoundaries();
1784 if (myBoundFaces.Extent())
1788 cout << "Begin vertices assembling..." << endl;
1792 VerticesAssembling (thePI);
1798 chr_local.Show(t_assembling);
1799 cout << "Vertices assembling finished after " << t_assembling << " s" << endl;
1804 cout << "Begin cutting..." << endl;
1814 chr_local.Show(t_cutting);
1815 cout << "Cutting finished after " << t_cutting << " s" << endl;
1819 cout << "Begin merging..." << endl;
1823 Merging (Standard_True, thePI);
1829 chr_local.Show(t_merging);
1830 cout << "Merging finished after " << t_merging << " s" << endl;
1835 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1837 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1838 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1847 cout << "Creating sewed shape..." << endl;
1849 // examine the multiple edges if any and process sameparameter for edges if necessary
1850 EdgeProcessing (thePI);
1856 mySewedShape.Nullify();
1859 if (mySameParameterMode && myFaceMode)
1860 SameParameterShape();
1863 mySewedShape.Nullify();
1867 cout << "Sewed shape created" << endl;
1871 // create edge informations for output
1872 CreateOutputInformations();
1875 mySewedShape.Nullify();
1881 chr_total.Show(t_total);
1882 cout << "Sewing finished!" << endl;
1883 cout << " analysis time : " << t_analysis << " s" << endl;
1884 cout << " assembling time : " << t_assembling << " s" << endl;
1885 cout << " cutting time : " << t_cutting << " s" << endl;
1886 cout << " merging time : " << t_merging << " s" << endl;
1887 cout << "Total time : " << t_total << " s" << endl;
1891 //=======================================================================
1892 //function : SewedShape
1893 //purpose : give the sewed shape
1894 // if a null shape, reasons:
1895 // -- no useable input shapes : all input shapes are degenerated
1896 // -- has multiple edges
1897 //=======================================================================
1899 const TopoDS_Shape& BRepBuilderAPI_Sewing::SewedShape() const
1901 return mySewedShape;
1904 //=======================================================================
1905 //function : NbFreeEdges
1907 //=======================================================================
1909 Standard_Integer BRepBuilderAPI_Sewing::NbFreeEdges() const
1911 return myFreeEdges.Extent();
1914 //=======================================================================
1915 //function : FreeEdge
1917 //=======================================================================
1919 const TopoDS_Edge& BRepBuilderAPI_Sewing::FreeEdge(const Standard_Integer index) const
1921 Standard_OutOfRange_Raise_if(index < 0 || index > NbFreeEdges(), "BRepBuilderAPI_Sewing::FreeEdge");
1922 return TopoDS::Edge(myFreeEdges(index));
1925 //=======================================================================
1926 //function : NbMultipleEdges
1928 //=======================================================================
1930 Standard_Integer BRepBuilderAPI_Sewing::NbMultipleEdges() const
1932 return myMultipleEdges.Extent();
1935 //=======================================================================
1936 //function : MultipleEdge
1938 //=======================================================================
1940 const TopoDS_Edge& BRepBuilderAPI_Sewing::MultipleEdge(const Standard_Integer index) const
1942 Standard_OutOfRange_Raise_if(index < 0 || index > NbMultipleEdges(), "BRepBuilderAPI_Sewing::MultipleEdge");
1943 return TopoDS::Edge(myMultipleEdges(index));
1946 //=======================================================================
1947 //function : NbContigousEdges
1949 //=======================================================================
1951 Standard_Integer BRepBuilderAPI_Sewing::NbContigousEdges() const
1953 return myContigousEdges.Extent();
1956 //=======================================================================
1957 //function : ContigousEdge
1959 //=======================================================================
1961 const TopoDS_Edge& BRepBuilderAPI_Sewing::ContigousEdge(const Standard_Integer index) const
1963 Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdge");
1964 return TopoDS::Edge(myContigousEdges.FindKey(index));
1967 //=======================================================================
1968 //function : ContigousEdgeCouple
1970 //=======================================================================
1972 const TopTools_ListOfShape& BRepBuilderAPI_Sewing::ContigousEdgeCouple(const Standard_Integer index) const
1974 Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdgeCouple");
1975 return myContigousEdges(index);
1978 //=======================================================================
1979 //function : IsSectionBound
1981 //=======================================================================
1983 Standard_Boolean BRepBuilderAPI_Sewing::IsSectionBound(const TopoDS_Edge& section) const
1985 if(myContigSecBound.IsBound(section)) {
1986 return Standard_True;
1989 return Standard_False;
1993 //=======================================================================
1994 //function : SectionToBoundary
1996 //=======================================================================
1998 const TopoDS_Edge& BRepBuilderAPI_Sewing::SectionToBoundary(const TopoDS_Edge& section) const
2000 Standard_NoSuchObject_Raise_if(!IsSectionBound(section), "BRepBuilderAPI_Sewing::SectionToBoundary");
2001 return TopoDS::Edge(myContigSecBound(section));
2003 //=======================================================================
2004 //function : NbDeletedFaces
2006 //=======================================================================
2007 Standard_Integer BRepBuilderAPI_Sewing::NbDeletedFaces() const
2009 return myLittleFace.Extent();
2012 //=======================================================================
2013 //function : DeletedFace
2015 //=======================================================================
2016 const TopoDS_Face& BRepBuilderAPI_Sewing::DeletedFace(const Standard_Integer index) const
2018 Standard_OutOfRange_Raise_if(index < 0 || index > NbDeletedFaces(), "BRepBuilderAPI_Sewing::DeletedFace");
2019 return TopoDS::Face(myLittleFace(index));
2022 //=======================================================================
2023 //function : NbDegeneratedShapes
2025 //=======================================================================
2027 Standard_Integer BRepBuilderAPI_Sewing::NbDegeneratedShapes() const
2029 return myDegenerated.Extent();
2032 //=======================================================================
2033 //function : DegeneratedShape
2035 //=======================================================================
2037 const TopoDS_Shape& BRepBuilderAPI_Sewing::DegeneratedShape(const Standard_Integer index) const
2039 Standard_OutOfRange_Raise_if(index < 0 || index > NbDegeneratedShapes(), "BRepBuilderAPI_Sewing::DegereratedShape");
2040 return myDegenerated(index);
2043 //=======================================================================
2044 //function : IsDegenerated
2046 //=======================================================================
2048 Standard_Boolean BRepBuilderAPI_Sewing::IsDegenerated(const TopoDS_Shape& aShape) const
2050 TopoDS_Shape NewShape = myReShape->Apply(aShape);
2052 if (aShape.ShapeType() == TopAbs_FACE)
2053 return NewShape.IsNull();
2054 if (NewShape.IsNull()) return Standard_False;
2056 if (NewShape.ShapeType() == TopAbs_EDGE)
2057 return BRep_Tool::Degenerated(TopoDS::Edge(NewShape));
2059 if (NewShape.ShapeType() == TopAbs_WIRE) {
2060 Standard_Boolean isDegenerated = Standard_True;
2061 for (TopoDS_Iterator aIt(NewShape); aIt.More() && isDegenerated; aIt.Next())
2062 isDegenerated = BRep_Tool::Degenerated(TopoDS::Edge(aIt.Value()));
2063 return isDegenerated;
2065 return Standard_False;
2068 //=======================================================================
2069 //function : IsModified
2071 //=======================================================================
2073 Standard_Boolean BRepBuilderAPI_Sewing::IsModified(const TopoDS_Shape& aShape) const
2075 TopoDS_Shape NewShape = aShape;
2076 if (myOldShapes.Contains(aShape))
2077 NewShape = myOldShapes.FindFromKey(aShape);
2078 if(!NewShape.IsSame(aShape)) return Standard_True;
2079 return Standard_False;
2082 //=======================================================================
2083 //function : Modified
2085 //=======================================================================
2087 const TopoDS_Shape& BRepBuilderAPI_Sewing::Modified(const TopoDS_Shape& aShape) const
2089 if (myOldShapes.Contains(aShape)) return myOldShapes.FindFromKey(aShape);
2090 //if (myOldFaces.Contains(aShape)) return myOldFaces.FindFromKey(aShape);
2094 //=======================================================================
2095 //function : IsModifiedSubShape
2097 //=======================================================================
2099 Standard_Boolean BRepBuilderAPI_Sewing::IsModifiedSubShape(const TopoDS_Shape& aShape) const
2101 TopoDS_Shape NewShape = myReShape->Apply(aShape);
2102 if(!NewShape.IsSame(aShape)) return Standard_True;
2103 return Standard_False;
2106 //=======================================================================
2107 //function : ModifiedSubShape
2109 //=======================================================================
2111 TopoDS_Shape BRepBuilderAPI_Sewing::ModifiedSubShape(const TopoDS_Shape& aShape) const
2113 return myReShape->Apply(aShape);
2116 //=======================================================================
2119 //=======================================================================
2121 void BRepBuilderAPI_Sewing::Dump() const
2123 Standard_Integer i, NbBounds = myBoundFaces.Extent(), NbSections = 0;
2124 TopTools_MapOfShape mapVertices, mapEdges;
2125 for (i = 1; i <= NbBounds; i++) {
2126 TopoDS_Shape bound = myBoundFaces.FindKey(i);
2127 if (myBoundSections.IsBound(bound)) NbSections += myBoundSections(bound).Extent();
2129 TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
2130 for (; aExp.More(); aExp.Next()) {
2131 TopoDS_Edge E = TopoDS::Edge(aExp.Current());
2133 TopoDS_Vertex V1, V2;
2134 TopExp::Vertices(E,V1,V2);
2135 mapVertices.Add(V1);
2136 mapVertices.Add(V2);
2139 cout << " " << endl;
2140 cout << " Informations " << endl;
2141 cout << " ===========================================================" << endl;
2142 cout << " " << endl;
2143 cout << " Number of input shapes : " << myOldShapes.Extent() << endl;
2144 cout << " Number of actual shapes : " << myNbShapes << endl;
2145 cout << " Number of Bounds : " << NbBounds << endl;
2146 cout << " Number of Sections : " << NbSections << endl;
2147 cout << " Number of Edges : " << mapEdges.Extent() << endl;
2148 cout << " Number of Vertices : " << myNbVertices << endl;
2149 cout << " Number of Nodes : " << mapVertices.Extent() << endl;
2150 cout << " Number of Free Edges : " << myFreeEdges.Extent() << endl;
2151 cout << " Number of Contigous Edges : " << myContigousEdges.Extent() << endl;
2152 cout << " Number of Multiple Edges : " << myMultipleEdges.Extent() << endl;
2153 cout << " Number of Degenerated Edges : " << myDegenerated.Extent() << endl;
2154 cout << " ===========================================================" << endl;
2155 cout << " " << endl;
2158 //=======================================================================
2159 //function : FaceAnalysis
2167 //=======================================================================
2169 void BRepBuilderAPI_Sewing::FaceAnalysis(const Handle(Message_ProgressIndicator)& thePI)
2171 if (!myShape.IsNull() && myOldShapes.IsEmpty()) {
2177 TopTools_MapOfShape SmallEdges;
2178 TopTools_DataMapOfShapeListOfShape GluedVertices;
2179 Standard_Integer i = 1;
2180 Message_ProgressSentry aPS (thePI, "Shape analysis", 0, myOldShapes.Extent(), 1);
2181 for (i = 1; i <= myOldShapes.Extent() && aPS.More(); i++, aPS.Next()) {
2182 for (TopExp_Explorer fexp(myOldShapes(i),TopAbs_FACE); fexp.More(); fexp.Next()) {
2184 // Retrieve current face
2185 TopoDS_Shape aTmpShape = fexp.Current(); //for porting
2186 TopoDS_Face face = TopoDS::Face(aTmpShape);
2187 Standard_Integer nbEdges = 0, nbSmall = 0;
2189 // Build replacing face
2190 aTmpShape = face.EmptyCopied().Oriented(TopAbs_FORWARD); //for porting
2191 TopoDS_Face nface = TopoDS::Face(aTmpShape);
2192 Standard_Boolean isFaceChanged = Standard_False;
2194 TopoDS_Iterator witer(face.Oriented(TopAbs_FORWARD));
2195 for (; witer.More(); witer.Next()) {
2197 // Retrieve current wire
2198 aTmpShape = witer.Value(); //for porting
2199 if( aTmpShape.ShapeType() != TopAbs_WIRE) continue;
2200 TopoDS_Wire wire = TopoDS::Wire(aTmpShape);
2202 // Build replacing wire
2203 aTmpShape = wire.EmptyCopied().Oriented(TopAbs_FORWARD);
2204 TopoDS_Wire nwire = TopoDS::Wire(aTmpShape);
2205 Standard_Boolean isWireChanged = Standard_False;
2207 TopoDS_Iterator eiter(wire.Oriented(TopAbs_FORWARD));
2208 for (; eiter.More(); eiter.Next()) {
2210 // Retrieve current edge
2211 aTmpShape = eiter.Value(); //for porting
2212 TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
2215 // Process degenerated edge
2216 if (BRep_Tool::Degenerated(edge)) {
2217 B.Add(nwire,edge); // Old edge kept
2218 myDegenerated.Add(edge);
2223 Standard_Boolean isSmall = SmallEdges.Contains(edge);
2226 // Check for small edge
2227 Standard_Real first, last;
2228 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,first,last);
2231 cout << "Warning: Possibly small edge can be sewed: No 3D curve" << endl;
2235 // Evaluate curve compactness
2236 const Standard_Integer npt = 5;
2237 gp_Pnt cp((c3d->Value(first).XYZ()+c3d->Value(last).XYZ())*0.5);
2238 Standard_Real dist, maxdist = 0.0;
2239 Standard_Real delta = (last - first)/(npt - 1);
2240 for (Standard_Integer idx = 0; idx < npt; idx++) {
2241 dist = cp.Distance(c3d->Value(first + idx*delta));
2242 if (maxdist < dist) maxdist = dist;
2244 isSmall = (2.*maxdist <= MinTolerance());
2246 GeomAdaptor_Curve cAdapt(c3d);
2247 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt,first,last);
2248 isSmall = (length <= MinTolerance());
2250 catch (Standard_Failure) {
2252 cout << "Warning: Possibly small edge can be sewed: ";
2253 Standard_Failure::Caught()->Print(cout); cout << endl;
2260 // Store small edge in the map
2261 SmallEdges.Add(edge);
2263 TopoDS_Vertex v1, v2;
2264 TopExp::Vertices(edge,v1,v2);
2265 TopoDS_Shape nv1 = myReShape->Apply(v1), nv2 = myReShape->Apply(v2);
2267 // Store glued vertices
2268 if (!nv1.IsSame(v1)) {
2269 TopTools_ListOfShape& vlist1 = GluedVertices(nv1);
2270 // First vertex was already glued
2271 if (!nv2.IsSame(v2)) {
2272 // Merge lists of glued vertices
2273 if (!nv1.IsSame(nv2)) {
2274 TopTools_ListIteratorOfListOfShape liter(GluedVertices(nv2));
2275 for (; liter.More(); liter.Next()) {
2276 TopoDS_Shape v = liter.Value();
2277 myReShape->Replace(v,nv1.Oriented(v.Orientation()));
2280 GluedVertices.UnBind(nv2);
2284 // Add second vertex to the existing list
2286 myReShape->Replace(v2,nv1.Oriented(v2.Orientation()));
2289 else if (!nv2.IsSame(v2)) {
2290 // Add first vertex to the existing list
2291 GluedVertices(nv2).Append(v1);
2292 myReShape->Replace(v1,nv2.Oriented(v1.Orientation()));
2294 else if (!v1.IsSame(v2)) {
2295 // Record new glued vertices
2298 TopTools_ListOfShape vlist;
2301 GluedVertices.Bind(nv,vlist);
2302 myReShape->Replace(v1,nv.Oriented(v1.Orientation()));
2303 myReShape->Replace(v2,nv.Oriented(v2.Orientation()));
2308 // Replace small edge
2311 cout << "Warning: Small edge made degenerated by FaceAnalysis" << endl;
2314 // Create new degenerated edge
2315 aTmpShape = edge.Oriented(TopAbs_FORWARD);
2316 TopoDS_Edge fedge = TopoDS::Edge(aTmpShape);
2317 Standard_Real pfirst, plast;
2318 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(fedge,face,pfirst,plast);
2319 if (!c2d.IsNull()) {
2322 B.UpdateEdge(nedge,c2d,face,Precision::Confusion());
2323 B.Range(nedge,pfirst,plast);
2324 B.Degenerated(nedge,Standard_True);
2325 TopoDS_Vertex v1, v2;
2326 TopExp::Vertices(fedge,v1,v2);
2327 B.Add(nedge,myReShape->Apply(v1).Oriented(v1.Orientation()));
2328 B.Add(nedge,myReShape->Apply(v2).Oriented(v2.Orientation()));
2329 B.Add(nwire,nedge.Oriented(edge.Orientation()));
2330 myDegenerated.Add(nedge);
2332 isWireChanged = Standard_True;
2334 else B.Add(nwire,edge); // Old edge kept
2337 // Record wire in the new face
2338 if (isWireChanged) {
2339 B.Add(nface,nwire.Oriented(wire.Orientation()));
2340 isFaceChanged = Standard_True;
2342 else B.Add(nface,wire);
2345 // Remove small face
2346 if (nbSmall == nbEdges) {
2348 cout << "Warning: Small face removed by FaceAnalysis" << endl;
2350 myLittleFace.Add(face);
2351 myReShape->Remove(face);
2353 else if (isFaceChanged) {
2355 myReShape->Replace(face,nface.Oriented(face.Orientation()));
2360 // Update glued vertices
2361 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape miter(GluedVertices);
2362 for (; miter.More(); miter.Next()) {
2363 TopoDS_Vertex vnew = TopoDS::Vertex(miter.Key());
2364 gp_XYZ coord(0.,0.,0.);
2365 Standard_Integer nbPoints = 0;
2366 const TopTools_ListOfShape& vlist = miter.Value();
2367 TopTools_ListIteratorOfListOfShape liter1(vlist);
2368 for (; liter1.More(); liter1.Next()) {
2369 coord += BRep_Tool::Pnt(TopoDS::Vertex(liter1.Value())).XYZ();
2373 gp_Pnt vp(coord / nbPoints);
2374 Standard_Real tol = 0.0, mtol = 0.0;
2375 TopTools_ListIteratorOfListOfShape liter2(vlist);
2376 for (; liter2.More(); liter2.Next()) {
2377 Standard_Real vtol = BRep_Tool::Tolerance(TopoDS::Vertex(liter2.Value()));
2378 if (mtol < vtol) mtol = vtol;
2379 vtol = vp.Distance(BRep_Tool::Pnt(TopoDS::Vertex(liter2.Value())));
2380 if (tol < vtol) tol = vtol;
2382 B.UpdateVertex(vnew,vp,tol+mtol);
2386 // Update input shapes
2387 for (i = 1; i <= myOldShapes.Extent(); i++)
2388 myOldShapes(i) = myReShape->Apply(myOldShapes(i));
2391 //=======================================================================
2392 //function : FindFreeBoundaries
2393 //purpose : Constructs :
2394 // myBoundFaces (bound = list of faces) - REFERENCE
2395 // myVertexNode (vertex = node)
2396 // myVertexNodeFree (floating vertex = node)
2398 //=======================================================================
2400 void BRepBuilderAPI_Sewing::FindFreeBoundaries()
2402 // Take into account the context shape if needed
2403 TopTools_IndexedMapOfShape NewShapes;
2404 if (!myShape.IsNull()) {
2405 if (myOldShapes.IsEmpty()) {
2410 TopoDS_Shape newShape = myReShape->Apply(myShape);
2411 if (!newShape.IsNull()) NewShapes.Add(newShape);
2414 // Create map Edge -> Faces
2415 TopTools_IndexedDataMapOfShapeListOfShape EdgeFaces;
2416 Standard_Integer i, nbShapes = myOldShapes.Extent();
2417 for (i = 1; i <= nbShapes; i++) {
2418 // Retrieve new shape
2419 TopoDS_Shape shape = myOldShapes(i);
2420 if (shape.IsNull()) continue;
2421 NewShapes.Add(shape);
2422 // Explore shape to find all boundaries
2423 for (TopExp_Explorer eExp(shape,TopAbs_EDGE); eExp.More(); eExp.Next()) {
2424 TopoDS_Shape edge = eExp.Current();
2425 if (!EdgeFaces.Contains(edge)) {
2426 TopTools_ListOfShape listFaces;
2427 EdgeFaces.Add(edge,listFaces);
2431 // Fill map Edge -> Faces
2432 nbShapes = NewShapes.Extent();
2433 TopTools_MapOfShape mapFaces;
2434 for (i = 1; i <= nbShapes; i++) {
2435 // Explore shape to find all faces
2436 TopExp_Explorer fExp(NewShapes.FindKey(i),TopAbs_FACE);
2437 for (; fExp.More(); fExp.Next()) {
2438 TopoDS_Shape face = fExp.Current();
2439 if(mapFaces.Contains(face)) continue;
2442 // Explore face to find all boundaries
2443 for (TopoDS_Iterator aIw(face); aIw.More(); aIw.Next()) {
2444 if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
2445 for (TopoDS_Iterator aIIe(aIw.Value()); aIIe.More(); aIIe.Next()) {
2447 TopoDS_Shape edge = aIIe.Value();
2449 if (EdgeFaces.Contains(edge)) {
2450 EdgeFaces.ChangeFromKey(edge).Append(face);
2451 //TopTools_ListOfShape& listFaces = EdgeFaces.ChangeFromKey(edge);
2452 //Standard_Boolean isContained = Standard_False;
2453 //TopTools_ListIteratorOfListOfShape itf(listFaces);
2454 //for (; itf.More() && !isContained; itf.Next())
2455 // isContained = face.IsSame(itf.Value());
2456 //if (!isContained) listFaces.Append(face);
2462 // Find free boundaries
2463 nbShapes = EdgeFaces.Extent();
2464 for (i = 1; i <= nbShapes; i++) {
2465 TopTools_ListOfShape& listFaces = EdgeFaces(i);
2466 Standard_Integer nbFaces = listFaces.Extent();
2467 TopoDS_Shape edge = EdgeFaces.FindKey(i);
2468 if(edge.Orientation() == TopAbs_INTERNAL)
2470 Standard_Boolean isSeam = Standard_False;
2472 TopoDS_Face face = TopoDS::Face(listFaces.First());
2473 isSeam = BRep_Tool::IsClosed(TopoDS::Edge(edge),face);
2475 ///Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
2476 //isSeam = (IsUClosedSurface(surf) || IsVClosedSurface(surf));
2479 TopoDS_Shape anewEdge = edge.EmptyCopied();
2480 TopoDS_Iterator aItV(edge);
2481 for( ; aItV.More() ; aItV.Next())
2482 aB.Add(anewEdge,aItV.Value());
2486 Standard_Real first2d,last2d;
2487 Handle(Geom2d_Curve) c2dold =
2488 BRep_Tool::CurveOnSurface(TopoDS::Edge(edge),TopoDS::Face(listFaces.First()),first2d,last2d);
2490 Handle(Geom2d_Curve) c2d;
2492 B.UpdateEdge(TopoDS::Edge(anewEdge),c2d,c2d,TopoDS::Face(listFaces.First()),0);
2493 B.UpdateEdge(TopoDS::Edge(anewEdge),c2dold,TopoDS::Face(listFaces.First()),0);
2495 Standard_Real aFirst, aLast;
2496 BRep_Tool::Range(TopoDS::Edge(edge),aFirst, aLast);
2497 aB.Range(TopoDS::Edge(anewEdge),aFirst, aLast);
2498 aB.Range(TopoDS::Edge(anewEdge),TopoDS::Face(listFaces.First()),first2d,last2d);
2499 myReShape->Replace(edge,anewEdge);
2503 isSeam = Standard_False;
2506 Standard_Boolean isBoundFloat = (myFloatingEdgesMode && !nbFaces);
2507 Standard_Boolean isBound = (myFaceMode && ((myNonmanifold && nbFaces) || (nbFaces == 1 && !isSeam)));
2508 if (isBound || isBoundFloat) {
2509 // Ignore degenerated edge
2510 if (BRep_Tool::Degenerated(TopoDS::Edge(edge))) continue;
2511 // Ignore edge with internal vertices
2512 // Standard_Integer nbVtx = 0;
2513 // for (TopExp_Explorer vExp(edge,TopAbs_VERTEX); vExp.More(); vExp.Next()) nbVtx++;
2514 // if (nbVtx != 2) continue;
2515 // Add to BoundFaces
2516 TopTools_ListOfShape listFacesCopy;
2517 listFacesCopy.Append(listFaces);
2518 myBoundFaces.Add(edge,listFacesCopy);
2519 // Process edge vertices
2520 TopoDS_Vertex vFirst, vLast;
2521 TopExp::Vertices(TopoDS::Edge(edge), vFirst, vLast);
2522 if(vFirst.IsNull() || vLast.IsNull()) continue;
2523 if(vFirst.Orientation() == TopAbs_INTERNAL || vLast.Orientation() == TopAbs_INTERNAL)
2526 // Add to VertexNode
2527 if (!myVertexNode.Contains(vFirst))
2528 myVertexNode.Add(vFirst,vFirst);
2529 if (!myVertexNode.Contains(vLast))
2530 myVertexNode.Add(vLast,vLast);
2533 // Add to VertexNodeFree
2534 if (!myVertexNodeFree.Contains(vFirst))
2535 myVertexNodeFree.Add(vFirst,vFirst);
2536 if (!myVertexNodeFree.Contains(vLast))
2537 myVertexNodeFree.Add(vLast,vLast);
2543 //=======================================================================
2544 //function : VerticesAssembling
2545 //purpose : Modifies :
2546 // myVertexNode (nodes glued)
2547 // myVertexNodeFree (nodes glued)
2548 // myNodeSections (lists of sections merged for glued nodes)
2550 //=======================================================================
2552 static Standard_Boolean CreateNewNodes(const TopTools_IndexedDataMapOfShapeShape& NodeNearestNode,
2553 const TopTools_IndexedDataMapOfShapeListOfShape& NodeVertices,
2554 TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2555 TopTools_DataMapOfShapeListOfShape& aNodeEdges)
2557 Standard_Integer i, nbNearest = NodeNearestNode.Extent();
2561 TopTools_DataMapOfShapeShape OldNodeNewNode;
2562 TopTools_DataMapOfShapeListOfShape NewNodeOldNodes;
2563 for (i = 1; i <= nbNearest; i++) {
2564 // Retrieve a pair of nodes to merge
2565 TopoDS_Shape oldnode1 = NodeNearestNode.FindKey(i);
2566 TopoDS_Shape oldnode2 = NodeNearestNode(i);
2567 // Second node should also be in the map
2568 if (!NodeNearestNode.Contains(oldnode2)) continue;
2569 // Get new node for old node #1
2570 if (OldNodeNewNode.IsBound(oldnode1)) {
2571 TopoDS_Shape newnode1 = OldNodeNewNode(oldnode1);
2572 if (OldNodeNewNode.IsBound(oldnode2)) {
2573 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2574 if (!newnode1.IsSame(newnode2)) {
2575 // Change data for new node #2
2576 TopTools_ListOfShape& lnode1 = NewNodeOldNodes(newnode1);
2577 TopTools_ListIteratorOfListOfShape itn(NewNodeOldNodes(newnode2));
2578 for (; itn.More(); itn.Next()) {
2579 TopoDS_Shape node2 = itn.Value();
2580 lnode1.Append(node2);
2581 OldNodeNewNode(node2) = newnode1;
2583 NewNodeOldNodes.UnBind(newnode2);
2587 // Old node #2 is not bound - add to old node #1
2588 OldNodeNewNode.Bind(oldnode2,newnode1);
2589 NewNodeOldNodes(newnode1).Append(oldnode2);
2593 if (OldNodeNewNode.IsBound(oldnode2)) {
2594 // Old node #1 is not bound - add to old node #2
2595 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2596 OldNodeNewNode.Bind(oldnode1,newnode2);
2597 NewNodeOldNodes(newnode2).Append(oldnode1);
2600 // Nodes are not bound - create new node
2601 TopoDS_Vertex newnode;
2602 B.MakeVertex(newnode);
2603 OldNodeNewNode.Bind(oldnode1,newnode);
2604 OldNodeNewNode.Bind(oldnode2,newnode);
2605 TopTools_ListOfShape lnodes;
2606 lnodes.Append(oldnode1);
2607 lnodes.Append(oldnode2);
2608 NewNodeOldNodes.Bind(newnode,lnodes);
2613 // Stop if no new nodes created
2614 if (!NewNodeOldNodes.Extent()) return Standard_False;
2616 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter1(NewNodeOldNodes);
2617 for (; iter1.More(); iter1.Next()) {
2618 const TopoDS_Vertex& newnode = TopoDS::Vertex(iter1.Key());
2619 // Calculate new node center point
2620 gp_XYZ theCoordinates(0.,0.,0.);
2621 TopTools_ListOfShape lvert; // Accumulate node vertices
2622 TopTools_MapOfShape medge;
2623 TopTools_ListOfShape ledge; // Accumulate node edges
2624 // Iterate on old nodes
2625 TopTools_ListIteratorOfListOfShape itn(iter1.Value());
2626 for (; itn.More(); itn.Next()) {
2627 const TopoDS_Shape& oldnode = itn.Value();
2628 // Iterate on node vertices
2629 TopTools_ListIteratorOfListOfShape itv(NodeVertices.FindFromKey(oldnode));
2630 for (; itv.More(); itv.Next()) {
2631 TopoDS_Vertex vertex = TopoDS::Vertex(itv.Value());
2632 // Change node for vertex
2633 aVertexNode.ChangeFromKey(vertex) = newnode;
2634 // Accumulate coordinates
2635 theCoordinates += BRep_Tool::Pnt(vertex).XYZ();
2636 lvert.Append(vertex);
2638 // Iterate on node edges
2639 const TopTools_ListOfShape& edges = aNodeEdges(oldnode);
2640 TopTools_ListIteratorOfListOfShape ite(edges);
2641 for (; ite.More(); ite.Next()) {
2642 TopoDS_Shape edge = ite.Value();
2643 if (!medge.Contains(edge)) { medge.Add(edge); ledge.Append(edge); }
2645 // Unbind old node edges
2646 aNodeEdges.UnBind(oldnode);
2648 // Bind new node edges
2649 aNodeEdges.Bind(newnode,ledge);
2650 gp_Pnt center(theCoordinates / lvert.Extent());
2651 // Calculate new node tolerance
2652 Standard_Real toler = 0.0;
2653 TopTools_ListIteratorOfListOfShape itv(lvert);
2654 for (; itv.More(); itv.Next()) {
2655 const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value());
2656 Standard_Real t = center.Distance(BRep_Tool::Pnt(vertex)) + BRep_Tool::Tolerance(vertex);
2657 if (toler < t) toler = t;
2659 // Update new node parameters
2660 B.UpdateVertex(newnode,center,toler);
2663 return Standard_True;
2666 static Standard_Integer IsMergedVertices(const TopoDS_Shape& face1,
2667 const TopoDS_Shape& e1, const TopoDS_Shape& e2,
2668 const TopoDS_Shape& vtx1, const TopoDS_Shape& vtx2)
2670 //Case of floating edges
2672 return (!IsClosedShape(e1,vtx1,vtx2));
2674 // Find wires containing given edges
2675 TopoDS_Shape wire1, wire2;
2676 TopExp_Explorer itw(face1,TopAbs_WIRE);
2677 for (; itw.More() && (wire1.IsNull() || wire2.IsNull()); itw.Next()) {
2678 TopoDS_Iterator ite(itw.Current(),Standard_False);
2679 for (; ite.More() && (wire1.IsNull() || wire2.IsNull()); ite.Next()) {
2680 if (wire1.IsNull() && e1.IsSame(ite.Value())) wire1 = itw.Current();
2681 if (wire2.IsNull() && e2.IsSame(ite.Value())) wire2 = itw.Current();
2684 Standard_Integer Status = 0;
2685 if (!wire1.IsNull() && !wire2.IsNull()) {
2686 if (wire1.IsSame(wire2)) {
2687 for (TopoDS_Iterator aIte(wire1,Standard_False); aIte.More(); aIte.Next()) {
2688 TopoDS_Vertex ve1,ve2;
2689 TopExp::Vertices(TopoDS::Edge(aIte.Value()),ve1,ve2);
2690 if ((ve1.IsSame(vtx1) && ve2.IsSame(vtx2)) ||
2691 (ve2.IsSame(vtx1) && ve1.IsSame(vtx2)))
2692 return (IsClosedShape(aIte.Value(),vtx1,vtx2)? 0 : 1);
2694 if (IsClosedShape(wire1,vtx1,vtx2)) {
2695 TopoDS_Vertex V1, V2;
2696 TopExp::Vertices(TopoDS::Wire(wire1),V1,V2);
2697 Standard_Boolean isEndVertex = ((V1.IsSame(vtx1) && V2.IsSame(vtx2)) ||
2698 (V2.IsSame(vtx1) && V1.IsSame(vtx2)));
2699 if (!isEndVertex) Status = 1;
2708 static Standard_Boolean GlueVertices(TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2709 TopTools_DataMapOfShapeListOfShape& aNodeEdges,
2710 const TopTools_IndexedDataMapOfShapeListOfShape& aBoundFaces,
2711 const Standard_Real Tolerance,
2712 const Handle(Message_ProgressIndicator)& theProgress)
2714 Standard_Integer i, nbVertices = aVertexNode.Extent();
2715 // Create map of node -> vertices
2716 TopTools_IndexedDataMapOfShapeListOfShape NodeVertices;
2717 for (i = 1; i <= nbVertices; i++) {
2718 TopoDS_Shape vertex = aVertexNode.FindKey(i);
2719 TopoDS_Vertex node = TopoDS::Vertex(aVertexNode(i));
2720 if (NodeVertices.Contains(node)) {
2721 NodeVertices.ChangeFromKey(node).Append(vertex);
2724 TopTools_ListOfShape vlist;
2725 vlist.Append(vertex);
2726 NodeVertices.Add(node,vlist);
2729 Standard_Integer nbNodes = NodeVertices.Extent();
2731 cout << "Glueing " << nbNodes << " nodes..." << endl;
2733 // Create array of boxes with nodes
2734 Handle(Bnd_HArray1OfBox) hSetBoxes = new Bnd_HArray1OfBox(1,nbNodes);
2736 Standard_Real eps = Tolerance*0.5;
2737 for (i = 1; i <= nbNodes; i++) {
2738 gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(NodeVertices.FindKey(i)));
2741 hSetBoxes->SetValue(i,aBox);
2743 // Merge nearest nodes
2744 TopTools_IndexedDataMapOfShapeShape NodeNearestNode;
2745 Message_ProgressSentry aPS (theProgress, "Glueing nodes", 0, nbNodes, 1, Standard_True);
2746 for (i = 1; i <= nbNodes && aPS.More(); i++, aPS.Next()) {
2747 TopoDS_Vertex node1 = TopoDS::Vertex(NodeVertices.FindKey(i));
2749 TColStd_ListOfInteger listIndex;
2750 SortBox(hSetBoxes,hSetBoxes->Value(i),listIndex);
2751 if (listIndex.IsEmpty()) continue;
2752 // Retrieve list of edges for the first node
2753 const TopTools_ListOfShape& ledges1 = aNodeEdges(node1);
2754 // Explore list of near nodes and fill the sequence of glued nodes
2755 TopTools_SequenceOfShape SeqNodes;
2756 TopTools_ListOfShape listNodesSameEdge;
2757 gp_Pnt pt1 = BRep_Tool::Pnt(node1);
2758 TColStd_ListIteratorOfListOfInteger iter1(listIndex);
2759 for (; iter1.More(); iter1.Next()) {
2760 TopoDS_Vertex node2 = TopoDS::Vertex(NodeVertices.FindKey(iter1.Value()));
2761 if (node1 == node2) continue;
2762 // Retrieve list of edges for the second node
2763 const TopTools_ListOfShape& ledges2 = aNodeEdges(node2);
2764 // Check merging condition for the pair of nodes
2765 Standard_Integer Status = 0, isSameEdge = Standard_False;
2766 // Explore edges of the first node
2767 TopTools_ListIteratorOfListOfShape Ie1(ledges1);
2768 for (; Ie1.More() && !Status && !isSameEdge; Ie1.Next()) {
2769 const TopoDS_Shape& e1 = Ie1.Value();
2770 // Obtain real vertex from edge
2771 TopoDS_Shape v1 = node1;
2772 { //szv: Use brackets to destroy local variables
2773 TopoDS_Vertex ov1, ov2;
2774 TopExp::Vertices(TopoDS::Edge(e1),ov1,ov2);
2775 if (aVertexNode.Contains(ov1)) {
2776 if (node1.IsSame(aVertexNode.FindFromKey(ov1))) v1 = ov1;
2778 if (aVertexNode.Contains(ov2)) {
2779 if (node1.IsSame(aVertexNode.FindFromKey(ov2))) v1 = ov2;
2782 // Create map of faces for e1
2783 TopTools_MapOfShape Faces1;
2784 const TopTools_ListOfShape& lfac1 = aBoundFaces.FindFromKey(e1);
2785 if (lfac1.Extent()) {
2786 TopTools_ListIteratorOfListOfShape itf(lfac1);
2787 for (; itf.More(); itf.Next())
2788 if (!itf.Value().IsNull())
2789 Faces1.Add(itf.Value());
2791 // Explore edges of the second node
2792 TopTools_ListIteratorOfListOfShape Ie2(ledges2);
2793 for (; Ie2.More() && !Status && !isSameEdge; Ie2.Next()) {
2794 const TopoDS_Shape& e2 = Ie2.Value();
2795 // Obtain real vertex from edge
2796 TopoDS_Shape v2 = node2;
2797 { //szv: Use brackets to destroy local variables
2798 TopoDS_Vertex ov1, ov2;
2799 TopExp::Vertices(TopoDS::Edge(e2),ov1,ov2);
2800 if (aVertexNode.Contains(ov1)) {
2801 if (node2.IsSame(aVertexNode.FindFromKey(ov1))) v2 = ov1;
2803 if (aVertexNode.Contains(ov2)) {
2804 if (node2.IsSame(aVertexNode.FindFromKey(ov2))) v2 = ov2;
2807 // Explore faces for e2
2808 const TopTools_ListOfShape& lfac2 = aBoundFaces.FindFromKey(e2);
2809 if (lfac2.Extent()) {
2810 TopTools_ListIteratorOfListOfShape itf(lfac2);
2811 for (; itf.More() && !Status && !isSameEdge; itf.Next()) {
2812 // Check merging conditions for the same face
2813 if (Faces1.Contains(itf.Value())) {
2814 Standard_Integer stat = IsMergedVertices(itf.Value(),e1,e2,v1,v2);
2815 if (stat == 1) isSameEdge = Standard_True;
2820 else if (Faces1.IsEmpty() && e1 == e2) {
2821 Standard_Integer stat = IsMergedVertices(TopoDS_Face(),e1,e1,v1,v2);
2822 if (stat == 1) isSameEdge = Standard_True;
2828 if (Status) continue;
2829 if (isSameEdge) listNodesSameEdge.Append(node2);
2830 // Append near node to the sequence
2831 gp_Pnt pt2 = BRep_Tool::Pnt(node2);
2832 Standard_Real dist = pt1.Distance(pt2);
2833 if (dist < Tolerance) {
2834 Standard_Boolean isIns = Standard_False;
2835 for (Standard_Integer kk = 1; kk <= SeqNodes.Length() && !isIns; kk++) {
2836 gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(SeqNodes.Value(kk)));
2837 if (dist < pt1.Distance(pt)) {
2838 SeqNodes.InsertBefore(kk,node2);
2839 isIns = Standard_True;
2842 if (!isIns) SeqNodes.Append(node2);
2845 if (SeqNodes.Length()) {
2846 // Remove nodes near to some other from the same edge
2847 if (listNodesSameEdge.Extent()) {
2848 TopTools_ListIteratorOfListOfShape lInt(listNodesSameEdge);
2849 for (; lInt.More(); lInt.Next()) {
2850 const TopoDS_Vertex& n2 = TopoDS::Vertex(lInt.Value());
2851 gp_Pnt p2 = BRep_Tool::Pnt(n2);
2852 for (Standard_Integer k = 1; k <= SeqNodes.Length(); ) {
2853 const TopoDS_Vertex& n1 = TopoDS::Vertex(SeqNodes.Value(k));
2855 gp_Pnt p1 = BRep_Tool::Pnt(n1);
2856 if (p2.Distance(p1) >= pt1.Distance(p1)) { k++; continue; }
2862 // Bind nearest node if at least one exists
2863 if (SeqNodes.Length())
2864 NodeNearestNode.Add(node1,SeqNodes.First());
2868 // Create new nodes for chained nearest nodes
2869 if (NodeNearestNode.IsEmpty()) return Standard_False;
2870 hSetBoxes.Nullify();
2872 return CreateNewNodes(NodeNearestNode,NodeVertices,aVertexNode,aNodeEdges);
2875 void BRepBuilderAPI_Sewing::VerticesAssembling(const Handle(Message_ProgressIndicator)& thePI)
2877 Standard_Integer nbVert = myVertexNode.Extent();
2878 Standard_Integer nbVertFree = myVertexNodeFree.Extent();
2879 Message_ProgressSentry aPS (thePI, "Vertices assembling", 0, 2, 1);
2880 if (nbVert || nbVertFree) {
2881 // Fill map node -> sections
2883 for (i = 1; i <= myBoundFaces.Extent(); i++) {
2884 TopoDS_Shape bound = myBoundFaces.FindKey(i);
2885 for (TopoDS_Iterator itv(bound,Standard_False); itv.More(); itv.Next()) {
2886 TopoDS_Shape node = itv.Value();
2887 if (myNodeSections.IsBound(node))
2888 myNodeSections(node).Append(bound);
2890 TopTools_ListOfShape lbnd;
2892 myNodeSections.Bind(node,lbnd);
2899 cout << "Assemble " << nbVert << " vertices on faces..." << endl;
2901 while (GlueVertices(myVertexNode,myNodeSections,myBoundFaces,myTolerance, thePI));
2908 cout << "Assemble " << nbVertFree << " vertices on floating edges..." << endl;
2910 while (GlueVertices(myVertexNodeFree,myNodeSections,myBoundFaces,myTolerance, thePI));
2915 //=======================================================================
2916 //function : replaceNMVertices
2917 //purpose : internal use (static)
2918 //=======================================================================
2919 static void replaceNMVertices(const TopoDS_Edge& theEdge,
2920 const TopoDS_Vertex& theV1,
2921 const TopoDS_Vertex& theV2,
2922 const Handle(BRepTools_ReShape)& theReShape)
2924 //To keep NM vertices on edge
2925 TopTools_SequenceOfShape aSeqNMVert;
2926 TColStd_SequenceOfReal aSeqNMPars;
2927 Standard_Boolean hasNMVert = findNMVertices(theEdge,aSeqNMVert,aSeqNMPars);
2930 Standard_Real first, last;
2931 BRep_Tool::Range(theEdge, first, last);
2932 TopLoc_Location aLoc;
2933 Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,aLoc,first, last);
2936 TopTools_SequenceOfShape aEdVert;
2937 TColStd_SequenceOfReal aEdParams;
2938 Standard_Integer i =1, nb = aSeqNMPars.Length();
2940 for( ; i <= nb;i++) {
2941 Standard_Real apar = aSeqNMPars.Value(i);
2942 if(fabs(apar - first) <= Precision::PConfusion()) {
2943 theReShape->Replace(aSeqNMVert.Value(i),theV1);
2946 if(fabs(apar - last) <= Precision::PConfusion()) {
2947 theReShape->Replace(aSeqNMVert.Value(i),theV2);
2950 TopoDS_Shape aV = aSeqNMVert.Value(i);
2951 Standard_Integer j =1;
2952 for( ; j <= aEdParams.Length();j++) {
2953 Standard_Real apar2 = aEdParams.Value(j);
2954 if(fabs(apar - apar2) <= Precision::PConfusion()) {
2955 theReShape->Replace(aV,aEdVert.Value(j));
2958 else if(apar < apar2) {
2959 TopoDS_Shape anewV = aV.EmptyCopied();
2960 aEdVert.InsertBefore(j,anewV);
2961 aEdParams.InsertBefore(j,apar);
2962 BRep_ListOfPointRepresentation& alistrep =
2963 (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints();
2964 Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
2965 alistrep.Append(aPRep);
2966 theReShape->Replace(aV,anewV);
2970 if (j > aEdParams.Length()) {
2971 TopoDS_Shape anewV = aV.EmptyCopied();
2972 aEdVert.Append(anewV);
2973 aEdParams.Append(apar);
2974 BRep_ListOfPointRepresentation& alistrep =
2975 (*((Handle(BRep_TVertex)*) &anewV.TShape()))->ChangePoints();
2976 Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
2977 alistrep.Append(aPRep);
2978 theReShape->Replace(aV,anewV);
2982 Standard_Integer newnb = aEdParams.Length();
2985 TopoDS_Shape anewEdge = theEdge.EmptyCopied();
2986 TopAbs_Orientation anOri = theEdge.Orientation();
2987 anewEdge.Orientation(TopAbs_FORWARD);
2989 aB.Add(anewEdge,theV1);
2990 aB.Add(anewEdge,theV2);
2992 for( i =1; i <= aEdVert.Length();i++)
2993 aB.Add(anewEdge,aEdVert.Value(i));
2994 anewEdge.Orientation(anOri);
2995 theReShape->Replace(theEdge,anewEdge);
3000 //=======================================================================
3001 //function : ReplaceEdge
3002 //purpose : internal use (static)
3003 //=======================================================================
3005 static void ReplaceEdge(const TopoDS_Shape& oldEdge,
3006 const TopoDS_Shape& theNewShape,
3007 const Handle(BRepTools_ReShape)& aReShape)
3009 TopoDS_Shape oldShape = aReShape->Apply(oldEdge);
3010 TopoDS_Shape newShape = aReShape->Apply(theNewShape);
3011 if (oldShape.IsSame(newShape)|| aReShape->IsRecorded(newShape)) return;
3014 aReShape->Replace(oldShape,newShape);
3015 TopoDS_Vertex V1old,V2old,V1new,V2new;
3016 TopExp::Vertices(TopoDS::Edge(oldShape),V1old,V2old);
3017 TopAbs_Orientation Orold = oldShape.Orientation();
3018 TopAbs_Orientation Ornew = Orold;
3019 if (newShape.ShapeType() == TopAbs_EDGE) {
3020 TopoDS_Edge aEn = TopoDS::Edge(newShape);
3021 TopExp::Vertices(aEn,V1new,V2new);
3022 Ornew = aEn.Orientation();
3023 replaceNMVertices(aEn,V1new,V2new,aReShape);
3025 else if (newShape.ShapeType() == TopAbs_WIRE) {
3026 for (TopExp_Explorer aex(newShape,TopAbs_EDGE); aex.More(); aex.Next()) {
3027 TopoDS_Edge ed = TopoDS::Edge(aex.Current());
3028 Ornew = ed.Orientation();
3029 TopoDS_Vertex aV1,aV2;
3030 TopExp::Vertices(ed,aV1,aV2);
3031 replaceNMVertices(ed,aV1,aV2,aReShape);
3038 V1new.Orientation(V1old.Orientation());
3039 V2new.Orientation(V2old.Orientation());
3040 if (V1old.IsSame(V2old) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) {
3041 aReShape->Replace(V1old,V1new);
3044 if (Orold == Ornew) {
3045 V1new.Orientation(V1old.Orientation());
3046 V2new.Orientation(V2old.Orientation());
3047 if (!V1old.IsSame(V1new) && !V1old.IsSame(V2new)&& !aReShape->IsRecorded(V1new))
3048 aReShape->Replace(V1old,V1new);
3049 if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3050 aReShape->Replace(V2old,V2new);
3053 V1new.Orientation(V2old.Orientation());
3054 V2new.Orientation(V1old.Orientation());
3055 if (!V1old.IsSame(V2new) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3056 aReShape->Replace(V1old,V2new);
3057 if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V1new))
3058 aReShape->Replace(V2old,V1new);
3062 //=======================================================================
3063 //function : Merging
3064 //purpose : Modifies :
3067 //=======================================================================
3069 void BRepBuilderAPI_Sewing::Merging(const Standard_Boolean /* firstTime */,
3070 const Handle(Message_ProgressIndicator)& thePI)
3073 // TopTools_MapOfShape MergedEdges;
3074 Message_ProgressSentry aPS (thePI, "Merging bounds", 0, myBoundFaces.Extent(), 1);
3075 for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
3077 TopoDS_Shape bound = myBoundFaces.FindKey(i);
3079 // If bound was already merged - continue
3080 if (myMergedEdges.Contains(bound)) continue;
3082 if (!myBoundFaces(i).Extent()) {
3083 // Merge free edge - only vertices
3084 TopoDS_Vertex no1, no2;
3085 TopExp::Vertices(TopoDS::Edge(bound),no1,no2);
3086 TopoDS_Shape nno1 = no1, nno2 = no2;
3087 if (myVertexNodeFree.Contains(no1))
3088 nno1 = myVertexNodeFree.FindFromKey(no1);
3089 if (myVertexNodeFree.Contains(no2))
3090 nno2 = myVertexNodeFree.FindFromKey(no2);
3091 if (!no1.IsSame(nno1)) {
3092 nno1.Orientation(no1.Orientation());
3093 myReShape->Replace(no1,nno1);
3095 if (!no2.IsSame(nno2)) {
3096 nno2.Orientation(no2.Orientation());
3097 myReShape->Replace(no2,nno2);
3099 myMergedEdges.Add(bound);
3103 // Check for previous splitting, build replacing wire
3104 TopoDS_Wire BoundWire;
3105 Standard_Boolean isPrevSplit = Standard_False;
3106 Standard_Boolean hasCuttingSections = myBoundSections.IsBound(bound);
3107 if (hasCuttingSections) {
3108 B.MakeWire(BoundWire);
3109 BoundWire.Orientation(bound.Orientation());
3110 // Iterate on cutting sections
3111 TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3112 for (; its.More(); its.Next()) {
3113 TopoDS_Shape section = its.Value();
3114 B.Add(BoundWire,section);
3115 if (myMergedEdges.Contains(section)) isPrevSplit = Standard_True;
3120 TopTools_DataMapOfShapeShape MergedWithBound;
3122 // Obtain sequence of edges merged with bound
3123 TopTools_SequenceOfShape seqMergedWithBound;
3124 TColStd_SequenceOfInteger seqMergedWithBoundOri;
3125 if (MergedNearestEdges(bound,seqMergedWithBound,seqMergedWithBoundOri)) {
3126 // Store bound in the map
3127 MergedWithBound.Bind(bound,bound);
3128 // Iterate on edges merged with bound
3129 Standard_Integer ii = 1;
3130 while (ii <= seqMergedWithBound.Length()) {
3131 TopoDS_Shape iedge = seqMergedWithBound.Value(ii);
3132 // Remove edge if recorded as merged
3133 Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) ||
3134 MergedWithBound.IsBound(iedge));
3136 if (myBoundSections.IsBound(iedge)) {
3137 // Edge is splitted - check sections
3138 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3139 for (; lit.More() && !isRejected; lit.Next()) {
3140 const TopoDS_Shape& sec = lit.Value();
3141 // Remove edge (bound) if at least one of its sections already merged
3142 isRejected = (myMergedEdges.Contains(sec) || MergedWithBound.IsBound(sec));
3146 if (mySectionBound.IsBound(iedge)) {
3147 // Edge is a section - check bound
3148 const TopoDS_Shape& bnd = mySectionBound(iedge);
3149 // Remove edge (section) if its bound already merged
3150 isRejected = (myMergedEdges.Contains(bnd) || MergedWithBound.IsBound(bnd));
3154 // To the next merged edge
3156 // Remove rejected edge
3157 seqMergedWithBound.Remove(ii);
3158 seqMergedWithBoundOri.Remove(ii);
3161 // Process accepted edge
3162 MergedWithBound.Bind(iedge,iedge);
3166 Standard_Integer nbMerged = seqMergedWithBound.Length();
3168 // Create same parameter edge
3169 TopTools_MapOfShape ActuallyMerged;
3170 TopoDS_Edge MergedEdge = SameParameterEdge(bound,seqMergedWithBound,
3171 seqMergedWithBoundOri,
3172 ActuallyMerged,myReShape);
3173 Standard_Boolean isForward = Standard_False;
3174 if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3175 // Process actually merged edges
3176 Standard_Integer nbActuallyMerged = 0;
3177 for (ii = 1; ii <= nbMerged; ii++) {
3178 TopoDS_Shape iedge = seqMergedWithBound(ii);
3179 if (ActuallyMerged.Contains(iedge)) {
3181 // Record merged edge in the map
3182 TopAbs_Orientation orient = iedge.Orientation();
3183 if (!isForward) orient = TopAbs::Reverse(orient);
3184 if (!seqMergedWithBoundOri(ii)) orient = TopAbs::Reverse(orient);
3185 MergedWithBound.ChangeFind(iedge) = MergedEdge.Oriented(orient);
3187 else MergedWithBound.UnBind(iedge);
3189 if (nbActuallyMerged) {
3190 // Record merged bound in the map
3191 TopAbs_Orientation orient = bound.Orientation();
3192 if (!isForward) orient = TopAbs::Reverse(orient);
3193 MergedWithBound.ChangeFind(bound) = MergedEdge.Oriented(orient);
3195 nbMerged = nbActuallyMerged;
3197 // Remove bound from the map if not finally merged
3198 if (!nbMerged) MergedWithBound.UnBind(bound);
3201 Standard_Boolean isMerged = MergedWithBound.Extent();
3203 // Merge with cutting sections
3204 Handle(BRepTools_ReShape) SectionsReShape = new BRepTools_ReShape;
3205 TopTools_DataMapOfShapeShape MergedWithSections;
3206 if (hasCuttingSections) {
3207 // Iterate on cutting sections
3208 TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3209 for (; its.More(); its.Next()) {
3210 // Retrieve cutting section
3211 TopoDS_Shape section = its.Value();
3212 // Skip section if already merged
3213 if (myMergedEdges.Contains(section)) continue;
3214 // Merge cutting section
3215 TopTools_SequenceOfShape seqMergedWithSection;
3216 TColStd_SequenceOfInteger seqMergedWithSectionOri;
3217 if (MergedNearestEdges(section,seqMergedWithSection,seqMergedWithSectionOri)) {
3218 // Store section in the map
3219 MergedWithSections.Bind(section,section);
3220 // Iterate on edges merged with section
3221 Standard_Integer ii = 1;
3222 while (ii <= seqMergedWithSection.Length()) {
3223 TopoDS_Shape iedge = seqMergedWithSection.Value(ii);
3224 // Remove edge if recorded as merged
3225 Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || MergedWithSections.IsBound(iedge));
3227 if (myBoundSections.IsBound(iedge)) {
3228 // Edge is splitted - check sections
3229 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3230 for (; lit.More() && !isRejected; lit.Next()) {
3231 const TopoDS_Shape& sec = lit.Value();
3232 // Remove edge (bound) if at least one of its sections already merged
3233 isRejected = (myMergedEdges.Contains(sec) || MergedWithSections.IsBound(sec));
3237 if (mySectionBound.IsBound(iedge)) {
3238 // Edge is a section - check bound
3239 const TopoDS_Shape& bnd = mySectionBound(iedge);
3240 // Remove edge (section) if its bound already merged
3241 isRejected = (myMergedEdges.Contains(bnd) || MergedWithSections.IsBound(bnd));
3245 // To the next merged edge
3247 // Remove rejected edge
3248 seqMergedWithSection.Remove(ii);
3249 seqMergedWithSectionOri.Remove(ii);
3252 // Process accepted edge
3253 MergedWithSections.Bind(iedge,iedge);
3257 Standard_Integer nbMerged = seqMergedWithSection.Length();
3259 // Create same parameter edge
3260 TopTools_MapOfShape ActuallyMerged;
3261 TopoDS_Edge MergedEdge = SameParameterEdge(section,seqMergedWithSection,
3262 seqMergedWithSectionOri,
3263 ActuallyMerged,SectionsReShape);
3264 Standard_Boolean isForward = Standard_False;
3265 if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3266 // Process actually merged edges
3267 Standard_Integer nbActuallyMerged = 0;
3268 for (ii = 1; ii <= nbMerged; ii++) {
3269 TopoDS_Shape iedge = seqMergedWithSection(ii);
3270 if (ActuallyMerged.Contains(iedge)) {
3272 // Record merged edge in the map
3273 TopAbs_Orientation orient = iedge.Orientation();
3274 if (!isForward) orient = TopAbs::Reverse(orient);
3275 if (!seqMergedWithSectionOri(ii)) orient = TopAbs::Reverse(orient);
3276 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3277 MergedWithSections.ChangeFind(iedge) = oedge;
3278 ReplaceEdge(myReShape->Apply(iedge),oedge,SectionsReShape);
3280 else MergedWithSections.UnBind(iedge);
3282 if (nbActuallyMerged) {
3283 // Record merged section in the map
3284 TopAbs_Orientation orient = section.Orientation();
3285 if (!isForward) orient = TopAbs::Reverse(orient);
3286 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3287 MergedWithSections.ChangeFind(section) = oedge;
3288 ReplaceEdge(myReShape->Apply(section),oedge,SectionsReShape);
3290 nbMerged = nbActuallyMerged;
3292 // Remove section from the map if not finally merged
3293 if (!nbMerged) MergedWithSections.UnBind(section);
3295 else if (isMerged) {
3296 // Reject merging of sections
3297 MergedWithSections.Clear();
3302 Standard_Boolean isMergedSplit = MergedWithSections.Extent();
3304 if (!isMerged && !isMergedSplit) {
3305 // Nothing was merged in this iteration
3307 // Replace previously splitted bound
3308 myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3310 // else if (hasCuttingSections) {
3311 // myBoundSections.UnBind(bound); //szv: are you sure ???
3316 // Set splitting flag
3317 Standard_Boolean isSplitted = ((!isMerged && isMergedSplit) || isPrevSplit);
3319 // Choose between bound and sections merging
3320 if (isMerged && isMergedSplit && !isPrevSplit) {
3321 // Fill map of merged cutting sections
3322 TopTools_MapOfShape MapSplitEdges;
3323 TopTools_DataMapIteratorOfDataMapOfShapeShape itm;
3324 for (itm.Initialize(MergedWithSections); itm.More(); itm.Next()) {
3325 TopoDS_Shape edge = itm.Key();
3326 MapSplitEdges.Add(edge);
3328 // Iterate on edges merged with bound
3329 for (itm.Initialize(MergedWithBound); itm.More(); itm.Next()) {
3330 // Retrieve edge merged with bound
3331 TopoDS_Shape edge = itm.Key();
3332 // Remove edge from the map
3333 if (MapSplitEdges.Contains(edge)) MapSplitEdges.Remove(edge);
3334 if (myBoundSections.IsBound(edge)) {
3335 // Edge has cutting sections
3336 TopTools_ListIteratorOfListOfShape its(myBoundSections(edge));
3337 for (; its.More(); its.Next()) {
3338 TopoDS_Shape sec = its.Value();
3339 // Remove section from the map
3340 if (MapSplitEdges.Contains(sec)) MapSplitEdges.Remove(sec);
3344 // Calculate section merging tolerance
3345 Standard_Real MinSplitTol = RealLast();
3346 TopTools_MapIteratorOfMapOfShape im(MapSplitEdges);
3347 for (; im.More(); im.Next()) {
3348 TopoDS_Edge edge = TopoDS::Edge(MergedWithSections(im.Key()));
3349 MinSplitTol = Min(MinSplitTol,BRep_Tool::Tolerance(edge));
3351 // Calculate bound merging tolerance
3352 TopoDS_Edge BoundEdge = TopoDS::Edge(MergedWithBound(bound));
3353 Standard_Real BoundEdgeTol = BRep_Tool::Tolerance(BoundEdge);
3354 isSplitted = ((MinSplitTol < BoundEdgeTol+MinTolerance()) || myNonmanifold);
3355 isSplitted = (!MapSplitEdges.IsEmpty() && isSplitted);
3359 // Merging of cutting sections
3360 //myMergedEdges.Add(bound);
3361 myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3362 TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithSections);
3363 for (; itm.More(); itm.Next()) {
3364 TopoDS_Shape oldedge = itm.Key();
3365 TopoDS_Shape newedge = SectionsReShape->Apply(itm.Value());
3366 ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3367 myMergedEdges.Add(oldedge);
3368 if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3373 // Merging of initial bound
3374 TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithBound);
3375 //myMergedEdges.Add(bound);
3376 for (; itm.More(); itm.Next()) {
3377 TopoDS_Shape oldedge = itm.Key();
3378 TopoDS_Shape newedge = itm.Value();
3379 ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3380 myMergedEdges.Add(oldedge);
3381 if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3383 if (myBoundSections.IsBound(bound)) myBoundSections.UnBind(bound);
3384 if(!myMergedEdges.Contains(bound))
3385 myMergedEdges.Add(bound);
3389 myNbVertices = myVertexNode.Extent() + myVertexNodeFree.Extent();
3390 myNodeSections.Clear();
3391 myVertexNode.Clear();
3392 myVertexNodeFree.Clear();
3393 myCuttingNode.Clear();
3396 //=======================================================================
3397 //function : MergedNearestEdges
3399 //=======================================================================
3401 Standard_Boolean BRepBuilderAPI_Sewing::MergedNearestEdges(const TopoDS_Shape& edge,
3402 TopTools_SequenceOfShape& SeqMergedEdge,
3403 TColStd_SequenceOfInteger& SeqMergedOri)
3405 // Retrieve edge nodes
3406 TopoDS_Vertex no1, no2;
3407 TopExp::Vertices(TopoDS::Edge(edge),no1,no2);
3408 TopoDS_Shape nno1 = no1, nno2 = no2;
3409 Standard_Boolean isNode1 = myVertexNode.Contains(no1);
3410 Standard_Boolean isNode2 = myVertexNode.Contains(no2);
3411 if (isNode1) nno1 = myVertexNode.FindFromKey(no1);
3412 if (isNode2) nno2 = myVertexNode.FindFromKey(no2);
3414 // Fill map of nodes connected to the node #1
3415 TopTools_MapOfShape mapVert1;
3417 if (myCuttingNode.IsBound(nno1)) {
3418 TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno1));
3419 for (; ilv.More(); ilv.Next()) {
3420 TopoDS_Shape v1 = ilv.Value();
3422 if (!isNode1 && myCuttingNode.IsBound(v1)) {
3423 TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3424 for (; ilvn.More(); ilvn.Next()) {
3425 TopoDS_Shape vn = ilvn.Value();
3432 // Fill map of nodes connected to the node #2
3433 TopTools_MapOfShape mapVert2;
3435 if (myCuttingNode.IsBound(nno2)) {
3436 TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno2));
3437 for (; ilv.More(); ilv.Next()) {
3438 TopoDS_Shape v1 = ilv.Value();
3440 if (!isNode2 && myCuttingNode.IsBound(v1)) {
3441 TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3442 for (; ilvn.More(); ilvn.Next()) {
3443 TopoDS_Shape vn = ilvn.Value();
3450 // Find all possible contigous edges
3451 TopTools_SequenceOfShape seqEdges;
3452 seqEdges.Append(edge);
3453 TopTools_MapOfShape mapEdges;
3455 for (TopTools_MapIteratorOfMapOfShape imv1(mapVert1); imv1.More(); imv1.Next()) {
3456 TopoDS_Shape node1 = imv1.Key();
3457 if (!myNodeSections.IsBound(node1)) continue;
3458 TopTools_ListIteratorOfListOfShape ilsec(myNodeSections(node1));
3459 for (; ilsec.More(); ilsec.Next()) {
3460 TopoDS_Shape sec = ilsec.Value();
3461 if (sec.IsSame(edge)) continue;
3462 // Retrieve section nodes
3463 TopoDS_Vertex vs1, vs2;
3464 TopExp::Vertices(TopoDS::Edge(sec),vs1,vs2);
3465 TopoDS_Shape vs1n = vs1, vs2n = vs2;
3466 if (myVertexNode.Contains(vs1)) vs1n = myVertexNode.FindFromKey(vs1);
3467 if (myVertexNode.Contains(vs2)) vs2n = myVertexNode.FindFromKey(vs2);
3468 if ((mapVert1.Contains(vs1n) && mapVert2.Contains(vs2n)) ||
3469 (mapVert1.Contains(vs2n) && mapVert2.Contains(vs1n)))
3470 if (mapEdges.Add(sec)) {
3471 // Check for rejected cutting
3472 Standard_Boolean isRejected = myMergedEdges.Contains(sec);
3473 if(!isRejected && myBoundSections.IsBound(sec))
3475 TopTools_ListIteratorOfListOfShape its(myBoundSections(sec));
3476 for (; its.More() && !isRejected; its.Next()) {
3477 TopoDS_Shape section = its.Value();
3479 if (myMergedEdges.Contains(section))
3480 isRejected = Standard_True;
3483 if( !isRejected && mySectionBound.IsBound(sec)) {
3484 const TopoDS_Shape& bnd = mySectionBound(sec);
3485 isRejected = (!myBoundSections.IsBound(bnd) ||
3486 myMergedEdges.Contains(bnd));
3489 if (!isRejected) seqEdges.Append(sec);
3496 Standard_Boolean success = Standard_False;
3498 Standard_Integer nbSection = seqEdges.Length();
3499 if (nbSection > 1) {
3500 // Find the longest edge CCI60011
3501 Standard_Integer i, indRef = 1;
3502 if (myNonmanifold) {
3503 Standard_Real lenRef = 0.;
3504 for (i = 1; i <= nbSection; i++) {
3506 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(seqEdges(i)), f, l);
3507 GeomAdaptor_Curve cAdapt(c3d);
3508 Standard_Real len = GCPnts_AbscissaPoint::Length(cAdapt, f, l);
3509 if (len > lenRef) { indRef = i; lenRef = len; }
3512 TopoDS_Shape longEdge = seqEdges(indRef);
3513 seqEdges(indRef) = seqEdges(1);
3514 seqEdges(1) = longEdge;
3518 // Find merging candidates
3519 TColStd_SequenceOfInteger seqForward;
3520 TColStd_SequenceOfInteger seqCandidates;
3521 TColStd_IndexedMapOfInteger mapReference;
3522 mapReference.Add(1); // Add index of reference section
3523 if (FindCandidates(seqEdges,mapReference,seqCandidates,seqForward)) {
3524 Standard_Integer nbCandidates = seqCandidates.Length();
3525 // Check if reference section is merged reversed
3526 Standard_Boolean toReverse = Standard_False;
3528 // Find reference edge in candidates
3529 Standard_Boolean isFound = Standard_False;
3530 for (i = 1; i <= nbCandidates && !isFound; i++) {
3531 isFound = (seqCandidates(i) == indRef);
3533 // Record orientation
3534 toReverse = !seqForward(i);
3535 // Restore first edge
3536 seqCandidates(i) = 1;
3540 // Fail if reference is not in candidates
3541 if (!isFound) return Standard_False;
3543 // Record candidate sections
3544 for (i = 1; i <= nbCandidates; i++) {
3545 // Retrieve merged edge
3546 TopoDS_Shape iedge = seqEdges(seqCandidates(i));
3547 Standard_Integer ori =
3548 ((seqForward(i) && toReverse) || (!seqForward(i) && !toReverse))? 0 : 1;
3549 SeqMergedEdge.Append(iedge);
3550 SeqMergedOri.Append(ori);
3551 if (!myNonmanifold) break;
3553 success = nbCandidates;
3560 //=======================================================================
3561 //function : Cutting
3562 //purpose : Modifies :
3566 //=======================================================================
3568 void BRepBuilderAPI_Sewing::Cutting(const Handle(Message_ProgressIndicator)& thePI)
3570 Standard_Integer i, nbVertices = myVertexNode.Extent();
3571 if (!nbVertices) return;
3572 // Create a sort box with vertices
3573 Standard_Real eps = myTolerance*0.5;
3574 Handle(Bnd_HArray1OfBox) hSetBoxes = new Bnd_HArray1OfBox(1,nbVertices);
3575 for (i = 1; i <= nbVertices; i++) {
3576 gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(myVertexNode.FindKey(i)));
3580 hSetBoxes->ChangeValue(i) = aBox;
3582 Handle(Geom_Curve) c3d;
3583 TopLoc_Location loc;
3584 Standard_Real first, last;
3585 // Iterate on all boundaries
3586 Standard_Integer nbBounds = myBoundFaces.Extent();
3587 Message_ProgressSentry aPS (thePI, "Cutting bounds", 0, nbBounds, 1);
3588 for (i = 1; i <= nbBounds && aPS.More(); i++, aPS.Next()) {
3589 const TopoDS_Edge& bound = TopoDS::Edge(myBoundFaces.FindKey(i));
3590 // Do not cut floating edges
3591 if (!myBoundFaces(i).Extent()) continue;
3592 // Create cutting sections
3593 TopTools_ListOfShape listSections;
3594 { //szv: Use brackets to destroy local variables
3595 // Obtain bound curve
3596 c3d = BRep_Tool::Curve(bound, loc, first, last);
3597 if (!loc.IsIdentity()) {
3598 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3599 c3d->Transform(loc.Transformation());
3601 // Obtain candidate vertices
3602 TopoDS_Vertex V1, V2;
3603 TopTools_IndexedMapOfShape CandidateVertices;
3604 { //szv: Use brackets to destroy local variables
3605 // Create bounding box around curve
3607 GeomAdaptor_Curve adptC(c3d,first,last);
3608 BndLib_Add3dCurve::Add(adptC,myTolerance,aGlobalBox);
3609 // Sort vertices to find candidates
3610 TColStd_ListOfInteger listIndex;
3611 SortBox(hSetBoxes,aGlobalBox,listIndex);
3612 // Skip bound if no node is in the boundind box
3613 if (!listIndex.Extent()) continue;
3614 // Retrieve bound nodes
3615 TopExp::Vertices(bound,V1,V2);
3616 const TopoDS_Shape& Node1 = myVertexNode.FindFromKey(V1);
3617 const TopoDS_Shape& Node2 = myVertexNode.FindFromKey(V2);
3618 // Fill map of candidate vertices
3619 TColStd_ListIteratorOfListOfInteger itl(listIndex);
3620 for (; itl.More(); itl.Next()) {
3621 const Standard_Integer index = itl.Value();
3622 const TopoDS_Shape& Node = myVertexNode.FindFromIndex(index);
3623 if (!Node.IsSame(Node1) && !Node.IsSame(Node2)) {
3624 TopoDS_Shape vertex = myVertexNode.FindKey(index);
3625 CandidateVertices.Add(vertex);
3629 Standard_Integer nbCandidates = CandidateVertices.Extent();
3630 if (!nbCandidates) continue;
3631 // Project vertices on curve
3632 TColStd_Array1OfReal arrPara(1,nbCandidates), arrDist(1,nbCandidates);
3633 TColgp_Array1OfPnt arrPnt(1,nbCandidates), arrProj(1,nbCandidates);
3634 for (Standard_Integer j = 1; j <= nbCandidates; j++)
3635 arrPnt(j) = BRep_Tool::Pnt(TopoDS::Vertex(CandidateVertices(j)));
3636 ProjectPointsOnCurve(arrPnt,c3d,first,last,arrDist,arrPara,arrProj,Standard_True);
3637 // Create cutting nodes
3638 TopTools_SequenceOfShape seqNode;
3639 TColStd_SequenceOfReal seqPara;
3640 CreateCuttingNodes(CandidateVertices,bound,
3641 V1,V2,arrDist,arrPara,arrProj,seqNode,seqPara);
3642 if (!seqPara.Length()) continue;
3643 // Create cutting sections
3644 CreateSections(bound, seqNode, seqPara, listSections);
3646 if (listSections.Extent() > 1) {
3647 // modification of maps:
3649 TopTools_ListIteratorOfListOfShape its(listSections);
3650 for (; its.More(); its.Next()) {
3651 TopoDS_Shape section = its.Value();
3652 // Iterate on section vertices
3653 for (TopoDS_Iterator itv(section); itv.More(); itv.Next()) {
3654 TopoDS_Shape vertex = itv.Value();
3655 // Convert vertex to node
3656 if (myVertexNode.Contains(vertex))
3657 vertex = TopoDS::Vertex(myVertexNode.FindFromKey(vertex));
3658 // Update node sections
3659 if (myNodeSections.IsBound(vertex))
3660 myNodeSections.ChangeFind(vertex).Append(section);
3662 TopTools_ListOfShape lsec;
3663 lsec.Append(section);
3664 myNodeSections.Bind(vertex,lsec);
3667 // Store bound for section
3668 mySectionBound.Bind(section,bound);
3670 // Store splitted bound
3671 myBoundSections.Bind(bound,listSections);
3675 cout << "From " << nbBounds << " bounds " << myBoundSections.Extent()
3676 << " were cut into " << mySectionBound.Extent() << " sections" << endl;
3680 //=======================================================================
3681 //function : GetSeqEdges
3683 //=======================================================================
3685 static void GetSeqEdges(const TopoDS_Shape& edge,
3686 TopTools_SequenceOfShape& seqEdges,
3687 TopTools_DataMapOfShapeListOfShape& VertEdge)
3689 Standard_Integer numV = 0;
3690 for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3691 TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3693 if (VertEdge.IsBound(V1)) {
3694 const TopTools_ListOfShape& listEdges = VertEdge.Find(V1);
3695 for (TopTools_ListIteratorOfListOfShape lIt(listEdges); lIt.More(); lIt.Next()) {
3696 TopoDS_Shape edge1 = lIt.Value();
3697 if (edge1.IsSame(edge)) continue;
3698 Standard_Boolean isContained = Standard_False;
3699 Standard_Integer i, index = 1;
3700 for (i = 1; i <= seqEdges.Length() && !isContained; i++) {
3701 isContained = seqEdges.Value(i).IsSame(edge1);
3702 if (!isContained && seqEdges.Value(i).IsSame(edge)) index = i;
3705 if (numV == 1) seqEdges.InsertBefore(index,edge1);
3706 else seqEdges.InsertAfter(index,edge1);
3707 GetSeqEdges(edge1,seqEdges,VertEdge);
3714 //=======================================================================
3715 //function : GetFreeWires
3717 //=======================================================================
3719 void BRepBuilderAPI_Sewing::GetFreeWires(TopTools_MapOfShape& MapFreeEdges, TopTools_SequenceOfShape& seqWires)
3721 TopTools_DataMapOfShapeListOfShape VertEdge;
3722 TopTools_MapIteratorOfMapOfShape itMap(MapFreeEdges);
3723 TopTools_SequenceOfShape seqFreeEdges;
3724 for (; itMap.More(); itMap.Next()) {
3725 TopoDS_Shape edge = itMap.Key();
3726 seqFreeEdges.Append(edge);
3727 for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3728 TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3729 if (VertEdge.IsBound(V1))
3730 VertEdge.ChangeFind(V1).Append(edge);
3732 TopTools_ListOfShape ls;
3734 VertEdge.Bind(V1,ls);
3739 Standard_Integer i, j;
3740 for (i = 1; i <= seqFreeEdges.Length(); i++) {
3741 TopTools_SequenceOfShape seqEdges;
3742 TopoDS_Shape edge = seqFreeEdges.Value(i);
3743 if (!MapFreeEdges.Contains(edge)) continue;
3744 seqEdges.Append(edge);
3745 GetSeqEdges(edge,seqEdges,VertEdge);
3748 for (j = 1; j <= seqEdges.Length(); j++) {
3749 B.Add(wire,seqEdges.Value(j));
3750 MapFreeEdges.Remove(seqEdges.Value(j));
3752 seqWires.Append(wire);
3753 if (MapFreeEdges.IsEmpty()) break;
3757 //=======================================================================
3758 //function : IsDegeneratedWire
3759 //purpose : internal use
3760 //=======================================================================
3762 static Standard_Boolean IsDegeneratedWire(const TopoDS_Shape& wire)
3764 if (wire.ShapeType() != TopAbs_WIRE) return Standard_False;
3765 // Get maximal vertices tolerance
3766 TopoDS_Vertex V1,V2;
3767 //TopExp::Vertices(TopoDS::Wire(wire),V1,V2);
3768 //Standard_Real tol = Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3769 Standard_Real wireLength = 0.0;
3770 TopLoc_Location loc;
3771 Standard_Real first, last;
3772 Standard_Integer nume = 0;
3773 Standard_Integer isSmall = 0;
3774 for (TopoDS_Iterator aIt(wire,Standard_False); aIt.More(); aIt.Next()) {
3776 TopoDS_Shape edge = aIt.Value();
3777 TopoDS_Vertex Ve1,Ve2;
3778 TopExp::Vertices(TopoDS::Edge(edge),Ve1,Ve2);
3786 else if(Ve1.IsSame(V2))
3790 else if(Ve2.IsSame(V2))
3793 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aIt.Value()),loc,first,last);
3794 if (!c3d.IsNull()) {
3795 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3796 if (!loc.IsIdentity()) {
3797 //c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3798 c3d->Transform(loc.Transformation());
3800 gp_Pnt pfirst = c3d->Value(first);
3801 gp_Pnt plast = c3d->Value(last);
3802 gp_Pnt pmid = c3d->Value((first +last)*0.5);
3803 Standard_Real length =0;
3804 if(pfirst.Distance(plast) > pfirst.Distance(pmid)) {
3805 length = pfirst.Distance(plast);
3808 GeomAdaptor_Curve cAdapt(c3d);
3809 length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3811 Standard_Real tole = BRep_Tool::Tolerance(Ve1)+BRep_Tool::Tolerance(Ve2);
3812 if(length <= tole) isSmall++;
3813 wireLength += length;
3816 if(isSmall == nume) return Standard_True;
3817 Standard_Real tol = BRep_Tool::Tolerance(V1)+BRep_Tool::Tolerance(V2);//Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3818 if (wireLength > tol) return Standard_False;
3819 return Standard_True;
3822 //=======================================================================
3823 //function : DegeneratedSection
3824 //purpose : internal use
3825 // create a new degenerated edge if the section is degenerated
3826 //=======================================================================
3828 static TopoDS_Edge DegeneratedSection(const TopoDS_Shape& section, const TopoDS_Shape& face)
3830 // Return if section is already degenerated
3831 if (BRep_Tool::Degenerated(TopoDS::Edge(section))) return TopoDS::Edge(section);
3833 // Retrieve edge curve
3834 TopLoc_Location loc;
3835 Standard_Real first, last;
3836 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(section), loc, first, last);
3837 if (c3d.IsNull()) { //gka
3839 TopoDS_Edge edge1 = TopoDS::Edge(section);
3840 aB.Degenerated(edge1, Standard_True);
3843 if (!loc.IsIdentity()) {
3844 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3845 c3d->Transform(loc.Transformation());
3848 // Test if the new edge is degenerated
3849 TopoDS_Vertex v1,v2;
3850 TopExp::Vertices(TopoDS::Edge(section),v1,v2);
3851 //Standard_Real tol = Max(BRep_Tool::Tolerance(v1),BRep_Tool::Tolerance(v2));
3852 //tol = Max(tolerance,tol);
3855 p1 = BRep_Tool::Pnt(v1);
3856 p3 = BRep_Tool::Pnt(v2);
3857 c3d->D0(0.5*(first + last),p2);
3859 //Standard_Boolean isDegenerated = Standard_False;
3860 //if (p1.Distance(p3) < tol) {
3861 //GeomAdaptor_Curve cAdapt(c3d);
3862 //Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3863 //isDegenerated = Standard_True; //(length < tol);
3867 //if (!isDegenerated) return edge;
3870 BRep_Builder aBuilder;
3871 edge = TopoDS::Edge(section);
3873 if (v1.IsSame(v2)) {
3874 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3875 aBuilder.Add(anEdge, v1.Oriented(TopAbs_FORWARD));
3876 aBuilder.Add(anEdge, v2.Oriented(TopAbs_REVERSED));
3879 TopoDS_Vertex newVertex;
3880 if (p1.Distance(p3) < BRep_Tool::Tolerance(v1))
3882 else if (p1.Distance(p3) < BRep_Tool::Tolerance(v2))
3885 Standard_Real d1 = BRep_Tool::Tolerance(v1) + p2.Distance(p1);
3886 Standard_Real d2 = BRep_Tool::Tolerance(v2) + p2.Distance(p3);
3887 Standard_Real newTolerance = Max(d1,d2);
3888 aBuilder.MakeVertex(newVertex, p2, newTolerance);
3890 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3891 aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_FORWARD));
3892 aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_REVERSED));
3895 BRep_Tool::Range(TopoDS::Edge(section), first, last);
3896 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3897 aBuilder.Range(TopoDS::Edge(anEdge), first, last);
3898 aBuilder.Degenerated(edge, Standard_True);
3899 Handle(Geom_Curve) aC3dNew;
3900 if (!face.IsNull()) {
3901 Standard_Real af,al;
3902 Handle(Geom2d_Curve) aC2dt = BRep_Tool::CurveOnSurface(TopoDS::Edge(section),TopoDS::Face(face),af,al);
3903 aBuilder.UpdateEdge(edge,aC3dNew,0);
3904 Handle(Geom2d_Curve) aC2dn = BRep_Tool::CurveOnSurface(edge,TopoDS::Face(face),af,al);
3906 aBuilder.UpdateEdge(edge,aC2dt,TopoDS::Face(face),0);
3912 //=======================================================================
3913 //function : EdgeProcessing
3914 //purpose : modifies :
3916 // myHasMultipleEdge
3918 // . if multiple edge
3919 // - length < 100.*myTolerance -> several free edge
3920 // . if no multiple edge
3921 // - make the contigous edges sameparameter
3922 //=======================================================================
3924 void BRepBuilderAPI_Sewing::EdgeProcessing(const Handle(Message_ProgressIndicator)& thePI)
3926 // constructs sectionEdge
3927 TopTools_MapOfShape MapFreeEdges;
3928 TopTools_DataMapOfShapeShape EdgeFace;
3929 Message_ProgressSentry aPS (thePI, "Edge processing", 0, myBoundFaces.Extent(), 1);
3930 for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
3931 const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
3932 const TopTools_ListOfShape& listFaces = myBoundFaces(i);
3933 if (listFaces.Extent() == 1) {
3934 if (myBoundSections.IsBound(bound)) {
3935 TopTools_ListIteratorOfListOfShape liter(myBoundSections(bound));
3936 for (; liter.More(); liter.Next()) {
3937 if (!myMergedEdges.Contains(liter.Value())) { //myReShape->IsRecorded(liter.Value())) {
3938 TopoDS_Shape edge = myReShape->Apply(liter.Value());
3939 if (!MapFreeEdges.Contains(edge)) {
3940 TopoDS_Shape face = listFaces.First();
3941 EdgeFace.Bind(edge,face);
3942 MapFreeEdges.Add(edge);
3948 if (!myMergedEdges.Contains(bound)) {
3949 TopoDS_Shape edge = myReShape->Apply(bound);
3950 if (!MapFreeEdges.Contains(edge)) {
3951 TopoDS_Shape face = listFaces.First();
3952 EdgeFace.Bind(edge,face);
3953 MapFreeEdges.Add(edge);
3960 if (!MapFreeEdges.IsEmpty()) {
3961 TopTools_SequenceOfShape seqWires;
3962 GetFreeWires(MapFreeEdges,seqWires);
3963 for (Standard_Integer j = 1; j <= seqWires.Length(); j++) {
3964 TopoDS_Wire wire = TopoDS::Wire(seqWires.Value(j));
3965 if (!IsDegeneratedWire(wire)) continue;
3966 for (TopoDS_Iterator Ie(wire,Standard_False); Ie.More(); Ie.Next()) {
3967 TopoDS_Shape aTmpShape = myReShape->Apply(Ie.Value()); //for porting
3968 TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
3970 if (EdgeFace.IsBound(edge))
3971 face = EdgeFace.Find(edge);
3972 TopoDS_Shape degedge = DegeneratedSection(edge,face);
3973 if (degedge.IsNull()) continue;
3974 if (!degedge.IsSame(edge))
3975 ReplaceEdge(edge,degedge,myReShape);
3976 if (BRep_Tool::Degenerated(TopoDS::Edge(degedge)))
3977 myDegenerated.Add(degedge);
3981 myMergedEdges.Clear();
3984 //=======================================================================
3985 //function : CreateSewedShape
3987 //=======================================================================
3989 void BRepBuilderAPI_Sewing::CreateSewedShape()
3991 // ---------------------
3992 // create the new shapes
3993 // ---------------------
3994 BRepTools_Quilt aQuilt;
3995 Standard_Boolean isLocal = !myShape.IsNull();
3998 TopoDS_Shape ns = myReShape->Apply(myShape);
4002 for (i = 1; i <= myOldShapes.Extent(); i++) {
4003 TopoDS_Shape sh = myOldShapes(i);
4005 sh = myReShape->Apply(sh);
4006 myOldShapes(i) = sh;
4007 if (!isLocal) aQuilt.Add(sh);
4010 TopoDS_Shape aNewShape = aQuilt.Shells();
4011 Standard_Integer numsh = 0;
4013 TopTools_IndexedMapOfShape OldShells;
4016 TopoDS_Compound aComp;
4017 aB.MakeCompound(aComp);
4018 for (TopoDS_Iterator aExpSh(aNewShape,Standard_False); aExpSh.More(); aExpSh.Next()) {
4019 TopoDS_Shape sh = aExpSh.Value();
4020 Standard_Boolean hasEdges = Standard_False;
4021 if (sh.ShapeType() == TopAbs_SHELL) {
4023 hasEdges = !OldShells.Contains(sh);
4026 Standard_Integer numf = 0;
4027 for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
4028 face = aExpF.Current();
4031 if (numf == 1) aB.Add(aComp,face);
4032 else if (numf > 1) aB.Add(aComp,sh);
4036 else if (sh.ShapeType() == TopAbs_FACE) {
4037 if (myNonmanifold) {
4042 hasEdges = Standard_True;
4044 else { aB.Add(aComp,sh); numsh++; }
4046 else { aB.Add(aComp,sh); numsh++; }
4047 if (hasEdges) OldShells.Add(sh);
4049 // Process collected shells
4050 if (myNonmanifold) {
4051 Standard_Integer nbOldShells = OldShells.Extent();
4052 if (nbOldShells == 1) {
4053 // Single shell - check for single face
4054 TopoDS_Shape sh = OldShells.FindKey(1);
4056 Standard_Integer numf = 0;
4057 for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
4058 face = aExpF.Current();
4061 if (numf == 1) aB.Add(aComp,face);
4062 else if (numf > 1) aB.Add(aComp,sh);
4065 else if (nbOldShells) {
4066 // Several shells should be merged
4067 TColStd_MapOfInteger IndexMerged;
4068 while (IndexMerged.Extent() < nbOldShells) {
4069 TopoDS_Shell NewShell;
4070 TopTools_MapOfShape NewEdges;
4071 for (i = 1; i <= nbOldShells; i++) {
4072 if (IndexMerged.Contains(i)) continue;
4073 TopoDS_Shell shell = TopoDS::Shell(OldShells.FindKey(i));
4074 if (NewShell.IsNull()) {
4076 aB.MakeShell(NewShell);
4077 TopoDS_Iterator aItSS(shell) ;
4078 for( ; aItSS.More(); aItSS.Next())
4079 aB.Add(NewShell,aItSS.Value())
4081 // Fill map of edges
4082 for (TopExp_Explorer eexp(shell,TopAbs_EDGE); eexp.More(); eexp.Next()) {
4083 TopoDS_Shape edge = eexp.Current();
4089 Standard_Boolean hasSharedEdge = Standard_False;
4090 TopExp_Explorer eexp(shell,TopAbs_EDGE);
4091 for (; eexp.More() && !hasSharedEdge; eexp.Next())
4092 hasSharedEdge = NewEdges.Contains(eexp.Current());
4093 if (hasSharedEdge) {
4094 // Add edges to the map
4095 for (TopExp_Explorer eexp1(shell,TopAbs_EDGE); eexp1.More(); eexp1.Next()) {
4096 TopoDS_Shape edge = eexp1.Current();
4099 // Add faces to the shell
4100 for (TopExp_Explorer fexp(shell,TopAbs_FACE); fexp.More(); fexp.Next()) {
4101 TopoDS_Shape face = fexp.Current();
4102 aB.Add(NewShell,face);
4108 // Process new shell
4110 Standard_Integer numf = 0;
4111 TopExp_Explorer aExpF(NewShell,TopAbs_FACE);
4112 for (; aExpF.More() && (numf < 2); aExpF.Next()) {
4113 face = aExpF.Current();
4116 if (numf == 1) aB.Add(aComp,face);
4117 else if (numf > 1) aB.Add(aComp,NewShell);
4123 // Extract single component
4124 TopoDS_Iterator aIt(aComp,Standard_False);
4125 mySewedShape = aIt.Value();
4128 mySewedShape = aComp;
4131 //=======================================================================
4132 //function : CreateOutputInformations
4133 //purpose : constructs :
4137 // myNbContigousEdges
4138 // myNbMultipleEdges
4140 //=======================================================================
4142 void BRepBuilderAPI_Sewing::CreateOutputInformations()
4144 // Construct edgeSections
4146 //TopTools_DataMapOfShapeListOfShape edgeSections;
4147 TopTools_IndexedDataMapOfShapeListOfShape edgeSections; //use index map for regulating free edges
4148 for (i = 1; i <= myBoundFaces.Extent(); i++) {
4149 const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
4150 TopTools_ListOfShape lsect;
4151 if (myBoundSections.IsBound(bound)) lsect = myBoundSections(bound);
4152 TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
4153 for (; aExp.More(); aExp.Next()) {
4154 TopoDS_Shape sec = bound, edge = aExp.Current();
4155 TopTools_ListIteratorOfListOfShape aI(lsect);
4156 for (; aI.More(); aI.Next()) {
4157 const TopoDS_Shape& section = aI.Value();
4158 if (edge.IsSame(myReShape->Apply(section))) { sec = section; break; }
4160 if (edgeSections.Contains(edge))
4161 edgeSections.ChangeFromKey(edge).Append(sec);
4163 TopTools_ListOfShape listSec;
4164 listSec.Append(sec);
4165 edgeSections.Add(edge,listSec);
4170 // Fill maps of Free, Contigous and Multiple edges
4171 //TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter2(edgeSections);
4172 for (i = 1; i <= edgeSections.Extent(); i++) {
4173 const TopoDS_Shape& edge = edgeSections.FindKey(i);
4174 const TopTools_ListOfShape& listSection = edgeSections(i);
4175 if (listSection.Extent() == 1) {
4176 if (BRep_Tool::Degenerated(TopoDS::Edge(edge)))
4177 myDegenerated.Add(edge);
4179 myFreeEdges.Add(edge);
4181 else if (listSection.Extent() == 2) {
4182 myContigousEdges.Add(edge,listSection);
4185 myMultipleEdges.Add(edge);
4189 // constructs myContigSectBound
4190 TopTools_DataMapOfShapeListOfShape aEdgeMap; //gka
4191 for (i = 1; i <= myBoundFaces.Extent(); i++) {
4192 TopoDS_Shape bound = myBoundFaces.FindKey(i);
4193 if (myBoundSections.IsBound(bound)) {
4194 TopTools_ListIteratorOfListOfShape iter(myBoundSections(bound));
4195 for (; iter.More(); iter.Next()) {
4196 TopoDS_Shape section = iter.Value();
4197 if(!myMergedEdges.Contains(section)) continue;
4198 //if (!myReShape->IsRecorded(section)) continue; // section is free
4199 TopoDS_Shape nedge = myReShape->Apply(section);
4200 if (nedge.IsNull()) continue; //szv debug
4201 if (!bound.IsSame(section))
4202 if (myContigousEdges.Contains(nedge))
4203 myContigSecBound.Bind(section, bound);
4209 //=======================================================================
4210 //function : ProjectPointsOnCurve
4211 //purpose : internal use
4212 //=======================================================================
4214 void BRepBuilderAPI_Sewing::ProjectPointsOnCurve(const TColgp_Array1OfPnt& arrPnt,
4215 const Handle(Geom_Curve)& c3d,
4216 const Standard_Real first,
4217 const Standard_Real last,
4218 TColStd_Array1OfReal& arrDist,
4219 TColStd_Array1OfReal& arrPara,
4220 TColgp_Array1OfPnt& arrProj,
4221 const Standard_Boolean isConsiderEnds) const
4225 GeomAdaptor_Curve GAC(c3d);
4226 Extrema_ExtPC locProj;
4227 locProj.Initialize(GAC, first, last);
4228 gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
4230 for (Standard_Integer i1 = 1; i1 <= arrPnt.Length(); i1++) {
4231 gp_Pnt pt = arrPnt(i1);
4232 Standard_Real worktol = myTolerance;
4233 Standard_Real distF2 = pfirst.SquareDistance(pt);
4234 Standard_Real distL2 = plast.SquareDistance(pt);
4235 Standard_Boolean isProjected = Standard_False;
4238 // Project current point on curve
4239 locProj.Perform(pt);
4240 if (locProj.IsDone() && locProj.NbExt() > 0) {
4241 Standard_Real dist2Min = Min(distF2,distL2);
4242 Standard_Integer ind, indMin = 0;
4243 for (ind = 1; ind <= locProj.NbExt(); ind++) {
4244 Standard_Real dProj2 = locProj.SquareDistance(ind);
4245 if (dProj2 < dist2Min) { indMin = ind; dist2Min = dProj2; }
4248 isProjected = Standard_True;
4249 Extrema_POnCurv pOnC = locProj.Point(indMin);
4250 Standard_Real paramProj = pOnC.Parameter();
4251 gp_Pnt ptProj = GAC.Value(paramProj);
4252 Standard_Real distProj2 = ptProj.SquareDistance(pt);
4253 if (!locProj.IsMin(indMin)) {
4254 if (Min(distF2,distL2) < dist2Min) {
4255 if (distF2 < distL2) {
4267 if (distProj2 < worktol * worktol) {
4268 arrDist(i1) = sqrt (distProj2);
4269 arrPara(i1) = paramProj;
4270 arrProj(i1) = ptProj;
4275 catch (Standard_Failure) {
4276 worktol = MinTolerance();
4278 cout << "Exception in BRepBuilderAPI_Sewing::ProjectPointsOnCurve: ";
4279 Standard_Failure::Caught()->Print(cout); cout << endl;
4282 if (!isProjected && isConsiderEnds) {
4283 if (Min(distF2,distL2) < worktol * worktol) {
4284 if (distF2 < distL2) {
4285 arrDist(i1) = sqrt (distF2);
4286 arrPara(i1) = first;
4287 arrProj(i1) = pfirst;
4290 arrDist(i1) = sqrt (distL2);
4292 arrProj(i1) = plast;
4299 //=======================================================================
4300 //function : CreateCuttingNodes
4301 //purpose : internal use
4302 //=======================================================================
4304 void BRepBuilderAPI_Sewing::CreateCuttingNodes(const TopTools_IndexedMapOfShape& MapVert,
4305 const TopoDS_Shape& bound,
4306 const TopoDS_Shape& vfirst,
4307 const TopoDS_Shape& vlast,
4308 const TColStd_Array1OfReal& arrDist,
4309 const TColStd_Array1OfReal& arrPara,
4310 const TColgp_Array1OfPnt& arrPnt,
4311 TopTools_SequenceOfShape& seqVert,
4312 TColStd_SequenceOfReal& seqPara)
4314 Standard_Integer i, j, nbProj = MapVert.Extent();
4316 // Reorder projections by distance
4317 TColStd_SequenceOfInteger seqOrderedIndex;
4318 { //szv: Use brackets to destroy local variables
4319 TColStd_SequenceOfReal seqOrderedDistance;
4320 for (i = 1; i <= nbProj; i++) {
4321 Standard_Real distProj = arrDist(i);
4322 if (distProj < 0.0) continue; // Skip vertex if not projected
4323 Standard_Boolean isInserted = Standard_False;
4324 for (j = 1; j <= seqOrderedIndex.Length() && !isInserted; j++) {
4325 isInserted = (distProj < seqOrderedDistance(j));
4327 seqOrderedIndex.InsertBefore(j,i);
4328 seqOrderedDistance.InsertBefore(j,distProj);
4332 seqOrderedIndex.Append(i);
4333 seqOrderedDistance.Append(distProj);
4337 nbProj = seqOrderedIndex.Length();
4338 if (!nbProj) return;
4340 BRep_Builder aBuilder;
4342 // Insert two initial vertices (to be removed later)
4343 TColStd_SequenceOfReal seqDist;
4344 TColgp_SequenceOfPnt seqPnt;
4345 { //szv: Use brackets to destroy local variables
4346 // Retrieve bound curve
4347 TopLoc_Location loc;
4348 Standard_Real first,last;
4349 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(bound), loc, first, last);
4350 if (!loc.IsIdentity()) {
4351 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
4352 c3d->Transform(loc.Transformation());
4354 GeomAdaptor_Curve GAC(c3d);
4355 seqVert.Prepend(vfirst); seqVert.Append(vlast);
4356 seqPara.Prepend(first); seqPara.Append(last);
4357 seqDist.Prepend(-1.0); seqDist.Append(-1.0);
4358 seqPnt.Prepend(GAC.Value(first)); seqPnt.Append(GAC.Value(last));
4361 TopTools_DataMapOfShapeShape NodeCuttingVertex;
4362 for (i = 1; i <= nbProj; i++) {
4364 const Standard_Integer index = seqOrderedIndex(i);
4365 Standard_Real disProj = arrDist(index);
4366 gp_Pnt pntProj = arrPnt(index);
4368 // Skip node if already bound to cutting vertex
4369 TopoDS_Shape node = myVertexNode.FindFromKey(MapVert(index));
4370 if (NodeCuttingVertex.IsBound(node)) continue;
4372 // Find the closest vertex
4373 Standard_Integer indexMin = 1;
4374 Standard_Real dist, distMin = pntProj.Distance(seqPnt(1));
4375 for (j = 2; j <= seqPnt.Length(); j++) {
4376 dist = pntProj.Distance(seqPnt(j));
4377 if (dist < distMin) { distMin = dist; indexMin = j; }
4380 // Check if current point is close to one of the existent
4381 if (distMin <= Max(disProj*0.1,MinTolerance())) {
4382 // Check distance if close
4383 Standard_Real jdist = seqDist.Value(indexMin);
4385 // Bind new cutting node (end vertex only)
4386 seqDist.SetValue(indexMin,disProj);
4387 TopoDS_Shape cvertex = seqVert.Value(indexMin);
4388 NodeCuttingVertex.Bind(node,cvertex);
4391 // Bind secondary cutting nodes
4392 NodeCuttingVertex.Bind(node,TopoDS_Vertex());
4396 // Build new cutting vertex
4397 TopoDS_Vertex cvertex;
4398 aBuilder.MakeVertex(cvertex, pntProj, Precision::Confusion());
4399 // Bind new cutting vertex
4400 NodeCuttingVertex.Bind(node,cvertex);
4401 // Insert cutting vertex in the sequences
4402 Standard_Real parProj = arrPara(index);
4403 for (j = 2; j <= seqPara.Length(); j++) {
4404 if (parProj <= seqPara.Value(j)) {
4405 seqVert.InsertBefore(j,cvertex);
4406 seqPara.InsertBefore(j,parProj);
4407 seqDist.InsertBefore(j,disProj);
4408 seqPnt.InsertBefore (j,pntProj);
4415 // filling map for cutting nodes
4416 TopTools_DataMapIteratorOfDataMapOfShapeShape mit(NodeCuttingVertex);
4417 for (; mit.More(); mit.Next()) {
4418 TopoDS_Shape cnode = mit.Value();
4419 // Skip secondary nodes
4420 if (cnode.IsNull()) continue;
4421 // Obtain vertex node
4422 TopoDS_Shape node = mit.Key();
4423 if (myVertexNode.Contains(cnode)) {
4424 // This is an end vertex
4425 cnode = myVertexNode.FindFromKey(cnode);
4428 // Create link: cutting vertex -> node
4429 TopTools_ListOfShape ls;
4431 myCuttingNode.Bind(cnode,ls);
4433 // Create link: node -> cutting vertex
4434 if (myCuttingNode.IsBound(node)) {
4435 myCuttingNode.ChangeFind(node).Append(cnode);
4438 TopTools_ListOfShape ls;
4440 myCuttingNode.Bind(node,ls);
4444 // Remove two initial vertices
4445 seqVert.Remove(1); seqVert.Remove(seqVert.Length());
4446 seqPara.Remove(1); seqPara.Remove(seqPara.Length());
4449 //=======================================================================
4450 //function : CreateSections
4451 //purpose : internal use
4452 //=======================================================================
4454 void BRepBuilderAPI_Sewing::CreateSections(const TopoDS_Shape& section,
4455 const TopTools_SequenceOfShape& seqNode,
4456 const TColStd_SequenceOfReal& seqPara,
4457 TopTools_ListOfShape& listEdge)
4459 const TopoDS_Edge& sec = TopoDS::Edge(section);
4460 // TopAbs_Orientation aInitOr = sec.Orientation();
4463 //To keep NM vertices on edge
4464 TopTools_SequenceOfShape aSeqNMVert;
4465 TColStd_SequenceOfReal aSeqNMPars;
4466 findNMVertices(sec,aSeqNMVert,aSeqNMPars);
4468 BRep_Builder aBuilder;
4470 Standard_Real first, last;
4471 BRep_Tool::Range(sec, first, last);
4473 // Create cutting sections
4474 Standard_Real par1, par2;
4475 TopoDS_Shape V1, V2;
4476 Standard_Integer i, len = seqPara.Length() + 1;
4477 for (i = 1; i <= len; i++) {
4479 TopoDS_Edge edge = sec;
4485 V1 = TopExp::FirstVertex(sec);
4488 else if (i == len) {
4489 par1 = seqPara(i-1);
4492 V2 = TopExp::LastVertex(sec);
4495 par1 = seqPara(i-1);
4501 TopoDS_Shape aTmpShape = edge.Oriented(TopAbs_FORWARD);
4502 TopoDS_Edge aTmpEdge = TopoDS::Edge (aTmpShape); // for porting
4503 aTmpShape = V1.Oriented(TopAbs_FORWARD);
4504 aBuilder.Add(aTmpEdge, aTmpShape);
4505 aTmpShape = V2.Oriented(TopAbs_REVERSED);
4506 aBuilder.Add(aTmpEdge, aTmpShape);
4507 aBuilder.Range(aTmpEdge, par1, par2);
4508 // if(aInitOr == TopAbs_REVERSED)
4509 // listEdge.Prepend(edge);
4512 Standard_Integer k =1;
4513 for( ; k <= aSeqNMPars.Length() ; k++) {
4514 Standard_Real apar = aSeqNMPars.Value(k);
4515 if(apar >= par1 && apar <= par2) {
4516 aBuilder.Add(aTmpEdge,aSeqNMVert.Value(k));
4517 aSeqNMVert.Remove(k);
4518 aSeqNMPars.Remove(k);
4522 listEdge.Append(edge);
4525 const TopTools_ListOfShape& listFaces = myBoundFaces.FindFromKey(sec);
4526 if (!listFaces.Extent()) return;
4528 Standard_Real tolEdge = BRep_Tool::Tolerance(sec);
4530 // Add cutting pcurves
4531 TopTools_ListIteratorOfListOfShape itf(listFaces);
4532 for (; itf.More(); itf.Next()) {
4534 const TopoDS_Face& fac = TopoDS::Face(itf.Value());
4536 // Retrieve curve on surface
4537 Standard_Real first2d=0., last2d=0.,first2d1=0,last2d1=0.;
4538 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(sec, fac, first2d, last2d);
4539 if (c2d.IsNull()) continue;
4540 Handle(Geom2d_Curve) c2d1;
4541 Standard_Boolean isSeam = BRep_Tool::IsClosed(sec,fac);
4543 //gka - Convert to BSpline was commented because
4544 //it is not necessary to create BSpline instead of Lines or cIrcles.
4545 //Besides after conversion circles to BSpline
4546 //it is necessary to recompute parameters of cutting because paramerization of created
4547 //BSpline curve differs from parametrization of circle.
4549 // Convert pcurve to BSpline
4550 /*Handle(Geom2d_BSplineCurve) c2dBSP,c2dBSP1;
4551 if (c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
4552 c2dBSP = Handle(Geom2d_BSplineCurve)::DownCast(c2d);
4555 if (first > (c2d->FirstParameter() + Precision::PConfusion()) ||
4556 last < (c2d->LastParameter() - Precision::PConfusion())) {
4557 Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d, first, last);
4558 c2dBSP = Geom2dConvert::CurveToBSplineCurve(TC);
4560 else c2dBSP = Geom2dConvert::CurveToBSplineCurve(c2d);
4562 if (c2dBSP.IsNull()) continue;*/
4563 //gka fix for bug OCC12203 21.04.06 addition second curve for seam edges
4567 TopoDS_Edge secRev = TopoDS::Edge(sec.Reversed());
4569 c2d1 = BRep_Tool::CurveOnSurface(secRev, fac, first2d1, last2d1);
4570 if (c2d1.IsNull()) continue;
4572 /*if (c2d1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
4573 c2dBSP1 = Handle(Geom2d_BSplineCurve)::DownCast(c2d1);
4576 if (first > (c2d1->FirstParameter() + Precision::PConfusion()) ||
4577 last < (c2d1->LastParameter() - Precision::PConfusion())) {
4578 Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d1, first, last);
4579 //c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(TC);
4581 //else c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(c2d);
4586 /*first2d = c2dBSP->FirstParameter();
4587 last2d = c2dBSP->LastParameter();
4589 if(!c2dBSP1.IsNull()) {
4590 first2d1 = c2dBSP1->FirstParameter();
4591 last2d1 = c2dBSP1->LastParameter();
4594 // Update cutting sections
4595 Handle(Geom2d_Curve) c2dNew,c2d1New;
4596 TopTools_ListIteratorOfListOfShape ite(listEdge);
4597 for (; ite.More(); ite.Next()) {
4599 // Retrieve cutting section
4600 const TopoDS_Edge& edge = TopoDS::Edge(ite.Value());
4601 BRep_Tool::Range(edge, par1, par2);
4603 // Cut BSpline pcurve
4605 c2dNew = Handle(Geom2d_Curve)::DownCast(c2d->Copy());
4606 //c2dNew = Handle(Geom2d_Curve)::DownCast(c2dBSP->Copy());
4607 //Handle(Geom2d_BSplineCurve)::DownCast(c2dNew)->Segment(Max(first2d,par1),Min(par2,last2d));
4608 if(!c2d1.IsNull()) { //if(!c2dBSP1.IsNull()) {
4609 c2d1New = Handle(Geom2d_Curve)::DownCast(c2d1->Copy());
4610 //c2d1New = Handle(Geom2d_Curve)::DownCast(c2dBSP1->Copy());
4611 //Handle(Geom2d_BSplineCurve)::DownCast(c2d1New)->Segment(Max(first2d1,par1),Min(par2,last2d1));
4614 /*catch (Standard_Failure) {
4616 cout << "Exception in CreateSections: segment [" << par1 << "," << par2 << "]: ";
4617 Standard_Failure::Caught()->Print(cout); cout << endl;
4619 Handle(Geom2d_TrimmedCurve) c2dT = new Geom2d_TrimmedCurve(c2dNew,Max(first2d,par1),Min(par2,last2d));
4624 if(!isSeam && c2d1New.IsNull())
4625 aBuilder.UpdateEdge(edge, c2dNew, fac, tolEdge);
4627 TopAbs_Orientation Ori = edge.Orientation();
4628 if(fac.Orientation() == TopAbs_REVERSED)
4629 Ori = TopAbs::Reverse(Ori);
4631 if(Ori == TopAbs_FORWARD)
4632 aBuilder.UpdateEdge(edge, c2dNew,c2d1New ,fac, tolEdge);
4634 aBuilder.UpdateEdge(edge, c2d1New,c2dNew ,fac, tolEdge);
4640 //=======================================================================
4641 //function : SameParameterShape
4643 //=======================================================================
4645 void BRepBuilderAPI_Sewing::SameParameterShape()
4647 if (!mySameParameterMode) return;
4648 TopExp_Explorer exp(mySewedShape, TopAbs_EDGE);
4649 // Le flag sameparameter est a false pour chaque edge cousue
4650 for (; exp.More(); exp.Next()) {
4651 const TopoDS_Edge& sec = TopoDS::Edge(exp.Current());
4654 BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec));
4656 catch (Standard_Failure) {
4658 cout << "Fail: BRepBuilderAPI_Sewing::SameParameterShape exception in BRepLib::SameParameter" << endl;