1 // Created on: 1995-03-24
2 // Created by: Jing Cheng MEI
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // dcl CCI60011 : Correction of degeneratedSection
18 // Improvement of SameParameter Edge to treat case of failure in BRepLib::SameParameter
19 // dcl Thu Aug 20 09:24:49 1998
20 // Suppression of little faces.
21 // dcl Fri Aug 7 15:27:46 1998
22 // Refection of function SameParameter Edge.
23 // Merge on the edge which has the less of poles.
24 // Suppression of the Connected Edge function.
25 // dcl Tue Jun 9 14:21:53 1998
26 // Do not merge edge if they belong the same face
27 // Tolerance management in VerticesAssembling
28 // Tolerance management in Cutting
29 // dcl Thu May 14 15:51:46 1998
30 // optimization of cutting
31 // dcl Thu May 7 15:51:46 1998
32 // Add of cutting option
33 // Add of SameParameter call
37 //-- dpf December 10 1997 Processing of pcurve collections
39 //rln 02.02.99 BUC60449 Making compilable on NT in DEB mode
40 //rln 02.02.99 BUC60449 Protection against exception on NT
45 #include <Bnd_Box.hxx>
46 #include <Bnd_Box2d.hxx>
47 #include <Bnd_HArray1OfBox.hxx>
48 #include <BndLib_Add2dCurve.hxx>
49 #include <BndLib_Add3dCurve.hxx>
50 #include <BRep_Builder.hxx>
51 #include <BRep_ListOfPointRepresentation.hxx>
52 #include <BRep_PointOnCurve.hxx>
53 #include <BRep_Tool.hxx>
54 #include <BRep_TVertex.hxx>
55 #include <BRepBuilderAPI_BndBoxTreeSelector.hxx>
56 #include <BRepBuilderAPI_CellFilter.hxx>
57 #include <BRepBuilderAPI_Sewing.hxx>
58 #include <BRepBuilderAPI_VertexInspector.hxx>
59 #include <BRepLib.hxx>
60 #include <BRepTools.hxx>
61 #include <BRepTools_Quilt.hxx>
62 #include <BRepTools_ReShape.hxx>
63 #include <BSplCLib.hxx>
64 #include <Extrema_ExtPC.hxx>
65 #include <GCPnts_AbscissaPoint.hxx>
66 #include <GCPnts_UniformAbscissa.hxx>
67 #include <GCPnts_UniformDeflection.hxx>
68 #include <Geom2d_BezierCurve.hxx>
69 #include <Geom2d_BSplineCurve.hxx>
70 #include <Geom2d_Curve.hxx>
71 #include <Geom2d_Line.hxx>
72 #include <Geom2d_TrimmedCurve.hxx>
73 #include <Geom2dAdaptor_Curve.hxx>
74 #include <Geom2dConvert.hxx>
75 #include <Geom_BezierCurve.hxx>
76 #include <Geom_BSplineCurve.hxx>
77 #include <Geom_Curve.hxx>
78 #include <Geom_Line.hxx>
79 #include <Geom_OffsetSurface.hxx>
80 #include <Geom_RectangularTrimmedSurface.hxx>
81 #include <Geom_Surface.hxx>
82 #include <GeomAdaptor_Curve.hxx>
83 #include <GeomAdaptor_Surface.hxx>
84 #include <GeomLib.hxx>
87 #include <Message_ProgressIndicator.hxx>
88 #include <Message_ProgressSentry.hxx>
89 #include <NCollection_UBTreeFiller.hxx>
90 #include <Precision.hxx>
91 #include <Standard_ErrorHandler.hxx>
92 #include <Standard_Failure.hxx>
93 #include <Standard_NoSuchObject.hxx>
94 #include <Standard_OutOfRange.hxx>
95 #include <Standard_Type.hxx>
96 #include <TColgp_Array1OfVec.hxx>
97 #include <TColgp_SequenceOfPnt.hxx>
98 #include <TColStd_Array1OfInteger.hxx>
99 #include <TColStd_Array1OfReal.hxx>
100 #include <TColStd_Array2OfReal.hxx>
101 #include <TColStd_DataMapIteratorOfDataMapOfIntegerListOfInteger.hxx>
102 #include <TColStd_DataMapOfIntegerListOfInteger.hxx>
103 #include <TColStd_IndexedMapOfInteger.hxx>
104 #include <TColStd_ListIteratorOfListOfInteger.hxx>
105 #include <TColStd_ListOfInteger.hxx>
106 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
107 #include <TColStd_MapOfInteger.hxx>
108 #include <TColStd_SequenceOfReal.hxx>
109 #include <TopAbs.hxx>
110 #include <TopExp.hxx>
111 #include <TopExp_Explorer.hxx>
112 #include <TopLoc_Location.hxx>
113 #include <TopoDS.hxx>
114 #include <TopoDS_Compound.hxx>
115 #include <TopoDS_Edge.hxx>
116 #include <TopoDS_Face.hxx>
117 #include <TopoDS_Iterator.hxx>
118 #include <TopoDS_Shape.hxx>
119 #include <TopoDS_Shell.hxx>
120 #include <TopoDS_Vertex.hxx>
121 #include <TopoDS_Wire.hxx>
122 #include <TopTools_Array1OfShape.hxx>
123 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
124 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
125 #include <TopTools_DataMapOfShapeInteger.hxx>
126 #include <TopTools_DataMapOfShapeListOfShape.hxx>
127 #include <TopTools_ListIteratorOfListOfShape.hxx>
128 #include <TopTools_ListOfShape.hxx>
129 #include <TopTools_MapIteratorOfMapOfShape.hxx>
130 #include <TopTools_MapOfShape.hxx>
131 #include <TopTools_SequenceOfShape.hxx>
133 IMPLEMENT_STANDARD_RTTIEXT(BRepBuilderAPI_Sewing,MMgt_TShared)
135 //#include <LocalAnalysis_SurfaceContinuity.hxx>
136 //=======================================================================
137 //function : SameRange
139 //=======================================================================
140 Handle(Geom2d_Curve) BRepBuilderAPI_Sewing::SameRange(const Handle(Geom2d_Curve)& CurvePtr,
141 const Standard_Real FirstOnCurve,
142 const Standard_Real LastOnCurve,
143 const Standard_Real RequestedFirst,
144 const Standard_Real RequestedLast) const
146 Handle(Geom2d_Curve) NewCurvePtr;
149 GeomLib::SameRange(Precision::PConfusion(),CurvePtr,FirstOnCurve,LastOnCurve,
150 RequestedFirst,RequestedLast,NewCurvePtr);
152 catch (Standard_Failure const& anException) {
154 cout << "Exception in BRepBuilderAPI_Sewing::SameRange: ";
155 anException.Print(cout); cout << endl;
162 //=======================================================================
163 //function : WhichFace
164 //purpose : Give the face whose edge is the border
165 //=======================================================================
167 TopoDS_Face BRepBuilderAPI_Sewing::WhichFace(const TopoDS_Edge& theEdg, const Standard_Integer index) const
169 TopoDS_Shape bound = theEdg;
170 if (mySectionBound.IsBound(bound)) bound = mySectionBound(bound);
171 if (myBoundFaces.Contains(bound)) {
172 Standard_Integer i = 1;
173 TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bound));
174 for (; itf.More(); itf.Next(), i++)
175 if (i == index) return TopoDS::Face(itf.Value());
177 return TopoDS_Face();
180 //=======================================================================
181 //function : IsClosedShape
183 //=======================================================================
185 static Standard_Boolean IsClosedShape(const TopoDS_Shape& theshape,
186 const TopoDS_Shape& v1, const TopoDS_Shape& v2)
188 Standard_Real TotLength = 0.0;
189 TopExp_Explorer aexp;
190 for (aexp.Init(theshape,TopAbs_EDGE); aexp.More(); aexp.Next()) {
191 TopoDS_Edge aedge = TopoDS::Edge(aexp.Current());
192 if (aedge.IsNull()) continue;
193 TopoDS_Vertex ve1,ve2;
194 TopExp::Vertices(aedge,ve1,ve2);
195 if (!ve1.IsSame(v1) && !ve1.IsSame(v2)) continue;
196 if (BRep_Tool::Degenerated(aedge)) continue;
197 Standard_Real first,last;
198 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aedge), first, last);
200 GeomAdaptor_Curve cAdapt(c3d);
201 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
203 if (ve2.IsSame(v1) || ve2.IsSame(v2)) break;
206 if (TotLength > 0.0) {
207 gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(v1));
208 gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(v2));
209 return (p1.Distance(p2) < TotLength/(1.2 * M_PI));
211 return Standard_False;
214 //=======================================================================
215 //function : IsClosedByIsos
217 //=======================================================================
218 static Standard_Boolean IsClosedByIsos(const Handle(Geom_Surface)& thesurf,
219 const Handle(Geom2d_Curve)& acrv2d,
220 const Standard_Real f2d,
221 const Standard_Real l2d,
222 const Standard_Boolean isUIsos)
224 Standard_Boolean isClosed = Standard_False;
226 gp_Pnt2d psurf1 = (acrv2d->IsPeriodic() ?
227 acrv2d->Value(f2d) : acrv2d->Value(Max(f2d,acrv2d->FirstParameter())));
228 gp_Pnt2d psurf2 = (acrv2d->IsPeriodic() ?
229 acrv2d->Value(l2d) : acrv2d->Value(Min(l2d,acrv2d->LastParameter())));
230 Handle(Geom_Curve) aCrv1;
231 Handle(Geom_Curve) aCrv2;
233 aCrv1 = thesurf->UIso(psurf1.X());
234 aCrv2 = thesurf->UIso(psurf2.X());
237 aCrv1 = thesurf->VIso(psurf1.Y());
238 aCrv2 = thesurf->VIso(psurf2.Y());
240 gp_Pnt p11,p1m,p12,p21,p2m,p22;
241 Standard_Real af1 = aCrv1->FirstParameter();
242 Standard_Real al1 = aCrv1->LastParameter();
243 Standard_Real af2 = aCrv2->FirstParameter();
244 Standard_Real al2 = aCrv2->LastParameter();
246 aCrv1->D0((af1+al1)*0.5,p1m);
249 aCrv2->D0((af2+al2)*0.5,p2m);
251 isClosed = (((p11.XYZ() - p12.XYZ()).Modulus() <
252 (p11.XYZ() - p1m.XYZ()).Modulus() - Precision::Confusion()) &&
253 ((p21.XYZ() - p22.XYZ()).Modulus() <
254 (p21.XYZ() - p2m.XYZ()).Modulus() - Precision::Confusion())) ;
257 //=======================================================================
258 //function : IsUClosedSurface
260 //=======================================================================
262 Standard_Boolean BRepBuilderAPI_Sewing::IsUClosedSurface(const Handle(Geom_Surface)& surf,
263 const TopoDS_Shape& theEdge,
264 const TopLoc_Location& theloc) const
266 Handle(Geom_Surface) tmpsurf = surf;
267 if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
268 tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
269 else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
270 tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
272 Standard_Boolean isClosed = tmpsurf->IsUClosed();
274 Standard_Real f2d, l2d;
275 Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
277 isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_False );
282 return IsUClosedSurface(tmpsurf,theEdge,theloc);
283 //return surf->IsUClosed();
286 //=======================================================================
287 //function : IsVClosedSurface
289 //=======================================================================
291 Standard_Boolean BRepBuilderAPI_Sewing::IsVClosedSurface(const Handle(Geom_Surface)& surf,
292 const TopoDS_Shape& theEdge,
293 const TopLoc_Location& theloc) const
295 Handle(Geom_Surface) tmpsurf = surf;
296 if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
297 tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
298 else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
299 tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
301 Standard_Boolean isClosed = tmpsurf->IsVClosed();
303 Standard_Real f2d, l2d;
304 Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
306 isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_True );
310 return IsVClosedSurface(tmpsurf,theEdge,theloc);
311 //return surf->IsVClosed();
314 //=======================================================================
315 //function : SameParameter
316 //purpose : internal use
317 //=======================================================================
319 void BRepBuilderAPI_Sewing::SameParameter(const TopoDS_Edge& edge) const
323 BRepLib::SameParameter(edge);
325 catch (Standard_Failure const& anException) {
327 cout << "Exception in BRepBuilderAPI_Sewing::SameParameter: ";
328 anException.Print(cout); cout << endl;
334 //=======================================================================
335 //function : SameParameterEdge
336 //purpose : internal use
337 // Merge the Sequence Of Section on one edge.
338 // This function keep the curve3d,curve2d,range and parametrization
339 // from the first section, and report and made sameparameter the
340 // pcurves of the other function.
341 // This function works when the are not more than two Pcurves
343 //=======================================================================
345 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Shape& edge,
346 const TopTools_SequenceOfShape& seqEdges,
347 const TColStd_SequenceOfBoolean& seqForward,
348 TopTools_MapOfShape& mapMerged,
349 const Handle(BRepTools_ReShape)& locReShape)
351 // Retrieve reference section
352 TopoDS_Shape aTmpShape = myReShape->Apply(edge); //for porting
353 TopoDS_Edge Edge1 = TopoDS::Edge(aTmpShape);
354 aTmpShape = locReShape->Apply(Edge1);
355 if (locReShape != myReShape) Edge1 = TopoDS::Edge(aTmpShape);
356 Standard_Boolean isDone = Standard_False;
358 // Create data structures for temporary merged edges
359 TopTools_ListOfShape listFaces1;
360 TopTools_MapOfShape MergedFaces;
364 // Fill MergedFaces with faces of Edge1
365 TopoDS_Shape bnd1 = edge;
366 if (mySectionBound.IsBound(bnd1)) bnd1 = mySectionBound(bnd1);
367 if (myBoundFaces.Contains(bnd1)) {
368 TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bnd1));
369 for (; itf.More(); itf.Next())
370 if (MergedFaces.Add(itf.Value()))
371 listFaces1.Append(itf.Value());
376 // Create presentation edge
377 TopoDS_Vertex V1, V2;
378 TopExp::Vertices(Edge1,V1,V2);
379 if (myVertexNode.Contains(V1)) V1 = TopoDS::Vertex(myVertexNode.FindFromKey(V1));
380 if (myVertexNode.Contains(V2)) V2 = TopoDS::Vertex(myVertexNode.FindFromKey(V2));
382 TopoDS_Edge NewEdge = Edge1;
386 BRep_Builder aBuilder;
387 TopoDS_Shape anEdge = NewEdge.Oriented(TopAbs_FORWARD);
388 aBuilder.Add(anEdge,V1.Oriented(TopAbs_FORWARD));
389 aBuilder.Add(anEdge,V2.Oriented(TopAbs_REVERSED));
394 Standard_Boolean isForward = Standard_True;
396 // Merge candidate sections
397 for (Standard_Integer i = 1; i <= seqEdges.Length(); i++) {
399 // Retrieve candidate section
400 TopoDS_Shape oedge2 = seqEdges(i);
404 aTmpShape = myReShape->Apply(oedge2); //for porting
405 TopoDS_Edge Edge2 = TopoDS::Edge(aTmpShape);
406 aTmpShape = locReShape->Apply(Edge2);
407 if (locReShape != myReShape) Edge2 = TopoDS::Edge(aTmpShape);
409 // Calculate relative orientation
410 Standard_Boolean Orientation = seqForward(i);
411 if (!isForward) Orientation = !Orientation;
413 // Retrieve faces information for the second edge
414 TopoDS_Shape bnd2 = oedge2;
415 if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
416 if (!myBoundFaces.Contains(bnd2)) continue; // Skip floating edge
417 const TopTools_ListOfShape& listFaces2 = myBoundFaces.FindFromKey(bnd2);
419 Standard_Integer whichSec = 1; // Indicates on which edge the pCurve has been reported
420 TopoDS_Edge NewEdge = SameParameterEdge(Edge1,Edge2,listFaces1,listFaces2,Orientation,whichSec);
421 if (NewEdge.IsNull()) continue;
423 // Record faces information for the temporary merged edge
424 TopTools_ListIteratorOfListOfShape itf(listFaces2);
425 for (; itf.More(); itf.Next())
426 if (MergedFaces.Add(itf.Value()))
427 listFaces1.Append(itf.Value());
429 // Record merged section orientation
430 if (!Orientation && whichSec != 1)
431 isForward = isForward? Standard_False : Standard_True;
435 // Append actually merged edge
436 mapMerged.Add(oedge2);
437 isDone = Standard_True;
439 if (!myNonmanifold) break;
443 // Change result orientation
444 Edge1.Orientation(isForward? TopAbs_FORWARD : TopAbs_REVERSED);
446 else Edge1.Nullify();
451 //=======================================================================
452 //function : SameParameterEdge
453 //purpose : internal use
454 //=======================================================================
455 static Standard_Boolean findNMVertices(const TopoDS_Edge& theEdge,
456 TopTools_SequenceOfShape& theSeqNMVert,
457 TColStd_SequenceOfReal& theSeqPars)
459 TopoDS_Iterator aItV(theEdge,Standard_False);
460 for( ; aItV.More(); aItV.Next()) {
461 if(aItV.Value().Orientation() == TopAbs_INTERNAL ||
462 aItV.Value().Orientation() == TopAbs_EXTERNAL)
463 theSeqNMVert.Append(aItV.Value());
465 Standard_Integer nbV = theSeqNMVert.Length();
467 return Standard_False;
468 Standard_Real first, last;
469 Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,first, last);
470 GeomAdaptor_Curve GAC(c3d);
471 Extrema_ExtPC locProj;
472 locProj.Initialize(GAC, first, last);
473 gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
476 for (Standard_Integer i = 1; i <= nbV; i++) {
477 TopoDS_Vertex aV = TopoDS::Vertex(theSeqNMVert.Value(i));
478 gp_Pnt pt = BRep_Tool::Pnt(aV);
480 Standard_Real distF2 = pfirst.SquareDistance(pt);
481 Standard_Real distL2 = plast.SquareDistance(pt);
482 Standard_Real apar = (distF2 > distL2 ? last : first);
483 // Project current point on curve
485 if (locProj.IsDone() && locProj.NbExt() > 0) {
486 Standard_Real dist2Min = Min(distF2,distL2);
487 Standard_Integer ind, indMin = 0;
488 for (ind = 1; ind <= locProj.NbExt(); ind++) {
489 Standard_Real dProj2 = locProj.SquareDistance(ind);
490 if (dProj2 < dist2Min) {
491 indMin = ind; dist2Min = dProj2;
495 apar = locProj.Point(indMin).Parameter();
497 theSeqPars.Append(apar);
501 return Standard_True;
504 static void ComputeToleranceVertex(TopoDS_Vertex theV1, TopoDS_Vertex theV2,
505 TopoDS_Vertex& theNewV)
507 Standard_Integer m, n;
508 Standard_Real aR[2], dR, aD, aEps;
513 aEps = RealEpsilon();
516 for (m = 0; m < 2; ++m) {
517 aP[m] = BRep_Tool::Pnt(aV[m]);
518 aR[m] = BRep_Tool::Tolerance(aV[m]);
528 dR = aR[m] - aR[n]; // dR >= 0.
529 gp_Vec aVD(aP[m], aP[n]);
530 aD = aVD.Magnitude();
532 if (aD <= dR || aD < aEps) {
533 aBB.MakeVertex (theNewV, aP[m], aR[m]);
540 aRr = 0.5 * (aR[m] + aR[n] + aD);
541 aXYZr = 0.5 * (aP[m].XYZ() + aP[n].XYZ() - aVD.XYZ() * (dR/aD));
544 aBB.MakeVertex (theNewV, aPr, aRr);
549 static void ComputeToleranceVertex(TopoDS_Vertex theV1, TopoDS_Vertex theV2,
550 TopoDS_Vertex theV3, TopoDS_Vertex& theNewV)
552 Standard_Real aDi, aDmax;
557 gp_XYZ aXYZ(0.,0.,0.);
561 for (Standard_Integer i = 0; i < 3; ++i) {
562 aP[i] = BRep_Tool::Pnt(aV[i]);
563 aR[i] = BRep_Tool::Tolerance(aV[i]);
564 aXYZ = aXYZ + aP[i].XYZ();
568 aCenter.SetXYZ(aXYZ);
571 for ( Standard_Integer i = 0; i < 3; ++i) {
572 aDi = aCenter.Distance(aP[i]);
579 aBB.MakeVertex (theNewV, aCenter, aDmax);
583 TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirst,
584 const TopoDS_Edge& edgeLast,
585 const TopTools_ListOfShape& listFacesFirst,
586 const TopTools_ListOfShape& listFacesLast,
587 const Standard_Boolean secForward,
588 Standard_Integer& whichSec,
589 const Standard_Boolean firstCall)
591 // Do not process floating edges
592 if (!listFacesFirst.Extent() || !listFacesLast.Extent()) return TopoDS_Edge();
595 TopoDS_Edge edge1, edge2;
597 // Take the longest edge as first
599 Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(TopoDS::Edge(edgeFirst), f, l);
600 GeomAdaptor_Curve cAdapt1(c3d1);
601 Standard_Real len1 = GCPnts_AbscissaPoint::Length(cAdapt1, f, l);
602 Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(TopoDS::Edge(edgeLast), f, l);
603 GeomAdaptor_Curve cAdapt2(c3d2);
604 Standard_Real len2 = GCPnts_AbscissaPoint::Length(cAdapt2, f, l);
629 Standard_Real first, last;
630 BRep_Tool::Range(edge1, first, last);
631 BRep_Builder aBuilder;
633 //To keep NM vertices on edge
634 TopTools_SequenceOfShape aSeqNMVert;
635 TColStd_SequenceOfReal aSeqNMPars;
636 findNMVertices(edge1,aSeqNMVert,aSeqNMPars);
637 findNMVertices(edge2,aSeqNMVert,aSeqNMPars);
641 aBuilder.MakeEdge(edge);
642 edge.Orientation( edge1.Orientation());
645 // Retrieve edge curve
646 TopLoc_Location loc3d;
647 Standard_Real first3d, last3d;
648 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge1, loc3d, first3d, last3d);
649 if (!loc3d.IsIdentity()) {
650 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
651 c3d->Transform(loc3d.Transformation());
653 aBuilder.UpdateEdge(edge,c3d,BRep_Tool::Tolerance(edge1));
654 aBuilder.Range(edge, first, last);
655 aBuilder.SameRange(edge, Standard_False); //Standard_True
656 aBuilder.SameParameter(edge, Standard_False);
657 // Create and add new vertices
659 TopoDS_Vertex V1New, V2New;
661 // Retrieve original vertices from edges
662 TopoDS_Vertex V11,V12,V21,V22;
663 TopExp::Vertices(edge1,V11,V12);
664 TopExp::Vertices(edge2,V21,V22);
666 //check that edges merged valid way (for edges having length less than specified
668 // Check if edges are closed
669 Standard_Boolean isClosed1 = V11.IsSame(V12);
670 Standard_Boolean isClosed2 = V21.IsSame(V22);
671 if(!isClosed1 && !isClosed2)
675 if( V11.IsSame(V22) || V12.IsSame(V21) )
676 return TopoDS_Edge();
680 if( V11.IsSame(V21) || V12.IsSame(V22) )
681 return TopoDS_Edge();
685 //szv: do not reshape here!!!
686 //V11 = TopoDS::Vertex(myReShape->Apply(V11));
687 //V12 = TopoDS::Vertex(myReShape->Apply(V12));
688 //V21 = TopoDS::Vertex(myReShape->Apply(V21));
689 //V22 = TopoDS::Vertex(myReShape->Apply(V22));
691 //Standard_Boolean isRev = Standard_False;
692 if (isClosed1 || isClosed2) {
693 // at least one of the edges is closed
694 if (isClosed1 && isClosed2) {
695 // both edges are closed
696 ComputeToleranceVertex(V11, V21, V1New);
698 else if (isClosed1) {
699 // only first edge is closed
700 ComputeToleranceVertex(V22, V21, V11, V1New);
703 // only second edge is closed
704 ComputeToleranceVertex(V11, V12, V21, V1New);
709 // both edges are open
710 Standard_Boolean isOldFirst = ( secForward ? V11.IsSame(V21) : V11.IsSame(V22) );
711 Standard_Boolean isOldLast = ( secForward ? V12.IsSame(V22) : V12.IsSame(V21)) ;
713 //case if vertices already sewed
716 ComputeToleranceVertex(V11, V21, V1New);
720 ComputeToleranceVertex(V12, V22, V2New);
726 ComputeToleranceVertex(V11, V22, V1New);
730 ComputeToleranceVertex(V12, V21, V2New);
739 // Add the vertices in the good sense
740 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
741 TopoDS_Shape aLocalEdge = V1New.Oriented(TopAbs_FORWARD); //(listNode.First()).Oriented(TopAbs_FORWARD);
742 aBuilder.Add(anEdge,aLocalEdge);
743 aLocalEdge = V2New.Oriented(TopAbs_REVERSED); //(listNode.Last()).Oriented(TopAbs_REVERSED);
744 aBuilder.Add(anEdge,aLocalEdge);
746 Standard_Integer k =1;
747 for( ; k <= aSeqNMVert.Length(); k++)
748 aBuilder.Add(anEdge,aSeqNMVert.Value(k));
752 // Retrieve second PCurves
753 TopLoc_Location loc2;
754 Handle(Geom_Surface) surf2;
756 //Handle(Geom2d_Curve) c2d2, c2d21;
757 // Standard_Real firstOld, lastOld;
759 TopTools_ListIteratorOfListOfShape itf2;
760 if (whichSec == 1) itf2.Initialize(listFacesLast);
761 else itf2.Initialize(listFacesFirst);
762 Standard_Boolean isResEdge = Standard_False;
764 for (; itf2.More(); itf2.Next()) {
765 Handle(Geom2d_Curve) c2d2, c2d21;
766 Standard_Real firstOld, lastOld;
767 fac2 = TopoDS::Face(itf2.Value());
769 surf2 = BRep_Tool::Surface(fac2, loc2);
770 Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) &&
771 BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2));
773 if (!myNonmanifold) return TopoDS_Edge();
774 TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting
775 c2d21 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac2, firstOld, lastOld);
777 c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld);
778 if (c2d2.IsNull() && c2d21.IsNull()) continue;
780 if (!c2d21.IsNull()) {
781 c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy());
783 if (c2d21->IsKind(STANDARD_TYPE(Geom2d_Line)))
784 c2d21 = new Geom2d_TrimmedCurve(c2d21, firstOld, lastOld);
785 Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
786 Standard_Real last2d = lastOld; //c2dTmp->LastParameter();
787 firstOld = c2d21->ReversedParameter(last2d);
788 lastOld = c2d21->ReversedParameter(first2d);
791 c2d21 = SameRange(c2d21,firstOld,lastOld,first,last);
794 // Make second PCurve sameRange with the 3d curve
795 c2d2 = Handle(Geom2d_Curve)::DownCast(c2d2->Copy());
798 if (c2d2->IsKind(STANDARD_TYPE(Geom2d_Line)))
799 c2d2 = new Geom2d_TrimmedCurve(c2d2, firstOld, lastOld);
800 Standard_Real first2d = firstOld;
801 Standard_Real last2d = lastOld;
802 firstOld = c2d2->ReversedParameter(last2d);
803 lastOld = c2d2->ReversedParameter(first2d);
807 c2d2 = SameRange(c2d2,firstOld,lastOld,first,last);
808 if (c2d2.IsNull()) continue;
811 Standard_Boolean isSeam = Standard_False;
812 TopAbs_Orientation Ori = TopAbs_FORWARD;
813 //Handle(Geom2d_Curve) c2d1, c2d11;
815 TopTools_ListIteratorOfListOfShape itf1;
816 if (whichSec == 1) itf1.Initialize(listFacesFirst);
817 else itf1.Initialize(listFacesLast);
818 for (; itf1.More() && !isSeam; itf1.Next()) {
819 Handle(Geom2d_Curve) c2d1, c2d11;
820 const TopoDS_Face& fac1 = TopoDS::Face(itf1.Value());
822 TopLoc_Location loc1;
823 Handle(Geom_Surface) surf1 = BRep_Tool::Surface(fac1, loc1);
825 Standard_Real first2d, last2d;
826 Standard_Boolean isSeam1 = ((IsUClosedSurface(surf1,edge1,loc1) || IsVClosedSurface(surf1,edge1,loc1)) &&
827 BRep_Tool::IsClosed(TopoDS::Edge(edge1),fac1));
828 c2d1 = BRep_Tool::CurveOnSurface(edge1, fac1, first2d, last2d);
829 Ori = edge1.Orientation();
830 if (fac1.Orientation() == TopAbs_REVERSED)
831 Ori = TopAbs::Reverse(Ori);
834 if (!myNonmanifold) return TopoDS_Edge();
835 TopoDS_Shape aTmpShape = edge1.Reversed(); //for porting
836 c2d11 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac1, first2d, last2d);
837 //if(fac1.Orientation() == TopAbs_REVERSED) //
838 if(Ori == TopAbs_FORWARD)
839 aBuilder.UpdateEdge(edge,c2d1,c2d11,fac1,0);
841 aBuilder.UpdateEdge(edge,c2d11,c2d1,fac1,0);
843 else aBuilder.UpdateEdge(edge,c2d1,fac1,0);
845 if (c2d1.IsNull() && c2d11.IsNull()) continue;
847 if (surf2 == surf1) {
848 // Merge sections which are on the same face
849 if (!loc2.IsDifferent(loc1)) {
850 Standard_Boolean uclosed = IsUClosedSurface(surf2,edge2,loc2);
851 Standard_Boolean vclosed = IsVClosedSurface(surf2,edge2,loc2);
852 if (uclosed || vclosed) {
853 Standard_Real pf = c2d1->FirstParameter();
854 // Standard_Real pl = c2d1->LastParameter();
855 gp_Pnt2d p1n = c2d1->Value(Max(first,pf));
856 // gp_Pnt2d p2n = c2d1->Value(Min(pl,last));
857 gp_Pnt2d p21n = c2d2->Value(Max(first,c2d2->FirstParameter()));
858 gp_Pnt2d p22n = c2d2->Value(Min(last,c2d2->LastParameter()));
859 Standard_Real aDist = Min(p1n.Distance(p21n), p1n.Distance(p22n));
860 Standard_Real U1, U2, V1, V2;
861 surf2->Bounds(U1, U2, V1, V2);
862 isSeam = ((uclosed && aDist > 0.75*(fabs(U2-U1))) ||
863 (vclosed && aDist > 0.75*(fabs(V2-V1))));
864 if( !isSeam && BRep_Tool::IsClosed(TopoDS::Edge(edge),fac1)) continue;
869 isResEdge = Standard_True;
871 if (Ori == TopAbs_FORWARD)
872 aBuilder.UpdateEdge(edge, c2d1, c2d2, surf2, loc2, Precision::Confusion());
874 aBuilder.UpdateEdge(edge, c2d2, c2d1, surf2, loc2, Precision::Confusion());
877 TopAbs_Orientation InitOri = edge2.Orientation();
878 TopAbs_Orientation SecOri = edge.Orientation();
879 if (fac2.Orientation() == TopAbs_REVERSED) {
881 InitOri = TopAbs::Reverse(InitOri);
882 SecOri = TopAbs::Reverse(SecOri);
885 InitOri = TopAbs::Reverse(InitOri);
887 if (InitOri == TopAbs_FORWARD)
888 aBuilder.UpdateEdge(edge, c2d2,c2d21, surf2, loc2, Precision::Confusion());
890 aBuilder.UpdateEdge(edge, c2d21,c2d2, surf2, loc2, Precision::Confusion());
893 aBuilder.UpdateEdge(edge, c2d2, surf2, loc2, Precision::Confusion());
897 Standard_Real tolReached = Precision::Infinite();
898 Standard_Boolean isSamePar = Standard_False;
905 if( BRep_Tool::SameParameter(edge))
907 isSamePar = Standard_True;
908 tolReached = BRep_Tool::Tolerance(edge);
912 catch(Standard_Failure)
914 isSamePar = Standard_False;
918 if (firstCall && ( !isResEdge || !isSamePar || tolReached > myTolerance)) {
919 Standard_Integer whichSecn = whichSec;
920 // Try to merge on the second section
921 Standard_Boolean second_ok = Standard_False;
922 TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast,
923 secForward,whichSecn,Standard_False);
924 if( !s_edge.IsNull())
926 Standard_Real tolReached_2 = BRep_Tool::Tolerance(s_edge);
927 second_ok = ( BRep_Tool::SameParameter(s_edge) && tolReached_2 < tolReached );
931 whichSec = whichSecn;
932 tolReached = tolReached_2;
936 if (!second_ok && !edge.IsNull()) {
938 GeomAdaptor_Curve c3dAdapt(c3d);
940 // Discretize edge curve
941 Standard_Integer i, j, nbp = 23;
942 Standard_Real deltaT = (last3d - first3d) / (nbp -1);
943 TColgp_Array1OfPnt c3dpnt(1,nbp);
944 for (i = 1; i <= nbp; i++)
945 c3dpnt(i) = c3dAdapt.Value(first3d + (i-1)*deltaT);
947 Standard_Real dist = 0., maxTol = -1.0;
948 Standard_Boolean more = Standard_True;
950 for (j = 1; more; j++) {
951 Handle(Geom2d_Curve) c2d2;
952 BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j);
954 more = !c2d2.IsNull();
956 Handle(Geom_Surface) aS = surf2;
957 if(!loc2.IsIdentity())
958 aS = Handle(Geom_Surface)::DownCast(surf2->Transformed ( loc2 ));
960 Standard_Real dist2 = 0.;
961 deltaT = (last - first) / (nbp - 1);
962 for (i = 1; i <= nbp; i++) {
963 gp_Pnt2d aP2d = c2d2->Value(first + (i -1)*deltaT);
964 gp_Pnt aP2(0.,0.,0.);
965 aS->D0(aP2d.X(),aP2d.Y(), aP2);
966 gp_Pnt aP1 = c3dpnt(i);
967 dist = aP2.SquareDistance(aP1);
971 maxTol = Max(sqrt(dist2), Precision::Confusion());
974 if(maxTol >= 0. && maxTol < tolReached)
975 aBuilder.UpdateEdge(edge, maxTol);
976 aBuilder.SameParameter(edge,Standard_True);
980 Standard_Real tolEdge1 = BRep_Tool::Tolerance(edge);
981 if (tolEdge1 > MaxTolerance()) edge.Nullify();
985 //=======================================================================
986 // function : EvaluateAngulars
987 // purpose : internal use
988 //=======================================================================
990 void BRepBuilderAPI_Sewing::EvaluateAngulars(TopTools_SequenceOfShape& sequenceSec,
991 TColStd_Array1OfBoolean& secForward,
992 TColStd_Array1OfReal& tabAng,
993 const Standard_Integer indRef) const
997 Standard_Integer i, j, npt = 4, lengSec = sequenceSec.Length();
1001 TopLoc_Location loc;
1002 Standard_Real first, last;
1003 Handle(Geom_Curve) c3d;
1004 Handle(Geom2d_Curve) c2d;
1005 Handle(Geom_Surface) surf;
1006 TColgp_Array1OfVec normRef(1,npt);
1008 for (i = indRef; i <= lengSec; i++) {
1010 edge = TopoDS::Edge(sequenceSec(i));
1012 TopoDS_Shape bnd = edge;
1013 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1014 if (myBoundFaces.Contains(bnd)) {
1015 face = TopoDS::Face(myBoundFaces.FindFromKey(bnd).First());
1016 surf = BRep_Tool::Surface(face,loc);
1017 if (!loc.IsIdentity()) {
1018 surf = Handle(Geom_Surface)::DownCast(surf->Copy());
1019 surf->Transform(loc.Transformation());
1021 c2d = BRep_Tool::CurveOnSurface(edge, face, first, last);
1023 else if (i == indRef) return;
1026 c3d = BRep_Tool::Curve(edge, loc, first, last);
1027 if (!loc.IsIdentity()) {
1028 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1029 c3d->Transform(loc.Transformation());
1032 GeomAdaptor_Curve adapt(c3d);
1033 GCPnts_UniformAbscissa uniAbs(adapt, npt, first, last);
1035 Standard_Real cumulateAngular = 0.0;
1036 Standard_Integer nbComputedAngle = 0;
1038 for (j = 1; j <= npt; j++) {
1040 c2d->D0(uniAbs.Parameter((secForward(i) || i == indRef)? j : npt-j+1),P);
1043 surf->D1(P.X(), P.Y(), unused, w1, w2);
1044 gp_Vec n = w1^w2; // Compute the normal vector
1045 if (i == indRef) normRef(j) = n;
1046 else if ((n.Magnitude()>gp::Resolution()) && (normRef(j).Magnitude()>gp::Resolution())) {
1048 Standard_Real angular = n.Angle(normRef(j));
1049 if (angular > M_PI/2.) angular = M_PI - angular;
1050 cumulateAngular += angular;
1054 if (nbComputedAngle)
1055 tabAng(i) = cumulateAngular/((Standard_Real)nbComputedAngle);
1059 //=======================================================================
1060 // function : EvaluateDistances
1061 // purpose : internal use
1062 // Evaluate distance beetween edges with indice indRef and the following edges in the list
1063 // Remarks (lengSec - indRef) must be >= 1
1064 //=======================================================================
1065 void BRepBuilderAPI_Sewing::EvaluateDistances(TopTools_SequenceOfShape& sequenceSec,
1066 TColStd_Array1OfBoolean& secForward,
1067 TColStd_Array1OfReal& tabDst,
1068 TColStd_Array1OfReal& arrLen,
1069 TColStd_Array1OfReal& tabMinDist,
1070 const Standard_Integer indRef) const
1072 secForward.Init(Standard_True);
1075 tabMinDist.Init(Precision::Infinite());
1076 const Standard_Integer npt = 8; // Number of points for curve discretization
1077 TColgp_Array1OfPnt ptsRef(1, npt), ptsSec(1, npt);
1079 Standard_Integer i, j, lengSec = sequenceSec.Length();
1080 TColgp_SequenceOfPnt seqSec;
1082 Handle(Geom_Curve) c3dRef;
1083 Standard_Real firstRef=0., lastRef=0.;
1085 for (i = indRef; i <= lengSec; i++) {
1087 // reading of the edge (attention for the first one: reference)
1088 const TopoDS_Edge& sec = TopoDS::Edge(sequenceSec(i));
1090 TopLoc_Location loc;
1091 Standard_Real first, last;
1092 Handle(Geom_Curve) c3d = BRep_Tool::Curve(sec, loc, first, last);
1093 if (c3d.IsNull()) continue;
1094 if (!loc.IsIdentity()) {
1095 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1096 c3d->Transform(loc.Transformation());
1100 c3dRef = c3d; firstRef = first; lastRef = last;
1103 Standard_Real dist = Precision::Infinite(), distFor = -1.0, distRev = -1.0;
1104 Standard_Real aMinDist = Precision::Infinite();
1106 Standard_Real T, deltaT = (last - first) / (npt - 1);
1107 Standard_Real aLenSec2 = 0.;
1109 Standard_Integer nbFound = 0;
1110 for (j = 1; j <= npt; j++) {
1112 // Uniform parameter on curve
1113 if (j == 1) T = first;
1114 else if (j == npt) T = last;
1115 else T = first + (j - 1) * deltaT;
1117 // Take point on curve
1118 gp_Pnt pt = c3d->Value(T);
1123 aLenSec2 += pt.SquareDistance(ptsRef(j-1));
1127 //protection to avoid merging with small sections
1129 aLenSec2 += pt.SquareDistance(ptsSec(j-1));
1130 // To evaluate mutual orientation and distance
1131 dist = pt.Distance(ptsRef(j));
1134 if (distFor < dist) distFor = dist;
1135 dist = pt.Distance(ptsRef(npt-j+1));
1139 if (distRev < dist) distRev = dist;
1141 // Check that point lays between vertices of reference curve
1142 const gp_Pnt &p11 = ptsRef(1);
1143 const gp_Pnt &p12 = ptsRef(npt);
1144 const gp_Vec aVec1(pt,p11);
1145 const gp_Vec aVec2(pt,p12);
1146 const gp_Vec aVecRef(p11,p12);
1147 if((aVecRef * aVec1) * (aVecRef * aVec2) < 0.)
1152 Standard_Real aLenSec = sqrt(aLenSec2);
1154 //if(aLenSec < myMinTolerance )
1156 arrLen.SetValue(i,aLenSec);
1157 // Record mutual orientation
1158 Standard_Boolean isForward = (distFor < distRev); //szv debug: <=
1159 secForward(i) = isForward;
1161 dist = (isForward? distFor : distRev);
1162 if(i == indRef || (dist < myTolerance && nbFound >= npt * 0.5) )
1165 tabMinDist(i) = aMinDist;
1169 nbFound = 0, aMinDist = Precision::Infinite(), dist = -1;
1170 TColgp_Array1OfPnt arrProj(1, npt);
1171 TColStd_Array1OfReal arrDist(1, npt), arrPara(1, npt);
1172 if( arrLen(indRef) >= arrLen(i))
1173 ProjectPointsOnCurve(ptsSec,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1175 ProjectPointsOnCurve(ptsRef,c3d,first,last,arrDist,arrPara,arrProj,Standard_False);
1176 for( j = 1; j <= npt; j++ )
1180 if(dist < arrDist(j))
1182 if( aMinDist > arrDist(j))
1183 aMinDist = arrDist(j);
1189 tabMinDist(i) = aMinDist;
1195 // Project distant points
1196 Standard_Integer nbFailed = seqSec.Length();
1197 if (!nbFailed) return;
1199 TColgp_Array1OfPnt arrPnt(1, nbFailed), arrProj(1, nbFailed);
1200 for (i = 1; i <= nbFailed; i++) arrPnt(i) = seqSec(i); seqSec.Clear();
1201 TColStd_Array1OfReal arrDist(1, nbFailed), arrPara(1, nbFailed);
1203 ProjectPointsOnCurve(arrPnt,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1205 // Process distant sections
1206 Standard_Integer idx1 = 1;
1207 for (i = indRef + 1; i <= lengSec; i++) {
1209 // Skip section if already evaluated
1210 if (tabDst(i) >= 0.0) continue;
1212 Standard_Real dist, distMax = -1.0, aMinDist = Precision::Infinite();
1214 Standard_Integer idx2 = (idx1 - 1)*npt;
1216 for (j = 1; j <= npt; j++) {
1218 dist = arrDist(idx2 + j);
1219 // If point is not projected - stop evaluation
1220 if (dist < 0.0) { distMax = -1.0; break; }
1221 if (distMax < dist) distMax = dist;
1222 if(aMinDist > dist) aMinDist = dist;
1225 // If section is close - record distance
1226 if (distMax >= 0.0) {
1227 if (secForward(i)) {
1228 dist = arrPnt(idx2+1).Distance(ptsRef(1));
1229 if (distMax < dist) distMax = dist;
1230 if(aMinDist > dist) aMinDist = dist;
1231 dist = arrPnt(idx2+npt).Distance(ptsRef(npt));
1232 if (distMax < dist) distMax = dist;
1233 if(aMinDist > dist) aMinDist = dist;
1236 dist = arrPnt(idx2+1).Distance(ptsRef(npt));
1237 if (distMax < dist) distMax = dist;
1238 if(aMinDist > dist) aMinDist = dist;
1239 dist = arrPnt(idx2+npt).Distance(ptsRef(1));
1240 if (distMax < dist) distMax = dist;
1241 if(aMinDist > dist) aMinDist = dist;
1244 if (distMax < myTolerance)
1246 tabDst(i) = distMax;
1247 tabMinDist(i) = aMinDist;
1251 idx1++; // To the next distant curve
1255 //=======================================================================
1256 //function : IsMergedClosed
1257 //purpose : internal use
1258 //=======================================================================
1260 Standard_Boolean BRepBuilderAPI_Sewing::IsMergedClosed(const TopoDS_Edge& Edge1,
1261 const TopoDS_Edge& Edge2,
1262 const TopoDS_Face& face) const
1264 // Check for closed surface
1265 TopLoc_Location loc;
1266 Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc);
1267 Standard_Boolean isUClosed = IsUClosedSurface(surf,Edge1,loc);
1268 Standard_Boolean isVClosed = IsVClosedSurface(surf,Edge1,loc);
1269 if (!isUClosed && !isVClosed) return Standard_False;
1270 // Check condition on closed surface
1272 Standard_Real first1,last1,first2,last2;
1273 Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(Edge1,first1,last1);
1274 Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(Edge2,first2,last2);
1275 if (C3d1.IsNull() || C3d2.IsNull()) return Standard_False;
1277 Standard_Real first2d1,last2d1,first2d2,last2d2;
1278 Handle(Geom2d_Curve) C2d1 = BRep_Tool::CurveOnSurface(Edge1,face,first2d1,last2d1);
1279 Handle(Geom2d_Curve) C2d2 = BRep_Tool::CurveOnSurface(Edge2,face,first2d2,last2d2);
1280 if (C2d1.IsNull() || C2d2.IsNull()) return Standard_False;
1282 gp_Pnt p1 = C3d1->Value(0.5*(first1 + last1));
1283 gp_Pnt p2 = C3d1->Value(0.5*(first2 + last2));
1284 Standard_Real dist = p1.Distance(p2);
1285 gp_Pnt2d p12d = C2d1->Value(0.5*(first2d1 + last2d1));
1286 gp_Pnt2d p22d = C2d1->Value(0.5*(first2d2 + last2d2));
1287 Standard_Real dist2d = p12d.Distance(p22d);
1288 GeomAdaptor_Surface Ads(BRep_Tool::Surface(face));
1289 Standard_Real distSurf = Max(Ads.UResolution(dist), Ads.VResolution(dist));
1290 return (dist2d*0.2 >= distSurf);
1292 Standard_Integer isULongC1, isULongC2, isVLongC1, isVLongC2;
1293 Standard_Real SUmin, SUmax, SVmin, SVmax;
1294 Standard_Real C1Umin, C1Vmin, C1Umax, C1Vmax;
1295 Standard_Real C2Umin, C2Vmin, C2Umax, C2Vmax;
1296 { //szv: Use brackets to destroy local variables
1298 Geom2dAdaptor_Curve aC2d1(C2d1), aC2d2(C2d2);
1299 BndLib_Add2dCurve::Add(aC2d1,first2d1,last2d1,Precision::PConfusion(),B1);
1300 BndLib_Add2dCurve::Add(aC2d2,first2d2,last2d2,Precision::PConfusion(),B2);
1301 B1.Get(C1Umin,C1Vmin,C1Umax,C1Vmax);
1302 B2.Get(C2Umin,C2Vmin,C2Umax,C2Vmax);
1303 Standard_Real du, dv;
1304 du = (C1Umax - C1Umin); dv = (C1Vmax - C1Vmin);
1305 isULongC1 = (dv <= du); isVLongC1 = (du <= dv);
1306 du = (C2Umax - C2Umin); dv = (C2Vmax - C2Vmin);
1307 isULongC2 = (dv <= du); isVLongC2 = (du <= dv);
1308 surf->Bounds(SUmin,SUmax,SVmin,SVmax);
1310 if (isUClosed && isVLongC1 && isVLongC2) {
1311 // Do not merge if not overlapped by V
1312 Standard_Real dist = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1314 Standard_Real distInner = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1315 Standard_Real distOuter = (SUmax - SUmin) - Max((C2Umax - C1Umin),(C1Umax - C2Umin));
1316 if (distOuter <= distInner) return Standard_True;
1319 if (isVClosed && isULongC1 && isULongC2) {
1320 // Do not merge if not overlapped by U
1321 Standard_Real dist = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1323 Standard_Real distInner = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1324 Standard_Real distOuter = (SVmax - SVmin) - Max((C2Vmax - C1Vmin),(C1Vmax - C2Vmin));
1325 if (distOuter <= distInner) return Standard_True;
1328 return Standard_False;
1331 //=======================================================================
1332 //function : AnalysisNearestEdges
1334 //=======================================================================
1336 void BRepBuilderAPI_Sewing::AnalysisNearestEdges(const TopTools_SequenceOfShape& sequenceSec,
1337 TColStd_SequenceOfInteger& seqIndCandidate,
1338 TColStd_SequenceOfBoolean& seqOrientations,
1339 const Standard_Boolean evalDist)
1342 Standard_Integer workIndex = seqIndCandidate.First();
1343 TopoDS_Shape workedge = sequenceSec.Value(workIndex);
1344 TopoDS_Shape bnd = workedge;
1345 TopTools_ListOfShape workfaces;
1346 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1347 if (myBoundFaces.Contains(bnd))
1348 workfaces = myBoundFaces.FindFromKey(bnd);
1349 if(workfaces.IsEmpty()) return;
1350 TopTools_MapOfShape mapFaces;
1351 TopTools_ListIteratorOfListOfShape lIt;
1352 for (lIt.Initialize(workfaces); lIt.More(); lIt.Next())
1353 mapFaces.Add(lIt.Value());
1354 TColStd_SequenceOfInteger seqNotCandidate;
1355 TColStd_SequenceOfInteger seqNewForward;
1356 // Separates edges belonging the same face as work edge
1357 // for exception of edges belonging closed faces
1359 seqNotCandidate.Append(workIndex);
1360 for(Standard_Integer i = 1; i<= seqIndCandidate.Length(); ) {
1361 Standard_Integer index = seqIndCandidate.Value(i);
1362 Standard_Boolean isRemove = Standard_False;
1363 if(index == workIndex) {
1364 seqIndCandidate.Remove(i);
1365 seqOrientations.Remove(i);
1366 isRemove = Standard_True;
1369 TopoDS_Shape bnd2 = sequenceSec.Value(index);
1370 if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
1372 if(myBoundFaces.Contains(bnd2)) {
1373 const TopTools_ListOfShape& listfaces = myBoundFaces.FindFromKey(bnd2);
1374 Standard_Boolean isMerged = Standard_True;
1375 for (lIt.Initialize(listfaces); lIt.More() && isMerged; lIt.Next()) {
1376 if(mapFaces.Contains(lIt.Value())) {
1377 TopLoc_Location loc;
1378 Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(lIt.Value()),loc);
1379 isMerged = ((IsUClosedSurface(surf,bnd2,loc) || IsVClosedSurface(surf,bnd2,loc)) &&
1380 IsMergedClosed(TopoDS::Edge(sequenceSec.Value(index)),TopoDS::Edge(workedge),TopoDS::Face(lIt.Value())));
1384 seqNotCandidate.Append(index);
1385 seqIndCandidate.Remove(i);
1386 seqOrientations.Remove(i);
1387 isRemove = Standard_True;
1391 seqIndCandidate.Remove(i);
1392 seqOrientations.Remove(i);
1393 isRemove = Standard_True;
1398 if(seqIndCandidate.Length() == 0 || seqNotCandidate.Length() == 1) return;
1399 if(!evalDist) return;
1400 TColStd_Array2OfReal TotTabDist(1,seqNotCandidate.Length(),1,seqIndCandidate.Length());
1401 TColStd_MapOfInteger MapIndex;
1402 TColStd_SequenceOfInteger seqForward;
1404 // Definition and removing edges wich are not candidate for work edge
1405 // ( they have other nearest edges belonging to the work face)
1406 for(Standard_Integer k = 1; k<= seqNotCandidate.Length(); k++) {
1407 Standard_Integer index1 = seqNotCandidate.Value(k);
1408 TopoDS_Shape edge = sequenceSec.Value(index1);
1409 TopTools_SequenceOfShape tmpSeq;
1410 tmpSeq.Append(edge);
1411 for(Standard_Integer kk = 1; kk <= seqIndCandidate.Length();kk++)
1412 tmpSeq.Append(sequenceSec.Value(seqIndCandidate.Value(kk)));
1414 Standard_Integer lengSec = tmpSeq.Length();
1415 TColStd_Array1OfBoolean tabForward(1,lengSec);
1416 TColStd_Array1OfReal tabDist(1,lengSec);
1417 TColStd_Array1OfReal arrLen(1,lengSec);
1418 TColStd_Array1OfReal tabMinDist(1,lengSec);
1419 for (Standard_Integer i1 = 1 ; i1 <= lengSec; i1++)
1422 EvaluateDistances(tmpSeq,tabForward, tabDist,arrLen,tabMinDist,1 );
1424 for(Standard_Integer n = 1; n < lengSec; n++) {
1425 if(tabDist(n+1) == -1 || tabDist(n+1) > myTolerance) {
1429 TotTabDist(k,n) = tabDist(n+1 );
1430 seqForward.Append(tabForward(n+1) ? 1:0);
1434 for(Standard_Integer n = 1; n < lengSec; n++) {
1435 if(tabDist(n) == -1 || tabDist(n) > myTolerance) continue;
1436 if(tabDist(n+1) < TotTabDist(1,n)) {
1444 Standard_Integer i2 = seqIndCandidate.Length();
1445 for( ; i2 >=1 ; i2--)
1447 if(MapIndex.Contains(i2))
1449 seqIndCandidate.Remove(i2);
1450 seqOrientations.Remove(i2);
1454 //for(TColStd_MapIteratorOfMapOfInteger IMap(MapIndex); IMap.More(); IMap.Next()) {
1455 // seqIndCandidate.Remove(IMap.Key());
1456 // seqOrientations.Remove(IMap.Key());
1460 //=======================================================================
1461 //function : FindCandidates
1462 //purpose : internal use
1463 //=======================================================================
1465 Standard_Boolean BRepBuilderAPI_Sewing::FindCandidates(TopTools_SequenceOfShape& seqSections,
1466 TColStd_IndexedMapOfInteger& mapReference,
1467 TColStd_SequenceOfInteger& seqCandidates,
1468 TColStd_SequenceOfBoolean& seqOrientations)
1470 Standard_Integer i, nbSections = seqSections.Length();
1472 return Standard_False;
1473 // Retrieve last reference index
1474 Standard_Integer indReference = mapReference(mapReference.Extent());
1475 Standard_Integer nbCandidates = 0;
1476 TopTools_MapOfShape Faces1;
1477 //if (nbSections > 1) {
1479 TopoDS_Edge Edge1 = TopoDS::Edge(seqSections(indReference));
1481 // Retrieve faces for reference section
1483 { //szv: Use brackets to destroy local variables
1484 TopoDS_Shape bnd = Edge1;
1485 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1486 if (myBoundFaces.Contains(bnd)) {
1487 TopTools_ListIteratorOfListOfShape itf1(myBoundFaces.FindFromKey(bnd));
1488 for (; itf1.More(); itf1.Next()) Faces1.Add(itf1.Value());
1492 // Check merging conditions for candidates and remove unsatisfactory
1493 TopTools_SequenceOfShape seqSectionsNew;
1494 TColStd_SequenceOfInteger seqCandidatesNew;
1495 for (i = 1; i <= nbSections; i++) {
1496 if (i == indReference) {
1497 seqSectionsNew.Prepend(Edge1);
1498 seqCandidatesNew.Prepend(i);
1501 const TopoDS_Edge& Edge2 = TopoDS::Edge(seqSections(i));
1502 seqSectionsNew.Append(Edge2);
1503 seqCandidatesNew.Append(i);
1507 Standard_Integer nbSectionsNew = seqSectionsNew.Length();
1508 if (nbSectionsNew > 1) {
1510 // Evaluate distances between reference and other sections
1511 TColStd_Array1OfBoolean arrForward(1,nbSectionsNew);
1512 TColStd_Array1OfReal arrDistance(1,nbSectionsNew);
1513 TColStd_Array1OfReal arrLen(1,nbSectionsNew);
1514 TColStd_Array1OfReal arrMinDist(1,nbSectionsNew);
1515 EvaluateDistances(seqSectionsNew,arrForward,arrDistance,arrLen,arrMinDist,1);
1517 // Fill sequence of candidate indices sorted by distance
1518 for (i = 2; i <= nbSectionsNew; i++) {
1519 Standard_Real aMaxDist = arrDistance(i);
1520 if (aMaxDist >= 0.0 && aMaxDist <= myTolerance && arrLen(i) > myMinTolerance) {
1522 // Reference section is connected to section #i
1523 Standard_Boolean isInserted = Standard_False;
1524 Standard_Boolean ori = arrForward(i);
1525 for (Standard_Integer j = 1; (j <= seqCandidates.Length()) && !isInserted; j++) {
1526 Standard_Real aDelta = arrDistance(i) - arrDistance(seqCandidates.Value(j));
1528 if( aDelta < Precision::Confusion()) {
1530 if(fabs(aDelta) > RealSmall() ||
1531 arrMinDist(i) < arrMinDist(seqCandidates.Value(j)))
1533 seqCandidates.InsertBefore(j,i);
1534 seqOrientations.InsertBefore(j,ori);
1535 isInserted = Standard_True;
1540 seqCandidates.Append(i);
1541 seqOrientations.Append(ori);
1546 nbCandidates = seqCandidates.Length();
1548 return Standard_False; // Section has no candidates to merge
1550 // Replace candidate indices
1552 for (i = 1; i <= nbCandidates; i++)
1553 seqCandidates(i) = seqCandidatesNew(seqCandidates(i));
1557 if (!nbCandidates) return Standard_False; // Section has no candidates to merge
1559 if (myNonmanifold && nbCandidates >1) {
1560 TColStd_SequenceOfInteger seqNewCandidates;
1561 TColStd_SequenceOfBoolean seqOrientationsNew;
1562 seqCandidates.Prepend(1);
1563 seqOrientations.Prepend(Standard_True);
1564 for(Standard_Integer k = 1; k <= seqSections.Length() && seqCandidates.Length() > 1 ; k++) {
1565 AnalysisNearestEdges(seqSections,seqCandidates,seqOrientations,(k==1));
1566 if(k == 1 && !seqCandidates.Length()) return Standard_False;
1567 if(seqCandidates.Length()) {
1568 seqNewCandidates.Append(seqCandidates.First());
1569 seqOrientationsNew.Append(seqOrientations.First());
1572 seqCandidates.Prepend(seqNewCandidates);
1573 seqOrientations.Prepend(seqOrientationsNew);
1574 return Standard_True;
1578 // For manifold case leave only one candidate from equidistant candidates
1579 /*Standard_Integer minIndex = seqCandidateIndex.First();
1580 Standard_Real minDistance = arrDistance(minIndex);
1582 // Find equidistant candidates
1583 TColStd_SequenceOfInteger seqEqDistantIndex; seqEqDistantIndex.Append(1);
1584 for (i = 2; i <= nbCandidates; i++) {
1585 Standard_Integer index = seqCandidateIndex(i);
1586 if (Abs(minDistance - arrDistance(index)) <= Precision::Confusion())
1587 seqEqDistantIndex.Append(index);
1590 Standard_Integer eqLen = seqEqDistantIndex.Length();
1593 // Fill map of faces which equidistant sections belong to
1594 TopTools_MapOfShape mapFace;
1595 for (i = 1; i <= eqLen; i++) {
1596 Standard_Integer index = seqEqDistantIndex.Value(i);
1597 if (isCandidate(index)) {
1598 mapFace.Add(arrFace(index));
1602 // Non Manifold case
1603 // Edges are merged by pair among a face continuity C1 criterion
1604 if (mapFace.Extent() == eqLen) {
1610 Standard_Integer indMin = -1;// To check if the edge can be merged.
1611 // Computation of distances between the edges.
1612 TopTools_SequenceOfShape seqSh;
1613 Standard_Integer nbInd = EqDistSeq.Length();
1614 TColStd_Array1OfBoolean tmptabForward(1,nbInd);
1615 seqSh.Append(sequenceSec.Value(1));
1616 for (j = 2; j <= EqDistSeq.Length(); j++) {
1617 Standard_Integer index = EqDistSeq.Value(j);
1618 tmptabForward(j) = tabForward(index);
1619 seqSh.Append(sequenceSec.Value(index));
1622 EvaluateAngulars(seqSh, tmptabForward, tabDist,1);
1624 for(j=2; j <= seqSh.Length(); j++) {
1625 if (tabDist(j) > -1.) { // if edge(j) is connected to edge(i)
1626 if (min > tabDist(j)) {
1633 // Construct minDist, tabMinInd , tabMinForward(i) = tabForward(j);
1635 seqSh.Remove(indMin);
1636 for(j =2; j <= tmpSeq.Length(); ) {
1637 TopoDS_Shape sh = tmpSeq.Value(j);
1638 Standard_Boolean isRem = Standard_False;
1639 for(Standard_Integer k = 1; k<= seqSh.Length();k++) {
1640 if(seqSh.Value(k) == sh) {
1641 isRem = Standard_True;
1647 tabMinForward.Remove(j); // = -1;
1655 // Find the best approved candidate
1656 while (nbCandidates) {
1657 // Retrieve first candidate
1658 Standard_Integer indCandidate = seqCandidates.First();
1659 // Candidate is approved if it is in the map
1660 if (mapReference.Contains(indCandidate)) break;
1661 // Find candidates for candidate #indCandidate
1662 mapReference.Add(indCandidate); // Push candidate in the map
1663 TColStd_SequenceOfInteger seqCandidates1;
1664 TColStd_SequenceOfBoolean seqOrientations1;
1665 Standard_Boolean isFound =
1666 FindCandidates(seqSections,mapReference,seqCandidates1,seqOrientations1);
1667 mapReference.RemoveLast(); // Pop candidate from the map
1668 if (isFound) isFound = (seqCandidates1.Length() > 0);
1670 Standard_Integer indCandidate1 = seqCandidates1.First();
1671 // If indReference is the best candidate for indCandidate
1672 // then indCandidate is the best candidate for indReference
1673 if (indCandidate1 == indReference) break;
1674 // If some other reference in the map is the best candidate for indCandidate
1675 // then assume that reference is the best candidate for indReference
1676 if (mapReference.Contains(indCandidate1)) {
1677 seqCandidates.Prepend(indCandidate1);
1681 isFound = Standard_False;
1684 // Remove candidate #1
1685 seqCandidates.Remove(1);
1686 seqOrientations.Remove(1);
1692 if(nbCandidates > 0)
1694 Standard_Integer anInd = seqCandidates.Value(1);
1695 TopoDS_Edge Edge2 = TopoDS::Edge(seqSections(anInd));
1696 TopoDS_Shape bnd = Edge2;
1697 if (mySectionBound.IsBound(bnd))
1698 bnd = mySectionBound(bnd);
1700 if (myBoundFaces.Contains(bnd)) {
1701 Standard_Boolean isOK = Standard_True;
1702 TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1703 for (; itf2.More() && isOK; itf2.Next()) {
1704 const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1705 // Check whether condition is satisfied
1706 isOK = !Faces1.Contains(Face2);
1707 if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1710 return Standard_False;
1713 return (nbCandidates > 0);
1716 //=======================================================================
1717 //function : Constructor
1719 //=======================================================================
1721 BRepBuilderAPI_Sewing::BRepBuilderAPI_Sewing(const Standard_Real tolerance,
1722 const Standard_Boolean optionSewing,
1723 const Standard_Boolean optionAnalysis,
1724 const Standard_Boolean optionCutting,
1725 const Standard_Boolean optionNonmanifold)
1727 myReShape = new BRepTools_ReShape;
1728 Init(tolerance, optionSewing, optionAnalysis, optionCutting, optionNonmanifold);
1731 //=======================================================================
1733 //purpose : Initialise Talerance, and options sewing, faceAnalysis and cutting
1734 //=======================================================================
1736 void BRepBuilderAPI_Sewing::Init(const Standard_Real tolerance,
1737 const Standard_Boolean optionSewing,
1738 const Standard_Boolean optionAnalysis,
1739 const Standard_Boolean optionCutting,
1740 const Standard_Boolean optionNonmanifold)
1742 // Set tolerance and Perform options
1743 myTolerance = Max (tolerance, Precision::Confusion());
1744 mySewing = optionSewing;
1745 myAnalysis = optionAnalysis;
1746 myCutting = optionCutting;
1747 myNonmanifold = optionNonmanifold;
1748 // Set min and max tolerances
1749 myMinTolerance = myTolerance * 1e-4; //szv: proposal
1750 if (myMinTolerance < Precision::Confusion()) myMinTolerance = Precision::Confusion();
1751 myMaxTolerance = Precision::Infinite();
1753 myFaceMode = Standard_True;
1754 myFloatingEdgesMode = Standard_False;
1755 //myCuttingFloatingEdgesMode = Standard_False; //gka
1756 mySameParameterMode = Standard_True;
1757 myLocalToleranceMode = Standard_False;
1758 mySewedShape.Nullify();
1760 Load(TopoDS_Shape());
1763 //=======================================================================
1765 //purpose : Loads the context shape
1766 //=======================================================================
1768 void BRepBuilderAPI_Sewing::Load(const TopoDS_Shape& theShape)
1771 if (theShape.IsNull()) myShape.Nullify();
1772 else myShape = myReShape->Apply(theShape);
1773 mySewedShape.Nullify();
1774 // Nullify flags and counters
1775 myNbShapes = myNbEdges = myNbVertices = 0;
1777 myOldShapes.Clear();
1778 //myOldFaces.Clear();
1779 myDegenerated.Clear();
1780 myFreeEdges.Clear();
1781 myMultipleEdges.Clear();
1782 myContigousEdges.Clear();
1783 myContigSecBound.Clear();
1784 myBoundFaces.Clear();
1785 myBoundSections.Clear();
1786 myVertexNode.Clear();
1787 myVertexNodeFree.Clear();
1788 myNodeSections.Clear();
1789 myCuttingNode.Clear();
1790 mySectionBound.Clear();
1791 myLittleFace.Clear();
1794 //=======================================================================
1797 //=======================================================================
1799 void BRepBuilderAPI_Sewing::Add(const TopoDS_Shape& aShape)
1801 if (aShape.IsNull()) return;
1802 TopoDS_Shape oShape = myReShape->Apply(aShape);
1803 myOldShapes.Add(aShape,oShape);
1804 myNbShapes = myOldShapes.Extent();
1807 //=======================================================================
1808 //function : Perform
1810 //=======================================================================
1813 #include <OSD_Timer.hxx>
1816 void BRepBuilderAPI_Sewing::Perform(const Handle(Message_ProgressIndicator)& thePI)
1818 const Standard_Integer aNumberOfStages = myAnalysis + myCutting + mySewing + 2;
1819 Message_ProgressSentry aPS (thePI, "Sewing", 0, aNumberOfStages, 1);
1821 Standard_Real t_total = 0., t_analysis = 0., t_assembling = 0., t_cutting = 0., t_merging = 0.;
1822 OSD_Chronometer chr_total, chr_local;
1831 cout << "Begin face analysis..." << endl;
1835 FaceAnalysis (thePI);
1841 chr_local.Show(t_analysis);
1842 cout << "Face analysis finished after " << t_analysis << " s" << endl;
1846 if (myNbShapes || !myShape.IsNull())
1849 FindFreeBoundaries();
1851 if (myBoundFaces.Extent())
1855 cout << "Begin vertices assembling..." << endl;
1859 VerticesAssembling (thePI);
1865 chr_local.Show(t_assembling);
1866 cout << "Vertices assembling finished after " << t_assembling << " s" << endl;
1871 cout << "Begin cutting..." << endl;
1881 chr_local.Show(t_cutting);
1882 cout << "Cutting finished after " << t_cutting << " s" << endl;
1886 cout << "Begin merging..." << endl;
1890 Merging (Standard_True, thePI);
1896 chr_local.Show(t_merging);
1897 cout << "Merging finished after " << t_merging << " s" << endl;
1902 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1904 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1905 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1914 cout << "Creating sewed shape..." << endl;
1916 // examine the multiple edges if any and process sameparameter for edges if necessary
1917 EdgeProcessing (thePI);
1923 mySewedShape.Nullify();
1927 EdgeRegularity (thePI);
1929 if (mySameParameterMode && myFaceMode)
1930 SameParameterShape();
1933 mySewedShape.Nullify();
1937 cout << "Sewed shape created" << endl;
1941 // create edge informations for output
1942 CreateOutputInformations();
1945 mySewedShape.Nullify();
1951 chr_total.Show(t_total);
1952 cout << "Sewing finished!" << endl;
1953 cout << " analysis time : " << t_analysis << " s" << endl;
1954 cout << " assembling time : " << t_assembling << " s" << endl;
1955 cout << " cutting time : " << t_cutting << " s" << endl;
1956 cout << " merging time : " << t_merging << " s" << endl;
1957 cout << "Total time : " << t_total << " s" << endl;
1961 //=======================================================================
1962 //function : SewedShape
1963 //purpose : give the sewed shape
1964 // if a null shape, reasons:
1965 // -- no useable input shapes : all input shapes are degenerated
1966 // -- has multiple edges
1967 //=======================================================================
1969 const TopoDS_Shape& BRepBuilderAPI_Sewing::SewedShape() const
1971 return mySewedShape;
1974 //=======================================================================
1975 //function : NbFreeEdges
1977 //=======================================================================
1979 Standard_Integer BRepBuilderAPI_Sewing::NbFreeEdges() const
1981 return myFreeEdges.Extent();
1984 //=======================================================================
1985 //function : FreeEdge
1987 //=======================================================================
1989 const TopoDS_Edge& BRepBuilderAPI_Sewing::FreeEdge(const Standard_Integer index) const
1991 Standard_OutOfRange_Raise_if(index < 0 || index > NbFreeEdges(), "BRepBuilderAPI_Sewing::FreeEdge");
1992 return TopoDS::Edge(myFreeEdges(index));
1995 //=======================================================================
1996 //function : NbMultipleEdges
1998 //=======================================================================
2000 Standard_Integer BRepBuilderAPI_Sewing::NbMultipleEdges() const
2002 return myMultipleEdges.Extent();
2005 //=======================================================================
2006 //function : MultipleEdge
2008 //=======================================================================
2010 const TopoDS_Edge& BRepBuilderAPI_Sewing::MultipleEdge(const Standard_Integer index) const
2012 Standard_OutOfRange_Raise_if(index < 0 || index > NbMultipleEdges(), "BRepBuilderAPI_Sewing::MultipleEdge");
2013 return TopoDS::Edge(myMultipleEdges(index));
2016 //=======================================================================
2017 //function : NbContigousEdges
2019 //=======================================================================
2021 Standard_Integer BRepBuilderAPI_Sewing::NbContigousEdges() const
2023 return myContigousEdges.Extent();
2026 //=======================================================================
2027 //function : ContigousEdge
2029 //=======================================================================
2031 const TopoDS_Edge& BRepBuilderAPI_Sewing::ContigousEdge(const Standard_Integer index) const
2033 Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdge");
2034 return TopoDS::Edge(myContigousEdges.FindKey(index));
2037 //=======================================================================
2038 //function : ContigousEdgeCouple
2040 //=======================================================================
2042 const TopTools_ListOfShape& BRepBuilderAPI_Sewing::ContigousEdgeCouple(const Standard_Integer index) const
2044 Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdgeCouple");
2045 return myContigousEdges(index);
2048 //=======================================================================
2049 //function : IsSectionBound
2051 //=======================================================================
2053 Standard_Boolean BRepBuilderAPI_Sewing::IsSectionBound(const TopoDS_Edge& section) const
2055 if(myContigSecBound.IsBound(section)) {
2056 return Standard_True;
2059 return Standard_False;
2063 //=======================================================================
2064 //function : SectionToBoundary
2066 //=======================================================================
2068 const TopoDS_Edge& BRepBuilderAPI_Sewing::SectionToBoundary(const TopoDS_Edge& section) const
2070 Standard_NoSuchObject_Raise_if(!IsSectionBound(section), "BRepBuilderAPI_Sewing::SectionToBoundary");
2071 return TopoDS::Edge(myContigSecBound(section));
2073 //=======================================================================
2074 //function : NbDeletedFaces
2076 //=======================================================================
2077 Standard_Integer BRepBuilderAPI_Sewing::NbDeletedFaces() const
2079 return myLittleFace.Extent();
2082 //=======================================================================
2083 //function : DeletedFace
2085 //=======================================================================
2086 const TopoDS_Face& BRepBuilderAPI_Sewing::DeletedFace(const Standard_Integer index) const
2088 Standard_OutOfRange_Raise_if(index < 0 || index > NbDeletedFaces(), "BRepBuilderAPI_Sewing::DeletedFace");
2089 return TopoDS::Face(myLittleFace(index));
2092 //=======================================================================
2093 //function : NbDegeneratedShapes
2095 //=======================================================================
2097 Standard_Integer BRepBuilderAPI_Sewing::NbDegeneratedShapes() const
2099 return myDegenerated.Extent();
2102 //=======================================================================
2103 //function : DegeneratedShape
2105 //=======================================================================
2107 const TopoDS_Shape& BRepBuilderAPI_Sewing::DegeneratedShape(const Standard_Integer index) const
2109 Standard_OutOfRange_Raise_if(index < 0 || index > NbDegeneratedShapes(), "BRepBuilderAPI_Sewing::DegereratedShape");
2110 return myDegenerated(index);
2113 //=======================================================================
2114 //function : IsDegenerated
2116 //=======================================================================
2118 Standard_Boolean BRepBuilderAPI_Sewing::IsDegenerated(const TopoDS_Shape& aShape) const
2120 TopoDS_Shape NewShape = myReShape->Apply(aShape);
2122 if (aShape.ShapeType() == TopAbs_FACE)
2123 return NewShape.IsNull();
2124 if (NewShape.IsNull()) return Standard_False;
2126 if (NewShape.ShapeType() == TopAbs_EDGE)
2127 return BRep_Tool::Degenerated(TopoDS::Edge(NewShape));
2129 if (NewShape.ShapeType() == TopAbs_WIRE) {
2130 Standard_Boolean isDegenerated = Standard_True;
2131 for (TopoDS_Iterator aIt(NewShape); aIt.More() && isDegenerated; aIt.Next())
2132 isDegenerated = BRep_Tool::Degenerated(TopoDS::Edge(aIt.Value()));
2133 return isDegenerated;
2135 return Standard_False;
2138 //=======================================================================
2139 //function : IsModified
2141 //=======================================================================
2143 Standard_Boolean BRepBuilderAPI_Sewing::IsModified(const TopoDS_Shape& aShape) const
2145 TopoDS_Shape NewShape = aShape;
2146 if (myOldShapes.Contains(aShape))
2147 NewShape = myOldShapes.FindFromKey(aShape);
2148 if(!NewShape.IsSame(aShape)) return Standard_True;
2149 return Standard_False;
2152 //=======================================================================
2153 //function : Modified
2155 //=======================================================================
2157 const TopoDS_Shape& BRepBuilderAPI_Sewing::Modified(const TopoDS_Shape& aShape) const
2159 if (myOldShapes.Contains(aShape)) return myOldShapes.FindFromKey(aShape);
2160 //if (myOldFaces.Contains(aShape)) return myOldFaces.FindFromKey(aShape);
2164 //=======================================================================
2165 //function : IsModifiedSubShape
2167 //=======================================================================
2169 Standard_Boolean BRepBuilderAPI_Sewing::IsModifiedSubShape(const TopoDS_Shape& aShape) const
2171 TopoDS_Shape NewShape = myReShape->Apply(aShape);
2172 if(!NewShape.IsSame(aShape)) return Standard_True;
2173 return Standard_False;
2176 //=======================================================================
2177 //function : ModifiedSubShape
2179 //=======================================================================
2181 TopoDS_Shape BRepBuilderAPI_Sewing::ModifiedSubShape(const TopoDS_Shape& aShape) const
2183 return myReShape->Apply(aShape);
2186 //=======================================================================
2189 //=======================================================================
2191 void BRepBuilderAPI_Sewing::Dump() const
2193 Standard_Integer i, NbBounds = myBoundFaces.Extent(), NbSections = 0;
2194 TopTools_MapOfShape mapVertices, mapEdges;
2195 for (i = 1; i <= NbBounds; i++) {
2196 TopoDS_Shape bound = myBoundFaces.FindKey(i);
2197 if (myBoundSections.IsBound(bound)) NbSections += myBoundSections(bound).Extent();
2199 TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
2200 for (; aExp.More(); aExp.Next()) {
2201 TopoDS_Edge E = TopoDS::Edge(aExp.Current());
2203 TopoDS_Vertex V1, V2;
2204 TopExp::Vertices(E,V1,V2);
2205 mapVertices.Add(V1);
2206 mapVertices.Add(V2);
2209 cout << " " << endl;
2210 cout << " Informations " << endl;
2211 cout << " ===========================================================" << endl;
2212 cout << " " << endl;
2213 cout << " Number of input shapes : " << myOldShapes.Extent() << endl;
2214 cout << " Number of actual shapes : " << myNbShapes << endl;
2215 cout << " Number of Bounds : " << NbBounds << endl;
2216 cout << " Number of Sections : " << NbSections << endl;
2217 cout << " Number of Edges : " << mapEdges.Extent() << endl;
2218 cout << " Number of Vertices : " << myNbVertices << endl;
2219 cout << " Number of Nodes : " << mapVertices.Extent() << endl;
2220 cout << " Number of Free Edges : " << myFreeEdges.Extent() << endl;
2221 cout << " Number of Contigous Edges : " << myContigousEdges.Extent() << endl;
2222 cout << " Number of Multiple Edges : " << myMultipleEdges.Extent() << endl;
2223 cout << " Number of Degenerated Edges : " << myDegenerated.Extent() << endl;
2224 cout << " ===========================================================" << endl;
2225 cout << " " << endl;
2228 //=======================================================================
2229 //function : FaceAnalysis
2237 //=======================================================================
2239 void BRepBuilderAPI_Sewing::FaceAnalysis(const Handle(Message_ProgressIndicator)& thePI)
2241 if (!myShape.IsNull() && myOldShapes.IsEmpty()) {
2247 TopTools_MapOfShape SmallEdges;
2248 TopTools_DataMapOfShapeListOfShape GluedVertices;
2249 Standard_Integer i = 1;
2250 Message_ProgressSentry aPS (thePI, "Shape analysis", 0, myOldShapes.Extent(), 1);
2251 for (i = 1; i <= myOldShapes.Extent() && aPS.More(); i++, aPS.Next()) {
2252 for (TopExp_Explorer fexp(myOldShapes(i),TopAbs_FACE); fexp.More(); fexp.Next()) {
2254 // Retrieve current face
2255 TopoDS_Shape aTmpShape = fexp.Current(); //for porting
2256 TopoDS_Face face = TopoDS::Face(aTmpShape);
2257 Standard_Integer nbEdges = 0, nbSmall = 0;
2259 // Build replacing face
2260 aTmpShape = face.EmptyCopied().Oriented(TopAbs_FORWARD); //for porting
2261 TopoDS_Face nface = TopoDS::Face(aTmpShape);
2262 Standard_Boolean isFaceChanged = Standard_False;
2264 TopoDS_Iterator witer(face.Oriented(TopAbs_FORWARD));
2265 for (; witer.More(); witer.Next()) {
2267 // Retrieve current wire
2268 aTmpShape = witer.Value(); //for porting
2269 if( aTmpShape.ShapeType() != TopAbs_WIRE) continue;
2270 TopoDS_Wire wire = TopoDS::Wire(aTmpShape);
2272 // Build replacing wire
2273 aTmpShape = wire.EmptyCopied().Oriented(TopAbs_FORWARD);
2274 TopoDS_Wire nwire = TopoDS::Wire(aTmpShape);
2275 Standard_Boolean isWireChanged = Standard_False;
2277 TopoDS_Iterator eiter(wire.Oriented(TopAbs_FORWARD));
2278 for (; eiter.More(); eiter.Next()) {
2280 // Retrieve current edge
2281 aTmpShape = eiter.Value(); //for porting
2282 TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
2285 // Process degenerated edge
2286 if (BRep_Tool::Degenerated(edge)) {
2287 B.Add(nwire,edge); // Old edge kept
2288 myDegenerated.Add(edge);
2293 Standard_Boolean isSmall = SmallEdges.Contains(edge);
2296 // Check for small edge
2297 Standard_Real first, last;
2298 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,first,last);
2301 cout << "Warning: Possibly small edge can be sewed: No 3D curve" << endl;
2305 // Evaluate curve compactness
2306 const Standard_Integer npt = 5;
2307 gp_Pnt cp((c3d->Value(first).XYZ()+c3d->Value(last).XYZ())*0.5);
2308 Standard_Real dist, maxdist = 0.0;
2309 Standard_Real delta = (last - first)/(npt - 1);
2310 for (Standard_Integer idx = 0; idx < npt; idx++) {
2311 dist = cp.Distance(c3d->Value(first + idx*delta));
2312 if (maxdist < dist) maxdist = dist;
2314 isSmall = (2.*maxdist <= MinTolerance());
2316 GeomAdaptor_Curve cAdapt(c3d);
2317 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt,first,last);
2318 isSmall = (length <= MinTolerance());
2320 catch (Standard_Failure) {
2322 cout << "Warning: Possibly small edge can be sewed: ";
2323 Standard_Failure::Caught()->Print(cout); cout << endl;
2330 // Store small edge in the map
2331 SmallEdges.Add(edge);
2333 TopoDS_Vertex v1, v2;
2334 TopExp::Vertices(edge,v1,v2);
2335 TopoDS_Shape nv1 = myReShape->Apply(v1), nv2 = myReShape->Apply(v2);
2337 // Store glued vertices
2338 if (!nv1.IsSame(v1)) {
2339 TopTools_ListOfShape& vlist1 = GluedVertices(nv1);
2340 // First vertex was already glued
2341 if (!nv2.IsSame(v2)) {
2342 // Merge lists of glued vertices
2343 if (!nv1.IsSame(nv2)) {
2344 TopTools_ListIteratorOfListOfShape liter(GluedVertices(nv2));
2345 for (; liter.More(); liter.Next()) {
2346 TopoDS_Shape v = liter.Value();
2347 myReShape->Replace(v,nv1.Oriented(v.Orientation()));
2350 GluedVertices.UnBind(nv2);
2354 // Add second vertex to the existing list
2356 myReShape->Replace(v2,nv1.Oriented(v2.Orientation()));
2359 else if (!nv2.IsSame(v2)) {
2360 // Add first vertex to the existing list
2361 GluedVertices(nv2).Append(v1);
2362 myReShape->Replace(v1,nv2.Oriented(v1.Orientation()));
2364 else if (!v1.IsSame(v2)) {
2365 // Record new glued vertices
2368 TopTools_ListOfShape vlist;
2371 GluedVertices.Bind(nv,vlist);
2372 myReShape->Replace(v1,nv.Oriented(v1.Orientation()));
2373 myReShape->Replace(v2,nv.Oriented(v2.Orientation()));
2378 // Replace small edge
2381 cout << "Warning: Small edge made degenerated by FaceAnalysis" << endl;
2384 // Create new degenerated edge
2385 aTmpShape = edge.Oriented(TopAbs_FORWARD);
2386 TopoDS_Edge fedge = TopoDS::Edge(aTmpShape);
2387 Standard_Real pfirst, plast;
2388 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(fedge,face,pfirst,plast);
2389 if (!c2d.IsNull()) {
2392 B.UpdateEdge(nedge,c2d,face,Precision::Confusion());
2393 B.Range(nedge,pfirst,plast);
2394 B.Degenerated(nedge,Standard_True);
2395 TopoDS_Vertex v1, v2;
2396 TopExp::Vertices(fedge,v1,v2);
2397 B.Add(nedge,myReShape->Apply(v1).Oriented(v1.Orientation()));
2398 B.Add(nedge,myReShape->Apply(v2).Oriented(v2.Orientation()));
2399 B.Add(nwire,nedge.Oriented(edge.Orientation()));
2400 myDegenerated.Add(nedge);
2402 isWireChanged = Standard_True;
2404 else B.Add(nwire,edge); // Old edge kept
2407 // Record wire in the new face
2408 if (isWireChanged) {
2409 B.Add(nface,nwire.Oriented(wire.Orientation()));
2410 isFaceChanged = Standard_True;
2412 else B.Add(nface,wire);
2415 // Remove small face
2416 if (nbSmall == nbEdges) {
2418 cout << "Warning: Small face removed by FaceAnalysis" << endl;
2420 myLittleFace.Add(face);
2421 myReShape->Remove(face);
2423 else if (isFaceChanged) {
2425 myReShape->Replace(face,nface.Oriented(face.Orientation()));
2430 // Update glued vertices
2431 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape miter(GluedVertices);
2432 for (; miter.More(); miter.Next()) {
2433 TopoDS_Vertex vnew = TopoDS::Vertex(miter.Key());
2434 gp_XYZ coord(0.,0.,0.);
2435 Standard_Integer nbPoints = 0;
2436 const TopTools_ListOfShape& vlist = miter.Value();
2437 TopTools_ListIteratorOfListOfShape liter1(vlist);
2438 for (; liter1.More(); liter1.Next()) {
2439 coord += BRep_Tool::Pnt(TopoDS::Vertex(liter1.Value())).XYZ();
2443 gp_Pnt vp(coord / nbPoints);
2444 Standard_Real tol = 0.0, mtol = 0.0;
2445 TopTools_ListIteratorOfListOfShape liter2(vlist);
2446 for (; liter2.More(); liter2.Next()) {
2447 Standard_Real vtol = BRep_Tool::Tolerance(TopoDS::Vertex(liter2.Value()));
2448 if (mtol < vtol) mtol = vtol;
2449 vtol = vp.Distance(BRep_Tool::Pnt(TopoDS::Vertex(liter2.Value())));
2450 if (tol < vtol) tol = vtol;
2452 B.UpdateVertex(vnew,vp,tol+mtol);
2456 // Update input shapes
2457 for (i = 1; i <= myOldShapes.Extent(); i++)
2458 myOldShapes(i) = myReShape->Apply(myOldShapes(i));
2461 //=======================================================================
2462 //function : FindFreeBoundaries
2463 //purpose : Constructs :
2464 // myBoundFaces (bound = list of faces) - REFERENCE
2465 // myVertexNode (vertex = node)
2466 // myVertexNodeFree (floating vertex = node)
2468 //=======================================================================
2470 void BRepBuilderAPI_Sewing::FindFreeBoundaries()
2472 // Take into account the context shape if needed
2473 TopTools_IndexedMapOfShape NewShapes;
2474 if (!myShape.IsNull()) {
2475 if (myOldShapes.IsEmpty()) {
2480 TopoDS_Shape newShape = myReShape->Apply(myShape);
2481 if (!newShape.IsNull()) NewShapes.Add(newShape);
2484 // Create map Edge -> Faces
2485 TopTools_IndexedDataMapOfShapeListOfShape EdgeFaces;
2486 Standard_Integer i, nbShapes = myOldShapes.Extent();
2487 for (i = 1; i <= nbShapes; i++) {
2488 // Retrieve new shape
2489 TopoDS_Shape shape = myOldShapes(i);
2490 if (shape.IsNull()) continue;
2491 NewShapes.Add(shape);
2492 // Explore shape to find all boundaries
2493 for (TopExp_Explorer eExp(shape,TopAbs_EDGE); eExp.More(); eExp.Next()) {
2494 TopoDS_Shape edge = eExp.Current();
2495 if (!EdgeFaces.Contains(edge)) {
2496 TopTools_ListOfShape listFaces;
2497 EdgeFaces.Add(edge,listFaces);
2501 // Fill map Edge -> Faces
2502 nbShapes = NewShapes.Extent();
2503 TopTools_MapOfShape mapFaces;
2504 for (i = 1; i <= nbShapes; i++) {
2505 // Explore shape to find all faces
2506 TopExp_Explorer fExp(NewShapes.FindKey(i),TopAbs_FACE);
2507 for (; fExp.More(); fExp.Next()) {
2508 TopoDS_Shape face = fExp.Current();
2509 if(mapFaces.Contains(face)) continue;
2512 // Explore face to find all boundaries
2513 for (TopoDS_Iterator aIw(face); aIw.More(); aIw.Next()) {
2514 if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
2515 for (TopoDS_Iterator aIIe(aIw.Value()); aIIe.More(); aIIe.Next()) {
2517 TopoDS_Shape edge = aIIe.Value();
2519 if (EdgeFaces.Contains(edge)) {
2520 EdgeFaces.ChangeFromKey(edge).Append(face);
2521 //TopTools_ListOfShape& listFaces = EdgeFaces.ChangeFromKey(edge);
2522 //Standard_Boolean isContained = Standard_False;
2523 //TopTools_ListIteratorOfListOfShape itf(listFaces);
2524 //for (; itf.More() && !isContained; itf.Next())
2525 // isContained = face.IsSame(itf.Value());
2526 //if (!isContained) listFaces.Append(face);
2532 // Find free boundaries
2533 nbShapes = EdgeFaces.Extent();
2534 for (i = 1; i <= nbShapes; i++) {
2535 TopTools_ListOfShape& listFaces = EdgeFaces(i);
2536 Standard_Integer nbFaces = listFaces.Extent();
2537 TopoDS_Shape edge = EdgeFaces.FindKey(i);
2538 if(edge.Orientation() == TopAbs_INTERNAL)
2540 Standard_Boolean isSeam = Standard_False;
2542 TopoDS_Face face = TopoDS::Face(listFaces.First());
2543 isSeam = BRep_Tool::IsClosed(TopoDS::Edge(edge),face);
2545 ///Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
2546 //isSeam = (IsUClosedSurface(surf) || IsVClosedSurface(surf));
2549 TopoDS_Shape anewEdge = edge.EmptyCopied();
2550 TopoDS_Iterator aItV(edge);
2551 for( ; aItV.More() ; aItV.Next())
2552 aB.Add(anewEdge,aItV.Value());
2556 Standard_Real first2d,last2d;
2557 Handle(Geom2d_Curve) c2dold =
2558 BRep_Tool::CurveOnSurface(TopoDS::Edge(edge),TopoDS::Face(listFaces.First()),first2d,last2d);
2560 Handle(Geom2d_Curve) c2d;
2562 B.UpdateEdge(TopoDS::Edge(anewEdge),c2d,c2d,TopoDS::Face(listFaces.First()),0);
2563 B.UpdateEdge(TopoDS::Edge(anewEdge),c2dold,TopoDS::Face(listFaces.First()),0);
2565 Standard_Real aFirst, aLast;
2566 BRep_Tool::Range(TopoDS::Edge(edge),aFirst, aLast);
2567 aB.Range(TopoDS::Edge(anewEdge),aFirst, aLast);
2568 aB.Range(TopoDS::Edge(anewEdge),TopoDS::Face(listFaces.First()),first2d,last2d);
2569 myReShape->Replace(edge,anewEdge);
2573 isSeam = Standard_False;
2576 Standard_Boolean isBoundFloat = (myFloatingEdgesMode && !nbFaces);
2577 Standard_Boolean isBound = (myFaceMode && ((myNonmanifold && nbFaces) || (nbFaces == 1 && !isSeam)));
2578 if (isBound || isBoundFloat) {
2579 // Ignore degenerated edge
2580 if (BRep_Tool::Degenerated(TopoDS::Edge(edge))) continue;
2581 // Ignore edge with internal vertices
2582 // Standard_Integer nbVtx = 0;
2583 // for (TopExp_Explorer vExp(edge,TopAbs_VERTEX); vExp.More(); vExp.Next()) nbVtx++;
2584 // if (nbVtx != 2) continue;
2585 // Add to BoundFaces
2586 TopTools_ListOfShape listFacesCopy;
2587 listFacesCopy.Append(listFaces);
2588 myBoundFaces.Add(edge,listFacesCopy);
2589 // Process edge vertices
2590 TopoDS_Vertex vFirst, vLast;
2591 TopExp::Vertices(TopoDS::Edge(edge), vFirst, vLast);
2592 if(vFirst.IsNull() || vLast.IsNull()) continue;
2593 if(vFirst.Orientation() == TopAbs_INTERNAL || vLast.Orientation() == TopAbs_INTERNAL)
2596 // Add to VertexNode
2597 if (!myVertexNode.Contains(vFirst))
2598 myVertexNode.Add(vFirst,vFirst);
2599 if (!myVertexNode.Contains(vLast))
2600 myVertexNode.Add(vLast,vLast);
2603 // Add to VertexNodeFree
2604 if (!myVertexNodeFree.Contains(vFirst))
2605 myVertexNodeFree.Add(vFirst,vFirst);
2606 if (!myVertexNodeFree.Contains(vLast))
2607 myVertexNodeFree.Add(vLast,vLast);
2613 //=======================================================================
2614 //function : VerticesAssembling
2615 //purpose : Modifies :
2616 // myVertexNode (nodes glued)
2617 // myVertexNodeFree (nodes glued)
2618 // myNodeSections (lists of sections merged for glued nodes)
2620 //=======================================================================
2622 static Standard_Boolean CreateNewNodes(const TopTools_IndexedDataMapOfShapeShape& NodeNearestNode,
2623 const TopTools_IndexedDataMapOfShapeListOfShape& NodeVertices,
2624 TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2625 TopTools_DataMapOfShapeListOfShape& aNodeEdges)
2627 Standard_Integer i, nbNearest = NodeNearestNode.Extent();
2631 TopTools_DataMapOfShapeShape OldNodeNewNode;
2632 TopTools_DataMapOfShapeListOfShape NewNodeOldNodes;
2633 for (i = 1; i <= nbNearest; i++) {
2634 // Retrieve a pair of nodes to merge
2635 TopoDS_Shape oldnode1 = NodeNearestNode.FindKey(i);
2636 TopoDS_Shape oldnode2 = NodeNearestNode(i);
2637 // Second node should also be in the map
2638 if (!NodeNearestNode.Contains(oldnode2)) continue;
2639 // Get new node for old node #1
2640 if (OldNodeNewNode.IsBound(oldnode1)) {
2641 TopoDS_Shape newnode1 = OldNodeNewNode(oldnode1);
2642 if (OldNodeNewNode.IsBound(oldnode2)) {
2643 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2644 if (!newnode1.IsSame(newnode2)) {
2645 // Change data for new node #2
2646 TopTools_ListOfShape& lnode1 = NewNodeOldNodes(newnode1);
2647 TopTools_ListIteratorOfListOfShape itn(NewNodeOldNodes(newnode2));
2648 for (; itn.More(); itn.Next()) {
2649 TopoDS_Shape node2 = itn.Value();
2650 lnode1.Append(node2);
2651 OldNodeNewNode(node2) = newnode1;
2653 NewNodeOldNodes.UnBind(newnode2);
2657 // Old node #2 is not bound - add to old node #1
2658 OldNodeNewNode.Bind(oldnode2,newnode1);
2659 NewNodeOldNodes(newnode1).Append(oldnode2);
2663 if (OldNodeNewNode.IsBound(oldnode2)) {
2664 // Old node #1 is not bound - add to old node #2
2665 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2666 OldNodeNewNode.Bind(oldnode1,newnode2);
2667 NewNodeOldNodes(newnode2).Append(oldnode1);
2670 // Nodes are not bound - create new node
2671 TopoDS_Vertex newnode;
2672 B.MakeVertex(newnode);
2673 OldNodeNewNode.Bind(oldnode1,newnode);
2674 OldNodeNewNode.Bind(oldnode2,newnode);
2675 TopTools_ListOfShape lnodes;
2676 lnodes.Append(oldnode1);
2677 lnodes.Append(oldnode2);
2678 NewNodeOldNodes.Bind(newnode,lnodes);
2683 // Stop if no new nodes created
2684 if (!NewNodeOldNodes.Extent()) return Standard_False;
2686 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter1(NewNodeOldNodes);
2687 for (; iter1.More(); iter1.Next()) {
2688 const TopoDS_Vertex& newnode = TopoDS::Vertex(iter1.Key());
2689 // Calculate new node center point
2690 gp_XYZ theCoordinates(0.,0.,0.);
2691 TopTools_ListOfShape lvert; // Accumulate node vertices
2692 TopTools_MapOfShape medge;
2693 TopTools_ListOfShape ledge; // Accumulate node edges
2694 // Iterate on old nodes
2695 TopTools_ListIteratorOfListOfShape itn(iter1.Value());
2696 for (; itn.More(); itn.Next()) {
2697 const TopoDS_Shape& oldnode = itn.Value();
2698 // Iterate on node vertices
2699 TopTools_ListIteratorOfListOfShape itv(NodeVertices.FindFromKey(oldnode));
2700 for (; itv.More(); itv.Next()) {
2701 TopoDS_Vertex vertex = TopoDS::Vertex(itv.Value());
2702 // Change node for vertex
2703 aVertexNode.ChangeFromKey(vertex) = newnode;
2704 // Accumulate coordinates
2705 theCoordinates += BRep_Tool::Pnt(vertex).XYZ();
2706 lvert.Append(vertex);
2708 // Iterate on node edges
2709 const TopTools_ListOfShape& edges = aNodeEdges(oldnode);
2710 TopTools_ListIteratorOfListOfShape ite(edges);
2711 for (; ite.More(); ite.Next()) {
2712 TopoDS_Shape edge = ite.Value();
2713 if (!medge.Contains(edge)) { medge.Add(edge); ledge.Append(edge); }
2715 // Unbind old node edges
2716 aNodeEdges.UnBind(oldnode);
2718 // Bind new node edges
2719 aNodeEdges.Bind(newnode,ledge);
2720 gp_Pnt center(theCoordinates / lvert.Extent());
2721 // Calculate new node tolerance
2722 Standard_Real toler = 0.0;
2723 TopTools_ListIteratorOfListOfShape itv(lvert);
2724 for (; itv.More(); itv.Next()) {
2725 const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value());
2726 Standard_Real t = center.Distance(BRep_Tool::Pnt(vertex)) + BRep_Tool::Tolerance(vertex);
2727 if (toler < t) toler = t;
2729 // Update new node parameters
2730 B.UpdateVertex(newnode,center,toler);
2733 return Standard_True;
2736 static Standard_Integer IsMergedVertices(const TopoDS_Shape& face1,
2737 const TopoDS_Shape& e1, const TopoDS_Shape& e2,
2738 const TopoDS_Shape& vtx1, const TopoDS_Shape& vtx2)
2740 //Case of floating edges
2742 return (!IsClosedShape(e1,vtx1,vtx2));
2744 // Find wires containing given edges
2745 TopoDS_Shape wire1, wire2;
2746 TopExp_Explorer itw(face1,TopAbs_WIRE);
2747 for (; itw.More() && (wire1.IsNull() || wire2.IsNull()); itw.Next()) {
2748 TopoDS_Iterator ite(itw.Current(),Standard_False);
2749 for (; ite.More() && (wire1.IsNull() || wire2.IsNull()); ite.Next()) {
2750 if (wire1.IsNull() && e1.IsSame(ite.Value())) wire1 = itw.Current();
2751 if (wire2.IsNull() && e2.IsSame(ite.Value())) wire2 = itw.Current();
2754 Standard_Integer Status = 0;
2755 if (!wire1.IsNull() && !wire2.IsNull()) {
2756 if (wire1.IsSame(wire2)) {
2757 for (TopoDS_Iterator aIte(wire1,Standard_False); aIte.More(); aIte.Next()) {
2758 TopoDS_Vertex ve1,ve2;
2759 TopExp::Vertices(TopoDS::Edge(aIte.Value()),ve1,ve2);
2760 if ((ve1.IsSame(vtx1) && ve2.IsSame(vtx2)) ||
2761 (ve2.IsSame(vtx1) && ve1.IsSame(vtx2)))
2762 return (IsClosedShape(aIte.Value(),vtx1,vtx2)? 0 : 1);
2764 if (IsClosedShape(wire1,vtx1,vtx2)) {
2765 TopoDS_Vertex V1, V2;
2766 TopExp::Vertices(TopoDS::Wire(wire1),V1,V2);
2767 Standard_Boolean isEndVertex = ((V1.IsSame(vtx1) && V2.IsSame(vtx2)) ||
2768 (V2.IsSame(vtx1) && V1.IsSame(vtx2)));
2769 if (!isEndVertex) Status = 1;
2778 static Standard_Boolean GlueVertices(TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2779 TopTools_DataMapOfShapeListOfShape& aNodeEdges,
2780 const TopTools_IndexedDataMapOfShapeListOfShape& aBoundFaces,
2781 const Standard_Real Tolerance,
2782 const Handle(Message_ProgressIndicator)& theProgress)
2784 Standard_Integer i, nbVertices = aVertexNode.Extent();
2785 // Create map of node -> vertices
2786 TopTools_IndexedDataMapOfShapeListOfShape NodeVertices;
2787 BRepBuilderAPI_CellFilter aFilter (Tolerance);
2788 BRepBuilderAPI_VertexInspector anInspector (Tolerance);
2789 for (i = 1; i <= nbVertices; i++) {
2790 TopoDS_Shape vertex = aVertexNode.FindKey(i);
2791 TopoDS_Vertex node = TopoDS::Vertex(aVertexNode(i));
2792 if (NodeVertices.Contains(node)) {
2793 NodeVertices.ChangeFromKey(node).Append(vertex);
2796 TopTools_ListOfShape vlist;
2797 vlist.Append(vertex);
2798 NodeVertices.Add(node,vlist);
2799 gp_Pnt aPnt = BRep_Tool::Pnt (TopoDS::Vertex (node));
2800 aFilter.Add (NodeVertices.FindIndex (node), aPnt.XYZ());
2801 anInspector.Add (aPnt.XYZ());
2804 Standard_Integer nbNodes = NodeVertices.Extent();
2806 cout << "Glueing " << nbNodes << " nodes..." << endl;
2808 // Merge nearest nodes
2809 TopTools_IndexedDataMapOfShapeShape NodeNearestNode;
2810 Message_ProgressSentry aPS (theProgress, "Glueing nodes", 0, nbNodes, 1, Standard_True);
2811 for (i = 1; i <= nbNodes && aPS.More(); i++, aPS.Next()) {
2812 TopoDS_Vertex node1 = TopoDS::Vertex(NodeVertices.FindKey(i));
2814 gp_Pnt pt1 = BRep_Tool::Pnt (node1);
2815 anInspector.SetCurrent (pt1.XYZ());
2816 gp_XYZ aPntMin = anInspector.Shift (pt1.XYZ(), -Tolerance);
2817 gp_XYZ aPntMax = anInspector.Shift (pt1.XYZ(), Tolerance);
2818 aFilter.Inspect (aPntMin, aPntMax, anInspector);
2819 if (anInspector.ResInd().IsEmpty()) continue;
2820 // Retrieve list of edges for the first node
2821 const TopTools_ListOfShape& ledges1 = aNodeEdges(node1);
2822 // Explore list of near nodes and fill the sequence of glued nodes
2823 TopTools_SequenceOfShape SeqNodes;
2824 TopTools_ListOfShape listNodesSameEdge;
2825 //gp_Pnt pt1 = BRep_Tool::Pnt(node1);
2826 TColStd_ListIteratorOfListOfInteger iter1(anInspector.ResInd());
2827 for (; iter1.More(); iter1.Next()) {
2828 TopoDS_Vertex node2 = TopoDS::Vertex(NodeVertices.FindKey(iter1.Value()));
2829 if (node1 == node2) continue;
2830 // Retrieve list of edges for the second node
2831 const TopTools_ListOfShape& ledges2 = aNodeEdges(node2);
2832 // Check merging condition for the pair of nodes
2833 Standard_Integer Status = 0, isSameEdge = Standard_False;
2834 // Explore edges of the first node
2835 TopTools_ListIteratorOfListOfShape Ie1(ledges1);
2836 for (; Ie1.More() && !Status && !isSameEdge; Ie1.Next()) {
2837 const TopoDS_Shape& e1 = Ie1.Value();
2838 // Obtain real vertex from edge
2839 TopoDS_Shape v1 = node1;
2840 { //szv: Use brackets to destroy local variables
2841 TopoDS_Vertex ov1, ov2;
2842 TopExp::Vertices(TopoDS::Edge(e1),ov1,ov2);
2843 if (aVertexNode.Contains(ov1)) {
2844 if (node1.IsSame(aVertexNode.FindFromKey(ov1))) v1 = ov1;
2846 if (aVertexNode.Contains(ov2)) {
2847 if (node1.IsSame(aVertexNode.FindFromKey(ov2))) v1 = ov2;
2850 // Create map of faces for e1
2851 TopTools_MapOfShape Faces1;
2852 const TopTools_ListOfShape& lfac1 = aBoundFaces.FindFromKey(e1);
2853 if (lfac1.Extent()) {
2854 TopTools_ListIteratorOfListOfShape itf(lfac1);
2855 for (; itf.More(); itf.Next())
2856 if (!itf.Value().IsNull())
2857 Faces1.Add(itf.Value());
2859 // Explore edges of the second node
2860 TopTools_ListIteratorOfListOfShape Ie2(ledges2);
2861 for (; Ie2.More() && !Status && !isSameEdge; Ie2.Next()) {
2862 const TopoDS_Shape& e2 = Ie2.Value();
2863 // Obtain real vertex from edge
2864 TopoDS_Shape v2 = node2;
2865 { //szv: Use brackets to destroy local variables
2866 TopoDS_Vertex ov1, ov2;
2867 TopExp::Vertices(TopoDS::Edge(e2),ov1,ov2);
2868 if (aVertexNode.Contains(ov1)) {
2869 if (node2.IsSame(aVertexNode.FindFromKey(ov1))) v2 = ov1;
2871 if (aVertexNode.Contains(ov2)) {
2872 if (node2.IsSame(aVertexNode.FindFromKey(ov2))) v2 = ov2;
2875 // Explore faces for e2
2876 const TopTools_ListOfShape& lfac2 = aBoundFaces.FindFromKey(e2);
2877 if (lfac2.Extent()) {
2878 TopTools_ListIteratorOfListOfShape itf(lfac2);
2879 for (; itf.More() && !Status && !isSameEdge; itf.Next()) {
2880 // Check merging conditions for the same face
2881 if (Faces1.Contains(itf.Value())) {
2882 Standard_Integer stat = IsMergedVertices(itf.Value(),e1,e2,v1,v2);
2883 if (stat == 1) isSameEdge = Standard_True;
2888 else if (Faces1.IsEmpty() && e1 == e2) {
2889 Standard_Integer stat = IsMergedVertices(TopoDS_Face(),e1,e1,v1,v2);
2890 if (stat == 1) isSameEdge = Standard_True;
2896 if (Status) continue;
2897 if (isSameEdge) listNodesSameEdge.Append(node2);
2898 // Append near node to the sequence
2899 gp_Pnt pt2 = BRep_Tool::Pnt(node2);
2900 Standard_Real dist = pt1.Distance(pt2);
2901 if (dist < Tolerance) {
2902 Standard_Boolean isIns = Standard_False;
2903 for (Standard_Integer kk = 1; kk <= SeqNodes.Length() && !isIns; kk++) {
2904 gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(SeqNodes.Value(kk)));
2905 if (dist < pt1.Distance(pt)) {
2906 SeqNodes.InsertBefore(kk,node2);
2907 isIns = Standard_True;
2910 if (!isIns) SeqNodes.Append(node2);
2913 if (SeqNodes.Length()) {
2914 // Remove nodes near to some other from the same edge
2915 if (listNodesSameEdge.Extent()) {
2916 TopTools_ListIteratorOfListOfShape lInt(listNodesSameEdge);
2917 for (; lInt.More(); lInt.Next()) {
2918 const TopoDS_Vertex& n2 = TopoDS::Vertex(lInt.Value());
2919 gp_Pnt p2 = BRep_Tool::Pnt(n2);
2920 for (Standard_Integer k = 1; k <= SeqNodes.Length(); ) {
2921 const TopoDS_Vertex& n1 = TopoDS::Vertex(SeqNodes.Value(k));
2923 gp_Pnt p1 = BRep_Tool::Pnt(n1);
2924 if (p2.Distance(p1) >= pt1.Distance(p1)) { k++; continue; }
2930 // Bind nearest node if at least one exists
2931 if (SeqNodes.Length())
2932 NodeNearestNode.Add(node1,SeqNodes.First());
2934 anInspector.ClearResList();
2937 // Create new nodes for chained nearest nodes
2938 if (NodeNearestNode.IsEmpty()) return Standard_False;
2940 return CreateNewNodes(NodeNearestNode,NodeVertices,aVertexNode,aNodeEdges);
2943 void BRepBuilderAPI_Sewing::VerticesAssembling(const Handle(Message_ProgressIndicator)& thePI)
2945 Standard_Integer nbVert = myVertexNode.Extent();
2946 Standard_Integer nbVertFree = myVertexNodeFree.Extent();
2947 Message_ProgressSentry aPS (thePI, "Vertices assembling", 0, 2, 1);
2948 if (nbVert || nbVertFree) {
2949 // Fill map node -> sections
2951 for (i = 1; i <= myBoundFaces.Extent(); i++) {
2952 TopoDS_Shape bound = myBoundFaces.FindKey(i);
2953 for (TopoDS_Iterator itv(bound,Standard_False); itv.More(); itv.Next()) {
2954 TopoDS_Shape node = itv.Value();
2955 if (myNodeSections.IsBound(node))
2956 myNodeSections(node).Append(bound);
2958 TopTools_ListOfShape lbnd;
2960 myNodeSections.Bind(node,lbnd);
2967 cout << "Assemble " << nbVert << " vertices on faces..." << endl;
2969 while (GlueVertices(myVertexNode,myNodeSections,myBoundFaces,myTolerance, thePI));
2976 cout << "Assemble " << nbVertFree << " vertices on floating edges..." << endl;
2978 while (GlueVertices(myVertexNodeFree,myNodeSections,myBoundFaces,myTolerance, thePI));
2983 //=======================================================================
2984 //function : replaceNMVertices
2985 //purpose : internal use (static)
2986 //=======================================================================
2987 static void replaceNMVertices(const TopoDS_Edge& theEdge,
2988 const TopoDS_Vertex& theV1,
2989 const TopoDS_Vertex& theV2,
2990 const Handle(BRepTools_ReShape)& theReShape)
2992 //To keep NM vertices on edge
2993 TopTools_SequenceOfShape aSeqNMVert;
2994 TColStd_SequenceOfReal aSeqNMPars;
2995 Standard_Boolean hasNMVert = findNMVertices(theEdge,aSeqNMVert,aSeqNMPars);
2998 Standard_Real first, last;
2999 BRep_Tool::Range(theEdge, first, last);
3000 TopLoc_Location aLoc;
3001 Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,aLoc,first, last);
3004 TopTools_SequenceOfShape aEdVert;
3005 TColStd_SequenceOfReal aEdParams;
3006 Standard_Integer i =1, nb = aSeqNMPars.Length();
3008 for( ; i <= nb;i++) {
3009 Standard_Real apar = aSeqNMPars.Value(i);
3010 if(fabs(apar - first) <= Precision::PConfusion()) {
3011 theReShape->Replace(aSeqNMVert.Value(i),theV1);
3014 if(fabs(apar - last) <= Precision::PConfusion()) {
3015 theReShape->Replace(aSeqNMVert.Value(i),theV2);
3018 TopoDS_Shape aV = aSeqNMVert.Value(i);
3019 Standard_Integer j =1;
3020 for( ; j <= aEdParams.Length();j++) {
3021 Standard_Real apar2 = aEdParams.Value(j);
3022 if(fabs(apar - apar2) <= Precision::PConfusion()) {
3023 theReShape->Replace(aV,aEdVert.Value(j));
3026 else if(apar < apar2) {
3027 TopoDS_Shape anewV = aV.EmptyCopied();
3028 aEdVert.InsertBefore(j,anewV);
3029 aEdParams.InsertBefore(j,apar);
3030 BRep_ListOfPointRepresentation& alistrep =
3031 (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints();
3032 Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
3033 alistrep.Append(aPRep);
3034 theReShape->Replace(aV,anewV);
3038 if (j > aEdParams.Length()) {
3039 TopoDS_Shape anewV = aV.EmptyCopied();
3040 aEdVert.Append(anewV);
3041 aEdParams.Append(apar);
3042 BRep_ListOfPointRepresentation& alistrep =
3043 (*((Handle(BRep_TVertex)*) &anewV.TShape()))->ChangePoints();
3044 Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
3045 alistrep.Append(aPRep);
3046 theReShape->Replace(aV,anewV);
3050 Standard_Integer newnb = aEdParams.Length();
3053 TopoDS_Shape anewEdge = theEdge.EmptyCopied();
3054 TopAbs_Orientation anOri = theEdge.Orientation();
3055 anewEdge.Orientation(TopAbs_FORWARD);
3057 aB.Add(anewEdge,theV1);
3058 aB.Add(anewEdge,theV2);
3060 for( i =1; i <= aEdVert.Length();i++)
3061 aB.Add(anewEdge,aEdVert.Value(i));
3062 anewEdge.Orientation(anOri);
3063 theReShape->Replace(theEdge,anewEdge);
3068 //=======================================================================
3069 //function : ReplaceEdge
3070 //purpose : internal use (static)
3071 //=======================================================================
3073 static void ReplaceEdge(const TopoDS_Shape& oldEdge,
3074 const TopoDS_Shape& theNewShape,
3075 const Handle(BRepTools_ReShape)& aReShape)
3077 TopoDS_Shape oldShape = aReShape->Apply(oldEdge);
3078 TopoDS_Shape newShape = aReShape->Apply(theNewShape);
3079 if (oldShape.IsSame(newShape)|| aReShape->IsRecorded(newShape)) return;
3082 aReShape->Replace(oldShape,newShape);
3083 TopoDS_Vertex V1old,V2old,V1new,V2new;
3084 TopExp::Vertices(TopoDS::Edge(oldShape),V1old,V2old);
3085 TopAbs_Orientation Orold = oldShape.Orientation();
3086 TopAbs_Orientation Ornew = Orold;
3087 if (newShape.ShapeType() == TopAbs_EDGE) {
3088 TopoDS_Edge aEn = TopoDS::Edge(newShape);
3089 TopExp::Vertices(aEn,V1new,V2new);
3090 Ornew = aEn.Orientation();
3091 replaceNMVertices(aEn,V1new,V2new,aReShape);
3093 else if (newShape.ShapeType() == TopAbs_WIRE) {
3094 for (TopExp_Explorer aex(newShape,TopAbs_EDGE); aex.More(); aex.Next()) {
3095 TopoDS_Edge ed = TopoDS::Edge(aex.Current());
3096 Ornew = ed.Orientation();
3097 TopoDS_Vertex aV1,aV2;
3098 TopExp::Vertices(ed,aV1,aV2);
3099 replaceNMVertices(ed,aV1,aV2,aReShape);
3106 V1new.Orientation(V1old.Orientation());
3107 V2new.Orientation(V2old.Orientation());
3108 if (V1old.IsSame(V2old) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) {
3109 aReShape->Replace(V1old,V1new);
3112 if (Orold == Ornew) {
3113 V1new.Orientation(V1old.Orientation());
3114 V2new.Orientation(V2old.Orientation());
3115 if (!V1old.IsSame(V1new) && !V1old.IsSame(V2new)&& !aReShape->IsRecorded(V1new))
3116 aReShape->Replace(V1old,V1new);
3117 if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3118 aReShape->Replace(V2old,V2new);
3121 V1new.Orientation(V2old.Orientation());
3122 V2new.Orientation(V1old.Orientation());
3123 if (!V1old.IsSame(V2new) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3124 aReShape->Replace(V1old,V2new);
3125 if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V1new))
3126 aReShape->Replace(V2old,V1new);
3130 //=======================================================================
3131 //function : Merging
3132 //purpose : Modifies :
3135 //=======================================================================
3137 void BRepBuilderAPI_Sewing::Merging(const Standard_Boolean /* firstTime */,
3138 const Handle(Message_ProgressIndicator)& thePI)
3141 // TopTools_MapOfShape MergedEdges;
3142 Message_ProgressSentry aPS (thePI, "Merging bounds", 0, myBoundFaces.Extent(), 1);
3143 for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
3145 TopoDS_Shape bound = myBoundFaces.FindKey(i);
3147 // If bound was already merged - continue
3148 if (myMergedEdges.Contains(bound)) continue;
3150 if (!myBoundFaces(i).Extent()) {
3151 // Merge free edge - only vertices
3152 TopoDS_Vertex no1, no2;
3153 TopExp::Vertices(TopoDS::Edge(bound),no1,no2);
3154 TopoDS_Shape nno1 = no1, nno2 = no2;
3155 if (myVertexNodeFree.Contains(no1))
3156 nno1 = myVertexNodeFree.FindFromKey(no1);
3157 if (myVertexNodeFree.Contains(no2))
3158 nno2 = myVertexNodeFree.FindFromKey(no2);
3159 if (!no1.IsSame(nno1)) {
3160 nno1.Orientation(no1.Orientation());
3161 myReShape->Replace(no1,nno1);
3163 if (!no2.IsSame(nno2)) {
3164 nno2.Orientation(no2.Orientation());
3165 myReShape->Replace(no2,nno2);
3167 myMergedEdges.Add(bound);
3171 // Check for previous splitting, build replacing wire
3172 TopoDS_Wire BoundWire;
3173 Standard_Boolean isPrevSplit = Standard_False;
3174 Standard_Boolean hasCuttingSections = myBoundSections.IsBound(bound);
3175 if (hasCuttingSections) {
3176 B.MakeWire(BoundWire);
3177 BoundWire.Orientation(bound.Orientation());
3178 // Iterate on cutting sections
3179 TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3180 for (; its.More(); its.Next()) {
3181 TopoDS_Shape section = its.Value();
3182 B.Add(BoundWire,section);
3183 if (myMergedEdges.Contains(section)) isPrevSplit = Standard_True;
3188 TopTools_DataMapOfShapeShape MergedWithBound;
3190 // Obtain sequence of edges merged with bound
3191 TopTools_SequenceOfShape seqMergedWithBound;
3192 TColStd_SequenceOfBoolean seqMergedWithBoundOri;
3193 if (MergedNearestEdges(bound,seqMergedWithBound,seqMergedWithBoundOri)) {
3194 // Store bound in the map
3195 MergedWithBound.Bind(bound,bound);
3196 // Iterate on edges merged with bound
3197 Standard_Integer ii = 1;
3198 while (ii <= seqMergedWithBound.Length()) {
3199 TopoDS_Shape iedge = seqMergedWithBound.Value(ii);
3200 // Remove edge if recorded as merged
3201 Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) ||
3202 MergedWithBound.IsBound(iedge));
3204 if (myBoundSections.IsBound(iedge)) {
3205 // Edge is splitted - check sections
3206 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3207 for (; lit.More() && !isRejected; lit.Next()) {
3208 const TopoDS_Shape& sec = lit.Value();
3209 // Remove edge (bound) if at least one of its sections already merged
3210 isRejected = (myMergedEdges.Contains(sec) || MergedWithBound.IsBound(sec));
3214 if (mySectionBound.IsBound(iedge)) {
3215 // Edge is a section - check bound
3216 const TopoDS_Shape& bnd = mySectionBound(iedge);
3217 // Remove edge (section) if its bound already merged
3218 isRejected = (myMergedEdges.Contains(bnd) || MergedWithBound.IsBound(bnd));
3222 // To the next merged edge
3224 // Remove rejected edge
3225 seqMergedWithBound.Remove(ii);
3226 seqMergedWithBoundOri.Remove(ii);
3229 // Process accepted edge
3230 MergedWithBound.Bind(iedge,iedge);
3234 Standard_Integer nbMerged = seqMergedWithBound.Length();
3236 // Create same parameter edge
3237 TopTools_MapOfShape ActuallyMerged;
3238 TopoDS_Edge MergedEdge = SameParameterEdge(bound,seqMergedWithBound,
3239 seqMergedWithBoundOri,
3240 ActuallyMerged,myReShape);
3241 Standard_Boolean isForward = Standard_False;
3242 if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3243 // Process actually merged edges
3244 Standard_Integer nbActuallyMerged = 0;
3245 for (ii = 1; ii <= nbMerged; ii++) {
3246 TopoDS_Shape iedge = seqMergedWithBound(ii);
3247 if (ActuallyMerged.Contains(iedge)) {
3249 // Record merged edge in the map
3250 TopAbs_Orientation orient = iedge.Orientation();
3251 if (!isForward) orient = TopAbs::Reverse(orient);
3252 if (!seqMergedWithBoundOri(ii)) orient = TopAbs::Reverse(orient);
3253 MergedWithBound.ChangeFind(iedge) = MergedEdge.Oriented(orient);
3255 else MergedWithBound.UnBind(iedge);
3257 if (nbActuallyMerged) {
3258 // Record merged bound in the map
3259 TopAbs_Orientation orient = bound.Orientation();
3260 if (!isForward) orient = TopAbs::Reverse(orient);
3261 MergedWithBound.ChangeFind(bound) = MergedEdge.Oriented(orient);
3263 nbMerged = nbActuallyMerged;
3265 // Remove bound from the map if not finally merged
3266 if (!nbMerged) MergedWithBound.UnBind(bound);
3269 const Standard_Boolean isMerged = !MergedWithBound.IsEmpty();
3271 // Merge with cutting sections
3272 Handle(BRepTools_ReShape) SectionsReShape = new BRepTools_ReShape;
3273 TopTools_DataMapOfShapeShape MergedWithSections;
3274 if (hasCuttingSections) {
3275 // Iterate on cutting sections
3276 TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3277 for (; its.More(); its.Next()) {
3278 // Retrieve cutting section
3279 TopoDS_Shape section = its.Value();
3280 // Skip section if already merged
3281 if (myMergedEdges.Contains(section)) continue;
3282 // Merge cutting section
3283 TopTools_SequenceOfShape seqMergedWithSection;
3284 TColStd_SequenceOfBoolean seqMergedWithSectionOri;
3285 if (MergedNearestEdges(section,seqMergedWithSection,seqMergedWithSectionOri)) {
3286 // Store section in the map
3287 MergedWithSections.Bind(section,section);
3288 // Iterate on edges merged with section
3289 Standard_Integer ii = 1;
3290 while (ii <= seqMergedWithSection.Length()) {
3291 TopoDS_Shape iedge = seqMergedWithSection.Value(ii);
3292 // Remove edge if recorded as merged
3293 Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || MergedWithSections.IsBound(iedge));
3295 if (myBoundSections.IsBound(iedge)) {
3296 // Edge is splitted - check sections
3297 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3298 for (; lit.More() && !isRejected; lit.Next()) {
3299 const TopoDS_Shape& sec = lit.Value();
3300 // Remove edge (bound) if at least one of its sections already merged
3301 isRejected = (myMergedEdges.Contains(sec) || MergedWithSections.IsBound(sec));
3305 if (mySectionBound.IsBound(iedge)) {
3306 // Edge is a section - check bound
3307 const TopoDS_Shape& bnd = mySectionBound(iedge);
3308 // Remove edge (section) if its bound already merged
3309 isRejected = (myMergedEdges.Contains(bnd) || MergedWithSections.IsBound(bnd));
3313 // To the next merged edge
3315 // Remove rejected edge
3316 seqMergedWithSection.Remove(ii);
3317 seqMergedWithSectionOri.Remove(ii);
3320 // Process accepted edge
3321 MergedWithSections.Bind(iedge,iedge);
3325 Standard_Integer nbMerged = seqMergedWithSection.Length();
3327 // Create same parameter edge
3328 TopTools_MapOfShape ActuallyMerged;
3329 TopoDS_Edge MergedEdge = SameParameterEdge(section,seqMergedWithSection,
3330 seqMergedWithSectionOri,
3331 ActuallyMerged,SectionsReShape);
3332 Standard_Boolean isForward = Standard_False;
3333 if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3334 // Process actually merged edges
3335 Standard_Integer nbActuallyMerged = 0;
3336 for (ii = 1; ii <= nbMerged; ii++) {
3337 TopoDS_Shape iedge = seqMergedWithSection(ii);
3338 if (ActuallyMerged.Contains(iedge)) {
3340 // Record merged edge in the map
3341 TopAbs_Orientation orient = iedge.Orientation();
3342 if (!isForward) orient = TopAbs::Reverse(orient);
3343 if (!seqMergedWithSectionOri(ii)) orient = TopAbs::Reverse(orient);
3344 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3345 MergedWithSections.ChangeFind(iedge) = oedge;
3346 ReplaceEdge(myReShape->Apply(iedge),oedge,SectionsReShape);
3348 else MergedWithSections.UnBind(iedge);
3350 if (nbActuallyMerged) {
3351 // Record merged section in the map
3352 TopAbs_Orientation orient = section.Orientation();
3353 if (!isForward) orient = TopAbs::Reverse(orient);
3354 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3355 MergedWithSections.ChangeFind(section) = oedge;
3356 ReplaceEdge(myReShape->Apply(section),oedge,SectionsReShape);
3358 nbMerged = nbActuallyMerged;
3360 // Remove section from the map if not finally merged
3361 if (!nbMerged) MergedWithSections.UnBind(section);
3363 else if (isMerged) {
3364 // Reject merging of sections
3365 MergedWithSections.Clear();
3370 const Standard_Boolean isMergedSplit = !MergedWithSections.IsEmpty();
3372 if (!isMerged && !isMergedSplit) {
3373 // Nothing was merged in this iteration
3375 // Replace previously splitted bound
3376 myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3378 // else if (hasCuttingSections) {
3379 // myBoundSections.UnBind(bound); //szv: are you sure ???
3384 // Set splitting flag
3385 Standard_Boolean isSplitted = ((!isMerged && isMergedSplit) || isPrevSplit);
3387 // Choose between bound and sections merging
3388 if (isMerged && isMergedSplit && !isPrevSplit) {
3389 // Fill map of merged cutting sections
3390 TopTools_MapOfShape MapSplitEdges;
3391 TopTools_DataMapIteratorOfDataMapOfShapeShape itm;
3392 for (itm.Initialize(MergedWithSections); itm.More(); itm.Next()) {
3393 TopoDS_Shape edge = itm.Key();
3394 MapSplitEdges.Add(edge);
3396 // Iterate on edges merged with bound
3397 for (itm.Initialize(MergedWithBound); itm.More(); itm.Next()) {
3398 // Retrieve edge merged with bound
3399 TopoDS_Shape edge = itm.Key();
3400 // Remove edge from the map
3401 if (MapSplitEdges.Contains(edge)) MapSplitEdges.Remove(edge);
3402 if (myBoundSections.IsBound(edge)) {
3403 // Edge has cutting sections
3404 TopTools_ListIteratorOfListOfShape its(myBoundSections(edge));
3405 for (; its.More(); its.Next()) {
3406 TopoDS_Shape sec = its.Value();
3407 // Remove section from the map
3408 if (MapSplitEdges.Contains(sec)) MapSplitEdges.Remove(sec);
3412 // Calculate section merging tolerance
3413 Standard_Real MinSplitTol = RealLast();
3414 TopTools_MapIteratorOfMapOfShape im(MapSplitEdges);
3415 for (; im.More(); im.Next()) {
3416 TopoDS_Edge edge = TopoDS::Edge(MergedWithSections(im.Key()));
3417 MinSplitTol = Min(MinSplitTol,BRep_Tool::Tolerance(edge));
3419 // Calculate bound merging tolerance
3420 TopoDS_Edge BoundEdge = TopoDS::Edge(MergedWithBound(bound));
3421 Standard_Real BoundEdgeTol = BRep_Tool::Tolerance(BoundEdge);
3422 isSplitted = ((MinSplitTol < BoundEdgeTol+MinTolerance()) || myNonmanifold);
3423 isSplitted = (!MapSplitEdges.IsEmpty() && isSplitted);
3427 // Merging of cutting sections
3428 //myMergedEdges.Add(bound);
3429 myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3430 TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithSections);
3431 for (; itm.More(); itm.Next()) {
3432 TopoDS_Shape oldedge = itm.Key();
3433 TopoDS_Shape newedge = SectionsReShape->Apply(itm.Value());
3434 ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3435 myMergedEdges.Add(oldedge);
3436 if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3441 // Merging of initial bound
3442 TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithBound);
3443 //myMergedEdges.Add(bound);
3444 for (; itm.More(); itm.Next()) {
3445 TopoDS_Shape oldedge = itm.Key();
3446 TopoDS_Shape newedge = itm.Value();
3447 ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3448 myMergedEdges.Add(oldedge);
3449 if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3451 if (myBoundSections.IsBound(bound)) myBoundSections.UnBind(bound);
3452 if(!myMergedEdges.Contains(bound))
3453 myMergedEdges.Add(bound);
3457 myNbVertices = myVertexNode.Extent() + myVertexNodeFree.Extent();
3458 myNodeSections.Clear();
3459 myVertexNode.Clear();
3460 myVertexNodeFree.Clear();
3461 myCuttingNode.Clear();
3464 //=======================================================================
3465 //function : MergedNearestEdges
3467 //=======================================================================
3469 Standard_Boolean BRepBuilderAPI_Sewing::MergedNearestEdges(const TopoDS_Shape& edge,
3470 TopTools_SequenceOfShape& SeqMergedEdge,
3471 TColStd_SequenceOfBoolean& SeqMergedOri)
3473 // Retrieve edge nodes
3474 TopoDS_Vertex no1, no2;
3475 TopExp::Vertices(TopoDS::Edge(edge),no1,no2);
3476 TopoDS_Shape nno1 = no1, nno2 = no2;
3477 Standard_Boolean isNode1 = myVertexNode.Contains(no1);
3478 Standard_Boolean isNode2 = myVertexNode.Contains(no2);
3479 if (isNode1) nno1 = myVertexNode.FindFromKey(no1);
3480 if (isNode2) nno2 = myVertexNode.FindFromKey(no2);
3482 // Fill map of nodes connected to the node #1
3483 TopTools_MapOfShape mapVert1;
3485 if (myCuttingNode.IsBound(nno1)) {
3486 TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno1));
3487 for (; ilv.More(); ilv.Next()) {
3488 TopoDS_Shape v1 = ilv.Value();
3490 if (!isNode1 && myCuttingNode.IsBound(v1)) {
3491 TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3492 for (; ilvn.More(); ilvn.Next()) {
3493 TopoDS_Shape vn = ilvn.Value();
3500 // Fill map of nodes connected to the node #2
3501 TopTools_MapOfShape mapVert2;
3503 if (myCuttingNode.IsBound(nno2)) {
3504 TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno2));
3505 for (; ilv.More(); ilv.Next()) {
3506 TopoDS_Shape v1 = ilv.Value();
3508 if (!isNode2 && myCuttingNode.IsBound(v1)) {
3509 TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3510 for (; ilvn.More(); ilvn.Next()) {
3511 TopoDS_Shape vn = ilvn.Value();
3518 // Find all possible contigous edges
3519 TopTools_SequenceOfShape seqEdges;
3520 seqEdges.Append(edge);
3521 TopTools_MapOfShape mapEdges;
3523 for (TopTools_MapIteratorOfMapOfShape imv1(mapVert1); imv1.More(); imv1.Next()) {
3524 TopoDS_Shape node1 = imv1.Key();
3525 if (!myNodeSections.IsBound(node1)) continue;
3526 TopTools_ListIteratorOfListOfShape ilsec(myNodeSections(node1));
3527 for (; ilsec.More(); ilsec.Next()) {
3528 TopoDS_Shape sec = ilsec.Value();
3529 if (sec.IsSame(edge)) continue;
3530 // Retrieve section nodes
3531 TopoDS_Vertex vs1, vs2;
3532 TopExp::Vertices(TopoDS::Edge(sec),vs1,vs2);
3533 TopoDS_Shape vs1n = vs1, vs2n = vs2;
3534 if (myVertexNode.Contains(vs1)) vs1n = myVertexNode.FindFromKey(vs1);
3535 if (myVertexNode.Contains(vs2)) vs2n = myVertexNode.FindFromKey(vs2);
3536 if ((mapVert1.Contains(vs1n) && mapVert2.Contains(vs2n)) ||
3537 (mapVert1.Contains(vs2n) && mapVert2.Contains(vs1n)))
3538 if (mapEdges.Add(sec)) {
3539 // Check for rejected cutting
3540 Standard_Boolean isRejected = myMergedEdges.Contains(sec);
3541 if(!isRejected && myBoundSections.IsBound(sec))
3543 TopTools_ListIteratorOfListOfShape its(myBoundSections(sec));
3544 for (; its.More() && !isRejected; its.Next()) {
3545 TopoDS_Shape section = its.Value();
3547 if (myMergedEdges.Contains(section))
3548 isRejected = Standard_True;
3551 if( !isRejected && mySectionBound.IsBound(sec)) {
3552 const TopoDS_Shape& bnd = mySectionBound(sec);
3553 isRejected = (!myBoundSections.IsBound(bnd) ||
3554 myMergedEdges.Contains(bnd));
3557 if (!isRejected) seqEdges.Append(sec);
3564 Standard_Boolean success = Standard_False;
3566 Standard_Integer nbSection = seqEdges.Length();
3567 if (nbSection > 1) {
3568 // Find the longest edge CCI60011
3569 Standard_Integer i, indRef = 1;
3570 if (myNonmanifold) {
3571 Standard_Real lenRef = 0.;
3572 for (i = 1; i <= nbSection; i++) {
3574 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(seqEdges(i)), f, l);
3575 GeomAdaptor_Curve cAdapt(c3d);
3576 Standard_Real len = GCPnts_AbscissaPoint::Length(cAdapt, f, l);
3577 if (len > lenRef) { indRef = i; lenRef = len; }
3580 TopoDS_Shape longEdge = seqEdges(indRef);
3581 seqEdges(indRef) = seqEdges(1);
3582 seqEdges(1) = longEdge;
3586 // Find merging candidates
3587 TColStd_SequenceOfBoolean seqForward;
3588 TColStd_SequenceOfInteger seqCandidates;
3589 TColStd_IndexedMapOfInteger mapReference;
3590 mapReference.Add(indRef); // Add index of reference section
3591 if (FindCandidates(seqEdges,mapReference,seqCandidates,seqForward)) {
3592 Standard_Integer nbCandidates = seqCandidates.Length();
3593 // Record candidate sections
3594 for (i = 1; i <= nbCandidates; i++) {
3595 // Retrieve merged edge
3596 TopoDS_Shape iedge = seqEdges(seqCandidates(i));
3597 Standard_Boolean ori = seqForward(i) != 0;
3598 SeqMergedEdge.Append(iedge);
3599 SeqMergedOri.Append(ori);
3600 if (!myNonmanifold) break;
3602 success = (nbCandidates != 0);
3609 //=======================================================================
3610 //function : Cutting
3611 //purpose : Modifies :
3615 //=======================================================================
3617 void BRepBuilderAPI_Sewing::Cutting(const Handle(Message_ProgressIndicator)& thePI)
3619 Standard_Integer i, nbVertices = myVertexNode.Extent();
3620 if (!nbVertices) return;
3621 // Create a box tree with vertices
3622 Standard_Real eps = myTolerance*0.5;
3623 BRepBuilderAPI_BndBoxTree aTree;
3624 NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller (aTree);
3625 BRepBuilderAPI_BndBoxTreeSelector aSelector;
3626 for (i = 1; i <= nbVertices; i++) {
3627 gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(myVertexNode.FindKey(i)));
3631 aTreeFiller.Add (i, aBox);
3635 Handle(Geom_Curve) c3d;
3636 TopLoc_Location loc;
3637 Standard_Real first, last;
3638 // Iterate on all boundaries
3639 Standard_Integer nbBounds = myBoundFaces.Extent();
3640 Message_ProgressSentry aPS (thePI, "Cutting bounds", 0, nbBounds, 1);
3641 for (i = 1; i <= nbBounds && aPS.More(); i++, aPS.Next()) {
3642 const TopoDS_Edge& bound = TopoDS::Edge(myBoundFaces.FindKey(i));
3643 // Do not cut floating edges
3644 if (!myBoundFaces(i).Extent()) continue;
3645 // Obtain bound curve
3646 c3d = BRep_Tool::Curve(bound, loc, first, last);
3647 if (c3d.IsNull()) continue;
3648 if (!loc.IsIdentity()) {
3649 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3650 c3d->Transform(loc.Transformation());
3652 // Create cutting sections
3653 TopTools_ListOfShape listSections;
3654 { //szv: Use brackets to destroy local variables
3655 // Obtain candidate vertices
3656 TopoDS_Vertex V1, V2;
3657 TopTools_IndexedMapOfShape CandidateVertices;
3658 { //szv: Use brackets to destroy local variables
3659 // Create bounding box around curve
3661 GeomAdaptor_Curve adptC(c3d,first,last);
3662 BndLib_Add3dCurve::Add(adptC,myTolerance,aGlobalBox);
3663 // Sort vertices to find candidates
3664 aSelector.SetCurrent (aGlobalBox);
3665 aTree.Select (aSelector);
3666 // Skip bound if no node is in the boundind box
3667 if (!aSelector.ResInd().Extent()) continue;
3668 // Retrieve bound nodes
3669 TopExp::Vertices(bound,V1,V2);
3670 const TopoDS_Shape& Node1 = myVertexNode.FindFromKey(V1);
3671 const TopoDS_Shape& Node2 = myVertexNode.FindFromKey(V2);
3672 // Fill map of candidate vertices
3673 TColStd_ListIteratorOfListOfInteger itl(aSelector.ResInd());
3674 for (; itl.More(); itl.Next()) {
3675 const Standard_Integer index = itl.Value();
3676 const TopoDS_Shape& Node = myVertexNode.FindFromIndex(index);
3677 if (!Node.IsSame(Node1) && !Node.IsSame(Node2)) {
3678 TopoDS_Shape vertex = myVertexNode.FindKey(index);
3679 CandidateVertices.Add(vertex);
3682 aSelector.ClearResList();
3684 Standard_Integer nbCandidates = CandidateVertices.Extent();
3685 if (!nbCandidates) continue;
3686 // Project vertices on curve
3687 TColStd_Array1OfReal arrPara(1,nbCandidates), arrDist(1,nbCandidates);
3688 TColgp_Array1OfPnt arrPnt(1,nbCandidates), arrProj(1,nbCandidates);
3689 for (Standard_Integer j = 1; j <= nbCandidates; j++)
3690 arrPnt(j) = BRep_Tool::Pnt(TopoDS::Vertex(CandidateVertices(j)));
3691 ProjectPointsOnCurve(arrPnt,c3d,first,last,arrDist,arrPara,arrProj,Standard_True);
3692 // Create cutting nodes
3693 TopTools_SequenceOfShape seqNode;
3694 TColStd_SequenceOfReal seqPara;
3695 CreateCuttingNodes(CandidateVertices,bound,
3696 V1,V2,arrDist,arrPara,arrProj,seqNode,seqPara);
3697 if (!seqPara.Length()) continue;
3698 // Create cutting sections
3699 CreateSections(bound, seqNode, seqPara, listSections);
3701 if (listSections.Extent() > 1) {
3702 // modification of maps:
3704 TopTools_ListIteratorOfListOfShape its(listSections);
3705 for (; its.More(); its.Next()) {
3706 TopoDS_Shape section = its.Value();
3707 // Iterate on section vertices
3708 for (TopoDS_Iterator itv(section); itv.More(); itv.Next()) {
3709 TopoDS_Shape vertex = itv.Value();
3710 // Convert vertex to node
3711 if (myVertexNode.Contains(vertex))
3712 vertex = TopoDS::Vertex(myVertexNode.FindFromKey(vertex));
3713 // Update node sections
3714 if (myNodeSections.IsBound(vertex))
3715 myNodeSections.ChangeFind(vertex).Append(section);
3717 TopTools_ListOfShape lsec;
3718 lsec.Append(section);
3719 myNodeSections.Bind(vertex,lsec);
3722 // Store bound for section
3723 mySectionBound.Bind(section,bound);
3725 // Store splitted bound
3726 myBoundSections.Bind(bound,listSections);
3730 cout << "From " << nbBounds << " bounds " << myBoundSections.Extent()
3731 << " were cut into " << mySectionBound.Extent() << " sections" << endl;
3735 //=======================================================================
3736 //function : GetSeqEdges
3738 //=======================================================================
3740 static void GetSeqEdges(const TopoDS_Shape& edge,
3741 TopTools_SequenceOfShape& seqEdges,
3742 TopTools_DataMapOfShapeListOfShape& VertEdge)
3744 Standard_Integer numV = 0;
3745 for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3746 TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3748 if (VertEdge.IsBound(V1)) {
3749 const TopTools_ListOfShape& listEdges = VertEdge.Find(V1);
3750 for (TopTools_ListIteratorOfListOfShape lIt(listEdges); lIt.More(); lIt.Next()) {
3751 TopoDS_Shape edge1 = lIt.Value();
3752 if (edge1.IsSame(edge)) continue;
3753 Standard_Boolean isContained = Standard_False;
3754 Standard_Integer i, index = 1;
3755 for (i = 1; i <= seqEdges.Length() && !isContained; i++) {
3756 isContained = seqEdges.Value(i).IsSame(edge1);
3757 if (!isContained && seqEdges.Value(i).IsSame(edge)) index = i;
3760 if (numV == 1) seqEdges.InsertBefore(index,edge1);
3761 else seqEdges.InsertAfter(index,edge1);
3762 GetSeqEdges(edge1,seqEdges,VertEdge);
3769 //=======================================================================
3770 //function : GetFreeWires
3772 //=======================================================================
3774 void BRepBuilderAPI_Sewing::GetFreeWires(TopTools_MapOfShape& MapFreeEdges, TopTools_SequenceOfShape& seqWires)
3776 TopTools_DataMapOfShapeListOfShape VertEdge;
3777 TopTools_MapIteratorOfMapOfShape itMap(MapFreeEdges);
3778 TopTools_SequenceOfShape seqFreeEdges;
3779 for (; itMap.More(); itMap.Next()) {
3780 TopoDS_Shape edge = itMap.Key();
3781 seqFreeEdges.Append(edge);
3782 for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3783 TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3784 if (VertEdge.IsBound(V1))
3785 VertEdge.ChangeFind(V1).Append(edge);
3787 TopTools_ListOfShape ls;
3789 VertEdge.Bind(V1,ls);
3794 Standard_Integer i, j;
3795 for (i = 1; i <= seqFreeEdges.Length(); i++) {
3796 TopTools_SequenceOfShape seqEdges;
3797 TopoDS_Shape edge = seqFreeEdges.Value(i);
3798 if (!MapFreeEdges.Contains(edge)) continue;
3799 seqEdges.Append(edge);
3800 GetSeqEdges(edge,seqEdges,VertEdge);
3803 for (j = 1; j <= seqEdges.Length(); j++) {
3804 B.Add(wire,seqEdges.Value(j));
3805 MapFreeEdges.Remove(seqEdges.Value(j));
3807 seqWires.Append(wire);
3808 if (MapFreeEdges.IsEmpty()) break;
3812 //=======================================================================
3813 //function : IsDegeneratedWire
3814 //purpose : internal use
3815 //=======================================================================
3817 static Standard_Boolean IsDegeneratedWire(const TopoDS_Shape& wire)
3819 if (wire.ShapeType() != TopAbs_WIRE) return Standard_False;
3820 // Get maximal vertices tolerance
3821 TopoDS_Vertex V1,V2;
3822 //TopExp::Vertices(TopoDS::Wire(wire),V1,V2);
3823 //Standard_Real tol = Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3824 Standard_Real wireLength = 0.0;
3825 TopLoc_Location loc;
3826 Standard_Real first, last;
3827 Standard_Integer nume = 0;
3828 Standard_Integer isSmall = 0;
3829 for (TopoDS_Iterator aIt(wire,Standard_False); aIt.More(); aIt.Next()) {
3831 TopoDS_Shape edge = aIt.Value();
3832 TopoDS_Vertex Ve1,Ve2;
3833 TopExp::Vertices(TopoDS::Edge(edge),Ve1,Ve2);
3841 else if(Ve1.IsSame(V2))
3845 else if(Ve2.IsSame(V2))
3848 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aIt.Value()),loc,first,last);
3849 if (!c3d.IsNull()) {
3850 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3851 if (!loc.IsIdentity()) {
3852 //c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3853 c3d->Transform(loc.Transformation());
3855 gp_Pnt pfirst = c3d->Value(first);
3856 gp_Pnt plast = c3d->Value(last);
3857 gp_Pnt pmid = c3d->Value((first +last)*0.5);
3858 Standard_Real length =0;
3859 if(pfirst.Distance(plast) > pfirst.Distance(pmid)) {
3860 length = pfirst.Distance(plast);
3863 GeomAdaptor_Curve cAdapt(c3d);
3864 length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3866 Standard_Real tole = BRep_Tool::Tolerance(Ve1)+BRep_Tool::Tolerance(Ve2);
3867 if(length <= tole) isSmall++;
3868 wireLength += length;
3871 if(isSmall == nume) return Standard_True;
3872 Standard_Real tol = BRep_Tool::Tolerance(V1)+BRep_Tool::Tolerance(V2);//Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3873 if (wireLength > tol) return Standard_False;
3874 return Standard_True;
3877 //=======================================================================
3878 //function : DegeneratedSection
3879 //purpose : internal use
3880 // create a new degenerated edge if the section is degenerated
3881 //=======================================================================
3883 static TopoDS_Edge DegeneratedSection(const TopoDS_Shape& section, const TopoDS_Shape& face)
3885 // Return if section is already degenerated
3886 if (BRep_Tool::Degenerated(TopoDS::Edge(section))) return TopoDS::Edge(section);
3888 // Retrieve edge curve
3889 TopLoc_Location loc;
3890 Standard_Real first, last;
3891 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(section), loc, first, last);
3892 if (c3d.IsNull()) { //gka
3894 TopoDS_Edge edge1 = TopoDS::Edge(section);
3895 aB.Degenerated(edge1, Standard_True);
3898 if (!loc.IsIdentity()) {
3899 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3900 c3d->Transform(loc.Transformation());
3903 // Test if the new edge is degenerated
3904 TopoDS_Vertex v1,v2;
3905 TopExp::Vertices(TopoDS::Edge(section),v1,v2);
3906 //Standard_Real tol = Max(BRep_Tool::Tolerance(v1),BRep_Tool::Tolerance(v2));
3907 //tol = Max(tolerance,tol);
3910 p1 = BRep_Tool::Pnt(v1);
3911 p3 = BRep_Tool::Pnt(v2);
3912 c3d->D0(0.5*(first + last),p2);
3914 //Standard_Boolean isDegenerated = Standard_False;
3915 //if (p1.Distance(p3) < tol) {
3916 //GeomAdaptor_Curve cAdapt(c3d);
3917 //Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3918 //isDegenerated = Standard_True; //(length < tol);
3922 //if (!isDegenerated) return edge;
3925 BRep_Builder aBuilder;
3926 edge = TopoDS::Edge(section);
3928 if (v1.IsSame(v2)) {
3929 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3930 aBuilder.Add(anEdge, v1.Oriented(TopAbs_FORWARD));
3931 aBuilder.Add(anEdge, v2.Oriented(TopAbs_REVERSED));
3934 TopoDS_Vertex newVertex;
3935 if (p1.Distance(p3) < BRep_Tool::Tolerance(v1))
3937 else if (p1.Distance(p3) < BRep_Tool::Tolerance(v2))
3940 Standard_Real d1 = BRep_Tool::Tolerance(v1) + p2.Distance(p1);
3941 Standard_Real d2 = BRep_Tool::Tolerance(v2) + p2.Distance(p3);
3942 Standard_Real newTolerance = Max(d1,d2);
3943 aBuilder.MakeVertex(newVertex, p2, newTolerance);
3945 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3946 aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_FORWARD));
3947 aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_REVERSED));
3950 BRep_Tool::Range(TopoDS::Edge(section), first, last);
3951 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3952 aBuilder.Range(TopoDS::Edge(anEdge), first, last);
3953 aBuilder.Degenerated(edge, Standard_True);
3954 Handle(Geom_Curve) aC3dNew;
3955 if (!face.IsNull()) {
3956 Standard_Real af,al;
3957 Handle(Geom2d_Curve) aC2dt = BRep_Tool::CurveOnSurface(TopoDS::Edge(section),TopoDS::Face(face),af,al);
3958 aBuilder.UpdateEdge(edge,aC3dNew,0);
3959 Handle(Geom2d_Curve) aC2dn = BRep_Tool::CurveOnSurface(edge,TopoDS::Face(face),af,al);
3961 aBuilder.UpdateEdge(edge,aC2dt,TopoDS::Face(face),0);
3967 //=======================================================================
3968 //function : EdgeProcessing
3969 //purpose : modifies :
3971 // myHasMultipleEdge
3973 // . if multiple edge
3974 // - length < 100.*myTolerance -> several free edge
3975 // . if no multiple edge
3976 // - make the contigous edges sameparameter
3977 //=======================================================================
3979 void BRepBuilderAPI_Sewing::EdgeProcessing(const Handle(Message_ProgressIndicator)& thePI)
3981 // constructs sectionEdge
3982 TopTools_MapOfShape MapFreeEdges;
3983 TopTools_DataMapOfShapeShape EdgeFace;
3984 Message_ProgressSentry aPS (thePI, "Edge processing", 0, myBoundFaces.Extent(), 1);
3985 for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
3986 const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
3987 const TopTools_ListOfShape& listFaces = myBoundFaces(i);
3988 if (listFaces.Extent() == 1) {
3989 if (myBoundSections.IsBound(bound)) {
3990 TopTools_ListIteratorOfListOfShape liter(myBoundSections(bound));
3991 for (; liter.More(); liter.Next()) {
3992 if (!myMergedEdges.Contains(liter.Value())) { //myReShape->IsRecorded(liter.Value())) {
3993 TopoDS_Shape edge = myReShape->Apply(liter.Value());
3994 if (!MapFreeEdges.Contains(edge)) {
3995 TopoDS_Shape face = listFaces.First();
3996 EdgeFace.Bind(edge,face);
3997 MapFreeEdges.Add(edge);
4003 if (!myMergedEdges.Contains(bound)) {
4004 TopoDS_Shape edge = myReShape->Apply(bound);
4005 if (!MapFreeEdges.Contains(edge)) {
4006 TopoDS_Shape face = listFaces.First();
4007 EdgeFace.Bind(edge,face);
4008 MapFreeEdges.Add(edge);
4015 if (!MapFreeEdges.IsEmpty()) {
4016 TopTools_SequenceOfShape seqWires;
4017 GetFreeWires(MapFreeEdges,seqWires);
4018 for (Standard_Integer j = 1; j <= seqWires.Length(); j++) {
4019 TopoDS_Wire wire = TopoDS::Wire(seqWires.Value(j));
4020 if (!IsDegeneratedWire(wire)) continue;
4021 for (TopoDS_Iterator Ie(wire,Standard_False); Ie.More(); Ie.Next()) {
4022 TopoDS_Shape aTmpShape = myReShape->Apply(Ie.Value()); //for porting
4023 TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
4025 if (EdgeFace.IsBound(edge))
4026 face = EdgeFace.Find(edge);
4027 TopoDS_Shape degedge = DegeneratedSection(edge,face);
4028 if (degedge.IsNull()) continue;
4029 if (!degedge.IsSame(edge))
4030 ReplaceEdge(edge,degedge,myReShape);
4031 if (BRep_Tool::Degenerated(TopoDS::Edge(degedge)))
4032 myDegenerated.Add(degedge);
4038 //=======================================================================
4039 //function : EdgeRegularity
4040 //purpose : update Continuity flag on newly created edges
4041 //=======================================================================
4043 void BRepBuilderAPI_Sewing::EdgeRegularity(const Handle(Message_ProgressIndicator)& thePI)
4045 TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
4046 TopExp::MapShapesAndAncestors(mySewedShape, TopAbs_EDGE, TopAbs_FACE, aMapEF);
4048 Message_ProgressSentry aPS(thePI, "Encode edge regularity", 0, myMergedEdges.Extent(), 1);
4049 for (TopTools_MapIteratorOfMapOfShape aMEIt(myMergedEdges); aMEIt.More() && aPS.More(); aMEIt.Next(), aPS.Next())
4051 TopoDS_Edge anEdge = TopoDS::Edge(myReShape->Apply(aMEIt.Value()));
4052 const TopTools_ListOfShape* aFaces = aMapEF.Seek(anEdge);
4053 // encode regularity if and only if edges is shared by two faces
4054 if (aFaces && aFaces->Extent() == 2)
4055 BRepLib::EncodeRegularity(anEdge, TopoDS::Face(aFaces->First()), TopoDS::Face(aFaces->Last()));
4058 myMergedEdges.Clear();
4061 //=======================================================================
4062 //function : CreateSewedShape
4064 //=======================================================================
4066 void BRepBuilderAPI_Sewing::CreateSewedShape()
4068 // ---------------------
4069 // create the new shapes
4070 // ---------------------
4071 BRepTools_Quilt aQuilt;
4072 Standard_Boolean isLocal = !myShape.IsNull();
4075 TopoDS_Shape ns = myReShape->Apply(myShape);
4079 for (i = 1; i <= myOldShapes.Extent(); i++) {
4080 TopoDS_Shape sh = myOldShapes(i);
4082 sh = myReShape->Apply(sh);
4083 myOldShapes(i) = sh;
4084 if (!isLocal) aQuilt.Add(sh);
4087 TopoDS_Shape aNewShape = aQuilt.Shells();
4088 Standard_Integer numsh = 0;
4090 TopTools_IndexedMapOfShape OldShells;
4093 TopoDS_Compound aComp;
4094 aB.MakeCompound(aComp);
4095 for (TopoDS_Iterator aExpSh(aNewShape,Standard_False); aExpSh.More(); aExpSh.Next()) {
4096 TopoDS_Shape sh = aExpSh.Value();
4097 Standard_Boolean hasEdges = Standard_False;
4098 if (sh.ShapeType() == TopAbs_SHELL) {
4100 hasEdges = !OldShells.Contains(sh);
4103 Standard_Integer numf = 0;
4104 for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
4105 face = aExpF.Current();
4108 if (numf == 1) aB.Add(aComp,face);
4109 else if (numf > 1) aB.Add(aComp,sh);
4113 else if (sh.ShapeType() == TopAbs_FACE) {
4114 if (myNonmanifold) {
4119 hasEdges = Standard_True;
4121 else { aB.Add(aComp,sh); numsh++; }
4123 else { aB.Add(aComp,sh); numsh++; }
4124 if (hasEdges) OldShells.Add(sh);
4126 // Process collected shells
4127 if (myNonmanifold) {
4128 Standard_Integer nbOldShells = OldShells.Extent();
4129 if (nbOldShells == 1) {
4130 // Single shell - check for single face
4131 TopoDS_Shape sh = OldShells.FindKey(1);
4133 Standard_Integer numf = 0;
4134 for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
4135 face = aExpF.Current();
4138 if (numf == 1) aB.Add(aComp,face);
4139 else if (numf > 1) aB.Add(aComp,sh);
4142 else if (nbOldShells) {
4143 // Several shells should be merged
4144 TColStd_MapOfInteger IndexMerged;
4145 while (IndexMerged.Extent() < nbOldShells) {
4146 TopoDS_Shell NewShell;
4147 TopTools_MapOfShape NewEdges;
4148 for (i = 1; i <= nbOldShells; i++) {
4149 if (IndexMerged.Contains(i)) continue;
4150 TopoDS_Shell shell = TopoDS::Shell(OldShells.FindKey(i));
4151 if (NewShell.IsNull()) {
4152 aB.MakeShell(NewShell);
4153 TopoDS_Iterator aItSS(shell) ;
4154 for( ; aItSS.More(); aItSS.Next())
4155 aB.Add(NewShell,aItSS.Value())
4157 // Fill map of edges
4158 for (TopExp_Explorer eexp(shell,TopAbs_EDGE); eexp.More(); eexp.Next()) {
4159 TopoDS_Shape edge = eexp.Current();
4165 Standard_Boolean hasSharedEdge = Standard_False;
4166 TopExp_Explorer eexp(shell,TopAbs_EDGE);
4167 for (; eexp.More() && !hasSharedEdge; eexp.Next())
4168 hasSharedEdge = NewEdges.Contains(eexp.Current());
4169 if (hasSharedEdge) {
4170 // Add edges to the map
4171 for (TopExp_Explorer eexp1(shell,TopAbs_EDGE); eexp1.More(); eexp1.Next()) {
4172 TopoDS_Shape edge = eexp1.Current();
4175 // Add faces to the shell
4176 for (TopExp_Explorer fexp(shell,TopAbs_FACE); fexp.More(); fexp.Next()) {
4177 TopoDS_Shape face = fexp.Current();
4178 aB.Add(NewShell,face);
4184 // Process new shell
4186 Standard_Integer numf = 0;
4187 TopExp_Explorer aExpF(NewShell,TopAbs_FACE);
4188 for (; aExpF.More() && (numf < 2); aExpF.Next()) {
4189 face = aExpF.Current();
4192 if (numf == 1) aB.Add(aComp,face);
4193 else if (numf > 1) aB.Add(aComp,NewShell);
4199 // Extract single component
4200 TopoDS_Iterator aIt(aComp,Standard_False);
4201 mySewedShape = aIt.Value();
4204 mySewedShape = aComp;
4207 //=======================================================================
4208 //function : CreateOutputInformations
4209 //purpose : constructs :
4213 // myNbContigousEdges
4214 // myNbMultipleEdges
4216 //=======================================================================
4218 void BRepBuilderAPI_Sewing::CreateOutputInformations()
4220 // Construct edgeSections
4222 //TopTools_DataMapOfShapeListOfShape edgeSections;
4223 TopTools_IndexedDataMapOfShapeListOfShape edgeSections; //use index map for regulating free edges
4224 for (i = 1; i <= myBoundFaces.Extent(); i++) {
4225 const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
4226 TopTools_ListOfShape lsect;
4227 if (myBoundSections.IsBound(bound)) lsect = myBoundSections(bound);
4228 TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
4229 for (; aExp.More(); aExp.Next()) {
4230 TopoDS_Shape sec = bound, edge = aExp.Current();
4231 TopTools_ListIteratorOfListOfShape aI(lsect);
4232 for (; aI.More(); aI.Next()) {
4233 const TopoDS_Shape& section = aI.Value();
4234 if (edge.IsSame(myReShape->Apply(section))) { sec = section; break; }
4236 if (edgeSections.Contains(edge))
4237 edgeSections.ChangeFromKey(edge).Append(sec);
4239 TopTools_ListOfShape listSec;
4240 listSec.Append(sec);
4241 edgeSections.Add(edge,listSec);
4246 // Fill maps of Free, Contigous and Multiple edges
4247 //TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter2(edgeSections);
4248 for (i = 1; i <= edgeSections.Extent(); i++) {
4249 const TopoDS_Shape& edge = edgeSections.FindKey(i);
4250 const TopTools_ListOfShape& listSection = edgeSections(i);
4251 if (listSection.Extent() == 1) {
4252 if (BRep_Tool::Degenerated(TopoDS::Edge(edge)))
4253 myDegenerated.Add(edge);
4255 myFreeEdges.Add(edge);
4257 else if (listSection.Extent() == 2) {
4258 myContigousEdges.Add(edge,listSection);
4261 myMultipleEdges.Add(edge);
4265 // constructs myContigSectBound
4266 TopTools_DataMapOfShapeListOfShape aEdgeMap; //gka
4267 for (i = 1; i <= myBoundFaces.Extent(); i++) {
4268 TopoDS_Shape bound = myBoundFaces.FindKey(i);
4269 if (myBoundSections.IsBound(bound)) {
4270 TopTools_ListIteratorOfListOfShape iter(myBoundSections(bound));
4271 for (; iter.More(); iter.Next()) {
4272 TopoDS_Shape section = iter.Value();
4273 if(!myMergedEdges.Contains(section)) continue;
4274 //if (!myReShape->IsRecorded(section)) continue; // section is free
4275 TopoDS_Shape nedge = myReShape->Apply(section);
4276 if (nedge.IsNull()) continue; //szv debug
4277 if (!bound.IsSame(section))
4278 if (myContigousEdges.Contains(nedge))
4279 myContigSecBound.Bind(section, bound);
4285 //=======================================================================
4286 //function : ProjectPointsOnCurve
4287 //purpose : internal use
4288 //=======================================================================
4290 void BRepBuilderAPI_Sewing::ProjectPointsOnCurve(const TColgp_Array1OfPnt& arrPnt,
4291 const Handle(Geom_Curve)& c3d,
4292 const Standard_Real first,
4293 const Standard_Real last,
4294 TColStd_Array1OfReal& arrDist,
4295 TColStd_Array1OfReal& arrPara,
4296 TColgp_Array1OfPnt& arrProj,
4297 const Standard_Boolean isConsiderEnds) const
4301 GeomAdaptor_Curve GAC(c3d);
4302 Extrema_ExtPC locProj;
4303 locProj.Initialize(GAC, first, last);
4304 gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
4305 Standard_Integer find = 1;//(isConsiderEnds ? 1 : 2);
4306 Standard_Integer lind = arrPnt.Length();//(isConsiderEnds ? arrPnt.Length() : arrPnt.Length() -1);
4308 for (Standard_Integer i1 = find; i1 <= lind ; i1++) {
4309 gp_Pnt pt = arrPnt(i1);
4310 Standard_Real worktol = myTolerance;
4311 Standard_Real distF2 = pfirst.SquareDistance(pt);
4312 Standard_Real distL2 = plast.SquareDistance(pt);
4313 Standard_Boolean isProjected = Standard_False;
4316 // Project current point on curve
4317 locProj.Perform(pt);
4318 if (locProj.IsDone() && locProj.NbExt() > 0) {
4319 Standard_Real dist2Min = (isConsiderEnds || i1 == find || i1 == lind ? Min(distF2,distL2) : Precision::Infinite());
4320 Standard_Integer ind, indMin = 0;
4321 for (ind = 1; ind <= locProj.NbExt(); ind++) {
4322 Standard_Real dProj2 = locProj.SquareDistance(ind);
4323 if (dProj2 < dist2Min) { indMin = ind; dist2Min = dProj2; }
4326 isProjected = Standard_True;
4327 Extrema_POnCurv pOnC = locProj.Point(indMin);
4328 Standard_Real paramProj = pOnC.Parameter();
4329 gp_Pnt ptProj = GAC.Value(paramProj);
4330 Standard_Real distProj2 = ptProj.SquareDistance(pt);
4331 if (!locProj.IsMin(indMin)) {
4332 if (Min(distF2,distL2) < dist2Min) {
4333 if (distF2 < distL2) {
4345 if (distProj2 < worktol * worktol || !isConsiderEnds) {
4346 arrDist(i1) = sqrt (distProj2);
4347 arrPara(i1) = paramProj;
4348 arrProj(i1) = ptProj;
4353 catch (Standard_Failure const& anException) {
4355 cout << "Exception in BRepBuilderAPI_Sewing::ProjectPointsOnCurve: ";
4356 anException.Print(cout); cout << endl;
4359 worktol = MinTolerance();
4361 if (!isProjected && isConsiderEnds) {
4362 if (Min(distF2,distL2) < worktol * worktol) {
4363 if (distF2 < distL2) {
4364 arrDist(i1) = sqrt (distF2);
4365 arrPara(i1) = first;
4366 arrProj(i1) = pfirst;
4369 arrDist(i1) = sqrt (distL2);
4371 arrProj(i1) = plast;
4378 //=======================================================================
4379 //function : CreateCuttingNodes
4380 //purpose : internal use
4381 //=======================================================================
4383 void BRepBuilderAPI_Sewing::CreateCuttingNodes(const TopTools_IndexedMapOfShape& MapVert,
4384 const TopoDS_Shape& bound,
4385 const TopoDS_Shape& vfirst,
4386 const TopoDS_Shape& vlast,
4387 const TColStd_Array1OfReal& arrDist,
4388 const TColStd_Array1OfReal& arrPara,
4389 const TColgp_Array1OfPnt& arrPnt,
4390 TopTools_SequenceOfShape& seqVert,
4391 TColStd_SequenceOfReal& seqPara)
4393 Standard_Integer i, j, nbProj = MapVert.Extent();
4395 // Reorder projections by distance
4396 TColStd_SequenceOfInteger seqOrderedIndex;
4397 { //szv: Use brackets to destroy local variables
4398 TColStd_SequenceOfReal seqOrderedDistance;
4399 for (i = 1; i <= nbProj; i++) {
4400 Standard_Real distProj = arrDist(i);
4401 if (distProj < 0.0) continue; // Skip vertex if not projected
4402 Standard_Boolean isInserted = Standard_False;
4403 for (j = 1; j <= seqOrderedIndex.Length() && !isInserted; j++) {
4404 isInserted = (distProj < seqOrderedDistance(j));
4406 seqOrderedIndex.InsertBefore(j,i);
4407 seqOrderedDistance.InsertBefore(j,distProj);
4411 seqOrderedIndex.Append(i);
4412 seqOrderedDistance.Append(distProj);
4416 nbProj = seqOrderedIndex.Length();
4417 if (!nbProj) return;
4419 BRep_Builder aBuilder;
4421 // Insert two initial vertices (to be removed later)
4422 TColStd_SequenceOfReal seqDist;
4423 TColgp_SequenceOfPnt seqPnt;
4424 { //szv: Use brackets to destroy local variables
4425 // Retrieve bound curve
4426 TopLoc_Location loc;
4427 Standard_Real first,last;
4428 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(bound), loc, first, last);
4429 if (!loc.IsIdentity()) {
4430 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
4431 c3d->Transform(loc.Transformation());
4433 GeomAdaptor_Curve GAC(c3d);
4434 seqVert.Prepend(vfirst); seqVert.Append(vlast);
4435 seqPara.Prepend(first); seqPara.Append(last);
4436 seqDist.Prepend(-1.0); seqDist.Append(-1.0);
4437 seqPnt.Prepend(GAC.Value(first)); seqPnt.Append(GAC.Value(last));
4440 TopTools_DataMapOfShapeShape NodeCuttingVertex;
4441 for (i = 1; i <= nbProj; i++) {
4443 const Standard_Integer index = seqOrderedIndex(i);
4444 Standard_Real disProj = arrDist(index);
4445 gp_Pnt pntProj = arrPnt(index);
4447 // Skip node if already bound to cutting vertex
4448 TopoDS_Shape node = myVertexNode.FindFromKey(MapVert(index));
4449 if (NodeCuttingVertex.IsBound(node)) continue;
4451 // Find the closest vertex
4452 Standard_Integer indexMin = 1;
4453 Standard_Real dist, distMin = pntProj.Distance(seqPnt(1));
4454 for (j = 2; j <= seqPnt.Length(); j++) {
4455 dist = pntProj.Distance(seqPnt(j));
4456 if (dist < distMin) { distMin = dist; indexMin = j; }
4459 // Check if current point is close to one of the existent
4460 if (distMin <= Max(disProj*0.1,MinTolerance())) {
4461 // Check distance if close
4462 Standard_Real jdist = seqDist.Value(indexMin);
4464 // Bind new cutting node (end vertex only)
4465 seqDist.SetValue(indexMin,disProj);
4466 TopoDS_Shape cvertex = seqVert.Value(indexMin);
4467 NodeCuttingVertex.Bind(node,cvertex);
4470 // Bind secondary cutting nodes
4471 NodeCuttingVertex.Bind(node,TopoDS_Vertex());
4475 // Build new cutting vertex
4476 TopoDS_Vertex cvertex;
4477 aBuilder.MakeVertex(cvertex, pntProj, Precision::Confusion());
4478 // Bind new cutting vertex
4479 NodeCuttingVertex.Bind(node,cvertex);
4480 // Insert cutting vertex in the sequences
4481 Standard_Real parProj = arrPara(index);
4482 for (j = 2; j <= seqPara.Length(); j++) {
4483 if (parProj <= seqPara.Value(j)) {
4484 seqVert.InsertBefore(j,cvertex);
4485 seqPara.InsertBefore(j,parProj);
4486 seqDist.InsertBefore(j,disProj);
4487 seqPnt.InsertBefore (j,pntProj);
4494 // filling map for cutting nodes
4495 TopTools_DataMapIteratorOfDataMapOfShapeShape mit(NodeCuttingVertex);
4496 for (; mit.More(); mit.Next()) {
4497 TopoDS_Shape cnode = mit.Value();
4498 // Skip secondary nodes
4499 if (cnode.IsNull()) continue;
4500 // Obtain vertex node
4501 TopoDS_Shape node = mit.Key();
4502 if (myVertexNode.Contains(cnode)) {
4503 // This is an end vertex
4504 cnode = myVertexNode.FindFromKey(cnode);
4507 // Create link: cutting vertex -> node
4508 TopTools_ListOfShape ls;
4510 myCuttingNode.Bind(cnode,ls);
4512 // Create link: node -> cutting vertex
4513 if (myCuttingNode.IsBound(node)) {
4514 myCuttingNode.ChangeFind(node).Append(cnode);
4517 TopTools_ListOfShape ls;
4519 myCuttingNode.Bind(node,ls);
4523 // Remove two initial vertices
4524 seqVert.Remove(1); seqVert.Remove(seqVert.Length());
4525 seqPara.Remove(1); seqPara.Remove(seqPara.Length());
4528 //=======================================================================
4529 //function : CreateSections
4530 //purpose : internal use
4531 //=======================================================================
4533 void BRepBuilderAPI_Sewing::CreateSections(const TopoDS_Shape& section,
4534 const TopTools_SequenceOfShape& seqNode,
4535 const TColStd_SequenceOfReal& seqPara,
4536 TopTools_ListOfShape& listEdge)
4538 const TopoDS_Edge& sec = TopoDS::Edge(section);
4539 // TopAbs_Orientation aInitOr = sec.Orientation();
4542 //To keep NM vertices on edge
4543 TopTools_SequenceOfShape aSeqNMVert;
4544 TColStd_SequenceOfReal aSeqNMPars;
4545 findNMVertices(sec,aSeqNMVert,aSeqNMPars);
4547 BRep_Builder aBuilder;
4549 Standard_Real first, last;
4550 BRep_Tool::Range(sec, first, last);
4552 // Create cutting sections
4553 Standard_Real par1, par2;
4554 TopoDS_Shape V1, V2;
4555 Standard_Integer i, len = seqPara.Length() + 1;
4556 for (i = 1; i <= len; i++) {
4558 TopoDS_Edge edge = sec;
4564 V1 = TopExp::FirstVertex(sec);
4567 else if (i == len) {
4568 par1 = seqPara(i-1);
4571 V2 = TopExp::LastVertex(sec);
4574 par1 = seqPara(i-1);
4580 TopoDS_Shape aTmpShape = edge.Oriented(TopAbs_FORWARD);
4581 TopoDS_Edge aTmpEdge = TopoDS::Edge (aTmpShape); // for porting
4582 aTmpShape = V1.Oriented(TopAbs_FORWARD);
4583 aBuilder.Add(aTmpEdge, aTmpShape);
4584 aTmpShape = V2.Oriented(TopAbs_REVERSED);
4585 aBuilder.Add(aTmpEdge, aTmpShape);
4586 aBuilder.Range(aTmpEdge, par1, par2);
4587 // if(aInitOr == TopAbs_REVERSED)
4588 // listEdge.Prepend(edge);
4591 Standard_Integer k =1;
4592 for( ; k <= aSeqNMPars.Length() ; k++) {
4593 Standard_Real apar = aSeqNMPars.Value(k);
4594 if(apar >= par1 && apar <= par2) {
4595 aBuilder.Add(aTmpEdge,aSeqNMVert.Value(k));
4596 aSeqNMVert.Remove(k);
4597 aSeqNMPars.Remove(k);
4601 listEdge.Append(edge);
4604 const TopTools_ListOfShape& listFaces = myBoundFaces.FindFromKey(sec);
4605 if (!listFaces.Extent()) return;
4607 Standard_Real tolEdge = BRep_Tool::Tolerance(sec);
4609 // Add cutting pcurves
4610 TopTools_ListIteratorOfListOfShape itf(listFaces);
4611 for (; itf.More(); itf.Next()) {
4613 const TopoDS_Face& fac = TopoDS::Face(itf.Value());
4615 // Retrieve curve on surface
4616 Standard_Real first2d=0., last2d=0.,first2d1=0,last2d1=0.;
4617 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(sec, fac, first2d, last2d);
4618 if (c2d.IsNull()) continue;
4619 Handle(Geom2d_Curve) c2d1;
4620 Standard_Boolean isSeam = BRep_Tool::IsClosed(sec,fac);
4622 //gka - Convert to BSpline was commented because
4623 //it is not necessary to create BSpline instead of Lines or cIrcles.
4624 //Besides after conversion circles to BSpline
4625 //it is necessary to recompute parameters of cutting because paramerization of created
4626 //BSpline curve differs from parametrization of circle.
4628 // Convert pcurve to BSpline
4629 /*Handle(Geom2d_BSplineCurve) c2dBSP,c2dBSP1;
4630 if (c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
4631 c2dBSP = Handle(Geom2d_BSplineCurve)::DownCast(c2d);
4634 if (first > (c2d->FirstParameter() + Precision::PConfusion()) ||
4635 last < (c2d->LastParameter() - Precision::PConfusion())) {
4636 Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d, first, last);
4637 c2dBSP = Geom2dConvert::CurveToBSplineCurve(TC);
4639 else c2dBSP = Geom2dConvert::CurveToBSplineCurve(c2d);
4641 if (c2dBSP.IsNull()) continue;*/
4642 //gka fix for bug OCC12203 21.04.06 addition second curve for seam edges
4646 TopoDS_Edge secRev = TopoDS::Edge(sec.Reversed());
4648 c2d1 = BRep_Tool::CurveOnSurface(secRev, fac, first2d1, last2d1);
4649 if (c2d1.IsNull()) continue;
4651 /*if (c2d1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
4652 c2dBSP1 = Handle(Geom2d_BSplineCurve)::DownCast(c2d1);
4655 if (first > (c2d1->FirstParameter() + Precision::PConfusion()) ||
4656 last < (c2d1->LastParameter() - Precision::PConfusion())) {
4657 Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d1, first, last);
4658 //c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(TC);
4660 //else c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(c2d);
4665 /*first2d = c2dBSP->FirstParameter();
4666 last2d = c2dBSP->LastParameter();
4668 if(!c2dBSP1.IsNull()) {
4669 first2d1 = c2dBSP1->FirstParameter();
4670 last2d1 = c2dBSP1->LastParameter();
4673 // Update cutting sections
4674 Handle(Geom2d_Curve) c2dNew,c2d1New;
4675 TopTools_ListIteratorOfListOfShape ite(listEdge);
4676 for (; ite.More(); ite.Next()) {
4678 // Retrieve cutting section
4679 const TopoDS_Edge& edge = TopoDS::Edge(ite.Value());
4680 BRep_Tool::Range(edge, par1, par2);
4682 // Cut BSpline pcurve
4684 c2dNew = Handle(Geom2d_Curve)::DownCast(c2d->Copy());
4685 //c2dNew = Handle(Geom2d_Curve)::DownCast(c2dBSP->Copy());
4686 //Handle(Geom2d_BSplineCurve)::DownCast(c2dNew)->Segment(Max(first2d,par1),Min(par2,last2d));
4687 if(!c2d1.IsNull()) { //if(!c2dBSP1.IsNull()) {
4688 c2d1New = Handle(Geom2d_Curve)::DownCast(c2d1->Copy());
4689 //c2d1New = Handle(Geom2d_Curve)::DownCast(c2dBSP1->Copy());
4690 //Handle(Geom2d_BSplineCurve)::DownCast(c2d1New)->Segment(Max(first2d1,par1),Min(par2,last2d1));
4693 /*catch (Standard_Failure) {
4695 cout << "Exception in CreateSections: segment [" << par1 << "," << par2 << "]: ";
4696 Standard_Failure::Caught()->Print(cout); cout << endl;
4698 Handle(Geom2d_TrimmedCurve) c2dT = new Geom2d_TrimmedCurve(c2dNew,Max(first2d,par1),Min(par2,last2d));
4703 if(!isSeam && c2d1New.IsNull())
4704 aBuilder.UpdateEdge(edge, c2dNew, fac, tolEdge);
4706 TopAbs_Orientation Ori = edge.Orientation();
4707 if(fac.Orientation() == TopAbs_REVERSED)
4708 Ori = TopAbs::Reverse(Ori);
4710 if(Ori == TopAbs_FORWARD)
4711 aBuilder.UpdateEdge(edge, c2dNew,c2d1New ,fac, tolEdge);
4713 aBuilder.UpdateEdge(edge, c2d1New,c2dNew ,fac, tolEdge);
4719 //=======================================================================
4720 //function : SameParameterShape
4722 //=======================================================================
4724 void BRepBuilderAPI_Sewing::SameParameterShape()
4726 if (!mySameParameterMode) return;
4727 TopExp_Explorer exp(mySewedShape, TopAbs_EDGE);
4728 // Le flag sameparameter est a false pour chaque edge cousue
4729 for (; exp.More(); exp.Next()) {
4730 const TopoDS_Edge& sec = TopoDS::Edge(exp.Current());
4733 BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec));
4735 catch (Standard_Failure) {
4737 cout << "Fail: BRepBuilderAPI_Sewing::SameParameterShape exception in BRepLib::SameParameter" << endl;
4744 //=======================================================================
4745 //function : Inspect
4746 //purpose : Used for selection and storage of coinciding points
4747 //=======================================================================
4749 NCollection_CellFilter_Action BRepBuilderAPI_VertexInspector::Inspect (const Standard_Integer theTarget)
4751 /*gp_Pnt aPnt = gp_Pnt (myPoints.Value (theTarget - 1));
4752 if (aPnt.SquareDistance (gp_Pnt (myCurrent)) <= myTol)
4753 myResInd.Append (theTarget);*/
4755 const gp_XYZ& aPnt = myPoints.Value (theTarget - 1);
4756 Standard_Real aDx, aDy, aDz;
4757 aDx = myCurrent.X() - aPnt.X();
4758 aDy = myCurrent.Y() - aPnt.Y();
4759 aDz = myCurrent.Z() - aPnt.Z();
4761 if ((aDx*aDx <= myTol) && (aDy*aDy <= myTol) && (aDz*aDz <= myTol))
4762 myResInd.Append (theTarget);
4763 return CellFilter_Keep;
4766 //=======================================================================
4767 //function : Context
4769 //=======================================================================
4770 const Handle(BRepTools_ReShape)& BRepBuilderAPI_Sewing::GetContext() const
4775 //=======================================================================
4776 //function : SetContext
4778 //=======================================================================
4779 void BRepBuilderAPI_Sewing::SetContext(const Handle(BRepTools_ReShape)& theContext)
4781 myReShape = theContext;