1 // Created on: 1995-03-24
2 // Created by: Jing Cheng MEI
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
22 // dcl CCI60011 : Correction of degeneratedSection
23 // Improvement of SameParameter Edge to treat case of failure in BRepLib::SameParameter
24 // dcl Thu Aug 20 09:24:49 1998
25 // Suppression of little faces.
26 // dcl Fri Aug 7 15:27:46 1998
27 // Refection of function SameParameter Edge.
28 // Merge on the edge which has the less of poles.
29 // Suppression of the Connected Edge function.
30 // dcl Tue Jun 9 14:21:53 1998
31 // Do not merge edge if they belong the same face
32 // Tolerance management in VerticesAssembling
33 // Tolerance management in Cutting
34 // dcl Thu May 14 15:51:46 1998
35 // optimization of cutting
36 // dcl Thu May 7 15:51:46 1998
37 // Add of cutting option
38 // Add of SameParameter call
42 //-- dpf December 10 1997 Processing of pcurve collections
44 //rln 02.02.99 BUC60449 Making compilable on NT in DEB mode
45 //rln 02.02.99 BUC60449 Protection against exception on NT
49 #include <BRepBuilderAPI_Sewing.ixx>
51 #include <Bnd_Box.hxx>
52 #include <Bnd_Box2d.hxx>
53 #include <Bnd_HArray1OfBox.hxx>
54 #include <BndLib_Add2dCurve.hxx>
55 #include <BndLib_Add3dCurve.hxx>
56 #include <BRep_Builder.hxx>
57 #include <BRep_Tool.hxx>
58 #include <BRepLib.hxx>
59 #include <BRepTools_Quilt.hxx>
60 #include <BSplCLib.hxx>
61 #include <Extrema_ExtPC.hxx>
62 #include <GCPnts_AbscissaPoint.hxx>
63 #include <GCPnts_UniformAbscissa.hxx>
64 #include <GCPnts_UniformDeflection.hxx>
65 #include <Geom2d_BezierCurve.hxx>
66 #include <Geom2d_BSplineCurve.hxx>
67 #include <Geom2d_Curve.hxx>
68 #include <Geom2d_Line.hxx>
69 #include <Geom2d_TrimmedCurve.hxx>
70 #include <Geom2dAdaptor_Curve.hxx>
71 #include <Geom2dConvert.hxx>
72 #include <Geom_BezierCurve.hxx>
73 #include <Geom_BSplineCurve.hxx>
74 #include <Geom_Curve.hxx>
75 #include <Geom_Line.hxx>
76 #include <Geom_Surface.hxx>
77 #include <GeomAdaptor_Curve.hxx>
78 #include <GeomAdaptor_Surface.hxx>
79 #include <GeomLib.hxx>
82 //#include <LocalAnalysis_SurfaceContinuity.hxx>
83 #include <Precision.hxx>
84 #include <Standard_ErrorHandler.hxx>
85 #include <Standard_Failure.hxx>
86 #include <TColgp_Array1OfVec.hxx>
87 #include <TColgp_SequenceOfPnt.hxx>
88 #include <TColStd_Array1OfInteger.hxx>
89 #include <TColStd_Array1OfReal.hxx>
90 #include <TColStd_DataMapIteratorOfDataMapOfIntegerListOfInteger.hxx>
91 #include <TColStd_DataMapOfIntegerListOfInteger.hxx>
92 #include <TColStd_IndexedMapOfInteger.hxx>
93 #include <TColStd_ListIteratorOfListOfInteger.hxx>
94 #include <TColStd_ListOfInteger.hxx>
95 #include <TColStd_MapOfInteger.hxx>
96 #include <TColStd_SequenceOfReal.hxx>
99 #include <TopExp_Explorer.hxx>
100 #include <TopLoc_Location.hxx>
101 #include <TopoDS.hxx>
102 #include <TopoDS_Edge.hxx>
103 #include <TopoDS_Iterator.hxx>
104 #include <TopoDS_Shape.hxx>
105 #include <TopoDS_Vertex.hxx>
106 #include <TopoDS_Wire.hxx>
107 #include <TopoDS_Shell.hxx>
108 #include <TopTools_Array1OfShape.hxx>
109 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
110 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
111 #include <TopTools_DataMapOfShapeInteger.hxx>
112 #include <TopTools_DataMapOfShapeListOfShape.hxx>
113 #include <TopTools_ListIteratorOfListOfShape.hxx>
114 #include <TopTools_ListOfShape.hxx>
115 #include <TopTools_MapIteratorOfMapOfShape.hxx>
116 #include <TopTools_MapOfShape.hxx>
117 #include <TopTools_SequenceOfShape.hxx>
118 #include <TopoDS_Compound.hxx>
119 #include <TColStd_Array2OfReal.hxx>
120 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
121 #include <BRepTools.hxx>
122 #include <Geom_RectangularTrimmedSurface.hxx>
123 #include <Geom_OffsetSurface.hxx>
124 #include <BRep_PointOnCurve.hxx>
125 #include <BRep_ListOfPointRepresentation.hxx>
126 #include <BRep_TVertex.hxx>
127 #include <Message_ProgressSentry.hxx>
128 #include <BRepBuilderAPI_VertexInspector.hxx>
129 #include <BRepBuilderAPI_CellFilter.hxx>
130 #include <BRepBuilderAPI_BndBoxTreeSelector.hxx>
131 #include <NCollection_UBTreeFiller.hxx>
133 //=======================================================================
134 //function : SameRange
136 //=======================================================================
138 Handle(Geom2d_Curve) BRepBuilderAPI_Sewing::SameRange(const Handle(Geom2d_Curve)& CurvePtr,
139 const Standard_Real FirstOnCurve,
140 const Standard_Real LastOnCurve,
141 const Standard_Real RequestedFirst,
142 const Standard_Real RequestedLast) const
144 Handle(Geom2d_Curve) NewCurvePtr;
147 GeomLib::SameRange(Precision::PConfusion(),CurvePtr,FirstOnCurve,LastOnCurve,
148 RequestedFirst,RequestedLast,NewCurvePtr);
150 catch (Standard_Failure) {
152 cout << "Exception in BRepBuilderAPI_Sewing::SameRange: ";
153 Standard_Failure::Caught()->Print(cout); cout << endl;
159 //=======================================================================
160 //function : WhichFace
161 //purpose : Give the face whose edge is the border
162 //=======================================================================
164 TopoDS_Face BRepBuilderAPI_Sewing::WhichFace(const TopoDS_Edge& theEdg, const Standard_Integer index) const
166 TopoDS_Shape bound = theEdg;
167 if (mySectionBound.IsBound(bound)) bound = mySectionBound(bound);
168 if (myBoundFaces.Contains(bound)) {
169 Standard_Integer i = 1;
170 TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bound));
171 for (; itf.More(); itf.Next(), i++)
172 if (i == index) return TopoDS::Face(itf.Value());
174 return TopoDS_Face();
177 //=======================================================================
178 //function : IsClosedShape
180 //=======================================================================
182 static Standard_Boolean IsClosedShape(const TopoDS_Shape& theshape,
183 const TopoDS_Shape& v1, const TopoDS_Shape& v2)
185 Standard_Real TotLength = 0.0;
186 TopExp_Explorer aexp;
187 for (aexp.Init(theshape,TopAbs_EDGE); aexp.More(); aexp.Next()) {
188 TopoDS_Edge aedge = TopoDS::Edge(aexp.Current());
189 if (aedge.IsNull()) continue;
190 TopoDS_Vertex ve1,ve2;
191 TopExp::Vertices(aedge,ve1,ve2);
192 if (!ve1.IsSame(v1) && !ve1.IsSame(v2)) continue;
193 if (BRep_Tool::Degenerated(aedge)) continue;
194 Standard_Real first,last;
195 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aedge), first, last);
197 GeomAdaptor_Curve cAdapt(c3d);
198 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
200 if (ve2.IsSame(v1) || ve2.IsSame(v2)) break;
203 if (TotLength > 0.0) {
204 gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(v1));
205 gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(v2));
206 return (p1.Distance(p2) < TotLength/(1.2 * M_PI));
208 return Standard_False;
211 //=======================================================================
212 //function : IsClosedByIsos
214 //=======================================================================
215 static Standard_Boolean IsClosedByIsos(const Handle(Geom_Surface)& thesurf,
216 const Handle(Geom2d_Curve)& acrv2d,
217 const Standard_Real f2d,
218 const Standard_Real l2d,
219 const Standard_Boolean isUIsos)
221 Standard_Boolean isClosed = Standard_False;
223 gp_Pnt2d psurf1 = (acrv2d->IsPeriodic() ?
224 acrv2d->Value(f2d) : acrv2d->Value(Max(f2d,acrv2d->FirstParameter())));
225 gp_Pnt2d psurf2 = (acrv2d->IsPeriodic() ?
226 acrv2d->Value(l2d) : acrv2d->Value(Min(l2d,acrv2d->LastParameter())));
227 Handle(Geom_Curve) aCrv1;
228 Handle(Geom_Curve) aCrv2;
230 aCrv1 = thesurf->UIso(psurf1.X());
231 aCrv2 = thesurf->UIso(psurf2.X());
234 aCrv1 = thesurf->VIso(psurf1.Y());
235 aCrv2 = thesurf->VIso(psurf2.Y());
237 gp_Pnt p11,p1m,p12,p21,p2m,p22;
238 Standard_Real af1 = aCrv1->FirstParameter();
239 Standard_Real al1 = aCrv1->LastParameter();
240 Standard_Real af2 = aCrv2->FirstParameter();
241 Standard_Real al2 = aCrv2->LastParameter();
243 aCrv1->D0((af1+al1)*0.5,p1m);
246 aCrv2->D0((af2+al2)*0.5,p2m);
248 isClosed = (((p11.XYZ() - p12.XYZ()).Modulus() <
249 (p11.XYZ() - p1m.XYZ()).Modulus() - Precision::Confusion()) &&
250 ((p21.XYZ() - p22.XYZ()).Modulus() <
251 (p21.XYZ() - p2m.XYZ()).Modulus() - Precision::Confusion())) ;
254 //=======================================================================
255 //function : IsUClosedSurface
257 //=======================================================================
259 Standard_Boolean BRepBuilderAPI_Sewing::IsUClosedSurface(const Handle(Geom_Surface)& surf,
260 const TopoDS_Shape& theEdge,
261 const TopLoc_Location& theloc) const
263 Handle(Geom_Surface) tmpsurf = surf;
264 if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
265 tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
266 else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
267 tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
269 Standard_Boolean isClosed = tmpsurf->IsUClosed();
271 Standard_Real f2d, l2d;
272 Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
274 isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_False );
279 return IsUClosedSurface(tmpsurf,theEdge,theloc);
280 //return surf->IsUClosed();
283 //=======================================================================
284 //function : IsVClosedSurface
286 //=======================================================================
288 Standard_Boolean BRepBuilderAPI_Sewing::IsVClosedSurface(const Handle(Geom_Surface)& surf,
289 const TopoDS_Shape& theEdge,
290 const TopLoc_Location& theloc) const
292 Handle(Geom_Surface) tmpsurf = surf;
293 if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
294 tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
295 else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
296 tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
298 Standard_Boolean isClosed = tmpsurf->IsVClosed();
300 Standard_Real f2d, l2d;
301 Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
303 isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_True );
307 return IsVClosedSurface(tmpsurf,theEdge,theloc);
308 //return surf->IsVClosed();
311 //=======================================================================
312 //function : SameParameter
313 //purpose : internal use
314 //=======================================================================
316 void BRepBuilderAPI_Sewing::SameParameter(const TopoDS_Edge& edge) const
320 BRepLib::SameParameter(edge);
322 catch (Standard_Failure) {
324 cout << "Exception in BRepBuilderAPI_Sewing::SameParameter: ";
325 Standard_Failure::Caught()->Print(cout); cout << endl;
330 //=======================================================================
331 //function : SameParameterEdge
332 //purpose : internal use
333 // Merge the Sequence Of Section on one edge.
334 // This function keep the curve3d,curve2d,range and parametrization
335 // from the first section, and report and made sameparameter the
336 // pcurves of the other function.
337 // This function works when the are not more than two Pcurves
339 //=======================================================================
341 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Shape& edge,
342 const TopTools_SequenceOfShape& seqEdges,
343 const TColStd_SequenceOfInteger& seqForward,
344 TopTools_MapOfShape& mapMerged,
345 const Handle(BRepTools_ReShape)& locReShape)
347 // Retrieve reference section
348 TopoDS_Shape aTmpShape = myReShape->Apply(edge); //for porting
349 TopoDS_Edge Edge1 = TopoDS::Edge(aTmpShape);
350 aTmpShape = locReShape->Apply(Edge1);
351 if (locReShape != myReShape) Edge1 = TopoDS::Edge(aTmpShape);
352 Standard_Boolean isDone = Standard_False;
354 // Create data structures for temporary merged edges
355 TopTools_ListOfShape listFaces1;
356 TopTools_MapOfShape MergedFaces;
360 // Fill MergedFaces with faces of Edge1
361 TopoDS_Shape bnd1 = edge;
362 if (mySectionBound.IsBound(bnd1)) bnd1 = mySectionBound(bnd1);
363 if (myBoundFaces.Contains(bnd1)) {
364 TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bnd1));
365 for (; itf.More(); itf.Next())
366 if (MergedFaces.Add(itf.Value()))
367 listFaces1.Append(itf.Value());
372 // Create presentation edge
373 TopoDS_Vertex V1, V2;
374 TopExp::Vertices(Edge1,V1,V2);
375 if (myVertexNode.Contains(V1)) V1 = TopoDS::Vertex(myVertexNode.FindFromKey(V1));
376 if (myVertexNode.Contains(V2)) V2 = TopoDS::Vertex(myVertexNode.FindFromKey(V2));
378 TopoDS_Edge NewEdge = Edge1;
382 BRep_Builder aBuilder;
383 TopoDS_Shape anEdge = NewEdge.Oriented(TopAbs_FORWARD);
384 aBuilder.Add(anEdge,V1.Oriented(TopAbs_FORWARD));
385 aBuilder.Add(anEdge,V2.Oriented(TopAbs_REVERSED));
390 Standard_Boolean isForward = Standard_True;
392 // Merge candidate sections
393 for (Standard_Integer i = 1; i <= seqEdges.Length(); i++) {
395 // Retrieve candidate section
396 TopoDS_Shape oedge2 = seqEdges(i);
400 aTmpShape = myReShape->Apply(oedge2); //for porting
401 TopoDS_Edge Edge2 = TopoDS::Edge(aTmpShape);
402 aTmpShape = locReShape->Apply(Edge2);
403 if (locReShape != myReShape) Edge2 = TopoDS::Edge(aTmpShape);
405 // Calculate relative orientation
406 Standard_Integer Orientation = seqForward(i);
407 if (!isForward) Orientation = (Orientation? 0 : 1);
409 // Retrieve faces information for the second edge
410 TopoDS_Shape bnd2 = oedge2;
411 if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
412 if (!myBoundFaces.Contains(bnd2)) continue; // Skip floating edge
413 const TopTools_ListOfShape& listFaces2 = myBoundFaces.FindFromKey(bnd2);
415 Standard_Integer whichSec = 1; // Indicates on which edge the pCurve has been reported
416 TopoDS_Edge NewEdge = SameParameterEdge(Edge1,Edge2,listFaces1,listFaces2,Orientation,whichSec);
417 if (NewEdge.IsNull()) continue;
419 // Record faces information for the temporary merged edge
420 TopTools_ListIteratorOfListOfShape itf(listFaces2);
421 for (; itf.More(); itf.Next())
422 if (MergedFaces.Add(itf.Value()))
423 listFaces1.Append(itf.Value());
425 // Record merged section orientation
426 if (!Orientation && whichSec != 1)
427 isForward = isForward? Standard_False : Standard_True;
431 // Append actually merged edge
432 mapMerged.Add(oedge2);
433 isDone = Standard_True;
435 if (!myNonmanifold) break;
439 // Change result orientation
440 Edge1.Orientation(isForward? TopAbs_FORWARD : TopAbs_REVERSED);
442 else Edge1.Nullify();
447 //=======================================================================
448 //function : SameParameterEdge
449 //purpose : internal use
450 //=======================================================================
451 static Standard_Boolean findNMVertices(const TopoDS_Edge& theEdge,
452 TopTools_SequenceOfShape& theSeqNMVert,
453 TColStd_SequenceOfReal& theSeqPars)
455 TopoDS_Iterator aItV(theEdge,Standard_False);
456 for( ; aItV.More(); aItV.Next()) {
457 if(aItV.Value().Orientation() == TopAbs_INTERNAL ||
458 aItV.Value().Orientation() == TopAbs_EXTERNAL)
459 theSeqNMVert.Append(aItV.Value());
461 Standard_Integer nbV = theSeqNMVert.Length();
463 return Standard_False;
464 Standard_Real first, last;
465 Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,first, last);
466 GeomAdaptor_Curve GAC(c3d);
467 Extrema_ExtPC locProj;
468 locProj.Initialize(GAC, first, last);
469 gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
472 for (Standard_Integer i = 1; i <= nbV; i++) {
473 TopoDS_Vertex aV = TopoDS::Vertex(theSeqNMVert.Value(i));
474 gp_Pnt pt = BRep_Tool::Pnt(aV);
476 Standard_Real distF2 = pfirst.SquareDistance(pt);
477 Standard_Real distL2 = plast.SquareDistance(pt);
478 Standard_Real apar = (distF2 > distL2 ? last : first);
479 // Project current point on curve
481 if (locProj.IsDone() && locProj.NbExt() > 0) {
482 Standard_Real dist2Min = Min(distF2,distL2);
483 Standard_Integer ind, indMin = 0;
484 for (ind = 1; ind <= locProj.NbExt(); ind++) {
485 Standard_Real dProj2 = locProj.SquareDistance(ind);
486 if (dProj2 < dist2Min) {
487 indMin = ind; dist2Min = dProj2;
491 apar = locProj.Point(indMin).Parameter();
493 theSeqPars.Append(apar);
497 return Standard_True;
500 static inline Standard_Real ComputeToleranceVertex(const Standard_Real dist, const Standard_Real Tol1, const Standard_Real Tol2)
502 return (dist * 0.5 + Tol1 + Tol2);
504 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirst,
505 const TopoDS_Edge& edgeLast,
506 const TopTools_ListOfShape& listFacesFirst,
507 const TopTools_ListOfShape& listFacesLast,
508 const Standard_Boolean secForward,
509 Standard_Integer& whichSec,
510 const Standard_Boolean firstCall)
512 // Do not process floating edges
513 if (!listFacesFirst.Extent() || !listFacesLast.Extent()) return TopoDS_Edge();
516 TopoDS_Edge edge1, edge2;
518 // Take the longest edge as first
520 Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(TopoDS::Edge(edgeFirst), f, l);
521 GeomAdaptor_Curve cAdapt1(c3d1);
522 Standard_Real len1 = GCPnts_AbscissaPoint::Length(cAdapt1, f, l);
523 Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(TopoDS::Edge(edgeLast), f, l);
524 GeomAdaptor_Curve cAdapt2(c3d2);
525 Standard_Real len2 = GCPnts_AbscissaPoint::Length(cAdapt2, f, l);
550 Standard_Real first, last;
551 BRep_Tool::Range(edge1, first, last);
552 BRep_Builder aBuilder;
554 //To keep NM vertices on edge
555 TopTools_SequenceOfShape aSeqNMVert;
556 TColStd_SequenceOfReal aSeqNMPars;
557 findNMVertices(edge1,aSeqNMVert,aSeqNMPars);
558 findNMVertices(edge2,aSeqNMVert,aSeqNMPars);
562 aBuilder.MakeEdge(edge);
563 edge.Orientation( edge1.Orientation());
566 // Retrieve edge curve
567 TopLoc_Location loc3d;
568 Standard_Real first3d, last3d;
569 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge1, loc3d, first3d, last3d);
570 if (!loc3d.IsIdentity()) {
571 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
572 c3d->Transform(loc3d.Transformation());
574 aBuilder.UpdateEdge(edge,c3d,BRep_Tool::Tolerance(edge1));
575 aBuilder.Range(edge, first, last);
576 aBuilder.SameRange(edge, Standard_False); //Standard_True
577 aBuilder.SameParameter(edge, Standard_False);
578 // Create and add new vertices
580 TopoDS_Vertex V1New, V2New;
582 // Retrieve original vertices from edges
583 TopoDS_Vertex V11,V12,V21,V22;
584 TopExp::Vertices(edge1,V11,V12);
585 TopExp::Vertices(edge2,V21,V22);
587 //check that edges merged valid way (for edges having length less than specified
589 // Check if edges are closed
590 Standard_Boolean isClosed1 = V11.IsSame(V12);
591 Standard_Boolean isClosed2 = V21.IsSame(V22);
592 if(!isClosed1 && !isClosed2)
596 if( V11.IsSame(V22) || V12.IsSame(V21) )
597 return TopoDS_Edge();
601 if( V11.IsSame(V21) || V12.IsSame(V22) )
602 return TopoDS_Edge();
606 //szv: do not reshape here!!!
607 //V11 = TopoDS::Vertex(myReShape->Apply(V11));
608 //V12 = TopoDS::Vertex(myReShape->Apply(V12));
609 //V21 = TopoDS::Vertex(myReShape->Apply(V21));
610 //V22 = TopoDS::Vertex(myReShape->Apply(V22));
612 gp_Pnt p11 = BRep_Tool::Pnt(V11);
613 gp_Pnt p12 = BRep_Tool::Pnt(V12);
614 gp_Pnt p21 = BRep_Tool::Pnt(V21);
615 gp_Pnt p22 = BRep_Tool::Pnt(V22);
619 //Standard_Boolean isRev = Standard_False;
621 Standard_Real Tol1 = 0.;
622 if (isClosed1 || isClosed2) {
623 // at least one of the edges is closed
624 if (isClosed1 && isClosed2) {
625 // both edges are closed
626 pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ()));
627 gp_Vec v1 = p21.XYZ() - p11.XYZ();
628 Standard_Real d1 = v1.Magnitude();
629 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21));
630 //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p21));
632 else if (isClosed1) {
633 // only first edge is closed
634 gp_XYZ pt =0.5*(p21.XYZ()+ p22.XYZ());
635 pfirst.SetXYZ(0.5*(p11.XYZ() + pt));
636 gp_Vec v1 = p22.XYZ() - p21.XYZ();
637 Standard_Real d1 = v1.Magnitude();
638 Tol1= ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V22),BRep_Tool::Tolerance(V21));
639 gp_Vec v2 = p11.XYZ() - pt;
640 Standard_Real d2 = v2.Magnitude();
641 Tol1= ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V11));
642 //Tol1 = Max(pfirst.Distance(p21),pfirst.Distance(p22));
643 //Tol1 = Max(pfirst.Distance(p11),Tol1);
646 // only second edge is closed
647 gp_XYZ pt = 0.5*(p11.XYZ()+ p12.XYZ());
648 pfirst.SetXYZ(0.5*(p21.XYZ() + pt));
649 gp_Vec v1 = p11.XYZ() - p12.XYZ();
650 Standard_Real d1 = v1.Magnitude();
651 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V12));
652 gp_Vec v2 = p21.XYZ() - pt;
653 Standard_Real d2 = v2.Magnitude();
654 Tol1 = ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V21));
655 //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p12));
656 //Tol1 = Max(pfirst.Distance(p21),Tol1);
658 aBuilder.MakeVertex(V1New,pfirst,Tol1);
662 // both edges are open
664 Standard_Real Tol2 = 0.;
665 Standard_Boolean isOldFirst = ( secForward ? V11.IsSame(V21) : V11.IsSame(V22) );
666 Standard_Boolean isOldLast = ( secForward ? V12.IsSame(V22) : V12.IsSame(V21)) ;
668 //case if vertices already sewed
671 pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ()));
672 gp_Vec v1 = p21.XYZ() - p11.XYZ();
673 Standard_Real d1 = v1.Magnitude();
674 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21));
678 plast.SetXYZ(0.5*(p12.XYZ() + p22.XYZ()));
680 gp_Vec v2 = p22.XYZ() - p12.XYZ();
681 Standard_Real d2 = v2.Magnitude();
683 Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V22));
690 pfirst.SetXYZ(0.5*(p11.XYZ() + p22.XYZ()));
691 gp_Vec v1 = p22.XYZ() - p11.XYZ();
692 Standard_Real d1 = v1.Magnitude();
693 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V22));
697 plast.SetXYZ(0.5*(p12.XYZ() + p21.XYZ()));
698 gp_Vec v2 = p21.XYZ() - p12.XYZ();
699 Standard_Real d2 = v2.Magnitude();
700 Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V21));
705 aBuilder.MakeVertex(V1New,pfirst,Tol1);
711 aBuilder.MakeVertex(V2New,plast,Tol2);
717 // Add the vertices in the good sense
718 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
719 TopoDS_Shape aLocalEdge = V1New.Oriented(TopAbs_FORWARD); //(listNode.First()).Oriented(TopAbs_FORWARD);
720 aBuilder.Add(anEdge,aLocalEdge);
721 aLocalEdge = V2New.Oriented(TopAbs_REVERSED); //(listNode.Last()).Oriented(TopAbs_REVERSED);
722 aBuilder.Add(anEdge,aLocalEdge);
724 Standard_Integer k =1;
725 for( ; k <= aSeqNMVert.Length(); k++)
726 aBuilder.Add(anEdge,aSeqNMVert.Value(k));
730 // Retrieve second PCurves
731 TopLoc_Location loc2;
732 Handle(Geom_Surface) surf2;
734 //Handle(Geom2d_Curve) c2d2, c2d21;
735 // Standard_Real firstOld, lastOld;
737 TopTools_ListIteratorOfListOfShape itf2;
738 if (whichSec == 1) itf2.Initialize(listFacesLast);
739 else itf2.Initialize(listFacesFirst);
740 Standard_Boolean isResEdge = Standard_False;
742 for (; itf2.More(); itf2.Next()) {
743 Handle(Geom2d_Curve) c2d2, c2d21;
744 Standard_Real firstOld, lastOld;
745 fac2 = TopoDS::Face(itf2.Value());
747 surf2 = BRep_Tool::Surface(fac2, loc2);
748 Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) &&
749 BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2));
751 if (!myNonmanifold) return TopoDS_Edge();
752 TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting
753 c2d21 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac2, firstOld, lastOld);
755 c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld);
756 if (c2d2.IsNull() && c2d21.IsNull()) continue;
758 if (!c2d21.IsNull()) {
759 c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy());
761 if (c2d21->IsKind(STANDARD_TYPE(Geom2d_Line)))
762 c2d21 = new Geom2d_TrimmedCurve(c2d21, firstOld, lastOld);
763 Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
764 Standard_Real last2d = lastOld; //c2dTmp->LastParameter();
765 firstOld = c2d21->ReversedParameter(last2d);
766 lastOld = c2d21->ReversedParameter(first2d);
769 c2d21 = SameRange(c2d21,firstOld,lastOld,first,last);
772 // Make second PCurve sameRange with the 3d curve
773 c2d2 = Handle(Geom2d_Curve)::DownCast(c2d2->Copy());
776 if (c2d2->IsKind(STANDARD_TYPE(Geom2d_Line)))
777 c2d2 = new Geom2d_TrimmedCurve(c2d2, firstOld, lastOld);
778 Standard_Real first2d = firstOld;
779 Standard_Real last2d = lastOld;
780 firstOld = c2d2->ReversedParameter(last2d);
781 lastOld = c2d2->ReversedParameter(first2d);
785 c2d2 = SameRange(c2d2,firstOld,lastOld,first,last);
786 if (c2d2.IsNull()) continue;
789 Standard_Boolean isSeam = Standard_False;
790 TopAbs_Orientation Ori = TopAbs_FORWARD;
791 //Handle(Geom2d_Curve) c2d1, c2d11;
793 TopTools_ListIteratorOfListOfShape itf1;
794 if (whichSec == 1) itf1.Initialize(listFacesFirst);
795 else itf1.Initialize(listFacesLast);
796 for (; itf1.More() && !isSeam; itf1.Next()) {
797 Handle(Geom2d_Curve) c2d1, c2d11;
798 const TopoDS_Face& fac1 = TopoDS::Face(itf1.Value());
800 TopLoc_Location loc1;
801 Handle(Geom_Surface) surf1 = BRep_Tool::Surface(fac1, loc1);
803 Standard_Real first2d, last2d;
804 Standard_Boolean isSeam1 = ((IsUClosedSurface(surf1,edge1,loc1) || IsVClosedSurface(surf1,edge1,loc1)) &&
805 BRep_Tool::IsClosed(TopoDS::Edge(edge1),fac1));
806 c2d1 = BRep_Tool::CurveOnSurface(edge1, fac1, first2d, last2d);
807 Ori = edge1.Orientation();
808 if (fac1.Orientation() == TopAbs_REVERSED)
809 Ori = TopAbs::Reverse(Ori);
812 if (!myNonmanifold) return TopoDS_Edge();
813 TopoDS_Shape aTmpShape = edge1.Reversed(); //for porting
814 c2d11 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac1, first2d, last2d);
815 //if(fac1.Orientation() == TopAbs_REVERSED) //
816 if(Ori == TopAbs_FORWARD)
817 aBuilder.UpdateEdge(edge,c2d1,c2d11,fac1,0);
819 aBuilder.UpdateEdge(edge,c2d11,c2d1,fac1,0);
821 else aBuilder.UpdateEdge(edge,c2d1,fac1,0);
823 if (c2d1.IsNull() && c2d11.IsNull()) continue;
825 if (surf2 == surf1) {
826 // Merge sections which are on the same face
827 if (!loc2.IsDifferent(loc1)) {
828 Standard_Boolean uclosed = IsUClosedSurface(surf2,edge2,loc2);
829 Standard_Boolean vclosed = IsVClosedSurface(surf2,edge2,loc2);
830 if (uclosed || vclosed) {
831 Standard_Real pf = c2d1->FirstParameter();
832 // Standard_Real pl = c2d1->LastParameter();
833 gp_Pnt2d p1n = c2d1->Value(Max(first,pf));
834 // gp_Pnt2d p2n = c2d1->Value(Min(pl,last));
835 gp_Pnt2d p21n = c2d2->Value(Max(first,c2d2->FirstParameter()));
836 gp_Pnt2d p22n = c2d2->Value(Min(last,c2d2->LastParameter()));
837 Standard_Real aDist = Min(p1n.Distance(p21n), p1n.Distance(p22n));
838 Standard_Real U1, U2, V1, V2;
839 surf2->Bounds(U1, U2, V1, V2);
840 isSeam = ((uclosed && aDist > 0.75*(fabs(U2-U1))) ||
841 (vclosed && aDist > 0.75*(fabs(V2-V1))));
842 if( !isSeam && BRep_Tool::IsClosed(TopoDS::Edge(edge),fac1)) continue;
847 isResEdge = Standard_True;
849 if (Ori == TopAbs_FORWARD)
850 aBuilder.UpdateEdge(edge, c2d1, c2d2, surf2, loc2, Precision::Confusion());
852 aBuilder.UpdateEdge(edge, c2d2, c2d1, surf2, loc2, Precision::Confusion());
855 TopAbs_Orientation InitOri = edge2.Orientation();
856 TopAbs_Orientation SecOri = edge.Orientation();
857 if (fac2.Orientation() == TopAbs_REVERSED) {
859 InitOri = TopAbs::Reverse(InitOri);
860 SecOri = TopAbs::Reverse(SecOri);
863 InitOri = TopAbs::Reverse(InitOri);
865 if (InitOri == TopAbs_FORWARD)
866 aBuilder.UpdateEdge(edge, c2d2,c2d21, surf2, loc2, Precision::Confusion());
868 aBuilder.UpdateEdge(edge, c2d21,c2d2, surf2, loc2, Precision::Confusion());
871 aBuilder.UpdateEdge(edge, c2d2, surf2, loc2, Precision::Confusion());
876 Standard_Real tolReached = Precision::Infinite();
877 Standard_Boolean isSamePar = Standard_False;
881 if( BRep_Tool::SameParameter(edge))
883 isSamePar = Standard_True;
884 tolReached = BRep_Tool::Tolerance(edge);
889 if (firstCall && ( !isResEdge || !isSamePar || tolReached > myTolerance)) {
890 Standard_Integer whichSecn = whichSec;
891 // Try to merge on the second section
892 Standard_Boolean second_ok = Standard_False;
893 TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast,
894 secForward,whichSecn,Standard_False);
895 if( !s_edge.IsNull())
897 Standard_Real tolReached_2 = BRep_Tool::Tolerance(s_edge);
898 second_ok = ( BRep_Tool::SameParameter(s_edge) && tolReached_2 < tolReached );
902 whichSec = whichSecn;
903 tolReached = tolReached_2;
907 if (!second_ok && !edge.IsNull()) {
909 GeomAdaptor_Curve c3dAdapt(c3d);
911 // Discretize edge curve
912 Standard_Integer i, j, nbp = 23;
913 Standard_Real deltaT = (last3d - first3d) / (nbp + 1);
914 TColgp_Array1OfPnt c3dpnt(1,nbp);
915 for (i = 1; i <= nbp; i++)
916 c3dpnt(i) = c3dAdapt.Value(first3d + i*deltaT);
918 Standard_Real dist = 0., maxTol = -1.0;
919 Standard_Boolean more = Standard_True;
920 Standard_Boolean useFace = Standard_False;
922 for (j = 1; more; j++) {
923 Handle(Geom2d_Curve) c2d2;
924 BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j);
926 more = !c2d2.IsNull();
928 Handle(Geom_Surface) aS = surf2;
929 if(!loc2.IsIdentity())
930 aS = Handle(Geom_Surface)::DownCast(surf2->Transformed ( loc2 ));
932 Standard_Real dist2 = 0.;
933 deltaT = (last - first) / (nbp + 1);
934 for (i = 1; i <= nbp; i++) {
935 gp_Pnt2d aP2d = c2d2->Value(first + i*deltaT);
936 gp_Pnt aP2(0.,0.,0.);
937 aS->D0(aP2d.X(),aP2d.Y(), aP2);
938 gp_Pnt aP1 = c3dpnt(i);
939 dist = aP2.SquareDistance(aP1);
943 maxTol = Max(sqrt(dist2), Precision::Confusion());
946 if(maxTol >= 0. && maxTol < tolReached)
947 aBuilder.UpdateEdge(edge, maxTol);
948 aBuilder.SameParameter(edge,Standard_True);
952 BRepLib::EncodeRegularity(edge,0.01);
953 Standard_Real tolEdge1 = BRep_Tool::Tolerance(edge);
954 if (tolEdge1 > MaxTolerance()) edge.Nullify();
958 //=======================================================================
959 // function : EvaluateAngulars
960 // purpose : internal use
961 //=======================================================================
963 void BRepBuilderAPI_Sewing::EvaluateAngulars(TopTools_SequenceOfShape& sequenceSec,
964 TColStd_Array1OfBoolean& secForward,
965 TColStd_Array1OfReal& tabAng,
966 const Standard_Integer indRef) const
970 Standard_Integer i, j, npt = 4, lengSec = sequenceSec.Length();
975 Standard_Real first, last;
976 Handle(Geom_Curve) c3d;
977 Handle(Geom2d_Curve) c2d;
978 Handle(Geom_Surface) surf;
979 TColgp_Array1OfVec normRef(1,npt);
981 for (i = indRef; i <= lengSec; i++) {
983 edge = TopoDS::Edge(sequenceSec(i));
985 TopoDS_Shape bnd = edge;
986 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
987 if (myBoundFaces.Contains(bnd)) {
988 face = TopoDS::Face(myBoundFaces.FindFromKey(bnd).First());
989 surf = BRep_Tool::Surface(face,loc);
990 if (!loc.IsIdentity()) {
991 surf = Handle(Geom_Surface)::DownCast(surf->Copy());
992 surf->Transform(loc.Transformation());
994 c2d = BRep_Tool::CurveOnSurface(edge, face, first, last);
996 else if (i == indRef) return;
999 c3d = BRep_Tool::Curve(edge, loc, first, last);
1000 if (!loc.IsIdentity()) {
1001 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1002 c3d->Transform(loc.Transformation());
1005 GeomAdaptor_Curve adapt(c3d);
1006 GCPnts_UniformAbscissa uniAbs(adapt, npt, first, last);
1008 Standard_Real cumulateAngular = 0.0;
1009 Standard_Integer nbComputedAngle = 0;
1011 for (j = 1; j <= npt; j++) {
1013 c2d->D0(uniAbs.Parameter((secForward(i) || i == indRef)? j : npt-j+1),P);
1016 surf->D1(P.X(), P.Y(), unused, w1, w2);
1017 gp_Vec n = w1^w2; // Compute the normal vector
1018 if (i == indRef) normRef(j) = n;
1019 else if ((n.Magnitude()>gp::Resolution()) && (normRef(j).Magnitude()>gp::Resolution())) {
1021 Standard_Real angular = n.Angle(normRef(j));
1022 if (angular > M_PI/2.) angular = M_PI - angular;
1023 cumulateAngular += angular;
1027 if (nbComputedAngle)
1028 tabAng(i) = cumulateAngular/((Standard_Real)nbComputedAngle);
1032 //=======================================================================
1033 // function : EvaluateDistances
1034 // purpose : internal use
1035 // Evaluate distance beetween edges with indice indRef and the following edges in the list
1036 // Remarks (lengSec - indRef) must be >= 1
1037 //=======================================================================
1038 void BRepBuilderAPI_Sewing::EvaluateDistances(TopTools_SequenceOfShape& sequenceSec,
1039 TColStd_Array1OfBoolean& secForward,
1040 TColStd_Array1OfReal& tabDst,
1041 TColStd_Array1OfReal& arrLen,
1042 TColStd_Array1OfReal& tabMinDist,
1043 const Standard_Integer indRef) const
1045 secForward.Init(Standard_True);
1048 tabMinDist.Init(Precision::Infinite());
1049 const Standard_Integer npt = 8; // Number of points for curve discretization
1050 TColgp_Array1OfPnt ptsRef(1, npt), ptsSec(1, npt);
1052 Standard_Integer i, j, lengSec = sequenceSec.Length();
1053 TColgp_SequenceOfPnt seqSec;
1055 Handle(Geom_Curve) c3dRef;
1056 Standard_Real firstRef=0., lastRef=0.;
1058 for (i = indRef; i <= lengSec; i++) {
1060 // reading of the edge (attention for the first one: reference)
1061 const TopoDS_Edge& sec = TopoDS::Edge(sequenceSec(i));
1063 TopLoc_Location loc;
1064 Standard_Real first, last;
1065 Handle(Geom_Curve) c3d = BRep_Tool::Curve(sec, loc, first, last);
1066 if (!loc.IsIdentity()) {
1067 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1068 c3d->Transform(loc.Transformation());
1072 c3dRef = c3d; firstRef = first; lastRef = last;
1075 Standard_Real dist = Precision::Infinite(), distFor = -1.0, distRev = -1.0;
1076 Standard_Real aMinDist = Precision::Infinite();
1078 Standard_Real T, deltaT = (last - first) / (npt - 1);
1079 Standard_Real aLenSec2 = 0.;
1081 Standard_Integer nbFound = 0;
1082 for (j = 1; j <= npt; j++) {
1084 // Uniform parameter on curve
1085 if (j == 1) T = first;
1086 else if (j == npt) T = last;
1087 else T = first + (j - 1) * deltaT;
1089 // Take point on curve
1090 gp_Pnt pt = c3d->Value(T);
1095 aLenSec2 += pt.SquareDistance(ptsRef(j-1));
1099 //protection to avoid merging with small sections
1101 aLenSec2 += pt.SquareDistance(ptsSec(j-1));
1102 // To evaluate mutual orientation and distance
1103 dist = pt.Distance(ptsRef(j));
1106 if (distFor < dist) distFor = dist;
1107 dist = pt.Distance(ptsRef(npt-j+1));
1111 if (distRev < dist) distRev = dist;
1113 // Check that point lays between vertices of reference curve
1114 const gp_Pnt &p11 = ptsRef(1);
1115 const gp_Pnt &p12 = ptsRef(npt);
1116 const gp_Vec aVec1(pt,p11);
1117 const gp_Vec aVec2(pt,p12);
1118 const gp_Vec aVecRef(p11,p12);
1119 if((aVecRef * aVec1) * (aVecRef * aVec2) < 0.)
1124 Standard_Real aLenSec = sqrt(aLenSec2);
1126 //if(aLenSec < myMinTolerance )
1128 arrLen.SetValue(i,aLenSec);
1129 // Record mutual orientation
1130 Standard_Boolean isForward = (distFor < distRev); //szv debug: <=
1131 secForward(i) = isForward;
1133 dist = (isForward? distFor : distRev);
1134 if(i == indRef || (dist < myTolerance && nbFound >= npt * 0.5) )
1137 tabMinDist(i) = aMinDist;
1141 nbFound = 0, aMinDist = Precision::Infinite(), dist = -1;
1142 TColgp_Array1OfPnt arrProj(1, npt);
1143 TColStd_Array1OfReal arrDist(1, npt), arrPara(1, npt);
1144 if( arrLen(indRef) >= arrLen(i))
1145 ProjectPointsOnCurve(ptsSec,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1147 ProjectPointsOnCurve(ptsRef,c3d,first,last,arrDist,arrPara,arrProj,Standard_False);
1148 for( j = 1; j <= npt; j++ )
1152 if(dist < arrDist(j))
1154 if( aMinDist > arrDist(j))
1155 aMinDist = arrDist(j);
1161 tabMinDist(i) = aMinDist;
1167 // Project distant points
1168 Standard_Integer nbFailed = seqSec.Length();
1169 if (!nbFailed) return;
1171 TColgp_Array1OfPnt arrPnt(1, nbFailed), arrProj(1, nbFailed);
1172 for (i = 1; i <= nbFailed; i++) arrPnt(i) = seqSec(i); seqSec.Clear();
1173 TColStd_Array1OfReal arrDist(1, nbFailed), arrPara(1, nbFailed);
1175 ProjectPointsOnCurve(arrPnt,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1177 // Process distant sections
1178 Standard_Integer idx1 = 1;
1179 for (i = indRef + 1; i <= lengSec; i++) {
1181 // Skip section if already evaluated
1182 if (tabDst(i) >= 0.0) continue;
1184 Standard_Real dist, distMax = -1.0, aMinDist = Precision::Infinite();
1186 Standard_Integer idx2 = (idx1 - 1)*npt;
1188 for (j = 1; j <= npt; j++) {
1190 dist = arrDist(idx2 + j);
1191 // If point is not projected - stop evaluation
1192 if (dist < 0.0) { distMax = -1.0; break; }
1193 if (distMax < dist) distMax = dist;
1194 if(aMinDist > dist) aMinDist = dist;
1197 // If section is close - record distance
1198 if (distMax >= 0.0) {
1199 if (secForward(i)) {
1200 dist = arrPnt(idx2+1).Distance(ptsRef(1));
1201 if (distMax < dist) distMax = dist;
1202 if(aMinDist > dist) aMinDist = dist;
1203 dist = arrPnt(idx2+npt).Distance(ptsRef(npt));
1204 if (distMax < dist) distMax = dist;
1205 if(aMinDist > dist) aMinDist = dist;
1208 dist = arrPnt(idx2+1).Distance(ptsRef(npt));
1209 if (distMax < dist) distMax = dist;
1210 if(aMinDist > dist) aMinDist = dist;
1211 dist = arrPnt(idx2+npt).Distance(ptsRef(1));
1212 if (distMax < dist) distMax = dist;
1213 if(aMinDist > dist) aMinDist = dist;
1216 if (distMax < myTolerance)
1218 tabDst(i) = distMax;
1219 tabMinDist(i) = aMinDist;
1223 idx1++; // To the next distant curve
1227 //=======================================================================
1228 //function : IsMergedClosed
1229 //purpose : internal use
1230 //=======================================================================
1232 Standard_Boolean BRepBuilderAPI_Sewing::IsMergedClosed(const TopoDS_Edge& Edge1,
1233 const TopoDS_Edge& Edge2,
1234 const TopoDS_Face& face) const
1236 // Check for closed surface
1237 TopLoc_Location loc;
1238 Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc);
1239 Standard_Boolean isUClosed = IsUClosedSurface(surf,Edge1,loc);
1240 Standard_Boolean isVClosed = IsVClosedSurface(surf,Edge1,loc);
1241 if (!isUClosed && !isVClosed) return Standard_False;
1242 // Check condition on closed surface
1244 Standard_Real first1,last1,first2,last2;
1245 Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(Edge1,first1,last1);
1246 Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(Edge2,first2,last2);
1247 if (C3d1.IsNull() || C3d2.IsNull()) return Standard_False;
1249 Standard_Real first2d1,last2d1,first2d2,last2d2;
1250 Handle(Geom2d_Curve) C2d1 = BRep_Tool::CurveOnSurface(Edge1,face,first2d1,last2d1);
1251 Handle(Geom2d_Curve) C2d2 = BRep_Tool::CurveOnSurface(Edge2,face,first2d2,last2d2);
1252 if (C2d1.IsNull() || C2d2.IsNull()) return Standard_False;
1254 gp_Pnt p1 = C3d1->Value(0.5*(first1 + last1));
1255 gp_Pnt p2 = C3d1->Value(0.5*(first2 + last2));
1256 Standard_Real dist = p1.Distance(p2);
1257 gp_Pnt2d p12d = C2d1->Value(0.5*(first2d1 + last2d1));
1258 gp_Pnt2d p22d = C2d1->Value(0.5*(first2d2 + last2d2));
1259 Standard_Real dist2d = p12d.Distance(p22d);
1260 GeomAdaptor_Surface Ads(BRep_Tool::Surface(face));
1261 Standard_Real distSurf = Max(Ads.UResolution(dist), Ads.VResolution(dist));
1262 return (dist2d*0.2 >= distSurf);
1264 Standard_Integer isULongC1, isULongC2, isVLongC1, isVLongC2;
1265 Standard_Real SUmin, SUmax, SVmin, SVmax;
1266 Standard_Real C1Umin, C1Vmin, C1Umax, C1Vmax;
1267 Standard_Real C2Umin, C2Vmin, C2Umax, C2Vmax;
1268 { //szv: Use brackets to destroy local variables
1270 Geom2dAdaptor_Curve aC2d1(C2d1), aC2d2(C2d2);
1271 BndLib_Add2dCurve::Add(aC2d1,first2d1,last2d1,Precision::PConfusion(),B1);
1272 BndLib_Add2dCurve::Add(aC2d2,first2d2,last2d2,Precision::PConfusion(),B2);
1273 B1.Get(C1Umin,C1Vmin,C1Umax,C1Vmax);
1274 B2.Get(C2Umin,C2Vmin,C2Umax,C2Vmax);
1275 Standard_Real du, dv;
1276 du = (C1Umax - C1Umin); dv = (C1Vmax - C1Vmin);
1277 isULongC1 = (dv <= du); isVLongC1 = (du <= dv);
1278 du = (C2Umax - C2Umin); dv = (C2Vmax - C2Vmin);
1279 isULongC2 = (dv <= du); isVLongC2 = (du <= dv);
1280 surf->Bounds(SUmin,SUmax,SVmin,SVmax);
1282 if (isUClosed && isVLongC1 && isVLongC2) {
1283 // Do not merge if not overlapped by V
1284 Standard_Real dist = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1286 Standard_Real distInner = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1287 Standard_Real distOuter = (SUmax - SUmin) - Max((C2Umax - C1Umin),(C1Umax - C2Umin));
1288 if (distOuter <= distInner) return Standard_True;
1291 if (isVClosed && isULongC1 && isULongC2) {
1292 // Do not merge if not overlapped by U
1293 Standard_Real dist = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1295 Standard_Real distInner = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1296 Standard_Real distOuter = (SVmax - SVmin) - Max((C2Vmax - C1Vmin),(C1Vmax - C2Vmin));
1297 if (distOuter <= distInner) return Standard_True;
1300 return Standard_False;
1303 //=======================================================================
1304 //function : AnalysisNearestEdges
1306 //=======================================================================
1308 void BRepBuilderAPI_Sewing::AnalysisNearestEdges(const TopTools_SequenceOfShape& sequenceSec,
1309 TColStd_SequenceOfInteger& seqIndCandidate,
1310 TColStd_SequenceOfInteger& seqOrientations,
1311 const Standard_Boolean evalDist)
1314 Standard_Integer workIndex = seqIndCandidate.First();
1315 TopoDS_Shape workedge = sequenceSec.Value(workIndex);
1316 TopoDS_Shape bnd = workedge;
1317 TopTools_ListOfShape workfaces;
1318 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1319 if (myBoundFaces.Contains(bnd))
1320 workfaces = myBoundFaces.FindFromKey(bnd);
1321 if(workfaces.IsEmpty()) return;
1322 TopTools_MapOfShape mapFaces;
1323 TopTools_ListIteratorOfListOfShape lIt;
1324 for (lIt.Initialize(workfaces); lIt.More(); lIt.Next())
1325 mapFaces.Add(lIt.Value());
1326 TColStd_SequenceOfInteger seqNotCandidate;
1327 TColStd_SequenceOfInteger seqNewForward;
1328 // Separates edges belonging the same face as work edge
1329 // for exception of edges belonging closed faces
1331 seqNotCandidate.Append(workIndex);
1332 for(Standard_Integer i = 1; i<= seqIndCandidate.Length(); ) {
1333 Standard_Integer index = seqIndCandidate.Value(i);
1334 Standard_Boolean isRemove = Standard_False;
1335 if(index == workIndex) {
1336 seqIndCandidate.Remove(i);
1337 seqOrientations.Remove(i);
1338 isRemove = Standard_True;
1341 TopoDS_Shape bnd2 = sequenceSec.Value(index);
1342 if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
1344 if(myBoundFaces.Contains(bnd2)) {
1345 const TopTools_ListOfShape& listfaces = myBoundFaces.FindFromKey(bnd2);
1346 Standard_Boolean isMerged = Standard_True;
1347 for (lIt.Initialize(listfaces); lIt.More() && isMerged; lIt.Next()) {
1348 if(mapFaces.Contains(lIt.Value())) {
1349 TopLoc_Location loc;
1350 Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(lIt.Value()),loc);
1351 isMerged = ((IsUClosedSurface(surf,bnd2,loc) || IsVClosedSurface(surf,bnd2,loc)) &&
1352 IsMergedClosed(TopoDS::Edge(sequenceSec.Value(index)),TopoDS::Edge(workedge),TopoDS::Face(lIt.Value())));
1356 seqNotCandidate.Append(index);
1357 seqIndCandidate.Remove(i);
1358 seqOrientations.Remove(i);
1359 isRemove = Standard_True;
1363 seqIndCandidate.Remove(i);
1364 seqOrientations.Remove(i);
1365 isRemove = Standard_True;
1370 if(seqIndCandidate.Length() == 0 || seqNotCandidate.Length() == 1) return;
1371 if(!evalDist) return;
1372 TColStd_Array2OfReal TotTabDist(1,seqNotCandidate.Length(),1,seqIndCandidate.Length());
1373 TColStd_MapOfInteger MapIndex;
1374 TColStd_SequenceOfInteger seqForward;
1376 // Definition and removing edges wich are not candidate for work edge
1377 // ( they have other nearest edges belonging to the work face)
1378 for(Standard_Integer k = 1; k<= seqNotCandidate.Length(); k++) {
1379 Standard_Integer index1 = seqNotCandidate.Value(k);
1380 TopoDS_Shape edge = sequenceSec.Value(index1);
1381 TopTools_SequenceOfShape tmpSeq;
1382 tmpSeq.Append(edge);
1383 for(Standard_Integer kk = 1; kk <= seqIndCandidate.Length();kk++)
1384 tmpSeq.Append(sequenceSec.Value(seqIndCandidate.Value(kk)));
1386 Standard_Integer lengSec = tmpSeq.Length();
1387 TColStd_Array1OfBoolean tabForward(1,lengSec);
1388 TColStd_Array1OfReal tabDist(1,lengSec);
1389 TColStd_Array1OfReal arrLen(1,lengSec);
1390 TColStd_Array1OfReal tabMinDist(1,lengSec);
1391 for (Standard_Integer i1 = 1 ; i1 <= lengSec; i1++)
1394 EvaluateDistances(tmpSeq,tabForward, tabDist,arrLen,tabMinDist,1 );
1396 for(Standard_Integer n = 1; n < lengSec; n++) {
1397 if(tabDist(n+1) == -1 || tabDist(n+1) > myTolerance) {
1401 TotTabDist(k,n) = tabDist(n+1 );
1402 seqForward.Append(tabForward(n+1) ? 1:0);
1406 for(Standard_Integer n = 1; n < lengSec; n++) {
1407 if(tabDist(n) == -1 || tabDist(n) > myTolerance) continue;
1408 if(tabDist(n+1) < TotTabDist(1,n)) {
1416 Standard_Integer i2 = seqIndCandidate.Length();
1417 for( ; i2 >=1 ; i2--)
1419 if(MapIndex.Contains(i2))
1421 seqIndCandidate.Remove(i2);
1422 seqOrientations.Remove(i2);
1426 //for(TColStd_MapIteratorOfMapOfInteger IMap(MapIndex); IMap.More(); IMap.Next()) {
1427 // seqIndCandidate.Remove(IMap.Key());
1428 // seqOrientations.Remove(IMap.Key());
1432 //=======================================================================
1433 //function : FindCandidates
1434 //purpose : internal use
1435 //=======================================================================
1437 Standard_Boolean BRepBuilderAPI_Sewing::FindCandidates(TopTools_SequenceOfShape& seqSections,
1438 TColStd_IndexedMapOfInteger& mapReference,
1439 TColStd_SequenceOfInteger& seqCandidates,
1440 TColStd_SequenceOfInteger& seqOrientations)
1442 Standard_Integer i, nbSections = seqSections.Length();
1444 return Standard_False;
1445 // Retrieve last reference index
1446 Standard_Integer indReference = mapReference(mapReference.Extent());
1447 Standard_Integer nbCandidates = 0;
1448 TopTools_MapOfShape Faces1;
1449 //if (nbSections > 1) {
1451 TopoDS_Edge Edge1 = TopoDS::Edge(seqSections(indReference));
1453 // Retrieve faces for reference section
1455 { //szv: Use brackets to destroy local variables
1456 TopoDS_Shape bnd = Edge1;
1457 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1458 if (myBoundFaces.Contains(bnd)) {
1459 TopTools_ListIteratorOfListOfShape itf1(myBoundFaces.FindFromKey(bnd));
1460 for (; itf1.More(); itf1.Next()) Faces1.Add(itf1.Value());
1464 // Check merging conditions for candidates and remove unsatisfactory
1465 TopTools_SequenceOfShape seqSectionsNew;
1466 TColStd_SequenceOfInteger seqCandidatesNew;
1467 for (i = 1; i <= nbSections; i++) {
1468 if (i == indReference) {
1469 seqSectionsNew.Prepend(Edge1);
1470 seqCandidatesNew.Prepend(i);
1473 const TopoDS_Edge& Edge2 = TopoDS::Edge(seqSections(i));
1474 seqSectionsNew.Append(Edge2);
1475 seqCandidatesNew.Append(i);
1479 Standard_Integer nbSectionsNew = seqSectionsNew.Length();
1480 if (nbSectionsNew > 1) {
1482 // Evaluate distances between reference and other sections
1483 TColStd_Array1OfBoolean arrForward(1,nbSectionsNew);
1484 TColStd_Array1OfReal arrDistance(1,nbSectionsNew);
1485 TColStd_Array1OfReal arrLen(1,nbSectionsNew);
1486 TColStd_Array1OfReal arrMinDist(1,nbSectionsNew);
1487 EvaluateDistances(seqSectionsNew,arrForward,arrDistance,arrLen,arrMinDist,1);
1489 // Fill sequence of candidate indices sorted by distance
1490 for (i = 2; i <= nbSectionsNew; i++) {
1491 Standard_Real aMaxDist = arrDistance(i);
1492 if (aMaxDist >= 0.0 && aMaxDist <= myTolerance && arrLen(i) > myMinTolerance) {
1494 // Reference section is connected to section #i
1495 Standard_Boolean isInserted = Standard_False;
1496 Standard_Integer j, ori = (arrForward(i)? 1 : 0);
1497 for (j = 1; (j <= seqCandidates.Length()) && !isInserted; j++) {
1498 Standard_Real aDelta = arrDistance(i) - arrDistance(seqCandidates.Value(j));
1500 if( aDelta < Precision::Confusion()) {
1502 if(fabs(aDelta) > RealSmall() ||
1503 arrMinDist(i) < arrMinDist(seqCandidates.Value(j)))
1505 seqCandidates.InsertBefore(j,i);
1506 seqOrientations.InsertBefore(j,ori);
1507 isInserted = Standard_True;
1512 seqCandidates.Append(i);
1513 seqOrientations.Append(ori);
1518 nbCandidates = seqCandidates.Length();
1520 return Standard_False; // Section has no candidates to merge
1522 // Replace candidate indices
1524 for (i = 1; i <= nbCandidates; i++)
1525 seqCandidates(i) = seqCandidatesNew(seqCandidates(i));
1529 if (!nbCandidates) return Standard_False; // Section has no candidates to merge
1531 if (myNonmanifold && nbCandidates >1) {
1532 TColStd_SequenceOfInteger seqNewCandidates;
1533 TColStd_SequenceOfInteger seqOrientationsNew;
1534 seqCandidates.Prepend(1);
1535 seqOrientations.Prepend(1);
1536 for(Standard_Integer k = 1; k <= seqSections.Length() && seqCandidates.Length() > 1 ; k++) {
1537 AnalysisNearestEdges(seqSections,seqCandidates,seqOrientations,(k==1));
1538 if(k == 1 && !seqCandidates.Length()) return Standard_False;
1539 if(seqCandidates.Length()) {
1540 seqNewCandidates.Append(seqCandidates.First());
1541 seqOrientationsNew.Append(seqOrientations.First());
1544 seqCandidates.Prepend(seqNewCandidates);
1545 seqOrientations.Prepend(seqOrientationsNew);
1546 return Standard_True;
1550 // For manifold case leave only one candidate from equidistant candidates
1551 /*Standard_Integer minIndex = seqCandidateIndex.First();
1552 Standard_Real minDistance = arrDistance(minIndex);
1554 // Find equidistant candidates
1555 TColStd_SequenceOfInteger seqEqDistantIndex; seqEqDistantIndex.Append(1);
1556 for (i = 2; i <= nbCandidates; i++) {
1557 Standard_Integer index = seqCandidateIndex(i);
1558 if (Abs(minDistance - arrDistance(index)) <= Precision::Confusion())
1559 seqEqDistantIndex.Append(index);
1562 Standard_Integer eqLen = seqEqDistantIndex.Length();
1565 // Fill map of faces which equidistant sections belong to
1566 TopTools_MapOfShape mapFace;
1567 for (i = 1; i <= eqLen; i++) {
1568 Standard_Integer index = seqEqDistantIndex.Value(i);
1569 if (isCandidate(index)) {
1570 mapFace.Add(arrFace(index));
1574 // Non Manifold case
1575 // Edges are merged by pair among a face continuity C1 criterion
1576 if (mapFace.Extent() == eqLen) {
1582 Standard_Integer indMin = -1;// To check if the edge can be merged.
1583 // Computation of distances between the edges.
1584 TopTools_SequenceOfShape seqSh;
1585 Standard_Integer nbInd = EqDistSeq.Length();
1586 TColStd_Array1OfBoolean tmptabForward(1,nbInd);
1587 seqSh.Append(sequenceSec.Value(1));
1588 for (j = 2; j <= EqDistSeq.Length(); j++) {
1589 Standard_Integer index = EqDistSeq.Value(j);
1590 tmptabForward(j) = tabForward(index);
1591 seqSh.Append(sequenceSec.Value(index));
1594 EvaluateAngulars(seqSh, tmptabForward, tabDist,1);
1596 for(j=2; j <= seqSh.Length(); j++) {
1597 if (tabDist(j) > -1.) { // if edge(j) is connected to edge(i)
1598 if (min > tabDist(j)) {
1605 // Construct minDist, tabMinInd , tabMinForward(i) = tabForward(j);
1607 seqSh.Remove(indMin);
1608 for(j =2; j <= tmpSeq.Length(); ) {
1609 TopoDS_Shape sh = tmpSeq.Value(j);
1610 Standard_Boolean isRem = Standard_False;
1611 for(Standard_Integer k = 1; k<= seqSh.Length();k++) {
1612 if(seqSh.Value(k) == sh) {
1613 isRem = Standard_True;
1619 tabMinForward.Remove(j); // = -1;
1627 // Find the best approved candidate
1628 while (nbCandidates) {
1629 // Retrieve first candidate
1630 Standard_Integer indCandidate = seqCandidates.First();
1631 // Candidate is approved if it is in the map
1632 if (mapReference.Contains(indCandidate)) break;
1633 // Find candidates for candidate #indCandidate
1634 mapReference.Add(indCandidate); // Push candidate in the map
1635 TColStd_SequenceOfInteger seqCandidates1, seqOrientations1;
1636 Standard_Boolean isFound =
1637 FindCandidates(seqSections,mapReference,seqCandidates1,seqOrientations1);
1638 mapReference.RemoveLast(); // Pop candidate from the map
1639 if (isFound) isFound = (seqCandidates1.Length() > 0);
1641 Standard_Integer indCandidate1 = seqCandidates1.First();
1642 // If indReference is the best candidate for indCandidate
1643 // then indCandidate is the best candidate for indReference
1644 if (indCandidate1 == indReference) break;
1645 // If some other reference in the map is the best candidate for indCandidate
1646 // then assume that reference is the best candidate for indReference
1647 if (mapReference.Contains(indCandidate1)) {
1648 seqCandidates.Prepend(indCandidate1);
1652 isFound = Standard_False;
1655 // Remove candidate #1
1656 seqCandidates.Remove(1);
1657 seqOrientations.Remove(1);
1663 if(nbCandidates > 0)
1665 Standard_Integer anInd = seqCandidates.Value(1);
1666 TopoDS_Edge Edge2 = TopoDS::Edge(seqSections(anInd));
1667 TopoDS_Shape bnd = Edge2;
1668 if (mySectionBound.IsBound(bnd))
1669 bnd = mySectionBound(bnd);
1671 if (myBoundFaces.Contains(bnd)) {
1672 Standard_Boolean isOK = Standard_True;
1673 TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1674 for (; itf2.More() && isOK; itf2.Next()) {
1675 const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1676 // Check whether condition is satisfied
1677 isOK = !Faces1.Contains(Face2);
1678 if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1681 return Standard_False;
1684 return (nbCandidates > 0);
1687 //=======================================================================
1688 //function : Constructor
1690 //=======================================================================
1692 BRepBuilderAPI_Sewing::BRepBuilderAPI_Sewing(const Standard_Real tolerance,
1693 const Standard_Boolean optionSewing,
1694 const Standard_Boolean optionAnalysis,
1695 const Standard_Boolean optionCutting,
1696 const Standard_Boolean optionNonmanifold)
1698 myReShape = new BRepTools_ReShape;
1699 Init(tolerance, optionSewing, optionAnalysis, optionCutting, optionNonmanifold);
1702 //=======================================================================
1704 //purpose : Initialise Talerance, and options sewing, faceAnalysis and cutting
1705 //=======================================================================
1707 void BRepBuilderAPI_Sewing::Init(const Standard_Real tolerance,
1708 const Standard_Boolean optionSewing,
1709 const Standard_Boolean optionAnalysis,
1710 const Standard_Boolean optionCutting,
1711 const Standard_Boolean optionNonmanifold)
1713 // Set tolerance and Perform options
1714 myTolerance = Max (tolerance, Precision::Confusion());
1715 mySewing = optionSewing;
1716 myAnalysis = optionAnalysis;
1717 myCutting = optionCutting;
1718 myNonmanifold = optionNonmanifold;
1719 // Set min and max tolerances
1720 myMinTolerance = myTolerance * 1e-4; //szv: proposal
1721 if (myMinTolerance < Precision::Confusion()) myMinTolerance = Precision::Confusion();
1722 myMaxTolerance = Precision::Infinite();
1724 myFaceMode = Standard_True;
1725 myFloatingEdgesMode = Standard_False;
1726 //myCuttingFloatingEdgesMode = Standard_False; //gka
1727 mySameParameterMode = Standard_True;
1728 myLocalToleranceMode = Standard_False;
1729 mySewedShape.Nullify();
1731 Load(TopoDS_Shape());
1734 //=======================================================================
1736 //purpose : Loads the context shape
1737 //=======================================================================
1739 void BRepBuilderAPI_Sewing::Load(const TopoDS_Shape& theShape)
1742 if (theShape.IsNull()) myShape.Nullify();
1743 else myShape = myReShape->Apply(theShape);
1744 mySewedShape.Nullify();
1745 // Nullify flags and counters
1746 myNbShapes = myNbEdges = myNbVertices = 0;
1748 myOldShapes.Clear();
1749 //myOldFaces.Clear();
1750 myDegenerated.Clear();
1751 myFreeEdges.Clear();
1752 myMultipleEdges.Clear();
1753 myContigousEdges.Clear();
1754 myContigSecBound.Clear();
1755 myBoundFaces.Clear();
1756 myBoundSections.Clear();
1757 myVertexNode.Clear();
1758 myVertexNodeFree.Clear();
1759 myNodeSections.Clear();
1760 myCuttingNode.Clear();
1761 mySectionBound.Clear();
1762 myLittleFace.Clear();
1765 //=======================================================================
1768 //=======================================================================
1770 void BRepBuilderAPI_Sewing::Add(const TopoDS_Shape& aShape)
1772 if (aShape.IsNull()) return;
1773 TopoDS_Shape oShape = myReShape->Apply(aShape);
1774 myOldShapes.Add(aShape,oShape);
1775 myNbShapes = myOldShapes.Extent();
1778 //=======================================================================
1779 //function : Perform
1781 //=======================================================================
1784 #include <OSD_Timer.hxx>
1787 void BRepBuilderAPI_Sewing::Perform(const Handle(Message_ProgressIndicator)& thePI)
1789 const Standard_Integer aNumberOfStages = myAnalysis + myCutting + mySewing + 2;
1790 Message_ProgressSentry aPS (thePI, "Sewing", 0, aNumberOfStages, 1);
1792 Standard_Real t_total = 0., t_analysis = 0., t_assembling = 0., t_cutting = 0., t_merging = 0.;
1793 OSD_Chronometer chr_total, chr_local;
1802 cout << "Begin face analysis..." << endl;
1806 FaceAnalysis (thePI);
1812 chr_local.Show(t_analysis);
1813 cout << "Face analysis finished after " << t_analysis << " s" << endl;
1817 if (myNbShapes || !myShape.IsNull())
1820 FindFreeBoundaries();
1822 if (myBoundFaces.Extent())
1826 cout << "Begin vertices assembling..." << endl;
1830 VerticesAssembling (thePI);
1836 chr_local.Show(t_assembling);
1837 cout << "Vertices assembling finished after " << t_assembling << " s" << endl;
1842 cout << "Begin cutting..." << endl;
1852 chr_local.Show(t_cutting);
1853 cout << "Cutting finished after " << t_cutting << " s" << endl;
1857 cout << "Begin merging..." << endl;
1861 Merging (Standard_True, thePI);
1867 chr_local.Show(t_merging);
1868 cout << "Merging finished after " << t_merging << " s" << endl;
1873 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1875 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1876 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1885 cout << "Creating sewed shape..." << endl;
1887 // examine the multiple edges if any and process sameparameter for edges if necessary
1888 EdgeProcessing (thePI);
1894 mySewedShape.Nullify();
1897 if (mySameParameterMode && myFaceMode)
1898 SameParameterShape();
1901 mySewedShape.Nullify();
1905 cout << "Sewed shape created" << endl;
1909 // create edge informations for output
1910 CreateOutputInformations();
1913 mySewedShape.Nullify();
1919 chr_total.Show(t_total);
1920 cout << "Sewing finished!" << endl;
1921 cout << " analysis time : " << t_analysis << " s" << endl;
1922 cout << " assembling time : " << t_assembling << " s" << endl;
1923 cout << " cutting time : " << t_cutting << " s" << endl;
1924 cout << " merging time : " << t_merging << " s" << endl;
1925 cout << "Total time : " << t_total << " s" << endl;
1929 //=======================================================================
1930 //function : SewedShape
1931 //purpose : give the sewed shape
1932 // if a null shape, reasons:
1933 // -- no useable input shapes : all input shapes are degenerated
1934 // -- has multiple edges
1935 //=======================================================================
1937 const TopoDS_Shape& BRepBuilderAPI_Sewing::SewedShape() const
1939 return mySewedShape;
1942 //=======================================================================
1943 //function : NbFreeEdges
1945 //=======================================================================
1947 Standard_Integer BRepBuilderAPI_Sewing::NbFreeEdges() const
1949 return myFreeEdges.Extent();
1952 //=======================================================================
1953 //function : FreeEdge
1955 //=======================================================================
1957 const TopoDS_Edge& BRepBuilderAPI_Sewing::FreeEdge(const Standard_Integer index) const
1959 Standard_OutOfRange_Raise_if(index < 0 || index > NbFreeEdges(), "BRepBuilderAPI_Sewing::FreeEdge");
1960 return TopoDS::Edge(myFreeEdges(index));
1963 //=======================================================================
1964 //function : NbMultipleEdges
1966 //=======================================================================
1968 Standard_Integer BRepBuilderAPI_Sewing::NbMultipleEdges() const
1970 return myMultipleEdges.Extent();
1973 //=======================================================================
1974 //function : MultipleEdge
1976 //=======================================================================
1978 const TopoDS_Edge& BRepBuilderAPI_Sewing::MultipleEdge(const Standard_Integer index) const
1980 Standard_OutOfRange_Raise_if(index < 0 || index > NbMultipleEdges(), "BRepBuilderAPI_Sewing::MultipleEdge");
1981 return TopoDS::Edge(myMultipleEdges(index));
1984 //=======================================================================
1985 //function : NbContigousEdges
1987 //=======================================================================
1989 Standard_Integer BRepBuilderAPI_Sewing::NbContigousEdges() const
1991 return myContigousEdges.Extent();
1994 //=======================================================================
1995 //function : ContigousEdge
1997 //=======================================================================
1999 const TopoDS_Edge& BRepBuilderAPI_Sewing::ContigousEdge(const Standard_Integer index) const
2001 Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdge");
2002 return TopoDS::Edge(myContigousEdges.FindKey(index));
2005 //=======================================================================
2006 //function : ContigousEdgeCouple
2008 //=======================================================================
2010 const TopTools_ListOfShape& BRepBuilderAPI_Sewing::ContigousEdgeCouple(const Standard_Integer index) const
2012 Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdgeCouple");
2013 return myContigousEdges(index);
2016 //=======================================================================
2017 //function : IsSectionBound
2019 //=======================================================================
2021 Standard_Boolean BRepBuilderAPI_Sewing::IsSectionBound(const TopoDS_Edge& section) const
2023 if(myContigSecBound.IsBound(section)) {
2024 return Standard_True;
2027 return Standard_False;
2031 //=======================================================================
2032 //function : SectionToBoundary
2034 //=======================================================================
2036 const TopoDS_Edge& BRepBuilderAPI_Sewing::SectionToBoundary(const TopoDS_Edge& section) const
2038 Standard_NoSuchObject_Raise_if(!IsSectionBound(section), "BRepBuilderAPI_Sewing::SectionToBoundary");
2039 return TopoDS::Edge(myContigSecBound(section));
2041 //=======================================================================
2042 //function : NbDeletedFaces
2044 //=======================================================================
2045 Standard_Integer BRepBuilderAPI_Sewing::NbDeletedFaces() const
2047 return myLittleFace.Extent();
2050 //=======================================================================
2051 //function : DeletedFace
2053 //=======================================================================
2054 const TopoDS_Face& BRepBuilderAPI_Sewing::DeletedFace(const Standard_Integer index) const
2056 Standard_OutOfRange_Raise_if(index < 0 || index > NbDeletedFaces(), "BRepBuilderAPI_Sewing::DeletedFace");
2057 return TopoDS::Face(myLittleFace(index));
2060 //=======================================================================
2061 //function : NbDegeneratedShapes
2063 //=======================================================================
2065 Standard_Integer BRepBuilderAPI_Sewing::NbDegeneratedShapes() const
2067 return myDegenerated.Extent();
2070 //=======================================================================
2071 //function : DegeneratedShape
2073 //=======================================================================
2075 const TopoDS_Shape& BRepBuilderAPI_Sewing::DegeneratedShape(const Standard_Integer index) const
2077 Standard_OutOfRange_Raise_if(index < 0 || index > NbDegeneratedShapes(), "BRepBuilderAPI_Sewing::DegereratedShape");
2078 return myDegenerated(index);
2081 //=======================================================================
2082 //function : IsDegenerated
2084 //=======================================================================
2086 Standard_Boolean BRepBuilderAPI_Sewing::IsDegenerated(const TopoDS_Shape& aShape) const
2088 TopoDS_Shape NewShape = myReShape->Apply(aShape);
2090 if (aShape.ShapeType() == TopAbs_FACE)
2091 return NewShape.IsNull();
2092 if (NewShape.IsNull()) return Standard_False;
2094 if (NewShape.ShapeType() == TopAbs_EDGE)
2095 return BRep_Tool::Degenerated(TopoDS::Edge(NewShape));
2097 if (NewShape.ShapeType() == TopAbs_WIRE) {
2098 Standard_Boolean isDegenerated = Standard_True;
2099 for (TopoDS_Iterator aIt(NewShape); aIt.More() && isDegenerated; aIt.Next())
2100 isDegenerated = BRep_Tool::Degenerated(TopoDS::Edge(aIt.Value()));
2101 return isDegenerated;
2103 return Standard_False;
2106 //=======================================================================
2107 //function : IsModified
2109 //=======================================================================
2111 Standard_Boolean BRepBuilderAPI_Sewing::IsModified(const TopoDS_Shape& aShape) const
2113 TopoDS_Shape NewShape = aShape;
2114 if (myOldShapes.Contains(aShape))
2115 NewShape = myOldShapes.FindFromKey(aShape);
2116 if(!NewShape.IsSame(aShape)) return Standard_True;
2117 return Standard_False;
2120 //=======================================================================
2121 //function : Modified
2123 //=======================================================================
2125 const TopoDS_Shape& BRepBuilderAPI_Sewing::Modified(const TopoDS_Shape& aShape) const
2127 if (myOldShapes.Contains(aShape)) return myOldShapes.FindFromKey(aShape);
2128 //if (myOldFaces.Contains(aShape)) return myOldFaces.FindFromKey(aShape);
2132 //=======================================================================
2133 //function : IsModifiedSubShape
2135 //=======================================================================
2137 Standard_Boolean BRepBuilderAPI_Sewing::IsModifiedSubShape(const TopoDS_Shape& aShape) const
2139 TopoDS_Shape NewShape = myReShape->Apply(aShape);
2140 if(!NewShape.IsSame(aShape)) return Standard_True;
2141 return Standard_False;
2144 //=======================================================================
2145 //function : ModifiedSubShape
2147 //=======================================================================
2149 TopoDS_Shape BRepBuilderAPI_Sewing::ModifiedSubShape(const TopoDS_Shape& aShape) const
2151 return myReShape->Apply(aShape);
2154 //=======================================================================
2157 //=======================================================================
2159 void BRepBuilderAPI_Sewing::Dump() const
2161 Standard_Integer i, NbBounds = myBoundFaces.Extent(), NbSections = 0;
2162 TopTools_MapOfShape mapVertices, mapEdges;
2163 for (i = 1; i <= NbBounds; i++) {
2164 TopoDS_Shape bound = myBoundFaces.FindKey(i);
2165 if (myBoundSections.IsBound(bound)) NbSections += myBoundSections(bound).Extent();
2167 TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
2168 for (; aExp.More(); aExp.Next()) {
2169 TopoDS_Edge E = TopoDS::Edge(aExp.Current());
2171 TopoDS_Vertex V1, V2;
2172 TopExp::Vertices(E,V1,V2);
2173 mapVertices.Add(V1);
2174 mapVertices.Add(V2);
2177 cout << " " << endl;
2178 cout << " Informations " << endl;
2179 cout << " ===========================================================" << endl;
2180 cout << " " << endl;
2181 cout << " Number of input shapes : " << myOldShapes.Extent() << endl;
2182 cout << " Number of actual shapes : " << myNbShapes << endl;
2183 cout << " Number of Bounds : " << NbBounds << endl;
2184 cout << " Number of Sections : " << NbSections << endl;
2185 cout << " Number of Edges : " << mapEdges.Extent() << endl;
2186 cout << " Number of Vertices : " << myNbVertices << endl;
2187 cout << " Number of Nodes : " << mapVertices.Extent() << endl;
2188 cout << " Number of Free Edges : " << myFreeEdges.Extent() << endl;
2189 cout << " Number of Contigous Edges : " << myContigousEdges.Extent() << endl;
2190 cout << " Number of Multiple Edges : " << myMultipleEdges.Extent() << endl;
2191 cout << " Number of Degenerated Edges : " << myDegenerated.Extent() << endl;
2192 cout << " ===========================================================" << endl;
2193 cout << " " << endl;
2196 //=======================================================================
2197 //function : FaceAnalysis
2205 //=======================================================================
2207 void BRepBuilderAPI_Sewing::FaceAnalysis(const Handle(Message_ProgressIndicator)& thePI)
2209 if (!myShape.IsNull() && myOldShapes.IsEmpty()) {
2215 TopTools_MapOfShape SmallEdges;
2216 TopTools_DataMapOfShapeListOfShape GluedVertices;
2217 Standard_Integer i = 1;
2218 Message_ProgressSentry aPS (thePI, "Shape analysis", 0, myOldShapes.Extent(), 1);
2219 for (i = 1; i <= myOldShapes.Extent() && aPS.More(); i++, aPS.Next()) {
2220 for (TopExp_Explorer fexp(myOldShapes(i),TopAbs_FACE); fexp.More(); fexp.Next()) {
2222 // Retrieve current face
2223 TopoDS_Shape aTmpShape = fexp.Current(); //for porting
2224 TopoDS_Face face = TopoDS::Face(aTmpShape);
2225 Standard_Integer nbEdges = 0, nbSmall = 0;
2227 // Build replacing face
2228 aTmpShape = face.EmptyCopied().Oriented(TopAbs_FORWARD); //for porting
2229 TopoDS_Face nface = TopoDS::Face(aTmpShape);
2230 Standard_Boolean isFaceChanged = Standard_False;
2232 TopoDS_Iterator witer(face.Oriented(TopAbs_FORWARD));
2233 for (; witer.More(); witer.Next()) {
2235 // Retrieve current wire
2236 aTmpShape = witer.Value(); //for porting
2237 if( aTmpShape.ShapeType() != TopAbs_WIRE) continue;
2238 TopoDS_Wire wire = TopoDS::Wire(aTmpShape);
2240 // Build replacing wire
2241 aTmpShape = wire.EmptyCopied().Oriented(TopAbs_FORWARD);
2242 TopoDS_Wire nwire = TopoDS::Wire(aTmpShape);
2243 Standard_Boolean isWireChanged = Standard_False;
2245 TopoDS_Iterator eiter(wire.Oriented(TopAbs_FORWARD));
2246 for (; eiter.More(); eiter.Next()) {
2248 // Retrieve current edge
2249 aTmpShape = eiter.Value(); //for porting
2250 TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
2253 // Process degenerated edge
2254 if (BRep_Tool::Degenerated(edge)) {
2255 B.Add(nwire,edge); // Old edge kept
2256 myDegenerated.Add(edge);
2261 Standard_Boolean isSmall = SmallEdges.Contains(edge);
2264 // Check for small edge
2265 Standard_Real first, last;
2266 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,first,last);
2269 cout << "Warning: Possibly small edge can be sewed: No 3D curve" << endl;
2273 // Evaluate curve compactness
2274 const Standard_Integer npt = 5;
2275 gp_Pnt cp((c3d->Value(first).XYZ()+c3d->Value(last).XYZ())*0.5);
2276 Standard_Real dist, maxdist = 0.0;
2277 Standard_Real delta = (last - first)/(npt - 1);
2278 for (Standard_Integer idx = 0; idx < npt; idx++) {
2279 dist = cp.Distance(c3d->Value(first + idx*delta));
2280 if (maxdist < dist) maxdist = dist;
2282 isSmall = (2.*maxdist <= MinTolerance());
2284 GeomAdaptor_Curve cAdapt(c3d);
2285 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt,first,last);
2286 isSmall = (length <= MinTolerance());
2288 catch (Standard_Failure) {
2290 cout << "Warning: Possibly small edge can be sewed: ";
2291 Standard_Failure::Caught()->Print(cout); cout << endl;
2298 // Store small edge in the map
2299 SmallEdges.Add(edge);
2301 TopoDS_Vertex v1, v2;
2302 TopExp::Vertices(edge,v1,v2);
2303 TopoDS_Shape nv1 = myReShape->Apply(v1), nv2 = myReShape->Apply(v2);
2305 // Store glued vertices
2306 if (!nv1.IsSame(v1)) {
2307 TopTools_ListOfShape& vlist1 = GluedVertices(nv1);
2308 // First vertex was already glued
2309 if (!nv2.IsSame(v2)) {
2310 // Merge lists of glued vertices
2311 if (!nv1.IsSame(nv2)) {
2312 TopTools_ListIteratorOfListOfShape liter(GluedVertices(nv2));
2313 for (; liter.More(); liter.Next()) {
2314 TopoDS_Shape v = liter.Value();
2315 myReShape->Replace(v,nv1.Oriented(v.Orientation()));
2318 GluedVertices.UnBind(nv2);
2322 // Add second vertex to the existing list
2324 myReShape->Replace(v2,nv1.Oriented(v2.Orientation()));
2327 else if (!nv2.IsSame(v2)) {
2328 // Add first vertex to the existing list
2329 GluedVertices(nv2).Append(v1);
2330 myReShape->Replace(v1,nv2.Oriented(v1.Orientation()));
2332 else if (!v1.IsSame(v2)) {
2333 // Record new glued vertices
2336 TopTools_ListOfShape vlist;
2339 GluedVertices.Bind(nv,vlist);
2340 myReShape->Replace(v1,nv.Oriented(v1.Orientation()));
2341 myReShape->Replace(v2,nv.Oriented(v2.Orientation()));
2346 // Replace small edge
2349 cout << "Warning: Small edge made degenerated by FaceAnalysis" << endl;
2352 // Create new degenerated edge
2353 aTmpShape = edge.Oriented(TopAbs_FORWARD);
2354 TopoDS_Edge fedge = TopoDS::Edge(aTmpShape);
2355 Standard_Real pfirst, plast;
2356 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(fedge,face,pfirst,plast);
2357 if (!c2d.IsNull()) {
2360 B.UpdateEdge(nedge,c2d,face,Precision::Confusion());
2361 B.Range(nedge,pfirst,plast);
2362 B.Degenerated(nedge,Standard_True);
2363 TopoDS_Vertex v1, v2;
2364 TopExp::Vertices(fedge,v1,v2);
2365 B.Add(nedge,myReShape->Apply(v1).Oriented(v1.Orientation()));
2366 B.Add(nedge,myReShape->Apply(v2).Oriented(v2.Orientation()));
2367 B.Add(nwire,nedge.Oriented(edge.Orientation()));
2368 myDegenerated.Add(nedge);
2370 isWireChanged = Standard_True;
2372 else B.Add(nwire,edge); // Old edge kept
2375 // Record wire in the new face
2376 if (isWireChanged) {
2377 B.Add(nface,nwire.Oriented(wire.Orientation()));
2378 isFaceChanged = Standard_True;
2380 else B.Add(nface,wire);
2383 // Remove small face
2384 if (nbSmall == nbEdges) {
2386 cout << "Warning: Small face removed by FaceAnalysis" << endl;
2388 myLittleFace.Add(face);
2389 myReShape->Remove(face);
2391 else if (isFaceChanged) {
2393 myReShape->Replace(face,nface.Oriented(face.Orientation()));
2398 // Update glued vertices
2399 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape miter(GluedVertices);
2400 for (; miter.More(); miter.Next()) {
2401 TopoDS_Vertex vnew = TopoDS::Vertex(miter.Key());
2402 gp_XYZ coord(0.,0.,0.);
2403 Standard_Integer nbPoints = 0;
2404 const TopTools_ListOfShape& vlist = miter.Value();
2405 TopTools_ListIteratorOfListOfShape liter1(vlist);
2406 for (; liter1.More(); liter1.Next()) {
2407 coord += BRep_Tool::Pnt(TopoDS::Vertex(liter1.Value())).XYZ();
2411 gp_Pnt vp(coord / nbPoints);
2412 Standard_Real tol = 0.0, mtol = 0.0;
2413 TopTools_ListIteratorOfListOfShape liter2(vlist);
2414 for (; liter2.More(); liter2.Next()) {
2415 Standard_Real vtol = BRep_Tool::Tolerance(TopoDS::Vertex(liter2.Value()));
2416 if (mtol < vtol) mtol = vtol;
2417 vtol = vp.Distance(BRep_Tool::Pnt(TopoDS::Vertex(liter2.Value())));
2418 if (tol < vtol) tol = vtol;
2420 B.UpdateVertex(vnew,vp,tol+mtol);
2424 // Update input shapes
2425 for (i = 1; i <= myOldShapes.Extent(); i++)
2426 myOldShapes(i) = myReShape->Apply(myOldShapes(i));
2429 //=======================================================================
2430 //function : FindFreeBoundaries
2431 //purpose : Constructs :
2432 // myBoundFaces (bound = list of faces) - REFERENCE
2433 // myVertexNode (vertex = node)
2434 // myVertexNodeFree (floating vertex = node)
2436 //=======================================================================
2438 void BRepBuilderAPI_Sewing::FindFreeBoundaries()
2440 // Take into account the context shape if needed
2441 TopTools_IndexedMapOfShape NewShapes;
2442 if (!myShape.IsNull()) {
2443 if (myOldShapes.IsEmpty()) {
2448 TopoDS_Shape newShape = myReShape->Apply(myShape);
2449 if (!newShape.IsNull()) NewShapes.Add(newShape);
2452 // Create map Edge -> Faces
2453 TopTools_IndexedDataMapOfShapeListOfShape EdgeFaces;
2454 Standard_Integer i, nbShapes = myOldShapes.Extent();
2455 for (i = 1; i <= nbShapes; i++) {
2456 // Retrieve new shape
2457 TopoDS_Shape shape = myOldShapes(i);
2458 if (shape.IsNull()) continue;
2459 NewShapes.Add(shape);
2460 // Explore shape to find all boundaries
2461 for (TopExp_Explorer eExp(shape,TopAbs_EDGE); eExp.More(); eExp.Next()) {
2462 TopoDS_Shape edge = eExp.Current();
2463 if (!EdgeFaces.Contains(edge)) {
2464 TopTools_ListOfShape listFaces;
2465 EdgeFaces.Add(edge,listFaces);
2469 // Fill map Edge -> Faces
2470 nbShapes = NewShapes.Extent();
2471 TopTools_MapOfShape mapFaces;
2472 for (i = 1; i <= nbShapes; i++) {
2473 // Explore shape to find all faces
2474 TopExp_Explorer fExp(NewShapes.FindKey(i),TopAbs_FACE);
2475 for (; fExp.More(); fExp.Next()) {
2476 TopoDS_Shape face = fExp.Current();
2477 if(mapFaces.Contains(face)) continue;
2480 // Explore face to find all boundaries
2481 for (TopoDS_Iterator aIw(face); aIw.More(); aIw.Next()) {
2482 if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
2483 for (TopoDS_Iterator aIIe(aIw.Value()); aIIe.More(); aIIe.Next()) {
2485 TopoDS_Shape edge = aIIe.Value();
2487 if (EdgeFaces.Contains(edge)) {
2488 EdgeFaces.ChangeFromKey(edge).Append(face);
2489 //TopTools_ListOfShape& listFaces = EdgeFaces.ChangeFromKey(edge);
2490 //Standard_Boolean isContained = Standard_False;
2491 //TopTools_ListIteratorOfListOfShape itf(listFaces);
2492 //for (; itf.More() && !isContained; itf.Next())
2493 // isContained = face.IsSame(itf.Value());
2494 //if (!isContained) listFaces.Append(face);
2500 // Find free boundaries
2501 nbShapes = EdgeFaces.Extent();
2502 for (i = 1; i <= nbShapes; i++) {
2503 TopTools_ListOfShape& listFaces = EdgeFaces(i);
2504 Standard_Integer nbFaces = listFaces.Extent();
2505 TopoDS_Shape edge = EdgeFaces.FindKey(i);
2506 if(edge.Orientation() == TopAbs_INTERNAL)
2508 Standard_Boolean isSeam = Standard_False;
2510 TopoDS_Face face = TopoDS::Face(listFaces.First());
2511 isSeam = BRep_Tool::IsClosed(TopoDS::Edge(edge),face);
2513 ///Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
2514 //isSeam = (IsUClosedSurface(surf) || IsVClosedSurface(surf));
2517 TopoDS_Shape anewEdge = edge.EmptyCopied();
2518 TopoDS_Iterator aItV(edge);
2519 for( ; aItV.More() ; aItV.Next())
2520 aB.Add(anewEdge,aItV.Value());
2524 Standard_Real first2d,last2d;
2525 Handle(Geom2d_Curve) c2dold =
2526 BRep_Tool::CurveOnSurface(TopoDS::Edge(edge),TopoDS::Face(listFaces.First()),first2d,last2d);
2528 Handle(Geom2d_Curve) c2d;
2530 B.UpdateEdge(TopoDS::Edge(anewEdge),c2d,c2d,TopoDS::Face(listFaces.First()),0);
2531 B.UpdateEdge(TopoDS::Edge(anewEdge),c2dold,TopoDS::Face(listFaces.First()),0);
2533 Standard_Real aFirst, aLast;
2534 BRep_Tool::Range(TopoDS::Edge(edge),aFirst, aLast);
2535 aB.Range(TopoDS::Edge(anewEdge),aFirst, aLast);
2536 aB.Range(TopoDS::Edge(anewEdge),TopoDS::Face(listFaces.First()),first2d,last2d);
2537 myReShape->Replace(edge,anewEdge);
2541 isSeam = Standard_False;
2544 Standard_Boolean isBoundFloat = (myFloatingEdgesMode && !nbFaces);
2545 Standard_Boolean isBound = (myFaceMode && ((myNonmanifold && nbFaces) || (nbFaces == 1 && !isSeam)));
2546 if (isBound || isBoundFloat) {
2547 // Ignore degenerated edge
2548 if (BRep_Tool::Degenerated(TopoDS::Edge(edge))) continue;
2549 // Ignore edge with internal vertices
2550 // Standard_Integer nbVtx = 0;
2551 // for (TopExp_Explorer vExp(edge,TopAbs_VERTEX); vExp.More(); vExp.Next()) nbVtx++;
2552 // if (nbVtx != 2) continue;
2553 // Add to BoundFaces
2554 TopTools_ListOfShape listFacesCopy;
2555 listFacesCopy.Append(listFaces);
2556 myBoundFaces.Add(edge,listFacesCopy);
2557 // Process edge vertices
2558 TopoDS_Vertex vFirst, vLast;
2559 TopExp::Vertices(TopoDS::Edge(edge), vFirst, vLast);
2560 if(vFirst.IsNull() || vLast.IsNull()) continue;
2561 if(vFirst.Orientation() == TopAbs_INTERNAL || vLast.Orientation() == TopAbs_INTERNAL)
2564 // Add to VertexNode
2565 if (!myVertexNode.Contains(vFirst))
2566 myVertexNode.Add(vFirst,vFirst);
2567 if (!myVertexNode.Contains(vLast))
2568 myVertexNode.Add(vLast,vLast);
2571 // Add to VertexNodeFree
2572 if (!myVertexNodeFree.Contains(vFirst))
2573 myVertexNodeFree.Add(vFirst,vFirst);
2574 if (!myVertexNodeFree.Contains(vLast))
2575 myVertexNodeFree.Add(vLast,vLast);
2581 //=======================================================================
2582 //function : VerticesAssembling
2583 //purpose : Modifies :
2584 // myVertexNode (nodes glued)
2585 // myVertexNodeFree (nodes glued)
2586 // myNodeSections (lists of sections merged for glued nodes)
2588 //=======================================================================
2590 static Standard_Boolean CreateNewNodes(const TopTools_IndexedDataMapOfShapeShape& NodeNearestNode,
2591 const TopTools_IndexedDataMapOfShapeListOfShape& NodeVertices,
2592 TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2593 TopTools_DataMapOfShapeListOfShape& aNodeEdges)
2595 Standard_Integer i, nbNearest = NodeNearestNode.Extent();
2599 TopTools_DataMapOfShapeShape OldNodeNewNode;
2600 TopTools_DataMapOfShapeListOfShape NewNodeOldNodes;
2601 for (i = 1; i <= nbNearest; i++) {
2602 // Retrieve a pair of nodes to merge
2603 TopoDS_Shape oldnode1 = NodeNearestNode.FindKey(i);
2604 TopoDS_Shape oldnode2 = NodeNearestNode(i);
2605 // Second node should also be in the map
2606 if (!NodeNearestNode.Contains(oldnode2)) continue;
2607 // Get new node for old node #1
2608 if (OldNodeNewNode.IsBound(oldnode1)) {
2609 TopoDS_Shape newnode1 = OldNodeNewNode(oldnode1);
2610 if (OldNodeNewNode.IsBound(oldnode2)) {
2611 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2612 if (!newnode1.IsSame(newnode2)) {
2613 // Change data for new node #2
2614 TopTools_ListOfShape& lnode1 = NewNodeOldNodes(newnode1);
2615 TopTools_ListIteratorOfListOfShape itn(NewNodeOldNodes(newnode2));
2616 for (; itn.More(); itn.Next()) {
2617 TopoDS_Shape node2 = itn.Value();
2618 lnode1.Append(node2);
2619 OldNodeNewNode(node2) = newnode1;
2621 NewNodeOldNodes.UnBind(newnode2);
2625 // Old node #2 is not bound - add to old node #1
2626 OldNodeNewNode.Bind(oldnode2,newnode1);
2627 NewNodeOldNodes(newnode1).Append(oldnode2);
2631 if (OldNodeNewNode.IsBound(oldnode2)) {
2632 // Old node #1 is not bound - add to old node #2
2633 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2634 OldNodeNewNode.Bind(oldnode1,newnode2);
2635 NewNodeOldNodes(newnode2).Append(oldnode1);
2638 // Nodes are not bound - create new node
2639 TopoDS_Vertex newnode;
2640 B.MakeVertex(newnode);
2641 OldNodeNewNode.Bind(oldnode1,newnode);
2642 OldNodeNewNode.Bind(oldnode2,newnode);
2643 TopTools_ListOfShape lnodes;
2644 lnodes.Append(oldnode1);
2645 lnodes.Append(oldnode2);
2646 NewNodeOldNodes.Bind(newnode,lnodes);
2651 // Stop if no new nodes created
2652 if (!NewNodeOldNodes.Extent()) return Standard_False;
2654 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter1(NewNodeOldNodes);
2655 for (; iter1.More(); iter1.Next()) {
2656 const TopoDS_Vertex& newnode = TopoDS::Vertex(iter1.Key());
2657 // Calculate new node center point
2658 gp_XYZ theCoordinates(0.,0.,0.);
2659 TopTools_ListOfShape lvert; // Accumulate node vertices
2660 TopTools_MapOfShape medge;
2661 TopTools_ListOfShape ledge; // Accumulate node edges
2662 // Iterate on old nodes
2663 TopTools_ListIteratorOfListOfShape itn(iter1.Value());
2664 for (; itn.More(); itn.Next()) {
2665 const TopoDS_Shape& oldnode = itn.Value();
2666 // Iterate on node vertices
2667 TopTools_ListIteratorOfListOfShape itv(NodeVertices.FindFromKey(oldnode));
2668 for (; itv.More(); itv.Next()) {
2669 TopoDS_Vertex vertex = TopoDS::Vertex(itv.Value());
2670 // Change node for vertex
2671 aVertexNode.ChangeFromKey(vertex) = newnode;
2672 // Accumulate coordinates
2673 theCoordinates += BRep_Tool::Pnt(vertex).XYZ();
2674 lvert.Append(vertex);
2676 // Iterate on node edges
2677 const TopTools_ListOfShape& edges = aNodeEdges(oldnode);
2678 TopTools_ListIteratorOfListOfShape ite(edges);
2679 for (; ite.More(); ite.Next()) {
2680 TopoDS_Shape edge = ite.Value();
2681 if (!medge.Contains(edge)) { medge.Add(edge); ledge.Append(edge); }
2683 // Unbind old node edges
2684 aNodeEdges.UnBind(oldnode);
2686 // Bind new node edges
2687 aNodeEdges.Bind(newnode,ledge);
2688 gp_Pnt center(theCoordinates / lvert.Extent());
2689 // Calculate new node tolerance
2690 Standard_Real toler = 0.0;
2691 TopTools_ListIteratorOfListOfShape itv(lvert);
2692 for (; itv.More(); itv.Next()) {
2693 const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value());
2694 Standard_Real t = center.Distance(BRep_Tool::Pnt(vertex)) + BRep_Tool::Tolerance(vertex);
2695 if (toler < t) toler = t;
2697 // Update new node parameters
2698 B.UpdateVertex(newnode,center,toler);
2701 return Standard_True;
2704 static Standard_Integer IsMergedVertices(const TopoDS_Shape& face1,
2705 const TopoDS_Shape& e1, const TopoDS_Shape& e2,
2706 const TopoDS_Shape& vtx1, const TopoDS_Shape& vtx2)
2708 //Case of floating edges
2710 return (!IsClosedShape(e1,vtx1,vtx2));
2712 // Find wires containing given edges
2713 TopoDS_Shape wire1, wire2;
2714 TopExp_Explorer itw(face1,TopAbs_WIRE);
2715 for (; itw.More() && (wire1.IsNull() || wire2.IsNull()); itw.Next()) {
2716 TopoDS_Iterator ite(itw.Current(),Standard_False);
2717 for (; ite.More() && (wire1.IsNull() || wire2.IsNull()); ite.Next()) {
2718 if (wire1.IsNull() && e1.IsSame(ite.Value())) wire1 = itw.Current();
2719 if (wire2.IsNull() && e2.IsSame(ite.Value())) wire2 = itw.Current();
2722 Standard_Integer Status = 0;
2723 if (!wire1.IsNull() && !wire2.IsNull()) {
2724 if (wire1.IsSame(wire2)) {
2725 for (TopoDS_Iterator aIte(wire1,Standard_False); aIte.More(); aIte.Next()) {
2726 TopoDS_Vertex ve1,ve2;
2727 TopExp::Vertices(TopoDS::Edge(aIte.Value()),ve1,ve2);
2728 if ((ve1.IsSame(vtx1) && ve2.IsSame(vtx2)) ||
2729 (ve2.IsSame(vtx1) && ve1.IsSame(vtx2)))
2730 return (IsClosedShape(aIte.Value(),vtx1,vtx2)? 0 : 1);
2732 if (IsClosedShape(wire1,vtx1,vtx2)) {
2733 TopoDS_Vertex V1, V2;
2734 TopExp::Vertices(TopoDS::Wire(wire1),V1,V2);
2735 Standard_Boolean isEndVertex = ((V1.IsSame(vtx1) && V2.IsSame(vtx2)) ||
2736 (V2.IsSame(vtx1) && V1.IsSame(vtx2)));
2737 if (!isEndVertex) Status = 1;
2746 static Standard_Boolean GlueVertices(TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2747 TopTools_DataMapOfShapeListOfShape& aNodeEdges,
2748 const TopTools_IndexedDataMapOfShapeListOfShape& aBoundFaces,
2749 const Standard_Real Tolerance,
2750 const Handle(Message_ProgressIndicator)& theProgress)
2752 Standard_Integer i, nbVertices = aVertexNode.Extent();
2753 // Create map of node -> vertices
2754 TopTools_IndexedDataMapOfShapeListOfShape NodeVertices;
2755 BRepBuilderAPI_CellFilter aFilter (Tolerance);
2756 BRepBuilderAPI_VertexInspector anInspector (Tolerance);
2757 for (i = 1; i <= nbVertices; i++) {
2758 TopoDS_Shape vertex = aVertexNode.FindKey(i);
2759 TopoDS_Vertex node = TopoDS::Vertex(aVertexNode(i));
2760 if (NodeVertices.Contains(node)) {
2761 NodeVertices.ChangeFromKey(node).Append(vertex);
2764 TopTools_ListOfShape vlist;
2765 vlist.Append(vertex);
2766 NodeVertices.Add(node,vlist);
2767 gp_Pnt aPnt = BRep_Tool::Pnt (TopoDS::Vertex (node));
2768 aFilter.Add (NodeVertices.FindIndex (node), aPnt.XYZ());
2769 anInspector.Add (aPnt.XYZ());
2772 Standard_Integer nbNodes = NodeVertices.Extent();
2774 cout << "Glueing " << nbNodes << " nodes..." << endl;
2776 // Merge nearest nodes
2777 TopTools_IndexedDataMapOfShapeShape NodeNearestNode;
2778 Message_ProgressSentry aPS (theProgress, "Glueing nodes", 0, nbNodes, 1, Standard_True);
2779 for (i = 1; i <= nbNodes && aPS.More(); i++, aPS.Next()) {
2780 TopoDS_Vertex node1 = TopoDS::Vertex(NodeVertices.FindKey(i));
2782 gp_Pnt pt1 = BRep_Tool::Pnt (node1);
2783 anInspector.SetCurrent (pt1.XYZ());
2784 gp_XYZ aPntMin = anInspector.Shift (pt1.XYZ(), -Tolerance);
2785 gp_XYZ aPntMax = anInspector.Shift (pt1.XYZ(), Tolerance);
2786 aFilter.Inspect (aPntMin, aPntMax, anInspector);
2787 if (anInspector.ResInd().IsEmpty()) continue;
2788 // Retrieve list of edges for the first node
2789 const TopTools_ListOfShape& ledges1 = aNodeEdges(node1);
2790 // Explore list of near nodes and fill the sequence of glued nodes
2791 TopTools_SequenceOfShape SeqNodes;
2792 TopTools_ListOfShape listNodesSameEdge;
2793 //gp_Pnt pt1 = BRep_Tool::Pnt(node1);
2794 TColStd_ListIteratorOfListOfInteger iter1(anInspector.ResInd());
2795 for (; iter1.More(); iter1.Next()) {
2796 TopoDS_Vertex node2 = TopoDS::Vertex(NodeVertices.FindKey(iter1.Value()));
2797 if (node1 == node2) continue;
2798 // Retrieve list of edges for the second node
2799 const TopTools_ListOfShape& ledges2 = aNodeEdges(node2);
2800 // Check merging condition for the pair of nodes
2801 Standard_Integer Status = 0, isSameEdge = Standard_False;
2802 // Explore edges of the first node
2803 TopTools_ListIteratorOfListOfShape Ie1(ledges1);
2804 for (; Ie1.More() && !Status && !isSameEdge; Ie1.Next()) {
2805 const TopoDS_Shape& e1 = Ie1.Value();
2806 // Obtain real vertex from edge
2807 TopoDS_Shape v1 = node1;
2808 { //szv: Use brackets to destroy local variables
2809 TopoDS_Vertex ov1, ov2;
2810 TopExp::Vertices(TopoDS::Edge(e1),ov1,ov2);
2811 if (aVertexNode.Contains(ov1)) {
2812 if (node1.IsSame(aVertexNode.FindFromKey(ov1))) v1 = ov1;
2814 if (aVertexNode.Contains(ov2)) {
2815 if (node1.IsSame(aVertexNode.FindFromKey(ov2))) v1 = ov2;
2818 // Create map of faces for e1
2819 TopTools_MapOfShape Faces1;
2820 const TopTools_ListOfShape& lfac1 = aBoundFaces.FindFromKey(e1);
2821 if (lfac1.Extent()) {
2822 TopTools_ListIteratorOfListOfShape itf(lfac1);
2823 for (; itf.More(); itf.Next())
2824 if (!itf.Value().IsNull())
2825 Faces1.Add(itf.Value());
2827 // Explore edges of the second node
2828 TopTools_ListIteratorOfListOfShape Ie2(ledges2);
2829 for (; Ie2.More() && !Status && !isSameEdge; Ie2.Next()) {
2830 const TopoDS_Shape& e2 = Ie2.Value();
2831 // Obtain real vertex from edge
2832 TopoDS_Shape v2 = node2;
2833 { //szv: Use brackets to destroy local variables
2834 TopoDS_Vertex ov1, ov2;
2835 TopExp::Vertices(TopoDS::Edge(e2),ov1,ov2);
2836 if (aVertexNode.Contains(ov1)) {
2837 if (node2.IsSame(aVertexNode.FindFromKey(ov1))) v2 = ov1;
2839 if (aVertexNode.Contains(ov2)) {
2840 if (node2.IsSame(aVertexNode.FindFromKey(ov2))) v2 = ov2;
2843 // Explore faces for e2
2844 const TopTools_ListOfShape& lfac2 = aBoundFaces.FindFromKey(e2);
2845 if (lfac2.Extent()) {
2846 TopTools_ListIteratorOfListOfShape itf(lfac2);
2847 for (; itf.More() && !Status && !isSameEdge; itf.Next()) {
2848 // Check merging conditions for the same face
2849 if (Faces1.Contains(itf.Value())) {
2850 Standard_Integer stat = IsMergedVertices(itf.Value(),e1,e2,v1,v2);
2851 if (stat == 1) isSameEdge = Standard_True;
2856 else if (Faces1.IsEmpty() && e1 == e2) {
2857 Standard_Integer stat = IsMergedVertices(TopoDS_Face(),e1,e1,v1,v2);
2858 if (stat == 1) isSameEdge = Standard_True;
2864 if (Status) continue;
2865 if (isSameEdge) listNodesSameEdge.Append(node2);
2866 // Append near node to the sequence
2867 gp_Pnt pt2 = BRep_Tool::Pnt(node2);
2868 Standard_Real dist = pt1.Distance(pt2);
2869 if (dist < Tolerance) {
2870 Standard_Boolean isIns = Standard_False;
2871 for (Standard_Integer kk = 1; kk <= SeqNodes.Length() && !isIns; kk++) {
2872 gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(SeqNodes.Value(kk)));
2873 if (dist < pt1.Distance(pt)) {
2874 SeqNodes.InsertBefore(kk,node2);
2875 isIns = Standard_True;
2878 if (!isIns) SeqNodes.Append(node2);
2881 if (SeqNodes.Length()) {
2882 // Remove nodes near to some other from the same edge
2883 if (listNodesSameEdge.Extent()) {
2884 TopTools_ListIteratorOfListOfShape lInt(listNodesSameEdge);
2885 for (; lInt.More(); lInt.Next()) {
2886 const TopoDS_Vertex& n2 = TopoDS::Vertex(lInt.Value());
2887 gp_Pnt p2 = BRep_Tool::Pnt(n2);
2888 for (Standard_Integer k = 1; k <= SeqNodes.Length(); ) {
2889 const TopoDS_Vertex& n1 = TopoDS::Vertex(SeqNodes.Value(k));
2891 gp_Pnt p1 = BRep_Tool::Pnt(n1);
2892 if (p2.Distance(p1) >= pt1.Distance(p1)) { k++; continue; }
2898 // Bind nearest node if at least one exists
2899 if (SeqNodes.Length())
2900 NodeNearestNode.Add(node1,SeqNodes.First());
2902 anInspector.ClearResList();
2905 // Create new nodes for chained nearest nodes
2906 if (NodeNearestNode.IsEmpty()) return Standard_False;
2908 return CreateNewNodes(NodeNearestNode,NodeVertices,aVertexNode,aNodeEdges);
2911 void BRepBuilderAPI_Sewing::VerticesAssembling(const Handle(Message_ProgressIndicator)& thePI)
2913 Standard_Integer nbVert = myVertexNode.Extent();
2914 Standard_Integer nbVertFree = myVertexNodeFree.Extent();
2915 Message_ProgressSentry aPS (thePI, "Vertices assembling", 0, 2, 1);
2916 if (nbVert || nbVertFree) {
2917 // Fill map node -> sections
2919 for (i = 1; i <= myBoundFaces.Extent(); i++) {
2920 TopoDS_Shape bound = myBoundFaces.FindKey(i);
2921 for (TopoDS_Iterator itv(bound,Standard_False); itv.More(); itv.Next()) {
2922 TopoDS_Shape node = itv.Value();
2923 if (myNodeSections.IsBound(node))
2924 myNodeSections(node).Append(bound);
2926 TopTools_ListOfShape lbnd;
2928 myNodeSections.Bind(node,lbnd);
2935 cout << "Assemble " << nbVert << " vertices on faces..." << endl;
2937 while (GlueVertices(myVertexNode,myNodeSections,myBoundFaces,myTolerance, thePI));
2944 cout << "Assemble " << nbVertFree << " vertices on floating edges..." << endl;
2946 while (GlueVertices(myVertexNodeFree,myNodeSections,myBoundFaces,myTolerance, thePI));
2951 //=======================================================================
2952 //function : replaceNMVertices
2953 //purpose : internal use (static)
2954 //=======================================================================
2955 static void replaceNMVertices(const TopoDS_Edge& theEdge,
2956 const TopoDS_Vertex& theV1,
2957 const TopoDS_Vertex& theV2,
2958 const Handle(BRepTools_ReShape)& theReShape)
2960 //To keep NM vertices on edge
2961 TopTools_SequenceOfShape aSeqNMVert;
2962 TColStd_SequenceOfReal aSeqNMPars;
2963 Standard_Boolean hasNMVert = findNMVertices(theEdge,aSeqNMVert,aSeqNMPars);
2966 Standard_Real first, last;
2967 BRep_Tool::Range(theEdge, first, last);
2968 TopLoc_Location aLoc;
2969 Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,aLoc,first, last);
2972 TopTools_SequenceOfShape aEdVert;
2973 TColStd_SequenceOfReal aEdParams;
2974 Standard_Integer i =1, nb = aSeqNMPars.Length();
2976 for( ; i <= nb;i++) {
2977 Standard_Real apar = aSeqNMPars.Value(i);
2978 if(fabs(apar - first) <= Precision::PConfusion()) {
2979 theReShape->Replace(aSeqNMVert.Value(i),theV1);
2982 if(fabs(apar - last) <= Precision::PConfusion()) {
2983 theReShape->Replace(aSeqNMVert.Value(i),theV2);
2986 TopoDS_Shape aV = aSeqNMVert.Value(i);
2987 Standard_Integer j =1;
2988 for( ; j <= aEdParams.Length();j++) {
2989 Standard_Real apar2 = aEdParams.Value(j);
2990 if(fabs(apar - apar2) <= Precision::PConfusion()) {
2991 theReShape->Replace(aV,aEdVert.Value(j));
2994 else if(apar < apar2) {
2995 TopoDS_Shape anewV = aV.EmptyCopied();
2996 aEdVert.InsertBefore(j,anewV);
2997 aEdParams.InsertBefore(j,apar);
2998 BRep_ListOfPointRepresentation& alistrep =
2999 (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints();
3000 Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
3001 alistrep.Append(aPRep);
3002 theReShape->Replace(aV,anewV);
3006 if (j > aEdParams.Length()) {
3007 TopoDS_Shape anewV = aV.EmptyCopied();
3008 aEdVert.Append(anewV);
3009 aEdParams.Append(apar);
3010 BRep_ListOfPointRepresentation& alistrep =
3011 (*((Handle(BRep_TVertex)*) &anewV.TShape()))->ChangePoints();
3012 Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
3013 alistrep.Append(aPRep);
3014 theReShape->Replace(aV,anewV);
3018 Standard_Integer newnb = aEdParams.Length();
3021 TopoDS_Shape anewEdge = theEdge.EmptyCopied();
3022 TopAbs_Orientation anOri = theEdge.Orientation();
3023 anewEdge.Orientation(TopAbs_FORWARD);
3025 aB.Add(anewEdge,theV1);
3026 aB.Add(anewEdge,theV2);
3028 for( i =1; i <= aEdVert.Length();i++)
3029 aB.Add(anewEdge,aEdVert.Value(i));
3030 anewEdge.Orientation(anOri);
3031 theReShape->Replace(theEdge,anewEdge);
3036 //=======================================================================
3037 //function : ReplaceEdge
3038 //purpose : internal use (static)
3039 //=======================================================================
3041 static void ReplaceEdge(const TopoDS_Shape& oldEdge,
3042 const TopoDS_Shape& theNewShape,
3043 const Handle(BRepTools_ReShape)& aReShape)
3045 TopoDS_Shape oldShape = aReShape->Apply(oldEdge);
3046 TopoDS_Shape newShape = aReShape->Apply(theNewShape);
3047 if (oldShape.IsSame(newShape)|| aReShape->IsRecorded(newShape)) return;
3050 aReShape->Replace(oldShape,newShape);
3051 TopoDS_Vertex V1old,V2old,V1new,V2new;
3052 TopExp::Vertices(TopoDS::Edge(oldShape),V1old,V2old);
3053 TopAbs_Orientation Orold = oldShape.Orientation();
3054 TopAbs_Orientation Ornew = Orold;
3055 if (newShape.ShapeType() == TopAbs_EDGE) {
3056 TopoDS_Edge aEn = TopoDS::Edge(newShape);
3057 TopExp::Vertices(aEn,V1new,V2new);
3058 Ornew = aEn.Orientation();
3059 replaceNMVertices(aEn,V1new,V2new,aReShape);
3061 else if (newShape.ShapeType() == TopAbs_WIRE) {
3062 for (TopExp_Explorer aex(newShape,TopAbs_EDGE); aex.More(); aex.Next()) {
3063 TopoDS_Edge ed = TopoDS::Edge(aex.Current());
3064 Ornew = ed.Orientation();
3065 TopoDS_Vertex aV1,aV2;
3066 TopExp::Vertices(ed,aV1,aV2);
3067 replaceNMVertices(ed,aV1,aV2,aReShape);
3074 V1new.Orientation(V1old.Orientation());
3075 V2new.Orientation(V2old.Orientation());
3076 if (V1old.IsSame(V2old) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) {
3077 aReShape->Replace(V1old,V1new);
3080 if (Orold == Ornew) {
3081 V1new.Orientation(V1old.Orientation());
3082 V2new.Orientation(V2old.Orientation());
3083 if (!V1old.IsSame(V1new) && !V1old.IsSame(V2new)&& !aReShape->IsRecorded(V1new))
3084 aReShape->Replace(V1old,V1new);
3085 if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3086 aReShape->Replace(V2old,V2new);
3089 V1new.Orientation(V2old.Orientation());
3090 V2new.Orientation(V1old.Orientation());
3091 if (!V1old.IsSame(V2new) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3092 aReShape->Replace(V1old,V2new);
3093 if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V1new))
3094 aReShape->Replace(V2old,V1new);
3098 //=======================================================================
3099 //function : Merging
3100 //purpose : Modifies :
3103 //=======================================================================
3105 void BRepBuilderAPI_Sewing::Merging(const Standard_Boolean /* firstTime */,
3106 const Handle(Message_ProgressIndicator)& thePI)
3109 // TopTools_MapOfShape MergedEdges;
3110 Message_ProgressSentry aPS (thePI, "Merging bounds", 0, myBoundFaces.Extent(), 1);
3111 for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
3113 TopoDS_Shape bound = myBoundFaces.FindKey(i);
3115 // If bound was already merged - continue
3116 if (myMergedEdges.Contains(bound)) continue;
3118 if (!myBoundFaces(i).Extent()) {
3119 // Merge free edge - only vertices
3120 TopoDS_Vertex no1, no2;
3121 TopExp::Vertices(TopoDS::Edge(bound),no1,no2);
3122 TopoDS_Shape nno1 = no1, nno2 = no2;
3123 if (myVertexNodeFree.Contains(no1))
3124 nno1 = myVertexNodeFree.FindFromKey(no1);
3125 if (myVertexNodeFree.Contains(no2))
3126 nno2 = myVertexNodeFree.FindFromKey(no2);
3127 if (!no1.IsSame(nno1)) {
3128 nno1.Orientation(no1.Orientation());
3129 myReShape->Replace(no1,nno1);
3131 if (!no2.IsSame(nno2)) {
3132 nno2.Orientation(no2.Orientation());
3133 myReShape->Replace(no2,nno2);
3135 myMergedEdges.Add(bound);
3139 // Check for previous splitting, build replacing wire
3140 TopoDS_Wire BoundWire;
3141 Standard_Boolean isPrevSplit = Standard_False;
3142 Standard_Boolean hasCuttingSections = myBoundSections.IsBound(bound);
3143 if (hasCuttingSections) {
3144 B.MakeWire(BoundWire);
3145 BoundWire.Orientation(bound.Orientation());
3146 // Iterate on cutting sections
3147 TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3148 for (; its.More(); its.Next()) {
3149 TopoDS_Shape section = its.Value();
3150 B.Add(BoundWire,section);
3151 if (myMergedEdges.Contains(section)) isPrevSplit = Standard_True;
3156 TopTools_DataMapOfShapeShape MergedWithBound;
3158 // Obtain sequence of edges merged with bound
3159 TopTools_SequenceOfShape seqMergedWithBound;
3160 TColStd_SequenceOfInteger seqMergedWithBoundOri;
3161 if (MergedNearestEdges(bound,seqMergedWithBound,seqMergedWithBoundOri)) {
3162 // Store bound in the map
3163 MergedWithBound.Bind(bound,bound);
3164 // Iterate on edges merged with bound
3165 Standard_Integer ii = 1;
3166 while (ii <= seqMergedWithBound.Length()) {
3167 TopoDS_Shape iedge = seqMergedWithBound.Value(ii);
3168 // Remove edge if recorded as merged
3169 Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) ||
3170 MergedWithBound.IsBound(iedge));
3172 if (myBoundSections.IsBound(iedge)) {
3173 // Edge is splitted - check sections
3174 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3175 for (; lit.More() && !isRejected; lit.Next()) {
3176 const TopoDS_Shape& sec = lit.Value();
3177 // Remove edge (bound) if at least one of its sections already merged
3178 isRejected = (myMergedEdges.Contains(sec) || MergedWithBound.IsBound(sec));
3182 if (mySectionBound.IsBound(iedge)) {
3183 // Edge is a section - check bound
3184 const TopoDS_Shape& bnd = mySectionBound(iedge);
3185 // Remove edge (section) if its bound already merged
3186 isRejected = (myMergedEdges.Contains(bnd) || MergedWithBound.IsBound(bnd));
3190 // To the next merged edge
3192 // Remove rejected edge
3193 seqMergedWithBound.Remove(ii);
3194 seqMergedWithBoundOri.Remove(ii);
3197 // Process accepted edge
3198 MergedWithBound.Bind(iedge,iedge);
3202 Standard_Integer nbMerged = seqMergedWithBound.Length();
3204 // Create same parameter edge
3205 TopTools_MapOfShape ActuallyMerged;
3206 TopoDS_Edge MergedEdge = SameParameterEdge(bound,seqMergedWithBound,
3207 seqMergedWithBoundOri,
3208 ActuallyMerged,myReShape);
3209 Standard_Boolean isForward = Standard_False;
3210 if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3211 // Process actually merged edges
3212 Standard_Integer nbActuallyMerged = 0;
3213 for (ii = 1; ii <= nbMerged; ii++) {
3214 TopoDS_Shape iedge = seqMergedWithBound(ii);
3215 if (ActuallyMerged.Contains(iedge)) {
3217 // Record merged edge in the map
3218 TopAbs_Orientation orient = iedge.Orientation();
3219 if (!isForward) orient = TopAbs::Reverse(orient);
3220 if (!seqMergedWithBoundOri(ii)) orient = TopAbs::Reverse(orient);
3221 MergedWithBound.ChangeFind(iedge) = MergedEdge.Oriented(orient);
3223 else MergedWithBound.UnBind(iedge);
3225 if (nbActuallyMerged) {
3226 // Record merged bound in the map
3227 TopAbs_Orientation orient = bound.Orientation();
3228 if (!isForward) orient = TopAbs::Reverse(orient);
3229 MergedWithBound.ChangeFind(bound) = MergedEdge.Oriented(orient);
3231 nbMerged = nbActuallyMerged;
3233 // Remove bound from the map if not finally merged
3234 if (!nbMerged) MergedWithBound.UnBind(bound);
3237 Standard_Boolean isMerged = MergedWithBound.Extent();
3239 // Merge with cutting sections
3240 Handle(BRepTools_ReShape) SectionsReShape = new BRepTools_ReShape;
3241 TopTools_DataMapOfShapeShape MergedWithSections;
3242 if (hasCuttingSections) {
3243 // Iterate on cutting sections
3244 TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3245 for (; its.More(); its.Next()) {
3246 // Retrieve cutting section
3247 TopoDS_Shape section = its.Value();
3248 // Skip section if already merged
3249 if (myMergedEdges.Contains(section)) continue;
3250 // Merge cutting section
3251 TopTools_SequenceOfShape seqMergedWithSection;
3252 TColStd_SequenceOfInteger seqMergedWithSectionOri;
3253 if (MergedNearestEdges(section,seqMergedWithSection,seqMergedWithSectionOri)) {
3254 // Store section in the map
3255 MergedWithSections.Bind(section,section);
3256 // Iterate on edges merged with section
3257 Standard_Integer ii = 1;
3258 while (ii <= seqMergedWithSection.Length()) {
3259 TopoDS_Shape iedge = seqMergedWithSection.Value(ii);
3260 // Remove edge if recorded as merged
3261 Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || MergedWithSections.IsBound(iedge));
3263 if (myBoundSections.IsBound(iedge)) {
3264 // Edge is splitted - check sections
3265 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3266 for (; lit.More() && !isRejected; lit.Next()) {
3267 const TopoDS_Shape& sec = lit.Value();
3268 // Remove edge (bound) if at least one of its sections already merged
3269 isRejected = (myMergedEdges.Contains(sec) || MergedWithSections.IsBound(sec));
3273 if (mySectionBound.IsBound(iedge)) {
3274 // Edge is a section - check bound
3275 const TopoDS_Shape& bnd = mySectionBound(iedge);
3276 // Remove edge (section) if its bound already merged
3277 isRejected = (myMergedEdges.Contains(bnd) || MergedWithSections.IsBound(bnd));
3281 // To the next merged edge
3283 // Remove rejected edge
3284 seqMergedWithSection.Remove(ii);
3285 seqMergedWithSectionOri.Remove(ii);
3288 // Process accepted edge
3289 MergedWithSections.Bind(iedge,iedge);
3293 Standard_Integer nbMerged = seqMergedWithSection.Length();
3295 // Create same parameter edge
3296 TopTools_MapOfShape ActuallyMerged;
3297 TopoDS_Edge MergedEdge = SameParameterEdge(section,seqMergedWithSection,
3298 seqMergedWithSectionOri,
3299 ActuallyMerged,SectionsReShape);
3300 Standard_Boolean isForward = Standard_False;
3301 if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3302 // Process actually merged edges
3303 Standard_Integer nbActuallyMerged = 0;
3304 for (ii = 1; ii <= nbMerged; ii++) {
3305 TopoDS_Shape iedge = seqMergedWithSection(ii);
3306 if (ActuallyMerged.Contains(iedge)) {
3308 // Record merged edge in the map
3309 TopAbs_Orientation orient = iedge.Orientation();
3310 if (!isForward) orient = TopAbs::Reverse(orient);
3311 if (!seqMergedWithSectionOri(ii)) orient = TopAbs::Reverse(orient);
3312 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3313 MergedWithSections.ChangeFind(iedge) = oedge;
3314 ReplaceEdge(myReShape->Apply(iedge),oedge,SectionsReShape);
3316 else MergedWithSections.UnBind(iedge);
3318 if (nbActuallyMerged) {
3319 // Record merged section in the map
3320 TopAbs_Orientation orient = section.Orientation();
3321 if (!isForward) orient = TopAbs::Reverse(orient);
3322 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3323 MergedWithSections.ChangeFind(section) = oedge;
3324 ReplaceEdge(myReShape->Apply(section),oedge,SectionsReShape);
3326 nbMerged = nbActuallyMerged;
3328 // Remove section from the map if not finally merged
3329 if (!nbMerged) MergedWithSections.UnBind(section);
3331 else if (isMerged) {
3332 // Reject merging of sections
3333 MergedWithSections.Clear();
3338 Standard_Boolean isMergedSplit = MergedWithSections.Extent();
3340 if (!isMerged && !isMergedSplit) {
3341 // Nothing was merged in this iteration
3343 // Replace previously splitted bound
3344 myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3346 // else if (hasCuttingSections) {
3347 // myBoundSections.UnBind(bound); //szv: are you sure ???
3352 // Set splitting flag
3353 Standard_Boolean isSplitted = ((!isMerged && isMergedSplit) || isPrevSplit);
3355 // Choose between bound and sections merging
3356 if (isMerged && isMergedSplit && !isPrevSplit) {
3357 // Fill map of merged cutting sections
3358 TopTools_MapOfShape MapSplitEdges;
3359 TopTools_DataMapIteratorOfDataMapOfShapeShape itm;
3360 for (itm.Initialize(MergedWithSections); itm.More(); itm.Next()) {
3361 TopoDS_Shape edge = itm.Key();
3362 MapSplitEdges.Add(edge);
3364 // Iterate on edges merged with bound
3365 for (itm.Initialize(MergedWithBound); itm.More(); itm.Next()) {
3366 // Retrieve edge merged with bound
3367 TopoDS_Shape edge = itm.Key();
3368 // Remove edge from the map
3369 if (MapSplitEdges.Contains(edge)) MapSplitEdges.Remove(edge);
3370 if (myBoundSections.IsBound(edge)) {
3371 // Edge has cutting sections
3372 TopTools_ListIteratorOfListOfShape its(myBoundSections(edge));
3373 for (; its.More(); its.Next()) {
3374 TopoDS_Shape sec = its.Value();
3375 // Remove section from the map
3376 if (MapSplitEdges.Contains(sec)) MapSplitEdges.Remove(sec);
3380 // Calculate section merging tolerance
3381 Standard_Real MinSplitTol = RealLast();
3382 TopTools_MapIteratorOfMapOfShape im(MapSplitEdges);
3383 for (; im.More(); im.Next()) {
3384 TopoDS_Edge edge = TopoDS::Edge(MergedWithSections(im.Key()));
3385 MinSplitTol = Min(MinSplitTol,BRep_Tool::Tolerance(edge));
3387 // Calculate bound merging tolerance
3388 TopoDS_Edge BoundEdge = TopoDS::Edge(MergedWithBound(bound));
3389 Standard_Real BoundEdgeTol = BRep_Tool::Tolerance(BoundEdge);
3390 isSplitted = ((MinSplitTol < BoundEdgeTol+MinTolerance()) || myNonmanifold);
3391 isSplitted = (!MapSplitEdges.IsEmpty() && isSplitted);
3395 // Merging of cutting sections
3396 //myMergedEdges.Add(bound);
3397 myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3398 TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithSections);
3399 for (; itm.More(); itm.Next()) {
3400 TopoDS_Shape oldedge = itm.Key();
3401 TopoDS_Shape newedge = SectionsReShape->Apply(itm.Value());
3402 ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3403 myMergedEdges.Add(oldedge);
3404 if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3409 // Merging of initial bound
3410 TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithBound);
3411 //myMergedEdges.Add(bound);
3412 for (; itm.More(); itm.Next()) {
3413 TopoDS_Shape oldedge = itm.Key();
3414 TopoDS_Shape newedge = itm.Value();
3415 ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3416 myMergedEdges.Add(oldedge);
3417 if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3419 if (myBoundSections.IsBound(bound)) myBoundSections.UnBind(bound);
3420 if(!myMergedEdges.Contains(bound))
3421 myMergedEdges.Add(bound);
3425 myNbVertices = myVertexNode.Extent() + myVertexNodeFree.Extent();
3426 myNodeSections.Clear();
3427 myVertexNode.Clear();
3428 myVertexNodeFree.Clear();
3429 myCuttingNode.Clear();
3432 //=======================================================================
3433 //function : MergedNearestEdges
3435 //=======================================================================
3437 Standard_Boolean BRepBuilderAPI_Sewing::MergedNearestEdges(const TopoDS_Shape& edge,
3438 TopTools_SequenceOfShape& SeqMergedEdge,
3439 TColStd_SequenceOfInteger& SeqMergedOri)
3441 // Retrieve edge nodes
3442 TopoDS_Vertex no1, no2;
3443 TopExp::Vertices(TopoDS::Edge(edge),no1,no2);
3444 TopoDS_Shape nno1 = no1, nno2 = no2;
3445 Standard_Boolean isNode1 = myVertexNode.Contains(no1);
3446 Standard_Boolean isNode2 = myVertexNode.Contains(no2);
3447 if (isNode1) nno1 = myVertexNode.FindFromKey(no1);
3448 if (isNode2) nno2 = myVertexNode.FindFromKey(no2);
3450 // Fill map of nodes connected to the node #1
3451 TopTools_MapOfShape mapVert1;
3453 if (myCuttingNode.IsBound(nno1)) {
3454 TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno1));
3455 for (; ilv.More(); ilv.Next()) {
3456 TopoDS_Shape v1 = ilv.Value();
3458 if (!isNode1 && myCuttingNode.IsBound(v1)) {
3459 TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3460 for (; ilvn.More(); ilvn.Next()) {
3461 TopoDS_Shape vn = ilvn.Value();
3468 // Fill map of nodes connected to the node #2
3469 TopTools_MapOfShape mapVert2;
3471 if (myCuttingNode.IsBound(nno2)) {
3472 TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno2));
3473 for (; ilv.More(); ilv.Next()) {
3474 TopoDS_Shape v1 = ilv.Value();
3476 if (!isNode2 && myCuttingNode.IsBound(v1)) {
3477 TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3478 for (; ilvn.More(); ilvn.Next()) {
3479 TopoDS_Shape vn = ilvn.Value();
3486 // Find all possible contigous edges
3487 TopTools_SequenceOfShape seqEdges;
3488 seqEdges.Append(edge);
3489 TopTools_MapOfShape mapEdges;
3491 for (TopTools_MapIteratorOfMapOfShape imv1(mapVert1); imv1.More(); imv1.Next()) {
3492 TopoDS_Shape node1 = imv1.Key();
3493 if (!myNodeSections.IsBound(node1)) continue;
3494 TopTools_ListIteratorOfListOfShape ilsec(myNodeSections(node1));
3495 for (; ilsec.More(); ilsec.Next()) {
3496 TopoDS_Shape sec = ilsec.Value();
3497 if (sec.IsSame(edge)) continue;
3498 // Retrieve section nodes
3499 TopoDS_Vertex vs1, vs2;
3500 TopExp::Vertices(TopoDS::Edge(sec),vs1,vs2);
3501 TopoDS_Shape vs1n = vs1, vs2n = vs2;
3502 if (myVertexNode.Contains(vs1)) vs1n = myVertexNode.FindFromKey(vs1);
3503 if (myVertexNode.Contains(vs2)) vs2n = myVertexNode.FindFromKey(vs2);
3504 if ((mapVert1.Contains(vs1n) && mapVert2.Contains(vs2n)) ||
3505 (mapVert1.Contains(vs2n) && mapVert2.Contains(vs1n)))
3506 if (mapEdges.Add(sec)) {
3507 // Check for rejected cutting
3508 Standard_Boolean isRejected = myMergedEdges.Contains(sec);
3509 if(!isRejected && myBoundSections.IsBound(sec))
3511 TopTools_ListIteratorOfListOfShape its(myBoundSections(sec));
3512 for (; its.More() && !isRejected; its.Next()) {
3513 TopoDS_Shape section = its.Value();
3515 if (myMergedEdges.Contains(section))
3516 isRejected = Standard_True;
3519 if( !isRejected && mySectionBound.IsBound(sec)) {
3520 const TopoDS_Shape& bnd = mySectionBound(sec);
3521 isRejected = (!myBoundSections.IsBound(bnd) ||
3522 myMergedEdges.Contains(bnd));
3525 if (!isRejected) seqEdges.Append(sec);
3532 Standard_Boolean success = Standard_False;
3534 Standard_Integer nbSection = seqEdges.Length();
3535 if (nbSection > 1) {
3536 // Find the longest edge CCI60011
3537 Standard_Integer i, indRef = 1;
3538 if (myNonmanifold) {
3539 Standard_Real lenRef = 0.;
3540 for (i = 1; i <= nbSection; i++) {
3542 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(seqEdges(i)), f, l);
3543 GeomAdaptor_Curve cAdapt(c3d);
3544 Standard_Real len = GCPnts_AbscissaPoint::Length(cAdapt, f, l);
3545 if (len > lenRef) { indRef = i; lenRef = len; }
3548 TopoDS_Shape longEdge = seqEdges(indRef);
3549 seqEdges(indRef) = seqEdges(1);
3550 seqEdges(1) = longEdge;
3554 // Find merging candidates
3555 TColStd_SequenceOfInteger seqForward;
3556 TColStd_SequenceOfInteger seqCandidates;
3557 TColStd_IndexedMapOfInteger mapReference;
3558 mapReference.Add(1); // Add index of reference section
3559 if (FindCandidates(seqEdges,mapReference,seqCandidates,seqForward)) {
3560 Standard_Integer nbCandidates = seqCandidates.Length();
3561 // Check if reference section is merged reversed
3562 Standard_Boolean toReverse = Standard_False;
3564 // Find reference edge in candidates
3565 Standard_Boolean isFound = Standard_False;
3566 for (i = 1; i <= nbCandidates && !isFound; i++) {
3567 isFound = (seqCandidates(i) == indRef);
3569 // Record orientation
3570 toReverse = !seqForward(i);
3571 // Restore first edge
3572 seqCandidates(i) = 1;
3576 // Fail if reference is not in candidates
3577 if (!isFound) return Standard_False;
3579 // Record candidate sections
3580 for (i = 1; i <= nbCandidates; i++) {
3581 // Retrieve merged edge
3582 TopoDS_Shape iedge = seqEdges(seqCandidates(i));
3583 Standard_Integer ori =
3584 ((seqForward(i) && toReverse) || (!seqForward(i) && !toReverse))? 0 : 1;
3585 SeqMergedEdge.Append(iedge);
3586 SeqMergedOri.Append(ori);
3587 if (!myNonmanifold) break;
3589 success = nbCandidates;
3596 //=======================================================================
3597 //function : Cutting
3598 //purpose : Modifies :
3602 //=======================================================================
3604 void BRepBuilderAPI_Sewing::Cutting(const Handle(Message_ProgressIndicator)& thePI)
3606 Standard_Integer i, nbVertices = myVertexNode.Extent();
3607 if (!nbVertices) return;
3608 // Create a box tree with vertices
3609 Standard_Real eps = myTolerance*0.5;
3610 BRepBuilderAPI_BndBoxTree aTree;
3611 NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller (aTree);
3612 BRepBuilderAPI_BndBoxTreeSelector aSelector;
3613 for (i = 1; i <= nbVertices; i++) {
3614 gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(myVertexNode.FindKey(i)));
3618 aTreeFiller.Add (i, aBox);
3622 Handle(Geom_Curve) c3d;
3623 TopLoc_Location loc;
3624 Standard_Real first, last;
3625 // Iterate on all boundaries
3626 Standard_Integer nbBounds = myBoundFaces.Extent();
3627 Message_ProgressSentry aPS (thePI, "Cutting bounds", 0, nbBounds, 1);
3628 for (i = 1; i <= nbBounds && aPS.More(); i++, aPS.Next()) {
3629 const TopoDS_Edge& bound = TopoDS::Edge(myBoundFaces.FindKey(i));
3630 // Do not cut floating edges
3631 if (!myBoundFaces(i).Extent()) continue;
3632 // Create cutting sections
3633 TopTools_ListOfShape listSections;
3634 { //szv: Use brackets to destroy local variables
3635 // Obtain bound curve
3636 c3d = BRep_Tool::Curve(bound, loc, first, last);
3637 if (!loc.IsIdentity()) {
3638 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3639 c3d->Transform(loc.Transformation());
3641 // Obtain candidate vertices
3642 TopoDS_Vertex V1, V2;
3643 TopTools_IndexedMapOfShape CandidateVertices;
3644 { //szv: Use brackets to destroy local variables
3645 // Create bounding box around curve
3647 GeomAdaptor_Curve adptC(c3d,first,last);
3648 BndLib_Add3dCurve::Add(adptC,myTolerance,aGlobalBox);
3649 // Sort vertices to find candidates
3650 aSelector.SetCurrent (aGlobalBox);
3651 aTree.Select (aSelector);
3652 // Skip bound if no node is in the boundind box
3653 if (!aSelector.ResInd().Extent()) continue;
3654 // Retrieve bound nodes
3655 TopExp::Vertices(bound,V1,V2);
3656 const TopoDS_Shape& Node1 = myVertexNode.FindFromKey(V1);
3657 const TopoDS_Shape& Node2 = myVertexNode.FindFromKey(V2);
3658 // Fill map of candidate vertices
3659 TColStd_ListIteratorOfListOfInteger itl(aSelector.ResInd());
3660 for (; itl.More(); itl.Next()) {
3661 const Standard_Integer index = itl.Value();
3662 const TopoDS_Shape& Node = myVertexNode.FindFromIndex(index);
3663 if (!Node.IsSame(Node1) && !Node.IsSame(Node2)) {
3664 TopoDS_Shape vertex = myVertexNode.FindKey(index);
3665 CandidateVertices.Add(vertex);
3668 aSelector.ClearResList();
3670 Standard_Integer nbCandidates = CandidateVertices.Extent();
3671 if (!nbCandidates) continue;
3672 // Project vertices on curve
3673 TColStd_Array1OfReal arrPara(1,nbCandidates), arrDist(1,nbCandidates);
3674 TColgp_Array1OfPnt arrPnt(1,nbCandidates), arrProj(1,nbCandidates);
3675 for (Standard_Integer j = 1; j <= nbCandidates; j++)
3676 arrPnt(j) = BRep_Tool::Pnt(TopoDS::Vertex(CandidateVertices(j)));
3677 ProjectPointsOnCurve(arrPnt,c3d,first,last,arrDist,arrPara,arrProj,Standard_True);
3678 // Create cutting nodes
3679 TopTools_SequenceOfShape seqNode;
3680 TColStd_SequenceOfReal seqPara;
3681 CreateCuttingNodes(CandidateVertices,bound,
3682 V1,V2,arrDist,arrPara,arrProj,seqNode,seqPara);
3683 if (!seqPara.Length()) continue;
3684 // Create cutting sections
3685 CreateSections(bound, seqNode, seqPara, listSections);
3687 if (listSections.Extent() > 1) {
3688 // modification of maps:
3690 TopTools_ListIteratorOfListOfShape its(listSections);
3691 for (; its.More(); its.Next()) {
3692 TopoDS_Shape section = its.Value();
3693 // Iterate on section vertices
3694 for (TopoDS_Iterator itv(section); itv.More(); itv.Next()) {
3695 TopoDS_Shape vertex = itv.Value();
3696 // Convert vertex to node
3697 if (myVertexNode.Contains(vertex))
3698 vertex = TopoDS::Vertex(myVertexNode.FindFromKey(vertex));
3699 // Update node sections
3700 if (myNodeSections.IsBound(vertex))
3701 myNodeSections.ChangeFind(vertex).Append(section);
3703 TopTools_ListOfShape lsec;
3704 lsec.Append(section);
3705 myNodeSections.Bind(vertex,lsec);
3708 // Store bound for section
3709 mySectionBound.Bind(section,bound);
3711 // Store splitted bound
3712 myBoundSections.Bind(bound,listSections);
3716 cout << "From " << nbBounds << " bounds " << myBoundSections.Extent()
3717 << " were cut into " << mySectionBound.Extent() << " sections" << endl;
3721 //=======================================================================
3722 //function : GetSeqEdges
3724 //=======================================================================
3726 static void GetSeqEdges(const TopoDS_Shape& edge,
3727 TopTools_SequenceOfShape& seqEdges,
3728 TopTools_DataMapOfShapeListOfShape& VertEdge)
3730 Standard_Integer numV = 0;
3731 for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3732 TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3734 if (VertEdge.IsBound(V1)) {
3735 const TopTools_ListOfShape& listEdges = VertEdge.Find(V1);
3736 for (TopTools_ListIteratorOfListOfShape lIt(listEdges); lIt.More(); lIt.Next()) {
3737 TopoDS_Shape edge1 = lIt.Value();
3738 if (edge1.IsSame(edge)) continue;
3739 Standard_Boolean isContained = Standard_False;
3740 Standard_Integer i, index = 1;
3741 for (i = 1; i <= seqEdges.Length() && !isContained; i++) {
3742 isContained = seqEdges.Value(i).IsSame(edge1);
3743 if (!isContained && seqEdges.Value(i).IsSame(edge)) index = i;
3746 if (numV == 1) seqEdges.InsertBefore(index,edge1);
3747 else seqEdges.InsertAfter(index,edge1);
3748 GetSeqEdges(edge1,seqEdges,VertEdge);
3755 //=======================================================================
3756 //function : GetFreeWires
3758 //=======================================================================
3760 void BRepBuilderAPI_Sewing::GetFreeWires(TopTools_MapOfShape& MapFreeEdges, TopTools_SequenceOfShape& seqWires)
3762 TopTools_DataMapOfShapeListOfShape VertEdge;
3763 TopTools_MapIteratorOfMapOfShape itMap(MapFreeEdges);
3764 TopTools_SequenceOfShape seqFreeEdges;
3765 for (; itMap.More(); itMap.Next()) {
3766 TopoDS_Shape edge = itMap.Key();
3767 seqFreeEdges.Append(edge);
3768 for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3769 TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3770 if (VertEdge.IsBound(V1))
3771 VertEdge.ChangeFind(V1).Append(edge);
3773 TopTools_ListOfShape ls;
3775 VertEdge.Bind(V1,ls);
3780 Standard_Integer i, j;
3781 for (i = 1; i <= seqFreeEdges.Length(); i++) {
3782 TopTools_SequenceOfShape seqEdges;
3783 TopoDS_Shape edge = seqFreeEdges.Value(i);
3784 if (!MapFreeEdges.Contains(edge)) continue;
3785 seqEdges.Append(edge);
3786 GetSeqEdges(edge,seqEdges,VertEdge);
3789 for (j = 1; j <= seqEdges.Length(); j++) {
3790 B.Add(wire,seqEdges.Value(j));
3791 MapFreeEdges.Remove(seqEdges.Value(j));
3793 seqWires.Append(wire);
3794 if (MapFreeEdges.IsEmpty()) break;
3798 //=======================================================================
3799 //function : IsDegeneratedWire
3800 //purpose : internal use
3801 //=======================================================================
3803 static Standard_Boolean IsDegeneratedWire(const TopoDS_Shape& wire)
3805 if (wire.ShapeType() != TopAbs_WIRE) return Standard_False;
3806 // Get maximal vertices tolerance
3807 TopoDS_Vertex V1,V2;
3808 //TopExp::Vertices(TopoDS::Wire(wire),V1,V2);
3809 //Standard_Real tol = Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3810 Standard_Real wireLength = 0.0;
3811 TopLoc_Location loc;
3812 Standard_Real first, last;
3813 Standard_Integer nume = 0;
3814 Standard_Integer isSmall = 0;
3815 for (TopoDS_Iterator aIt(wire,Standard_False); aIt.More(); aIt.Next()) {
3817 TopoDS_Shape edge = aIt.Value();
3818 TopoDS_Vertex Ve1,Ve2;
3819 TopExp::Vertices(TopoDS::Edge(edge),Ve1,Ve2);
3827 else if(Ve1.IsSame(V2))
3831 else if(Ve2.IsSame(V2))
3834 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aIt.Value()),loc,first,last);
3835 if (!c3d.IsNull()) {
3836 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3837 if (!loc.IsIdentity()) {
3838 //c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3839 c3d->Transform(loc.Transformation());
3841 gp_Pnt pfirst = c3d->Value(first);
3842 gp_Pnt plast = c3d->Value(last);
3843 gp_Pnt pmid = c3d->Value((first +last)*0.5);
3844 Standard_Real length =0;
3845 if(pfirst.Distance(plast) > pfirst.Distance(pmid)) {
3846 length = pfirst.Distance(plast);
3849 GeomAdaptor_Curve cAdapt(c3d);
3850 length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3852 Standard_Real tole = BRep_Tool::Tolerance(Ve1)+BRep_Tool::Tolerance(Ve2);
3853 if(length <= tole) isSmall++;
3854 wireLength += length;
3857 if(isSmall == nume) return Standard_True;
3858 Standard_Real tol = BRep_Tool::Tolerance(V1)+BRep_Tool::Tolerance(V2);//Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3859 if (wireLength > tol) return Standard_False;
3860 return Standard_True;
3863 //=======================================================================
3864 //function : DegeneratedSection
3865 //purpose : internal use
3866 // create a new degenerated edge if the section is degenerated
3867 //=======================================================================
3869 static TopoDS_Edge DegeneratedSection(const TopoDS_Shape& section, const TopoDS_Shape& face)
3871 // Return if section is already degenerated
3872 if (BRep_Tool::Degenerated(TopoDS::Edge(section))) return TopoDS::Edge(section);
3874 // Retrieve edge curve
3875 TopLoc_Location loc;
3876 Standard_Real first, last;
3877 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(section), loc, first, last);
3878 if (c3d.IsNull()) { //gka
3880 TopoDS_Edge edge1 = TopoDS::Edge(section);
3881 aB.Degenerated(edge1, Standard_True);
3884 if (!loc.IsIdentity()) {
3885 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3886 c3d->Transform(loc.Transformation());
3889 // Test if the new edge is degenerated
3890 TopoDS_Vertex v1,v2;
3891 TopExp::Vertices(TopoDS::Edge(section),v1,v2);
3892 //Standard_Real tol = Max(BRep_Tool::Tolerance(v1),BRep_Tool::Tolerance(v2));
3893 //tol = Max(tolerance,tol);
3896 p1 = BRep_Tool::Pnt(v1);
3897 p3 = BRep_Tool::Pnt(v2);
3898 c3d->D0(0.5*(first + last),p2);
3900 //Standard_Boolean isDegenerated = Standard_False;
3901 //if (p1.Distance(p3) < tol) {
3902 //GeomAdaptor_Curve cAdapt(c3d);
3903 //Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3904 //isDegenerated = Standard_True; //(length < tol);
3908 //if (!isDegenerated) return edge;
3911 BRep_Builder aBuilder;
3912 edge = TopoDS::Edge(section);
3914 if (v1.IsSame(v2)) {
3915 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3916 aBuilder.Add(anEdge, v1.Oriented(TopAbs_FORWARD));
3917 aBuilder.Add(anEdge, v2.Oriented(TopAbs_REVERSED));
3920 TopoDS_Vertex newVertex;
3921 if (p1.Distance(p3) < BRep_Tool::Tolerance(v1))
3923 else if (p1.Distance(p3) < BRep_Tool::Tolerance(v2))
3926 Standard_Real d1 = BRep_Tool::Tolerance(v1) + p2.Distance(p1);
3927 Standard_Real d2 = BRep_Tool::Tolerance(v2) + p2.Distance(p3);
3928 Standard_Real newTolerance = Max(d1,d2);
3929 aBuilder.MakeVertex(newVertex, p2, newTolerance);
3931 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3932 aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_FORWARD));
3933 aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_REVERSED));
3936 BRep_Tool::Range(TopoDS::Edge(section), first, last);
3937 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3938 aBuilder.Range(TopoDS::Edge(anEdge), first, last);
3939 aBuilder.Degenerated(edge, Standard_True);
3940 Handle(Geom_Curve) aC3dNew;
3941 if (!face.IsNull()) {
3942 Standard_Real af,al;
3943 Handle(Geom2d_Curve) aC2dt = BRep_Tool::CurveOnSurface(TopoDS::Edge(section),TopoDS::Face(face),af,al);
3944 aBuilder.UpdateEdge(edge,aC3dNew,0);
3945 Handle(Geom2d_Curve) aC2dn = BRep_Tool::CurveOnSurface(edge,TopoDS::Face(face),af,al);
3947 aBuilder.UpdateEdge(edge,aC2dt,TopoDS::Face(face),0);
3953 //=======================================================================
3954 //function : EdgeProcessing
3955 //purpose : modifies :
3957 // myHasMultipleEdge
3959 // . if multiple edge
3960 // - length < 100.*myTolerance -> several free edge
3961 // . if no multiple edge
3962 // - make the contigous edges sameparameter
3963 //=======================================================================
3965 void BRepBuilderAPI_Sewing::EdgeProcessing(const Handle(Message_ProgressIndicator)& thePI)
3967 // constructs sectionEdge
3968 TopTools_MapOfShape MapFreeEdges;
3969 TopTools_DataMapOfShapeShape EdgeFace;
3970 Message_ProgressSentry aPS (thePI, "Edge processing", 0, myBoundFaces.Extent(), 1);
3971 for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
3972 const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
3973 const TopTools_ListOfShape& listFaces = myBoundFaces(i);
3974 if (listFaces.Extent() == 1) {
3975 if (myBoundSections.IsBound(bound)) {
3976 TopTools_ListIteratorOfListOfShape liter(myBoundSections(bound));
3977 for (; liter.More(); liter.Next()) {
3978 if (!myMergedEdges.Contains(liter.Value())) { //myReShape->IsRecorded(liter.Value())) {
3979 TopoDS_Shape edge = myReShape->Apply(liter.Value());
3980 if (!MapFreeEdges.Contains(edge)) {
3981 TopoDS_Shape face = listFaces.First();
3982 EdgeFace.Bind(edge,face);
3983 MapFreeEdges.Add(edge);
3989 if (!myMergedEdges.Contains(bound)) {
3990 TopoDS_Shape edge = myReShape->Apply(bound);
3991 if (!MapFreeEdges.Contains(edge)) {
3992 TopoDS_Shape face = listFaces.First();
3993 EdgeFace.Bind(edge,face);
3994 MapFreeEdges.Add(edge);
4001 if (!MapFreeEdges.IsEmpty()) {
4002 TopTools_SequenceOfShape seqWires;
4003 GetFreeWires(MapFreeEdges,seqWires);
4004 for (Standard_Integer j = 1; j <= seqWires.Length(); j++) {
4005 TopoDS_Wire wire = TopoDS::Wire(seqWires.Value(j));
4006 if (!IsDegeneratedWire(wire)) continue;
4007 for (TopoDS_Iterator Ie(wire,Standard_False); Ie.More(); Ie.Next()) {
4008 TopoDS_Shape aTmpShape = myReShape->Apply(Ie.Value()); //for porting
4009 TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
4011 if (EdgeFace.IsBound(edge))
4012 face = EdgeFace.Find(edge);
4013 TopoDS_Shape degedge = DegeneratedSection(edge,face);
4014 if (degedge.IsNull()) continue;
4015 if (!degedge.IsSame(edge))
4016 ReplaceEdge(edge,degedge,myReShape);
4017 if (BRep_Tool::Degenerated(TopoDS::Edge(degedge)))
4018 myDegenerated.Add(degedge);
4022 myMergedEdges.Clear();
4025 //=======================================================================
4026 //function : CreateSewedShape
4028 //=======================================================================
4030 void BRepBuilderAPI_Sewing::CreateSewedShape()
4032 // ---------------------
4033 // create the new shapes
4034 // ---------------------
4035 BRepTools_Quilt aQuilt;
4036 Standard_Boolean isLocal = !myShape.IsNull();
4039 TopoDS_Shape ns = myReShape->Apply(myShape);
4043 for (i = 1; i <= myOldShapes.Extent(); i++) {
4044 TopoDS_Shape sh = myOldShapes(i);
4046 sh = myReShape->Apply(sh);
4047 myOldShapes(i) = sh;
4048 if (!isLocal) aQuilt.Add(sh);
4051 TopoDS_Shape aNewShape = aQuilt.Shells();
4052 Standard_Integer numsh = 0;
4054 TopTools_IndexedMapOfShape OldShells;
4057 TopoDS_Compound aComp;
4058 aB.MakeCompound(aComp);
4059 for (TopoDS_Iterator aExpSh(aNewShape,Standard_False); aExpSh.More(); aExpSh.Next()) {
4060 TopoDS_Shape sh = aExpSh.Value();
4061 Standard_Boolean hasEdges = Standard_False;
4062 if (sh.ShapeType() == TopAbs_SHELL) {
4064 hasEdges = !OldShells.Contains(sh);
4067 Standard_Integer numf = 0;
4068 for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
4069 face = aExpF.Current();
4072 if (numf == 1) aB.Add(aComp,face);
4073 else if (numf > 1) aB.Add(aComp,sh);
4077 else if (sh.ShapeType() == TopAbs_FACE) {
4078 if (myNonmanifold) {
4083 hasEdges = Standard_True;
4085 else { aB.Add(aComp,sh); numsh++; }
4087 else { aB.Add(aComp,sh); numsh++; }
4088 if (hasEdges) OldShells.Add(sh);
4090 // Process collected shells
4091 if (myNonmanifold) {
4092 Standard_Integer nbOldShells = OldShells.Extent();
4093 if (nbOldShells == 1) {
4094 // Single shell - check for single face
4095 TopoDS_Shape sh = OldShells.FindKey(1);
4097 Standard_Integer numf = 0;
4098 for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
4099 face = aExpF.Current();
4102 if (numf == 1) aB.Add(aComp,face);
4103 else if (numf > 1) aB.Add(aComp,sh);
4106 else if (nbOldShells) {
4107 // Several shells should be merged
4108 TColStd_MapOfInteger IndexMerged;
4109 while (IndexMerged.Extent() < nbOldShells) {
4110 TopoDS_Shell NewShell;
4111 TopTools_MapOfShape NewEdges;
4112 for (i = 1; i <= nbOldShells; i++) {
4113 if (IndexMerged.Contains(i)) continue;
4114 TopoDS_Shell shell = TopoDS::Shell(OldShells.FindKey(i));
4115 if (NewShell.IsNull()) {
4117 aB.MakeShell(NewShell);
4118 TopoDS_Iterator aItSS(shell) ;
4119 for( ; aItSS.More(); aItSS.Next())
4120 aB.Add(NewShell,aItSS.Value())
4122 // Fill map of edges
4123 for (TopExp_Explorer eexp(shell,TopAbs_EDGE); eexp.More(); eexp.Next()) {
4124 TopoDS_Shape edge = eexp.Current();
4130 Standard_Boolean hasSharedEdge = Standard_False;
4131 TopExp_Explorer eexp(shell,TopAbs_EDGE);
4132 for (; eexp.More() && !hasSharedEdge; eexp.Next())
4133 hasSharedEdge = NewEdges.Contains(eexp.Current());
4134 if (hasSharedEdge) {
4135 // Add edges to the map
4136 for (TopExp_Explorer eexp1(shell,TopAbs_EDGE); eexp1.More(); eexp1.Next()) {
4137 TopoDS_Shape edge = eexp1.Current();
4140 // Add faces to the shell
4141 for (TopExp_Explorer fexp(shell,TopAbs_FACE); fexp.More(); fexp.Next()) {
4142 TopoDS_Shape face = fexp.Current();
4143 aB.Add(NewShell,face);
4149 // Process new shell
4151 Standard_Integer numf = 0;
4152 TopExp_Explorer aExpF(NewShell,TopAbs_FACE);
4153 for (; aExpF.More() && (numf < 2); aExpF.Next()) {
4154 face = aExpF.Current();
4157 if (numf == 1) aB.Add(aComp,face);
4158 else if (numf > 1) aB.Add(aComp,NewShell);
4164 // Extract single component
4165 TopoDS_Iterator aIt(aComp,Standard_False);
4166 mySewedShape = aIt.Value();
4169 mySewedShape = aComp;
4172 //=======================================================================
4173 //function : CreateOutputInformations
4174 //purpose : constructs :
4178 // myNbContigousEdges
4179 // myNbMultipleEdges
4181 //=======================================================================
4183 void BRepBuilderAPI_Sewing::CreateOutputInformations()
4185 // Construct edgeSections
4187 //TopTools_DataMapOfShapeListOfShape edgeSections;
4188 TopTools_IndexedDataMapOfShapeListOfShape edgeSections; //use index map for regulating free edges
4189 for (i = 1; i <= myBoundFaces.Extent(); i++) {
4190 const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
4191 TopTools_ListOfShape lsect;
4192 if (myBoundSections.IsBound(bound)) lsect = myBoundSections(bound);
4193 TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
4194 for (; aExp.More(); aExp.Next()) {
4195 TopoDS_Shape sec = bound, edge = aExp.Current();
4196 TopTools_ListIteratorOfListOfShape aI(lsect);
4197 for (; aI.More(); aI.Next()) {
4198 const TopoDS_Shape& section = aI.Value();
4199 if (edge.IsSame(myReShape->Apply(section))) { sec = section; break; }
4201 if (edgeSections.Contains(edge))
4202 edgeSections.ChangeFromKey(edge).Append(sec);
4204 TopTools_ListOfShape listSec;
4205 listSec.Append(sec);
4206 edgeSections.Add(edge,listSec);
4211 // Fill maps of Free, Contigous and Multiple edges
4212 //TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter2(edgeSections);
4213 for (i = 1; i <= edgeSections.Extent(); i++) {
4214 const TopoDS_Shape& edge = edgeSections.FindKey(i);
4215 const TopTools_ListOfShape& listSection = edgeSections(i);
4216 if (listSection.Extent() == 1) {
4217 if (BRep_Tool::Degenerated(TopoDS::Edge(edge)))
4218 myDegenerated.Add(edge);
4220 myFreeEdges.Add(edge);
4222 else if (listSection.Extent() == 2) {
4223 myContigousEdges.Add(edge,listSection);
4226 myMultipleEdges.Add(edge);
4230 // constructs myContigSectBound
4231 TopTools_DataMapOfShapeListOfShape aEdgeMap; //gka
4232 for (i = 1; i <= myBoundFaces.Extent(); i++) {
4233 TopoDS_Shape bound = myBoundFaces.FindKey(i);
4234 if (myBoundSections.IsBound(bound)) {
4235 TopTools_ListIteratorOfListOfShape iter(myBoundSections(bound));
4236 for (; iter.More(); iter.Next()) {
4237 TopoDS_Shape section = iter.Value();
4238 if(!myMergedEdges.Contains(section)) continue;
4239 //if (!myReShape->IsRecorded(section)) continue; // section is free
4240 TopoDS_Shape nedge = myReShape->Apply(section);
4241 if (nedge.IsNull()) continue; //szv debug
4242 if (!bound.IsSame(section))
4243 if (myContigousEdges.Contains(nedge))
4244 myContigSecBound.Bind(section, bound);
4250 //=======================================================================
4251 //function : ProjectPointsOnCurve
4252 //purpose : internal use
4253 //=======================================================================
4255 void BRepBuilderAPI_Sewing::ProjectPointsOnCurve(const TColgp_Array1OfPnt& arrPnt,
4256 const Handle(Geom_Curve)& c3d,
4257 const Standard_Real first,
4258 const Standard_Real last,
4259 TColStd_Array1OfReal& arrDist,
4260 TColStd_Array1OfReal& arrPara,
4261 TColgp_Array1OfPnt& arrProj,
4262 const Standard_Boolean isConsiderEnds) const
4266 GeomAdaptor_Curve GAC(c3d);
4267 Extrema_ExtPC locProj;
4268 locProj.Initialize(GAC, first, last);
4269 gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
4270 Standard_Integer find = 1;//(isConsiderEnds ? 1 : 2);
4271 Standard_Integer lind = arrPnt.Length();//(isConsiderEnds ? arrPnt.Length() : arrPnt.Length() -1);
4273 for (Standard_Integer i1 = find; i1 <= lind ; i1++) {
4274 gp_Pnt pt = arrPnt(i1);
4275 Standard_Real worktol = myTolerance;
4276 Standard_Real distF2 = pfirst.SquareDistance(pt);
4277 Standard_Real distL2 = plast.SquareDistance(pt);
4278 Standard_Boolean isProjected = Standard_False;
4281 // Project current point on curve
4282 locProj.Perform(pt);
4283 if (locProj.IsDone() && locProj.NbExt() > 0) {
4284 Standard_Real dist2Min = (isConsiderEnds || i1 == find || i1 == lind ? Min(distF2,distL2) : Precision::Infinite());
4285 Standard_Integer ind, indMin = 0;
4286 for (ind = 1; ind <= locProj.NbExt(); ind++) {
4287 Standard_Real dProj2 = locProj.SquareDistance(ind);
4288 if (dProj2 < dist2Min) { indMin = ind; dist2Min = dProj2; }
4291 isProjected = Standard_True;
4292 Extrema_POnCurv pOnC = locProj.Point(indMin);
4293 Standard_Real paramProj = pOnC.Parameter();
4294 gp_Pnt ptProj = GAC.Value(paramProj);
4295 Standard_Real distProj2 = ptProj.SquareDistance(pt);
4296 if (!locProj.IsMin(indMin)) {
4297 if (Min(distF2,distL2) < dist2Min) {
4298 if (distF2 < distL2) {
4310 if (distProj2 < worktol * worktol || !isConsiderEnds) {
4311 arrDist(i1) = sqrt (distProj2);
4312 arrPara(i1) = paramProj;
4313 arrProj(i1) = ptProj;
4318 catch (Standard_Failure) {
4319 worktol = MinTolerance();
4321 cout << "Exception in BRepBuilderAPI_Sewing::ProjectPointsOnCurve: ";
4322 Standard_Failure::Caught()->Print(cout); cout << endl;
4325 if (!isProjected && isConsiderEnds) {
4326 if (Min(distF2,distL2) < worktol * worktol) {
4327 if (distF2 < distL2) {
4328 arrDist(i1) = sqrt (distF2);
4329 arrPara(i1) = first;
4330 arrProj(i1) = pfirst;
4333 arrDist(i1) = sqrt (distL2);
4335 arrProj(i1) = plast;
4342 //=======================================================================
4343 //function : CreateCuttingNodes
4344 //purpose : internal use
4345 //=======================================================================
4347 void BRepBuilderAPI_Sewing::CreateCuttingNodes(const TopTools_IndexedMapOfShape& MapVert,
4348 const TopoDS_Shape& bound,
4349 const TopoDS_Shape& vfirst,
4350 const TopoDS_Shape& vlast,
4351 const TColStd_Array1OfReal& arrDist,
4352 const TColStd_Array1OfReal& arrPara,
4353 const TColgp_Array1OfPnt& arrPnt,
4354 TopTools_SequenceOfShape& seqVert,
4355 TColStd_SequenceOfReal& seqPara)
4357 Standard_Integer i, j, nbProj = MapVert.Extent();
4359 // Reorder projections by distance
4360 TColStd_SequenceOfInteger seqOrderedIndex;
4361 { //szv: Use brackets to destroy local variables
4362 TColStd_SequenceOfReal seqOrderedDistance;
4363 for (i = 1; i <= nbProj; i++) {
4364 Standard_Real distProj = arrDist(i);
4365 if (distProj < 0.0) continue; // Skip vertex if not projected
4366 Standard_Boolean isInserted = Standard_False;
4367 for (j = 1; j <= seqOrderedIndex.Length() && !isInserted; j++) {
4368 isInserted = (distProj < seqOrderedDistance(j));
4370 seqOrderedIndex.InsertBefore(j,i);
4371 seqOrderedDistance.InsertBefore(j,distProj);
4375 seqOrderedIndex.Append(i);
4376 seqOrderedDistance.Append(distProj);
4380 nbProj = seqOrderedIndex.Length();
4381 if (!nbProj) return;
4383 BRep_Builder aBuilder;
4385 // Insert two initial vertices (to be removed later)
4386 TColStd_SequenceOfReal seqDist;
4387 TColgp_SequenceOfPnt seqPnt;
4388 { //szv: Use brackets to destroy local variables
4389 // Retrieve bound curve
4390 TopLoc_Location loc;
4391 Standard_Real first,last;
4392 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(bound), loc, first, last);
4393 if (!loc.IsIdentity()) {
4394 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
4395 c3d->Transform(loc.Transformation());
4397 GeomAdaptor_Curve GAC(c3d);
4398 seqVert.Prepend(vfirst); seqVert.Append(vlast);
4399 seqPara.Prepend(first); seqPara.Append(last);
4400 seqDist.Prepend(-1.0); seqDist.Append(-1.0);
4401 seqPnt.Prepend(GAC.Value(first)); seqPnt.Append(GAC.Value(last));
4404 TopTools_DataMapOfShapeShape NodeCuttingVertex;
4405 for (i = 1; i <= nbProj; i++) {
4407 const Standard_Integer index = seqOrderedIndex(i);
4408 Standard_Real disProj = arrDist(index);
4409 gp_Pnt pntProj = arrPnt(index);
4411 // Skip node if already bound to cutting vertex
4412 TopoDS_Shape node = myVertexNode.FindFromKey(MapVert(index));
4413 if (NodeCuttingVertex.IsBound(node)) continue;
4415 // Find the closest vertex
4416 Standard_Integer indexMin = 1;
4417 Standard_Real dist, distMin = pntProj.Distance(seqPnt(1));
4418 for (j = 2; j <= seqPnt.Length(); j++) {
4419 dist = pntProj.Distance(seqPnt(j));
4420 if (dist < distMin) { distMin = dist; indexMin = j; }
4423 // Check if current point is close to one of the existent
4424 if (distMin <= Max(disProj*0.1,MinTolerance())) {
4425 // Check distance if close
4426 Standard_Real jdist = seqDist.Value(indexMin);
4428 // Bind new cutting node (end vertex only)
4429 seqDist.SetValue(indexMin,disProj);
4430 TopoDS_Shape cvertex = seqVert.Value(indexMin);
4431 NodeCuttingVertex.Bind(node,cvertex);
4434 // Bind secondary cutting nodes
4435 NodeCuttingVertex.Bind(node,TopoDS_Vertex());
4439 // Build new cutting vertex
4440 TopoDS_Vertex cvertex;
4441 aBuilder.MakeVertex(cvertex, pntProj, Precision::Confusion());
4442 // Bind new cutting vertex
4443 NodeCuttingVertex.Bind(node,cvertex);
4444 // Insert cutting vertex in the sequences
4445 Standard_Real parProj = arrPara(index);
4446 for (j = 2; j <= seqPara.Length(); j++) {
4447 if (parProj <= seqPara.Value(j)) {
4448 seqVert.InsertBefore(j,cvertex);
4449 seqPara.InsertBefore(j,parProj);
4450 seqDist.InsertBefore(j,disProj);
4451 seqPnt.InsertBefore (j,pntProj);
4458 // filling map for cutting nodes
4459 TopTools_DataMapIteratorOfDataMapOfShapeShape mit(NodeCuttingVertex);
4460 for (; mit.More(); mit.Next()) {
4461 TopoDS_Shape cnode = mit.Value();
4462 // Skip secondary nodes
4463 if (cnode.IsNull()) continue;
4464 // Obtain vertex node
4465 TopoDS_Shape node = mit.Key();
4466 if (myVertexNode.Contains(cnode)) {
4467 // This is an end vertex
4468 cnode = myVertexNode.FindFromKey(cnode);
4471 // Create link: cutting vertex -> node
4472 TopTools_ListOfShape ls;
4474 myCuttingNode.Bind(cnode,ls);
4476 // Create link: node -> cutting vertex
4477 if (myCuttingNode.IsBound(node)) {
4478 myCuttingNode.ChangeFind(node).Append(cnode);
4481 TopTools_ListOfShape ls;
4483 myCuttingNode.Bind(node,ls);
4487 // Remove two initial vertices
4488 seqVert.Remove(1); seqVert.Remove(seqVert.Length());
4489 seqPara.Remove(1); seqPara.Remove(seqPara.Length());
4492 //=======================================================================
4493 //function : CreateSections
4494 //purpose : internal use
4495 //=======================================================================
4497 void BRepBuilderAPI_Sewing::CreateSections(const TopoDS_Shape& section,
4498 const TopTools_SequenceOfShape& seqNode,
4499 const TColStd_SequenceOfReal& seqPara,
4500 TopTools_ListOfShape& listEdge)
4502 const TopoDS_Edge& sec = TopoDS::Edge(section);
4503 // TopAbs_Orientation aInitOr = sec.Orientation();
4506 //To keep NM vertices on edge
4507 TopTools_SequenceOfShape aSeqNMVert;
4508 TColStd_SequenceOfReal aSeqNMPars;
4509 findNMVertices(sec,aSeqNMVert,aSeqNMPars);
4511 BRep_Builder aBuilder;
4513 Standard_Real first, last;
4514 BRep_Tool::Range(sec, first, last);
4516 // Create cutting sections
4517 Standard_Real par1, par2;
4518 TopoDS_Shape V1, V2;
4519 Standard_Integer i, len = seqPara.Length() + 1;
4520 for (i = 1; i <= len; i++) {
4522 TopoDS_Edge edge = sec;
4528 V1 = TopExp::FirstVertex(sec);
4531 else if (i == len) {
4532 par1 = seqPara(i-1);
4535 V2 = TopExp::LastVertex(sec);
4538 par1 = seqPara(i-1);
4544 TopoDS_Shape aTmpShape = edge.Oriented(TopAbs_FORWARD);
4545 TopoDS_Edge aTmpEdge = TopoDS::Edge (aTmpShape); // for porting
4546 aTmpShape = V1.Oriented(TopAbs_FORWARD);
4547 aBuilder.Add(aTmpEdge, aTmpShape);
4548 aTmpShape = V2.Oriented(TopAbs_REVERSED);
4549 aBuilder.Add(aTmpEdge, aTmpShape);
4550 aBuilder.Range(aTmpEdge, par1, par2);
4551 // if(aInitOr == TopAbs_REVERSED)
4552 // listEdge.Prepend(edge);
4555 Standard_Integer k =1;
4556 for( ; k <= aSeqNMPars.Length() ; k++) {
4557 Standard_Real apar = aSeqNMPars.Value(k);
4558 if(apar >= par1 && apar <= par2) {
4559 aBuilder.Add(aTmpEdge,aSeqNMVert.Value(k));
4560 aSeqNMVert.Remove(k);
4561 aSeqNMPars.Remove(k);
4565 listEdge.Append(edge);
4568 const TopTools_ListOfShape& listFaces = myBoundFaces.FindFromKey(sec);
4569 if (!listFaces.Extent()) return;
4571 Standard_Real tolEdge = BRep_Tool::Tolerance(sec);
4573 // Add cutting pcurves
4574 TopTools_ListIteratorOfListOfShape itf(listFaces);
4575 for (; itf.More(); itf.Next()) {
4577 const TopoDS_Face& fac = TopoDS::Face(itf.Value());
4579 // Retrieve curve on surface
4580 Standard_Real first2d=0., last2d=0.,first2d1=0,last2d1=0.;
4581 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(sec, fac, first2d, last2d);
4582 if (c2d.IsNull()) continue;
4583 Handle(Geom2d_Curve) c2d1;
4584 Standard_Boolean isSeam = BRep_Tool::IsClosed(sec,fac);
4586 //gka - Convert to BSpline was commented because
4587 //it is not necessary to create BSpline instead of Lines or cIrcles.
4588 //Besides after conversion circles to BSpline
4589 //it is necessary to recompute parameters of cutting because paramerization of created
4590 //BSpline curve differs from parametrization of circle.
4592 // Convert pcurve to BSpline
4593 /*Handle(Geom2d_BSplineCurve) c2dBSP,c2dBSP1;
4594 if (c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
4595 c2dBSP = Handle(Geom2d_BSplineCurve)::DownCast(c2d);
4598 if (first > (c2d->FirstParameter() + Precision::PConfusion()) ||
4599 last < (c2d->LastParameter() - Precision::PConfusion())) {
4600 Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d, first, last);
4601 c2dBSP = Geom2dConvert::CurveToBSplineCurve(TC);
4603 else c2dBSP = Geom2dConvert::CurveToBSplineCurve(c2d);
4605 if (c2dBSP.IsNull()) continue;*/
4606 //gka fix for bug OCC12203 21.04.06 addition second curve for seam edges
4610 TopoDS_Edge secRev = TopoDS::Edge(sec.Reversed());
4612 c2d1 = BRep_Tool::CurveOnSurface(secRev, fac, first2d1, last2d1);
4613 if (c2d1.IsNull()) continue;
4615 /*if (c2d1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
4616 c2dBSP1 = Handle(Geom2d_BSplineCurve)::DownCast(c2d1);
4619 if (first > (c2d1->FirstParameter() + Precision::PConfusion()) ||
4620 last < (c2d1->LastParameter() - Precision::PConfusion())) {
4621 Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d1, first, last);
4622 //c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(TC);
4624 //else c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(c2d);
4629 /*first2d = c2dBSP->FirstParameter();
4630 last2d = c2dBSP->LastParameter();
4632 if(!c2dBSP1.IsNull()) {
4633 first2d1 = c2dBSP1->FirstParameter();
4634 last2d1 = c2dBSP1->LastParameter();
4637 // Update cutting sections
4638 Handle(Geom2d_Curve) c2dNew,c2d1New;
4639 TopTools_ListIteratorOfListOfShape ite(listEdge);
4640 for (; ite.More(); ite.Next()) {
4642 // Retrieve cutting section
4643 const TopoDS_Edge& edge = TopoDS::Edge(ite.Value());
4644 BRep_Tool::Range(edge, par1, par2);
4646 // Cut BSpline pcurve
4648 c2dNew = Handle(Geom2d_Curve)::DownCast(c2d->Copy());
4649 //c2dNew = Handle(Geom2d_Curve)::DownCast(c2dBSP->Copy());
4650 //Handle(Geom2d_BSplineCurve)::DownCast(c2dNew)->Segment(Max(first2d,par1),Min(par2,last2d));
4651 if(!c2d1.IsNull()) { //if(!c2dBSP1.IsNull()) {
4652 c2d1New = Handle(Geom2d_Curve)::DownCast(c2d1->Copy());
4653 //c2d1New = Handle(Geom2d_Curve)::DownCast(c2dBSP1->Copy());
4654 //Handle(Geom2d_BSplineCurve)::DownCast(c2d1New)->Segment(Max(first2d1,par1),Min(par2,last2d1));
4657 /*catch (Standard_Failure) {
4659 cout << "Exception in CreateSections: segment [" << par1 << "," << par2 << "]: ";
4660 Standard_Failure::Caught()->Print(cout); cout << endl;
4662 Handle(Geom2d_TrimmedCurve) c2dT = new Geom2d_TrimmedCurve(c2dNew,Max(first2d,par1),Min(par2,last2d));
4667 if(!isSeam && c2d1New.IsNull())
4668 aBuilder.UpdateEdge(edge, c2dNew, fac, tolEdge);
4670 TopAbs_Orientation Ori = edge.Orientation();
4671 if(fac.Orientation() == TopAbs_REVERSED)
4672 Ori = TopAbs::Reverse(Ori);
4674 if(Ori == TopAbs_FORWARD)
4675 aBuilder.UpdateEdge(edge, c2dNew,c2d1New ,fac, tolEdge);
4677 aBuilder.UpdateEdge(edge, c2d1New,c2dNew ,fac, tolEdge);
4683 //=======================================================================
4684 //function : SameParameterShape
4686 //=======================================================================
4688 void BRepBuilderAPI_Sewing::SameParameterShape()
4690 if (!mySameParameterMode) return;
4691 TopExp_Explorer exp(mySewedShape, TopAbs_EDGE);
4692 // Le flag sameparameter est a false pour chaque edge cousue
4693 for (; exp.More(); exp.Next()) {
4694 const TopoDS_Edge& sec = TopoDS::Edge(exp.Current());
4697 BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec));
4699 catch (Standard_Failure) {
4701 cout << "Fail: BRepBuilderAPI_Sewing::SameParameterShape exception in BRepLib::SameParameter" << endl;
4708 //=======================================================================
4709 //function : Inspect
4710 //purpose : Used for selection and storage of coinciding points
4711 //=======================================================================
4713 NCollection_CellFilter_Action BRepBuilderAPI_VertexInspector::Inspect (const Standard_Integer theTarget)
4715 /*gp_Pnt aPnt = gp_Pnt (myPoints.Value (theTarget - 1));
4716 if (aPnt.SquareDistance (gp_Pnt (myCurrent)) <= myTol)
4717 myResInd.Append (theTarget);*/
4719 const gp_XYZ& aPnt = myPoints.Value (theTarget - 1);
4720 Standard_Real aDx, aDy, aDz;
4721 aDx = myCurrent.X() - aPnt.X();
4722 aDy = myCurrent.Y() - aPnt.Y();
4723 aDz = myCurrent.Z() - aPnt.Z();
4725 if ((aDx*aDx <= myTol) && (aDy*aDy <= myTol) && (aDz*aDz <= myTol))
4726 myResInd.Append (theTarget);
4727 return CellFilter_Keep;