0024002: Overall code and build procedure refactoring -- automatic
[occt.git] / src / BRepBuilderAPI / BRepBuilderAPI_Sewing.cxx
CommitLineData
b311480e 1// Created on: 1995-03-24
2// Created by: Jing Cheng MEI
3// Copyright (c) 1995-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
47980104 16
7fd59977 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
34
35
0d969553
Y
36//-- lbr April 1 97
37//-- dpf December 10 1997 Processing of pcurve collections
7fd59977 38
39//rln 02.02.99 BUC60449 Making compilable on NT in DEB mode
40//rln 02.02.99 BUC60449 Protection against exception on NT
41
42#define TEST 1
43
7fd59977 44
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>
42cf5bc1 51#include <BRep_ListOfPointRepresentation.hxx>
52#include <BRep_PointOnCurve.hxx>
7fd59977 53#include <BRep_Tool.hxx>
42cf5bc1 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>
7fd59977 59#include <BRepLib.hxx>
42cf5bc1 60#include <BRepTools.hxx>
7fd59977 61#include <BRepTools_Quilt.hxx>
42cf5bc1 62#include <BRepTools_ReShape.hxx>
7fd59977 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>
42cf5bc1 79#include <Geom_OffsetSurface.hxx>
80#include <Geom_RectangularTrimmedSurface.hxx>
7fd59977 81#include <Geom_Surface.hxx>
82#include <GeomAdaptor_Curve.hxx>
83#include <GeomAdaptor_Surface.hxx>
84#include <GeomLib.hxx>
85#include <gp_Pnt.hxx>
86#include <gp_Vec.hxx>
42cf5bc1 87#include <Message_ProgressIndicator.hxx>
88#include <Message_ProgressSentry.hxx>
89#include <NCollection_UBTreeFiller.hxx>
7fd59977 90#include <Precision.hxx>
91#include <Standard_ErrorHandler.hxx>
92#include <Standard_Failure.hxx>
42cf5bc1 93#include <Standard_NoSuchObject.hxx>
94#include <Standard_OutOfRange.hxx>
95#include <Standard_Type.hxx>
7fd59977 96#include <TColgp_Array1OfVec.hxx>
97#include <TColgp_SequenceOfPnt.hxx>
98#include <TColStd_Array1OfInteger.hxx>
99#include <TColStd_Array1OfReal.hxx>
42cf5bc1 100#include <TColStd_Array2OfReal.hxx>
7fd59977 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>
42cf5bc1 106#include <TColStd_MapIteratorOfMapOfInteger.hxx>
7fd59977 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>
42cf5bc1 114#include <TopoDS_Compound.hxx>
7fd59977 115#include <TopoDS_Edge.hxx>
42cf5bc1 116#include <TopoDS_Face.hxx>
7fd59977 117#include <TopoDS_Iterator.hxx>
118#include <TopoDS_Shape.hxx>
42cf5bc1 119#include <TopoDS_Shell.hxx>
7fd59977 120#include <TopoDS_Vertex.hxx>
121#include <TopoDS_Wire.hxx>
7fd59977 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>
7fd59977 132
42cf5bc1 133//#include <LocalAnalysis_SurfaceContinuity.hxx>
7fd59977 134//=======================================================================
135//function : SameRange
136//purpose :
137//=======================================================================
7fd59977 138Handle(Geom2d_Curve) BRepBuilderAPI_Sewing::SameRange(const Handle(Geom2d_Curve)& CurvePtr,
139 const Standard_Real FirstOnCurve,
140 const Standard_Real LastOnCurve,
141 const Standard_Real RequestedFirst,
142 const Standard_Real RequestedLast) const
143{
144 Handle(Geom2d_Curve) NewCurvePtr;
145 try {
146
147 GeomLib::SameRange(Precision::PConfusion(),CurvePtr,FirstOnCurve,LastOnCurve,
148 RequestedFirst,RequestedLast,NewCurvePtr);
149 }
150 catch (Standard_Failure) {
0797d9d3 151#ifdef OCCT_DEBUG
7fd59977 152 cout << "Exception in BRepBuilderAPI_Sewing::SameRange: ";
153 Standard_Failure::Caught()->Print(cout); cout << endl;
154#endif
155 }
156 return NewCurvePtr;
157}
158
159//=======================================================================
160//function : WhichFace
0d969553 161//purpose : Give the face whose edge is the border
7fd59977 162//=======================================================================
163
164TopoDS_Face BRepBuilderAPI_Sewing::WhichFace(const TopoDS_Edge& theEdg, const Standard_Integer index) const
165{
166 TopoDS_Shape bound = theEdg;
167 if (mySectionBound.IsBound(bound)) bound = mySectionBound(bound);
168 if (myBoundFaces.Contains(bound)) {
169 Standard_Integer i = 1;
170 TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bound));
171 for (; itf.More(); itf.Next(), i++)
172 if (i == index) return TopoDS::Face(itf.Value());
173 }
174 return TopoDS_Face();
175}
176
177//=======================================================================
178//function : IsClosedShape
179//purpose :
180//=======================================================================
181
182static Standard_Boolean IsClosedShape(const TopoDS_Shape& theshape,
183 const TopoDS_Shape& v1, const TopoDS_Shape& v2)
184{
185 Standard_Real TotLength = 0.0;
186 TopExp_Explorer aexp;
187 for (aexp.Init(theshape,TopAbs_EDGE); aexp.More(); aexp.Next()) {
188 TopoDS_Edge aedge = TopoDS::Edge(aexp.Current());
189 if (aedge.IsNull()) continue;
190 TopoDS_Vertex ve1,ve2;
191 TopExp::Vertices(aedge,ve1,ve2);
192 if (!ve1.IsSame(v1) && !ve1.IsSame(v2)) continue;
193 if (BRep_Tool::Degenerated(aedge)) continue;
194 Standard_Real first,last;
195 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aedge), first, last);
196 if (!c3d.IsNull()) {
197 GeomAdaptor_Curve cAdapt(c3d);
198 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
199 TotLength += length;
200 if (ve2.IsSame(v1) || ve2.IsSame(v2)) break;
201 }
202 }
203 if (TotLength > 0.0) {
204 gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(v1));
205 gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(v2));
c6541a0c 206 return (p1.Distance(p2) < TotLength/(1.2 * M_PI));
7fd59977 207 }
208 return Standard_False;
209}
210
211//=======================================================================
212//function : IsClosedByIsos
213//purpose :
214//=======================================================================
215static Standard_Boolean IsClosedByIsos(const Handle(Geom_Surface)& thesurf,
216 const Handle(Geom2d_Curve)& acrv2d,
217 const Standard_Real f2d,
218 const Standard_Real l2d,
219 const Standard_Boolean isUIsos)
220{
221 Standard_Boolean isClosed = Standard_False;
222
223 gp_Pnt2d psurf1 = (acrv2d->IsPeriodic() ?
224 acrv2d->Value(f2d) : acrv2d->Value(Max(f2d,acrv2d->FirstParameter())));
225 gp_Pnt2d psurf2 = (acrv2d->IsPeriodic() ?
226 acrv2d->Value(l2d) : acrv2d->Value(Min(l2d,acrv2d->LastParameter())));
227 Handle(Geom_Curve) aCrv1;
228 Handle(Geom_Curve) aCrv2;
229 if(isUIsos) {
230 aCrv1 = thesurf->UIso(psurf1.X());
231 aCrv2 = thesurf->UIso(psurf2.X());
232 }
233 else {
234 aCrv1 = thesurf->VIso(psurf1.Y());
235 aCrv2 = thesurf->VIso(psurf2.Y());
236 }
237 gp_Pnt p11,p1m,p12,p21,p2m,p22;
238 Standard_Real af1 = aCrv1->FirstParameter();
239 Standard_Real al1 = aCrv1->LastParameter();
240 Standard_Real af2 = aCrv2->FirstParameter();
241 Standard_Real al2 = aCrv2->LastParameter();
242 aCrv1->D0(af1,p11);
243 aCrv1->D0((af1+al1)*0.5,p1m);
244 aCrv1->D0(al1,p12);
245 aCrv2->D0(af2,p21);
246 aCrv2->D0((af2+al2)*0.5,p2m);
247 aCrv2->D0(al2,p22);
248 isClosed = (((p11.XYZ() - p12.XYZ()).Modulus() <
249 (p11.XYZ() - p1m.XYZ()).Modulus() - Precision::Confusion()) &&
250 ((p21.XYZ() - p22.XYZ()).Modulus() <
251 (p21.XYZ() - p2m.XYZ()).Modulus() - Precision::Confusion())) ;
252 return isClosed;
253}
254//=======================================================================
255//function : IsUClosedSurface
256//purpose :
257//=======================================================================
258
259Standard_Boolean BRepBuilderAPI_Sewing::IsUClosedSurface(const Handle(Geom_Surface)& surf,
260 const TopoDS_Shape& theEdge,
261 const TopLoc_Location& theloc) const
262{
263 Handle(Geom_Surface) tmpsurf = surf;
264 if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
265 tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
266 else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
267 tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
268 else {
269 Standard_Boolean isClosed = tmpsurf->IsUClosed();
270 if(!isClosed) {
271 Standard_Real f2d, l2d;
272 Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
273 if(!acrv2d.IsNull())
274 isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_False );
275
276 }
277 return isClosed;
278 }
279 return IsUClosedSurface(tmpsurf,theEdge,theloc);
280 //return surf->IsUClosed();
281}
282
283//=======================================================================
284//function : IsVClosedSurface
285//purpose :
286//=======================================================================
287
288Standard_Boolean BRepBuilderAPI_Sewing::IsVClosedSurface(const Handle(Geom_Surface)& surf,
289 const TopoDS_Shape& theEdge,
290 const TopLoc_Location& theloc) const
291{
292 Handle(Geom_Surface) tmpsurf = surf;
293 if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
294 tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
295 else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
296 tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
297 else {
298 Standard_Boolean isClosed = tmpsurf->IsVClosed();
299 if(!isClosed) {
300 Standard_Real f2d, l2d;
301 Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
302 if(!acrv2d.IsNull())
303 isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_True );
304 }
305 return isClosed;
306 }
307 return IsVClosedSurface(tmpsurf,theEdge,theloc);
308 //return surf->IsVClosed();
309}
310
311//=======================================================================
312//function : SameParameter
313//purpose : internal use
314//=======================================================================
315
316void BRepBuilderAPI_Sewing::SameParameter(const TopoDS_Edge& edge) const
317{
318 try {
319
320 BRepLib::SameParameter(edge);
321 }
322 catch (Standard_Failure) {
0797d9d3 323#ifdef OCCT_DEBUG
7fd59977 324 cout << "Exception in BRepBuilderAPI_Sewing::SameParameter: ";
325 Standard_Failure::Caught()->Print(cout); cout << endl;
326#endif
327 }
328}
329
330//=======================================================================
331//function : SameParameterEdge
332//purpose : internal use
333// Merge the Sequence Of Section on one edge.
334// This function keep the curve3d,curve2d,range and parametrization
335// from the first section, and report and made sameparameter the
336// pcurves of the other function.
337// This function works when the are not more than two Pcurves
338// on a same face.
339//=======================================================================
340
341TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Shape& edge,
342 const TopTools_SequenceOfShape& seqEdges,
343 const TColStd_SequenceOfInteger& seqForward,
344 TopTools_MapOfShape& mapMerged,
345 const Handle(BRepTools_ReShape)& locReShape)
346{
347 // Retrieve reference section
348 TopoDS_Shape aTmpShape = myReShape->Apply(edge); //for porting
349 TopoDS_Edge Edge1 = TopoDS::Edge(aTmpShape);
350 aTmpShape = locReShape->Apply(Edge1);
351 if (locReShape != myReShape) Edge1 = TopoDS::Edge(aTmpShape);
352 Standard_Boolean isDone = Standard_False;
353
354 // Create data structures for temporary merged edges
355 TopTools_ListOfShape listFaces1;
356 TopTools_MapOfShape MergedFaces;
357
358 if (mySewing) {
359
360 // Fill MergedFaces with faces of Edge1
361 TopoDS_Shape bnd1 = edge;
362 if (mySectionBound.IsBound(bnd1)) bnd1 = mySectionBound(bnd1);
363 if (myBoundFaces.Contains(bnd1)) {
364 TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bnd1));
365 for (; itf.More(); itf.Next())
366 if (MergedFaces.Add(itf.Value()))
367 listFaces1.Append(itf.Value());
368 }
369 }
370 else {
371
372 // Create presentation edge
373 TopoDS_Vertex V1, V2;
374 TopExp::Vertices(Edge1,V1,V2);
375 if (myVertexNode.Contains(V1)) V1 = TopoDS::Vertex(myVertexNode.FindFromKey(V1));
376 if (myVertexNode.Contains(V2)) V2 = TopoDS::Vertex(myVertexNode.FindFromKey(V2));
377
378 TopoDS_Edge NewEdge = Edge1;
379 NewEdge.EmptyCopy();
380
381 // Add the vertices
382 BRep_Builder aBuilder;
383 TopoDS_Shape anEdge = NewEdge.Oriented(TopAbs_FORWARD);
384 aBuilder.Add(anEdge,V1.Oriented(TopAbs_FORWARD));
385 aBuilder.Add(anEdge,V2.Oriented(TopAbs_REVERSED));
386
387 Edge1 = NewEdge;
388 }
389
390 Standard_Boolean isForward = Standard_True;
391
392 // Merge candidate sections
393 for (Standard_Integer i = 1; i <= seqEdges.Length(); i++) {
394
395 // Retrieve candidate section
396 TopoDS_Shape oedge2 = seqEdges(i);
397
398 if (mySewing) {
399
400 aTmpShape = myReShape->Apply(oedge2); //for porting
401 TopoDS_Edge Edge2 = TopoDS::Edge(aTmpShape);
402 aTmpShape = locReShape->Apply(Edge2);
403 if (locReShape != myReShape) Edge2 = TopoDS::Edge(aTmpShape);
404
405 // Calculate relative orientation
406 Standard_Integer Orientation = seqForward(i);
407 if (!isForward) Orientation = (Orientation? 0 : 1);
408
409 // Retrieve faces information for the second edge
410 TopoDS_Shape bnd2 = oedge2;
411 if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
412 if (!myBoundFaces.Contains(bnd2)) continue; // Skip floating edge
413 const TopTools_ListOfShape& listFaces2 = myBoundFaces.FindFromKey(bnd2);
414
415 Standard_Integer whichSec = 1; // Indicates on which edge the pCurve has been reported
416 TopoDS_Edge NewEdge = SameParameterEdge(Edge1,Edge2,listFaces1,listFaces2,Orientation,whichSec);
417 if (NewEdge.IsNull()) continue;
418
419 // Record faces information for the temporary merged edge
420 TopTools_ListIteratorOfListOfShape itf(listFaces2);
421 for (; itf.More(); itf.Next())
422 if (MergedFaces.Add(itf.Value()))
423 listFaces1.Append(itf.Value());
424
425 // Record merged section orientation
426 if (!Orientation && whichSec != 1)
427 isForward = isForward? Standard_False : Standard_True;
428 Edge1 = NewEdge;
429 }
430
431 // Append actually merged edge
432 mapMerged.Add(oedge2);
433 isDone = Standard_True;
434
435 if (!myNonmanifold) break;
436 }
437
438 if (isDone) {
439 // Change result orientation
440 Edge1.Orientation(isForward? TopAbs_FORWARD : TopAbs_REVERSED);
441 }
442 else Edge1.Nullify();
443
444 return Edge1;
445}
446
447//=======================================================================
448//function : SameParameterEdge
449//purpose : internal use
450//=======================================================================
451static Standard_Boolean findNMVertices(const TopoDS_Edge& theEdge,
452 TopTools_SequenceOfShape& theSeqNMVert,
453 TColStd_SequenceOfReal& theSeqPars)
454{
455 TopoDS_Iterator aItV(theEdge,Standard_False);
456 for( ; aItV.More(); aItV.Next()) {
457 if(aItV.Value().Orientation() == TopAbs_INTERNAL ||
458 aItV.Value().Orientation() == TopAbs_EXTERNAL)
459 theSeqNMVert.Append(aItV.Value());
460 }
461 Standard_Integer nbV = theSeqNMVert.Length();
462 if(!nbV)
463 return Standard_False;
464 Standard_Real first, last;
465 Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,first, last);
466 GeomAdaptor_Curve GAC(c3d);
467 Extrema_ExtPC locProj;
468 locProj.Initialize(GAC, first, last);
469 gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
470
471
472 for (Standard_Integer i = 1; i <= nbV; i++) {
473 TopoDS_Vertex aV = TopoDS::Vertex(theSeqNMVert.Value(i));
474 gp_Pnt pt = BRep_Tool::Pnt(aV);
475
476 Standard_Real distF2 = pfirst.SquareDistance(pt);
477 Standard_Real distL2 = plast.SquareDistance(pt);
478 Standard_Real apar = (distF2 > distL2 ? last : first);
479 // Project current point on curve
480 locProj.Perform(pt);
481 if (locProj.IsDone() && locProj.NbExt() > 0) {
482 Standard_Real dist2Min = Min(distF2,distL2);
483 Standard_Integer ind, indMin = 0;
484 for (ind = 1; ind <= locProj.NbExt(); ind++) {
485 Standard_Real dProj2 = locProj.SquareDistance(ind);
486 if (dProj2 < dist2Min) {
487 indMin = ind; dist2Min = dProj2;
488 }
489 }
490 if(indMin)
491 apar = locProj.Point(indMin).Parameter();
492
493 theSeqPars.Append(apar);
494
495 }
496 }
497 return Standard_True;
498}
499
93937391 500static void ComputeToleranceVertex(TopoDS_Vertex theV1, TopoDS_Vertex theV2,
501 TopoDS_Vertex& theNewV)
7fd59977 502{
93937391 503 Standard_Integer m, n;
504 Standard_Real aR[2], dR, aD, aEps;
505 TopoDS_Vertex aV[2];
506 gp_Pnt aP[2];
507 BRep_Builder aBB;
508 //
509 aEps = RealEpsilon();
510 aV[0] = theV1;
511 aV[1] = theV2;
512 for (m = 0; m < 2; ++m) {
513 aP[m] = BRep_Tool::Pnt(aV[m]);
514 aR[m] = BRep_Tool::Tolerance(aV[m]);
515 }
516 //
517 m=0; // max R
518 n=1; // min R
519 if (aR[0] < aR[1]) {
520 m=1;
521 n=0;
522 }
523 //
524 dR = aR[m] - aR[n]; // dR >= 0.
525 gp_Vec aVD(aP[m], aP[n]);
526 aD = aVD.Magnitude();
527 //
528 if (aD <= dR || aD < aEps) {
529 aBB.MakeVertex (theNewV, aP[m], aR[m]);
530 }
531 else {
532 Standard_Real aRr;
533 gp_XYZ aXYZr;
534 gp_Pnt aPr;
535 //
536 aRr = 0.5 * (aR[m] + aR[n] + aD);
537 aXYZr = 0.5 * (aP[m].XYZ() + aP[n].XYZ() - aVD.XYZ() * (dR/aD));
538 aPr.SetXYZ(aXYZr);
539 //
540 aBB.MakeVertex (theNewV, aPr, aRr);
541 }
542 return;
543}
544
545static void ComputeToleranceVertex(TopoDS_Vertex theV1, TopoDS_Vertex theV2,
546 TopoDS_Vertex theV3, TopoDS_Vertex& theNewV)
547{
548 Standard_Real aDi, aDmax;
549 gp_Pnt aCenter;
550 gp_Pnt aP[3];
551 Standard_Real aR[3];
552 TopoDS_Vertex aV[3];
553 gp_XYZ aXYZ(0.,0.,0.);
554 aV[0] = theV1;
555 aV[1] = theV2;
556 aV[2] = theV3;
557 for (Standard_Integer i = 0; i < 3; ++i) {
558 aP[i] = BRep_Tool::Pnt(aV[i]);
559 aR[i] = BRep_Tool::Tolerance(aV[i]);
560 aXYZ = aXYZ + aP[i].XYZ();
561 }
562 //
563 aXYZ.Divide(3.0);
564 aCenter.SetXYZ(aXYZ);
565 //
566 aDmax=-1.;
567 for ( Standard_Integer i = 0; i < 3; ++i) {
568 aDi = aCenter.Distance(aP[i]);
569 aDi += aR[i];
570 if (aDi > aDmax)
571 aDmax = aDi;
572 }
573
574 BRep_Builder aBB;
575 aBB.MakeVertex (theNewV, aCenter, aDmax);
576 return;
7fd59977 577}
2a739b6d 578
7fd59977 579TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirst,
580 const TopoDS_Edge& edgeLast,
581 const TopTools_ListOfShape& listFacesFirst,
582 const TopTools_ListOfShape& listFacesLast,
583 const Standard_Boolean secForward,
584 Standard_Integer& whichSec,
585 const Standard_Boolean firstCall)
586{
587 // Do not process floating edges
588 if (!listFacesFirst.Extent() || !listFacesLast.Extent()) return TopoDS_Edge();
589
590 // Sort input edges
591 TopoDS_Edge edge1, edge2;
592 if (firstCall) {
593 // Take the longest edge as first
594 Standard_Real f, l;
595 Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(TopoDS::Edge(edgeFirst), f, l);
596 GeomAdaptor_Curve cAdapt1(c3d1);
597 Standard_Real len1 = GCPnts_AbscissaPoint::Length(cAdapt1, f, l);
598 Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(TopoDS::Edge(edgeLast), f, l);
599 GeomAdaptor_Curve cAdapt2(c3d2);
600 Standard_Real len2 = GCPnts_AbscissaPoint::Length(cAdapt2, f, l);
601 if (len1 < len2) {
602 edge1 = edgeLast;
603 edge2 = edgeFirst;
604 whichSec = 2;
605 }
606 else {
607 edge1 = edgeFirst;
608 edge2 = edgeLast;
609 whichSec = 1;
610 }
611 }
612 else {
613 if (whichSec == 1) {
614 edge1 = edgeLast;
615 edge2 = edgeFirst;
616 whichSec = 2;
617 }
618 else {
619 edge1 = edgeFirst;
620 edge2 = edgeLast;
621 whichSec = 1;
622 }
623 }
624
625 Standard_Real first, last;
626 BRep_Tool::Range(edge1, first, last);
627 BRep_Builder aBuilder;
628
629 //To keep NM vertices on edge
630 TopTools_SequenceOfShape aSeqNMVert;
631 TColStd_SequenceOfReal aSeqNMPars;
632 findNMVertices(edge1,aSeqNMVert,aSeqNMPars);
633 findNMVertices(edge2,aSeqNMVert,aSeqNMPars);
634
635 // Create new edge
636 TopoDS_Edge edge;
637 aBuilder.MakeEdge(edge);
638 edge.Orientation( edge1.Orientation());
639
640
641 // Retrieve edge curve
642 TopLoc_Location loc3d;
643 Standard_Real first3d, last3d;
644 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge1, loc3d, first3d, last3d);
645 if (!loc3d.IsIdentity()) {
646 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
647 c3d->Transform(loc3d.Transformation());
648 }
649 aBuilder.UpdateEdge(edge,c3d,BRep_Tool::Tolerance(edge1));
650 aBuilder.Range(edge, first, last);
651 aBuilder.SameRange(edge, Standard_False); //Standard_True
652 aBuilder.SameParameter(edge, Standard_False);
653 // Create and add new vertices
654 {
655 TopoDS_Vertex V1New, V2New;
656
657 // Retrieve original vertices from edges
658 TopoDS_Vertex V11,V12,V21,V22;
659 TopExp::Vertices(edge1,V11,V12);
660 TopExp::Vertices(edge2,V21,V22);
661
67ffcad0
G
662 //check that edges merged valid way (for edges having length less than specified
663 //tolerance
9781f215
G
664 // Check if edges are closed
665 Standard_Boolean isClosed1 = V11.IsSame(V12);
666 Standard_Boolean isClosed2 = V21.IsSame(V22);
667 if(!isClosed1 && !isClosed2)
2028d00c 668 {
9781f215
G
669 if(secForward )
670 {
671 if( V11.IsSame(V22) || V12.IsSame(V21) )
672 return TopoDS_Edge();
673 }
674 else
675 {
676 if( V11.IsSame(V21) || V12.IsSame(V22) )
677 return TopoDS_Edge();
678 }
2028d00c
G
679 }
680
7fd59977 681 //szv: do not reshape here!!!
682 //V11 = TopoDS::Vertex(myReShape->Apply(V11));
683 //V12 = TopoDS::Vertex(myReShape->Apply(V12));
684 //V21 = TopoDS::Vertex(myReShape->Apply(V21));
685 //V22 = TopoDS::Vertex(myReShape->Apply(V22));
686
7fd59977 687 //Standard_Boolean isRev = Standard_False;
7fd59977 688 if (isClosed1 || isClosed2) {
689 // at least one of the edges is closed
690 if (isClosed1 && isClosed2) {
67ffcad0 691 // both edges are closed
93937391 692 ComputeToleranceVertex(V11, V21, V1New);
7fd59977 693 }
694 else if (isClosed1) {
67ffcad0 695 // only first edge is closed
93937391 696 ComputeToleranceVertex(V22, V21, V11, V1New);
7fd59977 697 }
698 else {
67ffcad0 699 // only second edge is closed
93937391 700 ComputeToleranceVertex(V11, V12, V21, V1New);
7fd59977 701 }
7fd59977 702 V2New = V1New;
703 }
704 else {
705 // both edges are open
67ffcad0
G
706 Standard_Boolean isOldFirst = ( secForward ? V11.IsSame(V21) : V11.IsSame(V22) );
707 Standard_Boolean isOldLast = ( secForward ? V12.IsSame(V22) : V12.IsSame(V21)) ;
7fd59977 708 if (secForward) {
67ffcad0
G
709 //case if vertices already sewed
710 if(!isOldFirst)
711 {
93937391 712 ComputeToleranceVertex(V11, V21, V1New);
67ffcad0
G
713 }
714 if(!isOldLast)
715 {
93937391 716 ComputeToleranceVertex(V12, V22, V2New);
67ffcad0 717 }
7fd59977 718 }
719 else {
67ffcad0
G
720 if(!isOldFirst)
721 {
93937391 722 ComputeToleranceVertex(V11, V22, V1New);
67ffcad0
G
723 }
724 if(!isOldLast)
725 {
93937391 726 ComputeToleranceVertex(V12, V21, V2New);
67ffcad0 727 }
7fd59977 728 }
93937391 729 if(isOldFirst)
67ffcad0 730 V1New = V11;
67ffcad0 731
93937391 732 if(isOldLast)
67ffcad0 733 V2New = V12;
7fd59977 734 }
7fd59977 735 // Add the vertices in the good sense
736 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
737 TopoDS_Shape aLocalEdge = V1New.Oriented(TopAbs_FORWARD); //(listNode.First()).Oriented(TopAbs_FORWARD);
738 aBuilder.Add(anEdge,aLocalEdge);
739 aLocalEdge = V2New.Oriented(TopAbs_REVERSED); //(listNode.Last()).Oriented(TopAbs_REVERSED);
740 aBuilder.Add(anEdge,aLocalEdge);
741
742 Standard_Integer k =1;
743 for( ; k <= aSeqNMVert.Length(); k++)
744 aBuilder.Add(anEdge,aSeqNMVert.Value(k));
745
746 }
747
748 // Retrieve second PCurves
749 TopLoc_Location loc2;
750 Handle(Geom_Surface) surf2;
47980104 751
7fd59977 752 //Handle(Geom2d_Curve) c2d2, c2d21;
753 // Standard_Real firstOld, lastOld;
754
755 TopTools_ListIteratorOfListOfShape itf2;
756 if (whichSec == 1) itf2.Initialize(listFacesLast);
757 else itf2.Initialize(listFacesFirst);
758 Standard_Boolean isResEdge = Standard_False;
0221b126 759 TopoDS_Face fac2;
7fd59977 760 for (; itf2.More(); itf2.Next()) {
761 Handle(Geom2d_Curve) c2d2, c2d21;
762 Standard_Real firstOld, lastOld;
0221b126 763 fac2 = TopoDS::Face(itf2.Value());
7fd59977 764
765 surf2 = BRep_Tool::Surface(fac2, loc2);
766 Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) &&
67ffcad0 767 BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2));
7fd59977 768 if (isSeam2) {
769 if (!myNonmanifold) return TopoDS_Edge();
770 TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting
771 c2d21 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac2, firstOld, lastOld);
772 }
773 c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld);
774 if (c2d2.IsNull() && c2d21.IsNull()) continue;
775
776 if (!c2d21.IsNull()) {
777 c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy());
778 if (!secForward) {
67ffcad0
G
779 if (c2d21->IsKind(STANDARD_TYPE(Geom2d_Line)))
780 c2d21 = new Geom2d_TrimmedCurve(c2d21, firstOld, lastOld);
781 Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
782 Standard_Real last2d = lastOld; //c2dTmp->LastParameter();
783 firstOld = c2d21->ReversedParameter(last2d);
784 lastOld = c2d21->ReversedParameter(first2d);
785 c2d21->Reverse();
7fd59977 786 }
787 c2d21 = SameRange(c2d21,firstOld,lastOld,first,last);
788 }
789
790 // Make second PCurve sameRange with the 3d curve
791 c2d2 = Handle(Geom2d_Curve)::DownCast(c2d2->Copy());
67ffcad0 792
7fd59977 793 if (!secForward) {
794 if (c2d2->IsKind(STANDARD_TYPE(Geom2d_Line)))
67ffcad0
G
795 c2d2 = new Geom2d_TrimmedCurve(c2d2, firstOld, lastOld);
796 Standard_Real first2d = firstOld;
797 Standard_Real last2d = lastOld;
7fd59977 798 firstOld = c2d2->ReversedParameter(last2d);
799 lastOld = c2d2->ReversedParameter(first2d);
800 c2d2->Reverse();
801 }
802
803 c2d2 = SameRange(c2d2,firstOld,lastOld,first,last);
804 if (c2d2.IsNull()) continue;
67ffcad0 805
7fd59977 806 // Add second PCurve
807 Standard_Boolean isSeam = Standard_False;
808 TopAbs_Orientation Ori = TopAbs_FORWARD;
809 //Handle(Geom2d_Curve) c2d1, c2d11;
810
811 TopTools_ListIteratorOfListOfShape itf1;
812 if (whichSec == 1) itf1.Initialize(listFacesFirst);
813 else itf1.Initialize(listFacesLast);
814 for (; itf1.More() && !isSeam; itf1.Next()) {
815 Handle(Geom2d_Curve) c2d1, c2d11;
816 const TopoDS_Face& fac1 = TopoDS::Face(itf1.Value());
817
818 TopLoc_Location loc1;
819 Handle(Geom_Surface) surf1 = BRep_Tool::Surface(fac1, loc1);
47980104 820
7fd59977 821 Standard_Real first2d, last2d;
822 Standard_Boolean isSeam1 = ((IsUClosedSurface(surf1,edge1,loc1) || IsVClosedSurface(surf1,edge1,loc1)) &&
67ffcad0 823 BRep_Tool::IsClosed(TopoDS::Edge(edge1),fac1));
7fd59977 824 c2d1 = BRep_Tool::CurveOnSurface(edge1, fac1, first2d, last2d);
825 Ori = edge1.Orientation();
826 if (fac1.Orientation() == TopAbs_REVERSED)
827 Ori = TopAbs::Reverse(Ori);
67ffcad0 828
7fd59977 829 if (isSeam1) {
67ffcad0 830 if (!myNonmanifold) return TopoDS_Edge();
7fd59977 831 TopoDS_Shape aTmpShape = edge1.Reversed(); //for porting
832 c2d11 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac1, first2d, last2d);
833 //if(fac1.Orientation() == TopAbs_REVERSED) //
834 if(Ori == TopAbs_FORWARD)
835 aBuilder.UpdateEdge(edge,c2d1,c2d11,fac1,0);
836 else
837 aBuilder.UpdateEdge(edge,c2d11,c2d1,fac1,0);
838 }
839 else aBuilder.UpdateEdge(edge,c2d1,fac1,0);
7fd59977 840
67ffcad0 841 if (c2d1.IsNull() && c2d11.IsNull()) continue;
7fd59977 842
843 if (surf2 == surf1) {
67ffcad0
G
844 // Merge sections which are on the same face
845 if (!loc2.IsDifferent(loc1)) {
846 Standard_Boolean uclosed = IsUClosedSurface(surf2,edge2,loc2);
847 Standard_Boolean vclosed = IsVClosedSurface(surf2,edge2,loc2);
848 if (uclosed || vclosed) {
849 Standard_Real pf = c2d1->FirstParameter();
850 // Standard_Real pl = c2d1->LastParameter();
851 gp_Pnt2d p1n = c2d1->Value(Max(first,pf));
852 // gp_Pnt2d p2n = c2d1->Value(Min(pl,last));
7fd59977 853 gp_Pnt2d p21n = c2d2->Value(Max(first,c2d2->FirstParameter()));
854 gp_Pnt2d p22n = c2d2->Value(Min(last,c2d2->LastParameter()));
855 Standard_Real aDist = Min(p1n.Distance(p21n), p1n.Distance(p22n));
67ffcad0
G
856 Standard_Real U1, U2, V1, V2;
857 surf2->Bounds(U1, U2, V1, V2);
858 isSeam = ((uclosed && aDist > 0.75*(fabs(U2-U1))) ||
859 (vclosed && aDist > 0.75*(fabs(V2-V1))));
7fd59977 860 if( !isSeam && BRep_Tool::IsClosed(TopoDS::Edge(edge),fac1)) continue;
67ffcad0
G
861 }
862 }
7fd59977 863 }
67ffcad0 864
7fd59977 865 isResEdge = Standard_True;
866 if (isSeam) {
867 if (Ori == TopAbs_FORWARD)
868 aBuilder.UpdateEdge(edge, c2d1, c2d2, surf2, loc2, Precision::Confusion());
869 else
870 aBuilder.UpdateEdge(edge, c2d2, c2d1, surf2, loc2, Precision::Confusion());
871 }
872 else if (isSeam2) {
873 TopAbs_Orientation InitOri = edge2.Orientation();
67ffcad0 874 TopAbs_Orientation SecOri = edge.Orientation();
7fd59977 875 if (fac2.Orientation() == TopAbs_REVERSED) {
67ffcad0 876
7fd59977 877 InitOri = TopAbs::Reverse(InitOri);
878 SecOri = TopAbs::Reverse(SecOri);
879 }
880 if(!secForward)
881 InitOri = TopAbs::Reverse(InitOri);
67ffcad0 882
7fd59977 883 if (InitOri == TopAbs_FORWARD)
884 aBuilder.UpdateEdge(edge, c2d2,c2d21, surf2, loc2, Precision::Confusion());
885 else
886 aBuilder.UpdateEdge(edge, c2d21,c2d2, surf2, loc2, Precision::Confusion());
887 }
888 else {
889 aBuilder.UpdateEdge(edge, c2d2, surf2, loc2, Precision::Confusion());
890 }
67ffcad0 891
7fd59977 892 }
893 }
47980104 894 Standard_Real tolReached = Precision::Infinite();
895 Standard_Boolean isSamePar = Standard_False;
2a739b6d 896 try
47980104 897 {
2a739b6d 898 if( isResEdge)
899 SameParameter(edge);
900
901
47980104 902 if( BRep_Tool::SameParameter(edge))
903 {
904 isSamePar = Standard_True;
905 tolReached = BRep_Tool::Tolerance(edge);
906 }
907 }
2a739b6d 908
909 catch(Standard_Failure)
910 {
911 isSamePar = Standard_False;
912 }
47980104 913
914
915 if (firstCall && ( !isResEdge || !isSamePar || tolReached > myTolerance)) {
7fd59977 916 Standard_Integer whichSecn = whichSec;
917 // Try to merge on the second section
47980104 918 Standard_Boolean second_ok = Standard_False;
7fd59977 919 TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast,
67ffcad0 920 secForward,whichSecn,Standard_False);
47980104 921 if( !s_edge.IsNull())
922 {
923 Standard_Real tolReached_2 = BRep_Tool::Tolerance(s_edge);
924 second_ok = ( BRep_Tool::SameParameter(s_edge) && tolReached_2 < tolReached );
925 if( second_ok)
926 {
927 edge = s_edge;
928 whichSec = whichSecn;
0221b126 929 tolReached = tolReached_2;
47980104 930 }
7fd59977 931 }
932
47980104 933 if (!second_ok && !edge.IsNull()) {
7fd59977 934
935 GeomAdaptor_Curve c3dAdapt(c3d);
936
937 // Discretize edge curve
0221b126 938 Standard_Integer i, j, nbp = 23;
2a739b6d 939 Standard_Real deltaT = (last3d - first3d) / (nbp -1);
7fd59977 940 TColgp_Array1OfPnt c3dpnt(1,nbp);
0221b126 941 for (i = 1; i <= nbp; i++)
2a739b6d 942 c3dpnt(i) = c3dAdapt.Value(first3d + (i-1)*deltaT);
7fd59977 943
0221b126 944 Standard_Real dist = 0., maxTol = -1.0;
7fd59977 945 Standard_Boolean more = Standard_True;
946
947 for (j = 1; more; j++) {
948 Handle(Geom2d_Curve) c2d2;
67ffcad0 949 BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j);
0221b126 950
67ffcad0
G
951 more = !c2d2.IsNull();
952 if (more) {
0221b126 953 Handle(Geom_Surface) aS = surf2;
954 if(!loc2.IsIdentity())
955 aS = Handle(Geom_Surface)::DownCast(surf2->Transformed ( loc2 ));
67ffcad0 956
0221b126 957 Standard_Real dist2 = 0.;
2a739b6d 958 deltaT = (last - first) / (nbp - 1);
67ffcad0 959 for (i = 1; i <= nbp; i++) {
2a739b6d 960 gp_Pnt2d aP2d = c2d2->Value(first + (i -1)*deltaT);
0221b126 961 gp_Pnt aP2(0.,0.,0.);
962 aS->D0(aP2d.X(),aP2d.Y(), aP2);
963 gp_Pnt aP1 = c3dpnt(i);
964 dist = aP2.SquareDistance(aP1);
965 if (dist > dist2)
966 dist2 = dist;
67ffcad0 967 }
0221b126 968 maxTol = Max(sqrt(dist2), Precision::Confusion());
67ffcad0 969 }
7fd59977 970 }
0221b126 971 if(maxTol >= 0. && maxTol < tolReached)
972 aBuilder.UpdateEdge(edge, maxTol);
7fd59977 973 aBuilder.SameParameter(edge,Standard_True);
974 }
975 }
976
977 BRepLib::EncodeRegularity(edge,0.01);
978 Standard_Real tolEdge1 = BRep_Tool::Tolerance(edge);
979 if (tolEdge1 > MaxTolerance()) edge.Nullify();
980 return edge;
981}
982
983//=======================================================================
984// function : EvaluateAngulars
985// purpose : internal use
986//=======================================================================
987
988void BRepBuilderAPI_Sewing::EvaluateAngulars(TopTools_SequenceOfShape& sequenceSec,
989 TColStd_Array1OfBoolean& secForward,
990 TColStd_Array1OfReal& tabAng,
991 const Standard_Integer indRef) const
992{
993 tabAng.Init(-1.0);
994
995 Standard_Integer i, j, npt = 4, lengSec = sequenceSec.Length();
996
997 TopoDS_Edge edge;
998 TopoDS_Face face;
999 TopLoc_Location loc;
1000 Standard_Real first, last;
1001 Handle(Geom_Curve) c3d;
1002 Handle(Geom2d_Curve) c2d;
1003 Handle(Geom_Surface) surf;
1004 TColgp_Array1OfVec normRef(1,npt);
1005
1006 for (i = indRef; i <= lengSec; i++) {
1007
1008 edge = TopoDS::Edge(sequenceSec(i));
1009
1010 TopoDS_Shape bnd = edge;
1011 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1012 if (myBoundFaces.Contains(bnd)) {
1013 face = TopoDS::Face(myBoundFaces.FindFromKey(bnd).First());
1014 surf = BRep_Tool::Surface(face,loc);
1015 if (!loc.IsIdentity()) {
1016 surf = Handle(Geom_Surface)::DownCast(surf->Copy());
1017 surf->Transform(loc.Transformation());
1018 }
1019 c2d = BRep_Tool::CurveOnSurface(edge, face, first, last);
1020 }
1021 else if (i == indRef) return;
1022 else continue;
1023
1024 c3d = BRep_Tool::Curve(edge, loc, first, last);
1025 if (!loc.IsIdentity()) {
1026 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1027 c3d->Transform(loc.Transformation());
1028 }
1029
1030 GeomAdaptor_Curve adapt(c3d);
1031 GCPnts_UniformAbscissa uniAbs(adapt, npt, first, last);
1032
1033 Standard_Real cumulateAngular = 0.0;
1034 Standard_Integer nbComputedAngle = 0;
1035
1036 for (j = 1; j <= npt; j++) {
1037 gp_Pnt2d P;
1038 c2d->D0(uniAbs.Parameter((secForward(i) || i == indRef)? j : npt-j+1),P);
1039 gp_Vec w1, w2;
1040 gp_Pnt unused;
1041 surf->D1(P.X(), P.Y(), unused, w1, w2);
1042 gp_Vec n = w1^w2; // Compute the normal vector
1043 if (i == indRef) normRef(j) = n;
1044 else if ((n.Magnitude()>gp::Resolution()) && (normRef(j).Magnitude()>gp::Resolution())) {
1045 nbComputedAngle++;
1046 Standard_Real angular = n.Angle(normRef(j));
c6541a0c 1047 if (angular > M_PI/2.) angular = M_PI - angular;
7fd59977 1048 cumulateAngular += angular;
1049 }
1050 }
1051
1052 if (nbComputedAngle)
1053 tabAng(i) = cumulateAngular/((Standard_Real)nbComputedAngle);
1054 }
1055}
1056
1057//=======================================================================
1058// function : EvaluateDistances
1059// purpose : internal use
1060// Evaluate distance beetween edges with indice indRef and the following edges in the list
1061// Remarks (lengSec - indRef) must be >= 1
1062//=======================================================================
7fd59977 1063void BRepBuilderAPI_Sewing::EvaluateDistances(TopTools_SequenceOfShape& sequenceSec,
1064 TColStd_Array1OfBoolean& secForward,
1065 TColStd_Array1OfReal& tabDst,
1066 TColStd_Array1OfReal& arrLen,
1067 TColStd_Array1OfReal& tabMinDist,
1068 const Standard_Integer indRef) const
1069{
1070 secForward.Init(Standard_True);
1071 tabDst.Init(-1.0);
1072 arrLen.Init(0.);
2028d00c 1073 tabMinDist.Init(Precision::Infinite());
7fd59977 1074 const Standard_Integer npt = 8; // Number of points for curve discretization
1075 TColgp_Array1OfPnt ptsRef(1, npt), ptsSec(1, npt);
1076
1077 Standard_Integer i, j, lengSec = sequenceSec.Length();
1078 TColgp_SequenceOfPnt seqSec;
1079
1080 Handle(Geom_Curve) c3dRef;
1081 Standard_Real firstRef=0., lastRef=0.;
67ffcad0 1082
7fd59977 1083 for (i = indRef; i <= lengSec; i++) {
1084
1085 // reading of the edge (attention for the first one: reference)
1086 const TopoDS_Edge& sec = TopoDS::Edge(sequenceSec(i));
1087
1088 TopLoc_Location loc;
1089 Standard_Real first, last;
1090 Handle(Geom_Curve) c3d = BRep_Tool::Curve(sec, loc, first, last);
de10d8b1 1091 if (c3d.IsNull()) continue;
7fd59977 1092 if (!loc.IsIdentity()) {
1093 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1094 c3d->Transform(loc.Transformation());
1095 }
1096
1097 if (i == indRef) {
1098 c3dRef = c3d; firstRef = first; lastRef = last;
1099 }
1100
2028d00c 1101 Standard_Real dist = Precision::Infinite(), distFor = -1.0, distRev = -1.0;
7fd59977 1102 Standard_Real aMinDist = Precision::Infinite();
1103
1104 Standard_Real T, deltaT = (last - first) / (npt - 1);
1105 Standard_Real aLenSec2 = 0.;
67ffcad0
G
1106
1107 Standard_Integer nbFound = 0;
7fd59977 1108 for (j = 1; j <= npt; j++) {
1109
1110 // Uniform parameter on curve
1111 if (j == 1) T = first;
1112 else if (j == npt) T = last;
1113 else T = first + (j - 1) * deltaT;
1114
1115 // Take point on curve
1116 gp_Pnt pt = c3d->Value(T);
2028d00c 1117
7fd59977 1118 if (i == indRef) {
1119 ptsRef(j) = pt;
2028d00c
G
1120 if(j > 1)
1121 aLenSec2 += pt.SquareDistance(ptsRef(j-1));
7fd59977 1122 }
1123 else {
1124 ptsSec(j) = pt;
1125 //protection to avoid merging with small sections
2028d00c 1126 if(j > 1)
7fd59977 1127 aLenSec2 += pt.SquareDistance(ptsSec(j-1));
1128 // To evaluate mutual orientation and distance
1129 dist = pt.Distance(ptsRef(j));
1130 if(aMinDist > dist)
1131 aMinDist = dist;
1132 if (distFor < dist) distFor = dist;
1133 dist = pt.Distance(ptsRef(npt-j+1));
2028d00c 1134
7fd59977 1135 if(aMinDist > dist)
1136 aMinDist = dist;
1137 if (distRev < dist) distRev = dist;
2028d00c
G
1138
1139 // Check that point lays between vertices of reference curve
1140 const gp_Pnt &p11 = ptsRef(1);
1141 const gp_Pnt &p12 = ptsRef(npt);
1142 const gp_Vec aVec1(pt,p11);
1143 const gp_Vec aVec2(pt,p12);
1144 const gp_Vec aVecRef(p11,p12);
1145 if((aVecRef * aVec1) * (aVecRef * aVec2) < 0.)
1146 nbFound++;
7fd59977 1147 }
1148 }
1149
1150 Standard_Real aLenSec = sqrt(aLenSec2);
1151
1152 //if(aLenSec < myMinTolerance )
1153 // continue;
1154 arrLen.SetValue(i,aLenSec);
1155 // Record mutual orientation
1156 Standard_Boolean isForward = (distFor < distRev); //szv debug: <=
1157 secForward(i) = isForward;
1158
1159 dist = (isForward? distFor : distRev);
2028d00c
G
1160 if(i == indRef || (dist < myTolerance && nbFound >= npt * 0.5) )
1161 {
7fd59977 1162 tabDst(i) = dist;
1163 tabMinDist(i) = aMinDist;
7fd59977 1164 }
2028d00c
G
1165 else
1166 {
1167 nbFound = 0, aMinDist = Precision::Infinite(), dist = -1;
1168 TColgp_Array1OfPnt arrProj(1, npt);
1169 TColStd_Array1OfReal arrDist(1, npt), arrPara(1, npt);
1170 if( arrLen(indRef) >= arrLen(i))
1171 ProjectPointsOnCurve(ptsSec,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1172 else
1173 ProjectPointsOnCurve(ptsRef,c3d,first,last,arrDist,arrPara,arrProj,Standard_False);
1174 for( j = 1; j <= npt; j++ )
1175 {
2c896b8f 1176 if(arrDist(j) < 0.)
2028d00c
G
1177 continue;
1178 if(dist < arrDist(j))
1179 dist = arrDist(j);
1180 if( aMinDist > arrDist(j))
1181 aMinDist = arrDist(j);
1182 nbFound++;
1183 }
1184 if(nbFound > 1)
1185 {
1186 tabDst(i) = dist;
1187 tabMinDist(i) = aMinDist;
1188 }
7fd59977 1189 }
1190 }
1191
2028d00c 1192 /*
7fd59977 1193 // Project distant points
1194 Standard_Integer nbFailed = seqSec.Length();
1195 if (!nbFailed) return;
1196
1197 TColgp_Array1OfPnt arrPnt(1, nbFailed), arrProj(1, nbFailed);
1198 for (i = 1; i <= nbFailed; i++) arrPnt(i) = seqSec(i); seqSec.Clear();
1199 TColStd_Array1OfReal arrDist(1, nbFailed), arrPara(1, nbFailed);
1200
2028d00c 1201 ProjectPointsOnCurve(arrPnt,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
7fd59977 1202
1203 // Process distant sections
1204 Standard_Integer idx1 = 1;
1205 for (i = indRef + 1; i <= lengSec; i++) {
1206
1207 // Skip section if already evaluated
1208 if (tabDst(i) >= 0.0) continue;
1209
1210 Standard_Real dist, distMax = -1.0, aMinDist = Precision::Infinite();
1211
1212 Standard_Integer idx2 = (idx1 - 1)*npt;
1213
1214 for (j = 1; j <= npt; j++) {
1215
1216 dist = arrDist(idx2 + j);
1217 // If point is not projected - stop evaluation
1218 if (dist < 0.0) { distMax = -1.0; break; }
1219 if (distMax < dist) distMax = dist;
1220 if(aMinDist > dist) aMinDist = dist;
1221 }
1222
1223 // If section is close - record distance
1224 if (distMax >= 0.0) {
1225 if (secForward(i)) {
1226 dist = arrPnt(idx2+1).Distance(ptsRef(1));
1227 if (distMax < dist) distMax = dist;
1228 if(aMinDist > dist) aMinDist = dist;
1229 dist = arrPnt(idx2+npt).Distance(ptsRef(npt));
1230 if (distMax < dist) distMax = dist;
1231 if(aMinDist > dist) aMinDist = dist;
1232 }
1233 else {
1234 dist = arrPnt(idx2+1).Distance(ptsRef(npt));
1235 if (distMax < dist) distMax = dist;
1236 if(aMinDist > dist) aMinDist = dist;
1237 dist = arrPnt(idx2+npt).Distance(ptsRef(1));
1238 if (distMax < dist) distMax = dist;
1239 if(aMinDist > dist) aMinDist = dist;
1240 }
1241
1242 if (distMax < myTolerance)
1243 {
1244 tabDst(i) = distMax;
1245 tabMinDist(i) = aMinDist;
1246 }
1247 }
1248
1249 idx1++; // To the next distant curve
2028d00c 1250 }*/
7fd59977 1251}
1252
1253//=======================================================================
1254//function : IsMergedClosed
1255//purpose : internal use
1256//=======================================================================
1257
1258Standard_Boolean BRepBuilderAPI_Sewing::IsMergedClosed(const TopoDS_Edge& Edge1,
1259 const TopoDS_Edge& Edge2,
1260 const TopoDS_Face& face) const
1261{
1262 // Check for closed surface
1263 TopLoc_Location loc;
1264 Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc);
1265 Standard_Boolean isUClosed = IsUClosedSurface(surf,Edge1,loc);
1266 Standard_Boolean isVClosed = IsVClosedSurface(surf,Edge1,loc);
1267 if (!isUClosed && !isVClosed) return Standard_False;
1268 // Check condition on closed surface
1269 /*
1270 Standard_Real first1,last1,first2,last2;
1271 Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(Edge1,first1,last1);
1272 Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(Edge2,first2,last2);
1273 if (C3d1.IsNull() || C3d2.IsNull()) return Standard_False;
1274 */
1275 Standard_Real first2d1,last2d1,first2d2,last2d2;
1276 Handle(Geom2d_Curve) C2d1 = BRep_Tool::CurveOnSurface(Edge1,face,first2d1,last2d1);
1277 Handle(Geom2d_Curve) C2d2 = BRep_Tool::CurveOnSurface(Edge2,face,first2d2,last2d2);
1278 if (C2d1.IsNull() || C2d2.IsNull()) return Standard_False;
1279 /*
1280 gp_Pnt p1 = C3d1->Value(0.5*(first1 + last1));
1281 gp_Pnt p2 = C3d1->Value(0.5*(first2 + last2));
1282 Standard_Real dist = p1.Distance(p2);
1283 gp_Pnt2d p12d = C2d1->Value(0.5*(first2d1 + last2d1));
1284 gp_Pnt2d p22d = C2d1->Value(0.5*(first2d2 + last2d2));
1285 Standard_Real dist2d = p12d.Distance(p22d);
1286 GeomAdaptor_Surface Ads(BRep_Tool::Surface(face));
1287 Standard_Real distSurf = Max(Ads.UResolution(dist), Ads.VResolution(dist));
1288 return (dist2d*0.2 >= distSurf);
1289 */
1290 Standard_Integer isULongC1, isULongC2, isVLongC1, isVLongC2;
1291 Standard_Real SUmin, SUmax, SVmin, SVmax;
1292 Standard_Real C1Umin, C1Vmin, C1Umax, C1Vmax;
1293 Standard_Real C2Umin, C2Vmin, C2Umax, C2Vmax;
1294 { //szv: Use brackets to destroy local variables
1295 Bnd_Box2d B1, B2;
1296 Geom2dAdaptor_Curve aC2d1(C2d1), aC2d2(C2d2);
1297 BndLib_Add2dCurve::Add(aC2d1,first2d1,last2d1,Precision::PConfusion(),B1);
1298 BndLib_Add2dCurve::Add(aC2d2,first2d2,last2d2,Precision::PConfusion(),B2);
1299 B1.Get(C1Umin,C1Vmin,C1Umax,C1Vmax);
1300 B2.Get(C2Umin,C2Vmin,C2Umax,C2Vmax);
1301 Standard_Real du, dv;
1302 du = (C1Umax - C1Umin); dv = (C1Vmax - C1Vmin);
1303 isULongC1 = (dv <= du); isVLongC1 = (du <= dv);
1304 du = (C2Umax - C2Umin); dv = (C2Vmax - C2Vmin);
1305 isULongC2 = (dv <= du); isVLongC2 = (du <= dv);
1306 surf->Bounds(SUmin,SUmax,SVmin,SVmax);
1307 }
1308 if (isUClosed && isVLongC1 && isVLongC2) {
1309 // Do not merge if not overlapped by V
1310 Standard_Real dist = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1311 if (dist < 0.0) {
1312 Standard_Real distInner = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1313 Standard_Real distOuter = (SUmax - SUmin) - Max((C2Umax - C1Umin),(C1Umax - C2Umin));
1314 if (distOuter <= distInner) return Standard_True;
1315 }
1316 }
1317 if (isVClosed && isULongC1 && isULongC2) {
1318 // Do not merge if not overlapped by U
1319 Standard_Real dist = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1320 if (dist < 0.0) {
1321 Standard_Real distInner = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1322 Standard_Real distOuter = (SVmax - SVmin) - Max((C2Vmax - C1Vmin),(C1Vmax - C2Vmin));
1323 if (distOuter <= distInner) return Standard_True;
1324 }
1325 }
1326 return Standard_False;
1327}
1328
1329//=======================================================================
1330//function : AnalysisNearestEdges
1331//purpose :
1332//=======================================================================
1333
1334void BRepBuilderAPI_Sewing::AnalysisNearestEdges(const TopTools_SequenceOfShape& sequenceSec,
1335 TColStd_SequenceOfInteger& seqIndCandidate,
1336 TColStd_SequenceOfInteger& seqOrientations,
1337 const Standard_Boolean evalDist)
1338{
1339
1340 Standard_Integer workIndex = seqIndCandidate.First();
1341 TopoDS_Shape workedge = sequenceSec.Value(workIndex);
1342 TopoDS_Shape bnd = workedge;
1343 TopTools_ListOfShape workfaces;
1344 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1345 if (myBoundFaces.Contains(bnd))
1346 workfaces = myBoundFaces.FindFromKey(bnd);
1347 if(workfaces.IsEmpty()) return;
1348 TopTools_MapOfShape mapFaces;
1349 TopTools_ListIteratorOfListOfShape lIt;
1350 for (lIt.Initialize(workfaces); lIt.More(); lIt.Next())
1351 mapFaces.Add(lIt.Value());
1352 TColStd_SequenceOfInteger seqNotCandidate;
1353 TColStd_SequenceOfInteger seqNewForward;
1354 // Separates edges belonging the same face as work edge
1355 // for exception of edges belonging closed faces
1356
1357 seqNotCandidate.Append(workIndex);
1358 for(Standard_Integer i = 1; i<= seqIndCandidate.Length(); ) {
1359 Standard_Integer index = seqIndCandidate.Value(i);
1360 Standard_Boolean isRemove = Standard_False;
1361 if(index == workIndex) {
1362 seqIndCandidate.Remove(i);
1363 seqOrientations.Remove(i);
1364 isRemove = Standard_True;
1365 }
1366 if(!isRemove) {
1367 TopoDS_Shape bnd2 = sequenceSec.Value(index);
1368 if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
1369
1370 if(myBoundFaces.Contains(bnd2)) {
1371 const TopTools_ListOfShape& listfaces = myBoundFaces.FindFromKey(bnd2);
1372 Standard_Boolean isMerged = Standard_True;
1373 for (lIt.Initialize(listfaces); lIt.More() && isMerged; lIt.Next()) {
1374 if(mapFaces.Contains(lIt.Value())) {
1375 TopLoc_Location loc;
1376 Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(lIt.Value()),loc);
1377 isMerged = ((IsUClosedSurface(surf,bnd2,loc) || IsVClosedSurface(surf,bnd2,loc)) &&
1378 IsMergedClosed(TopoDS::Edge(sequenceSec.Value(index)),TopoDS::Edge(workedge),TopoDS::Face(lIt.Value())));
1379 }
1380 }
1381 if(!isMerged) {
1382 seqNotCandidate.Append(index);
1383 seqIndCandidate.Remove(i);
1384 seqOrientations.Remove(i);
1385 isRemove = Standard_True;
1386 }
1387 }
1388 else {
1389 seqIndCandidate.Remove(i);
1390 seqOrientations.Remove(i);
1391 isRemove = Standard_True;
1392 }
1393 }
1394 if(!isRemove) i++;
1395 }
1396 if(seqIndCandidate.Length() == 0 || seqNotCandidate.Length() == 1) return;
1397 if(!evalDist) return;
1398 TColStd_Array2OfReal TotTabDist(1,seqNotCandidate.Length(),1,seqIndCandidate.Length());
1399 TColStd_MapOfInteger MapIndex;
1400 TColStd_SequenceOfInteger seqForward;
1401
1402 // Definition and removing edges wich are not candidate for work edge
1403 // ( they have other nearest edges belonging to the work face)
1404 for(Standard_Integer k = 1; k<= seqNotCandidate.Length(); k++) {
1405 Standard_Integer index1 = seqNotCandidate.Value(k);
1406 TopoDS_Shape edge = sequenceSec.Value(index1);
1407 TopTools_SequenceOfShape tmpSeq;
1408 tmpSeq.Append(edge);
1409 for(Standard_Integer kk = 1; kk <= seqIndCandidate.Length();kk++)
1410 tmpSeq.Append(sequenceSec.Value(seqIndCandidate.Value(kk)));
1411
1412 Standard_Integer lengSec = tmpSeq.Length();
1413 TColStd_Array1OfBoolean tabForward(1,lengSec);
1414 TColStd_Array1OfReal tabDist(1,lengSec);
1415 TColStd_Array1OfReal arrLen(1,lengSec);
1416 TColStd_Array1OfReal tabMinDist(1,lengSec);
1417 for (Standard_Integer i1 = 1 ; i1 <= lengSec; i1++)
1418 tabDist(i1) =-1;
1419
1420 EvaluateDistances(tmpSeq,tabForward, tabDist,arrLen,tabMinDist,1 );
1421 if(k == 1) {
1422 for(Standard_Integer n = 1; n < lengSec; n++) {
1423 if(tabDist(n+1) == -1 || tabDist(n+1) > myTolerance) {
1424 MapIndex.Add(n);
1425 continue;
1426 }
1427 TotTabDist(k,n) = tabDist(n+1 );
1428 seqForward.Append(tabForward(n+1) ? 1:0);
1429 }
1430 }
1431 else {
1432 for(Standard_Integer n = 1; n < lengSec; n++) {
1433 if(tabDist(n) == -1 || tabDist(n) > myTolerance) continue;
1434 if(tabDist(n+1) < TotTabDist(1,n)) {
1435 MapIndex.Add(n);
1436 }
1437 }
1438 }
1439
1440 }
1441
1442 Standard_Integer i2 = seqIndCandidate.Length();
1443 for( ; i2 >=1 ; i2--)
1444 {
1445 if(MapIndex.Contains(i2))
1446 {
1447 seqIndCandidate.Remove(i2);
1448 seqOrientations.Remove(i2);
1449 }
1450
1451 }
1452 //for(TColStd_MapIteratorOfMapOfInteger IMap(MapIndex); IMap.More(); IMap.Next()) {
1453 // seqIndCandidate.Remove(IMap.Key());
1454 // seqOrientations.Remove(IMap.Key());
1455 //}
1456}
1457
1458//=======================================================================
1459//function : FindCandidates
1460//purpose : internal use
1461//=======================================================================
1462
1463Standard_Boolean BRepBuilderAPI_Sewing::FindCandidates(TopTools_SequenceOfShape& seqSections,
1464 TColStd_IndexedMapOfInteger& mapReference,
1465 TColStd_SequenceOfInteger& seqCandidates,
1466 TColStd_SequenceOfInteger& seqOrientations)
1467{
1468 Standard_Integer i, nbSections = seqSections.Length();
1469 if(nbSections <= 1)
1470 return Standard_False;
1471 // Retrieve last reference index
1472 Standard_Integer indReference = mapReference(mapReference.Extent());
1473 Standard_Integer nbCandidates = 0;
1474 TopTools_MapOfShape Faces1;
1475 //if (nbSections > 1) {
1476
1477 TopoDS_Edge Edge1 = TopoDS::Edge(seqSections(indReference));
1478
1479 // Retrieve faces for reference section
1480
1481 { //szv: Use brackets to destroy local variables
1482 TopoDS_Shape bnd = Edge1;
1483 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1484 if (myBoundFaces.Contains(bnd)) {
1485 TopTools_ListIteratorOfListOfShape itf1(myBoundFaces.FindFromKey(bnd));
1486 for (; itf1.More(); itf1.Next()) Faces1.Add(itf1.Value());
1487 }
1488 }
1489
1490 // Check merging conditions for candidates and remove unsatisfactory
1491 TopTools_SequenceOfShape seqSectionsNew;
1492 TColStd_SequenceOfInteger seqCandidatesNew;
1493 for (i = 1; i <= nbSections; i++) {
1494 if (i == indReference) {
1495 seqSectionsNew.Prepend(Edge1);
1496 seqCandidatesNew.Prepend(i);
1497 }
1498 else {
1499 const TopoDS_Edge& Edge2 = TopoDS::Edge(seqSections(i));
7fd59977 1500 seqSectionsNew.Append(Edge2);
1501 seqCandidatesNew.Append(i);
7fd59977 1502 }
1503 }
1504
1505 Standard_Integer nbSectionsNew = seqSectionsNew.Length();
1506 if (nbSectionsNew > 1) {
5a29f57e 1507
7fd59977 1508 // Evaluate distances between reference and other sections
1509 TColStd_Array1OfBoolean arrForward(1,nbSectionsNew);
1510 TColStd_Array1OfReal arrDistance(1,nbSectionsNew);
1511 TColStd_Array1OfReal arrLen(1,nbSectionsNew);
1512 TColStd_Array1OfReal arrMinDist(1,nbSectionsNew);
1513 EvaluateDistances(seqSectionsNew,arrForward,arrDistance,arrLen,arrMinDist,1);
5a29f57e 1514
7fd59977 1515 // Fill sequence of candidate indices sorted by distance
1516 for (i = 2; i <= nbSectionsNew; i++) {
5a29f57e 1517 Standard_Real aMaxDist = arrDistance(i);
1518 if (aMaxDist >= 0.0 && aMaxDist <= myTolerance && arrLen(i) > myMinTolerance) {
1519
7fd59977 1520 // Reference section is connected to section #i
1521 Standard_Boolean isInserted = Standard_False;
1522 Standard_Integer j, ori = (arrForward(i)? 1 : 0);
1523 for (j = 1; (j <= seqCandidates.Length()) && !isInserted; j++) {
7fd59977 1524 Standard_Real aDelta = arrDistance(i) - arrDistance(seqCandidates.Value(j));
5a29f57e 1525
7fd59977 1526 if( aDelta < Precision::Confusion()) {
1527
1528 if(fabs(aDelta) > RealSmall() ||
1529 arrMinDist(i) < arrMinDist(seqCandidates.Value(j)))
1530 {
1531 seqCandidates.InsertBefore(j,i);
1532 seqOrientations.InsertBefore(j,ori);
1533 isInserted = Standard_True;
1534 }
1535 }
1536 }
1537 if (!isInserted) {
1538 seqCandidates.Append(i);
1539 seqOrientations.Append(ori);
1540 }
1541 }
1542 }
5a29f57e 1543
7fd59977 1544 nbCandidates = seqCandidates.Length();
5a29f57e 1545 if (!nbCandidates)
1546 return Standard_False; // Section has no candidates to merge
1547
1548 // Replace candidate indices
1549
7fd59977 1550 for (i = 1; i <= nbCandidates; i++)
1551 seqCandidates(i) = seqCandidatesNew(seqCandidates(i));
5a29f57e 1552
7fd59977 1553 }
5a29f57e 1554
7fd59977 1555 if (!nbCandidates) return Standard_False; // Section has no candidates to merge
1556
1557 if (myNonmanifold && nbCandidates >1) {
1558 TColStd_SequenceOfInteger seqNewCandidates;
1559 TColStd_SequenceOfInteger seqOrientationsNew;
1560 seqCandidates.Prepend(1);
1561 seqOrientations.Prepend(1);
1562 for(Standard_Integer k = 1; k <= seqSections.Length() && seqCandidates.Length() > 1 ; k++) {
1563 AnalysisNearestEdges(seqSections,seqCandidates,seqOrientations,(k==1));
1564 if(k == 1 && !seqCandidates.Length()) return Standard_False;
1565 if(seqCandidates.Length()) {
1566 seqNewCandidates.Append(seqCandidates.First());
1567 seqOrientationsNew.Append(seqOrientations.First());
1568 }
1569 }
1570 seqCandidates.Prepend(seqNewCandidates);
1571 seqOrientations.Prepend(seqOrientationsNew);
1572 return Standard_True;
1573 }
1574 else {
1575
1576 // For manifold case leave only one candidate from equidistant candidates
1577 /*Standard_Integer minIndex = seqCandidateIndex.First();
1578 Standard_Real minDistance = arrDistance(minIndex);
1579
1580 // Find equidistant candidates
1581 TColStd_SequenceOfInteger seqEqDistantIndex; seqEqDistantIndex.Append(1);
1582 for (i = 2; i <= nbCandidates; i++) {
1583 Standard_Integer index = seqCandidateIndex(i);
1584 if (Abs(minDistance - arrDistance(index)) <= Precision::Confusion())
1585 seqEqDistantIndex.Append(index);
1586 }
1587
1588 Standard_Integer eqLen = seqEqDistantIndex.Length();
1589 if (eqLen > 2) {
1590
1591 // Fill map of faces which equidistant sections belong to
1592 TopTools_MapOfShape mapFace;
1593 for (i = 1; i <= eqLen; i++) {
1594 Standard_Integer index = seqEqDistantIndex.Value(i);
1595 if (isCandidate(index)) {
1596 mapFace.Add(arrFace(index));
1597 }
1598 }
1599
1600 // Non Manifold case
1601 // Edges are merged by pair among a face continuity C1 criterion
1602 if (mapFace.Extent() == eqLen) {
1603
1604 tabDist.Init(-1);
1605 tabMinInd.Init(-1);
1606 min=10000000.;
1607 //indMin = -1;
1608 Standard_Integer indMin = -1;// To check if the edge can be merged.
1609 // Computation of distances between the edges.
1610 TopTools_SequenceOfShape seqSh;
1611 Standard_Integer nbInd = EqDistSeq.Length();
1612 TColStd_Array1OfBoolean tmptabForward(1,nbInd);
1613 seqSh.Append(sequenceSec.Value(1));
1614 for (j = 2; j <= EqDistSeq.Length(); j++) {
1615 Standard_Integer index = EqDistSeq.Value(j);
1616 tmptabForward(j) = tabForward(index);
1617 seqSh.Append(sequenceSec.Value(index));
1618 }
1619
1620 EvaluateAngulars(seqSh, tmptabForward, tabDist,1);
1621
1622 for(j=2; j <= seqSh.Length(); j++) {
1623 if (tabDist(j) > -1.) { // if edge(j) is connected to edge(i)
1624 if (min > tabDist(j)) {
1625 min = tabDist(j);
1626 indMin = j;
1627 }
1628 }
1629 }
1630
1631 // Construct minDist, tabMinInd , tabMinForward(i) = tabForward(j);
1632 if (indMin > 0) {
1633 seqSh.Remove(indMin);
1634 for(j =2; j <= tmpSeq.Length(); ) {
1635 TopoDS_Shape sh = tmpSeq.Value(j);
1636 Standard_Boolean isRem = Standard_False;
1637 for(Standard_Integer k = 1; k<= seqSh.Length();k++) {
1638 if(seqSh.Value(k) == sh) {
1639 isRem = Standard_True;
1640 break;
1641 }
1642 }
1643 if(isRem) {
1644 tmpSeq.Remove(j);
1645 tabMinForward.Remove(j); // = -1;
1646 }
1647 else j++;
1648 }
1649 }
1650 }
1651 }*/
1652
1653 // Find the best approved candidate
1654 while (nbCandidates) {
1655 // Retrieve first candidate
1656 Standard_Integer indCandidate = seqCandidates.First();
1657 // Candidate is approved if it is in the map
1658 if (mapReference.Contains(indCandidate)) break;
1659 // Find candidates for candidate #indCandidate
1660 mapReference.Add(indCandidate); // Push candidate in the map
1661 TColStd_SequenceOfInteger seqCandidates1, seqOrientations1;
1662 Standard_Boolean isFound =
1663 FindCandidates(seqSections,mapReference,seqCandidates1,seqOrientations1);
1664 mapReference.RemoveLast(); // Pop candidate from the map
1665 if (isFound) isFound = (seqCandidates1.Length() > 0);
1666 if (isFound) {
1667 Standard_Integer indCandidate1 = seqCandidates1.First();
1668 // If indReference is the best candidate for indCandidate
1669 // then indCandidate is the best candidate for indReference
1670 if (indCandidate1 == indReference) break;
1671 // If some other reference in the map is the best candidate for indCandidate
1672 // then assume that reference is the best candidate for indReference
1673 if (mapReference.Contains(indCandidate1)) {
1674 seqCandidates.Prepend(indCandidate1);
1675 nbCandidates++;
1676 break;
1677 }
1678 isFound = Standard_False;
1679 }
1680 if (!isFound) {
1681 // Remove candidate #1
1682 seqCandidates.Remove(1);
1683 seqOrientations.Remove(1);
1684 nbCandidates--;
1685 }
1686 }
1687 }
1688 //gka
1689 if(nbCandidates > 0)
1690 {
1691 Standard_Integer anInd = seqCandidates.Value(1);
1692 TopoDS_Edge Edge2 = TopoDS::Edge(seqSections(anInd));
1693 TopoDS_Shape bnd = Edge2;
1694 if (mySectionBound.IsBound(bnd))
1695 bnd = mySectionBound(bnd);
1696 //gka
1697 if (myBoundFaces.Contains(bnd)) {
1698 Standard_Boolean isOK = Standard_True;
1699 TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1700 for (; itf2.More() && isOK; itf2.Next()) {
1701 const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1702 // Check whether condition is satisfied
1703 isOK = !Faces1.Contains(Face2);
1704 if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1705 }
1706 if(!isOK)
1707 return Standard_False;
1708 }
1709 }
1710 return (nbCandidates > 0);
1711}
1712
1713//=======================================================================
1714//function : Constructor
1715//purpose :
1716//=======================================================================
1717
1718BRepBuilderAPI_Sewing::BRepBuilderAPI_Sewing(const Standard_Real tolerance,
1719 const Standard_Boolean optionSewing,
1720 const Standard_Boolean optionAnalysis,
1721 const Standard_Boolean optionCutting,
1722 const Standard_Boolean optionNonmanifold)
1723{
1724 myReShape = new BRepTools_ReShape;
1725 Init(tolerance, optionSewing, optionAnalysis, optionCutting, optionNonmanifold);
1726}
1727
1728//=======================================================================
1729//function : Init
1730//purpose : Initialise Talerance, and options sewing, faceAnalysis and cutting
1731//=======================================================================
1732
1733void BRepBuilderAPI_Sewing::Init(const Standard_Real tolerance,
1734 const Standard_Boolean optionSewing,
1735 const Standard_Boolean optionAnalysis,
1736 const Standard_Boolean optionCutting,
1737 const Standard_Boolean optionNonmanifold)
1738{
1739 // Set tolerance and Perform options
eb7c351a 1740 myTolerance = Max (tolerance, Precision::Confusion());
7fd59977 1741 mySewing = optionSewing;
1742 myAnalysis = optionAnalysis;
1743 myCutting = optionCutting;
1744 myNonmanifold = optionNonmanifold;
1745 // Set min and max tolerances
eb7c351a 1746 myMinTolerance = myTolerance * 1e-4; //szv: proposal
7fd59977 1747 if (myMinTolerance < Precision::Confusion()) myMinTolerance = Precision::Confusion();
1748 myMaxTolerance = Precision::Infinite();
1749 // Set other modes
1750 myFaceMode = Standard_True;
1751 myFloatingEdgesMode = Standard_False;
1752 //myCuttingFloatingEdgesMode = Standard_False; //gka
1753 mySameParameterMode = Standard_True;
1754 myLocalToleranceMode = Standard_False;
1755 mySewedShape.Nullify();
1756 // Load empty shape
1757 Load(TopoDS_Shape());
1758}
1759
1760//=======================================================================
1761//function : Load
1762//purpose : Loads the context shape
1763//=======================================================================
1764
1765void BRepBuilderAPI_Sewing::Load(const TopoDS_Shape& theShape)
1766{
1767 myReShape->Clear();
1768 if (theShape.IsNull()) myShape.Nullify();
1769 else myShape = myReShape->Apply(theShape);
1770 mySewedShape.Nullify();
1771 // Nullify flags and counters
1772 myNbShapes = myNbEdges = myNbVertices = 0;
1773 // Clear all maps
1774 myOldShapes.Clear();
1775 //myOldFaces.Clear();
1776 myDegenerated.Clear();
1777 myFreeEdges.Clear();
1778 myMultipleEdges.Clear();
1779 myContigousEdges.Clear();
1780 myContigSecBound.Clear();
1781 myBoundFaces.Clear();
1782 myBoundSections.Clear();
1783 myVertexNode.Clear();
1784 myVertexNodeFree.Clear();
1785 myNodeSections.Clear();
1786 myCuttingNode.Clear();
1787 mySectionBound.Clear();
1788 myLittleFace.Clear();
1789}
1790
1791//=======================================================================
1792//function : Add
1793//purpose :
1794//=======================================================================
1795
1796void BRepBuilderAPI_Sewing::Add(const TopoDS_Shape& aShape)
1797{
1798 if (aShape.IsNull()) return;
1799 TopoDS_Shape oShape = myReShape->Apply(aShape);
1800 myOldShapes.Add(aShape,oShape);
1801 myNbShapes = myOldShapes.Extent();
1802}
1803
1804//=======================================================================
1805//function : Perform
1806//purpose :
1807//=======================================================================
1808
0797d9d3 1809#ifdef OCCT_DEBUG
7fd59977 1810#include <OSD_Timer.hxx>
1811#endif
1812
92434a36 1813void BRepBuilderAPI_Sewing::Perform(const Handle(Message_ProgressIndicator)& thePI)
7fd59977 1814{
92434a36
A
1815 const Standard_Integer aNumberOfStages = myAnalysis + myCutting + mySewing + 2;
1816 Message_ProgressSentry aPS (thePI, "Sewing", 0, aNumberOfStages, 1);
0797d9d3 1817#ifdef OCCT_DEBUG
7fd59977 1818 Standard_Real t_total = 0., t_analysis = 0., t_assembling = 0., t_cutting = 0., t_merging = 0.;
1819 OSD_Chronometer chr_total, chr_local;
1820 chr_total.Reset();
1821 chr_total.Start();
1822#endif
1823
1824 // face analysis
92434a36
A
1825 if (myAnalysis)
1826 {
0797d9d3 1827#ifdef OCCT_DEBUG
7fd59977 1828 cout << "Begin face analysis..." << endl;
1829 chr_local.Reset();
1830 chr_local.Start();
1831#endif
92434a36
A
1832 FaceAnalysis (thePI);
1833 if (!aPS.More())
1834 return;
1835 aPS.Next();
0797d9d3 1836#ifdef OCCT_DEBUG
7fd59977 1837 chr_local.Stop();
1838 chr_local.Show(t_analysis);
1839 cout << "Face analysis finished after " << t_analysis << " s" << endl;
1840#endif
1841 }
1842
92434a36
A
1843 if (myNbShapes || !myShape.IsNull())
1844 {
7fd59977 1845
1846 FindFreeBoundaries();
1847
92434a36
A
1848 if (myBoundFaces.Extent())
1849 {
7fd59977 1850
0797d9d3 1851#ifdef OCCT_DEBUG
7fd59977 1852 cout << "Begin vertices assembling..." << endl;
1853 chr_local.Reset();
1854 chr_local.Start();
1855#endif
92434a36
A
1856 VerticesAssembling (thePI);
1857 if (!aPS.More())
1858 return;
1859 aPS.Next();
0797d9d3 1860#ifdef OCCT_DEBUG
7fd59977 1861 chr_local.Stop();
1862 chr_local.Show(t_assembling);
1863 cout << "Vertices assembling finished after " << t_assembling << " s" << endl;
1864#endif
92434a36
A
1865 if (myCutting)
1866 {
0797d9d3 1867#ifdef OCCT_DEBUG
92434a36
A
1868 cout << "Begin cutting..." << endl;
1869 chr_local.Reset();
1870 chr_local.Start();
7fd59977 1871#endif
92434a36
A
1872 Cutting (thePI);
1873 if (!aPS.More())
1874 return;
1875 aPS.Next();
0797d9d3 1876#ifdef OCCT_DEBUG
92434a36
A
1877 chr_local.Stop();
1878 chr_local.Show(t_cutting);
1879 cout << "Cutting finished after " << t_cutting << " s" << endl;
7fd59977 1880#endif
1881 }
0797d9d3 1882#ifdef OCCT_DEBUG
7fd59977 1883 cout << "Begin merging..." << endl;
1884 chr_local.Reset();
1885 chr_local.Start();
1886#endif
92434a36
A
1887 Merging (Standard_True, thePI);
1888 if (!aPS.More())
1889 return;
1890 aPS.Next();
0797d9d3 1891#ifdef OCCT_DEBUG
7fd59977 1892 chr_local.Stop();
1893 chr_local.Show(t_merging);
1894 cout << "Merging finished after " << t_merging << " s" << endl;
1895#endif
1896 }
92434a36
A
1897 else
1898 {
1899 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1900 if (myCutting)
1901 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1902 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1903 if (!aPS.More())
1904 return;
1905 }
7fd59977 1906
92434a36
A
1907 if (mySewing)
1908 {
7fd59977 1909
0797d9d3 1910#ifdef OCCT_DEBUG
7fd59977 1911 cout << "Creating sewed shape..." << endl;
1912#endif
1913 // examine the multiple edges if any and process sameparameter for edges if necessary
92434a36
A
1914 EdgeProcessing (thePI);
1915 if (!aPS.More())
1916 return;
7fd59977 1917 CreateSewedShape();
92434a36
A
1918 if (!aPS.More())
1919 {
1920 mySewedShape.Nullify();
1921 return;
1922 }
1923 if (mySameParameterMode && myFaceMode)
1924 SameParameterShape();
1925 if (!aPS.More())
1926 {
1927 mySewedShape.Nullify();
1928 return;
1929 }
0797d9d3 1930#ifdef OCCT_DEBUG
7fd59977 1931 cout << "Sewed shape created" << endl;
1932#endif
1933 }
92434a36 1934
7fd59977 1935 // create edge informations for output
1936 CreateOutputInformations();
92434a36
A
1937 if (!aPS.More())
1938 {
1939 mySewedShape.Nullify();
1940 return;
1941 }
7fd59977 1942 }
0797d9d3 1943#ifdef OCCT_DEBUG
7fd59977 1944 chr_total.Stop();
1945 chr_total.Show(t_total);
1946 cout << "Sewing finished!" << endl;
1947 cout << " analysis time : " << t_analysis << " s" << endl;
1948 cout << " assembling time : " << t_assembling << " s" << endl;
1949 cout << " cutting time : " << t_cutting << " s" << endl;
1950 cout << " merging time : " << t_merging << " s" << endl;
1951 cout << "Total time : " << t_total << " s" << endl;
1952#endif
1953}
1954
1955//=======================================================================
1956//function : SewedShape
1957//purpose : give the sewed shape
1958// if a null shape, reasons:
1959// -- no useable input shapes : all input shapes are degenerated
1960// -- has multiple edges
1961//=======================================================================
1962
1963const TopoDS_Shape& BRepBuilderAPI_Sewing::SewedShape() const
1964{
1965 return mySewedShape;
1966}
1967
1968//=======================================================================
1969//function : NbFreeEdges
1970//purpose :
1971//=======================================================================
1972
1973Standard_Integer BRepBuilderAPI_Sewing::NbFreeEdges() const
1974{
1975 return myFreeEdges.Extent();
1976}
1977
1978//=======================================================================
1979//function : FreeEdge
1980//purpose :
1981//=======================================================================
1982
1983const TopoDS_Edge& BRepBuilderAPI_Sewing::FreeEdge(const Standard_Integer index) const
1984{
1985 Standard_OutOfRange_Raise_if(index < 0 || index > NbFreeEdges(), "BRepBuilderAPI_Sewing::FreeEdge");
1986 return TopoDS::Edge(myFreeEdges(index));
1987}
1988
1989//=======================================================================
1990//function : NbMultipleEdges
1991//purpose :
1992//=======================================================================
1993
1994Standard_Integer BRepBuilderAPI_Sewing::NbMultipleEdges() const
1995{
1996 return myMultipleEdges.Extent();
1997}
1998
1999//=======================================================================
2000//function : MultipleEdge
2001//purpose :
2002//=======================================================================
2003
2004const TopoDS_Edge& BRepBuilderAPI_Sewing::MultipleEdge(const Standard_Integer index) const
2005{
2006 Standard_OutOfRange_Raise_if(index < 0 || index > NbMultipleEdges(), "BRepBuilderAPI_Sewing::MultipleEdge");
2007 return TopoDS::Edge(myMultipleEdges(index));
2008}
2009
2010//=======================================================================
2011//function : NbContigousEdges
2012//purpose :
2013//=======================================================================
2014
2015Standard_Integer BRepBuilderAPI_Sewing::NbContigousEdges() const
2016{
2017 return myContigousEdges.Extent();
2018}
2019
2020//=======================================================================
2021//function : ContigousEdge
2022//purpose :
2023//=======================================================================
2024
2025const TopoDS_Edge& BRepBuilderAPI_Sewing::ContigousEdge(const Standard_Integer index) const
2026{
2027 Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdge");
2028 return TopoDS::Edge(myContigousEdges.FindKey(index));
2029}
2030
2031//=======================================================================
2032//function : ContigousEdgeCouple
2033//purpose :
2034//=======================================================================
2035
2036const TopTools_ListOfShape& BRepBuilderAPI_Sewing::ContigousEdgeCouple(const Standard_Integer index) const
2037{
2038 Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdgeCouple");
2039 return myContigousEdges(index);
2040}
2041
2042//=======================================================================
2043//function : IsSectionBound
2044//purpose :
2045//=======================================================================
2046
2047Standard_Boolean BRepBuilderAPI_Sewing::IsSectionBound(const TopoDS_Edge& section) const
2048{
2049 if(myContigSecBound.IsBound(section)) {
2050 return Standard_True;
2051 }
2052 else {
2053 return Standard_False;
2054 }
2055}
2056
2057//=======================================================================
2058//function : SectionToBoundary
2059//purpose :
2060//=======================================================================
2061
2062const TopoDS_Edge& BRepBuilderAPI_Sewing::SectionToBoundary(const TopoDS_Edge& section) const
2063{
2064 Standard_NoSuchObject_Raise_if(!IsSectionBound(section), "BRepBuilderAPI_Sewing::SectionToBoundary");
2065 return TopoDS::Edge(myContigSecBound(section));
2066}
2067//=======================================================================
2068//function : NbDeletedFaces
2069//purpose :
2070//=======================================================================
2071 Standard_Integer BRepBuilderAPI_Sewing::NbDeletedFaces() const
2072{
2073 return myLittleFace.Extent();
2074}
2075
2076//=======================================================================
2077//function : DeletedFace
2078//purpose :
2079//=======================================================================
2080const TopoDS_Face& BRepBuilderAPI_Sewing::DeletedFace(const Standard_Integer index) const
2081{
2082 Standard_OutOfRange_Raise_if(index < 0 || index > NbDeletedFaces(), "BRepBuilderAPI_Sewing::DeletedFace");
2083 return TopoDS::Face(myLittleFace(index));
2084}
2085
2086//=======================================================================
2087//function : NbDegeneratedShapes
2088//purpose :
2089//=======================================================================
2090
2091Standard_Integer BRepBuilderAPI_Sewing::NbDegeneratedShapes() const
2092{
2093 return myDegenerated.Extent();
2094}
2095
2096//=======================================================================
2097//function : DegeneratedShape
2098//purpose :
2099//=======================================================================
2100
2101const TopoDS_Shape& BRepBuilderAPI_Sewing::DegeneratedShape(const Standard_Integer index) const
2102{
2103 Standard_OutOfRange_Raise_if(index < 0 || index > NbDegeneratedShapes(), "BRepBuilderAPI_Sewing::DegereratedShape");
2104 return myDegenerated(index);
2105}
2106
2107//=======================================================================
2108//function : IsDegenerated
2109//purpose :
2110//=======================================================================
2111
2112Standard_Boolean BRepBuilderAPI_Sewing::IsDegenerated(const TopoDS_Shape& aShape) const
2113{
2114 TopoDS_Shape NewShape = myReShape->Apply(aShape);
2115 // Degenerated face
2116 if (aShape.ShapeType() == TopAbs_FACE)
2117 return NewShape.IsNull();
2118 if (NewShape.IsNull()) return Standard_False;
2119 // Degenerated edge
2120 if (NewShape.ShapeType() == TopAbs_EDGE)
2121 return BRep_Tool::Degenerated(TopoDS::Edge(NewShape));
2122 // Degenerated wire
2123 if (NewShape.ShapeType() == TopAbs_WIRE) {
2124 Standard_Boolean isDegenerated = Standard_True;
2125 for (TopoDS_Iterator aIt(NewShape); aIt.More() && isDegenerated; aIt.Next())
2126 isDegenerated = BRep_Tool::Degenerated(TopoDS::Edge(aIt.Value()));
2127 return isDegenerated;
2128 }
2129 return Standard_False;
2130}
2131
2132//=======================================================================
2133//function : IsModified
2134//purpose :
2135//=======================================================================
2136
2137Standard_Boolean BRepBuilderAPI_Sewing::IsModified(const TopoDS_Shape& aShape) const
2138{
2139 TopoDS_Shape NewShape = aShape;
2140 if (myOldShapes.Contains(aShape))
2141 NewShape = myOldShapes.FindFromKey(aShape);
2142 if(!NewShape.IsSame(aShape)) return Standard_True;
2143 return Standard_False;
2144}
2145
2146//=======================================================================
2147//function : Modified
2148//purpose :
2149//=======================================================================
2150
2151const TopoDS_Shape& BRepBuilderAPI_Sewing::Modified(const TopoDS_Shape& aShape) const
2152{
2153 if (myOldShapes.Contains(aShape)) return myOldShapes.FindFromKey(aShape);
2154 //if (myOldFaces.Contains(aShape)) return myOldFaces.FindFromKey(aShape);
2155 return aShape;
2156}
2157
2158//=======================================================================
2159//function : IsModifiedSubShape
2160//purpose :
2161//=======================================================================
2162
2163Standard_Boolean BRepBuilderAPI_Sewing::IsModifiedSubShape(const TopoDS_Shape& aShape) const
2164{
2165 TopoDS_Shape NewShape = myReShape->Apply(aShape);
2166 if(!NewShape.IsSame(aShape)) return Standard_True;
2167 return Standard_False;
2168}
2169
2170//=======================================================================
2171//function : ModifiedSubShape
2172//purpose :
2173//=======================================================================
2174
2175TopoDS_Shape BRepBuilderAPI_Sewing::ModifiedSubShape(const TopoDS_Shape& aShape) const
2176{
2177 return myReShape->Apply(aShape);
2178}
2179
2180//=======================================================================
2181//function : Dump
2182//purpose :
2183//=======================================================================
2184
2185void BRepBuilderAPI_Sewing::Dump() const
2186{
2187 Standard_Integer i, NbBounds = myBoundFaces.Extent(), NbSections = 0;
2188 TopTools_MapOfShape mapVertices, mapEdges;
2189 for (i = 1; i <= NbBounds; i++) {
2190 TopoDS_Shape bound = myBoundFaces.FindKey(i);
2191 if (myBoundSections.IsBound(bound)) NbSections += myBoundSections(bound).Extent();
2192 else NbSections++;
2193 TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
2194 for (; aExp.More(); aExp.Next()) {
2195 TopoDS_Edge E = TopoDS::Edge(aExp.Current());
2196 mapEdges.Add(E);
2197 TopoDS_Vertex V1, V2;
2198 TopExp::Vertices(E,V1,V2);
2199 mapVertices.Add(V1);
2200 mapVertices.Add(V2);
2201 }
2202 }
2203 cout << " " << endl;
2204 cout << " Informations " << endl;
2205 cout << " ===========================================================" << endl;
2206 cout << " " << endl;
2207 cout << " Number of input shapes : " << myOldShapes.Extent() << endl;
2208 cout << " Number of actual shapes : " << myNbShapes << endl;
2209 cout << " Number of Bounds : " << NbBounds << endl;
2210 cout << " Number of Sections : " << NbSections << endl;
2211 cout << " Number of Edges : " << mapEdges.Extent() << endl;
2212 cout << " Number of Vertices : " << myNbVertices << endl;
2213 cout << " Number of Nodes : " << mapVertices.Extent() << endl;
2214 cout << " Number of Free Edges : " << myFreeEdges.Extent() << endl;
2215 cout << " Number of Contigous Edges : " << myContigousEdges.Extent() << endl;
2216 cout << " Number of Multiple Edges : " << myMultipleEdges.Extent() << endl;
2217 cout << " Number of Degenerated Edges : " << myDegenerated.Extent() << endl;
2218 cout << " ===========================================================" << endl;
2219 cout << " " << endl;
2220}
2221
2222//=======================================================================
2223//function : FaceAnalysis
2224//purpose : Remove
2225// Modifies:
2226// myNbShapes
2227// myOldShapes
2228//
2229// Constructs:
2230// myDegenerated
2231//=======================================================================
2232
92434a36 2233void BRepBuilderAPI_Sewing::FaceAnalysis(const Handle(Message_ProgressIndicator)& thePI)
7fd59977 2234{
2235 if (!myShape.IsNull() && myOldShapes.IsEmpty()) {
2236 Add(myShape);
2237 myShape.Nullify();
2238 }
2239
2240 BRep_Builder B;
2241 TopTools_MapOfShape SmallEdges;
2242 TopTools_DataMapOfShapeListOfShape GluedVertices;
2243 Standard_Integer i = 1;
92434a36
A
2244 Message_ProgressSentry aPS (thePI, "Shape analysis", 0, myOldShapes.Extent(), 1);
2245 for (i = 1; i <= myOldShapes.Extent() && aPS.More(); i++, aPS.Next()) {
7fd59977 2246 for (TopExp_Explorer fexp(myOldShapes(i),TopAbs_FACE); fexp.More(); fexp.Next()) {
2247
2248 // Retrieve current face
2249 TopoDS_Shape aTmpShape = fexp.Current(); //for porting
2250 TopoDS_Face face = TopoDS::Face(aTmpShape);
2251 Standard_Integer nbEdges = 0, nbSmall = 0;
2252
2253 // Build replacing face
2254 aTmpShape = face.EmptyCopied().Oriented(TopAbs_FORWARD); //for porting
2255 TopoDS_Face nface = TopoDS::Face(aTmpShape);
2256 Standard_Boolean isFaceChanged = Standard_False;
2257
2258 TopoDS_Iterator witer(face.Oriented(TopAbs_FORWARD));
2259 for (; witer.More(); witer.Next()) {
2260
2261 // Retrieve current wire
2262 aTmpShape = witer.Value(); //for porting
2263 if( aTmpShape.ShapeType() != TopAbs_WIRE) continue;
2264 TopoDS_Wire wire = TopoDS::Wire(aTmpShape);
2265
2266 // Build replacing wire
2267 aTmpShape = wire.EmptyCopied().Oriented(TopAbs_FORWARD);
2268 TopoDS_Wire nwire = TopoDS::Wire(aTmpShape);
2269 Standard_Boolean isWireChanged = Standard_False;
2270
2271 TopoDS_Iterator eiter(wire.Oriented(TopAbs_FORWARD));
2272 for (; eiter.More(); eiter.Next()) {
2273
2274 // Retrieve current edge
2275 aTmpShape = eiter.Value(); //for porting
2276 TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
2277 nbEdges++;
2278
2279 // Process degenerated edge
2280 if (BRep_Tool::Degenerated(edge)) {
2281 B.Add(nwire,edge); // Old edge kept
2282 myDegenerated.Add(edge);
2283 nbSmall++;
2284 continue;
2285 }
2286
2287 Standard_Boolean isSmall = SmallEdges.Contains(edge);
2288 if (!isSmall) {
2289
2290 // Check for small edge
2291 Standard_Real first, last;
2292 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,first,last);
2293 if (c3d.IsNull()) {
0797d9d3 2294#ifdef OCCT_DEBUG
7fd59977 2295 cout << "Warning: Possibly small edge can be sewed: No 3D curve" << endl;
2296#endif
2297 }
2298 else {
2299 // Evaluate curve compactness
2300 const Standard_Integer npt = 5;
2301 gp_Pnt cp((c3d->Value(first).XYZ()+c3d->Value(last).XYZ())*0.5);
2302 Standard_Real dist, maxdist = 0.0;
2303 Standard_Real delta = (last - first)/(npt - 1);
2304 for (Standard_Integer idx = 0; idx < npt; idx++) {
2305 dist = cp.Distance(c3d->Value(first + idx*delta));
2306 if (maxdist < dist) maxdist = dist;
2307 }
2308 isSmall = (2.*maxdist <= MinTolerance());
2309 /*try {
2310 GeomAdaptor_Curve cAdapt(c3d);
2311 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt,first,last);
2312 isSmall = (length <= MinTolerance());
2313 }
2314 catch (Standard_Failure) {
0797d9d3 2315#ifdef OCCT_DEBUG
7fd59977 2316 cout << "Warning: Possibly small edge can be sewed: ";
2317 Standard_Failure::Caught()->Print(cout); cout << endl;
2318#endif
2319 }*/
2320 }
2321
2322 if (isSmall) {
2323
2324 // Store small edge in the map
2325 SmallEdges.Add(edge);
2326
2327 TopoDS_Vertex v1, v2;
2328 TopExp::Vertices(edge,v1,v2);
2329 TopoDS_Shape nv1 = myReShape->Apply(v1), nv2 = myReShape->Apply(v2);
2330
2331 // Store glued vertices
2332 if (!nv1.IsSame(v1)) {
2333 TopTools_ListOfShape& vlist1 = GluedVertices(nv1);
2334 // First vertex was already glued
2335 if (!nv2.IsSame(v2)) {
2336 // Merge lists of glued vertices
2337 if (!nv1.IsSame(nv2)) {
2338 TopTools_ListIteratorOfListOfShape liter(GluedVertices(nv2));
2339 for (; liter.More(); liter.Next()) {
2340 TopoDS_Shape v = liter.Value();
2341 myReShape->Replace(v,nv1.Oriented(v.Orientation()));
2342 vlist1.Append(v);
2343 }
2344 GluedVertices.UnBind(nv2);
2345 }
2346 }
2347 else {
2348 // Add second vertex to the existing list
2349 vlist1.Append(v2);
2350 myReShape->Replace(v2,nv1.Oriented(v2.Orientation()));
2351 }
2352 }
2353 else if (!nv2.IsSame(v2)) {
2354 // Add first vertex to the existing list
2355 GluedVertices(nv2).Append(v1);
2356 myReShape->Replace(v1,nv2.Oriented(v1.Orientation()));
2357 }
2358 else if (!v1.IsSame(v2)) {
2359 // Record new glued vertices
2360 TopoDS_Vertex nv;
2361 B.MakeVertex(nv);
2362 TopTools_ListOfShape vlist;
2363 vlist.Append(v1);
2364 vlist.Append(v2);
2365 GluedVertices.Bind(nv,vlist);
2366 myReShape->Replace(v1,nv.Oriented(v1.Orientation()));
2367 myReShape->Replace(v2,nv.Oriented(v2.Orientation()));
2368 }
2369 }
2370 }
2371
2372 // Replace small edge
2373 if (isSmall) {
0797d9d3 2374#ifdef OCCT_DEBUG
7fd59977 2375 cout << "Warning: Small edge made degenerated by FaceAnalysis" << endl;
2376#endif
2377 nbSmall++;
2378 // Create new degenerated edge
2379 aTmpShape = edge.Oriented(TopAbs_FORWARD);
2380 TopoDS_Edge fedge = TopoDS::Edge(aTmpShape);
2381 Standard_Real pfirst, plast;
2382 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(fedge,face,pfirst,plast);
2383 if (!c2d.IsNull()) {
2384 TopoDS_Edge nedge;
2385 B.MakeEdge(nedge);
2386 B.UpdateEdge(nedge,c2d,face,Precision::Confusion());
2387 B.Range(nedge,pfirst,plast);
2388 B.Degenerated(nedge,Standard_True);
2389 TopoDS_Vertex v1, v2;
2390 TopExp::Vertices(fedge,v1,v2);
2391 B.Add(nedge,myReShape->Apply(v1).Oriented(v1.Orientation()));
2392 B.Add(nedge,myReShape->Apply(v2).Oriented(v2.Orientation()));
2393 B.Add(nwire,nedge.Oriented(edge.Orientation()));
2394 myDegenerated.Add(nedge);
2395 }
2396 isWireChanged = Standard_True;
2397 }
2398 else B.Add(nwire,edge); // Old edge kept
2399 }
2400
2401 // Record wire in the new face
2402 if (isWireChanged) {
2403 B.Add(nface,nwire.Oriented(wire.Orientation()));
2404 isFaceChanged = Standard_True;
2405 }
2406 else B.Add(nface,wire);
2407 }
2408
2409 // Remove small face
2410 if (nbSmall == nbEdges) {
0797d9d3 2411#ifdef OCCT_DEBUG
7fd59977 2412 cout << "Warning: Small face removed by FaceAnalysis" << endl;
2413#endif
2414 myLittleFace.Add(face);
2415 myReShape->Remove(face);
2416 }
2417 else if (isFaceChanged) {
2418
2419 myReShape->Replace(face,nface.Oriented(face.Orientation()));
2420 }
2421 }
2422 }
2423
2424 // Update glued vertices
2425 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape miter(GluedVertices);
2426 for (; miter.More(); miter.Next()) {
2427 TopoDS_Vertex vnew = TopoDS::Vertex(miter.Key());
2428 gp_XYZ coord(0.,0.,0.);
2429 Standard_Integer nbPoints = 0;
2430 const TopTools_ListOfShape& vlist = miter.Value();
2431 TopTools_ListIteratorOfListOfShape liter1(vlist);
2432 for (; liter1.More(); liter1.Next()) {
2433 coord += BRep_Tool::Pnt(TopoDS::Vertex(liter1.Value())).XYZ();
2434 nbPoints++;
2435 }
2436 if (nbPoints) {
2437 gp_Pnt vp(coord / nbPoints);
2438 Standard_Real tol = 0.0, mtol = 0.0;
2439 TopTools_ListIteratorOfListOfShape liter2(vlist);
2440 for (; liter2.More(); liter2.Next()) {
2441 Standard_Real vtol = BRep_Tool::Tolerance(TopoDS::Vertex(liter2.Value()));
2442 if (mtol < vtol) mtol = vtol;
2443 vtol = vp.Distance(BRep_Tool::Pnt(TopoDS::Vertex(liter2.Value())));
2444 if (tol < vtol) tol = vtol;
2445 }
2446 B.UpdateVertex(vnew,vp,tol+mtol);
2447 }
2448 }
2449
2450 // Update input shapes
2451 for (i = 1; i <= myOldShapes.Extent(); i++)
2452 myOldShapes(i) = myReShape->Apply(myOldShapes(i));
2453}
2454
2455//=======================================================================
2456//function : FindFreeBoundaries
2457//purpose : Constructs :
2458// myBoundFaces (bound = list of faces) - REFERENCE
2459// myVertexNode (vertex = node)
2460// myVertexNodeFree (floating vertex = node)
2461//
2462//=======================================================================
2463
2464void BRepBuilderAPI_Sewing::FindFreeBoundaries()
2465{
2466 // Take into account the context shape if needed
2467 TopTools_IndexedMapOfShape NewShapes;
2468 if (!myShape.IsNull()) {
2469 if (myOldShapes.IsEmpty()) {
2470 Add(myShape);
2471 myShape.Nullify();
2472 }
2473 else {
2474 TopoDS_Shape newShape = myReShape->Apply(myShape);
2475 if (!newShape.IsNull()) NewShapes.Add(newShape);
2476 }
2477 }
2478 // Create map Edge -> Faces
2479 TopTools_IndexedDataMapOfShapeListOfShape EdgeFaces;
2480 Standard_Integer i, nbShapes = myOldShapes.Extent();
2481 for (i = 1; i <= nbShapes; i++) {
2482 // Retrieve new shape
2483 TopoDS_Shape shape = myOldShapes(i);
2484 if (shape.IsNull()) continue;
2485 NewShapes.Add(shape);
2486 // Explore shape to find all boundaries
2487 for (TopExp_Explorer eExp(shape,TopAbs_EDGE); eExp.More(); eExp.Next()) {
2488 TopoDS_Shape edge = eExp.Current();
2489 if (!EdgeFaces.Contains(edge)) {
2490 TopTools_ListOfShape listFaces;
2491 EdgeFaces.Add(edge,listFaces);
2492 }
2493 }
2494 }
2495 // Fill map Edge -> Faces
2496 nbShapes = NewShapes.Extent();
2497 TopTools_MapOfShape mapFaces;
2498 for (i = 1; i <= nbShapes; i++) {
2499 // Explore shape to find all faces
2500 TopExp_Explorer fExp(NewShapes.FindKey(i),TopAbs_FACE);
2501 for (; fExp.More(); fExp.Next()) {
2502 TopoDS_Shape face = fExp.Current();
2503 if(mapFaces.Contains(face)) continue;
2504 else
2505 mapFaces.Add(face);
2506 // Explore face to find all boundaries
2507 for (TopoDS_Iterator aIw(face); aIw.More(); aIw.Next()) {
2508 if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
2509 for (TopoDS_Iterator aIIe(aIw.Value()); aIIe.More(); aIIe.Next()) {
2510
2511 TopoDS_Shape edge = aIIe.Value();
2512
2513 if (EdgeFaces.Contains(edge)) {
2514 EdgeFaces.ChangeFromKey(edge).Append(face);
2515 //TopTools_ListOfShape& listFaces = EdgeFaces.ChangeFromKey(edge);
2516 //Standard_Boolean isContained = Standard_False;
2517 //TopTools_ListIteratorOfListOfShape itf(listFaces);
2518 //for (; itf.More() && !isContained; itf.Next())
2519 // isContained = face.IsSame(itf.Value());
2520 //if (!isContained) listFaces.Append(face);
2521 }
2522 }
2523 }
2524 }
2525 }
2526 // Find free boundaries
2527 nbShapes = EdgeFaces.Extent();
2528 for (i = 1; i <= nbShapes; i++) {
2529 TopTools_ListOfShape& listFaces = EdgeFaces(i);
2530 Standard_Integer nbFaces = listFaces.Extent();
2531 TopoDS_Shape edge = EdgeFaces.FindKey(i);
2532 if(edge.Orientation() == TopAbs_INTERNAL)
2533 continue;
2534 Standard_Boolean isSeam = Standard_False;
2535 if (nbFaces == 1) {
2536 TopoDS_Face face = TopoDS::Face(listFaces.First());
2537 isSeam = BRep_Tool::IsClosed(TopoDS::Edge(edge),face);
2538 if (isSeam) {
2539 ///Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
2540 //isSeam = (IsUClosedSurface(surf) || IsVClosedSurface(surf));
2541 //if(!isSeam) {
2542 BRep_Builder aB;
2543 TopoDS_Shape anewEdge = edge.EmptyCopied();
2544 TopoDS_Iterator aItV(edge);
2545 for( ; aItV.More() ; aItV.Next())
2546 aB.Add(anewEdge,aItV.Value());
2547
2548
2549
2550 Standard_Real first2d,last2d;
2551 Handle(Geom2d_Curve) c2dold =
2552 BRep_Tool::CurveOnSurface(TopoDS::Edge(edge),TopoDS::Face(listFaces.First()),first2d,last2d);
2553
2554 Handle(Geom2d_Curve) c2d;
2555 BRep_Builder B;
2556 B.UpdateEdge(TopoDS::Edge(anewEdge),c2d,c2d,TopoDS::Face(listFaces.First()),0);
2557 B.UpdateEdge(TopoDS::Edge(anewEdge),c2dold,TopoDS::Face(listFaces.First()),0);
2558
2559 Standard_Real aFirst, aLast;
2560 BRep_Tool::Range(TopoDS::Edge(edge),aFirst, aLast);
2561 aB.Range(TopoDS::Edge(anewEdge),aFirst, aLast);
2562 aB.Range(TopoDS::Edge(anewEdge),TopoDS::Face(listFaces.First()),first2d,last2d);
2563 myReShape->Replace(edge,anewEdge);
2564 edge = anewEdge;
2565
2566 //}
2567 isSeam = Standard_False;
2568 }
2569 }
2570 Standard_Boolean isBoundFloat = (myFloatingEdgesMode && !nbFaces);
2571 Standard_Boolean isBound = (myFaceMode && ((myNonmanifold && nbFaces) || (nbFaces == 1 && !isSeam)));
2572 if (isBound || isBoundFloat) {
2573 // Ignore degenerated edge
2574 if (BRep_Tool::Degenerated(TopoDS::Edge(edge))) continue;
2575 // Ignore edge with internal vertices
2576 // Standard_Integer nbVtx = 0;
2577 // for (TopExp_Explorer vExp(edge,TopAbs_VERTEX); vExp.More(); vExp.Next()) nbVtx++;
2578 // if (nbVtx != 2) continue;
2579 // Add to BoundFaces
2580 TopTools_ListOfShape listFacesCopy;
2581 listFacesCopy.Append(listFaces);
2582 myBoundFaces.Add(edge,listFacesCopy);
2583 // Process edge vertices
2584 TopoDS_Vertex vFirst, vLast;
2585 TopExp::Vertices(TopoDS::Edge(edge), vFirst, vLast);
2586 if(vFirst.IsNull() || vLast.IsNull()) continue;
2587 if(vFirst.Orientation() == TopAbs_INTERNAL || vLast.Orientation() == TopAbs_INTERNAL)
2588 continue;
2589 if (isBound) {
2590 // Add to VertexNode
2591 if (!myVertexNode.Contains(vFirst))
2592 myVertexNode.Add(vFirst,vFirst);
2593 if (!myVertexNode.Contains(vLast))
2594 myVertexNode.Add(vLast,vLast);
2595 }
2596 else {
2597 // Add to VertexNodeFree
2598 if (!myVertexNodeFree.Contains(vFirst))
2599 myVertexNodeFree.Add(vFirst,vFirst);
2600 if (!myVertexNodeFree.Contains(vLast))
2601 myVertexNodeFree.Add(vLast,vLast);
2602 }
2603 }
2604 }
2605}
2606
2607//=======================================================================
2608//function : VerticesAssembling
2609//purpose : Modifies :
2610// myVertexNode (nodes glued)
2611// myVertexNodeFree (nodes glued)
2612// myNodeSections (lists of sections merged for glued nodes)
2613//
2614//=======================================================================
2615
2616static Standard_Boolean CreateNewNodes(const TopTools_IndexedDataMapOfShapeShape& NodeNearestNode,
2617 const TopTools_IndexedDataMapOfShapeListOfShape& NodeVertices,
2618 TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2619 TopTools_DataMapOfShapeListOfShape& aNodeEdges)
2620{
2621 Standard_Integer i, nbNearest = NodeNearestNode.Extent();
2622
2623 // Create new nodes
2624 BRep_Builder B;
2625 TopTools_DataMapOfShapeShape OldNodeNewNode;
2626 TopTools_DataMapOfShapeListOfShape NewNodeOldNodes;
2627 for (i = 1; i <= nbNearest; i++) {
2628 // Retrieve a pair of nodes to merge
2629 TopoDS_Shape oldnode1 = NodeNearestNode.FindKey(i);
2630 TopoDS_Shape oldnode2 = NodeNearestNode(i);
2631 // Second node should also be in the map
2632 if (!NodeNearestNode.Contains(oldnode2)) continue;
2633 // Get new node for old node #1
2634 if (OldNodeNewNode.IsBound(oldnode1)) {
2635 TopoDS_Shape newnode1 = OldNodeNewNode(oldnode1);
2636 if (OldNodeNewNode.IsBound(oldnode2)) {
2637 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2638 if (!newnode1.IsSame(newnode2)) {
2639 // Change data for new node #2
2640 TopTools_ListOfShape& lnode1 = NewNodeOldNodes(newnode1);
2641 TopTools_ListIteratorOfListOfShape itn(NewNodeOldNodes(newnode2));
2642 for (; itn.More(); itn.Next()) {
2643 TopoDS_Shape node2 = itn.Value();
2644 lnode1.Append(node2);
2645 OldNodeNewNode(node2) = newnode1;
2646 }
2647 NewNodeOldNodes.UnBind(newnode2);
2648 }
2649 }
2650 else {
2651 // Old node #2 is not bound - add to old node #1
2652 OldNodeNewNode.Bind(oldnode2,newnode1);
2653 NewNodeOldNodes(newnode1).Append(oldnode2);
2654 }
2655 }
2656 else {
2657 if (OldNodeNewNode.IsBound(oldnode2)) {
2658 // Old node #1 is not bound - add to old node #2
2659 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2660 OldNodeNewNode.Bind(oldnode1,newnode2);
2661 NewNodeOldNodes(newnode2).Append(oldnode1);
2662 }
2663 else {
2664 // Nodes are not bound - create new node
2665 TopoDS_Vertex newnode;
2666 B.MakeVertex(newnode);
2667 OldNodeNewNode.Bind(oldnode1,newnode);
2668 OldNodeNewNode.Bind(oldnode2,newnode);
2669 TopTools_ListOfShape lnodes;
2670 lnodes.Append(oldnode1);
2671 lnodes.Append(oldnode2);
2672 NewNodeOldNodes.Bind(newnode,lnodes);
2673 }
2674 }
2675 }
2676
2677 // Stop if no new nodes created
2678 if (!NewNodeOldNodes.Extent()) return Standard_False;
2679
2680 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter1(NewNodeOldNodes);
2681 for (; iter1.More(); iter1.Next()) {
2682 const TopoDS_Vertex& newnode = TopoDS::Vertex(iter1.Key());
2683 // Calculate new node center point
2684 gp_XYZ theCoordinates(0.,0.,0.);
2685 TopTools_ListOfShape lvert; // Accumulate node vertices
2686 TopTools_MapOfShape medge;
2687 TopTools_ListOfShape ledge; // Accumulate node edges
2688 // Iterate on old nodes
2689 TopTools_ListIteratorOfListOfShape itn(iter1.Value());
2690 for (; itn.More(); itn.Next()) {
2691 const TopoDS_Shape& oldnode = itn.Value();
2692 // Iterate on node vertices
2693 TopTools_ListIteratorOfListOfShape itv(NodeVertices.FindFromKey(oldnode));
2694 for (; itv.More(); itv.Next()) {
2695 TopoDS_Vertex vertex = TopoDS::Vertex(itv.Value());
2696 // Change node for vertex
2697 aVertexNode.ChangeFromKey(vertex) = newnode;
2698 // Accumulate coordinates
2699 theCoordinates += BRep_Tool::Pnt(vertex).XYZ();
2700 lvert.Append(vertex);
2701 }
2702 // Iterate on node edges
2703 const TopTools_ListOfShape& edges = aNodeEdges(oldnode);
2704 TopTools_ListIteratorOfListOfShape ite(edges);
2705 for (; ite.More(); ite.Next()) {
2706 TopoDS_Shape edge = ite.Value();
2707 if (!medge.Contains(edge)) { medge.Add(edge); ledge.Append(edge); }
2708 }
2709 // Unbind old node edges
2710 aNodeEdges.UnBind(oldnode);
2711 }
2712 // Bind new node edges
2713 aNodeEdges.Bind(newnode,ledge);
2714 gp_Pnt center(theCoordinates / lvert.Extent());
2715 // Calculate new node tolerance
2716 Standard_Real toler = 0.0;
2717 TopTools_ListIteratorOfListOfShape itv(lvert);
2718 for (; itv.More(); itv.Next()) {
2719 const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value());
2720 Standard_Real t = center.Distance(BRep_Tool::Pnt(vertex)) + BRep_Tool::Tolerance(vertex);
2721 if (toler < t) toler = t;
2722 }
2723 // Update new node parameters
2724 B.UpdateVertex(newnode,center,toler);
2725 }
2726
2727 return Standard_True;
2728}
2729
2730static Standard_Integer IsMergedVertices(const TopoDS_Shape& face1,
2731 const TopoDS_Shape& e1, const TopoDS_Shape& e2,
2732 const TopoDS_Shape& vtx1, const TopoDS_Shape& vtx2)
2733{
2734 //Case of floating edges
2735 if (face1.IsNull())
2736 return (!IsClosedShape(e1,vtx1,vtx2));
2737
2738 // Find wires containing given edges
2739 TopoDS_Shape wire1, wire2;
2740 TopExp_Explorer itw(face1,TopAbs_WIRE);
2741 for (; itw.More() && (wire1.IsNull() || wire2.IsNull()); itw.Next()) {
2742 TopoDS_Iterator ite(itw.Current(),Standard_False);
2743 for (; ite.More() && (wire1.IsNull() || wire2.IsNull()); ite.Next()) {
2744 if (wire1.IsNull() && e1.IsSame(ite.Value())) wire1 = itw.Current();
2745 if (wire2.IsNull() && e2.IsSame(ite.Value())) wire2 = itw.Current();
2746 }
2747 }
2748 Standard_Integer Status = 0;
2749 if (!wire1.IsNull() && !wire2.IsNull()) {
2750 if (wire1.IsSame(wire2)) {
2751 for (TopoDS_Iterator aIte(wire1,Standard_False); aIte.More(); aIte.Next()) {
2752 TopoDS_Vertex ve1,ve2;
2753 TopExp::Vertices(TopoDS::Edge(aIte.Value()),ve1,ve2);
2754 if ((ve1.IsSame(vtx1) && ve2.IsSame(vtx2)) ||
2755 (ve2.IsSame(vtx1) && ve1.IsSame(vtx2)))
2756 return (IsClosedShape(aIte.Value(),vtx1,vtx2)? 0 : 1);
2757 }
2758 if (IsClosedShape(wire1,vtx1,vtx2)) {
2759 TopoDS_Vertex V1, V2;
2760 TopExp::Vertices(TopoDS::Wire(wire1),V1,V2);
2761 Standard_Boolean isEndVertex = ((V1.IsSame(vtx1) && V2.IsSame(vtx2)) ||
2762 (V2.IsSame(vtx1) && V1.IsSame(vtx2)));
2763 if (!isEndVertex) Status = 1;
2764 }
2765 else Status = 1;
2766 }
2767 else Status = -1;
2768 }
2769 return Status;
2770}
2771
2772static Standard_Boolean GlueVertices(TopTools_IndexedDataMapOfShapeShape& aVertexNode,
92434a36
A
2773 TopTools_DataMapOfShapeListOfShape& aNodeEdges,
2774 const TopTools_IndexedDataMapOfShapeListOfShape& aBoundFaces,
2775 const Standard_Real Tolerance,
2776 const Handle(Message_ProgressIndicator)& theProgress)
7fd59977 2777{
2778 Standard_Integer i, nbVertices = aVertexNode.Extent();
2779 // Create map of node -> vertices
2780 TopTools_IndexedDataMapOfShapeListOfShape NodeVertices;
82192477 2781 BRepBuilderAPI_CellFilter aFilter (Tolerance);
2782 BRepBuilderAPI_VertexInspector anInspector (Tolerance);
7fd59977 2783 for (i = 1; i <= nbVertices; i++) {
2784 TopoDS_Shape vertex = aVertexNode.FindKey(i);
2785 TopoDS_Vertex node = TopoDS::Vertex(aVertexNode(i));
2786 if (NodeVertices.Contains(node)) {
2787 NodeVertices.ChangeFromKey(node).Append(vertex);
2788 }
2789 else {
2790 TopTools_ListOfShape vlist;
2791 vlist.Append(vertex);
2792 NodeVertices.Add(node,vlist);
82192477 2793 gp_Pnt aPnt = BRep_Tool::Pnt (TopoDS::Vertex (node));
2794 aFilter.Add (NodeVertices.FindIndex (node), aPnt.XYZ());
2795 anInspector.Add (aPnt.XYZ());
7fd59977 2796 }
2797 }
2798 Standard_Integer nbNodes = NodeVertices.Extent();
0797d9d3 2799#ifdef OCCT_DEBUG
7fd59977 2800 cout << "Glueing " << nbNodes << " nodes..." << endl;
2801#endif
7fd59977 2802 // Merge nearest nodes
2803 TopTools_IndexedDataMapOfShapeShape NodeNearestNode;
92434a36
A
2804 Message_ProgressSentry aPS (theProgress, "Glueing nodes", 0, nbNodes, 1, Standard_True);
2805 for (i = 1; i <= nbNodes && aPS.More(); i++, aPS.Next()) {
7fd59977 2806 TopoDS_Vertex node1 = TopoDS::Vertex(NodeVertices.FindKey(i));
2807 // Find near nodes
82192477 2808 gp_Pnt pt1 = BRep_Tool::Pnt (node1);
2809 anInspector.SetCurrent (pt1.XYZ());
2810 gp_XYZ aPntMin = anInspector.Shift (pt1.XYZ(), -Tolerance);
2811 gp_XYZ aPntMax = anInspector.Shift (pt1.XYZ(), Tolerance);
2812 aFilter.Inspect (aPntMin, aPntMax, anInspector);
2813 if (anInspector.ResInd().IsEmpty()) continue;
7fd59977 2814 // Retrieve list of edges for the first node
2815 const TopTools_ListOfShape& ledges1 = aNodeEdges(node1);
2816 // Explore list of near nodes and fill the sequence of glued nodes
2817 TopTools_SequenceOfShape SeqNodes;
2818 TopTools_ListOfShape listNodesSameEdge;
82192477 2819 //gp_Pnt pt1 = BRep_Tool::Pnt(node1);
2820 TColStd_ListIteratorOfListOfInteger iter1(anInspector.ResInd());
7fd59977 2821 for (; iter1.More(); iter1.Next()) {
2822 TopoDS_Vertex node2 = TopoDS::Vertex(NodeVertices.FindKey(iter1.Value()));
2823 if (node1 == node2) continue;
2824 // Retrieve list of edges for the second node
2825 const TopTools_ListOfShape& ledges2 = aNodeEdges(node2);
2826 // Check merging condition for the pair of nodes
2827 Standard_Integer Status = 0, isSameEdge = Standard_False;
2828 // Explore edges of the first node
2829 TopTools_ListIteratorOfListOfShape Ie1(ledges1);
2830 for (; Ie1.More() && !Status && !isSameEdge; Ie1.Next()) {
2831 const TopoDS_Shape& e1 = Ie1.Value();
2832 // Obtain real vertex from edge
2833 TopoDS_Shape v1 = node1;
2834 { //szv: Use brackets to destroy local variables
2835 TopoDS_Vertex ov1, ov2;
2836 TopExp::Vertices(TopoDS::Edge(e1),ov1,ov2);
2837 if (aVertexNode.Contains(ov1)) {
2838 if (node1.IsSame(aVertexNode.FindFromKey(ov1))) v1 = ov1;
2839 }
2840 if (aVertexNode.Contains(ov2)) {
2841 if (node1.IsSame(aVertexNode.FindFromKey(ov2))) v1 = ov2;
2842 }
2843 }
2844 // Create map of faces for e1
2845 TopTools_MapOfShape Faces1;
2846 const TopTools_ListOfShape& lfac1 = aBoundFaces.FindFromKey(e1);
2847 if (lfac1.Extent()) {
2848 TopTools_ListIteratorOfListOfShape itf(lfac1);
2849 for (; itf.More(); itf.Next())
2850 if (!itf.Value().IsNull())
2851 Faces1.Add(itf.Value());
2852 }
2853 // Explore edges of the second node
2854 TopTools_ListIteratorOfListOfShape Ie2(ledges2);
2855 for (; Ie2.More() && !Status && !isSameEdge; Ie2.Next()) {
2856 const TopoDS_Shape& e2 = Ie2.Value();
2857 // Obtain real vertex from edge
2858 TopoDS_Shape v2 = node2;
2859 { //szv: Use brackets to destroy local variables
2860 TopoDS_Vertex ov1, ov2;
2861 TopExp::Vertices(TopoDS::Edge(e2),ov1,ov2);
2862 if (aVertexNode.Contains(ov1)) {
2863 if (node2.IsSame(aVertexNode.FindFromKey(ov1))) v2 = ov1;
2864 }
2865 if (aVertexNode.Contains(ov2)) {
2866 if (node2.IsSame(aVertexNode.FindFromKey(ov2))) v2 = ov2;
2867 }
2868 }
2869 // Explore faces for e2
2870 const TopTools_ListOfShape& lfac2 = aBoundFaces.FindFromKey(e2);
2871 if (lfac2.Extent()) {
2872 TopTools_ListIteratorOfListOfShape itf(lfac2);
2873 for (; itf.More() && !Status && !isSameEdge; itf.Next()) {
2874 // Check merging conditions for the same face
2875 if (Faces1.Contains(itf.Value())) {
2876 Standard_Integer stat = IsMergedVertices(itf.Value(),e1,e2,v1,v2);
2877 if (stat == 1) isSameEdge = Standard_True;
2878 else Status = stat;
2879 }
2880 }
2881 }
2882 else if (Faces1.IsEmpty() && e1 == e2) {
2883 Standard_Integer stat = IsMergedVertices(TopoDS_Face(),e1,e1,v1,v2);
2884 if (stat == 1) isSameEdge = Standard_True;
2885 else Status = stat;
2886 break;
2887 }
2888 }
2889 }
2890 if (Status) continue;
2891 if (isSameEdge) listNodesSameEdge.Append(node2);
2892 // Append near node to the sequence
2893 gp_Pnt pt2 = BRep_Tool::Pnt(node2);
2894 Standard_Real dist = pt1.Distance(pt2);
2895 if (dist < Tolerance) {
2896 Standard_Boolean isIns = Standard_False;
2897 for (Standard_Integer kk = 1; kk <= SeqNodes.Length() && !isIns; kk++) {
2898 gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(SeqNodes.Value(kk)));
2899 if (dist < pt1.Distance(pt)) {
2900 SeqNodes.InsertBefore(kk,node2);
2901 isIns = Standard_True;
2902 }
2903 }
2904 if (!isIns) SeqNodes.Append(node2);
2905 }
2906 }
2907 if (SeqNodes.Length()) {
2908 // Remove nodes near to some other from the same edge
2909 if (listNodesSameEdge.Extent()) {
2910 TopTools_ListIteratorOfListOfShape lInt(listNodesSameEdge);
2911 for (; lInt.More(); lInt.Next()) {
2912 const TopoDS_Vertex& n2 = TopoDS::Vertex(lInt.Value());
2913 gp_Pnt p2 = BRep_Tool::Pnt(n2);
2914 for (Standard_Integer k = 1; k <= SeqNodes.Length(); ) {
2915 const TopoDS_Vertex& n1 = TopoDS::Vertex(SeqNodes.Value(k));
2916 if (n1 != n2) {
2917 gp_Pnt p1 = BRep_Tool::Pnt(n1);
2918 if (p2.Distance(p1) >= pt1.Distance(p1)) { k++; continue; }
2919 }
2920 SeqNodes.Remove(k);
2921 }
2922 }
2923 }
2924 // Bind nearest node if at least one exists
2925 if (SeqNodes.Length())
2926 NodeNearestNode.Add(node1,SeqNodes.First());
2927 }
82192477 2928 anInspector.ClearResList();
7fd59977 2929 }
2930
2931 // Create new nodes for chained nearest nodes
2932 if (NodeNearestNode.IsEmpty()) return Standard_False;
7fd59977 2933
2934 return CreateNewNodes(NodeNearestNode,NodeVertices,aVertexNode,aNodeEdges);
2935}
2936
92434a36 2937void BRepBuilderAPI_Sewing::VerticesAssembling(const Handle(Message_ProgressIndicator)& thePI)
7fd59977 2938{
2939 Standard_Integer nbVert = myVertexNode.Extent();
2940 Standard_Integer nbVertFree = myVertexNodeFree.Extent();
92434a36 2941 Message_ProgressSentry aPS (thePI, "Vertices assembling", 0, 2, 1);
7fd59977 2942 if (nbVert || nbVertFree) {
2943 // Fill map node -> sections
2944 Standard_Integer i;
2945 for (i = 1; i <= myBoundFaces.Extent(); i++) {
2946 TopoDS_Shape bound = myBoundFaces.FindKey(i);
2947 for (TopoDS_Iterator itv(bound,Standard_False); itv.More(); itv.Next()) {
2948 TopoDS_Shape node = itv.Value();
2949 if (myNodeSections.IsBound(node))
2950 myNodeSections(node).Append(bound);
2951 else {
2952 TopTools_ListOfShape lbnd;
2953 lbnd.Append(bound);
2954 myNodeSections.Bind(node,lbnd);
2955 }
2956 }
2957 }
2958 // Glue vertices
2959 if (nbVert) {
0797d9d3 2960#ifdef OCCT_DEBUG
7fd59977 2961 cout << "Assemble " << nbVert << " vertices on faces..." << endl;
2962#endif
92434a36 2963 while (GlueVertices(myVertexNode,myNodeSections,myBoundFaces,myTolerance, thePI));
7fd59977 2964 }
92434a36
A
2965 if (!aPS.More())
2966 return;
2967 aPS.Next();
7fd59977 2968 if (nbVertFree) {
0797d9d3 2969#ifdef OCCT_DEBUG
7fd59977 2970 cout << "Assemble " << nbVertFree << " vertices on floating edges..." << endl;
2971#endif
92434a36 2972 while (GlueVertices(myVertexNodeFree,myNodeSections,myBoundFaces,myTolerance, thePI));
7fd59977 2973 }
2974 }
2975}
2976
2977//=======================================================================
2978//function : replaceNMVertices
2979//purpose : internal use (static)
2980//=======================================================================
2981static void replaceNMVertices(const TopoDS_Edge& theEdge,
2982 const TopoDS_Vertex& theV1,
2983 const TopoDS_Vertex& theV2,
2984 const Handle(BRepTools_ReShape)& theReShape)
2985{
2986 //To keep NM vertices on edge
2987 TopTools_SequenceOfShape aSeqNMVert;
2988 TColStd_SequenceOfReal aSeqNMPars;
2989 Standard_Boolean hasNMVert = findNMVertices(theEdge,aSeqNMVert,aSeqNMPars);
2990 if(!hasNMVert)
2991 return;
2992 Standard_Real first, last;
2993 BRep_Tool::Range(theEdge, first, last);
2994 TopLoc_Location aLoc;
2995 Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,aLoc,first, last);
2996 if(c3d.IsNull())
2997 return;
2998 TopTools_SequenceOfShape aEdVert;
2999 TColStd_SequenceOfReal aEdParams;
3000 Standard_Integer i =1, nb = aSeqNMPars.Length();
3001
3002 for( ; i <= nb;i++) {
3003 Standard_Real apar = aSeqNMPars.Value(i);
3004 if(fabs(apar - first) <= Precision::PConfusion()) {
3005 theReShape->Replace(aSeqNMVert.Value(i),theV1);
3006 continue;
3007 }
3008 if(fabs(apar - last) <= Precision::PConfusion()) {
3009 theReShape->Replace(aSeqNMVert.Value(i),theV2);
3010 continue;
3011 }
3012 TopoDS_Shape aV = aSeqNMVert.Value(i);
3013 Standard_Integer j =1;
3014 for( ; j <= aEdParams.Length();j++) {
3015 Standard_Real apar2 = aEdParams.Value(j);
3016 if(fabs(apar - apar2) <= Precision::PConfusion()) {
3017 theReShape->Replace(aV,aEdVert.Value(j));
3018 break;
3019 }
3020 else if(apar < apar2) {
3021 TopoDS_Shape anewV = aV.EmptyCopied();
3022 aEdVert.InsertBefore(j,anewV);
3023 aEdParams.InsertBefore(j,apar);
3024 BRep_ListOfPointRepresentation& alistrep =
3025 (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints();
3026 Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
3027 alistrep.Append(aPRep);
3028 theReShape->Replace(aV,anewV);
3029 break;
3030 }
3031 }
3032 if (j > aEdParams.Length()) {
3033 TopoDS_Shape anewV = aV.EmptyCopied();
3034 aEdVert.Append(anewV);
3035 aEdParams.Append(apar);
3036 BRep_ListOfPointRepresentation& alistrep =
3037 (*((Handle(BRep_TVertex)*) &anewV.TShape()))->ChangePoints();
3038 Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
3039 alistrep.Append(aPRep);
3040 theReShape->Replace(aV,anewV);
3041 }
3042 }
3043
3044 Standard_Integer newnb = aEdParams.Length();
3045 if(newnb < nb) {
3046
3047 TopoDS_Shape anewEdge = theEdge.EmptyCopied();
3048 TopAbs_Orientation anOri = theEdge.Orientation();
3049 anewEdge.Orientation(TopAbs_FORWARD);
3050 BRep_Builder aB;
3051 aB.Add(anewEdge,theV1);
3052 aB.Add(anewEdge,theV2);
3053
3054 for( i =1; i <= aEdVert.Length();i++)
3055 aB.Add(anewEdge,aEdVert.Value(i));
3056 anewEdge.Orientation(anOri);
3057 theReShape->Replace(theEdge,anewEdge);
3058 }
3059
3060}
3061
3062//=======================================================================
3063//function : ReplaceEdge
3064//purpose : internal use (static)
3065//=======================================================================
3066
3067static void ReplaceEdge(const TopoDS_Shape& oldEdge,
3068 const TopoDS_Shape& theNewShape,
3069 const Handle(BRepTools_ReShape)& aReShape)
3070{
3071 TopoDS_Shape oldShape = aReShape->Apply(oldEdge);
3072 TopoDS_Shape newShape = aReShape->Apply(theNewShape);
3073 if (oldShape.IsSame(newShape)|| aReShape->IsRecorded(newShape)) return;
3074
3075
3076 aReShape->Replace(oldShape,newShape);
3077 TopoDS_Vertex V1old,V2old,V1new,V2new;
3078 TopExp::Vertices(TopoDS::Edge(oldShape),V1old,V2old);
3079 TopAbs_Orientation Orold = oldShape.Orientation();
3080 TopAbs_Orientation Ornew = Orold;
3081 if (newShape.ShapeType() == TopAbs_EDGE) {
3082 TopoDS_Edge aEn = TopoDS::Edge(newShape);
3083 TopExp::Vertices(aEn,V1new,V2new);
3084 Ornew = aEn.Orientation();
3085 replaceNMVertices(aEn,V1new,V2new,aReShape);
3086 }
3087 else if (newShape.ShapeType() == TopAbs_WIRE) {
3088 for (TopExp_Explorer aex(newShape,TopAbs_EDGE); aex.More(); aex.Next()) {
3089 TopoDS_Edge ed = TopoDS::Edge(aex.Current());
3090 Ornew = ed.Orientation();
3091 TopoDS_Vertex aV1,aV2;
3092 TopExp::Vertices(ed,aV1,aV2);
3093 replaceNMVertices(ed,aV1,aV2,aReShape);
3094 if (V1new.IsNull())
3095 V1new = aV1;
3096 V2new =aV2;
3097 }
3098 }
3099
3100 V1new.Orientation(V1old.Orientation());
3101 V2new.Orientation(V2old.Orientation());
3102 if (V1old.IsSame(V2old) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) {
3103 aReShape->Replace(V1old,V1new);
3104 return;
3105 }
3106 if (Orold == Ornew) {
3107 V1new.Orientation(V1old.Orientation());
3108 V2new.Orientation(V2old.Orientation());
3109 if (!V1old.IsSame(V1new) && !V1old.IsSame(V2new)&& !aReShape->IsRecorded(V1new))
3110 aReShape->Replace(V1old,V1new);
3111 if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3112 aReShape->Replace(V2old,V2new);
3113 }
3114 else {
3115 V1new.Orientation(V2old.Orientation());
3116 V2new.Orientation(V1old.Orientation());
3117 if (!V1old.IsSame(V2new) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3118 aReShape->Replace(V1old,V2new);
3119 if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V1new))
3120 aReShape->Replace(V2old,V1new);
3121 }
3122}
3123
3124//=======================================================================
3125//function : Merging
3126//purpose : Modifies :
3127// myHasFreeBound
3128//
3129//=======================================================================
3130
92434a36
A
3131void BRepBuilderAPI_Sewing::Merging(const Standard_Boolean /* firstTime */,
3132 const Handle(Message_ProgressIndicator)& thePI)
7fd59977 3133{
3134 BRep_Builder B;
3135 // TopTools_MapOfShape MergedEdges;
92434a36
A
3136 Message_ProgressSentry aPS (thePI, "Merging bounds", 0, myBoundFaces.Extent(), 1);
3137 for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
7fd59977 3138
3139 TopoDS_Shape bound = myBoundFaces.FindKey(i);
3140
3141 // If bound was already merged - continue
3142 if (myMergedEdges.Contains(bound)) continue;
3143
3144 if (!myBoundFaces(i).Extent()) {
3145 // Merge free edge - only vertices
3146 TopoDS_Vertex no1, no2;
3147 TopExp::Vertices(TopoDS::Edge(bound),no1,no2);
3148 TopoDS_Shape nno1 = no1, nno2 = no2;
3149 if (myVertexNodeFree.Contains(no1))
3150 nno1 = myVertexNodeFree.FindFromKey(no1);
3151 if (myVertexNodeFree.Contains(no2))
3152 nno2 = myVertexNodeFree.FindFromKey(no2);
3153 if (!no1.IsSame(nno1)) {
3154 nno1.Orientation(no1.Orientation());
3155 myReShape->Replace(no1,nno1);
3156 }
3157 if (!no2.IsSame(nno2)) {
3158 nno2.Orientation(no2.Orientation());
3159 myReShape->Replace(no2,nno2);
3160 }
3161 myMergedEdges.Add(bound);
3162 continue;
3163 }
3164
3165 // Check for previous splitting, build replacing wire
3166 TopoDS_Wire BoundWire;
3167 Standard_Boolean isPrevSplit = Standard_False;
3168 Standard_Boolean hasCuttingSections = myBoundSections.IsBound(bound);
3169 if (hasCuttingSections) {
3170 B.MakeWire(BoundWire);
3171 BoundWire.Orientation(bound.Orientation());
3172 // Iterate on cutting sections
3173 TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3174 for (; its.More(); its.Next()) {
3175 TopoDS_Shape section = its.Value();
3176 B.Add(BoundWire,section);
3177 if (myMergedEdges.Contains(section)) isPrevSplit = Standard_True;
3178 }
3179 }
3180
3181 // Merge with bound
3182 TopTools_DataMapOfShapeShape MergedWithBound;
3183 if (!isPrevSplit) {
3184 // Obtain sequence of edges merged with bound
3185 TopTools_SequenceOfShape seqMergedWithBound;
3186 TColStd_SequenceOfInteger seqMergedWithBoundOri;
3187 if (MergedNearestEdges(bound,seqMergedWithBound,seqMergedWithBoundOri)) {
3188 // Store bound in the map
3189 MergedWithBound.Bind(bound,bound);
3190 // Iterate on edges merged with bound
3191 Standard_Integer ii = 1;
3192 while (ii <= seqMergedWithBound.Length()) {
3193 TopoDS_Shape iedge = seqMergedWithBound.Value(ii);
3194 // Remove edge if recorded as merged
3195 Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) ||
3196 MergedWithBound.IsBound(iedge));
3197 if (!isRejected) {
3198 if (myBoundSections.IsBound(iedge)) {
3199 // Edge is splitted - check sections
3200 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3201 for (; lit.More() && !isRejected; lit.Next()) {
3202 const TopoDS_Shape& sec = lit.Value();
3203 // Remove edge (bound) if at least one of its sections already merged
3204 isRejected = (myMergedEdges.Contains(sec) || MergedWithBound.IsBound(sec));
3205 }
3206 }
3207 if (!isRejected) {
3208 if (mySectionBound.IsBound(iedge)) {
3209 // Edge is a section - check bound
3210 const TopoDS_Shape& bnd = mySectionBound(iedge);
3211 // Remove edge (section) if its bound already merged
3212 isRejected = (myMergedEdges.Contains(bnd) || MergedWithBound.IsBound(bnd));
3213 }
3214 }
3215 }
3216 // To the next merged edge
3217 if (isRejected) {
3218 // Remove rejected edge
3219 seqMergedWithBound.Remove(ii);
3220 seqMergedWithBoundOri.Remove(ii);
3221 }
3222 else {
3223 // Process accepted edge
3224 MergedWithBound.Bind(iedge,iedge);
3225 ii++;
3226 }
3227 }
3228 Standard_Integer nbMerged = seqMergedWithBound.Length();
3229 if (nbMerged) {
3230 // Create same parameter edge
3231 TopTools_MapOfShape ActuallyMerged;
3232 TopoDS_Edge MergedEdge = SameParameterEdge(bound,seqMergedWithBound,
3233 seqMergedWithBoundOri,
3234 ActuallyMerged,myReShape);
3235 Standard_Boolean isForward = Standard_False;
3236 if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3237 // Process actually merged edges
3238 Standard_Integer nbActuallyMerged = 0;
3239 for (ii = 1; ii <= nbMerged; ii++) {
3240 TopoDS_Shape iedge = seqMergedWithBound(ii);
3241 if (ActuallyMerged.Contains(iedge)) {
3242 nbActuallyMerged++;
3243 // Record merged edge in the map
3244 TopAbs_Orientation orient = iedge.Orientation();
3245 if (!isForward) orient = TopAbs::Reverse(orient);
3246 if (!seqMergedWithBoundOri(ii)) orient = TopAbs::Reverse(orient);
3247 MergedWithBound.ChangeFind(iedge) = MergedEdge.Oriented(orient);
3248 }
3249 else MergedWithBound.UnBind(iedge);
3250 }
3251 if (nbActuallyMerged) {
3252 // Record merged bound in the map
3253 TopAbs_Orientation orient = bound.Orientation();
3254 if (!isForward) orient = TopAbs::Reverse(orient);
3255 MergedWithBound.ChangeFind(bound) = MergedEdge.Oriented(orient);
3256 }
3257 nbMerged = nbActuallyMerged;
3258 }
3259 // Remove bound from the map if not finally merged
3260 if (!nbMerged) MergedWithBound.UnBind(bound);
3261 }
3262 }
3263 Standard_Boolean isMerged = MergedWithBound.Extent();
3264
3265 // Merge with cutting sections
3266 Handle(BRepTools_ReShape) SectionsReShape = new BRepTools_ReShape;
3267 TopTools_DataMapOfShapeShape MergedWithSections;
3268 if (hasCuttingSections) {
3269 // Iterate on cutting sections
3270 TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3271 for (; its.More(); its.Next()) {
3272 // Retrieve cutting section
3273 TopoDS_Shape section = its.Value();
3274 // Skip section if already merged
3275 if (myMergedEdges.Contains(section)) continue;
3276 // Merge cutting section
3277 TopTools_SequenceOfShape seqMergedWithSection;
3278 TColStd_SequenceOfInteger seqMergedWithSectionOri;
3279 if (MergedNearestEdges(section,seqMergedWithSection,seqMergedWithSectionOri)) {
3280 // Store section in the map
3281 MergedWithSections.Bind(section,section);
3282 // Iterate on edges merged with section
3283 Standard_Integer ii = 1;
3284 while (ii <= seqMergedWithSection.Length()) {
3285 TopoDS_Shape iedge = seqMergedWithSection.Value(ii);
3286 // Remove edge if recorded as merged
3287 Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || MergedWithSections.IsBound(iedge));
3288 if (!isRejected) {
3289 if (myBoundSections.IsBound(iedge)) {
3290 // Edge is splitted - check sections
3291 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3292 for (; lit.More() && !isRejected; lit.Next()) {
3293 const TopoDS_Shape& sec = lit.Value();
3294 // Remove edge (bound) if at least one of its sections already merged
3295 isRejected = (myMergedEdges.Contains(sec) || MergedWithSections.IsBound(sec));
3296 }
3297 }
3298 if (!isRejected) {
3299 if (mySectionBound.IsBound(iedge)) {
3300 // Edge is a section - check bound
3301 const TopoDS_Shape& bnd = mySectionBound(iedge);
3302 // Remove edge (section) if its bound already merged
3303 isRejected = (myMergedEdges.Contains(bnd) || MergedWithSections.IsBound(bnd));
3304 }
3305 }
3306 }
3307 // To the next merged edge
3308 if (isRejected) {
3309 // Remove rejected edge
3310 seqMergedWithSection.Remove(ii);
3311 seqMergedWithSectionOri.Remove(ii);
3312 }
3313 else {
3314 // Process accepted edge
3315 MergedWithSections.Bind(iedge,iedge);
3316 ii++;
3317 }
3318 }
3319 Standard_Integer nbMerged = seqMergedWithSection.Length();
3320 if (nbMerged) {
3321 // Create same parameter edge
3322 TopTools_MapOfShape ActuallyMerged;
3323 TopoDS_Edge MergedEdge = SameParameterEdge(section,seqMergedWithSection,
3324 seqMergedWithSectionOri,
3325 ActuallyMerged,SectionsReShape);
3326 Standard_Boolean isForward = Standard_False;
3327 if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3328 // Process actually merged edges
3329 Standard_Integer nbActuallyMerged = 0;
3330 for (ii = 1; ii <= nbMerged; ii++) {
3331 TopoDS_Shape iedge = seqMergedWithSection(ii);
3332 if (ActuallyMerged.Contains(iedge)) {
3333 nbActuallyMerged++;
3334 // Record merged edge in the map
3335 TopAbs_Orientation orient = iedge.Orientation();
3336 if (!isForward) orient = TopAbs::Reverse(orient);
3337 if (!seqMergedWithSectionOri(ii)) orient = TopAbs::Reverse(orient);
3338 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3339 MergedWithSections.ChangeFind(iedge) = oedge;
3340 ReplaceEdge(myReShape->Apply(iedge),oedge,SectionsReShape);
3341 }
3342 else MergedWithSections.UnBind(iedge);
3343 }
3344 if (nbActuallyMerged) {
3345 // Record merged section in the map
3346 TopAbs_Orientation orient = section.Orientation();
3347 if (!isForward) orient = TopAbs::Reverse(orient);
3348 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3349 MergedWithSections.ChangeFind(section) = oedge;
3350 ReplaceEdge(myReShape->Apply(section),oedge,SectionsReShape);
3351 }
3352 nbMerged = nbActuallyMerged;
3353 }
3354 // Remove section from the map if not finally merged
3355 if (!nbMerged) MergedWithSections.UnBind(section);
3356 }
3357 else if (isMerged) {
3358 // Reject merging of sections
3359 MergedWithSections.Clear();
3360 break;
3361 }
3362 }
3363 }
3364 Standard_Boolean isMergedSplit = MergedWithSections.Extent();
3365
3366 if (!isMerged && !isMergedSplit) {
3367 // Nothing was merged in this iteration
3368 if (isPrevSplit) {
3369 // Replace previously splitted bound
3370 myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3371 }
3372 // else if (hasCuttingSections) {
3373 // myBoundSections.UnBind(bound); //szv: are you sure ???
3374 // }
3375 continue;
3376 }
3377
3378 // Set splitting flag
3379 Standard_Boolean isSplitted = ((!isMerged && isMergedSplit) || isPrevSplit);
3380
3381 // Choose between bound and sections merging
3382 if (isMerged && isMergedSplit && !isPrevSplit) {
3383 // Fill map of merged cutting sections
3384 TopTools_MapOfShape MapSplitEdges;
3385 TopTools_DataMapIteratorOfDataMapOfShapeShape itm;
3386 for (itm.Initialize(MergedWithSections); itm.More(); itm.Next()) {
3387 TopoDS_Shape edge = itm.Key();
3388 MapSplitEdges.Add(edge);
3389 }
3390 // Iterate on edges merged with bound
3391 for (itm.Initialize(MergedWithBound); itm.More(); itm.Next()) {
3392 // Retrieve edge merged with bound
3393 TopoDS_Shape edge = itm.Key();
3394 // Remove edge from the map
3395 if (MapSplitEdges.Contains(edge)) MapSplitEdges.Remove(edge);
3396 if (myBoundSections.IsBound(edge)) {
3397 // Edge has cutting sections
3398 TopTools_ListIteratorOfListOfShape its(myBoundSections(edge));
3399 for (; its.More(); its.Next()) {
3400 TopoDS_Shape sec = its.Value();
3401 // Remove section from the map
3402 if (MapSplitEdges.Contains(sec)) MapSplitEdges.Remove(sec);
3403 }
3404 }
3405 }
3406 // Calculate section merging tolerance
3407 Standard_Real MinSplitTol = RealLast();
3408 TopTools_MapIteratorOfMapOfShape im(MapSplitEdges);
3409 for (; im.More(); im.Next()) {
3410 TopoDS_Edge edge = TopoDS::Edge(MergedWithSections(im.Key()));
3411 MinSplitTol = Min(MinSplitTol,BRep_Tool::Tolerance(edge));
3412 }
3413 // Calculate bound merging tolerance