0023375: (OCC 6.5.3 regression) BRepBuilderAPI_Sewing returns wrong result
[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
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21// dcl CCI60011 : Correction of degeneratedSection
22// Improvement of SameParameter Edge to treat case of failure in BRepLib::SameParameter
23// dcl Thu Aug 20 09:24:49 1998
24// Suppression of little faces.
25// dcl Fri Aug 7 15:27:46 1998
26// Refection of function SameParameter Edge.
27// Merge on the edge which has the less of poles.
28// Suppression of the Connected Edge function.
29// dcl Tue Jun 9 14:21:53 1998
30// Do not merge edge if they belong the same face
31// Tolerance management in VerticesAssembling
32// Tolerance management in Cutting
33// dcl Thu May 14 15:51:46 1998
34// optimization of cutting
35// dcl Thu May 7 15:51:46 1998
36// Add of cutting option
37// Add of SameParameter call
38
39
0d969553
Y
40//-- lbr April 1 97
41//-- dpf December 10 1997 Processing of pcurve collections
7fd59977 42
43//rln 02.02.99 BUC60449 Making compilable on NT in DEB mode
44//rln 02.02.99 BUC60449 Protection against exception on NT
45
46#define TEST 1
47
48#include <BRepBuilderAPI_Sewing.ixx>
49
50#include <Bnd_Box.hxx>
51#include <Bnd_Box2d.hxx>
52#include <Bnd_HArray1OfBox.hxx>
53#include <BndLib_Add2dCurve.hxx>
54#include <BndLib_Add3dCurve.hxx>
55#include <BRep_Builder.hxx>
56#include <BRep_Tool.hxx>
57#include <BRepLib.hxx>
58#include <BRepTools_Quilt.hxx>
59#include <BSplCLib.hxx>
60#include <Extrema_ExtPC.hxx>
61#include <GCPnts_AbscissaPoint.hxx>
62#include <GCPnts_UniformAbscissa.hxx>
63#include <GCPnts_UniformDeflection.hxx>
64#include <Geom2d_BezierCurve.hxx>
65#include <Geom2d_BSplineCurve.hxx>
66#include <Geom2d_Curve.hxx>
67#include <Geom2d_Line.hxx>
68#include <Geom2d_TrimmedCurve.hxx>
69#include <Geom2dAdaptor_Curve.hxx>
70#include <Geom2dConvert.hxx>
71#include <Geom_BezierCurve.hxx>
72#include <Geom_BSplineCurve.hxx>
73#include <Geom_Curve.hxx>
74#include <Geom_Line.hxx>
75#include <Geom_Surface.hxx>
76#include <GeomAdaptor_Curve.hxx>
77#include <GeomAdaptor_Surface.hxx>
78#include <GeomLib.hxx>
79#include <gp_Pnt.hxx>
80#include <gp_Vec.hxx>
81//#include <LocalAnalysis_SurfaceContinuity.hxx>
82#include <Precision.hxx>
83#include <Standard_ErrorHandler.hxx>
84#include <Standard_Failure.hxx>
85#include <TColgp_Array1OfVec.hxx>
86#include <TColgp_SequenceOfPnt.hxx>
87#include <TColStd_Array1OfInteger.hxx>
88#include <TColStd_Array1OfReal.hxx>
89#include <TColStd_DataMapIteratorOfDataMapOfIntegerListOfInteger.hxx>
90#include <TColStd_DataMapOfIntegerListOfInteger.hxx>
91#include <TColStd_IndexedMapOfInteger.hxx>
92#include <TColStd_ListIteratorOfListOfInteger.hxx>
93#include <TColStd_ListOfInteger.hxx>
94#include <TColStd_MapOfInteger.hxx>
95#include <TColStd_SequenceOfReal.hxx>
96#include <TopAbs.hxx>
97#include <TopExp.hxx>
98#include <TopExp_Explorer.hxx>
99#include <TopLoc_Location.hxx>
100#include <TopoDS.hxx>
101#include <TopoDS_Edge.hxx>
102#include <TopoDS_Iterator.hxx>
103#include <TopoDS_Shape.hxx>
104#include <TopoDS_Vertex.hxx>
105#include <TopoDS_Wire.hxx>
106#include <TopoDS_Shell.hxx>
107#include <TopTools_Array1OfShape.hxx>
108#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
109#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
110#include <TopTools_DataMapOfShapeInteger.hxx>
111#include <TopTools_DataMapOfShapeListOfShape.hxx>
112#include <TopTools_ListIteratorOfListOfShape.hxx>
113#include <TopTools_ListOfShape.hxx>
114#include <TopTools_MapIteratorOfMapOfShape.hxx>
115#include <TopTools_MapOfShape.hxx>
116#include <TopTools_SequenceOfShape.hxx>
117#include <TopoDS_Compound.hxx>
118#include <TColStd_Array2OfReal.hxx>
119#include <TColStd_MapIteratorOfMapOfInteger.hxx>
120#include <BRepTools.hxx>
121#include <Geom_RectangularTrimmedSurface.hxx>
122#include <Geom_OffsetSurface.hxx>
123#include <BRep_PointOnCurve.hxx>
124#include <BRep_ListOfPointRepresentation.hxx>
125#include <BRep_TVertex.hxx>
92434a36 126#include <Message_ProgressSentry.hxx>
82192477 127#include <BRepBuilderAPI_VertexInspector.hxx>
128#include <BRepBuilderAPI_CellFilter.hxx>
129#include <BRepBuilderAPI_BndBoxTreeSelector.hxx>
130#include <NCollection_UBTreeFiller.hxx>
7fd59977 131
132static void SortBox (const Handle(Bnd_HArray1OfBox) hSetBoxes,
133 const Bnd_Box& aBox,
134 TColStd_ListOfInteger& listIndex)
135{
136 Standard_Integer i, nbBoxes = hSetBoxes->Length();
137 for (i = 1; i <= nbBoxes; i++)
138 if (!aBox.IsOut(hSetBoxes->Value(i)))
139 listIndex.Append(i);
140}
141
142//=======================================================================
143//function : SameRange
144//purpose :
145//=======================================================================
146
147Handle(Geom2d_Curve) BRepBuilderAPI_Sewing::SameRange(const Handle(Geom2d_Curve)& CurvePtr,
148 const Standard_Real FirstOnCurve,
149 const Standard_Real LastOnCurve,
150 const Standard_Real RequestedFirst,
151 const Standard_Real RequestedLast) const
152{
153 Handle(Geom2d_Curve) NewCurvePtr;
154 try {
155
156 GeomLib::SameRange(Precision::PConfusion(),CurvePtr,FirstOnCurve,LastOnCurve,
157 RequestedFirst,RequestedLast,NewCurvePtr);
158 }
159 catch (Standard_Failure) {
160#ifdef DEB
161 cout << "Exception in BRepBuilderAPI_Sewing::SameRange: ";
162 Standard_Failure::Caught()->Print(cout); cout << endl;
163#endif
164 }
165 return NewCurvePtr;
166}
167
168//=======================================================================
169//function : WhichFace
0d969553 170//purpose : Give the face whose edge is the border
7fd59977 171//=======================================================================
172
173TopoDS_Face BRepBuilderAPI_Sewing::WhichFace(const TopoDS_Edge& theEdg, const Standard_Integer index) const
174{
175 TopoDS_Shape bound = theEdg;
176 if (mySectionBound.IsBound(bound)) bound = mySectionBound(bound);
177 if (myBoundFaces.Contains(bound)) {
178 Standard_Integer i = 1;
179 TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bound));
180 for (; itf.More(); itf.Next(), i++)
181 if (i == index) return TopoDS::Face(itf.Value());
182 }
183 return TopoDS_Face();
184}
185
186//=======================================================================
187//function : IsClosedShape
188//purpose :
189//=======================================================================
190
191static Standard_Boolean IsClosedShape(const TopoDS_Shape& theshape,
192 const TopoDS_Shape& v1, const TopoDS_Shape& v2)
193{
194 Standard_Real TotLength = 0.0;
195 TopExp_Explorer aexp;
196 for (aexp.Init(theshape,TopAbs_EDGE); aexp.More(); aexp.Next()) {
197 TopoDS_Edge aedge = TopoDS::Edge(aexp.Current());
198 if (aedge.IsNull()) continue;
199 TopoDS_Vertex ve1,ve2;
200 TopExp::Vertices(aedge,ve1,ve2);
201 if (!ve1.IsSame(v1) && !ve1.IsSame(v2)) continue;
202 if (BRep_Tool::Degenerated(aedge)) continue;
203 Standard_Real first,last;
204 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aedge), first, last);
205 if (!c3d.IsNull()) {
206 GeomAdaptor_Curve cAdapt(c3d);
207 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
208 TotLength += length;
209 if (ve2.IsSame(v1) || ve2.IsSame(v2)) break;
210 }
211 }
212 if (TotLength > 0.0) {
213 gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(v1));
214 gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(v2));
c6541a0c 215 return (p1.Distance(p2) < TotLength/(1.2 * M_PI));
7fd59977 216 }
217 return Standard_False;
218}
219
220//=======================================================================
221//function : IsClosedByIsos
222//purpose :
223//=======================================================================
224static Standard_Boolean IsClosedByIsos(const Handle(Geom_Surface)& thesurf,
225 const Handle(Geom2d_Curve)& acrv2d,
226 const Standard_Real f2d,
227 const Standard_Real l2d,
228 const Standard_Boolean isUIsos)
229{
230 Standard_Boolean isClosed = Standard_False;
231
232 gp_Pnt2d psurf1 = (acrv2d->IsPeriodic() ?
233 acrv2d->Value(f2d) : acrv2d->Value(Max(f2d,acrv2d->FirstParameter())));
234 gp_Pnt2d psurf2 = (acrv2d->IsPeriodic() ?
235 acrv2d->Value(l2d) : acrv2d->Value(Min(l2d,acrv2d->LastParameter())));
236 Handle(Geom_Curve) aCrv1;
237 Handle(Geom_Curve) aCrv2;
238 if(isUIsos) {
239 aCrv1 = thesurf->UIso(psurf1.X());
240 aCrv2 = thesurf->UIso(psurf2.X());
241 }
242 else {
243 aCrv1 = thesurf->VIso(psurf1.Y());
244 aCrv2 = thesurf->VIso(psurf2.Y());
245 }
246 gp_Pnt p11,p1m,p12,p21,p2m,p22;
247 Standard_Real af1 = aCrv1->FirstParameter();
248 Standard_Real al1 = aCrv1->LastParameter();
249 Standard_Real af2 = aCrv2->FirstParameter();
250 Standard_Real al2 = aCrv2->LastParameter();
251 aCrv1->D0(af1,p11);
252 aCrv1->D0((af1+al1)*0.5,p1m);
253 aCrv1->D0(al1,p12);
254 aCrv2->D0(af2,p21);
255 aCrv2->D0((af2+al2)*0.5,p2m);
256 aCrv2->D0(al2,p22);
257 isClosed = (((p11.XYZ() - p12.XYZ()).Modulus() <
258 (p11.XYZ() - p1m.XYZ()).Modulus() - Precision::Confusion()) &&
259 ((p21.XYZ() - p22.XYZ()).Modulus() <
260 (p21.XYZ() - p2m.XYZ()).Modulus() - Precision::Confusion())) ;
261 return isClosed;
262}
263//=======================================================================
264//function : IsUClosedSurface
265//purpose :
266//=======================================================================
267
268Standard_Boolean BRepBuilderAPI_Sewing::IsUClosedSurface(const Handle(Geom_Surface)& surf,
269 const TopoDS_Shape& theEdge,
270 const TopLoc_Location& theloc) const
271{
272 Handle(Geom_Surface) tmpsurf = surf;
273 if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
274 tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
275 else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
276 tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
277 else {
278 Standard_Boolean isClosed = tmpsurf->IsUClosed();
279 if(!isClosed) {
280 Standard_Real f2d, l2d;
281 Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
282 if(!acrv2d.IsNull())
283 isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_False );
284
285 }
286 return isClosed;
287 }
288 return IsUClosedSurface(tmpsurf,theEdge,theloc);
289 //return surf->IsUClosed();
290}
291
292//=======================================================================
293//function : IsVClosedSurface
294//purpose :
295//=======================================================================
296
297Standard_Boolean BRepBuilderAPI_Sewing::IsVClosedSurface(const Handle(Geom_Surface)& surf,
298 const TopoDS_Shape& theEdge,
299 const TopLoc_Location& theloc) const
300{
301 Handle(Geom_Surface) tmpsurf = surf;
302 if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
303 tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface();
304 else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
305 tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface();
306 else {
307 Standard_Boolean isClosed = tmpsurf->IsVClosed();
308 if(!isClosed) {
309 Standard_Real f2d, l2d;
310 Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d);
311 if(!acrv2d.IsNull())
312 isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_True );
313 }
314 return isClosed;
315 }
316 return IsVClosedSurface(tmpsurf,theEdge,theloc);
317 //return surf->IsVClosed();
318}
319
320//=======================================================================
321//function : SameParameter
322//purpose : internal use
323//=======================================================================
324
325void BRepBuilderAPI_Sewing::SameParameter(const TopoDS_Edge& edge) const
326{
327 try {
328
329 BRepLib::SameParameter(edge);
330 }
331 catch (Standard_Failure) {
332#ifdef DEB
333 cout << "Exception in BRepBuilderAPI_Sewing::SameParameter: ";
334 Standard_Failure::Caught()->Print(cout); cout << endl;
335#endif
336 }
337}
338
339//=======================================================================
340//function : SameParameterEdge
341//purpose : internal use
342// Merge the Sequence Of Section on one edge.
343// This function keep the curve3d,curve2d,range and parametrization
344// from the first section, and report and made sameparameter the
345// pcurves of the other function.
346// This function works when the are not more than two Pcurves
347// on a same face.
348//=======================================================================
349
350TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Shape& edge,
351 const TopTools_SequenceOfShape& seqEdges,
352 const TColStd_SequenceOfInteger& seqForward,
353 TopTools_MapOfShape& mapMerged,
354 const Handle(BRepTools_ReShape)& locReShape)
355{
356 // Retrieve reference section
357 TopoDS_Shape aTmpShape = myReShape->Apply(edge); //for porting
358 TopoDS_Edge Edge1 = TopoDS::Edge(aTmpShape);
359 aTmpShape = locReShape->Apply(Edge1);
360 if (locReShape != myReShape) Edge1 = TopoDS::Edge(aTmpShape);
361 Standard_Boolean isDone = Standard_False;
362
363 // Create data structures for temporary merged edges
364 TopTools_ListOfShape listFaces1;
365 TopTools_MapOfShape MergedFaces;
366
367 if (mySewing) {
368
369 // Fill MergedFaces with faces of Edge1
370 TopoDS_Shape bnd1 = edge;
371 if (mySectionBound.IsBound(bnd1)) bnd1 = mySectionBound(bnd1);
372 if (myBoundFaces.Contains(bnd1)) {
373 TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bnd1));
374 for (; itf.More(); itf.Next())
375 if (MergedFaces.Add(itf.Value()))
376 listFaces1.Append(itf.Value());
377 }
378 }
379 else {
380
381 // Create presentation edge
382 TopoDS_Vertex V1, V2;
383 TopExp::Vertices(Edge1,V1,V2);
384 if (myVertexNode.Contains(V1)) V1 = TopoDS::Vertex(myVertexNode.FindFromKey(V1));
385 if (myVertexNode.Contains(V2)) V2 = TopoDS::Vertex(myVertexNode.FindFromKey(V2));
386
387 TopoDS_Edge NewEdge = Edge1;
388 NewEdge.EmptyCopy();
389
390 // Add the vertices
391 BRep_Builder aBuilder;
392 TopoDS_Shape anEdge = NewEdge.Oriented(TopAbs_FORWARD);
393 aBuilder.Add(anEdge,V1.Oriented(TopAbs_FORWARD));
394 aBuilder.Add(anEdge,V2.Oriented(TopAbs_REVERSED));
395
396 Edge1 = NewEdge;
397 }
398
399 Standard_Boolean isForward = Standard_True;
400
401 // Merge candidate sections
402 for (Standard_Integer i = 1; i <= seqEdges.Length(); i++) {
403
404 // Retrieve candidate section
405 TopoDS_Shape oedge2 = seqEdges(i);
406
407 if (mySewing) {
408
409 aTmpShape = myReShape->Apply(oedge2); //for porting
410 TopoDS_Edge Edge2 = TopoDS::Edge(aTmpShape);
411 aTmpShape = locReShape->Apply(Edge2);
412 if (locReShape != myReShape) Edge2 = TopoDS::Edge(aTmpShape);
413
414 // Calculate relative orientation
415 Standard_Integer Orientation = seqForward(i);
416 if (!isForward) Orientation = (Orientation? 0 : 1);
417
418 // Retrieve faces information for the second edge
419 TopoDS_Shape bnd2 = oedge2;
420 if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
421 if (!myBoundFaces.Contains(bnd2)) continue; // Skip floating edge
422 const TopTools_ListOfShape& listFaces2 = myBoundFaces.FindFromKey(bnd2);
423
424 Standard_Integer whichSec = 1; // Indicates on which edge the pCurve has been reported
425 TopoDS_Edge NewEdge = SameParameterEdge(Edge1,Edge2,listFaces1,listFaces2,Orientation,whichSec);
426 if (NewEdge.IsNull()) continue;
427
428 // Record faces information for the temporary merged edge
429 TopTools_ListIteratorOfListOfShape itf(listFaces2);
430 for (; itf.More(); itf.Next())
431 if (MergedFaces.Add(itf.Value()))
432 listFaces1.Append(itf.Value());
433
434 // Record merged section orientation
435 if (!Orientation && whichSec != 1)
436 isForward = isForward? Standard_False : Standard_True;
437 Edge1 = NewEdge;
438 }
439
440 // Append actually merged edge
441 mapMerged.Add(oedge2);
442 isDone = Standard_True;
443
444 if (!myNonmanifold) break;
445 }
446
447 if (isDone) {
448 // Change result orientation
449 Edge1.Orientation(isForward? TopAbs_FORWARD : TopAbs_REVERSED);
450 }
451 else Edge1.Nullify();
452
453 return Edge1;
454}
455
456//=======================================================================
457//function : SameParameterEdge
458//purpose : internal use
459//=======================================================================
460static Standard_Boolean findNMVertices(const TopoDS_Edge& theEdge,
461 TopTools_SequenceOfShape& theSeqNMVert,
462 TColStd_SequenceOfReal& theSeqPars)
463{
464 TopoDS_Iterator aItV(theEdge,Standard_False);
465 for( ; aItV.More(); aItV.Next()) {
466 if(aItV.Value().Orientation() == TopAbs_INTERNAL ||
467 aItV.Value().Orientation() == TopAbs_EXTERNAL)
468 theSeqNMVert.Append(aItV.Value());
469 }
470 Standard_Integer nbV = theSeqNMVert.Length();
471 if(!nbV)
472 return Standard_False;
473 Standard_Real first, last;
474 Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,first, last);
475 GeomAdaptor_Curve GAC(c3d);
476 Extrema_ExtPC locProj;
477 locProj.Initialize(GAC, first, last);
478 gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
479
480
481 for (Standard_Integer i = 1; i <= nbV; i++) {
482 TopoDS_Vertex aV = TopoDS::Vertex(theSeqNMVert.Value(i));
483 gp_Pnt pt = BRep_Tool::Pnt(aV);
484
485 Standard_Real distF2 = pfirst.SquareDistance(pt);
486 Standard_Real distL2 = plast.SquareDistance(pt);
487 Standard_Real apar = (distF2 > distL2 ? last : first);
488 // Project current point on curve
489 locProj.Perform(pt);
490 if (locProj.IsDone() && locProj.NbExt() > 0) {
491 Standard_Real dist2Min = Min(distF2,distL2);
492 Standard_Integer ind, indMin = 0;
493 for (ind = 1; ind <= locProj.NbExt(); ind++) {
494 Standard_Real dProj2 = locProj.SquareDistance(ind);
495 if (dProj2 < dist2Min) {
496 indMin = ind; dist2Min = dProj2;
497 }
498 }
499 if(indMin)
500 apar = locProj.Point(indMin).Parameter();
501
502 theSeqPars.Append(apar);
503
504 }
505 }
506 return Standard_True;
507}
508
2028d00c 509static inline Standard_Real ComputeToleranceVertex(const Standard_Real dist, const Standard_Real Tol1, const Standard_Real Tol2)
7fd59977 510{
2028d00c 511 return (dist * 0.5 + Tol1 + Tol2);
7fd59977 512}
513TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirst,
514 const TopoDS_Edge& edgeLast,
515 const TopTools_ListOfShape& listFacesFirst,
516 const TopTools_ListOfShape& listFacesLast,
517 const Standard_Boolean secForward,
518 Standard_Integer& whichSec,
519 const Standard_Boolean firstCall)
520{
521 // Do not process floating edges
522 if (!listFacesFirst.Extent() || !listFacesLast.Extent()) return TopoDS_Edge();
523
524 // Sort input edges
525 TopoDS_Edge edge1, edge2;
526 if (firstCall) {
527 // Take the longest edge as first
528 Standard_Real f, l;
529 Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(TopoDS::Edge(edgeFirst), f, l);
530 GeomAdaptor_Curve cAdapt1(c3d1);
531 Standard_Real len1 = GCPnts_AbscissaPoint::Length(cAdapt1, f, l);
532 Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(TopoDS::Edge(edgeLast), f, l);
533 GeomAdaptor_Curve cAdapt2(c3d2);
534 Standard_Real len2 = GCPnts_AbscissaPoint::Length(cAdapt2, f, l);
535 if (len1 < len2) {
536 edge1 = edgeLast;
537 edge2 = edgeFirst;
538 whichSec = 2;
539 }
540 else {
541 edge1 = edgeFirst;
542 edge2 = edgeLast;
543 whichSec = 1;
544 }
545 }
546 else {
547 if (whichSec == 1) {
548 edge1 = edgeLast;
549 edge2 = edgeFirst;
550 whichSec = 2;
551 }
552 else {
553 edge1 = edgeFirst;
554 edge2 = edgeLast;
555 whichSec = 1;
556 }
557 }
558
559 Standard_Real first, last;
560 BRep_Tool::Range(edge1, first, last);
561 BRep_Builder aBuilder;
562
563 //To keep NM vertices on edge
564 TopTools_SequenceOfShape aSeqNMVert;
565 TColStd_SequenceOfReal aSeqNMPars;
566 findNMVertices(edge1,aSeqNMVert,aSeqNMPars);
567 findNMVertices(edge2,aSeqNMVert,aSeqNMPars);
568
569 // Create new edge
570 TopoDS_Edge edge;
571 aBuilder.MakeEdge(edge);
572 edge.Orientation( edge1.Orientation());
573
574
575 // Retrieve edge curve
576 TopLoc_Location loc3d;
577 Standard_Real first3d, last3d;
578 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge1, loc3d, first3d, last3d);
579 if (!loc3d.IsIdentity()) {
580 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
581 c3d->Transform(loc3d.Transformation());
582 }
583 aBuilder.UpdateEdge(edge,c3d,BRep_Tool::Tolerance(edge1));
584 aBuilder.Range(edge, first, last);
585 aBuilder.SameRange(edge, Standard_False); //Standard_True
586 aBuilder.SameParameter(edge, Standard_False);
587 // Create and add new vertices
588 {
589 TopoDS_Vertex V1New, V2New;
590
591 // Retrieve original vertices from edges
592 TopoDS_Vertex V11,V12,V21,V22;
593 TopExp::Vertices(edge1,V11,V12);
594 TopExp::Vertices(edge2,V21,V22);
595
67ffcad0
G
596 //check that edges merged valid way (for edges having length less than specified
597 //tolerance
9781f215
G
598 // Check if edges are closed
599 Standard_Boolean isClosed1 = V11.IsSame(V12);
600 Standard_Boolean isClosed2 = V21.IsSame(V22);
601 if(!isClosed1 && !isClosed2)
2028d00c 602 {
9781f215
G
603 if(secForward )
604 {
605 if( V11.IsSame(V22) || V12.IsSame(V21) )
606 return TopoDS_Edge();
607 }
608 else
609 {
610 if( V11.IsSame(V21) || V12.IsSame(V22) )
611 return TopoDS_Edge();
612 }
2028d00c
G
613 }
614
7fd59977 615 //szv: do not reshape here!!!
616 //V11 = TopoDS::Vertex(myReShape->Apply(V11));
617 //V12 = TopoDS::Vertex(myReShape->Apply(V12));
618 //V21 = TopoDS::Vertex(myReShape->Apply(V21));
619 //V22 = TopoDS::Vertex(myReShape->Apply(V22));
620
621 gp_Pnt p11 = BRep_Tool::Pnt(V11);
622 gp_Pnt p12 = BRep_Tool::Pnt(V12);
623 gp_Pnt p21 = BRep_Tool::Pnt(V21);
624 gp_Pnt p22 = BRep_Tool::Pnt(V22);
625
9781f215 626
7fd59977 627
628 //Standard_Boolean isRev = Standard_False;
629 gp_Pnt pfirst;
630 Standard_Real Tol1 = 0.;
631 if (isClosed1 || isClosed2) {
632 // at least one of the edges is closed
633 if (isClosed1 && isClosed2) {
67ffcad0
G
634 // both edges are closed
635 pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ()));
7fd59977 636 gp_Vec v1 = p21.XYZ() - p11.XYZ();
637 Standard_Real d1 = v1.Magnitude();
638 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21));
67ffcad0 639 //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p21));
7fd59977 640 }
641 else if (isClosed1) {
67ffcad0 642 // only first edge is closed
7fd59977 643 gp_XYZ pt =0.5*(p21.XYZ()+ p22.XYZ());
67ffcad0 644 pfirst.SetXYZ(0.5*(p11.XYZ() + pt));
7fd59977 645 gp_Vec v1 = p22.XYZ() - p21.XYZ();
646 Standard_Real d1 = v1.Magnitude();
647 Tol1= ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V22),BRep_Tool::Tolerance(V21));
648 gp_Vec v2 = p11.XYZ() - pt;
649 Standard_Real d2 = v2.Magnitude();
650 Tol1= ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V11));
67ffcad0
G
651 //Tol1 = Max(pfirst.Distance(p21),pfirst.Distance(p22));
652 //Tol1 = Max(pfirst.Distance(p11),Tol1);
7fd59977 653 }
654 else {
67ffcad0 655 // only second edge is closed
7fd59977 656 gp_XYZ pt = 0.5*(p11.XYZ()+ p12.XYZ());
67ffcad0 657 pfirst.SetXYZ(0.5*(p21.XYZ() + pt));
7fd59977 658 gp_Vec v1 = p11.XYZ() - p12.XYZ();
659 Standard_Real d1 = v1.Magnitude();
660 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V12));
661 gp_Vec v2 = p21.XYZ() - pt;
662 Standard_Real d2 = v2.Magnitude();
663 Tol1 = ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V21));
67ffcad0
G
664 //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p12));
665 //Tol1 = Max(pfirst.Distance(p21),Tol1);
7fd59977 666 }
667 aBuilder.MakeVertex(V1New,pfirst,Tol1);
668 V2New = V1New;
669 }
670 else {
671 // both edges are open
672 gp_Pnt plast;
673 Standard_Real Tol2 = 0.;
67ffcad0
G
674 Standard_Boolean isOldFirst = ( secForward ? V11.IsSame(V21) : V11.IsSame(V22) );
675 Standard_Boolean isOldLast = ( secForward ? V12.IsSame(V22) : V12.IsSame(V21)) ;
7fd59977 676 if (secForward) {
67ffcad0
G
677 //case if vertices already sewed
678 if(!isOldFirst)
679 {
680 pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ()));
681 gp_Vec v1 = p21.XYZ() - p11.XYZ();
682 Standard_Real d1 = v1.Magnitude();
683 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21));
684 }
685 if(!isOldLast)
686 {
687 plast.SetXYZ(0.5*(p12.XYZ() + p22.XYZ()));
688
689 gp_Vec v2 = p22.XYZ() - p12.XYZ();
690 Standard_Real d2 = v2.Magnitude();
691
692 Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V22));
693 }
7fd59977 694
7fd59977 695 }
696 else {
67ffcad0
G
697 if(!isOldFirst)
698 {
699 pfirst.SetXYZ(0.5*(p11.XYZ() + p22.XYZ()));
700 gp_Vec v1 = p22.XYZ() - p11.XYZ();
701 Standard_Real d1 = v1.Magnitude();
702 Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V22));
703 }
704 if(!isOldLast)
705 {
706 plast.SetXYZ(0.5*(p12.XYZ() + p21.XYZ()));
707 gp_Vec v2 = p21.XYZ() - p12.XYZ();
708 Standard_Real d2 = v2.Magnitude();
709 Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V21));
710 }
711
7fd59977 712 }
67ffcad0
G
713 if(!isOldFirst)
714 aBuilder.MakeVertex(V1New,pfirst,Tol1);
715 else
716 V1New = V11;
717
718
719 if(!isOldLast)
720 aBuilder.MakeVertex(V2New,plast,Tol2);
721 else
722 V2New = V12;
723
7fd59977 724 }
725
726 // Add the vertices in the good sense
727 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
728 TopoDS_Shape aLocalEdge = V1New.Oriented(TopAbs_FORWARD); //(listNode.First()).Oriented(TopAbs_FORWARD);
729 aBuilder.Add(anEdge,aLocalEdge);
730 aLocalEdge = V2New.Oriented(TopAbs_REVERSED); //(listNode.Last()).Oriented(TopAbs_REVERSED);
731 aBuilder.Add(anEdge,aLocalEdge);
732
733 Standard_Integer k =1;
734 for( ; k <= aSeqNMVert.Length(); k++)
735 aBuilder.Add(anEdge,aSeqNMVert.Value(k));
736
737 }
738
739 // Retrieve second PCurves
740 TopLoc_Location loc2;
741 Handle(Geom_Surface) surf2;
742 //Handle(Geom2d_Curve) c2d2, c2d21;
743 // Standard_Real firstOld, lastOld;
744
745 TopTools_ListIteratorOfListOfShape itf2;
746 if (whichSec == 1) itf2.Initialize(listFacesLast);
747 else itf2.Initialize(listFacesFirst);
748 Standard_Boolean isResEdge = Standard_False;
749 for (; itf2.More(); itf2.Next()) {
750 Handle(Geom2d_Curve) c2d2, c2d21;
751 Standard_Real firstOld, lastOld;
752 const TopoDS_Face& fac2 = TopoDS::Face(itf2.Value());
753
754 surf2 = BRep_Tool::Surface(fac2, loc2);
755 Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) &&
67ffcad0 756 BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2));
7fd59977 757 if (isSeam2) {
758 if (!myNonmanifold) return TopoDS_Edge();
759 TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting
760 c2d21 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac2, firstOld, lastOld);
761 }
762 c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld);
763 if (c2d2.IsNull() && c2d21.IsNull()) continue;
764
765 if (!c2d21.IsNull()) {
766 c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy());
767 if (!secForward) {
67ffcad0
G
768 if (c2d21->IsKind(STANDARD_TYPE(Geom2d_Line)))
769 c2d21 = new Geom2d_TrimmedCurve(c2d21, firstOld, lastOld);
770 Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321
771 Standard_Real last2d = lastOld; //c2dTmp->LastParameter();
772 firstOld = c2d21->ReversedParameter(last2d);
773 lastOld = c2d21->ReversedParameter(first2d);
774 c2d21->Reverse();
7fd59977 775 }
776 c2d21 = SameRange(c2d21,firstOld,lastOld,first,last);
777 }
778
779 // Make second PCurve sameRange with the 3d curve
780 c2d2 = Handle(Geom2d_Curve)::DownCast(c2d2->Copy());
67ffcad0 781
7fd59977 782 if (!secForward) {
783 if (c2d2->IsKind(STANDARD_TYPE(Geom2d_Line)))
67ffcad0
G
784 c2d2 = new Geom2d_TrimmedCurve(c2d2, firstOld, lastOld);
785 Standard_Real first2d = firstOld;
786 Standard_Real last2d = lastOld;
7fd59977 787 firstOld = c2d2->ReversedParameter(last2d);
788 lastOld = c2d2->ReversedParameter(first2d);
789 c2d2->Reverse();
790 }
791
792 c2d2 = SameRange(c2d2,firstOld,lastOld,first,last);
793 if (c2d2.IsNull()) continue;
67ffcad0 794
7fd59977 795 // Add second PCurve
796 Standard_Boolean isSeam = Standard_False;
797 TopAbs_Orientation Ori = TopAbs_FORWARD;
798 //Handle(Geom2d_Curve) c2d1, c2d11;
799
800 TopTools_ListIteratorOfListOfShape itf1;
801 if (whichSec == 1) itf1.Initialize(listFacesFirst);
802 else itf1.Initialize(listFacesLast);
803 for (; itf1.More() && !isSeam; itf1.Next()) {
804 Handle(Geom2d_Curve) c2d1, c2d11;
805 const TopoDS_Face& fac1 = TopoDS::Face(itf1.Value());
806
807 TopLoc_Location loc1;
808 Handle(Geom_Surface) surf1 = BRep_Tool::Surface(fac1, loc1);
809 Standard_Real first2d, last2d;
810 Standard_Boolean isSeam1 = ((IsUClosedSurface(surf1,edge1,loc1) || IsVClosedSurface(surf1,edge1,loc1)) &&
67ffcad0 811 BRep_Tool::IsClosed(TopoDS::Edge(edge1),fac1));
7fd59977 812 c2d1 = BRep_Tool::CurveOnSurface(edge1, fac1, first2d, last2d);
813 Ori = edge1.Orientation();
814 if (fac1.Orientation() == TopAbs_REVERSED)
815 Ori = TopAbs::Reverse(Ori);
67ffcad0 816
7fd59977 817 if (isSeam1) {
67ffcad0 818 if (!myNonmanifold) return TopoDS_Edge();
7fd59977 819 TopoDS_Shape aTmpShape = edge1.Reversed(); //for porting
820 c2d11 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac1, first2d, last2d);
821 //if(fac1.Orientation() == TopAbs_REVERSED) //
822 if(Ori == TopAbs_FORWARD)
823 aBuilder.UpdateEdge(edge,c2d1,c2d11,fac1,0);
824 else
825 aBuilder.UpdateEdge(edge,c2d11,c2d1,fac1,0);
826 }
827 else aBuilder.UpdateEdge(edge,c2d1,fac1,0);
7fd59977 828
67ffcad0 829 if (c2d1.IsNull() && c2d11.IsNull()) continue;
7fd59977 830
831 if (surf2 == surf1) {
67ffcad0
G
832 // Merge sections which are on the same face
833 if (!loc2.IsDifferent(loc1)) {
834 Standard_Boolean uclosed = IsUClosedSurface(surf2,edge2,loc2);
835 Standard_Boolean vclosed = IsVClosedSurface(surf2,edge2,loc2);
836 if (uclosed || vclosed) {
837 Standard_Real pf = c2d1->FirstParameter();
838 // Standard_Real pl = c2d1->LastParameter();
839 gp_Pnt2d p1n = c2d1->Value(Max(first,pf));
840 // gp_Pnt2d p2n = c2d1->Value(Min(pl,last));
7fd59977 841 gp_Pnt2d p21n = c2d2->Value(Max(first,c2d2->FirstParameter()));
842 gp_Pnt2d p22n = c2d2->Value(Min(last,c2d2->LastParameter()));
843 Standard_Real aDist = Min(p1n.Distance(p21n), p1n.Distance(p22n));
67ffcad0
G
844 Standard_Real U1, U2, V1, V2;
845 surf2->Bounds(U1, U2, V1, V2);
846 isSeam = ((uclosed && aDist > 0.75*(fabs(U2-U1))) ||
847 (vclosed && aDist > 0.75*(fabs(V2-V1))));
7fd59977 848 if( !isSeam && BRep_Tool::IsClosed(TopoDS::Edge(edge),fac1)) continue;
67ffcad0
G
849 }
850 }
7fd59977 851 }
67ffcad0 852
7fd59977 853 isResEdge = Standard_True;
854 if (isSeam) {
855 if (Ori == TopAbs_FORWARD)
856 aBuilder.UpdateEdge(edge, c2d1, c2d2, surf2, loc2, Precision::Confusion());
857 else
858 aBuilder.UpdateEdge(edge, c2d2, c2d1, surf2, loc2, Precision::Confusion());
859 }
860 else if (isSeam2) {
861 TopAbs_Orientation InitOri = edge2.Orientation();
67ffcad0 862 TopAbs_Orientation SecOri = edge.Orientation();
7fd59977 863 if (fac2.Orientation() == TopAbs_REVERSED) {
67ffcad0 864
7fd59977 865 InitOri = TopAbs::Reverse(InitOri);
866 SecOri = TopAbs::Reverse(SecOri);
867 }
868 if(!secForward)
869 InitOri = TopAbs::Reverse(InitOri);
67ffcad0 870
7fd59977 871 if (InitOri == TopAbs_FORWARD)
872 aBuilder.UpdateEdge(edge, c2d2,c2d21, surf2, loc2, Precision::Confusion());
873 else
874 aBuilder.UpdateEdge(edge, c2d21,c2d2, surf2, loc2, Precision::Confusion());
875 }
876 else {
877 aBuilder.UpdateEdge(edge, c2d2, surf2, loc2, Precision::Confusion());
878 }
67ffcad0 879
7fd59977 880 }
881 }
882 if(isResEdge)
67ffcad0 883 // Try to make the edge sameparameter
7fd59977 884 SameParameter(edge);
885
886 // Standard_Real tolReached = BRep_Tool::Tolerance(edge);
887 //if (!BRep_Tool::SameParameter(edge)) return edge; //gka ????????
888
889 if (firstCall && (!BRep_Tool::SameParameter(edge) || !isResEdge)) {
890 Standard_Integer whichSecn = whichSec;
891 // Try to merge on the second section
892 Standard_Boolean second_ok = Standard_True;
893 TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast,
67ffcad0 894 secForward,whichSecn,Standard_False);
7fd59977 895 //if (s_edge.IsNull()) return s_edge; // gka version for free edges
896 if (s_edge.IsNull()) second_ok = Standard_False;
897 else if (!BRep_Tool::SameParameter(s_edge)) second_ok = Standard_False;
898 else {
899 edge = s_edge;
900 whichSec = whichSecn;
901 }
902
903 if (!second_ok) {
904
905 GeomAdaptor_Curve c3dAdapt(c3d);
906
907 // Discretize edge curve
908 Standard_Integer i, j, nbp = 15;
909 Standard_Real deltaT = (last3d - first3d) / (nbp + 1);
910 TColgp_Array1OfPnt c3dpnt(1,nbp);
911 for (i = 1; i <= nbp; i++) c3dpnt(i) = c3dAdapt.Value(first3d + i*deltaT);
912
913 Standard_Real u, v, dist, maxTol = -1.0;
914 Standard_Boolean more = Standard_True;
915
916 for (j = 1; more; j++) {
917 Handle(Geom2d_Curve) c2d2;
67ffcad0
G
918 BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j);
919 more = !c2d2.IsNull();
920 if (more) {
921
922 deltaT = (last - first) / (nbp + 1);
923 for (i = 1; i <= nbp; i++) {
924 c2d2->Value(first + i*deltaT).Coord(u,v);
925 dist = surf2->Value(u,v).Distance(c3dpnt(i));
926 if (dist > maxTol) maxTol = dist;
927 }
928 }
7fd59977 929 }
930
931 if (maxTol >= 0.) aBuilder.UpdateEdge(edge, maxTol);
932 aBuilder.SameParameter(edge,Standard_True);
933 }
934 }
935
936 BRepLib::EncodeRegularity(edge,0.01);
937 Standard_Real tolEdge1 = BRep_Tool::Tolerance(edge);
938 if (tolEdge1 > MaxTolerance()) edge.Nullify();
939 return edge;
940}
941
942//=======================================================================
943// function : EvaluateAngulars
944// purpose : internal use
945//=======================================================================
946
947void BRepBuilderAPI_Sewing::EvaluateAngulars(TopTools_SequenceOfShape& sequenceSec,
948 TColStd_Array1OfBoolean& secForward,
949 TColStd_Array1OfReal& tabAng,
950 const Standard_Integer indRef) const
951{
952 tabAng.Init(-1.0);
953
954 Standard_Integer i, j, npt = 4, lengSec = sequenceSec.Length();
955
956 TopoDS_Edge edge;
957 TopoDS_Face face;
958 TopLoc_Location loc;
959 Standard_Real first, last;
960 Handle(Geom_Curve) c3d;
961 Handle(Geom2d_Curve) c2d;
962 Handle(Geom_Surface) surf;
963 TColgp_Array1OfVec normRef(1,npt);
964
965 for (i = indRef; i <= lengSec; i++) {
966
967 edge = TopoDS::Edge(sequenceSec(i));
968
969 TopoDS_Shape bnd = edge;
970 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
971 if (myBoundFaces.Contains(bnd)) {
972 face = TopoDS::Face(myBoundFaces.FindFromKey(bnd).First());
973 surf = BRep_Tool::Surface(face,loc);
974 if (!loc.IsIdentity()) {
975 surf = Handle(Geom_Surface)::DownCast(surf->Copy());
976 surf->Transform(loc.Transformation());
977 }
978 c2d = BRep_Tool::CurveOnSurface(edge, face, first, last);
979 }
980 else if (i == indRef) return;
981 else continue;
982
983 c3d = BRep_Tool::Curve(edge, loc, first, last);
984 if (!loc.IsIdentity()) {
985 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
986 c3d->Transform(loc.Transformation());
987 }
988
989 GeomAdaptor_Curve adapt(c3d);
990 GCPnts_UniformAbscissa uniAbs(adapt, npt, first, last);
991
992 Standard_Real cumulateAngular = 0.0;
993 Standard_Integer nbComputedAngle = 0;
994
995 for (j = 1; j <= npt; j++) {
996 gp_Pnt2d P;
997 c2d->D0(uniAbs.Parameter((secForward(i) || i == indRef)? j : npt-j+1),P);
998 gp_Vec w1, w2;
999 gp_Pnt unused;
1000 surf->D1(P.X(), P.Y(), unused, w1, w2);
1001 gp_Vec n = w1^w2; // Compute the normal vector
1002 if (i == indRef) normRef(j) = n;
1003 else if ((n.Magnitude()>gp::Resolution()) && (normRef(j).Magnitude()>gp::Resolution())) {
1004 nbComputedAngle++;
1005 Standard_Real angular = n.Angle(normRef(j));
c6541a0c 1006 if (angular > M_PI/2.) angular = M_PI - angular;
7fd59977 1007 cumulateAngular += angular;
1008 }
1009 }
1010
1011 if (nbComputedAngle)
1012 tabAng(i) = cumulateAngular/((Standard_Real)nbComputedAngle);
1013 }
1014}
1015
1016//=======================================================================
1017// function : EvaluateDistances
1018// purpose : internal use
1019// Evaluate distance beetween edges with indice indRef and the following edges in the list
1020// Remarks (lengSec - indRef) must be >= 1
1021//=======================================================================
7fd59977 1022void BRepBuilderAPI_Sewing::EvaluateDistances(TopTools_SequenceOfShape& sequenceSec,
1023 TColStd_Array1OfBoolean& secForward,
1024 TColStd_Array1OfReal& tabDst,
1025 TColStd_Array1OfReal& arrLen,
1026 TColStd_Array1OfReal& tabMinDist,
1027 const Standard_Integer indRef) const
1028{
1029 secForward.Init(Standard_True);
1030 tabDst.Init(-1.0);
1031 arrLen.Init(0.);
2028d00c 1032 tabMinDist.Init(Precision::Infinite());
7fd59977 1033 const Standard_Integer npt = 8; // Number of points for curve discretization
1034 TColgp_Array1OfPnt ptsRef(1, npt), ptsSec(1, npt);
1035
1036 Standard_Integer i, j, lengSec = sequenceSec.Length();
1037 TColgp_SequenceOfPnt seqSec;
1038
1039 Handle(Geom_Curve) c3dRef;
1040 Standard_Real firstRef=0., lastRef=0.;
67ffcad0 1041
7fd59977 1042 for (i = indRef; i <= lengSec; i++) {
1043
1044 // reading of the edge (attention for the first one: reference)
1045 const TopoDS_Edge& sec = TopoDS::Edge(sequenceSec(i));
1046
1047 TopLoc_Location loc;
1048 Standard_Real first, last;
1049 Handle(Geom_Curve) c3d = BRep_Tool::Curve(sec, loc, first, last);
1050 if (!loc.IsIdentity()) {
1051 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
1052 c3d->Transform(loc.Transformation());
1053 }
1054
1055 if (i == indRef) {
1056 c3dRef = c3d; firstRef = first; lastRef = last;
1057 }
1058
2028d00c 1059 Standard_Real dist = Precision::Infinite(), distFor = -1.0, distRev = -1.0;
7fd59977 1060 Standard_Real aMinDist = Precision::Infinite();
1061
1062 Standard_Real T, deltaT = (last - first) / (npt - 1);
1063 Standard_Real aLenSec2 = 0.;
67ffcad0
G
1064
1065 Standard_Integer nbFound = 0;
7fd59977 1066 for (j = 1; j <= npt; j++) {
1067
1068 // Uniform parameter on curve
1069 if (j == 1) T = first;
1070 else if (j == npt) T = last;
1071 else T = first + (j - 1) * deltaT;
1072
1073 // Take point on curve
1074 gp_Pnt pt = c3d->Value(T);
2028d00c 1075
7fd59977 1076 if (i == indRef) {
1077 ptsRef(j) = pt;
2028d00c
G
1078 if(j > 1)
1079 aLenSec2 += pt.SquareDistance(ptsRef(j-1));
7fd59977 1080 }
1081 else {
1082 ptsSec(j) = pt;
1083 //protection to avoid merging with small sections
2028d00c 1084 if(j > 1)
7fd59977 1085 aLenSec2 += pt.SquareDistance(ptsSec(j-1));
1086 // To evaluate mutual orientation and distance
1087 dist = pt.Distance(ptsRef(j));
1088 if(aMinDist > dist)
1089 aMinDist = dist;
1090 if (distFor < dist) distFor = dist;
1091 dist = pt.Distance(ptsRef(npt-j+1));
2028d00c 1092
7fd59977 1093 if(aMinDist > dist)
1094 aMinDist = dist;
1095 if (distRev < dist) distRev = dist;
2028d00c
G
1096
1097 // Check that point lays between vertices of reference curve
1098 const gp_Pnt &p11 = ptsRef(1);
1099 const gp_Pnt &p12 = ptsRef(npt);
1100 const gp_Vec aVec1(pt,p11);
1101 const gp_Vec aVec2(pt,p12);
1102 const gp_Vec aVecRef(p11,p12);
1103 if((aVecRef * aVec1) * (aVecRef * aVec2) < 0.)
1104 nbFound++;
7fd59977 1105 }
1106 }
1107
1108 Standard_Real aLenSec = sqrt(aLenSec2);
1109
1110 //if(aLenSec < myMinTolerance )
1111 // continue;
1112 arrLen.SetValue(i,aLenSec);
1113 // Record mutual orientation
1114 Standard_Boolean isForward = (distFor < distRev); //szv debug: <=
1115 secForward(i) = isForward;
1116
1117 dist = (isForward? distFor : distRev);
2028d00c
G
1118 if(i == indRef || (dist < myTolerance && nbFound >= npt * 0.5) )
1119 {
7fd59977 1120 tabDst(i) = dist;
1121 tabMinDist(i) = aMinDist;
7fd59977 1122 }
2028d00c
G
1123 else
1124 {
1125 nbFound = 0, aMinDist = Precision::Infinite(), dist = -1;
1126 TColgp_Array1OfPnt arrProj(1, npt);
1127 TColStd_Array1OfReal arrDist(1, npt), arrPara(1, npt);
1128 if( arrLen(indRef) >= arrLen(i))
1129 ProjectPointsOnCurve(ptsSec,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
1130 else
1131 ProjectPointsOnCurve(ptsRef,c3d,first,last,arrDist,arrPara,arrProj,Standard_False);
1132 for( j = 1; j <= npt; j++ )
1133 {
2c896b8f 1134 if(arrDist(j) < 0.)
2028d00c
G
1135 continue;
1136 if(dist < arrDist(j))
1137 dist = arrDist(j);
1138 if( aMinDist > arrDist(j))
1139 aMinDist = arrDist(j);
1140 nbFound++;
1141 }
1142 if(nbFound > 1)
1143 {
1144 tabDst(i) = dist;
1145 tabMinDist(i) = aMinDist;
1146 }
7fd59977 1147 }
1148 }
1149
2028d00c 1150 /*
7fd59977 1151 // Project distant points
1152 Standard_Integer nbFailed = seqSec.Length();
1153 if (!nbFailed) return;
1154
1155 TColgp_Array1OfPnt arrPnt(1, nbFailed), arrProj(1, nbFailed);
1156 for (i = 1; i <= nbFailed; i++) arrPnt(i) = seqSec(i); seqSec.Clear();
1157 TColStd_Array1OfReal arrDist(1, nbFailed), arrPara(1, nbFailed);
1158
2028d00c 1159 ProjectPointsOnCurve(arrPnt,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False);
7fd59977 1160
1161 // Process distant sections
1162 Standard_Integer idx1 = 1;
1163 for (i = indRef + 1; i <= lengSec; i++) {
1164
1165 // Skip section if already evaluated
1166 if (tabDst(i) >= 0.0) continue;
1167
1168 Standard_Real dist, distMax = -1.0, aMinDist = Precision::Infinite();
1169
1170 Standard_Integer idx2 = (idx1 - 1)*npt;
1171
1172 for (j = 1; j <= npt; j++) {
1173
1174 dist = arrDist(idx2 + j);
1175 // If point is not projected - stop evaluation
1176 if (dist < 0.0) { distMax = -1.0; break; }
1177 if (distMax < dist) distMax = dist;
1178 if(aMinDist > dist) aMinDist = dist;
1179 }
1180
1181 // If section is close - record distance
1182 if (distMax >= 0.0) {
1183 if (secForward(i)) {
1184 dist = arrPnt(idx2+1).Distance(ptsRef(1));
1185 if (distMax < dist) distMax = dist;
1186 if(aMinDist > dist) aMinDist = dist;
1187 dist = arrPnt(idx2+npt).Distance(ptsRef(npt));
1188 if (distMax < dist) distMax = dist;
1189 if(aMinDist > dist) aMinDist = dist;
1190 }
1191 else {
1192 dist = arrPnt(idx2+1).Distance(ptsRef(npt));
1193 if (distMax < dist) distMax = dist;
1194 if(aMinDist > dist) aMinDist = dist;
1195 dist = arrPnt(idx2+npt).Distance(ptsRef(1));
1196 if (distMax < dist) distMax = dist;
1197 if(aMinDist > dist) aMinDist = dist;
1198 }
1199
1200 if (distMax < myTolerance)
1201 {
1202 tabDst(i) = distMax;
1203 tabMinDist(i) = aMinDist;
1204 }
1205 }
1206
1207 idx1++; // To the next distant curve
2028d00c 1208 }*/
7fd59977 1209}
1210
1211//=======================================================================
1212//function : IsMergedClosed
1213//purpose : internal use
1214//=======================================================================
1215
1216Standard_Boolean BRepBuilderAPI_Sewing::IsMergedClosed(const TopoDS_Edge& Edge1,
1217 const TopoDS_Edge& Edge2,
1218 const TopoDS_Face& face) const
1219{
1220 // Check for closed surface
1221 TopLoc_Location loc;
1222 Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc);
1223 Standard_Boolean isUClosed = IsUClosedSurface(surf,Edge1,loc);
1224 Standard_Boolean isVClosed = IsVClosedSurface(surf,Edge1,loc);
1225 if (!isUClosed && !isVClosed) return Standard_False;
1226 // Check condition on closed surface
1227 /*
1228 Standard_Real first1,last1,first2,last2;
1229 Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(Edge1,first1,last1);
1230 Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(Edge2,first2,last2);
1231 if (C3d1.IsNull() || C3d2.IsNull()) return Standard_False;
1232 */
1233 Standard_Real first2d1,last2d1,first2d2,last2d2;
1234 Handle(Geom2d_Curve) C2d1 = BRep_Tool::CurveOnSurface(Edge1,face,first2d1,last2d1);
1235 Handle(Geom2d_Curve) C2d2 = BRep_Tool::CurveOnSurface(Edge2,face,first2d2,last2d2);
1236 if (C2d1.IsNull() || C2d2.IsNull()) return Standard_False;
1237 /*
1238 gp_Pnt p1 = C3d1->Value(0.5*(first1 + last1));
1239 gp_Pnt p2 = C3d1->Value(0.5*(first2 + last2));
1240 Standard_Real dist = p1.Distance(p2);
1241 gp_Pnt2d p12d = C2d1->Value(0.5*(first2d1 + last2d1));
1242 gp_Pnt2d p22d = C2d1->Value(0.5*(first2d2 + last2d2));
1243 Standard_Real dist2d = p12d.Distance(p22d);
1244 GeomAdaptor_Surface Ads(BRep_Tool::Surface(face));
1245 Standard_Real distSurf = Max(Ads.UResolution(dist), Ads.VResolution(dist));
1246 return (dist2d*0.2 >= distSurf);
1247 */
1248 Standard_Integer isULongC1, isULongC2, isVLongC1, isVLongC2;
1249 Standard_Real SUmin, SUmax, SVmin, SVmax;
1250 Standard_Real C1Umin, C1Vmin, C1Umax, C1Vmax;
1251 Standard_Real C2Umin, C2Vmin, C2Umax, C2Vmax;
1252 { //szv: Use brackets to destroy local variables
1253 Bnd_Box2d B1, B2;
1254 Geom2dAdaptor_Curve aC2d1(C2d1), aC2d2(C2d2);
1255 BndLib_Add2dCurve::Add(aC2d1,first2d1,last2d1,Precision::PConfusion(),B1);
1256 BndLib_Add2dCurve::Add(aC2d2,first2d2,last2d2,Precision::PConfusion(),B2);
1257 B1.Get(C1Umin,C1Vmin,C1Umax,C1Vmax);
1258 B2.Get(C2Umin,C2Vmin,C2Umax,C2Vmax);
1259 Standard_Real du, dv;
1260 du = (C1Umax - C1Umin); dv = (C1Vmax - C1Vmin);
1261 isULongC1 = (dv <= du); isVLongC1 = (du <= dv);
1262 du = (C2Umax - C2Umin); dv = (C2Vmax - C2Vmin);
1263 isULongC2 = (dv <= du); isVLongC2 = (du <= dv);
1264 surf->Bounds(SUmin,SUmax,SVmin,SVmax);
1265 }
1266 if (isUClosed && isVLongC1 && isVLongC2) {
1267 // Do not merge if not overlapped by V
1268 Standard_Real dist = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1269 if (dist < 0.0) {
1270 Standard_Real distInner = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1271 Standard_Real distOuter = (SUmax - SUmin) - Max((C2Umax - C1Umin),(C1Umax - C2Umin));
1272 if (distOuter <= distInner) return Standard_True;
1273 }
1274 }
1275 if (isVClosed && isULongC1 && isULongC2) {
1276 // Do not merge if not overlapped by U
1277 Standard_Real dist = Max((C2Umin - C1Umax),(C1Umin - C2Umax));
1278 if (dist < 0.0) {
1279 Standard_Real distInner = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax));
1280 Standard_Real distOuter = (SVmax - SVmin) - Max((C2Vmax - C1Vmin),(C1Vmax - C2Vmin));
1281 if (distOuter <= distInner) return Standard_True;
1282 }
1283 }
1284 return Standard_False;
1285}
1286
1287//=======================================================================
1288//function : AnalysisNearestEdges
1289//purpose :
1290//=======================================================================
1291
1292void BRepBuilderAPI_Sewing::AnalysisNearestEdges(const TopTools_SequenceOfShape& sequenceSec,
1293 TColStd_SequenceOfInteger& seqIndCandidate,
1294 TColStd_SequenceOfInteger& seqOrientations,
1295 const Standard_Boolean evalDist)
1296{
1297
1298 Standard_Integer workIndex = seqIndCandidate.First();
1299 TopoDS_Shape workedge = sequenceSec.Value(workIndex);
1300 TopoDS_Shape bnd = workedge;
1301 TopTools_ListOfShape workfaces;
1302 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1303 if (myBoundFaces.Contains(bnd))
1304 workfaces = myBoundFaces.FindFromKey(bnd);
1305 if(workfaces.IsEmpty()) return;
1306 TopTools_MapOfShape mapFaces;
1307 TopTools_ListIteratorOfListOfShape lIt;
1308 for (lIt.Initialize(workfaces); lIt.More(); lIt.Next())
1309 mapFaces.Add(lIt.Value());
1310 TColStd_SequenceOfInteger seqNotCandidate;
1311 TColStd_SequenceOfInteger seqNewForward;
1312 // Separates edges belonging the same face as work edge
1313 // for exception of edges belonging closed faces
1314
1315 seqNotCandidate.Append(workIndex);
1316 for(Standard_Integer i = 1; i<= seqIndCandidate.Length(); ) {
1317 Standard_Integer index = seqIndCandidate.Value(i);
1318 Standard_Boolean isRemove = Standard_False;
1319 if(index == workIndex) {
1320 seqIndCandidate.Remove(i);
1321 seqOrientations.Remove(i);
1322 isRemove = Standard_True;
1323 }
1324 if(!isRemove) {
1325 TopoDS_Shape bnd2 = sequenceSec.Value(index);
1326 if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2);
1327
1328 if(myBoundFaces.Contains(bnd2)) {
1329 const TopTools_ListOfShape& listfaces = myBoundFaces.FindFromKey(bnd2);
1330 Standard_Boolean isMerged = Standard_True;
1331 for (lIt.Initialize(listfaces); lIt.More() && isMerged; lIt.Next()) {
1332 if(mapFaces.Contains(lIt.Value())) {
1333 TopLoc_Location loc;
1334 Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(lIt.Value()),loc);
1335 isMerged = ((IsUClosedSurface(surf,bnd2,loc) || IsVClosedSurface(surf,bnd2,loc)) &&
1336 IsMergedClosed(TopoDS::Edge(sequenceSec.Value(index)),TopoDS::Edge(workedge),TopoDS::Face(lIt.Value())));
1337 }
1338 }
1339 if(!isMerged) {
1340 seqNotCandidate.Append(index);
1341 seqIndCandidate.Remove(i);
1342 seqOrientations.Remove(i);
1343 isRemove = Standard_True;
1344 }
1345 }
1346 else {
1347 seqIndCandidate.Remove(i);
1348 seqOrientations.Remove(i);
1349 isRemove = Standard_True;
1350 }
1351 }
1352 if(!isRemove) i++;
1353 }
1354 if(seqIndCandidate.Length() == 0 || seqNotCandidate.Length() == 1) return;
1355 if(!evalDist) return;
1356 TColStd_Array2OfReal TotTabDist(1,seqNotCandidate.Length(),1,seqIndCandidate.Length());
1357 TColStd_MapOfInteger MapIndex;
1358 TColStd_SequenceOfInteger seqForward;
1359
1360 // Definition and removing edges wich are not candidate for work edge
1361 // ( they have other nearest edges belonging to the work face)
1362 for(Standard_Integer k = 1; k<= seqNotCandidate.Length(); k++) {
1363 Standard_Integer index1 = seqNotCandidate.Value(k);
1364 TopoDS_Shape edge = sequenceSec.Value(index1);
1365 TopTools_SequenceOfShape tmpSeq;
1366 tmpSeq.Append(edge);
1367 for(Standard_Integer kk = 1; kk <= seqIndCandidate.Length();kk++)
1368 tmpSeq.Append(sequenceSec.Value(seqIndCandidate.Value(kk)));
1369
1370 Standard_Integer lengSec = tmpSeq.Length();
1371 TColStd_Array1OfBoolean tabForward(1,lengSec);
1372 TColStd_Array1OfReal tabDist(1,lengSec);
1373 TColStd_Array1OfReal arrLen(1,lengSec);
1374 TColStd_Array1OfReal tabMinDist(1,lengSec);
1375 for (Standard_Integer i1 = 1 ; i1 <= lengSec; i1++)
1376 tabDist(i1) =-1;
1377
1378 EvaluateDistances(tmpSeq,tabForward, tabDist,arrLen,tabMinDist,1 );
1379 if(k == 1) {
1380 for(Standard_Integer n = 1; n < lengSec; n++) {
1381 if(tabDist(n+1) == -1 || tabDist(n+1) > myTolerance) {
1382 MapIndex.Add(n);
1383 continue;
1384 }
1385 TotTabDist(k,n) = tabDist(n+1 );
1386 seqForward.Append(tabForward(n+1) ? 1:0);
1387 }
1388 }
1389 else {
1390 for(Standard_Integer n = 1; n < lengSec; n++) {
1391 if(tabDist(n) == -1 || tabDist(n) > myTolerance) continue;
1392 if(tabDist(n+1) < TotTabDist(1,n)) {
1393 MapIndex.Add(n);
1394 }
1395 }
1396 }
1397
1398 }
1399
1400 Standard_Integer i2 = seqIndCandidate.Length();
1401 for( ; i2 >=1 ; i2--)
1402 {
1403 if(MapIndex.Contains(i2))
1404 {
1405 seqIndCandidate.Remove(i2);
1406 seqOrientations.Remove(i2);
1407 }
1408
1409 }
1410 //for(TColStd_MapIteratorOfMapOfInteger IMap(MapIndex); IMap.More(); IMap.Next()) {
1411 // seqIndCandidate.Remove(IMap.Key());
1412 // seqOrientations.Remove(IMap.Key());
1413 //}
1414}
1415
1416//=======================================================================
1417//function : FindCandidates
1418//purpose : internal use
1419//=======================================================================
1420
1421Standard_Boolean BRepBuilderAPI_Sewing::FindCandidates(TopTools_SequenceOfShape& seqSections,
1422 TColStd_IndexedMapOfInteger& mapReference,
1423 TColStd_SequenceOfInteger& seqCandidates,
1424 TColStd_SequenceOfInteger& seqOrientations)
1425{
1426 Standard_Integer i, nbSections = seqSections.Length();
1427 if(nbSections <= 1)
1428 return Standard_False;
1429 // Retrieve last reference index
1430 Standard_Integer indReference = mapReference(mapReference.Extent());
1431 Standard_Integer nbCandidates = 0;
1432 TopTools_MapOfShape Faces1;
1433 //if (nbSections > 1) {
1434
1435 TopoDS_Edge Edge1 = TopoDS::Edge(seqSections(indReference));
1436
1437 // Retrieve faces for reference section
1438
1439 { //szv: Use brackets to destroy local variables
1440 TopoDS_Shape bnd = Edge1;
1441 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1442 if (myBoundFaces.Contains(bnd)) {
1443 TopTools_ListIteratorOfListOfShape itf1(myBoundFaces.FindFromKey(bnd));
1444 for (; itf1.More(); itf1.Next()) Faces1.Add(itf1.Value());
1445 }
1446 }
1447
1448 // Check merging conditions for candidates and remove unsatisfactory
1449 TopTools_SequenceOfShape seqSectionsNew;
1450 TColStd_SequenceOfInteger seqCandidatesNew;
1451 for (i = 1; i <= nbSections; i++) {
1452 if (i == indReference) {
1453 seqSectionsNew.Prepend(Edge1);
1454 seqCandidatesNew.Prepend(i);
1455 }
1456 else {
1457 const TopoDS_Edge& Edge2 = TopoDS::Edge(seqSections(i));
1458 //gka
1459 seqSectionsNew.Append(Edge2);
1460 seqCandidatesNew.Append(i);
1461 /*TopoDS_Shape bnd = Edge2;
1462 if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd);
1463 //gka
1464 if (myBoundFaces.Contains(bnd)) {
1465 Standard_Boolean isOK = Standard_True;
1466 TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1467 for (; itf2.More() && isOK; itf2.Next()) {
1468 const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1469 // Check whether condition is satisfied
1470 isOK = !Faces1.Contains(Face2);
1471 if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1472 }
1473 if (isOK) {
1474 seqSectionsNew.Append(Edge2);
1475 seqCandidatesNew.Append(i);
1476 }
1477 }*/
1478 }
1479 }
1480
1481 Standard_Integer nbSectionsNew = seqSectionsNew.Length();
1482 if (nbSectionsNew > 1) {
1483
1484 // Evaluate distances between reference and other sections
1485 TColStd_Array1OfBoolean arrForward(1,nbSectionsNew);
1486 TColStd_Array1OfReal arrDistance(1,nbSectionsNew);
1487 TColStd_Array1OfReal arrLen(1,nbSectionsNew);
1488 TColStd_Array1OfReal arrMinDist(1,nbSectionsNew);
1489 EvaluateDistances(seqSectionsNew,arrForward,arrDistance,arrLen,arrMinDist,1);
1490
1491 // Fill sequence of candidate indices sorted by distance
1492 for (i = 2; i <= nbSectionsNew; i++) {
1493 if (arrDistance(i) >= 0.0 && arrLen(i) > myMinTolerance) {
1494 // Reference section is connected to section #i
1495 Standard_Boolean isInserted = Standard_False;
1496 Standard_Integer j, ori = (arrForward(i)? 1 : 0);
1497 for (j = 1; (j <= seqCandidates.Length()) && !isInserted; j++) {
7fd59977 1498 Standard_Real aDelta = arrDistance(i) - arrDistance(seqCandidates.Value(j));
1499 //if (arrDistance(i) <= arrDistance(seqCandidates.Value(j))) {
1500 if( aDelta < Precision::Confusion()) {
1501
1502 if(fabs(aDelta) > RealSmall() ||
1503 arrMinDist(i) < arrMinDist(seqCandidates.Value(j)))
1504 {
1505 seqCandidates.InsertBefore(j,i);
1506 seqOrientations.InsertBefore(j,ori);
1507 isInserted = Standard_True;
1508 }
1509 }
1510 }
1511 if (!isInserted) {
1512 seqCandidates.Append(i);
1513 seqOrientations.Append(ori);
1514 }
1515 }
1516 }
1517
1518 // Replace candidate indices
1519 nbCandidates = seqCandidates.Length();
1520 for (i = 1; i <= nbCandidates; i++)
1521 seqCandidates(i) = seqCandidatesNew(seqCandidates(i));
1522 }
1523 //}
1524
1525 if (!nbCandidates) return Standard_False; // Section has no candidates to merge
1526
1527 if (myNonmanifold && nbCandidates >1) {
1528 TColStd_SequenceOfInteger seqNewCandidates;
1529 TColStd_SequenceOfInteger seqOrientationsNew;
1530 seqCandidates.Prepend(1);
1531 seqOrientations.Prepend(1);
1532 for(Standard_Integer k = 1; k <= seqSections.Length() && seqCandidates.Length() > 1 ; k++) {
1533 AnalysisNearestEdges(seqSections,seqCandidates,seqOrientations,(k==1));
1534 if(k == 1 && !seqCandidates.Length()) return Standard_False;
1535 if(seqCandidates.Length()) {
1536 seqNewCandidates.Append(seqCandidates.First());
1537 seqOrientationsNew.Append(seqOrientations.First());
1538 }
1539 }
1540 seqCandidates.Prepend(seqNewCandidates);
1541 seqOrientations.Prepend(seqOrientationsNew);
1542 return Standard_True;
1543 }
1544 else {
1545
1546 // For manifold case leave only one candidate from equidistant candidates
1547 /*Standard_Integer minIndex = seqCandidateIndex.First();
1548 Standard_Real minDistance = arrDistance(minIndex);
1549
1550 // Find equidistant candidates
1551 TColStd_SequenceOfInteger seqEqDistantIndex; seqEqDistantIndex.Append(1);
1552 for (i = 2; i <= nbCandidates; i++) {
1553 Standard_Integer index = seqCandidateIndex(i);
1554 if (Abs(minDistance - arrDistance(index)) <= Precision::Confusion())
1555 seqEqDistantIndex.Append(index);
1556 }
1557
1558 Standard_Integer eqLen = seqEqDistantIndex.Length();
1559 if (eqLen > 2) {
1560
1561 // Fill map of faces which equidistant sections belong to
1562 TopTools_MapOfShape mapFace;
1563 for (i = 1; i <= eqLen; i++) {
1564 Standard_Integer index = seqEqDistantIndex.Value(i);
1565 if (isCandidate(index)) {
1566 mapFace.Add(arrFace(index));
1567 }
1568 }
1569
1570 // Non Manifold case
1571 // Edges are merged by pair among a face continuity C1 criterion
1572 if (mapFace.Extent() == eqLen) {
1573
1574 tabDist.Init(-1);
1575 tabMinInd.Init(-1);
1576 min=10000000.;
1577 //indMin = -1;
1578 Standard_Integer indMin = -1;// To check if the edge can be merged.
1579 // Computation of distances between the edges.
1580 TopTools_SequenceOfShape seqSh;
1581 Standard_Integer nbInd = EqDistSeq.Length();
1582 TColStd_Array1OfBoolean tmptabForward(1,nbInd);
1583 seqSh.Append(sequenceSec.Value(1));
1584 for (j = 2; j <= EqDistSeq.Length(); j++) {
1585 Standard_Integer index = EqDistSeq.Value(j);
1586 tmptabForward(j) = tabForward(index);
1587 seqSh.Append(sequenceSec.Value(index));
1588 }
1589
1590 EvaluateAngulars(seqSh, tmptabForward, tabDist,1);
1591
1592 for(j=2; j <= seqSh.Length(); j++) {
1593 if (tabDist(j) > -1.) { // if edge(j) is connected to edge(i)
1594 if (min > tabDist(j)) {
1595 min = tabDist(j);
1596 indMin = j;
1597 }
1598 }
1599 }
1600
1601 // Construct minDist, tabMinInd , tabMinForward(i) = tabForward(j);
1602 if (indMin > 0) {
1603 seqSh.Remove(indMin);
1604 for(j =2; j <= tmpSeq.Length(); ) {
1605 TopoDS_Shape sh = tmpSeq.Value(j);
1606 Standard_Boolean isRem = Standard_False;
1607 for(Standard_Integer k = 1; k<= seqSh.Length();k++) {
1608 if(seqSh.Value(k) == sh) {
1609 isRem = Standard_True;
1610 break;
1611 }
1612 }
1613 if(isRem) {
1614 tmpSeq.Remove(j);
1615 tabMinForward.Remove(j); // = -1;
1616 }
1617 else j++;
1618 }
1619 }
1620 }
1621 }*/
1622
1623 // Find the best approved candidate
1624 while (nbCandidates) {
1625 // Retrieve first candidate
1626 Standard_Integer indCandidate = seqCandidates.First();
1627 // Candidate is approved if it is in the map
1628 if (mapReference.Contains(indCandidate)) break;
1629 // Find candidates for candidate #indCandidate
1630 mapReference.Add(indCandidate); // Push candidate in the map
1631 TColStd_SequenceOfInteger seqCandidates1, seqOrientations1;
1632 Standard_Boolean isFound =
1633 FindCandidates(seqSections,mapReference,seqCandidates1,seqOrientations1);
1634 mapReference.RemoveLast(); // Pop candidate from the map
1635 if (isFound) isFound = (seqCandidates1.Length() > 0);
1636 if (isFound) {
1637 Standard_Integer indCandidate1 = seqCandidates1.First();
1638 // If indReference is the best candidate for indCandidate
1639 // then indCandidate is the best candidate for indReference
1640 if (indCandidate1 == indReference) break;
1641 // If some other reference in the map is the best candidate for indCandidate
1642 // then assume that reference is the best candidate for indReference
1643 if (mapReference.Contains(indCandidate1)) {
1644 seqCandidates.Prepend(indCandidate1);
1645 nbCandidates++;
1646 break;
1647 }
1648 isFound = Standard_False;
1649 }
1650 if (!isFound) {
1651 // Remove candidate #1
1652 seqCandidates.Remove(1);
1653 seqOrientations.Remove(1);
1654 nbCandidates--;
1655 }
1656 }
1657 }
1658 //gka
1659 if(nbCandidates > 0)
1660 {
1661 Standard_Integer anInd = seqCandidates.Value(1);
1662 TopoDS_Edge Edge2 = TopoDS::Edge(seqSections(anInd));
1663 TopoDS_Shape bnd = Edge2;
1664 if (mySectionBound.IsBound(bnd))
1665 bnd = mySectionBound(bnd);
1666 //gka
1667 if (myBoundFaces.Contains(bnd)) {
1668 Standard_Boolean isOK = Standard_True;
1669 TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd));
1670 for (; itf2.More() && isOK; itf2.Next()) {
1671 const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value());
1672 // Check whether condition is satisfied
1673 isOK = !Faces1.Contains(Face2);
1674 if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2);
1675 }
1676 if(!isOK)
1677 return Standard_False;
1678 }
1679 }
1680 return (nbCandidates > 0);
1681}
1682
1683//=======================================================================
1684//function : Constructor
1685//purpose :
1686//=======================================================================
1687
1688BRepBuilderAPI_Sewing::BRepBuilderAPI_Sewing(const Standard_Real tolerance,
1689 const Standard_Boolean optionSewing,
1690 const Standard_Boolean optionAnalysis,
1691 const Standard_Boolean optionCutting,
1692 const Standard_Boolean optionNonmanifold)
1693{
1694 myReShape = new BRepTools_ReShape;
1695 Init(tolerance, optionSewing, optionAnalysis, optionCutting, optionNonmanifold);
1696}
1697
1698//=======================================================================
1699//function : Init
1700//purpose : Initialise Talerance, and options sewing, faceAnalysis and cutting
1701//=======================================================================
1702
1703void BRepBuilderAPI_Sewing::Init(const Standard_Real tolerance,
1704 const Standard_Boolean optionSewing,
1705 const Standard_Boolean optionAnalysis,
1706 const Standard_Boolean optionCutting,
1707 const Standard_Boolean optionNonmanifold)
1708{
1709 // Set tolerance and Perform options
1710 myTolerance = tolerance;
1711 mySewing = optionSewing;
1712 myAnalysis = optionAnalysis;
1713 myCutting = optionCutting;
1714 myNonmanifold = optionNonmanifold;
1715 // Set min and max tolerances
1716 myMinTolerance = tolerance*1e-4; //szv: proposal
1717 if (myMinTolerance < Precision::Confusion()) myMinTolerance = Precision::Confusion();
1718 myMaxTolerance = Precision::Infinite();
1719 // Set other modes
1720 myFaceMode = Standard_True;
1721 myFloatingEdgesMode = Standard_False;
1722 //myCuttingFloatingEdgesMode = Standard_False; //gka
1723 mySameParameterMode = Standard_True;
1724 myLocalToleranceMode = Standard_False;
1725 mySewedShape.Nullify();
1726 // Load empty shape
1727 Load(TopoDS_Shape());
1728}
1729
1730//=======================================================================
1731//function : Load
1732//purpose : Loads the context shape
1733//=======================================================================
1734
1735void BRepBuilderAPI_Sewing::Load(const TopoDS_Shape& theShape)
1736{
1737 myReShape->Clear();
1738 if (theShape.IsNull()) myShape.Nullify();
1739 else myShape = myReShape->Apply(theShape);
1740 mySewedShape.Nullify();
1741 // Nullify flags and counters
1742 myNbShapes = myNbEdges = myNbVertices = 0;
1743 // Clear all maps
1744 myOldShapes.Clear();
1745 //myOldFaces.Clear();
1746 myDegenerated.Clear();
1747 myFreeEdges.Clear();
1748 myMultipleEdges.Clear();
1749 myContigousEdges.Clear();
1750 myContigSecBound.Clear();
1751 myBoundFaces.Clear();
1752 myBoundSections.Clear();
1753 myVertexNode.Clear();
1754 myVertexNodeFree.Clear();
1755 myNodeSections.Clear();
1756 myCuttingNode.Clear();
1757 mySectionBound.Clear();
1758 myLittleFace.Clear();
1759}
1760
1761//=======================================================================
1762//function : Add
1763//purpose :
1764//=======================================================================
1765
1766void BRepBuilderAPI_Sewing::Add(const TopoDS_Shape& aShape)
1767{
1768 if (aShape.IsNull()) return;
1769 TopoDS_Shape oShape = myReShape->Apply(aShape);
1770 myOldShapes.Add(aShape,oShape);
1771 myNbShapes = myOldShapes.Extent();
1772}
1773
1774//=======================================================================
1775//function : Perform
1776//purpose :
1777//=======================================================================
1778
1779#ifdef DEB
1780#include <OSD_Timer.hxx>
1781#endif
1782
92434a36 1783void BRepBuilderAPI_Sewing::Perform(const Handle(Message_ProgressIndicator)& thePI)
7fd59977 1784{
92434a36
A
1785 const Standard_Integer aNumberOfStages = myAnalysis + myCutting + mySewing + 2;
1786 Message_ProgressSentry aPS (thePI, "Sewing", 0, aNumberOfStages, 1);
7fd59977 1787#ifdef DEB
1788 Standard_Real t_total = 0., t_analysis = 0., t_assembling = 0., t_cutting = 0., t_merging = 0.;
1789 OSD_Chronometer chr_total, chr_local;
1790 chr_total.Reset();
1791 chr_total.Start();
1792#endif
1793
1794 // face analysis
92434a36
A
1795 if (myAnalysis)
1796 {
7fd59977 1797#if DEB
1798 cout << "Begin face analysis..." << endl;
1799 chr_local.Reset();
1800 chr_local.Start();
1801#endif
92434a36
A
1802 FaceAnalysis (thePI);
1803 if (!aPS.More())
1804 return;
1805 aPS.Next();
7fd59977 1806#if DEB
1807 chr_local.Stop();
1808 chr_local.Show(t_analysis);
1809 cout << "Face analysis finished after " << t_analysis << " s" << endl;
1810#endif
1811 }
1812
92434a36
A
1813 if (myNbShapes || !myShape.IsNull())
1814 {
7fd59977 1815
1816 FindFreeBoundaries();
1817
92434a36
A
1818 if (myBoundFaces.Extent())
1819 {
7fd59977 1820
1821#if DEB
1822 cout << "Begin vertices assembling..." << endl;
1823 chr_local.Reset();
1824 chr_local.Start();
1825#endif
92434a36
A
1826 VerticesAssembling (thePI);
1827 if (!aPS.More())
1828 return;
1829 aPS.Next();
7fd59977 1830#if DEB
1831 chr_local.Stop();
1832 chr_local.Show(t_assembling);
1833 cout << "Vertices assembling finished after " << t_assembling << " s" << endl;
1834#endif
92434a36
A
1835 if (myCutting)
1836 {
7fd59977 1837#if DEB
92434a36
A
1838 cout << "Begin cutting..." << endl;
1839 chr_local.Reset();
1840 chr_local.Start();
7fd59977 1841#endif
92434a36
A
1842 Cutting (thePI);
1843 if (!aPS.More())
1844 return;
1845 aPS.Next();
7fd59977 1846#if DEB
92434a36
A
1847 chr_local.Stop();
1848 chr_local.Show(t_cutting);
1849 cout << "Cutting finished after " << t_cutting << " s" << endl;
7fd59977 1850#endif
1851 }
1852#if DEB
1853 cout << "Begin merging..." << endl;
1854 chr_local.Reset();
1855 chr_local.Start();
1856#endif
92434a36
A
1857 Merging (Standard_True, thePI);
1858 if (!aPS.More())
1859 return;
1860 aPS.Next();
7fd59977 1861#if DEB
1862 chr_local.Stop();
1863 chr_local.Show(t_merging);
1864 cout << "Merging finished after " << t_merging << " s" << endl;
1865#endif
1866 }
92434a36
A
1867 else
1868 {
1869 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1870 if (myCutting)
1871 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1872 aPS.Next( 1, Handle(TCollection_HAsciiString)());
1873 if (!aPS.More())
1874 return;
1875 }
7fd59977 1876
92434a36
A
1877 if (mySewing)
1878 {
7fd59977 1879
1880#if DEB
1881 cout << "Creating sewed shape..." << endl;
1882#endif
1883 // examine the multiple edges if any and process sameparameter for edges if necessary
92434a36
A
1884 EdgeProcessing (thePI);
1885 if (!aPS.More())
1886 return;
7fd59977 1887 CreateSewedShape();
92434a36
A
1888 if (!aPS.More())
1889 {
1890 mySewedShape.Nullify();
1891 return;
1892 }
1893 if (mySameParameterMode && myFaceMode)
1894 SameParameterShape();
1895 if (!aPS.More())
1896 {
1897 mySewedShape.Nullify();
1898 return;
1899 }
7fd59977 1900#if DEB
1901 cout << "Sewed shape created" << endl;
1902#endif
1903 }
92434a36 1904
7fd59977 1905 // create edge informations for output
1906 CreateOutputInformations();
92434a36
A
1907 if (!aPS.More())
1908 {
1909 mySewedShape.Nullify();
1910 return;
1911 }
7fd59977 1912 }
1913#if DEB
1914 chr_total.Stop();
1915 chr_total.Show(t_total);
1916 cout << "Sewing finished!" << endl;
1917 cout << " analysis time : " << t_analysis << " s" << endl;
1918 cout << " assembling time : " << t_assembling << " s" << endl;
1919 cout << " cutting time : " << t_cutting << " s" << endl;
1920 cout << " merging time : " << t_merging << " s" << endl;
1921 cout << "Total time : " << t_total << " s" << endl;
1922#endif
1923}
1924
1925//=======================================================================
1926//function : SewedShape
1927//purpose : give the sewed shape
1928// if a null shape, reasons:
1929// -- no useable input shapes : all input shapes are degenerated
1930// -- has multiple edges
1931//=======================================================================
1932
1933const TopoDS_Shape& BRepBuilderAPI_Sewing::SewedShape() const
1934{
1935 return mySewedShape;
1936}
1937
1938//=======================================================================
1939//function : NbFreeEdges
1940//purpose :
1941//=======================================================================
1942
1943Standard_Integer BRepBuilderAPI_Sewing::NbFreeEdges() const
1944{
1945 return myFreeEdges.Extent();
1946}
1947
1948//=======================================================================
1949//function : FreeEdge
1950//purpose :
1951//=======================================================================
1952
1953const TopoDS_Edge& BRepBuilderAPI_Sewing::FreeEdge(const Standard_Integer index) const
1954{
1955 Standard_OutOfRange_Raise_if(index < 0 || index > NbFreeEdges(), "BRepBuilderAPI_Sewing::FreeEdge");
1956 return TopoDS::Edge(myFreeEdges(index));
1957}
1958
1959//=======================================================================
1960//function : NbMultipleEdges
1961//purpose :
1962//=======================================================================
1963
1964Standard_Integer BRepBuilderAPI_Sewing::NbMultipleEdges() const
1965{
1966 return myMultipleEdges.Extent();
1967}
1968
1969//=======================================================================
1970//function : MultipleEdge
1971//purpose :
1972//=======================================================================
1973
1974const TopoDS_Edge& BRepBuilderAPI_Sewing::MultipleEdge(const Standard_Integer index) const
1975{
1976 Standard_OutOfRange_Raise_if(index < 0 || index > NbMultipleEdges(), "BRepBuilderAPI_Sewing::MultipleEdge");
1977 return TopoDS::Edge(myMultipleEdges(index));
1978}
1979
1980//=======================================================================
1981//function : NbContigousEdges
1982//purpose :
1983//=======================================================================
1984
1985Standard_Integer BRepBuilderAPI_Sewing::NbContigousEdges() const
1986{
1987 return myContigousEdges.Extent();
1988}
1989
1990//=======================================================================
1991//function : ContigousEdge
1992//purpose :
1993//=======================================================================
1994
1995const TopoDS_Edge& BRepBuilderAPI_Sewing::ContigousEdge(const Standard_Integer index) const
1996{
1997 Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdge");
1998 return TopoDS::Edge(myContigousEdges.FindKey(index));
1999}
2000
2001//=======================================================================
2002//function : ContigousEdgeCouple
2003//purpose :
2004//=======================================================================
2005
2006const TopTools_ListOfShape& BRepBuilderAPI_Sewing::ContigousEdgeCouple(const Standard_Integer index) const
2007{
2008 Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdgeCouple");
2009 return myContigousEdges(index);
2010}
2011
2012//=======================================================================
2013//function : IsSectionBound
2014//purpose :
2015//=======================================================================
2016
2017Standard_Boolean BRepBuilderAPI_Sewing::IsSectionBound(const TopoDS_Edge& section) const
2018{
2019 if(myContigSecBound.IsBound(section)) {
2020 return Standard_True;
2021 }
2022 else {
2023 return Standard_False;
2024 }
2025}
2026
2027//=======================================================================
2028//function : SectionToBoundary
2029//purpose :
2030//=======================================================================
2031
2032const TopoDS_Edge& BRepBuilderAPI_Sewing::SectionToBoundary(const TopoDS_Edge& section) const
2033{
2034 Standard_NoSuchObject_Raise_if(!IsSectionBound(section), "BRepBuilderAPI_Sewing::SectionToBoundary");
2035 return TopoDS::Edge(myContigSecBound(section));
2036}
2037//=======================================================================
2038//function : NbDeletedFaces
2039//purpose :
2040//=======================================================================
2041 Standard_Integer BRepBuilderAPI_Sewing::NbDeletedFaces() const
2042{
2043 return myLittleFace.Extent();
2044}
2045
2046//=======================================================================
2047//function : DeletedFace
2048//purpose :
2049//=======================================================================
2050const TopoDS_Face& BRepBuilderAPI_Sewing::DeletedFace(const Standard_Integer index) const
2051{
2052 Standard_OutOfRange_Raise_if(index < 0 || index > NbDeletedFaces(), "BRepBuilderAPI_Sewing::DeletedFace");
2053 return TopoDS::Face(myLittleFace(index));
2054}
2055
2056//=======================================================================
2057//function : NbDegeneratedShapes
2058//purpose :
2059//=======================================================================
2060
2061Standard_Integer BRepBuilderAPI_Sewing::NbDegeneratedShapes() const
2062{
2063 return myDegenerated.Extent();
2064}
2065
2066//=======================================================================
2067//function : DegeneratedShape
2068//purpose :
2069//=======================================================================
2070
2071const TopoDS_Shape& BRepBuilderAPI_Sewing::DegeneratedShape(const Standard_Integer index) const
2072{
2073 Standard_OutOfRange_Raise_if(index < 0 || index > NbDegeneratedShapes(), "BRepBuilderAPI_Sewing::DegereratedShape");
2074 return myDegenerated(index);
2075}
2076
2077//=======================================================================
2078//function : IsDegenerated
2079//purpose :
2080//=======================================================================
2081
2082Standard_Boolean BRepBuilderAPI_Sewing::IsDegenerated(const TopoDS_Shape& aShape) const
2083{
2084 TopoDS_Shape NewShape = myReShape->Apply(aShape);
2085 // Degenerated face
2086 if (aShape.ShapeType() == TopAbs_FACE)
2087 return NewShape.IsNull();
2088 if (NewShape.IsNull()) return Standard_False;
2089 // Degenerated edge
2090 if (NewShape.ShapeType() == TopAbs_EDGE)
2091 return BRep_Tool::Degenerated(TopoDS::Edge(NewShape));
2092 // Degenerated wire
2093 if (NewShape.ShapeType() == TopAbs_WIRE) {
2094 Standard_Boolean isDegenerated = Standard_True;
2095 for (TopoDS_Iterator aIt(NewShape); aIt.More() && isDegenerated; aIt.Next())
2096 isDegenerated = BRep_Tool::Degenerated(TopoDS::Edge(aIt.Value()));
2097 return isDegenerated;
2098 }
2099 return Standard_False;
2100}
2101
2102//=======================================================================
2103//function : IsModified
2104//purpose :
2105//=======================================================================
2106
2107Standard_Boolean BRepBuilderAPI_Sewing::IsModified(const TopoDS_Shape& aShape) const
2108{
2109 TopoDS_Shape NewShape = aShape;
2110 if (myOldShapes.Contains(aShape))
2111 NewShape = myOldShapes.FindFromKey(aShape);
2112 if(!NewShape.IsSame(aShape)) return Standard_True;
2113 return Standard_False;
2114}
2115
2116//=======================================================================
2117//function : Modified
2118//purpose :
2119//=======================================================================
2120
2121const TopoDS_Shape& BRepBuilderAPI_Sewing::Modified(const TopoDS_Shape& aShape) const
2122{
2123 if (myOldShapes.Contains(aShape)) return myOldShapes.FindFromKey(aShape);
2124 //if (myOldFaces.Contains(aShape)) return myOldFaces.FindFromKey(aShape);
2125 return aShape;
2126}
2127
2128//=======================================================================
2129//function : IsModifiedSubShape
2130//purpose :
2131//=======================================================================
2132
2133Standard_Boolean BRepBuilderAPI_Sewing::IsModifiedSubShape(const TopoDS_Shape& aShape) const
2134{
2135 TopoDS_Shape NewShape = myReShape->Apply(aShape);
2136 if(!NewShape.IsSame(aShape)) return Standard_True;
2137 return Standard_False;
2138}
2139
2140//=======================================================================
2141//function : ModifiedSubShape
2142//purpose :
2143//=======================================================================
2144
2145TopoDS_Shape BRepBuilderAPI_Sewing::ModifiedSubShape(const TopoDS_Shape& aShape) const
2146{
2147 return myReShape->Apply(aShape);
2148}
2149
2150//=======================================================================
2151//function : Dump
2152//purpose :
2153//=======================================================================
2154
2155void BRepBuilderAPI_Sewing::Dump() const
2156{
2157 Standard_Integer i, NbBounds = myBoundFaces.Extent(), NbSections = 0;
2158 TopTools_MapOfShape mapVertices, mapEdges;
2159 for (i = 1; i <= NbBounds; i++) {
2160 TopoDS_Shape bound = myBoundFaces.FindKey(i);
2161 if (myBoundSections.IsBound(bound)) NbSections += myBoundSections(bound).Extent();
2162 else NbSections++;
2163 TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
2164 for (; aExp.More(); aExp.Next()) {
2165 TopoDS_Edge E = TopoDS::Edge(aExp.Current());
2166 mapEdges.Add(E);
2167 TopoDS_Vertex V1, V2;
2168 TopExp::Vertices(E,V1,V2);
2169 mapVertices.Add(V1);
2170 mapVertices.Add(V2);
2171 }
2172 }
2173 cout << " " << endl;
2174 cout << " Informations " << endl;
2175 cout << " ===========================================================" << endl;
2176 cout << " " << endl;
2177 cout << " Number of input shapes : " << myOldShapes.Extent() << endl;
2178 cout << " Number of actual shapes : " << myNbShapes << endl;
2179 cout << " Number of Bounds : " << NbBounds << endl;
2180 cout << " Number of Sections : " << NbSections << endl;
2181 cout << " Number of Edges : " << mapEdges.Extent() << endl;
2182 cout << " Number of Vertices : " << myNbVertices << endl;
2183 cout << " Number of Nodes : " << mapVertices.Extent() << endl;
2184 cout << " Number of Free Edges : " << myFreeEdges.Extent() << endl;
2185 cout << " Number of Contigous Edges : " << myContigousEdges.Extent() << endl;
2186 cout << " Number of Multiple Edges : " << myMultipleEdges.Extent() << endl;
2187 cout << " Number of Degenerated Edges : " << myDegenerated.Extent() << endl;
2188 cout << " ===========================================================" << endl;
2189 cout << " " << endl;
2190}
2191
2192//=======================================================================
2193//function : FaceAnalysis
2194//purpose : Remove
2195// Modifies:
2196// myNbShapes
2197// myOldShapes
2198//
2199// Constructs:
2200// myDegenerated
2201//=======================================================================
2202
92434a36 2203void BRepBuilderAPI_Sewing::FaceAnalysis(const Handle(Message_ProgressIndicator)& thePI)
7fd59977 2204{
2205 if (!myShape.IsNull() && myOldShapes.IsEmpty()) {
2206 Add(myShape);
2207 myShape.Nullify();
2208 }
2209
2210 BRep_Builder B;
2211 TopTools_MapOfShape SmallEdges;
2212 TopTools_DataMapOfShapeListOfShape GluedVertices;
2213 Standard_Integer i = 1;
92434a36
A
2214 Message_ProgressSentry aPS (thePI, "Shape analysis", 0, myOldShapes.Extent(), 1);
2215 for (i = 1; i <= myOldShapes.Extent() && aPS.More(); i++, aPS.Next()) {
7fd59977 2216 for (TopExp_Explorer fexp(myOldShapes(i),TopAbs_FACE); fexp.More(); fexp.Next()) {
2217
2218 // Retrieve current face
2219 TopoDS_Shape aTmpShape = fexp.Current(); //for porting
2220 TopoDS_Face face = TopoDS::Face(aTmpShape);
2221 Standard_Integer nbEdges = 0, nbSmall = 0;
2222
2223 // Build replacing face
2224 aTmpShape = face.EmptyCopied().Oriented(TopAbs_FORWARD); //for porting
2225 TopoDS_Face nface = TopoDS::Face(aTmpShape);
2226 Standard_Boolean isFaceChanged = Standard_False;
2227
2228 TopoDS_Iterator witer(face.Oriented(TopAbs_FORWARD));
2229 for (; witer.More(); witer.Next()) {
2230
2231 // Retrieve current wire
2232 aTmpShape = witer.Value(); //for porting
2233 if( aTmpShape.ShapeType() != TopAbs_WIRE) continue;
2234 TopoDS_Wire wire = TopoDS::Wire(aTmpShape);
2235
2236 // Build replacing wire
2237 aTmpShape = wire.EmptyCopied().Oriented(TopAbs_FORWARD);
2238 TopoDS_Wire nwire = TopoDS::Wire(aTmpShape);
2239 Standard_Boolean isWireChanged = Standard_False;
2240
2241 TopoDS_Iterator eiter(wire.Oriented(TopAbs_FORWARD));
2242 for (; eiter.More(); eiter.Next()) {
2243
2244 // Retrieve current edge
2245 aTmpShape = eiter.Value(); //for porting
2246 TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
2247 nbEdges++;
2248
2249 // Process degenerated edge
2250 if (BRep_Tool::Degenerated(edge)) {
2251 B.Add(nwire,edge); // Old edge kept
2252 myDegenerated.Add(edge);
2253 nbSmall++;
2254 continue;
2255 }
2256
2257 Standard_Boolean isSmall = SmallEdges.Contains(edge);
2258 if (!isSmall) {
2259
2260 // Check for small edge
2261 Standard_Real first, last;
2262 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,first,last);
2263 if (c3d.IsNull()) {
2264#ifdef DEB
2265 cout << "Warning: Possibly small edge can be sewed: No 3D curve" << endl;
2266#endif
2267 }
2268 else {
2269 // Evaluate curve compactness
2270 const Standard_Integer npt = 5;
2271 gp_Pnt cp((c3d->Value(first).XYZ()+c3d->Value(last).XYZ())*0.5);
2272 Standard_Real dist, maxdist = 0.0;
2273 Standard_Real delta = (last - first)/(npt - 1);
2274 for (Standard_Integer idx = 0; idx < npt; idx++) {
2275 dist = cp.Distance(c3d->Value(first + idx*delta));
2276 if (maxdist < dist) maxdist = dist;
2277 }
2278 isSmall = (2.*maxdist <= MinTolerance());
2279 /*try {
2280 GeomAdaptor_Curve cAdapt(c3d);
2281 Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt,first,last);
2282 isSmall = (length <= MinTolerance());
2283 }
2284 catch (Standard_Failure) {
2285#ifdef DEB
2286 cout << "Warning: Possibly small edge can be sewed: ";
2287 Standard_Failure::Caught()->Print(cout); cout << endl;
2288#endif
2289 }*/
2290 }
2291
2292 if (isSmall) {
2293
2294 // Store small edge in the map
2295 SmallEdges.Add(edge);
2296
2297 TopoDS_Vertex v1, v2;
2298 TopExp::Vertices(edge,v1,v2);
2299 TopoDS_Shape nv1 = myReShape->Apply(v1), nv2 = myReShape->Apply(v2);
2300
2301 // Store glued vertices
2302 if (!nv1.IsSame(v1)) {
2303 TopTools_ListOfShape& vlist1 = GluedVertices(nv1);
2304 // First vertex was already glued
2305 if (!nv2.IsSame(v2)) {
2306 // Merge lists of glued vertices
2307 if (!nv1.IsSame(nv2)) {
2308 TopTools_ListIteratorOfListOfShape liter(GluedVertices(nv2));
2309 for (; liter.More(); liter.Next()) {
2310 TopoDS_Shape v = liter.Value();
2311 myReShape->Replace(v,nv1.Oriented(v.Orientation()));
2312 vlist1.Append(v);
2313 }
2314 GluedVertices.UnBind(nv2);
2315 }
2316 }
2317 else {
2318 // Add second vertex to the existing list
2319 vlist1.Append(v2);
2320 myReShape->Replace(v2,nv1.Oriented(v2.Orientation()));
2321 }
2322 }
2323 else if (!nv2.IsSame(v2)) {
2324 // Add first vertex to the existing list
2325 GluedVertices(nv2).Append(v1);
2326 myReShape->Replace(v1,nv2.Oriented(v1.Orientation()));
2327 }
2328 else if (!v1.IsSame(v2)) {
2329 // Record new glued vertices
2330 TopoDS_Vertex nv;
2331 B.MakeVertex(nv);
2332 TopTools_ListOfShape vlist;
2333 vlist.Append(v1);
2334 vlist.Append(v2);
2335 GluedVertices.Bind(nv,vlist);
2336 myReShape->Replace(v1,nv.Oriented(v1.Orientation()));
2337 myReShape->Replace(v2,nv.Oriented(v2.Orientation()));
2338 }
2339 }
2340 }
2341
2342 // Replace small edge
2343 if (isSmall) {
2344#ifdef DEB
2345 cout << "Warning: Small edge made degenerated by FaceAnalysis" << endl;
2346#endif
2347 nbSmall++;
2348 // Create new degenerated edge
2349 aTmpShape = edge.Oriented(TopAbs_FORWARD);
2350 TopoDS_Edge fedge = TopoDS::Edge(aTmpShape);
2351 Standard_Real pfirst, plast;
2352 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(fedge,face,pfirst,plast);
2353 if (!c2d.IsNull()) {
2354 TopoDS_Edge nedge;
2355 B.MakeEdge(nedge);
2356 B.UpdateEdge(nedge,c2d,face,Precision::Confusion());
2357 B.Range(nedge,pfirst,plast);
2358 B.Degenerated(nedge,Standard_True);
2359 TopoDS_Vertex v1, v2;
2360 TopExp::Vertices(fedge,v1,v2);
2361 B.Add(nedge,myReShape->Apply(v1).Oriented(v1.Orientation()));
2362 B.Add(nedge,myReShape->Apply(v2).Oriented(v2.Orientation()));
2363 B.Add(nwire,nedge.Oriented(edge.Orientation()));
2364 myDegenerated.Add(nedge);
2365 }
2366 isWireChanged = Standard_True;
2367 }
2368 else B.Add(nwire,edge); // Old edge kept
2369 }
2370
2371 // Record wire in the new face
2372 if (isWireChanged) {
2373 B.Add(nface,nwire.Oriented(wire.Orientation()));
2374 isFaceChanged = Standard_True;
2375 }
2376 else B.Add(nface,wire);
2377 }
2378
2379 // Remove small face
2380 if (nbSmall == nbEdges) {
2381#ifdef DEB
2382 cout << "Warning: Small face removed by FaceAnalysis" << endl;
2383#endif
2384 myLittleFace.Add(face);
2385 myReShape->Remove(face);
2386 }
2387 else if (isFaceChanged) {
2388
2389 myReShape->Replace(face,nface.Oriented(face.Orientation()));
2390 }
2391 }
2392 }
2393
2394 // Update glued vertices
2395 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape miter(GluedVertices);
2396 for (; miter.More(); miter.Next()) {
2397 TopoDS_Vertex vnew = TopoDS::Vertex(miter.Key());
2398 gp_XYZ coord(0.,0.,0.);
2399 Standard_Integer nbPoints = 0;
2400 const TopTools_ListOfShape& vlist = miter.Value();
2401 TopTools_ListIteratorOfListOfShape liter1(vlist);
2402 for (; liter1.More(); liter1.Next()) {
2403 coord += BRep_Tool::Pnt(TopoDS::Vertex(liter1.Value())).XYZ();
2404 nbPoints++;
2405 }
2406 if (nbPoints) {
2407 gp_Pnt vp(coord / nbPoints);
2408 Standard_Real tol = 0.0, mtol = 0.0;
2409 TopTools_ListIteratorOfListOfShape liter2(vlist);
2410 for (; liter2.More(); liter2.Next()) {
2411 Standard_Real vtol = BRep_Tool::Tolerance(TopoDS::Vertex(liter2.Value()));
2412 if (mtol < vtol) mtol = vtol;
2413 vtol = vp.Distance(BRep_Tool::Pnt(TopoDS::Vertex(liter2.Value())));
2414 if (tol < vtol) tol = vtol;
2415 }
2416 B.UpdateVertex(vnew,vp,tol+mtol);
2417 }
2418 }
2419
2420 // Update input shapes
2421 for (i = 1; i <= myOldShapes.Extent(); i++)
2422 myOldShapes(i) = myReShape->Apply(myOldShapes(i));
2423}
2424
2425//=======================================================================
2426//function : FindFreeBoundaries
2427//purpose : Constructs :
2428// myBoundFaces (bound = list of faces) - REFERENCE
2429// myVertexNode (vertex = node)
2430// myVertexNodeFree (floating vertex = node)
2431//
2432//=======================================================================
2433
2434void BRepBuilderAPI_Sewing::FindFreeBoundaries()
2435{
2436 // Take into account the context shape if needed
2437 TopTools_IndexedMapOfShape NewShapes;
2438 if (!myShape.IsNull()) {
2439 if (myOldShapes.IsEmpty()) {
2440 Add(myShape);
2441 myShape.Nullify();
2442 }
2443 else {
2444 TopoDS_Shape newShape = myReShape->Apply(myShape);
2445 if (!newShape.IsNull()) NewShapes.Add(newShape);
2446 }
2447 }
2448 // Create map Edge -> Faces
2449 TopTools_IndexedDataMapOfShapeListOfShape EdgeFaces;
2450 Standard_Integer i, nbShapes = myOldShapes.Extent();
2451 for (i = 1; i <= nbShapes; i++) {
2452 // Retrieve new shape
2453 TopoDS_Shape shape = myOldShapes(i);
2454 if (shape.IsNull()) continue;
2455 NewShapes.Add(shape);
2456 // Explore shape to find all boundaries
2457 for (TopExp_Explorer eExp(shape,TopAbs_EDGE); eExp.More(); eExp.Next()) {
2458 TopoDS_Shape edge = eExp.Current();
2459 if (!EdgeFaces.Contains(edge)) {
2460 TopTools_ListOfShape listFaces;
2461 EdgeFaces.Add(edge,listFaces);
2462 }
2463 }
2464 }
2465 // Fill map Edge -> Faces
2466 nbShapes = NewShapes.Extent();
2467 TopTools_MapOfShape mapFaces;
2468 for (i = 1; i <= nbShapes; i++) {
2469 // Explore shape to find all faces
2470 TopExp_Explorer fExp(NewShapes.FindKey(i),TopAbs_FACE);
2471 for (; fExp.More(); fExp.Next()) {
2472 TopoDS_Shape face = fExp.Current();
2473 if(mapFaces.Contains(face)) continue;
2474 else
2475 mapFaces.Add(face);
2476 // Explore face to find all boundaries
2477 for (TopoDS_Iterator aIw(face); aIw.More(); aIw.Next()) {
2478 if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
2479 for (TopoDS_Iterator aIIe(aIw.Value()); aIIe.More(); aIIe.Next()) {
2480
2481 TopoDS_Shape edge = aIIe.Value();
2482
2483 if (EdgeFaces.Contains(edge)) {
2484 EdgeFaces.ChangeFromKey(edge).Append(face);
2485 //TopTools_ListOfShape& listFaces = EdgeFaces.ChangeFromKey(edge);
2486 //Standard_Boolean isContained = Standard_False;
2487 //TopTools_ListIteratorOfListOfShape itf(listFaces);
2488 //for (; itf.More() && !isContained; itf.Next())
2489 // isContained = face.IsSame(itf.Value());
2490 //if (!isContained) listFaces.Append(face);
2491 }
2492 }
2493 }
2494 }
2495 }
2496 // Find free boundaries
2497 nbShapes = EdgeFaces.Extent();
2498 for (i = 1; i <= nbShapes; i++) {
2499 TopTools_ListOfShape& listFaces = EdgeFaces(i);
2500 Standard_Integer nbFaces = listFaces.Extent();
2501 TopoDS_Shape edge = EdgeFaces.FindKey(i);
2502 if(edge.Orientation() == TopAbs_INTERNAL)
2503 continue;
2504 Standard_Boolean isSeam = Standard_False;
2505 if (nbFaces == 1) {
2506 TopoDS_Face face = TopoDS::Face(listFaces.First());
2507 isSeam = BRep_Tool::IsClosed(TopoDS::Edge(edge),face);
2508 if (isSeam) {
2509 ///Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
2510 //isSeam = (IsUClosedSurface(surf) || IsVClosedSurface(surf));
2511 //if(!isSeam) {
2512 BRep_Builder aB;
2513 TopoDS_Shape anewEdge = edge.EmptyCopied();
2514 TopoDS_Iterator aItV(edge);
2515 for( ; aItV.More() ; aItV.Next())
2516 aB.Add(anewEdge,aItV.Value());
2517
2518
2519
2520 Standard_Real first2d,last2d;
2521 Handle(Geom2d_Curve) c2dold =
2522 BRep_Tool::CurveOnSurface(TopoDS::Edge(edge),TopoDS::Face(listFaces.First()),first2d,last2d);
2523
2524 Handle(Geom2d_Curve) c2d;
2525 BRep_Builder B;
2526 B.UpdateEdge(TopoDS::Edge(anewEdge),c2d,c2d,TopoDS::Face(listFaces.First()),0);
2527 B.UpdateEdge(TopoDS::Edge(anewEdge),c2dold,TopoDS::Face(listFaces.First()),0);
2528
2529 Standard_Real aFirst, aLast;
2530 BRep_Tool::Range(TopoDS::Edge(edge),aFirst, aLast);
2531 aB.Range(TopoDS::Edge(anewEdge),aFirst, aLast);
2532 aB.Range(TopoDS::Edge(anewEdge),TopoDS::Face(listFaces.First()),first2d,last2d);
2533 myReShape->Replace(edge,anewEdge);
2534 edge = anewEdge;
2535
2536 //}
2537 isSeam = Standard_False;
2538 }
2539 }
2540 Standard_Boolean isBoundFloat = (myFloatingEdgesMode && !nbFaces);
2541 Standard_Boolean isBound = (myFaceMode && ((myNonmanifold && nbFaces) || (nbFaces == 1 && !isSeam)));
2542 if (isBound || isBoundFloat) {
2543 // Ignore degenerated edge
2544 if (BRep_Tool::Degenerated(TopoDS::Edge(edge))) continue;
2545 // Ignore edge with internal vertices
2546 // Standard_Integer nbVtx = 0;
2547 // for (TopExp_Explorer vExp(edge,TopAbs_VERTEX); vExp.More(); vExp.Next()) nbVtx++;
2548 // if (nbVtx != 2) continue;
2549 // Add to BoundFaces
2550 TopTools_ListOfShape listFacesCopy;
2551 listFacesCopy.Append(listFaces);
2552 myBoundFaces.Add(edge,listFacesCopy);
2553 // Process edge vertices
2554 TopoDS_Vertex vFirst, vLast;
2555 TopExp::Vertices(TopoDS::Edge(edge), vFirst, vLast);
2556 if(vFirst.IsNull() || vLast.IsNull()) continue;
2557 if(vFirst.Orientation() == TopAbs_INTERNAL || vLast.Orientation() == TopAbs_INTERNAL)
2558 continue;
2559 if (isBound) {
2560 // Add to VertexNode
2561 if (!myVertexNode.Contains(vFirst))
2562 myVertexNode.Add(vFirst,vFirst);
2563 if (!myVertexNode.Contains(vLast))
2564 myVertexNode.Add(vLast,vLast);
2565 }
2566 else {
2567 // Add to VertexNodeFree
2568 if (!myVertexNodeFree.Contains(vFirst))
2569 myVertexNodeFree.Add(vFirst,vFirst);
2570 if (!myVertexNodeFree.Contains(vLast))
2571 myVertexNodeFree.Add(vLast,vLast);
2572 }
2573 }
2574 }
2575}
2576
2577//=======================================================================
2578//function : VerticesAssembling
2579//purpose : Modifies :
2580// myVertexNode (nodes glued)
2581// myVertexNodeFree (nodes glued)
2582// myNodeSections (lists of sections merged for glued nodes)
2583//
2584//=======================================================================
2585
2586static Standard_Boolean CreateNewNodes(const TopTools_IndexedDataMapOfShapeShape& NodeNearestNode,
2587 const TopTools_IndexedDataMapOfShapeListOfShape& NodeVertices,
2588 TopTools_IndexedDataMapOfShapeShape& aVertexNode,
2589 TopTools_DataMapOfShapeListOfShape& aNodeEdges)
2590{
2591 Standard_Integer i, nbNearest = NodeNearestNode.Extent();
2592
2593 // Create new nodes
2594 BRep_Builder B;
2595 TopTools_DataMapOfShapeShape OldNodeNewNode;
2596 TopTools_DataMapOfShapeListOfShape NewNodeOldNodes;
2597 for (i = 1; i <= nbNearest; i++) {
2598 // Retrieve a pair of nodes to merge
2599 TopoDS_Shape oldnode1 = NodeNearestNode.FindKey(i);
2600 TopoDS_Shape oldnode2 = NodeNearestNode(i);
2601 // Second node should also be in the map
2602 if (!NodeNearestNode.Contains(oldnode2)) continue;
2603 // Get new node for old node #1
2604 if (OldNodeNewNode.IsBound(oldnode1)) {
2605 TopoDS_Shape newnode1 = OldNodeNewNode(oldnode1);
2606 if (OldNodeNewNode.IsBound(oldnode2)) {
2607 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2608 if (!newnode1.IsSame(newnode2)) {
2609 // Change data for new node #2
2610 TopTools_ListOfShape& lnode1 = NewNodeOldNodes(newnode1);
2611 TopTools_ListIteratorOfListOfShape itn(NewNodeOldNodes(newnode2));
2612 for (; itn.More(); itn.Next()) {
2613 TopoDS_Shape node2 = itn.Value();
2614 lnode1.Append(node2);
2615 OldNodeNewNode(node2) = newnode1;
2616 }
2617 NewNodeOldNodes.UnBind(newnode2);
2618 }
2619 }
2620 else {
2621 // Old node #2 is not bound - add to old node #1
2622 OldNodeNewNode.Bind(oldnode2,newnode1);
2623 NewNodeOldNodes(newnode1).Append(oldnode2);
2624 }
2625 }
2626 else {
2627 if (OldNodeNewNode.IsBound(oldnode2)) {
2628 // Old node #1 is not bound - add to old node #2
2629 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2);
2630 OldNodeNewNode.Bind(oldnode1,newnode2);
2631 NewNodeOldNodes(newnode2).Append(oldnode1);
2632 }
2633 else {
2634 // Nodes are not bound - create new node
2635 TopoDS_Vertex newnode;
2636 B.MakeVertex(newnode);
2637 OldNodeNewNode.Bind(oldnode1,newnode);
2638 OldNodeNewNode.Bind(oldnode2,newnode);
2639 TopTools_ListOfShape lnodes;
2640 lnodes.Append(oldnode1);
2641 lnodes.Append(oldnode2);
2642 NewNodeOldNodes.Bind(newnode,lnodes);
2643 }
2644 }
2645 }
2646
2647 // Stop if no new nodes created
2648 if (!NewNodeOldNodes.Extent()) return Standard_False;
2649
2650 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter1(NewNodeOldNodes);
2651 for (; iter1.More(); iter1.Next()) {
2652 const TopoDS_Vertex& newnode = TopoDS::Vertex(iter1.Key());
2653 // Calculate new node center point
2654 gp_XYZ theCoordinates(0.,0.,0.);
2655 TopTools_ListOfShape lvert; // Accumulate node vertices
2656 TopTools_MapOfShape medge;
2657 TopTools_ListOfShape ledge; // Accumulate node edges
2658 // Iterate on old nodes
2659 TopTools_ListIteratorOfListOfShape itn(iter1.Value());
2660 for (; itn.More(); itn.Next()) {
2661 const TopoDS_Shape& oldnode = itn.Value();
2662 // Iterate on node vertices
2663 TopTools_ListIteratorOfListOfShape itv(NodeVertices.FindFromKey(oldnode));
2664 for (; itv.More(); itv.Next()) {
2665 TopoDS_Vertex vertex = TopoDS::Vertex(itv.Value());
2666 // Change node for vertex
2667 aVertexNode.ChangeFromKey(vertex) = newnode;
2668 // Accumulate coordinates
2669 theCoordinates += BRep_Tool::Pnt(vertex).XYZ();
2670 lvert.Append(vertex);
2671 }
2672 // Iterate on node edges
2673 const TopTools_ListOfShape& edges = aNodeEdges(oldnode);
2674 TopTools_ListIteratorOfListOfShape ite(edges);
2675 for (; ite.More(); ite.Next()) {
2676 TopoDS_Shape edge = ite.Value();
2677 if (!medge.Contains(edge)) { medge.Add(edge); ledge.Append(edge); }
2678 }
2679 // Unbind old node edges
2680 aNodeEdges.UnBind(oldnode);
2681 }
2682 // Bind new node edges
2683 aNodeEdges.Bind(newnode,ledge);
2684 gp_Pnt center(theCoordinates / lvert.Extent());
2685 // Calculate new node tolerance
2686 Standard_Real toler = 0.0;
2687 TopTools_ListIteratorOfListOfShape itv(lvert);
2688 for (; itv.More(); itv.Next()) {
2689 const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value());
2690 Standard_Real t = center.Distance(BRep_Tool::Pnt(vertex)) + BRep_Tool::Tolerance(vertex);
2691 if (toler < t) toler = t;
2692 }
2693 // Update new node parameters
2694 B.UpdateVertex(newnode,center,toler);
2695 }
2696
2697 return Standard_True;
2698}
2699
2700static Standard_Integer IsMergedVertices(const TopoDS_Shape& face1,
2701 const TopoDS_Shape& e1, const TopoDS_Shape& e2,
2702 const TopoDS_Shape& vtx1, const TopoDS_Shape& vtx2)
2703{
2704 //Case of floating edges
2705 if (face1.IsNull())
2706 return (!IsClosedShape(e1,vtx1,vtx2));
2707
2708 // Find wires containing given edges
2709 TopoDS_Shape wire1, wire2;
2710 TopExp_Explorer itw(face1,TopAbs_WIRE);
2711 for (; itw.More() && (wire1.IsNull() || wire2.IsNull()); itw.Next()) {
2712 TopoDS_Iterator ite(itw.Current(),Standard_False);
2713 for (; ite.More() && (wire1.IsNull() || wire2.IsNull()); ite.Next()) {
2714 if (wire1.IsNull() && e1.IsSame(ite.Value())) wire1 = itw.Current();
2715 if (wire2.IsNull() && e2.IsSame(ite.Value())) wire2 = itw.Current();
2716 }
2717 }
2718 Standard_Integer Status = 0;
2719 if (!wire1.IsNull() && !wire2.IsNull()) {
2720 if (wire1.IsSame(wire2)) {
2721 for (TopoDS_Iterator aIte(wire1,Standard_False); aIte.More(); aIte.Next()) {
2722 TopoDS_Vertex ve1,ve2;
2723 TopExp::Vertices(TopoDS::Edge(aIte.Value()),ve1,ve2);
2724 if ((ve1.IsSame(vtx1) && ve2.IsSame(vtx2)) ||
2725 (ve2.IsSame(vtx1) && ve1.IsSame(vtx2)))
2726 return (IsClosedShape(aIte.Value(),vtx1,vtx2)? 0 : 1);
2727 }
2728 if (IsClosedShape(wire1,vtx1,vtx2)) {
2729 TopoDS_Vertex V1, V2;
2730 TopExp::Vertices(TopoDS::Wire(wire1),V1,V2);
2731 Standard_Boolean isEndVertex = ((V1.IsSame(vtx1) && V2.IsSame(vtx2)) ||
2732 (V2.IsSame(vtx1) && V1.IsSame(vtx2)));
2733 if (!isEndVertex) Status = 1;
2734 }
2735 else Status = 1;
2736 }
2737 else Status = -1;
2738 }
2739 return Status;
2740}
2741
2742static Standard_Boolean GlueVertices(TopTools_IndexedDataMapOfShapeShape& aVertexNode,
92434a36
A
2743 TopTools_DataMapOfShapeListOfShape& aNodeEdges,
2744 const TopTools_IndexedDataMapOfShapeListOfShape& aBoundFaces,
2745 const Standard_Real Tolerance,
2746 const Handle(Message_ProgressIndicator)& theProgress)
7fd59977 2747{
2748 Standard_Integer i, nbVertices = aVertexNode.Extent();
2749 // Create map of node -> vertices
2750 TopTools_IndexedDataMapOfShapeListOfShape NodeVertices;
82192477 2751 BRepBuilderAPI_CellFilter aFilter (Tolerance);
2752 BRepBuilderAPI_VertexInspector anInspector (Tolerance);
7fd59977 2753 for (i = 1; i <= nbVertices; i++) {
2754 TopoDS_Shape vertex = aVertexNode.FindKey(i);
2755 TopoDS_Vertex node = TopoDS::Vertex(aVertexNode(i));
2756 if (NodeVertices.Contains(node)) {
2757 NodeVertices.ChangeFromKey(node).Append(vertex);
2758 }
2759 else {
2760 TopTools_ListOfShape vlist;
2761 vlist.Append(vertex);
2762 NodeVertices.Add(node,vlist);
82192477 2763 gp_Pnt aPnt = BRep_Tool::Pnt (TopoDS::Vertex (node));
2764 aFilter.Add (NodeVertices.FindIndex (node), aPnt.XYZ());
2765 anInspector.Add (aPnt.XYZ());
7fd59977 2766 }
2767 }
2768 Standard_Integer nbNodes = NodeVertices.Extent();
2769#ifdef DEB
2770 cout << "Glueing " << nbNodes << " nodes..." << endl;
2771#endif
7fd59977 2772 // Merge nearest nodes
2773 TopTools_IndexedDataMapOfShapeShape NodeNearestNode;
92434a36
A
2774 Message_ProgressSentry aPS (theProgress, "Glueing nodes", 0, nbNodes, 1, Standard_True);
2775 for (i = 1; i <= nbNodes && aPS.More(); i++, aPS.Next()) {
7fd59977 2776 TopoDS_Vertex node1 = TopoDS::Vertex(NodeVertices.FindKey(i));
2777 // Find near nodes
82192477 2778 gp_Pnt pt1 = BRep_Tool::Pnt (node1);
2779 anInspector.SetCurrent (pt1.XYZ());
2780 gp_XYZ aPntMin = anInspector.Shift (pt1.XYZ(), -Tolerance);
2781 gp_XYZ aPntMax = anInspector.Shift (pt1.XYZ(), Tolerance);
2782 aFilter.Inspect (aPntMin, aPntMax, anInspector);
2783 if (anInspector.ResInd().IsEmpty()) continue;
7fd59977 2784 // Retrieve list of edges for the first node
2785 const TopTools_ListOfShape& ledges1 = aNodeEdges(node1);
2786 // Explore list of near nodes and fill the sequence of glued nodes
2787 TopTools_SequenceOfShape SeqNodes;
2788 TopTools_ListOfShape listNodesSameEdge;
82192477 2789 //gp_Pnt pt1 = BRep_Tool::Pnt(node1);
2790 TColStd_ListIteratorOfListOfInteger iter1(anInspector.ResInd());
7fd59977 2791 for (; iter1.More(); iter1.Next()) {
2792 TopoDS_Vertex node2 = TopoDS::Vertex(NodeVertices.FindKey(iter1.Value()));
2793 if (node1 == node2) continue;
2794 // Retrieve list of edges for the second node
2795 const TopTools_ListOfShape& ledges2 = aNodeEdges(node2);
2796 // Check merging condition for the pair of nodes
2797 Standard_Integer Status = 0, isSameEdge = Standard_False;
2798 // Explore edges of the first node
2799 TopTools_ListIteratorOfListOfShape Ie1(ledges1);
2800 for (; Ie1.More() && !Status && !isSameEdge; Ie1.Next()) {
2801 const TopoDS_Shape& e1 = Ie1.Value();
2802 // Obtain real vertex from edge
2803 TopoDS_Shape v1 = node1;
2804 { //szv: Use brackets to destroy local variables
2805 TopoDS_Vertex ov1, ov2;
2806 TopExp::Vertices(TopoDS::Edge(e1),ov1,ov2);
2807 if (aVertexNode.Contains(ov1)) {
2808 if (node1.IsSame(aVertexNode.FindFromKey(ov1))) v1 = ov1;
2809 }
2810 if (aVertexNode.Contains(ov2)) {
2811 if (node1.IsSame(aVertexNode.FindFromKey(ov2))) v1 = ov2;
2812 }
2813 }
2814 // Create map of faces for e1
2815 TopTools_MapOfShape Faces1;
2816 const TopTools_ListOfShape& lfac1 = aBoundFaces.FindFromKey(e1);
2817 if (lfac1.Extent()) {
2818 TopTools_ListIteratorOfListOfShape itf(lfac1);
2819 for (; itf.More(); itf.Next())
2820 if (!itf.Value().IsNull())
2821 Faces1.Add(itf.Value());
2822 }
2823 // Explore edges of the second node
2824 TopTools_ListIteratorOfListOfShape Ie2(ledges2);
2825 for (; Ie2.More() && !Status && !isSameEdge; Ie2.Next()) {
2826 const TopoDS_Shape& e2 = Ie2.Value();
2827 // Obtain real vertex from edge
2828 TopoDS_Shape v2 = node2;
2829 { //szv: Use brackets to destroy local variables
2830 TopoDS_Vertex ov1, ov2;
2831 TopExp::Vertices(TopoDS::Edge(e2),ov1,ov2);
2832 if (aVertexNode.Contains(ov1)) {
2833 if (node2.IsSame(aVertexNode.FindFromKey(ov1))) v2 = ov1;
2834 }
2835 if (aVertexNode.Contains(ov2)) {
2836 if (node2.IsSame(aVertexNode.FindFromKey(ov2))) v2 = ov2;
2837 }
2838 }
2839 // Explore faces for e2
2840 const TopTools_ListOfShape& lfac2 = aBoundFaces.FindFromKey(e2);
2841 if (lfac2.Extent()) {
2842 TopTools_ListIteratorOfListOfShape itf(lfac2);
2843 for (; itf.More() && !Status && !isSameEdge; itf.Next()) {
2844 // Check merging conditions for the same face
2845 if (Faces1.Contains(itf.Value())) {
2846 Standard_Integer stat = IsMergedVertices(itf.Value(),e1,e2,v1,v2);
2847 if (stat == 1) isSameEdge = Standard_True;
2848 else Status = stat;
2849 }
2850 }
2851 }
2852 else if (Faces1.IsEmpty() && e1 == e2) {
2853 Standard_Integer stat = IsMergedVertices(TopoDS_Face(),e1,e1,v1,v2);
2854 if (stat == 1) isSameEdge = Standard_True;
2855 else Status = stat;
2856 break;
2857 }
2858 }
2859 }
2860 if (Status) continue;
2861 if (isSameEdge) listNodesSameEdge.Append(node2);
2862 // Append near node to the sequence
2863 gp_Pnt pt2 = BRep_Tool::Pnt(node2);
2864 Standard_Real dist = pt1.Distance(pt2);
2865 if (dist < Tolerance) {
2866 Standard_Boolean isIns = Standard_False;
2867 for (Standard_Integer kk = 1; kk <= SeqNodes.Length() && !isIns; kk++) {
2868 gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(SeqNodes.Value(kk)));
2869 if (dist < pt1.Distance(pt)) {
2870 SeqNodes.InsertBefore(kk,node2);
2871 isIns = Standard_True;
2872 }
2873 }
2874 if (!isIns) SeqNodes.Append(node2);
2875 }
2876 }
2877 if (SeqNodes.Length()) {
2878 // Remove nodes near to some other from the same edge
2879 if (listNodesSameEdge.Extent()) {
2880 TopTools_ListIteratorOfListOfShape lInt(listNodesSameEdge);
2881 for (; lInt.More(); lInt.Next()) {
2882 const TopoDS_Vertex& n2 = TopoDS::Vertex(lInt.Value());
2883 gp_Pnt p2 = BRep_Tool::Pnt(n2);
2884 for (Standard_Integer k = 1; k <= SeqNodes.Length(); ) {
2885 const TopoDS_Vertex& n1 = TopoDS::Vertex(SeqNodes.Value(k));
2886 if (n1 != n2) {
2887 gp_Pnt p1 = BRep_Tool::Pnt(n1);
2888 if (p2.Distance(p1) >= pt1.Distance(p1)) { k++; continue; }
2889 }
2890 SeqNodes.Remove(k);
2891 }
2892 }
2893 }
2894 // Bind nearest node if at least one exists
2895 if (SeqNodes.Length())
2896 NodeNearestNode.Add(node1,SeqNodes.First());
2897 }
82192477 2898 anInspector.ClearResList();
7fd59977 2899 }
2900
2901 // Create new nodes for chained nearest nodes
2902 if (NodeNearestNode.IsEmpty()) return Standard_False;
7fd59977 2903
2904 return CreateNewNodes(NodeNearestNode,NodeVertices,aVertexNode,aNodeEdges);
2905}
2906
92434a36 2907void BRepBuilderAPI_Sewing::VerticesAssembling(const Handle(Message_ProgressIndicator)& thePI)
7fd59977 2908{
2909 Standard_Integer nbVert = myVertexNode.Extent();
2910 Standard_Integer nbVertFree = myVertexNodeFree.Extent();
92434a36 2911 Message_ProgressSentry aPS (thePI, "Vertices assembling", 0, 2, 1);
7fd59977 2912 if (nbVert || nbVertFree) {
2913 // Fill map node -> sections
2914 Standard_Integer i;
2915 for (i = 1; i <= myBoundFaces.Extent(); i++) {
2916 TopoDS_Shape bound = myBoundFaces.FindKey(i);
2917 for (TopoDS_Iterator itv(bound,Standard_False); itv.More(); itv.Next()) {
2918 TopoDS_Shape node = itv.Value();
2919 if (myNodeSections.IsBound(node))
2920 myNodeSections(node).Append(bound);
2921 else {
2922 TopTools_ListOfShape lbnd;
2923 lbnd.Append(bound);
2924 myNodeSections.Bind(node,lbnd);
2925 }
2926 }
2927 }
2928 // Glue vertices
2929 if (nbVert) {
2930#ifdef DEB
2931 cout << "Assemble " << nbVert << " vertices on faces..." << endl;
2932#endif
92434a36 2933 while (GlueVertices(myVertexNode,myNodeSections,myBoundFaces,myTolerance, thePI));
7fd59977 2934 }
92434a36
A
2935 if (!aPS.More())
2936 return;
2937 aPS.Next();
7fd59977 2938 if (nbVertFree) {
2939#ifdef DEB
2940 cout << "Assemble " << nbVertFree << " vertices on floating edges..." << endl;
2941#endif
92434a36 2942 while (GlueVertices(myVertexNodeFree,myNodeSections,myBoundFaces,myTolerance, thePI));
7fd59977 2943 }
2944 }
2945}
2946
2947//=======================================================================
2948//function : replaceNMVertices
2949//purpose : internal use (static)
2950//=======================================================================
2951static void replaceNMVertices(const TopoDS_Edge& theEdge,
2952 const TopoDS_Vertex& theV1,
2953 const TopoDS_Vertex& theV2,
2954 const Handle(BRepTools_ReShape)& theReShape)
2955{
2956 //To keep NM vertices on edge
2957 TopTools_SequenceOfShape aSeqNMVert;
2958 TColStd_SequenceOfReal aSeqNMPars;
2959 Standard_Boolean hasNMVert = findNMVertices(theEdge,aSeqNMVert,aSeqNMPars);
2960 if(!hasNMVert)
2961 return;
2962 Standard_Real first, last;
2963 BRep_Tool::Range(theEdge, first, last);
2964 TopLoc_Location aLoc;
2965 Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,aLoc,first, last);
2966 if(c3d.IsNull())
2967 return;
2968 TopTools_SequenceOfShape aEdVert;
2969 TColStd_SequenceOfReal aEdParams;
2970 Standard_Integer i =1, nb = aSeqNMPars.Length();
2971
2972 for( ; i <= nb;i++) {
2973 Standard_Real apar = aSeqNMPars.Value(i);
2974 if(fabs(apar - first) <= Precision::PConfusion()) {
2975 theReShape->Replace(aSeqNMVert.Value(i),theV1);
2976 continue;
2977 }
2978 if(fabs(apar - last) <= Precision::PConfusion()) {
2979 theReShape->Replace(aSeqNMVert.Value(i),theV2);
2980 continue;
2981 }
2982 TopoDS_Shape aV = aSeqNMVert.Value(i);
2983 Standard_Integer j =1;
2984 for( ; j <= aEdParams.Length();j++) {
2985 Standard_Real apar2 = aEdParams.Value(j);
2986 if(fabs(apar - apar2) <= Precision::PConfusion()) {
2987 theReShape->Replace(aV,aEdVert.Value(j));
2988 break;
2989 }
2990 else if(apar < apar2) {
2991 TopoDS_Shape anewV = aV.EmptyCopied();
2992 aEdVert.InsertBefore(j,anewV);
2993 aEdParams.InsertBefore(j,apar);
2994 BRep_ListOfPointRepresentation& alistrep =
2995 (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints();
2996 Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
2997 alistrep.Append(aPRep);
2998 theReShape->Replace(aV,anewV);
2999 break;
3000 }
3001 }
3002 if (j > aEdParams.Length()) {
3003 TopoDS_Shape anewV = aV.EmptyCopied();
3004 aEdVert.Append(anewV);
3005 aEdParams.Append(apar);
3006 BRep_ListOfPointRepresentation& alistrep =
3007 (*((Handle(BRep_TVertex)*) &anewV.TShape()))->ChangePoints();
3008 Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc);
3009 alistrep.Append(aPRep);
3010 theReShape->Replace(aV,anewV);
3011 }
3012 }
3013
3014 Standard_Integer newnb = aEdParams.Length();
3015 if(newnb < nb) {
3016
3017 TopoDS_Shape anewEdge = theEdge.EmptyCopied();
3018 TopAbs_Orientation anOri = theEdge.Orientation();
3019 anewEdge.Orientation(TopAbs_FORWARD);
3020 BRep_Builder aB;
3021 aB.Add(anewEdge,theV1);
3022 aB.Add(anewEdge,theV2);
3023
3024 for( i =1; i <= aEdVert.Length();i++)
3025 aB.Add(anewEdge,aEdVert.Value(i));
3026 anewEdge.Orientation(anOri);
3027 theReShape->Replace(theEdge,anewEdge);
3028 }
3029
3030}
3031
3032//=======================================================================
3033//function : ReplaceEdge
3034//purpose : internal use (static)
3035//=======================================================================
3036
3037static void ReplaceEdge(const TopoDS_Shape& oldEdge,
3038 const TopoDS_Shape& theNewShape,
3039 const Handle(BRepTools_ReShape)& aReShape)
3040{
3041 TopoDS_Shape oldShape = aReShape->Apply(oldEdge);
3042 TopoDS_Shape newShape = aReShape->Apply(theNewShape);
3043 if (oldShape.IsSame(newShape)|| aReShape->IsRecorded(newShape)) return;
3044
3045
3046 aReShape->Replace(oldShape,newShape);
3047 TopoDS_Vertex V1old,V2old,V1new,V2new;
3048 TopExp::Vertices(TopoDS::Edge(oldShape),V1old,V2old);
3049 TopAbs_Orientation Orold = oldShape.Orientation();
3050 TopAbs_Orientation Ornew = Orold;
3051 if (newShape.ShapeType() == TopAbs_EDGE) {
3052 TopoDS_Edge aEn = TopoDS::Edge(newShape);
3053 TopExp::Vertices(aEn,V1new,V2new);
3054 Ornew = aEn.Orientation();
3055 replaceNMVertices(aEn,V1new,V2new,aReShape);
3056 }
3057 else if (newShape.ShapeType() == TopAbs_WIRE) {
3058 for (TopExp_Explorer aex(newShape,TopAbs_EDGE); aex.More(); aex.Next()) {
3059 TopoDS_Edge ed = TopoDS::Edge(aex.Current());
3060 Ornew = ed.Orientation();
3061 TopoDS_Vertex aV1,aV2;
3062 TopExp::Vertices(ed,aV1,aV2);
3063 replaceNMVertices(ed,aV1,aV2,aReShape);
3064 if (V1new.IsNull())
3065 V1new = aV1;
3066 V2new =aV2;
3067 }
3068 }
3069
3070 V1new.Orientation(V1old.Orientation());
3071 V2new.Orientation(V2old.Orientation());
3072 if (V1old.IsSame(V2old) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) {
3073 aReShape->Replace(V1old,V1new);
3074 return;
3075 }
3076 if (Orold == Ornew) {
3077 V1new.Orientation(V1old.Orientation());
3078 V2new.Orientation(V2old.Orientation());
3079 if (!V1old.IsSame(V1new) && !V1old.IsSame(V2new)&& !aReShape->IsRecorded(V1new))
3080 aReShape->Replace(V1old,V1new);
3081 if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3082 aReShape->Replace(V2old,V2new);
3083 }
3084 else {
3085 V1new.Orientation(V2old.Orientation());
3086 V2new.Orientation(V1old.Orientation());
3087 if (!V1old.IsSame(V2new) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V2new))
3088 aReShape->Replace(V1old,V2new);
3089 if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V1new))
3090 aReShape->Replace(V2old,V1new);
3091 }
3092}
3093
3094//=======================================================================
3095//function : Merging
3096//purpose : Modifies :
3097// myHasFreeBound
3098//
3099//=======================================================================
3100
92434a36
A
3101void BRepBuilderAPI_Sewing::Merging(const Standard_Boolean /* firstTime */,
3102 const Handle(Message_ProgressIndicator)& thePI)
7fd59977 3103{
3104 BRep_Builder B;
3105 // TopTools_MapOfShape MergedEdges;
92434a36
A
3106 Message_ProgressSentry aPS (thePI, "Merging bounds", 0, myBoundFaces.Extent(), 1);
3107 for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
7fd59977 3108
3109 TopoDS_Shape bound = myBoundFaces.FindKey(i);
3110
3111 // If bound was already merged - continue
3112 if (myMergedEdges.Contains(bound)) continue;
3113
3114 if (!myBoundFaces(i).Extent()) {
3115 // Merge free edge - only vertices
3116 TopoDS_Vertex no1, no2;
3117 TopExp::Vertices(TopoDS::Edge(bound),no1,no2);
3118 TopoDS_Shape nno1 = no1, nno2 = no2;
3119 if (myVertexNodeFree.Contains(no1))
3120 nno1 = myVertexNodeFree.FindFromKey(no1);
3121 if (myVertexNodeFree.Contains(no2))
3122 nno2 = myVertexNodeFree.FindFromKey(no2);
3123 if (!no1.IsSame(nno1)) {
3124 nno1.Orientation(no1.Orientation());
3125 myReShape->Replace(no1,nno1);
3126 }
3127 if (!no2.IsSame(nno2)) {
3128 nno2.Orientation(no2.Orientation());
3129 myReShape->Replace(no2,nno2);
3130 }
3131 myMergedEdges.Add(bound);
3132 continue;
3133 }
3134
3135 // Check for previous splitting, build replacing wire
3136 TopoDS_Wire BoundWire;
3137 Standard_Boolean isPrevSplit = Standard_False;
3138 Standard_Boolean hasCuttingSections = myBoundSections.IsBound(bound);
3139 if (hasCuttingSections) {
3140 B.MakeWire(BoundWire);
3141 BoundWire.Orientation(bound.Orientation());
3142 // Iterate on cutting sections
3143 TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3144 for (; its.More(); its.Next()) {
3145 TopoDS_Shape section = its.Value();
3146 B.Add(BoundWire,section);
3147 if (myMergedEdges.Contains(section)) isPrevSplit = Standard_True;
3148 }
3149 }
3150
3151 // Merge with bound
3152 TopTools_DataMapOfShapeShape MergedWithBound;
3153 if (!isPrevSplit) {
3154 // Obtain sequence of edges merged with bound
3155 TopTools_SequenceOfShape seqMergedWithBound;
3156 TColStd_SequenceOfInteger seqMergedWithBoundOri;
3157 if (MergedNearestEdges(bound,seqMergedWithBound,seqMergedWithBoundOri)) {
3158 // Store bound in the map
3159 MergedWithBound.Bind(bound,bound);
3160 // Iterate on edges merged with bound
3161 Standard_Integer ii = 1;
3162 while (ii <= seqMergedWithBound.Length()) {
3163 TopoDS_Shape iedge = seqMergedWithBound.Value(ii);
3164 // Remove edge if recorded as merged
3165 Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) ||
3166 MergedWithBound.IsBound(iedge));
3167 if (!isRejected) {
3168 if (myBoundSections.IsBound(iedge)) {
3169 // Edge is splitted - check sections
3170 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3171 for (; lit.More() && !isRejected; lit.Next()) {
3172 const TopoDS_Shape& sec = lit.Value();
3173 // Remove edge (bound) if at least one of its sections already merged
3174 isRejected = (myMergedEdges.Contains(sec) || MergedWithBound.IsBound(sec));
3175 }
3176 }
3177 if (!isRejected) {
3178 if (mySectionBound.IsBound(iedge)) {
3179 // Edge is a section - check bound
3180 const TopoDS_Shape& bnd = mySectionBound(iedge);
3181 // Remove edge (section) if its bound already merged
3182 isRejected = (myMergedEdges.Contains(bnd) || MergedWithBound.IsBound(bnd));
3183 }
3184 }
3185 }
3186 // To the next merged edge
3187 if (isRejected) {
3188 // Remove rejected edge
3189 seqMergedWithBound.Remove(ii);
3190 seqMergedWithBoundOri.Remove(ii);
3191 }
3192 else {
3193 // Process accepted edge
3194 MergedWithBound.Bind(iedge,iedge);
3195 ii++;
3196 }
3197 }
3198 Standard_Integer nbMerged = seqMergedWithBound.Length();
3199 if (nbMerged) {
3200 // Create same parameter edge
3201 TopTools_MapOfShape ActuallyMerged;
3202 TopoDS_Edge MergedEdge = SameParameterEdge(bound,seqMergedWithBound,
3203 seqMergedWithBoundOri,
3204 ActuallyMerged,myReShape);
3205 Standard_Boolean isForward = Standard_False;
3206 if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3207 // Process actually merged edges
3208 Standard_Integer nbActuallyMerged = 0;
3209 for (ii = 1; ii <= nbMerged; ii++) {
3210 TopoDS_Shape iedge = seqMergedWithBound(ii);
3211 if (ActuallyMerged.Contains(iedge)) {
3212 nbActuallyMerged++;
3213 // Record merged edge in the map
3214 TopAbs_Orientation orient = iedge.Orientation();
3215 if (!isForward) orient = TopAbs::Reverse(orient);
3216 if (!seqMergedWithBoundOri(ii)) orient = TopAbs::Reverse(orient);
3217 MergedWithBound.ChangeFind(iedge) = MergedEdge.Oriented(orient);
3218 }
3219 else MergedWithBound.UnBind(iedge);
3220 }
3221 if (nbActuallyMerged) {
3222 // Record merged bound in the map
3223 TopAbs_Orientation orient = bound.Orientation();
3224 if (!isForward) orient = TopAbs::Reverse(orient);
3225 MergedWithBound.ChangeFind(bound) = MergedEdge.Oriented(orient);
3226 }
3227 nbMerged = nbActuallyMerged;
3228 }
3229 // Remove bound from the map if not finally merged
3230 if (!nbMerged) MergedWithBound.UnBind(bound);
3231 }
3232 }
3233 Standard_Boolean isMerged = MergedWithBound.Extent();
3234
3235 // Merge with cutting sections
3236 Handle(BRepTools_ReShape) SectionsReShape = new BRepTools_ReShape;
3237 TopTools_DataMapOfShapeShape MergedWithSections;
3238 if (hasCuttingSections) {
3239 // Iterate on cutting sections
3240 TopTools_ListIteratorOfListOfShape its(myBoundSections(bound));
3241 for (; its.More(); its.Next()) {
3242 // Retrieve cutting section
3243 TopoDS_Shape section = its.Value();
3244 // Skip section if already merged
3245 if (myMergedEdges.Contains(section)) continue;
3246 // Merge cutting section
3247 TopTools_SequenceOfShape seqMergedWithSection;
3248 TColStd_SequenceOfInteger seqMergedWithSectionOri;
3249 if (MergedNearestEdges(section,seqMergedWithSection,seqMergedWithSectionOri)) {
3250 // Store section in the map
3251 MergedWithSections.Bind(section,section);
3252 // Iterate on edges merged with section
3253 Standard_Integer ii = 1;
3254 while (ii <= seqMergedWithSection.Length()) {
3255 TopoDS_Shape iedge = seqMergedWithSection.Value(ii);
3256 // Remove edge if recorded as merged
3257 Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || MergedWithSections.IsBound(iedge));
3258 if (!isRejected) {
3259 if (myBoundSections.IsBound(iedge)) {
3260 // Edge is splitted - check sections
3261 TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge));
3262 for (; lit.More() && !isRejected; lit.Next()) {
3263 const TopoDS_Shape& sec = lit.Value();
3264 // Remove edge (bound) if at least one of its sections already merged
3265 isRejected = (myMergedEdges.Contains(sec) || MergedWithSections.IsBound(sec));
3266 }
3267 }
3268 if (!isRejected) {
3269 if (mySectionBound.IsBound(iedge)) {
3270 // Edge is a section - check bound
3271 const TopoDS_Shape& bnd = mySectionBound(iedge);
3272 // Remove edge (section) if its bound already merged
3273 isRejected = (myMergedEdges.Contains(bnd) || MergedWithSections.IsBound(bnd));
3274 }
3275 }
3276 }
3277 // To the next merged edge
3278 if (isRejected) {
3279 // Remove rejected edge
3280 seqMergedWithSection.Remove(ii);
3281 seqMergedWithSectionOri.Remove(ii);
3282 }
3283 else {
3284 // Process accepted edge
3285 MergedWithSections.Bind(iedge,iedge);
3286 ii++;
3287 }
3288 }
3289 Standard_Integer nbMerged = seqMergedWithSection.Length();
3290 if (nbMerged) {
3291 // Create same parameter edge
3292 TopTools_MapOfShape ActuallyMerged;
3293 TopoDS_Edge MergedEdge = SameParameterEdge(section,seqMergedWithSection,
3294 seqMergedWithSectionOri,
3295 ActuallyMerged,SectionsReShape);
3296 Standard_Boolean isForward = Standard_False;
3297 if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD);
3298 // Process actually merged edges
3299 Standard_Integer nbActuallyMerged = 0;
3300 for (ii = 1; ii <= nbMerged; ii++) {
3301 TopoDS_Shape iedge = seqMergedWithSection(ii);
3302 if (ActuallyMerged.Contains(iedge)) {
3303 nbActuallyMerged++;
3304 // Record merged edge in the map
3305 TopAbs_Orientation orient = iedge.Orientation();
3306 if (!isForward) orient = TopAbs::Reverse(orient);
3307 if (!seqMergedWithSectionOri(ii)) orient = TopAbs::Reverse(orient);
3308 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3309 MergedWithSections.ChangeFind(iedge) = oedge;
3310 ReplaceEdge(myReShape->Apply(iedge),oedge,SectionsReShape);
3311 }
3312 else MergedWithSections.UnBind(iedge);
3313 }
3314 if (nbActuallyMerged) {
3315 // Record merged section in the map
3316 TopAbs_Orientation orient = section.Orientation();
3317 if (!isForward) orient = TopAbs::Reverse(orient);
3318 TopoDS_Shape oedge = MergedEdge.Oriented(orient);
3319 MergedWithSections.ChangeFind(section) = oedge;
3320 ReplaceEdge(myReShape->Apply(section),oedge,SectionsReShape);
3321 }
3322 nbMerged = nbActuallyMerged;
3323 }
3324 // Remove section from the map if not finally merged
3325 if (!nbMerged) MergedWithSections.UnBind(section);
3326 }
3327 else if (isMerged) {
3328 // Reject merging of sections
3329 MergedWithSections.Clear();
3330 break;
3331 }
3332 }
3333 }
3334 Standard_Boolean isMergedSplit = MergedWithSections.Extent();
3335
3336 if (!isMerged && !isMergedSplit) {
3337 // Nothing was merged in this iteration
3338 if (isPrevSplit) {
3339 // Replace previously splitted bound
3340 myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3341 }
3342 // else if (hasCuttingSections) {
3343 // myBoundSections.UnBind(bound); //szv: are you sure ???
3344 // }
3345 continue;
3346 }
3347
3348 // Set splitting flag
3349 Standard_Boolean isSplitted = ((!isMerged && isMergedSplit) || isPrevSplit);
3350
3351 // Choose between bound and sections merging
3352 if (isMerged && isMergedSplit && !isPrevSplit) {
3353 // Fill map of merged cutting sections
3354 TopTools_MapOfShape MapSplitEdges;
3355 TopTools_DataMapIteratorOfDataMapOfShapeShape itm;
3356 for (itm.Initialize(MergedWithSections); itm.More(); itm.Next()) {
3357 TopoDS_Shape edge = itm.Key();
3358 MapSplitEdges.Add(edge);
3359 }
3360 // Iterate on edges merged with bound
3361 for (itm.Initialize(MergedWithBound); itm.More(); itm.Next()) {
3362 // Retrieve edge merged with bound
3363 TopoDS_Shape edge = itm.Key();
3364 // Remove edge from the map
3365 if (MapSplitEdges.Contains(edge)) MapSplitEdges.Remove(edge);
3366 if (myBoundSections.IsBound(edge)) {
3367 // Edge has cutting sections
3368 TopTools_ListIteratorOfListOfShape its(myBoundSections(edge));
3369 for (; its.More(); its.Next()) {
3370 TopoDS_Shape sec = its.Value();
3371 // Remove section from the map
3372 if (MapSplitEdges.Contains(sec)) MapSplitEdges.Remove(sec);
3373 }
3374 }
3375 }
3376 // Calculate section merging tolerance
3377 Standard_Real MinSplitTol = RealLast();
3378 TopTools_MapIteratorOfMapOfShape im(MapSplitEdges);
3379 for (; im.More(); im.Next()) {
3380 TopoDS_Edge edge = TopoDS::Edge(MergedWithSections(im.Key()));
3381 MinSplitTol = Min(MinSplitTol,BRep_Tool::Tolerance(edge));
3382 }
3383 // Calculate bound merging tolerance
3384 TopoDS_Edge BoundEdge = TopoDS::Edge(MergedWithBound(bound));
3385 Standard_Real BoundEdgeTol = BRep_Tool::Tolerance(BoundEdge);
3386 isSplitted = ((MinSplitTol < BoundEdgeTol+MinTolerance()) || myNonmanifold);
3387 isSplitted = (!MapSplitEdges.IsEmpty() && isSplitted);
3388 }
3389
3390 if (isSplitted) {
3391 // Merging of cutting sections
3392 //myMergedEdges.Add(bound);
3393 myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire));
3394 TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithSections);
3395 for (; itm.More(); itm.Next()) {
3396 TopoDS_Shape oldedge = itm.Key();
3397 TopoDS_Shape newedge = SectionsReShape->Apply(itm.Value());
3398 ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3399 myMergedEdges.Add(oldedge);
3400 if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3401
3402 }
3403 }
3404 else {
3405 // Merging of initial bound
3406 TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithBound);
3407 //myMergedEdges.Add(bound);
3408 for (; itm.More(); itm.Next()) {
3409 TopoDS_Shape oldedge = itm.Key();
3410 TopoDS_Shape newedge = itm.Value();
3411 ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape);
3412 myMergedEdges.Add(oldedge);
3413 if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge);
3414 }
3415 if (myBoundSections.IsBound(bound)) myBoundSections.UnBind(bound);
3416 if(!myMergedEdges.Contains(bound))
3417 myMergedEdges.Add(bound);
3418 }
3419 }
3420
3421 myNbVertices = myVertexNode.Extent() + myVertexNodeFree.Extent();
3422 myNodeSections.Clear();
3423 myVertexNode.Clear();
3424 myVertexNodeFree.Clear();
3425 myCuttingNode.Clear();
3426}
3427
3428//=======================================================================
3429//function : MergedNearestEdges
3430//purpose :
3431//=======================================================================
3432
3433Standard_Boolean BRepBuilderAPI_Sewing::MergedNearestEdges(const TopoDS_Shape& edge,
3434 TopTools_SequenceOfShape& SeqMergedEdge,
3435 TColStd_SequenceOfInteger& SeqMergedOri)
3436{
3437 // Retrieve edge nodes
3438 TopoDS_Vertex no1, no2;
3439 TopExp::Vertices(TopoDS::Edge(edge),no1,no2);
3440 TopoDS_Shape nno1 = no1, nno2 = no2;
3441 Standard_Boolean isNode1 = myVertexNode.Contains(no1);
3442 Standard_Boolean isNode2 = myVertexNode.Contains(no2);
3443 if (isNode1) nno1 = myVertexNode.FindFromKey(no1);
3444 if (isNode2) nno2 = myVertexNode.FindFromKey(no2);
3445
3446 // Fill map of nodes connected to the node #1
3447 TopTools_MapOfShape mapVert1;
3448 mapVert1.Add(nno1);
3449 if (myCuttingNode.IsBound(nno1)) {
3450 TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno1));
3451 for (; ilv.More(); ilv.Next()) {
3452 TopoDS_Shape v1 = ilv.Value();
3453 mapVert1.Add(v1);
3454 if (!isNode1 && myCuttingNode.IsBound(v1)) {
3455 TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3456 for (; ilvn.More(); ilvn.Next()) {
3457 TopoDS_Shape vn = ilvn.Value();
3458 mapVert1.Add(vn);
3459 }
3460 }
3461 }
3462 }
3463
3464 // Fill map of nodes connected to the node #2
3465 TopTools_MapOfShape mapVert2;
3466 mapVert2.Add(nno2);
3467 if (myCuttingNode.IsBound(nno2)) {
3468 TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno2));
3469 for (; ilv.More(); ilv.Next()) {
3470 TopoDS_Shape v1 = ilv.Value();
3471 mapVert2.Add(v1);
3472 if (!isNode2 && myCuttingNode.IsBound(v1)) {
3473 TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1));
3474 for (; ilvn.More(); ilvn.Next()) {
3475 TopoDS_Shape vn = ilvn.Value();
3476 mapVert2.Add(vn);
3477 }
3478 }
3479 }
3480 }
3481
3482 // Find all possible contigous edges
3483 TopTools_SequenceOfShape seqEdges;
3484 seqEdges.Append(edge);
3485 TopTools_MapOfShape mapEdges;
3486 mapEdges.Add(edge);
3487 for (TopTools_MapIteratorOfMapOfShape imv1(mapVert1); imv1.More(); imv1.Next()) {
3488 TopoDS_Shape node1 = imv1.Key();
3489 if (!myNodeSections.IsBound(node1)) continue;
3490 TopTools_ListIteratorOfListOfShape ilsec(myNodeSections(node1));
3491 for (; ilsec.More(); ilsec.Next()) {
3492 TopoDS_Shape sec = ilsec.Value();
3493 if (sec.IsSame(edge)) continue;
3494 // Retrieve section nodes
3495 TopoDS_Vertex vs1, vs2;
3496 TopExp::Vertices(TopoDS::Edge(sec),vs1,vs2);
3497 TopoDS_Shape vs1n = vs1, vs2n = vs2;
3498 if (myVertexNode.Contains(vs1)) vs1n = myVertexNode.FindFromKey(vs1);
3499 if (myVertexNode.Contains(vs2)) vs2n = myVertexNode.FindFromKey(vs2);
3500 if ((mapVert1.Contains(vs1n) && mapVert2.Contains(vs2n)) ||
3501 (mapVert1.Contains(vs2n) && mapVert2.Contains(vs1n)))
3502 if (mapEdges.Add(sec)) {
3503 // Check for rejected cutting
3504 Standard_Boolean isRejected = myMergedEdges.Contains(sec);
3505 if(!isRejected && myBoundSections.IsBound(sec))
3506 {
3507 TopTools_ListIteratorOfListOfShape its(myBoundSections(sec));
3508 for (; its.More() && !isRejected; its.Next()) {
3509 TopoDS_Shape section = its.Value();
3510
3511 if (myMergedEdges.Contains(section))
3512 isRejected = Standard_True;
3513 }
3514 }
3515 if( !isRejected && mySectionBound.IsBound(sec)) {
3516 const TopoDS_Shape& bnd = mySectionBound(sec);
3517 isRejected = (!myBoundSections.IsBound(bnd) ||
3518 myMergedEdges.Contains(bnd));
3519 }
3520
3521 if (!isRejected) seqEdges.Append(sec);
3522 }
3523 }
3524 }
3525
3526 mapEdges.Clear();
3527
3528 Standard_Boolean success = Standard_False;
3529
3530 Standard_Integer nbSection = seqEdges.Length();
3531 if (nbSection > 1) {
3532 // Find the longest edge CCI60011
3533 Standard_Integer i, indRef = 1;
3534 if (myNonmanifold) {
3535 Standard_Real lenRef = 0.;
3536 for (i = 1; i <= nbSection; i++) {
3537 Standard_Real f, l;
3538 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(seqEdges(i)), f, l);
3539 GeomAdaptor_Curve cAdapt(c3d);
3540 Standard_Real len = GCPnts_AbscissaPoint::Length(cAdapt, f, l);
3541 if (len > lenRef) { indRef = i; lenRef = len; }
3542 }
3543 if (indRef != 1) {
3544 TopoDS_Shape longEdge = seqEdges(indRef);
3545 seqEdges(indRef) = seqEdges(1);
3546 seqEdges(1) = longEdge;
3547 }
3548 }
3549
3550 // Find merging candidates
3551 TColStd_SequenceOfInteger seqForward;
3552 TColStd_SequenceOfInteger seqCandidates;
3553 TColStd_IndexedMapOfInteger mapReference;
3554 mapReference.Add(1); // Add index of reference section
3555 if (FindCandidates(seqEdges,mapReference,seqCandidates,seqForward)) {
3556 Standard_Integer nbCandidates = seqCandidates.Length();
3557 // Check if reference section is merged reversed
3558 Standard_Boolean toReverse = Standard_False;
3559 if (indRef != 1) {
3560 // Find reference edge in candidates
3561 Standard_Boolean isFound = Standard_False;
3562 for (i = 1; i <= nbCandidates && !isFound; i++) {
3563 isFound = (seqCandidates(i) == indRef);
3564 if (isFound) {
3565 // Record orientation
3566 toReverse = !seqForward(i);
3567 // Restore first edge
3568 seqCandidates(i) = 1;
3569 seqForward(i) = 1;
3570 }
3571 }
3572 // Fail if reference is not in candidates
3573 if (!isFound) return Standard_False;
3574 }
3575 // Record candidate sections
3576 for (i = 1; i <= nbCandidates; i++) {
3577 // Retrieve merged edge
3578 TopoDS_Shape iedge = seqEdges(seqCandidates(i));
3579 Standard_Integer ori =
3580 ((seqForward(i) && toReverse) || (!seqForward(i) && !toReverse))? 0 : 1;
3581 SeqMergedEdge.Append(iedge);
3582 SeqMergedOri.Append(ori);
3583 if (!myNonmanifold) break;
3584 }
3585 success = nbCandidates;
3586 }
3587 }
3588
3589 return success;
3590}
3591
3592//=======================================================================
3593//function : Cutting
3594//purpose : Modifies :
3595// myBoundSections
3596// myNodeSections
3597// myCuttingNode
3598//=======================================================================
3599
92434a36 3600void BRepBuilderAPI_Sewing::Cutting(const Handle(Message_ProgressIndicator)& thePI)
7fd59977 3601{
3602 Standard_Integer i, nbVertices = myVertexNode.Extent();
3603 if (!nbVertices) return;
82192477 3604 // Create a box tree with vertices
7fd59977 3605 Standard_Real eps = myTolerance*0.5;
82192477 3606 BRepBuilderAPI_BndBoxTree aTree;
3607 NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller (aTree);
3608 BRepBuilderAPI_BndBoxTreeSelector aSelector;
7fd59977 3609 for (i = 1; i <= nbVertices; i++) {
3610 gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(myVertexNode.FindKey(i)));
3611 Bnd_Box aBox;
3612 aBox.Set(pt);
3613 aBox.Enlarge(eps);
82192477 3614 aTreeFiller.Add (i, aBox);
7fd59977 3615 }
82192477 3616 aTreeFiller.Fill();
3617
7fd59977 3618 Handle(Geom_Curve) c3d;
3619 TopLoc_Location loc;
3620 Standard_Real first, last;
3621 // Iterate on all boundaries
3622 Standard_Integer nbBounds = myBoundFaces.Extent();
92434a36
A
3623 Message_ProgressSentry aPS (thePI, "Cutting bounds", 0, nbBounds, 1);
3624 for (i = 1; i <= nbBounds && aPS.More(); i++, aPS.Next()) {
7fd59977 3625 const TopoDS_Edge& bound = TopoDS::Edge(myBoundFaces.FindKey(i));
3626 // Do not cut floating edges
3627 if (!myBoundFaces(i).Extent()) continue;
3628 // Create cutting sections
3629 TopTools_ListOfShape listSections;
3630 { //szv: Use brackets to destroy local variables
3631 // Obtain bound curve
3632 c3d = BRep_Tool::Curve(bound, loc, first, last);
3633 if (!loc.IsIdentity()) {
3634 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3635 c3d->Transform(loc.Transformation());
3636 }
3637 // Obtain candidate vertices
3638 TopoDS_Vertex V1, V2;
3639 TopTools_IndexedMapOfShape CandidateVertices;
3640 { //szv: Use brackets to destroy local variables
3641 // Create bounding box around curve
3642 Bnd_Box aGlobalBox;
3643 GeomAdaptor_Curve adptC(c3d,first,last);
3644 BndLib_Add3dCurve::Add(adptC,myTolerance,aGlobalBox);
3645 // Sort vertices to find candidates
82192477 3646 aSelector.SetCurrent (aGlobalBox);
3647 aTree.Select (aSelector);
7fd59977 3648 // Skip bound if no node is in the boundind box
82192477 3649 if (!aSelector.ResInd().Extent()) continue;
7fd59977 3650 // Retrieve bound nodes
3651 TopExp::Vertices(bound,V1,V2);
3652 const TopoDS_Shape& Node1 = myVertexNode.FindFromKey(V1);
3653 const TopoDS_Shape& Node2 = myVertexNode.FindFromKey(V2);
3654 // Fill map of candidate vertices
82192477 3655 TColStd_ListIteratorOfListOfInteger itl(aSelector.ResInd());
7fd59977 3656 for (; itl.More(); itl.Next()) {
3657 const Standard_Integer index = itl.Value();
3658 const TopoDS_Shape& Node = myVertexNode.FindFromIndex(index);
3659 if (!Node.IsSame(Node1) && !Node.IsSame(Node2)) {
3660 TopoDS_Shape vertex = myVertexNode.FindKey(index);
3661 CandidateVertices.Add(vertex);
3662 }
3663 }
82192477 3664 aSelector.ClearResList();
7fd59977 3665 }
3666 Standard_Integer nbCandidates = CandidateVertices.Extent();
3667 if (!nbCandidates) continue;
3668 // Project vertices on curve
3669 TColStd_Array1OfReal arrPara(1,nbCandidates), arrDist(1,nbCandidates);
3670 TColgp_Array1OfPnt arrPnt(1,nbCandidates), arrProj(1,nbCandidates);
3671 for (Standard_Integer j = 1; j <= nbCandidates; j++)
3672 arrPnt(j) = BRep_Tool::Pnt(TopoDS::Vertex(CandidateVertices(j)));
2028d00c 3673 ProjectPointsOnCurve(arrPnt,c3d,first,last,arrDist,arrPara,arrProj,Standard_True);
7fd59977 3674 // Create cutting nodes
3675 TopTools_SequenceOfShape seqNode;
3676 TColStd_SequenceOfReal seqPara;
3677 CreateCuttingNodes(CandidateVertices,bound,
3678 V1,V2,arrDist,arrPara,arrProj,seqNode,seqPara);
3679 if (!seqPara.Length()) continue;
3680 // Create cutting sections
3681 CreateSections(bound, seqNode, seqPara, listSections);
3682 }
3683 if (listSections.Extent() > 1) {
3684 // modification of maps:
3685 // myBoundSections
3686 TopTools_ListIteratorOfListOfShape its(listSections);
3687 for (; its.More(); its.Next()) {
3688 TopoDS_Shape section = its.Value();
3689 // Iterate on section vertices
3690 for (TopoDS_Iterator itv(section); itv.More(); itv.Next()) {
3691 TopoDS_Shape vertex = itv.Value();
3692 // Convert vertex to node
3693 if (myVertexNode.Contains(vertex))
3694 vertex = TopoDS::Vertex(myVertexNode.FindFromKey(vertex));
3695 // Update node sections
3696 if (myNodeSections.IsBound(vertex))
3697 myNodeSections.ChangeFind(vertex).Append(section);
3698 else {
3699 TopTools_ListOfShape lsec;
3700 lsec.Append(section);
3701 myNodeSections.Bind(vertex,lsec);
3702 }
3703 }
3704 // Store bound for section
3705 mySectionBound.Bind(section,bound);
3706 }
3707 // Store splitted bound
3708 myBoundSections.Bind(bound,listSections);
3709 }
3710 }
3711#ifdef DEB
3712 cout << "From " << nbBounds << " bounds " << myBoundSections.Extent()
3713 << " were cut into " << mySectionBound.Extent() << " sections" << endl;
3714#endif
3715}
3716
3717//=======================================================================
3718//function : GetSeqEdges
3719//purpose :
3720//=======================================================================
3721
3722static void GetSeqEdges(const TopoDS_Shape& edge,
3723 TopTools_SequenceOfShape& seqEdges,
3724 TopTools_DataMapOfShapeListOfShape& VertEdge)
3725{
3726 Standard_Integer numV = 0;
3727 for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3728 TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3729 numV++;
3730 if (VertEdge.IsBound(V1)) {
3731 const TopTools_ListOfShape& listEdges = VertEdge.Find(V1);
3732 for (TopTools_ListIteratorOfListOfShape lIt(listEdges); lIt.More(); lIt.Next()) {
3733 TopoDS_Shape edge1 = lIt.Value();
3734 if (edge1.IsSame(edge)) continue;
3735 Standard_Boolean isContained = Standard_False;
3736 Standard_Integer i, index = 1;
3737 for (i = 1; i <= seqEdges.Length() && !isContained; i++) {
3738 isContained = seqEdges.Value(i).IsSame(edge1);
3739 if (!isContained && seqEdges.Value(i).IsSame(edge)) index = i;
3740 }
3741 if (!isContained) {
3742 if (numV == 1) seqEdges.InsertBefore(index,edge1);
3743 else seqEdges.InsertAfter(index,edge1);
3744 GetSeqEdges(edge1,seqEdges,VertEdge);
3745 }
3746 }
3747 }
3748 }
3749}
3750
3751//=======================================================================
3752//function : GetFreeWires
3753//purpose :
3754//=======================================================================
3755
3756void BRepBuilderAPI_Sewing::GetFreeWires(TopTools_MapOfShape& MapFreeEdges, TopTools_SequenceOfShape& seqWires)
3757{
3758 TopTools_DataMapOfShapeListOfShape VertEdge;
3759 TopTools_MapIteratorOfMapOfShape itMap(MapFreeEdges);
3760 TopTools_SequenceOfShape seqFreeEdges;
3761 for (; itMap.More(); itMap.Next()) {
3762 TopoDS_Shape edge = itMap.Key();
3763 seqFreeEdges.Append(edge);
3764 for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) {
3765 TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value());
3766 if (VertEdge.IsBound(V1))
3767 VertEdge.ChangeFind(V1).Append(edge);
3768 else {
3769 TopTools_ListOfShape ls;
3770 ls.Append(edge);
3771 VertEdge.Bind(V1,ls);
3772 }
3773 }
3774 }
3775 BRep_Builder B;
3776 Standard_Integer i, j;
3777 for (i = 1; i <= seqFreeEdges.Length(); i++) {
3778 TopTools_SequenceOfShape seqEdges;
3779 TopoDS_Shape edge = seqFreeEdges.Value(i);
3780 if (!MapFreeEdges.Contains(edge)) continue;
3781 seqEdges.Append(edge);
3782 GetSeqEdges(edge,seqEdges,VertEdge);
3783 TopoDS_Wire wire;
3784 B.MakeWire(wire);
3785 for (j = 1; j <= seqEdges.Length(); j++) {
3786 B.Add(wire,seqEdges.Value(j));
3787 MapFreeEdges.Remove(seqEdges.Value(j));
3788 }
3789 seqWires.Append(wire);
3790 if (MapFreeEdges.IsEmpty()) break;
3791 }
3792}
3793
3794//=======================================================================
3795//function : IsDegeneratedWire
3796//purpose : internal use
3797//=======================================================================
3798
3799static Standard_Boolean IsDegeneratedWire(const TopoDS_Shape& wire)
3800{
3801 if (wire.ShapeType() != TopAbs_WIRE) return Standard_False;
3802 // Get maximal vertices tolerance
3803 TopoDS_Vertex V1,V2;
3804 //TopExp::Vertices(TopoDS::Wire(wire),V1,V2);
3805 //Standard_Real tol = Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3806 Standard_Real wireLength = 0.0;
3807 TopLoc_Location loc;
3808 Standard_Real first, last;
3809 Standard_Integer nume = 0;
3810 Standard_Integer isSmall = 0;
3811 for (TopoDS_Iterator aIt(wire,Standard_False); aIt.More(); aIt.Next()) {
3812 nume++;
3813 TopoDS_Shape edge = aIt.Value();
3814 TopoDS_Vertex Ve1,Ve2;
3815 TopExp::Vertices(TopoDS::Edge(edge),Ve1,Ve2);
3816 if(nume == 1) {
3817 V1 = Ve1;
3818 V2 = Ve2;
3819 }
3820 else {
3821 if(Ve1.IsSame(V1))
3822 V1 = Ve2;
3823 else if(Ve1.IsSame(V2))
3824 V2 = Ve2;
3825 if(Ve2.IsSame(V1))
3826 V1 = Ve1;
3827 else if(Ve2.IsSame(V2))
3828 V2 = Ve1;
3829 }
3830 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aIt.Value()),loc,first,last);
3831 if (!c3d.IsNull()) {
3832 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3833 if (!loc.IsIdentity()) {
3834 //c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3835 c3d->Transform(loc.Transformation());
3836 }
3837 gp_Pnt pfirst = c3d->Value(first);
3838 gp_Pnt plast = c3d->Value(last);
3839 gp_Pnt pmid = c3d->Value((first +last)*0.5);
3840 Standard_Real length =0;
3841 if(pfirst.Distance(plast) > pfirst.Distance(pmid)) {
3842 length = pfirst.Distance(plast);
3843 }
3844 else {
3845 GeomAdaptor_Curve cAdapt(c3d);
3846 length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3847 }
3848 Standard_Real tole = BRep_Tool::Tolerance(Ve1)+BRep_Tool::Tolerance(Ve2);
3849 if(length <= tole) isSmall++;
3850 wireLength += length;
3851 }
3852 }
3853 if(isSmall == nume) return Standard_True;
3854 Standard_Real tol = BRep_Tool::Tolerance(V1)+BRep_Tool::Tolerance(V2);//Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
3855 if (wireLength > tol) return Standard_False;
3856 return Standard_True;
3857}
3858
3859//=======================================================================
3860//function : DegeneratedSection
3861//purpose : internal use
3862// create a new degenerated edge if the section is degenerated
3863//=======================================================================
3864
3865static TopoDS_Edge DegeneratedSection(const TopoDS_Shape& section, const TopoDS_Shape& face)
3866{
3867 // Return if section is already degenerated
3868 if (BRep_Tool::Degenerated(TopoDS::Edge(section))) return TopoDS::Edge(section);
3869
3870 // Retrieve edge curve
3871 TopLoc_Location loc;
3872 Standard_Real first, last;
3873 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(section), loc, first, last);
3874 if (c3d.IsNull()) { //gka
3875 BRep_Builder aB;
3876 TopoDS_Edge edge1 = TopoDS::Edge(section);
3877 aB.Degenerated(edge1, Standard_True);
3878 return edge1;
3879 }
3880 if (!loc.IsIdentity()) {
3881 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
3882 c3d->Transform(loc.Transformation());
3883 }
3884
3885 // Test if the new edge is degenerated
3886 TopoDS_Vertex v1,v2;
3887 TopExp::Vertices(TopoDS::Edge(section),v1,v2);
3888 //Standard_Real tol = Max(BRep_Tool::Tolerance(v1),BRep_Tool::Tolerance(v2));
3889 //tol = Max(tolerance,tol);
3890
3891 gp_Pnt p1, p2, p3;
3892 p1 = BRep_Tool::Pnt(v1);
3893 p3 = BRep_Tool::Pnt(v2);
3894 c3d->D0(0.5*(first + last),p2);
3895
3896 //Standard_Boolean isDegenerated = Standard_False;
3897 //if (p1.Distance(p3) < tol) {
3898 //GeomAdaptor_Curve cAdapt(c3d);
3899 //Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last);
3900 //isDegenerated = Standard_True; //(length < tol);
3901 //}
3902
3903 TopoDS_Edge edge;
3904 //if (!isDegenerated) return edge;
3905
3906 // processing
3907 BRep_Builder aBuilder;
3908 edge = TopoDS::Edge(section);
3909 edge.EmptyCopy();
3910 if (v1.IsSame(v2)) {
3911 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3912 aBuilder.Add(anEdge, v1.Oriented(TopAbs_FORWARD));
3913 aBuilder.Add(anEdge, v2.Oriented(TopAbs_REVERSED));
3914 }
3915 else {
3916 TopoDS_Vertex newVertex;
3917 if (p1.Distance(p3) < BRep_Tool::Tolerance(v1))
3918 newVertex = v1;
3919 else if (p1.Distance(p3) < BRep_Tool::Tolerance(v2))
3920 newVertex = v2;
3921 else {
3922 Standard_Real d1 = BRep_Tool::Tolerance(v1) + p2.Distance(p1);
3923 Standard_Real d2 = BRep_Tool::Tolerance(v2) + p2.Distance(p3);
3924 Standard_Real newTolerance = Max(d1,d2);
3925 aBuilder.MakeVertex(newVertex, p2, newTolerance);
3926 }
3927 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3928 aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_FORWARD));
3929 aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_REVERSED));
3930 }
3931
3932 BRep_Tool::Range(TopoDS::Edge(section), first, last);
3933 TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD);
3934 aBuilder.Range(TopoDS::Edge(anEdge), first, last);
3935 aBuilder.Degenerated(edge, Standard_True);
3936 Handle(Geom_Curve) aC3dNew;
3937 if (!face.IsNull()) {
3938 Standard_Real af,al;
3939 Handle(Geom2d_Curve) aC2dt = BRep_Tool::CurveOnSurface(TopoDS::Edge(section),TopoDS::Face(face),af,al);
3940 aBuilder.UpdateEdge(edge,aC3dNew,0);
3941 Handle(Geom2d_Curve) aC2dn = BRep_Tool::CurveOnSurface(edge,TopoDS::Face(face),af,al);
3942 if (aC2dn.IsNull())
3943 aBuilder.UpdateEdge(edge,aC2dt,TopoDS::Face(face),0);
3944 }
3945
3946 return edge;
3947}
3948
3949//=======================================================================
3950//function : EdgeProcessing
3951//purpose : modifies :
3952// myNbEdges
3953// myHasMultipleEdge
3954// myHasFreeBound
3955// . if multiple edge
3956// - length < 100.*myTolerance -> several free edge
3957// . if no multiple edge
3958// - make the contigous edges sameparameter
3959//=======================================================================
3960
92434a36 3961void BRepBuilderAPI_Sewing::EdgeProcessing(const Handle(Message_ProgressIndicator)& thePI)
7fd59977 3962{
3963 // constructs sectionEdge
3964 TopTools_MapOfShape MapFreeEdges;
3965 TopTools_DataMapOfShapeShape EdgeFace;
92434a36
A
3966 Message_ProgressSentry aPS (thePI, "Edge processing", 0, myBoundFaces.Extent(), 1);
3967 for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) {
7fd59977 3968 const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
3969 const TopTools_ListOfShape& listFaces = myBoundFaces(i);
3970 if (listFaces.Extent() == 1) {
3971 if (myBoundSections.IsBound(bound)) {
3972 TopTools_ListIteratorOfListOfShape liter(myBoundSections(bound));
3973 for (; liter.More(); liter.Next()) {
3974 if (!myMergedEdges.Contains(liter.Value())) { //myReShape->IsRecorded(liter.Value())) {
3975 TopoDS_Shape edge = myReShape->Apply(liter.Value());
3976 if (!MapFreeEdges.Contains(edge)) {
3977 TopoDS_Shape face = listFaces.First();
3978 EdgeFace.Bind(edge,face);
3979 MapFreeEdges.Add(edge);
3980 }
3981 }
3982 }
3983 }
3984 else {
3985 if (!myMergedEdges.Contains(bound)) {
3986 TopoDS_Shape edge = myReShape->Apply(bound);
3987 if (!MapFreeEdges.Contains(edge)) {
3988 TopoDS_Shape face = listFaces.First();
3989 EdgeFace.Bind(edge,face);
3990 MapFreeEdges.Add(edge);
3991 }
3992 }
3993 }
3994 }
3995 }
3996
3997 if (!MapFreeEdges.IsEmpty()) {
3998 TopTools_SequenceOfShape seqWires;
3999 GetFreeWires(MapFreeEdges,seqWires);
4000 for (Standard_Integer j = 1; j <= seqWires.Length(); j++) {
4001 TopoDS_Wire wire = TopoDS::Wire(seqWires.Value(j));
4002 if (!IsDegeneratedWire(wire)) continue;
4003 for (TopoDS_Iterator Ie(wire,Standard_False); Ie.More(); Ie.Next()) {
4004 TopoDS_Shape aTmpShape = myReShape->Apply(Ie.Value()); //for porting
4005 TopoDS_Edge edge = TopoDS::Edge(aTmpShape);
4006 TopoDS_Shape face;
4007 if (EdgeFace.IsBound(edge))
4008 face = EdgeFace.Find(edge);
4009 TopoDS_Shape degedge = DegeneratedSection(edge,face);
4010 if (degedge.IsNull()) continue;
4011 if (!degedge.IsSame(edge))
4012 ReplaceEdge(edge,degedge,myReShape);
4013 if (BRep_Tool::Degenerated(TopoDS::Edge(degedge)))
4014 myDegenerated.Add(degedge);
4015 }
4016 }
4017 }
4018 myMergedEdges.Clear();
4019}
4020
4021//=======================================================================
4022//function : CreateSewedShape
4023//purpose :
4024//=======================================================================
4025
4026void BRepBuilderAPI_Sewing::CreateSewedShape()
4027{
4028 // ---------------------
4029 // create the new shapes
4030 // ---------------------
4031 BRepTools_Quilt aQuilt;
4032 Standard_Boolean isLocal = !myShape.IsNull();
4033 if (isLocal) {
4034 // Local sewing
4035 TopoDS_Shape ns = myReShape->Apply(myShape);
4036 aQuilt.Add(ns);
4037 }
4038 Standard_Integer i;
4039 for (i = 1; i <= myOldShapes.Extent(); i++) {
4040 TopoDS_Shape sh = myOldShapes(i);
4041 if (!sh.IsNull()) {
4042 sh = myReShape->Apply(sh);
4043 myOldShapes(i) = sh;
4044 if (!isLocal) aQuilt.Add(sh);
4045 }
4046 }
4047 TopoDS_Shape aNewShape = aQuilt.Shells();
4048 Standard_Integer numsh = 0;
4049
4050 TopTools_IndexedMapOfShape OldShells;
4051
4052 BRep_Builder aB;
4053 TopoDS_Compound aComp;
4054 aB.MakeCompound(aComp);
4055 for (TopoDS_Iterator aExpSh(aNewShape,Standard_False); aExpSh.More(); aExpSh.Next()) {
4056 TopoDS_Shape sh = aExpSh.Value();
4057 Standard_Boolean hasEdges = Standard_False;
4058 if (sh.ShapeType() == TopAbs_SHELL) {
4059 if (myNonmanifold)
4060 hasEdges = !OldShells.Contains(sh);
4061 else {
4062 TopoDS_Shape face;
4063 Standard_Integer numf = 0;
4064 for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
4065 face = aExpF.Current();
4066 numf++;
4067 }
4068 if (numf == 1) aB.Add(aComp,face);
4069 else if (numf > 1) aB.Add(aComp,sh);
4070 if (numf) numsh++;
4071 }
4072 }
4073 else if (sh.ShapeType() == TopAbs_FACE) {
4074 if (myNonmanifold) {
4075 TopoDS_Shell ss;
4076 aB.MakeShell(ss);
4077 aB.Add(ss,sh);
4078 sh = ss;
4079 hasEdges = Standard_True;
4080 }
4081 else { aB.Add(aComp,sh); numsh++; }
4082 }
4083 else { aB.Add(aComp,sh); numsh++; }
4084 if (hasEdges) OldShells.Add(sh);
4085 }
4086 // Process collected shells
4087 if (myNonmanifold) {
4088 Standard_Integer nbOldShells = OldShells.Extent();
4089 if (nbOldShells == 1) {
4090 // Single shell - check for single face
4091 TopoDS_Shape sh = OldShells.FindKey(1);
4092 TopoDS_Shape face;
4093 Standard_Integer numf = 0;
4094 for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) {
4095 face = aExpF.Current();
4096 numf++;
4097 }
4098 if (numf == 1) aB.Add(aComp,face);
4099 else if (numf > 1) aB.Add(aComp,sh);
4100 if (numf) numsh++;
4101 }
4102 else if (nbOldShells) {
4103 // Several shells should be merged
4104 TColStd_MapOfInteger IndexMerged;
4105 while (IndexMerged.Extent() < nbOldShells) {
4106 TopoDS_Shell NewShell;
4107 TopTools_MapOfShape NewEdges;
4108 for (i = 1; i <= nbOldShells; i++) {
4109 if (IndexMerged.Contains(i)) continue;
4110 TopoDS_Shell shell = TopoDS::Shell(OldShells.FindKey(i));
4111 if (NewShell.IsNull()) {
4112 BRep_Builder aB;
4113 aB.MakeShell(NewShell);
4114 TopoDS_Iterator aItSS(shell) ;
4115 for( ; aItSS.More(); aItSS.Next())
4116 aB.Add(NewShell,aItSS.Value())
4117 ;
4118 // Fill map of edges
4119 for (TopExp_Explorer eexp(shell,TopAbs_EDGE); eexp.More(); eexp.Next()) {
4120 TopoDS_Shape edge = eexp.Current();
4121 NewEdges.Add(edge);
4122 }
4123 IndexMerged.Add(i);
4124 }
4125 else {
4126 Standard_Boolean hasSharedEdge = Standard_False;
4127 TopExp_Explorer eexp(shell,TopAbs_EDGE);
4128 for (; eexp.More() && !hasSharedEdge; eexp.Next())
4129 hasSharedEdge = NewEdges.Contains(eexp.Current());
4130 if (hasSharedEdge) {
4131 // Add edges to the map
4132 for (TopExp_Explorer eexp1(shell,TopAbs_EDGE); eexp1.More(); eexp1.Next()) {
4133 TopoDS_Shape edge = eexp1.Current();
4134 NewEdges.Add(edge);
4135 }
4136 // Add faces to the shell
4137 for (TopExp_Explorer fexp(shell,TopAbs_FACE); fexp.More(); fexp.Next()) {
4138 TopoDS_Shape face = fexp.Current();
4139 aB.Add(NewShell,face);
4140 }
4141 IndexMerged.Add(i);
4142 }
4143 }
4144 }
4145 // Process new shell
4146 TopoDS_Shape face;
4147 Standard_Integer numf = 0;
4148 TopExp_Explorer aExpF(NewShell,TopAbs_FACE);
4149 for (; aExpF.More() && (numf < 2); aExpF.Next()) {
4150 face = aExpF.Current();
4151 numf++;
4152 }
4153 if (numf == 1) aB.Add(aComp,face);
4154 else if (numf > 1) aB.Add(aComp,NewShell);
4155 if (numf) numsh++;
4156 }
4157 }
4158 }
4159 if (numsh == 1) {
4160 // Extract single component
4161 TopoDS_Iterator aIt(aComp,Standard_False);
4162 mySewedShape = aIt.Value();
4163 }
4164 else
4165 mySewedShape = aComp;
4166}
4167
4168//=======================================================================
4169//function : CreateOutputInformations
4170//purpose : constructs :
4171// myEdgeSections
4172// mySectionBound
4173// myNbFreeEdges
4174// myNbContigousEdges
4175// myNbMultipleEdges
4176// myNbDegenerated
4177//=======================================================================
4178
4179void BRepBuilderAPI_Sewing::CreateOutputInformations()
4180{
4181 // Construct edgeSections
4182 Standard_Integer i;
4183 //TopTools_DataMapOfShapeListOfShape edgeSections;
4184 TopTools_IndexedDataMapOfShapeListOfShape edgeSections; //use index map for regulating free edges
4185 for (i = 1; i <= myBoundFaces.Extent(); i++) {
4186 const TopoDS_Shape& bound = myBoundFaces.FindKey(i);
4187 TopTools_ListOfShape lsect;
4188 if (myBoundSections.IsBound(bound)) lsect = myBoundSections(bound);
4189 TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE);
4190 for (; aExp.More(); aExp.Next()) {
4191 TopoDS_Shape sec = bound, edge = aExp.Current();
4192 TopTools_ListIteratorOfListOfShape aI(lsect);
4193 for (; aI.More(); aI.Next()) {
4194 const TopoDS_Shape& section = aI.Value();
4195 if (edge.IsSame(myReShape->Apply(section))) { sec = section; break; }
4196 }
4197 if (edgeSections.Contains(edge))
4198 edgeSections.ChangeFromKey(edge).Append(sec);
4199 else {
4200 TopTools_ListOfShape listSec;
4201 listSec.Append(sec);
4202 edgeSections.Add(edge,listSec);
4203 }
4204 }
4205 }
4206
4207 // Fill maps of Free, Contigous and Multiple edges
4208 //TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter2(edgeSections);
4209 for (i = 1; i <= edgeSections.Extent(); i++) {
4210 const TopoDS_Shape& edge = edgeSections.FindKey(i);
4211 const TopTools_ListOfShape& listSection = edgeSections(i);
4212 if (listSection.Extent() == 1) {
4213 if (BRep_Tool::Degenerated(TopoDS::Edge(edge)))
4214 myDegenerated.Add(edge);
4215 else
4216 myFreeEdges.Add(edge);
4217 }
4218 else if (listSection.Extent() == 2) {
4219 myContigousEdges.Add(edge,listSection);
4220 }
4221 else {
4222 myMultipleEdges.Add(edge);
4223 }
4224 }
4225
4226 // constructs myContigSectBound
4227 TopTools_DataMapOfShapeListOfShape aEdgeMap; //gka
4228 for (i = 1; i <= myBoundFaces.Extent(); i++) {
4229 TopoDS_Shape bound = myBoundFaces.FindKey(i);
4230 if (myBoundSections.IsBound(bound)) {
4231 TopTools_ListIteratorOfListOfShape iter(myBoundSections(bound));
4232 for (; iter.More(); iter.Next()) {
4233 TopoDS_Shape section = iter.Value();
4234 if(!myMergedEdges.Contains(section)) continue;
4235 //if (!myReShape->IsRecorded(section)) continue; // section is free
4236 TopoDS_Shape nedge = myReShape->Apply(section);
4237 if (nedge.IsNull()) continue; //szv debug
4238 if (!bound.IsSame(section))
4239 if (myContigousEdges.Contains(nedge))
4240 myContigSecBound.Bind(section, bound);
4241 }
4242 }
4243 }
4244}
4245
4246//=======================================================================
4247//function : ProjectPointsOnCurve
4248//purpose : internal use
4249//=======================================================================
4250
4251void BRepBuilderAPI_Sewing::ProjectPointsOnCurve(const TColgp_Array1OfPnt& arrPnt,
4252 const Handle(Geom_Curve)& c3d,
4253 const Standard_Real first,
4254 const Standard_Real last,
4255 TColStd_Array1OfReal& arrDist,
4256 TColStd_Array1OfReal& arrPara,
2028d00c
G
4257 TColgp_Array1OfPnt& arrProj,
4258 const Standard_Boolean isConsiderEnds) const
7fd59977 4259{
4260 arrDist.Init(-1.0);
4261
4262 GeomAdaptor_Curve GAC(c3d);
4263 Extrema_ExtPC locProj;
4264 locProj.Initialize(GAC, first, last);
4265 gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last);
4266
4267 for (Standard_Integer i1 = 1; i1 <= arrPnt.Length(); i1++) {
4268 gp_Pnt pt = arrPnt(i1);
4269 Standard_Real worktol = myTolerance;
4270 Standard_Real distF2 = pfirst.SquareDistance(pt);
4271 Standard_Real distL2 = plast.SquareDistance(pt);
4272 Standard_Boolean isProjected = Standard_False;
4273 try {
4274
4275 // Project current point on curve
4276 locProj.Perform(pt);
4277 if (locProj.IsDone() && locProj.NbExt() > 0) {
4278 Standard_Real dist2Min = Min(distF2,distL2);
4279 Standard_Integer ind, indMin = 0;
4280 for (ind = 1; ind <= locProj.NbExt(); ind++) {
4281 Standard_Real dProj2 = locProj.SquareDistance(ind);
4282 if (dProj2 < dist2Min) { indMin = ind; dist2Min = dProj2; }
4283 }
4284 if (indMin) {
4285 isProjected = Standard_True;
4286 Extrema_POnCurv pOnC = locProj.Point(indMin);
4287 Standard_Real paramProj = pOnC.Parameter();
4288 gp_Pnt ptProj = GAC.Value(paramProj);
4289 Standard_Real distProj2 = ptProj.SquareDistance(pt);
4290 if (!locProj.IsMin(indMin)) {
4291 if (Min(distF2,distL2) < dist2Min) {
4292 if (distF2 < distL2) {
4293 paramProj = first;
4294 distProj2 = distF2;
4295 ptProj = pfirst;
4296 }
4297 else {
4298 paramProj = last;
4299 distProj2 = distL2;
4300 ptProj = plast;
4301 }
4302 }
4303 }
2c896b8f 4304 if (distProj2 < worktol * worktol || !isConsiderEnds) {
7fd59977 4305 arrDist(i1) = sqrt (distProj2);
4306 arrPara(i1) = paramProj;
4307 arrProj(i1) = ptProj;
4308 }
4309 }
4310 }
4311 }
4312 catch (Standard_Failure) {
4313 worktol = MinTolerance();
4314#ifdef DEB
4315 cout << "Exception in BRepBuilderAPI_Sewing::ProjectPointsOnCurve: ";
4316 Standard_Failure::Caught()->Print(cout); cout << endl;
4317#endif
4318 }
2028d00c 4319 if (!isProjected && isConsiderEnds) {
7fd59977 4320 if (Min(distF2,distL2) < worktol * worktol) {
4321 if (distF2 < distL2) {
4322 arrDist(i1) = sqrt (distF2);
4323 arrPara(i1) = first;
4324 arrProj(i1) = pfirst;
4325 }
4326 else {
4327 arrDist(i1) = sqrt (distL2);
4328 arrPara(i1) = last;
4329 arrProj(i1) = plast;
4330 }
4331 }
4332 }
4333 }
4334}
4335
4336//=======================================================================
4337//function : CreateCuttingNodes
4338//purpose : internal use
4339//=======================================================================
4340
4341void BRepBuilderAPI_Sewing::CreateCuttingNodes(const TopTools_IndexedMapOfShape& MapVert,
4342 const TopoDS_Shape& bound,
4343 const TopoDS_Shape& vfirst,
4344 const TopoDS_Shape& vlast,
4345 const TColStd_Array1OfReal& arrDist,
4346 const TColStd_Array1OfReal& arrPara,
4347 const TColgp_Array1OfPnt& arrPnt,
4348 TopTools_SequenceOfShape& seqVert,
4349 TColStd_SequenceOfReal& seqPara)
4350{
4351 Standard_Integer i, j, nbProj = MapVert.Extent();
4352
4353 // Reorder projections by distance
4354 TColStd_SequenceOfInteger seqOrderedIndex;
4355 { //szv: Use brackets to destroy local variables
4356 TColStd_SequenceOfReal seqOrderedDistance;
4357 for (i = 1; i <= nbProj; i++) {
4358 Standard_Real distProj = arrDist(i);
4359 if (distProj < 0.0) continue; // Skip vertex if not projected
4360 Standard_Boolean isInserted = Standard_False;
4361 for (j = 1; j <= seqOrderedIndex.Length() && !isInserted; j++) {
4362 isInserted = (distProj < seqOrderedDistance(j));
4363 if (isInserted) {
4364 seqOrderedIndex.InsertBefore(j,i);
4365 seqOrderedDistance.InsertBefore(j,distProj);
4366 }
4367 }
4368 if (!isInserted) {
4369 seqOrderedIndex.Append(i);
4370 seqOrderedDistance.Append(distProj);
4371 }
4372 }
4373 }
4374 nbProj = seqOrderedIndex.Length();
4375 if (!nbProj) return;
4376
4377 BRep_Builder aBuilder;
4378
4379 // Insert two initial vertices (to be removed later)
4380 TColStd_SequenceOfReal seqDist;
4381 TColgp_SequenceOfPnt seqPnt;
4382 { //szv: Use brackets to destroy local variables
4383 // Retrieve bound curve
4384 TopLoc_Location loc;
4385 Standard_Real first,last;
4386 Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(bound), loc, first, last);
4387 if (!loc.IsIdentity()) {
4388 c3d = Handle(Geom_Curve)::DownCast(c3d->Copy());
4389 c3d->Transform(loc.Transformation());
4390 }
4391 GeomAdaptor_Curve GAC(c3d);
4392 seqVert.Prepend(vfirst); seqVert.Append(vlast);
4393 seqPara.Prepend(first); seqPara.Append(last);
4394 seqDist.Prepend(-1.0); seqDist.Append(-1.0);
4395 seqPnt.Prepend(GAC.Value(first)); seqPnt.Append(GAC.Value(last));
4396 }
4397
4398 TopTools_DataMapOfShapeShape NodeCuttingVertex;
4399 for (i = 1; i <= nbProj; i++) {
4400
4401 const Standard_Integer index = seqOrderedIndex(i);
4402 Standard_Real disProj = arrDist(index);
4403 gp_Pnt pntProj = arrPnt(index);
4404
4405 // Skip node if already bound to cutting vertex
4406 TopoDS_Shape node = myVertexNode.FindFromKey(MapVert(index));
4407 if (NodeCuttingVertex.IsBound(node)) continue;
4408
4409 // Find the closest vertex
4410 Standard_Integer indexMin = 1;
4411 Standard_Real dist, distMin = pntProj.Distance(seqPnt(1));
4412 for (j = 2; j <= seqPnt.Length(); j++) {
4413 dist = pntProj.Distance(seqPnt(j));
4414 if (dist < distMin) { distMin = dist; indexMin = j; }
4415 }
4416
4417 // Check if current point is close to one of the existent
4418 if (distMin <= Max(disProj*0.1,MinTolerance())) {
4419 // Check distance if close
4420 Standard_Real jdist = seqDist.Value(indexMin);
4421 if (jdist < 0.0) {
4422 // Bind new cutting node (end vertex only)
4423 seqDist.SetValue(indexMin,disProj);
4424 TopoDS_Shape cvertex = seqVert.Value(indexMin);
4425 NodeCuttingVertex.Bind(node,cvertex);
4426 }
4427 else {
4428 // Bind secondary cutting nodes
4429 NodeCuttingVertex.Bind(node,TopoDS_Vertex());
4430 }
4431 }
4432 else {
4433 // Build new cutting vertex
4434 TopoDS_Vertex cvertex;
4435 aBuilder.MakeVertex(cvertex, pntProj, Precision::Confusion());
4436 // Bind new cutting vertex
4437 NodeCuttingVertex.Bind(node,cvertex);
4438 // Insert cutting vertex in the sequences
4439 Standard_Real parProj = arrPara(index);
4440 for (j = 2; j <= seqPara.Length(); j++) {
4441 if (parProj <= seqPara.Value(j)) {
4442 seqVert.InsertBefore(j,cvertex);
4443 seqPara.InsertBefore(j,parProj);
4444 seqDist.InsertBefore(j,disProj);
4445 seqPnt.InsertBefore (j,pntProj);
4446 break;
4447 }
4448 }
4449 }
4450 }
4451
4452 // filling map for cutting nodes
4453 TopTools_DataMapIteratorOfDataMapOfShapeShape mit(NodeCuttingVertex);
4454 for (; mit.More(); mit.Next()) {
4455 TopoDS_Shape cnode = mit.Value();
4456 // Skip secondary nodes
4457 if (cnode.IsNull()) continue;
4458 // Obtain vertex node
4459 TopoDS_Shape node = mit.Key();
4460 if (myVertexNode.Contains(cnode)) {
4461 // This is an end vertex
4462 cnode = myVertexNode.FindFromKey(cnode);
4463 }
4464 else {
4465 // Create link: cutting vertex -> node
4466 TopTools_ListOfShape ls;
4467 ls.Append(node);
4468 myCuttingNode.Bind(cnode,ls);
4469 }
4470 // Create link: node -> cutting vertex
4471 if (myCuttingNode.IsBound(node)) {
4472 myCuttingNode.ChangeFind(node).Append(cnode);
4473 }
4474 else {
4475 TopTools_ListOfShape ls;
4476 ls.Append(cnode);
4477 myCuttingNode.Bind(node,ls);
4478 }
4479 }
4480
4481 // Remove two initial vertices
4482 seqVert.Remove(1); seqVert.Remove(seqVert.Length());
4483 seqPara.Remove(1); seqPara.Remove(seqPara.Length());
4484}
4485
4486//=======================================================================
4487//function : CreateSections
4488//purpose : internal use
4489//=======================================================================
4490
4491void BRepBuilderAPI_Sewing::CreateSections(const TopoDS_Shape& section,
4492 const TopTools_SequenceOfShape& seqNode,
4493 const TColStd_SequenceOfReal& seqPara,
4494 TopTools_ListOfShape& listEdge)
4495{
4496 const TopoDS_Edge& sec = TopoDS::Edge(section);
4497 // TopAbs_Orientation aInitOr = sec.Orientation();
4498
4499
4500 //To keep NM vertices on edge
4501 TopTools_SequenceOfShape aSeqNMVert;
4502 TColStd_SequenceOfReal aSeqNMPars;
4503 findNMVertices(sec,aSeqNMVert,aSeqNMPars);
4504
4505 BRep_Builder aBuilder;
4506
4507 Standard_Real first, last;
4508 BRep_Tool::Range(sec, first, last);
4509
4510 // Create cutting sections
4511 Standard_Real par1, par2;
4512 TopoDS_Shape V1, V2;
4513 Standard_Integer i, len = seqPara.Length() + 1;
4514 for (i = 1; i <= len; i++) {
4515
4516 TopoDS_Edge edge = sec;
4517 edge.EmptyCopy();
4518
4519 if (i == 1) {
4520 par1 = first;
4521 par2 = seqPara(i);
4522 V1 = TopExp::FirstVertex(sec);
4523 V2 = seqNode(i);
4524 }
4525 else if (i == len) {
4526 par1 = seqPara(i-1);
4527 par2 = last;
4528 V1 = seqNode(i-1);
4529 V2 = TopExp::LastVertex(sec);
4530 }
4531 else {
4532 par1 = seqPara(i-1);
4533 par2 = seqPara(i);
4534 V1 = seqNode(i-1);
4535 V2 = seqNode(i);
4536 }
4537
4538 TopoDS_Shape aTmpShape = edge.Oriented(TopAbs_FORWARD);
4539 TopoDS_Edge aTmpEdge = TopoDS::Edge (aTmpShape); // for porting
4540 aTmpShape = V1.Oriented(TopAbs_FORWARD);
4541 aBuilder.Add(aTmpEdge, aTmpShape);
4542 aTmpShape = V2.Oriented(TopAbs_REVERSED);
4543 aBuilder.Add(aTmpEdge, aTmpShape);
4544 aBuilder.Range(aTmpEdge, par1, par2);
4545 // if(aInitOr == TopAbs_REVERSED)
4546 // listEdge.Prepend(edge);
4547 // else
4548
4549 Standard_Integer k =1;
4550 for( ; k <= aSeqNMPars.Length() ; k++) {
4551 Standard_Real apar = aSeqNMPars.Value(k);
4552 if(apar >= par1 && apar <= par2) {
4553 aBuilder.Add(aTmpEdge,aSeqNMVert.Value(k));
4554 aSeqNMVert.Remove(k);
4555 aSeqNMPars.Remove(k);
4556 k--;
4557 }
4558 }
4559 listEdge.Append(edge);
4560 }
4561
4562 const TopTools_ListOfShape& listFaces = myBoundFaces.FindFromKey(sec);
4563 if (!listFaces.Extent()) return;
4564
4565 Standard_Real tolEdge = BRep_Tool::Tolerance(sec);
4566
4567 // Add cutting pcurves
4568 TopTools_ListIteratorOfListOfShape itf(listFaces);
4569 for (; itf.More(); itf.Next()) {
4570
4571 const TopoDS_Face& fac = TopoDS::Face(itf.Value());
4572
4573 // Retrieve curve on surface
4574 Standard_Real first2d=0., last2d=0.,first2d1=0,last2d1=0.;
4575 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(sec, fac, first2d, last2d);
4576 if (c2d.IsNull()) continue;
4577 Handle(Geom2d_Curve) c2d1;
4578 Standard_Boolean isSeam = BRep_Tool::IsClosed(sec,fac);
4579
4580 //gka - Convert to BSpline was commented because
4581 //it is not necessary to create BSpline instead of Lines or cIrcles.
4582 //Besides after conversion circles to BSpline
4583 //it is necessary to recompute parameters of cutting because paramerization of created
4584 //BSpline curve differs from parametrization of circle.
4585
4586 // Convert pcurve to BSpline
4587 /*Handle(Geom2d_BSplineCurve) c2dBSP,c2dBSP1;
4588 if (c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
4589 c2dBSP = Handle(Geom2d_BSplineCurve)::DownCast(c2d);
4590 }
4591 else {
4592 if (first > (c2d->FirstParameter() + Precision::PConfusion()) ||
4593 last < (c2d->LastParameter() - Precision::PConfusion())) {
4594 Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d, first, last);
4595 c2dBSP = Geom2dConvert::CurveToBSplineCurve(TC);
4596 }
4597 else c2dBSP = Geom2dConvert::CurveToBSplineCurve(c2d);
4598 }
4599 if (c2dBSP.IsNull()) continue;*/
4600 //gka fix for bug OCC12203 21.04.06 addition second curve for seam edges
4601
4602 if(isSeam)
4603 {
4604 TopoDS_Edge secRev = TopoDS::Edge(sec.Reversed());
4605
4606 c2d1 = BRep_Tool::CurveOnSurface(secRev, fac, first2d1, last2d1);
4607 if (c2d1.IsNull()) continue;
4608
4609 /*if (c2d1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
4610 c2dBSP1 = Handle(Geom2d_BSplineCurve)::DownCast(c2d1);
4611 }
4612 else {
4613 if (first > (c2d1->FirstParameter() + Precision::PConfusion()) ||
4614 last < (c2d1->LastParameter() - Precision::PConfusion())) {
4615 Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d1, first, last);
4616 //c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(TC);
4617 }
4618 //else c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(c2d);
4619
4620 }*/
4621 }
4622
4623 /*first2d = c2dBSP->FirstParameter();
4624 last2d = c2dBSP->LastParameter();
4625
4626 if(!c2dBSP1.IsNull()) {
4627 first2d1 = c2dBSP1->FirstParameter();
4628 last2d1 = c2dBSP1->LastParameter();
4629 }*/
4630
4631 // Update cutting sections
4632 Handle(Geom2d_Curve) c2dNew,c2d1New;
4633 TopTools_ListIteratorOfListOfShape ite(listEdge);
4634 for (; ite.More(); ite.Next()) {
4635
4636 // Retrieve cutting section
4637 const TopoDS_Edge& edge = TopoDS::Edge(ite.Value());
4638 BRep_Tool::Range(edge, par1, par2);
4639
4640 // Cut BSpline pcurve
4641 // try {
4642 c2dNew = Handle(Geom2d_Curve)::DownCast(c2d->Copy());
4643 //c2dNew = Handle(Geom2d_Curve)::DownCast(c2dBSP->Copy());
4644 //Handle(Geom2d_BSplineCurve)::DownCast(c2dNew)->Segment(Max(first2d,par1),Min(par2,last2d));
4645 if(!c2d1.IsNull()) { //if(!c2dBSP1.IsNull()) {
4646 c2d1New = Handle(Geom2d_Curve)::DownCast(c2d1->Copy());
4647 //c2d1New = Handle(Geom2d_Curve)::DownCast(c2dBSP1->Copy());
4648 //Handle(Geom2d_BSplineCurve)::DownCast(c2d1New)->Segment(Max(first2d1,par1),Min(par2,last2d1));
4649 }
4650 //}
4651 /*catch (Standard_Failure) {
4652 #ifdef DEB
4653 cout << "Exception in CreateSections: segment [" << par1 << "," << par2 << "]: ";
4654 Standard_Failure::Caught()->Print(cout); cout << endl;
4655 #endif
4656 Handle(Geom2d_TrimmedCurve) c2dT = new Geom2d_TrimmedCurve(c2dNew,Max(first2d,par1),Min(par2,last2d));
4657 c2dNew = c2dT;
4658 }*/
4659
4660
4661 if(!isSeam && c2d1New.IsNull())
4662 aBuilder.UpdateEdge(edge, c2dNew, fac, tolEdge);
4663 else {
4664 TopAbs_Orientation Ori = edge.Orientation();
4665 if(fac.Orientation() == TopAbs_REVERSED)
4666 Ori = TopAbs::Reverse(Ori);
4667
4668 if(Ori == TopAbs_FORWARD)
4669 aBuilder.UpdateEdge(edge, c2dNew,c2d1New ,fac, tolEdge);
4670 else
4671 aBuilder.UpdateEdge(edge, c2d1New,c2dNew ,fac, tolEdge);
4672 }
4673 }
4674 }
4675}
4676
4677//=======================================================================
4678//function : SameParameterShape
4679//purpose :
4680//=======================================================================
4681
4682void BRepBuilderAPI_Sewing::SameParameterShape()
4683{
4684 if (!mySameParameterMode) return;
4685 TopExp_Explorer exp(mySewedShape, TopAbs_EDGE);
4686 // Le flag sameparameter est a false pour chaque edge cousue
4687 for (; exp.More(); exp.Next()) {
4688 const TopoDS_Edge& sec = TopoDS::Edge(exp.Current());
4689 try {
4690
4691 BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec));
4692 }
4693 catch (Standard_Failure) {
4694#ifdef DEB
4695 cout << "Fail: BRepBuilderAPI_Sewing::SameParameterShape exception in BRepLib::SameParameter" << endl;
4696#endif
4697 continue;
4698 }
4699 }
4700}
82192477 4701
4702//=======================================================================
4703//function : Inspect
4704//purpose : Used for selection and storage of coinciding points
4705//=======================================================================
4706
4707NCollection_CellFilter_Action BRepBuilderAPI_VertexInspector::Inspect (const Standard_Integer theTarget)
4708{
4709 /*gp_Pnt aPnt = gp_Pnt (myPoints.Value (theTarget - 1));
4710 if (aPnt.SquareDistance (gp_Pnt (myCurrent)) <= myTol)
4711 myResInd.Append (theTarget);*/
4712
4713 const gp_XYZ& aPnt = myPoints.Value (theTarget - 1);
4714 Standard_Real aDx, aDy, aDz;
4715 aDx = myCurrent.X() - aPnt.X();
4716 aDy = myCurrent.Y() - aPnt.Y();
4717 aDz = myCurrent.Z() - aPnt.Z();
4718
4719 if ((aDx*aDx <= myTol) && (aDy*aDy <= myTol) && (aDz*aDz <= myTol))
4720 myResInd.Append (theTarget);
4721 return CellFilter_Keep;
4722}