0025553: ShapeFix_Face::FixMissingSeam() fails to correct a face
[occt.git] / src / ShapeFix / ShapeFix_IntersectionTool.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
b311480e 13
7fd59977 14
42cf5bc1 15#include <Bnd_Box2d.hxx>
16#include <BndLib_Add2dCurve.hxx>
7fd59977 17#include <BRep_Builder.hxx>
18#include <BRep_Tool.hxx>
19#include <BRepTools.hxx>
7fd59977 20#include <Geom2d_BSplineCurve.hxx>
21#include <Geom2d_Curve.hxx>
22#include <Geom2d_Line.hxx>
23#include <Geom2d_TrimmedCurve.hxx>
24#include <Geom2dAdaptor_Curve.hxx>
25#include <Geom2dInt_GInter.hxx>
42cf5bc1 26#include <Geom_Curve.hxx>
27#include <Geom_Surface.hxx>
28#include <GeomAdaptor_Curve.hxx>
29#include <GeomAdaptor_HSurface.hxx>
7fd59977 30#include <gp_Pnt.hxx>
31#include <IntRes2d_Domain.hxx>
32#include <IntRes2d_IntersectionPoint.hxx>
33#include <IntRes2d_IntersectionSegment.hxx>
34#include <IntRes2d_Position.hxx>
42cf5bc1 35#include <NCollection_Sequence.hxx>
7fd59977 36#include <ShapeAnalysis.hxx>
37#include <ShapeAnalysis_Edge.hxx>
38#include <ShapeAnalysis_Surface.hxx>
39#include <ShapeAnalysis_TransferParametersProj.hxx>
40#include <ShapeBuild_Edge.hxx>
42cf5bc1 41#include <ShapeBuild_ReShape.hxx>
42#include <ShapeExtend_WireData.hxx>
7fd59977 43#include <ShapeFix_DataMapOfShapeBox2d.hxx>
42cf5bc1 44#include <ShapeFix_IntersectionTool.hxx>
7fd59977 45#include <TopExp_Explorer.hxx>
46#include <TopoDS.hxx>
42cf5bc1 47#include <TopoDS_Edge.hxx>
48#include <TopoDS_Face.hxx>
7fd59977 49#include <TopoDS_Iterator.hxx>
42cf5bc1 50#include <TopoDS_Vertex.hxx>
7fd59977 51#include <TopoDS_Wire.hxx>
52#include <TopTools_SequenceOfShape.hxx>
53
54//gka 06.09.04 BUG 6555 shape is modified always independently either intersection was fixed or not
55//=======================================================================
56//function : ShapeFix_IntersectionTool
57//purpose :
58//=======================================================================
7fd59977 59ShapeFix_IntersectionTool::ShapeFix_IntersectionTool(const Handle(ShapeBuild_ReShape)& context,
60 const Standard_Real preci,
61 const Standard_Real maxtol)
62{
63 myContext = context;
64 myPreci = preci;
65 myMaxTol = maxtol;
66}
67
68
69//=======================================================================
70//function : GetPointOnEdge
71//purpose : auxiliary
72//:h0 abv 29 May 98: PRO10105 1949: like in BRepCheck, point is to be taken
73// from 3d curve (but only if edge is SameParameter)
74//=======================================================================
75static gp_Pnt GetPointOnEdge(const TopoDS_Edge &edge,
76 const Handle(ShapeAnalysis_Surface) &surf,
94f71cad 77 const Geom2dAdaptor_Curve &Crv2d,
7fd59977 78 const Standard_Real param )
79{
80 if( BRep_Tool::SameParameter(edge) ) {
81 Standard_Real f,l;
82 TopLoc_Location L;
83 const Handle(Geom_Curve) ConS = BRep_Tool::Curve ( edge, L, f, l );
84 if( !ConS.IsNull() )
85 return ConS->Value(param).Transformed(L.Transformation());
86 }
94f71cad 87 gp_Pnt2d aP2d = Crv2d.Value(param);
88 return surf->Adaptor3d()->Value(aP2d.X(), aP2d.Y());
7fd59977 89}
90
91
92//=======================================================================
93//function : SplitEdge
94//purpose :
95//=======================================================================
96
97Standard_Boolean ShapeFix_IntersectionTool::SplitEdge(const TopoDS_Edge& edge,
98 const Standard_Real param,
99 const TopoDS_Vertex& vert,
100 const TopoDS_Face& face,
101 TopoDS_Edge& newE1,
102 TopoDS_Edge& newE2,
103 const Standard_Real preci) const
104{
105 Standard_Real a, b;
106 ShapeAnalysis_Edge sae;
107
108 TopoDS_Vertex V1 = sae.FirstVertex(edge);
109 TopoDS_Vertex V2 = sae.LastVertex(edge);
110 if( V1.IsSame(vert) || V2.IsSame(vert) )
111 return Standard_False;
112
113 Handle(Geom2d_Curve) c2d;
114 sae.PCurve(edge,face,c2d,a,b,Standard_True );
115 if( Abs(a-param)<0.01*preci || Abs(b-param)<0.01*preci )
116 return Standard_False;
117 // check distanse between edge and new vertex
118 gp_Pnt P1;
119 TopLoc_Location L;
9cbe6290 120 if(BRep_Tool::SameParameter(edge) && !BRep_Tool::Degenerated(edge)) {
7fd59977 121 Standard_Real f,l;
122 const Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,L,f,l);
123 if(c3d.IsNull())
124 return Standard_False;
125 P1 = c3d->Value(param);
126 if(!L.IsIdentity()) P1 = P1.Transformed(L.Transformation());
127 }
128 else {
129 Handle(Geom_Surface) surf = BRep_Tool::Surface(face,L);
130 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(surf);
131 P1 = sas->Value(c2d->Value(param));
132 if(!L.IsIdentity()) P1 = P1.Transformed(L.Transformation());
133 }
134 gp_Pnt P2 = BRep_Tool::Pnt(vert);
135 if(P1.Distance(P2)>preci) {
136 //return Standard_False;
137 BRep_Builder B;
138 B.UpdateVertex(vert,P1.Distance(P2));
139 }
140
141 Handle(ShapeAnalysis_TransferParametersProj) transferParameters =
142 new ShapeAnalysis_TransferParametersProj;
143 transferParameters->SetMaxTolerance(preci);
144 transferParameters->Init(edge,face);
145 Standard_Real first, last;
146 if (a < b ) {
147 first = a;
148 last = b;
149 }
150 else {
151 first = b;
152 last = a;
153 }
154
155 ShapeBuild_Edge sbe;
156 TopAbs_Orientation orient = edge.Orientation();
157 BRep_Builder B;
158 TopoDS_Edge wE = edge;
159 wE.Orientation ( TopAbs_FORWARD );
160 TopoDS_Shape aTmpShape = vert.Oriented(TopAbs_REVERSED); //for porting
161 newE1 = sbe.CopyReplaceVertices ( wE, sae.FirstVertex(wE), TopoDS::Vertex(aTmpShape) );
162 sbe.CopyPCurves ( newE1, wE );
163 transferParameters->TransferRange(newE1,first,param,Standard_True);
164 B.SameRange(newE1,Standard_False);
165 B.SameParameter(newE1,Standard_False);
166 aTmpShape = vert.Oriented(TopAbs_FORWARD);
167 newE2 = sbe.CopyReplaceVertices ( wE, TopoDS::Vertex(aTmpShape),sae.LastVertex(wE) );
168 sbe.CopyPCurves ( newE2, wE );
169 transferParameters->TransferRange(newE2,param,last,Standard_True);
170 B.SameRange(newE2,Standard_False);
171 B.SameParameter(newE2,Standard_False);
172
173 newE1.Orientation(orient);
174 newE2.Orientation(orient);
175 if (orient==TopAbs_REVERSED) {
176 TopoDS_Edge tmp = newE2; newE2 = newE1; newE1=tmp;
177 }
178
179 return Standard_True;
180}
181
182
183//=======================================================================
184//function : CutEdge
185//purpose :
186//=======================================================================
187
188Standard_Boolean ShapeFix_IntersectionTool::CutEdge(const TopoDS_Edge &edge,
189 const Standard_Real pend,
190 const Standard_Real cut,
191 const TopoDS_Face &face,
192 Standard_Boolean &iscutline) const
193{
194 if( Abs(cut-pend)<10.*Precision::PConfusion() ) return Standard_False;
195 Standard_Real aRange = Abs(cut-pend);
196 Standard_Real a, b;
197 BRep_Tool::Range(edge, a, b);
198
199 if( aRange<10.*Precision::PConfusion() ) return Standard_False;
200
201 // case pcurve is trimm of line
202 if( !BRep_Tool::SameParameter(edge) ) {
203 ShapeAnalysis_Edge sae;
204 Handle(Geom2d_Curve) Crv;
205 Standard_Real fp,lp;
206 if ( sae.PCurve(edge,face,Crv,fp,lp,Standard_False) ) {
207 if(Crv->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
208 Handle(Geom2d_TrimmedCurve) tc = Handle(Geom2d_TrimmedCurve)::DownCast(Crv);
209 if(tc->BasisCurve()->IsKind(STANDARD_TYPE(Geom2d_Line))) {
210 BRep_Builder B;
211 B.Range(edge,Min(pend,cut),Max(pend,cut));
212 if( Abs(pend-lp)<Precision::PConfusion() ) { // cut from the begining
213 Standard_Real cut3d = (cut-fp)*(b-a)/(lp-fp);
214 B.Range(edge, a+cut3d, b, Standard_True);
215 iscutline = Standard_True;
216 }
217 else if( Abs(pend-fp)<Precision::PConfusion() ) { // cut from the end
218 Standard_Real cut3d = (lp-cut)*(b-a)/(lp-fp);
219 B.Range(edge, a, b-cut3d, Standard_True);
220 iscutline = Standard_True;
221 }
222 }
9cbe6290 223
224 return Standard_True;
7fd59977 225 }
0d3d226e 226
7fd59977 227 }
9cbe6290 228 return Standard_False;
7fd59977 229 }
230
231 // det-study on 03/12/01 checking the old and new ranges
232 if( Abs(Abs(a-b)-aRange) < Precision::PConfusion() ) return Standard_False;
233 if( aRange<10.*Precision::PConfusion() ) return Standard_False;
234
235 BRep_Builder B;
236 B.Range( edge, Min(pend,cut), Max(pend,cut) );
237
238 return Standard_True;
239}
240
241
242//=======================================================================
243//function : SplitEdge1
244//purpose : split edge[a,b] om two part e1[a,param]
245// and e2[param,b] using vertex vert
246//=======================================================================
247
248Standard_Boolean ShapeFix_IntersectionTool::SplitEdge1(const Handle(ShapeExtend_WireData)& sewd,
249 const TopoDS_Face& face,
250 const Standard_Integer num,
251 const Standard_Real param,
252 const TopoDS_Vertex& vert,
253 const Standard_Real preci,
254 ShapeFix_DataMapOfShapeBox2d& boxes) const
255{
256 TopoDS_Edge edge = sewd->Edge(num);
257 TopoDS_Edge newE1, newE2;
258 if(!SplitEdge(edge,param,vert,face,newE1,newE2,preci)) return Standard_False;
259
260 // change context
261 Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData;
262 wd->Add(newE1);
263 wd->Add(newE2);
264 if(!myContext.IsNull()) myContext->Replace( edge, wd->Wire() );
265 for (TopExp_Explorer exp ( wd->Wire(), TopAbs_EDGE ); exp.More(); exp.Next() ) {
266 TopoDS_Edge E = TopoDS::Edge ( exp.Current() );
267 BRepTools::Update(E);
268 }
269
270 // change sewd
271 sewd->Set(newE1,num);
272 if(num==sewd->NbEdges())
273 sewd->Add(newE2);
274 else
275 sewd->Add(newE2,num+1);
276
277 // change boxes
278 boxes.UnBind(edge);
279 TopLoc_Location L;
280 const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L);
281 Handle(Geom2d_Curve) c2d;
282 Standard_Real cf,cl;
283 ShapeAnalysis_Edge sae;
284 if(sae.PCurve(newE1,S,L,c2d,cf,cl,Standard_False)) {
285 Bnd_Box2d box;
286 Geom2dAdaptor_Curve gac;
287 Standard_Real aFirst = c2d->FirstParameter();
288 Standard_Real aLast = c2d->LastParameter();
289 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
290 && (cf < aFirst || cl > aLast)) {
291 //pdn avoiding problems with segment in Bnd_Box
292 gac.Load(c2d);
293 }
294 else
295 gac.Load(c2d,cf,cl);
296 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
297 boxes.Bind(newE1,box);
298 }
299 if(sae.PCurve(newE2,S,L,c2d,cf,cl,Standard_False)) {
300 Bnd_Box2d box;
301 Geom2dAdaptor_Curve gac;
302 Standard_Real aFirst = c2d->FirstParameter();
303 Standard_Real aLast = c2d->LastParameter();
304 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
305 && (cf < aFirst || cl > aLast)) {
306 //pdn avoiding problems with segment in Bnd_Box
307 gac.Load(c2d);
308 }
309 else
310 gac.Load(c2d,cf,cl);
311 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
312 boxes.Bind(newE2,box);
313 }
314
315 return Standard_True;
316}
317
318
319//=======================================================================
320//function : SplitEdge2
321//purpose : auxilary: split edge[a,b] om two part e1[a,param1]
322// and e2[param2,b] using vertex vert
323// (remove segment (param1,param2) from edge)
324//=======================================================================
325
326Standard_Boolean ShapeFix_IntersectionTool::SplitEdge2(const Handle(ShapeExtend_WireData)& sewd,
327 const TopoDS_Face& face,
328 const Standard_Integer num,
329 const Standard_Real param1,
330 const Standard_Real param2,
331 const TopoDS_Vertex& vert,
332 const Standard_Real preci,
333 ShapeFix_DataMapOfShapeBox2d& boxes) const
334{
335 TopoDS_Edge edge = sewd->Edge(num);
336 TopoDS_Edge newE1, newE2;
337 Standard_Real param = (param1+param2)/2;
338 if(!SplitEdge(edge,param,vert,face,newE1,newE2,preci)) return Standard_False;
339 // cut new edges by param1 and param2
340 Standard_Boolean IsCutLine;
341 Handle(Geom2d_Curve) Crv1, Crv2;
342 Standard_Real fp1,lp1,fp2,lp2;
343 ShapeAnalysis_Edge sae;
344 if(sae.PCurve ( newE1, face, Crv1, fp1, lp1, Standard_False )) {
345 if(sae.PCurve ( newE2, face, Crv2, fp2, lp2, Standard_False )) {
346 if(lp1==param) {
347 if( (lp1-fp1)*(lp1-param1)>0 ) {
348 CutEdge(newE1, fp1, param1, face, IsCutLine);
349 CutEdge(newE2, lp2, param2, face, IsCutLine);
350 }
351 else {
352 CutEdge(newE1, fp1, param2, face, IsCutLine);
353 CutEdge(newE2, lp2, param1, face, IsCutLine);
354 }
355 }
356 else {
357 if( (fp1-lp1)*(fp1-param1)>0 ) {
358 CutEdge(newE1, lp1, param1, face, IsCutLine);
359 CutEdge(newE2, fp2, param2, face, IsCutLine);
360 }
361 else {
362 CutEdge(newE1, lp1, param2, face, IsCutLine);
363 CutEdge(newE2, fp2, param1, face, IsCutLine);
364 }
365 }
366 }
367 }
368
369 // change context
370 Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData;
371 wd->Add(newE1);
372 wd->Add(newE2);
373 if(!myContext.IsNull()) myContext->Replace( edge, wd->Wire() );
374 for (TopExp_Explorer exp ( wd->Wire(), TopAbs_EDGE ); exp.More(); exp.Next() ) {
375 TopoDS_Edge E = TopoDS::Edge ( exp.Current() );
376 BRepTools::Update(E);
377 }
378
379 // change sewd
380 sewd->Set(newE1,num);
381 if(num==sewd->NbEdges())
382 sewd->Add(newE2);
383 else
384 sewd->Add(newE2,num+1);
385
386 // change boxes
387 boxes.UnBind(edge);
388 TopLoc_Location L;
389 const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L);
390 Handle(Geom2d_Curve) c2d;
391 Standard_Real cf,cl;
392 if(sae.PCurve(newE1,S,L,c2d,cf,cl,Standard_False)) {
393 Bnd_Box2d box;
394 Geom2dAdaptor_Curve gac;
395 Standard_Real aFirst = c2d->FirstParameter();
396 Standard_Real aLast = c2d->LastParameter();
397 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
398 && (cf < aFirst || cl > aLast)) {
399 //pdn avoiding problems with segment in Bnd_Box
400 gac.Load(c2d);
401 }
402 else
403 gac.Load(c2d,cf,cl);
404 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
405 boxes.Bind(newE1,box);
406 }
407 if(sae.PCurve(newE2,S,L,c2d,cf,cl,Standard_False)) {
408 Bnd_Box2d box;
409 Geom2dAdaptor_Curve gac;
410 Standard_Real aFirst = c2d->FirstParameter();
411 Standard_Real aLast = c2d->LastParameter();
412 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
413 && (cf < aFirst || cl > aLast)) {
414 //pdn avoiding problems with segment in Bnd_Box
415 gac.Load(c2d);
416 }
417 else
418 gac.Load(c2d,cf,cl);
419 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
420 boxes.Bind(newE2,box);
421 }
422
423 return Standard_True;
424}
425
426
427//=======================================================================
428//function : UnionVertexes
429//purpose :
430//=======================================================================
431
432Standard_Boolean ShapeFix_IntersectionTool::UnionVertexes(const Handle(ShapeExtend_WireData)& sewd,
433 TopoDS_Edge& edge1,
434 TopoDS_Edge& edge2,
435 const Standard_Integer num2,
436 ShapeFix_DataMapOfShapeBox2d& boxes,
437 const Bnd_Box2d& B2) const
438{
439 // union vertexes
9cbe6290 440 Standard_Boolean res = Standard_False;
7fd59977 441 ShapeBuild_Edge sbe;
442 ShapeAnalysis_Edge sae;
443 BRep_Builder B;
444 TopoDS_Vertex V;
445 TopoDS_Vertex V1F = sae.FirstVertex(edge1);
446 gp_Pnt PV1F = BRep_Tool::Pnt(V1F);
447 TopoDS_Vertex V1L = sae.LastVertex(edge1);
448 gp_Pnt PV1L = BRep_Tool::Pnt(V1L);
449 TopoDS_Vertex V2F = sae.FirstVertex(edge2);
450 gp_Pnt PV2F = BRep_Tool::Pnt(V2F);
451 TopoDS_Vertex V2L = sae.LastVertex(edge2);
452 gp_Pnt PV2L = BRep_Tool::Pnt(V2L);
453 Standard_Real d11 = PV1F.Distance(PV2F);
454 Standard_Real d12 = PV1F.Distance(PV2L);
455 Standard_Real d21 = PV1L.Distance(PV2F);
456 Standard_Real d22 = PV1L.Distance(PV2L);
457 if(d11<d12 && d11<d21 && d11<d22) {
458 Standard_Real tolv = Max(BRep_Tool::Tolerance(V1F),BRep_Tool::Tolerance(V2F));
459 if( !V2F.IsSame(V1F) && d11<tolv ) {
460 // union vertexes V1F and V2F
461 B.UpdateVertex(V1F,tolv);
462 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V1F,V2L);
463// cout<<"union vertexes V1F and V2F"<<endl;
464// gp_Pnt Ptmp = BRep_Tool::Pnt(V1F);
465// B.MakeVertex(V,Ptmp,tolv);
466// myContext->Replace(V1F,V);
467// myContext->Replace(V2F,V);
468// TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V,V2L);
469 myContext->Replace(edge2,NewE);
470 sewd->Set(NewE,num2);
471 edge2 = NewE;
472 boxes.Bind(NewE,B2); // update boxes
473 // replace vertex in other edge
474 Standard_Integer num21,num22;
475 if(num2>1) num21=num2-1;
476 else num21=sewd->NbEdges();
477 if(num2<sewd->NbEdges()) num22=num2+1;
478 else num22=1;
479 TopoDS_Edge edge21 = sewd->Edge(num21);
480 TopoDS_Edge edge22 = sewd->Edge(num22);
481 TopoDS_Vertex V21F = sae.FirstVertex(edge21);
482 TopoDS_Vertex V21L = sae.LastVertex(edge21);
483 TopoDS_Vertex V22F = sae.FirstVertex(edge22);
484 TopoDS_Vertex V22L = sae.LastVertex(edge22);
485 if(V21F.IsSame(V2F)) {
486 NewE = sbe.CopyReplaceVertices(edge21,V1F,V21L);
487 //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
488 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
489 myContext->Replace(edge21,NewE);
490 sewd->Set(NewE,num21);
491 }
492 if(V21L.IsSame(V2F)) {
493 NewE = sbe.CopyReplaceVertices(edge21,V21F,V1F);
494 //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
495 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
496 myContext->Replace(edge21,NewE);
497 sewd->Set(NewE,num21);
498 }
499 if(V22F.IsSame(V2F)) {
500 NewE = sbe.CopyReplaceVertices(edge22,V1F,V22L);
501 //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
502 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
503 myContext->Replace(edge22,NewE);
504 sewd->Set(NewE,num22);
505 }
506 if(V22L.IsSame(V2F)) {
507 NewE = sbe.CopyReplaceVertices(edge22,V22F,V1F);
508 //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
509 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
510 myContext->Replace(edge22,NewE);
511 sewd->Set(NewE,num22);
512 }
9cbe6290 513 res = Standard_True;
7fd59977 514 }
515 }
516 else if(d12<d21 && d12<d22) {
517 Standard_Real tolv = Max(BRep_Tool::Tolerance(V1F),BRep_Tool::Tolerance(V2L));
518 if( !V2L.IsSame(V1F) && d12<tolv ) {
519 // union vertexes V1F and V2L
520 B.UpdateVertex(V1F,tolv);
521 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V1F);
522// cout<<"union vertexes V1F and V2L"<<endl;
523// gp_Pnt Ptmp = BRep_Tool::Pnt(V1F);
524// B.MakeVertex(V,Ptmp,tolv);
525// myContext->Replace(V1F,V);
526// myContext->Replace(V2L,V);
527// TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V);
528 myContext->Replace(edge2,NewE);
529 sewd->Set(NewE,num2);
530 edge2 = NewE;
531 //boxes.Bind(NewE,boxes.Find(edge2)); // update boxes
532 boxes.Bind(NewE,B2); // update boxes
533 // replace vertex in other edge
534 Standard_Integer num21,num22;
535 if(num2>1) num21=num2-1;
536 else num21=sewd->NbEdges();
537 if(num2<sewd->NbEdges()) num22=num2+1;
538 else num22=1;
539 TopoDS_Edge edge21 = sewd->Edge(num21);
540 TopoDS_Edge edge22 = sewd->Edge(num22);
541 TopoDS_Vertex V21F = sae.FirstVertex(edge21);
542 TopoDS_Vertex V21L = sae.LastVertex(edge21);
543 TopoDS_Vertex V22F = sae.FirstVertex(edge22);
544 TopoDS_Vertex V22L = sae.LastVertex(edge22);
545 if(V21F.IsSame(V2L)) {
546 NewE = sbe.CopyReplaceVertices(edge21,V1F,V21L);
547 //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
548 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
549 myContext->Replace(edge21,NewE);
550 sewd->Set(NewE,num21);
551 }
552 if(V21L.IsSame(V2L)) {
553 NewE = sbe.CopyReplaceVertices(edge21,V21F,V1F);
554 //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
555 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
556 myContext->Replace(edge21,NewE);
557 sewd->Set(NewE,num21);
558 }
559 if(V22F.IsSame(V2L)) {
560 NewE = sbe.CopyReplaceVertices(edge22,V1F,V22L);
561 //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
562 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
563 myContext->Replace(edge22,NewE);
564 sewd->Set(NewE,num22);
565 }
566 if(V22L.IsSame(V2L)) {
567 NewE = sbe.CopyReplaceVertices(edge22,V22F,V1F);
568 //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
569 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
570 myContext->Replace(edge22,NewE);
571 sewd->Set(NewE,num22);
572 }
9cbe6290 573 res = Standard_True;
7fd59977 574 }
575 }
576 else if(d21<d22) {
577 Standard_Real tolv = Max(BRep_Tool::Tolerance(V1L),BRep_Tool::Tolerance(V2F));
578 if( !V2F.IsSame(V1L) && d21<tolv ) {
579 // union vertexes V1L and V2F
580 B.UpdateVertex(V1L,tolv);
581 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V1L,V2L);
582// cout<<"union vertexes V1L and V2F"<<endl;
583// gp_Pnt Ptmp = BRep_Tool::Pnt(V1L);
584// B.MakeVertex(V,Ptmp,tolv);
585// myContext->Replace(V1L,V);
586// myContext->Replace(V2F,V);
587// TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V,V2L);
588 myContext->Replace(edge2,NewE);
589 sewd->Set(NewE,num2);
590 edge2 = NewE;
591 boxes.Bind(NewE,B2); // update boxes
592 // replace vertex in other edge
593 Standard_Integer num21,num22;
594 if(num2>1) num21=num2-1;
595 else num21=sewd->NbEdges();
596 if(num2<sewd->NbEdges()) num22=num2+1;
597 else num22=1;
598 TopoDS_Edge edge21 = sewd->Edge(num21);
599 TopoDS_Edge edge22 = sewd->Edge(num22);
600 TopoDS_Vertex V21F = sae.FirstVertex(edge21);
601 TopoDS_Vertex V21L = sae.LastVertex(edge21);
602 TopoDS_Vertex V22F = sae.FirstVertex(edge22);
603 TopoDS_Vertex V22L = sae.LastVertex(edge22);
604 if(V21F.IsSame(V2F)) {
605 NewE = sbe.CopyReplaceVertices(edge21,V1L,V21L);
606 //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
607 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
608 myContext->Replace(edge21,NewE);
609 sewd->Set(NewE,num21);
610 }
611 if(V21L.IsSame(V2F)) {
612 NewE = sbe.CopyReplaceVertices(edge21,V21F,V1L);
613 //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
614 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
615 myContext->Replace(edge21,NewE);
616 sewd->Set(NewE,num21);
617 }
618 if(V22F.IsSame(V2F)) {
619 NewE = sbe.CopyReplaceVertices(edge22,V1L,V22L);
620 //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
621 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
622 myContext->Replace(edge22,NewE);
623 sewd->Set(NewE,num22);
624 }
625 if(V22L.IsSame(V2F)) {
626 NewE = sbe.CopyReplaceVertices(edge22,V22F,V1L);
627 //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
628 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
629 myContext->Replace(edge22,NewE);
630 sewd->Set(NewE,num22);
631 }
9cbe6290 632 res = Standard_True;
7fd59977 633 }
634 }
635 else {
636 Standard_Real tolv = Max(BRep_Tool::Tolerance(V1L),BRep_Tool::Tolerance(V2L));
637 if( !V2L.IsSame(V1L) && d22<tolv ) {
638 // union vertexes V1L and V2L
639 B.UpdateVertex(V1L,tolv);
640 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V1L);
641// cout<<"union vertexes V1L and V2L"<<endl;
642// gp_Pnt Ptmp = BRep_Tool::Pnt(V1L);
643// B.MakeVertex(V,Ptmp,tolv);
644// myContext->Replace(V1L,V);
645// myContext->Replace(V2L,V);
646// TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V);
647 myContext->Replace(edge2,NewE);
648 sewd->Set(NewE,num2);
649 edge2 = NewE;
650 boxes.Bind(NewE,B2); // update boxes
651 // replace vertex in other edge
652 Standard_Integer num21,num22;
653 if(num2>1) num21=num2-1;
654 else num21=sewd->NbEdges();
655 if(num2<sewd->NbEdges()) num22=num2+1;
656 else num22=1;
657 TopoDS_Edge edge21 = sewd->Edge(num21);
658 TopoDS_Edge edge22 = sewd->Edge(num22);
659 TopoDS_Vertex V21F = sae.FirstVertex(edge21);
660 TopoDS_Vertex V21L = sae.LastVertex(edge21);
661 TopoDS_Vertex V22F = sae.FirstVertex(edge22);
662 TopoDS_Vertex V22L = sae.LastVertex(edge22);
663 if(V21F.IsSame(V2L)) {
664 NewE = sbe.CopyReplaceVertices(edge21,V1L,V21L);
665 //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
666 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
667 myContext->Replace(edge21,NewE);
668 sewd->Set(NewE,num21);
669 }
670 if(V21L.IsSame(V2L)) {
671 NewE = sbe.CopyReplaceVertices(edge21,V21F,V1L);
672 //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
673 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
674 myContext->Replace(edge21,NewE);
675 sewd->Set(NewE,num21);
676 }
677 if(V22F.IsSame(V2L)) {
678 NewE = sbe.CopyReplaceVertices(edge22,V1L,V22L);
679 //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
680 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
681 myContext->Replace(edge22,NewE);
682 sewd->Set(NewE,num22);
683 }
684 if(V22L.IsSame(V2L)) {
685 NewE = sbe.CopyReplaceVertices(edge22,V22F,V1L);
686 //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
687 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
688 myContext->Replace(edge22,NewE);
689 sewd->Set(NewE,num22);
690 }
9cbe6290 691 res = Standard_True;
7fd59977 692 }
693 }
694
9cbe6290 695 return res;
7fd59977 696}
697
698
699//=======================================================================
700//function : CreateBoxes2d
701//purpose : auxilary
702//=======================================================================
7c8090aa 703static Bnd_Box2d CreateBoxes2d(const Handle(ShapeExtend_WireData)& sewd,
7fd59977 704 const TopoDS_Face& face,
705 ShapeFix_DataMapOfShapeBox2d& boxes)
706{
707 // create box2d for edges from wire
7c8090aa 708 Bnd_Box2d aTotalBox;
7fd59977 709 TopLoc_Location L;
710 const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L);
711 Handle(Geom2d_Curve) c2d;
712 Standard_Real cf,cl;
713 ShapeAnalysis_Edge sae;
714 for(Standard_Integer i=1; i<=sewd->NbEdges(); i++){
715 TopoDS_Edge E = sewd->Edge(i);
716 if(sae.PCurve(E,S,L,c2d,cf,cl,Standard_False)) {
717 Bnd_Box2d box;
718 Geom2dAdaptor_Curve gac;
719 Standard_Real aFirst = c2d->FirstParameter();
720 Standard_Real aLast = c2d->LastParameter();
721 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
722 && (cf < aFirst || cl > aLast)) {
723 //pdn avoiding problems with segment in Bnd_Box
724 gac.Load(c2d);
725 }
726 else
727 gac.Load(c2d,cf,cl);
728 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
729 boxes.Bind(E,box);
7c8090aa 730 aTotalBox.Add (box);
7fd59977 731 }
732 }
7c8090aa 733 return aTotalBox;
7fd59977 734}
735
736
737//=======================================================================
738//function : SelectIntPnt
739//purpose : auxilary
740//=======================================================================
741static void SelectIntPnt(const Geom2dInt_GInter& Inter,
742 IntRes2d_IntersectionPoint& IP,
743 IntRes2d_Transition& Tr1,
744 IntRes2d_Transition& Tr2)
745{
746 IP = Inter.Point(1);
747 Tr1 = IP.TransitionOfFirst();
748 Tr2 = IP.TransitionOfSecond();
749 if(Inter.NbPoints()==2) {
750 // possible second point is better?
751 Standard_Integer status1=0,status2=0;
752 if(Tr1.PositionOnCurve()==IntRes2d_Middle) status1+=1;
753 if(Tr2.PositionOnCurve()==IntRes2d_Middle) status1+=2;
754 IntRes2d_IntersectionPoint IP2;
755 IntRes2d_Transition Tr12, Tr22;
756 IP2 = Inter.Point(2);
757 Tr12 = IP2.TransitionOfFirst();
758 Tr22 = IP2.TransitionOfSecond();
759 if(Tr12.PositionOnCurve()==IntRes2d_Middle) status2+=1;
760 if(Tr22.PositionOnCurve()==IntRes2d_Middle) status2+=2;
761 if(status2>status1) {
762 IP=IP2; Tr1=Tr12; Tr2=Tr22;
763 }
764 }
765}
766
767
768//=======================================================================
769//function : FindVertAndSplitEdge
770//purpose : auxilary
771//=======================================================================
772Standard_Boolean ShapeFix_IntersectionTool::FindVertAndSplitEdge
773 (const Standard_Real param1,
774 const TopoDS_Edge& edge1, const TopoDS_Edge& edge2,
775 const Handle(Geom2d_Curve)& Crv1,
776 Standard_Real& MaxTolVert,
777 Standard_Integer& num1,
778 const Handle(ShapeExtend_WireData)& sewd,
779 const TopoDS_Face& face,
780 ShapeFix_DataMapOfShapeBox2d& boxes,
781 const Standard_Boolean aTmpKey) const
782{
783 // find needed vertex from edge2 and split edge1 using it
784 ShapeAnalysis_Edge sae;
785 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(BRep_Tool::Surface(face));
786 gp_Pnt pi1 = GetPointOnEdge(edge1,sas,Crv1,param1);
787 BRep_Builder B;
788 TopoDS_Vertex V;
789 Standard_Real tolV;
790 TopoDS_Vertex V1 = sae.FirstVertex(edge2);
791 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
792 TopoDS_Vertex V2 = sae.LastVertex(edge2);
793 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
794 TopoDS_Vertex V11 = sae.FirstVertex(edge1);
795 TopoDS_Vertex V12 = sae.LastVertex(edge1);
796 Standard_Boolean NeedSplit = Standard_True;
797 if(pi1.Distance(PV1)<pi1.Distance(PV2)) {
798 if( V1.IsSame(V11) || V1.IsSame(V12) ) {
799 NeedSplit = Standard_False;
800 }
801 V = V1;
802 tolV = Max( (pi1.Distance(PV1)/2)*1.00001, BRep_Tool::Tolerance(V1) );
803 }
804 else {
805 if( V2.IsSame(V11) || V2.IsSame(V12) ) {
806 NeedSplit = Standard_False;
807 }
808 V = V2;
809 tolV = Max( (pi1.Distance(PV2)/2)*1.00001, BRep_Tool::Tolerance(V2) );
810 }
811 if( NeedSplit || aTmpKey ) {
812 if(SplitEdge1(sewd, face, num1, param1, V, tolV, boxes)) {
813 B.UpdateVertex(V,tolV);
814 MaxTolVert = Max(MaxTolVert,tolV);
815// NbSplit++;
816 num1--;
817 return Standard_True;
818 //break;
819 }
820 }
821 return Standard_False;
822}
823
824
825//=======================================================================
826//function : FixSelfIntersectWire
827//purpose :
828//=======================================================================
829
830Standard_Boolean ShapeFix_IntersectionTool::FixSelfIntersectWire
831 (Handle(ShapeExtend_WireData)& sewd, const TopoDS_Face& face,
832 Standard_Integer& NbSplit, Standard_Integer& NbCut,
833 Standard_Integer& NbRemoved) const
834{
835 if(myContext.IsNull() || face.IsNull()) return Standard_False;
836
837 //Standard_Real area2d = ShapeAnalysis::TotCross2D(sewd,face);
838 //if(area2d<Precision::PConfusion()*Precision::PConfusion()) return Standard_False; //gka 06.09.04 BUG 6555
839
840 TopoDS_Shape SF = face;
841 Standard_Real MaxTolVert=0.0;
842 for(TopExp_Explorer exp(SF,TopAbs_VERTEX); exp.More(); exp.Next()) {
843 Standard_Real tolV = BRep_Tool::Tolerance(TopoDS::Vertex(exp.Current()));
844 MaxTolVert = Max(MaxTolVert,tolV);
845 }
846 MaxTolVert = Min(MaxTolVert,myMaxTol);
847 ShapeAnalysis_Edge sae;
848
849 // step 1 : intersection of adjacent edges
850
851 // step 2 : intersection of non-adjacent edges
852 ShapeFix_DataMapOfShapeBox2d boxes;
276130e7 853 (void)CreateBoxes2d(sewd,face,boxes);
7fd59977 854 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(BRep_Tool::Surface(face));
855
856 NbSplit=0;
857 NbCut=0;
858 Standard_Integer nbReplaced =0;
859 Standard_Boolean isDone = Standard_False;
860 for(Standard_Integer num1=1; num1<sewd->NbEdges() && NbSplit<30; num1++) {
861 // for each edge from first wire
862 for(Standard_Integer num2=num1+2; num2<=sewd->NbEdges() && NbSplit<30; num2++) {
863 // for each edge from second wire
864 if( num1==1 && num2==sewd->NbEdges() ) continue;
865 TopoDS_Edge edge1 = sewd->Edge(num1);
866 TopoDS_Edge edge2 = sewd->Edge(num2);
867 if(edge1.IsSame(edge2)) continue;
868 if( BRep_Tool::Degenerated(edge1) || BRep_Tool::Degenerated(edge2) ) continue;
869 if( !boxes.IsBound(edge1) || !boxes.IsBound(edge2) ) continue;
870 Bnd_Box2d B1 = boxes.Find(edge1);
871 Bnd_Box2d B2 = boxes.Find(edge2);
872 if(!B1.IsOut(B2)) {
873 // intersection is possible...
874 Standard_Real a1, b1, a2, b2;
875 Handle(Geom2d_Curve) Crv1, Crv2;
876 if( !sae.PCurve(edge1, face, Crv1, a1, b1, Standard_False) ) return Standard_False;
877 if( !sae.PCurve(edge2, face, Crv2, a2, b2, Standard_False) ) return Standard_False;
878 Standard_Real tolint = 1.0e-10;
7fd59977 879 Geom2dAdaptor_Curve C1(Crv1), C2(Crv2);
94f71cad 880 IntRes2d_Domain d1(C1.Value(a1),a1,tolint,C1.Value(b1),b1,tolint);
881 IntRes2d_Domain d2(C2.Value(a2),a2,tolint,C2.Value(b2),b2,tolint);
7fd59977 882 Geom2dInt_GInter Inter;
883 Inter.Perform( C1, d1, C2, d2, tolint, tolint );
884 if(!Inter.IsDone()) continue;
885 // intersection is point
886 if( Inter.NbPoints()>0 && Inter.NbPoints()<3 ) {
887 IntRes2d_IntersectionPoint IP;
888 IntRes2d_Transition Tr1, Tr2;
889 SelectIntPnt(Inter,IP,Tr1,Tr2);
890 if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
891 Tr2.PositionOnCurve() == IntRes2d_Middle ) {
892 Standard_Real param1 = IP.ParamOnFirst();
893 Standard_Real param2 = IP.ParamOnSecond();
94f71cad 894 gp_Pnt pi1 = GetPointOnEdge(edge1,sas,C1,param1);
895 gp_Pnt pi2 = GetPointOnEdge(edge2,sas,C2,param2);
7fd59977 896 BRep_Builder B;
897 TopoDS_Vertex V;
898 Standard_Real tolV=0;
899 // analysis for edge1
900 Standard_Boolean ModifE1 = Standard_False;
901 TopoDS_Vertex VF1 = sae.FirstVertex(edge1);
902 gp_Pnt PVF1 = BRep_Tool::Pnt(VF1);
903 TopoDS_Vertex VL1 = sae.LastVertex(edge1);
904 gp_Pnt PVL1 = BRep_Tool::Pnt(VL1);
905 Standard_Real dist1 = pi1.Distance(PVF1);
906 Standard_Real dist2 = pi1.Distance(PVL1);
9cbe6290 907 Standard_Real distmin = Min(dist1, dist2);
908 if( dist1 != dist2 && distmin < MaxTolVert ) {
909 if (dist1 < dist2) {
910 tolV = Max( dist1*1.00001, BRep_Tool::Tolerance(VF1) );
911 B.UpdateVertex(VF1,tolV);
912 V = VF1;
913 } else {
914 tolV = Max( dist2*1.00001, BRep_Tool::Tolerance(VL1) );
915 B.UpdateVertex(VL1,tolV);
916 V = VL1;
917 }
918
7fd59977 919 Standard_Real dista = Abs(a1-param1);
920 Standard_Real distb = Abs(b1-param1);
921 Standard_Boolean IsCutLine;
9cbe6290 922 ModifE1 = CutEdge(edge1, (( dista > distb ) ? a1 : b1 ), param1, face, IsCutLine);
923 if (ModifE1)
924 NbCut++;
925 //not needed split edge, if one of parts is too small
926 ModifE1 = ModifE1 || distmin < Precision::Confusion();
7fd59977 927 }
928 // analysis for edge2
929 Standard_Boolean ModifE2 = Standard_False;
930 TopoDS_Vertex VF2 = sae.FirstVertex(edge2);
931 gp_Pnt PVF2 = BRep_Tool::Pnt(VF2);
932 TopoDS_Vertex VL2 = sae.LastVertex(edge2);
933 gp_Pnt PVL2 = BRep_Tool::Pnt(VL2);
934 dist1 = pi2.Distance(PVF2);
935 dist2 = pi2.Distance(PVL2);
9cbe6290 936 distmin = Min(dist1, dist2);
937 if( dist1 != dist2 && distmin < MaxTolVert ) {
938 if (dist1 < dist2) {
939 tolV = Max( dist1*1.00001, BRep_Tool::Tolerance(VF2) );
940 B.UpdateVertex(VF2,tolV);
941 V = VF2;
942 } else {
943 tolV = Max( dist2*1.00001, BRep_Tool::Tolerance(VL2) );
944 B.UpdateVertex(VL2,tolV);
945 V = VL2;
946 }
947
7fd59977 948 Standard_Real dista = Abs(a2-param2);
949 Standard_Real distb = Abs(b2-param2);
950 Standard_Boolean IsCutLine;
9cbe6290 951 ModifE2 = CutEdge(edge2, (( dista > distb ) ? a2 : b2 ), param2, face, IsCutLine);
952 if (ModifE2)
953 NbCut++;
954 //not needed split edge, if one of parts is too small
955 ModifE2 = ModifE2 || distmin < Precision::Confusion();
7fd59977 956 }
957 if( ModifE1 && !ModifE2 ) {
958 if(SplitEdge1(sewd, face, num2, param2, V, tolV, boxes)) {
959 NbSplit++;
960 num2--;
961 continue;
962
963 }
964 }
965 if( !ModifE1 && ModifE2 ) {
966 if(SplitEdge1(sewd, face, num1, param1, V, tolV, boxes)) {
967 NbSplit++;
968 num1--;
969 break;
970 }
971 }
972 if( !ModifE1 && !ModifE2 ) {
973 gp_Pnt P0( (pi1.X()+pi2.X())/2, (pi1.Y()+pi2.Y())/2, (pi1.Z()+pi2.Z())/2 );
974 tolV = Max( (pi1.Distance(pi2)/2)*1.00001, Precision::Confusion() );
975 B.MakeVertex(V,P0,tolV);
976 MaxTolVert = Max(MaxTolVert,tolV);
977 Standard_Boolean isEdgeSplit2 = SplitEdge1(sewd, face, num2, param2,
978 V, tolV, boxes);
979 if(isEdgeSplit2) {
980 NbSplit++;
981 num2--;
982 }
983 if(SplitEdge1(sewd, face, num1, param1, V, tolV, boxes)) {
984 NbSplit++;
985 num1--;
986 break;
987 }
988 if(isEdgeSplit2)
989 continue;
990 }
991 }
992 if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
993 Tr2.PositionOnCurve() != IntRes2d_Middle ) {
994 // find needed vertex from edge2 and split edge1 using it
995 Standard_Real param1 = IP.ParamOnFirst();
996 if(FindVertAndSplitEdge(param1, edge1, edge2, Crv1, MaxTolVert,
997 num1, sewd, face, boxes, Standard_False) ) {
998 NbSplit++;
999 break;
1000 }
1001 }
1002 if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1003 Tr2.PositionOnCurve() == IntRes2d_Middle ) {
1004 // find needed vertex from edge1 and split edge2 using it
1005 Standard_Real param2 = IP.ParamOnSecond();
1006 if(FindVertAndSplitEdge(param2, edge2, edge1, Crv2, MaxTolVert,
1007 num2, sewd, face, boxes, Standard_False) ) {
1008 NbSplit++;
1009 continue;
1010 }
1011 }
1012 if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1013 Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1014 // union vertexes
1015 if( UnionVertexes(sewd, edge1, edge2, num2, boxes, B2) )
1016 nbReplaced ++; //gka 06.09.04
1017 }
1018 }
1019 // intersection is segment
1020 if( Inter.NbSegments()==1 ) {
1021 IntRes2d_IntersectionSegment IS = Inter.Segment(1);
1022 if ( IS.HasFirstPoint() && IS.HasLastPoint() ) {
1023 Standard_Boolean IsModified1 = Standard_False;
1024 Standard_Boolean IsModified2 = Standard_False;
1025 TopoDS_Vertex NewV;
1026 BRep_Builder B;
1027 Standard_Real newtol=0.0;
1028 IntRes2d_IntersectionPoint IPF = IS.FirstPoint();
1029 Standard_Real p11 = IPF.ParamOnFirst();
1030 Standard_Real p21 = IPF.ParamOnSecond();
1031 IntRes2d_IntersectionPoint IPL = IS.LastPoint();
1032 Standard_Real p12 = IPL.ParamOnFirst();
1033 Standard_Real p22 = IPL.ParamOnSecond();
94f71cad 1034 gp_Pnt Pnt11 = GetPointOnEdge(edge1,sas,C1,p11);
1035 gp_Pnt Pnt12 = GetPointOnEdge(edge1,sas,C1,p12);
1036 gp_Pnt Pnt21 = GetPointOnEdge(edge2,sas,C2,p21);
1037 gp_Pnt Pnt22 = GetPointOnEdge(edge2,sas,C2,p22);
7fd59977 1038 // next string commented by skl 29.12.2004 for OCC7624
1039 //if( Pnt11.Distance(Pnt21)>myPreci || Pnt12.Distance(Pnt22)>myPreci ) continue;
1040 if( Pnt11.Distance(Pnt21)>MaxTolVert || Pnt12.Distance(Pnt22)>MaxTolVert ) continue;
1041 // analysis for edge1
1042 TopoDS_Vertex V1 = sae.FirstVertex(edge1);
1043 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
1044 TopoDS_Vertex V2 = sae.LastVertex(edge1);
1045 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
1046 //Standard_Real tol1 = BRep_Tool::Tolerance(V1);
1047 //Standard_Real tol2 = BRep_Tool::Tolerance(V2);
1048 //Standard_Real maxtol = Max(tol1,tol2);
1049 Standard_Real dist1 = Pnt11.Distance(PV1);
1050 Standard_Real dist2 = Pnt12.Distance(PV1);
1051 Standard_Real maxdist = Max(dist1,dist2);
1052 Standard_Real pdist;
1053 if(edge1.Orientation()==TopAbs_REVERSED)
1054 pdist = Max(Abs(b1-p11),Abs(b1-p12));
1055 else
1056 pdist = Max(Abs(a1-p11),Abs(a1-p12));
1057 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1058 //if(maxdist<maxtol || pdist<Abs(b1-a1)*0.01) {
1059 newtol = maxdist;
1060 NewV = V1;
1061 IsModified1 = Standard_True;
1062 }
1063 dist1 = Pnt11.Distance(PV2);
1064 dist2 = Pnt12.Distance(PV2);
1065 maxdist = Max(dist1,dist2);
1066 if(edge1.Orientation()==TopAbs_REVERSED)
1067 pdist = Max(Abs(a1-p11),Abs(a1-p12));
1068 else
1069 pdist = Max(Abs(b1-p11),Abs(b1-p12));
1070 //if(maxdist<maxtol || pdist<Abs(b1-a1)*0.01) {
1071 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1072 if( ( IsModified1 && maxdist<newtol ) || !IsModified1 ) {
1073 newtol = maxdist;
1074 NewV = V2;
1075 IsModified1 = Standard_True;
1076 }
1077 }
1078 if(IsModified1) {
1079 // cut edge1 and update tolerance NewV
1080 Standard_Real dista = Abs(a1-p11)+Abs(a1-p12);
1081 Standard_Real distb = Abs(b1-p11)+Abs(b1-p12);
1082 Standard_Real pend,cut;
1083 if(dista>distb) pend=a1;
1084 else pend=b1;
1085 if(Abs(pend-p11)>Abs(pend-p12)) cut=p12;
1086 else cut=p11;
1087 Standard_Boolean IsCutLine;
9cbe6290 1088 if (CutEdge(edge1, pend, cut, face, IsCutLine))
1089 NbCut++;
7fd59977 1090 if(newtol>BRep_Tool::Tolerance(NewV)) {
1091 B.UpdateVertex(NewV,newtol);
1092 }
1093 else newtol = BRep_Tool::Tolerance(NewV);
1094 }
1095 // analysis for edge2
1096 TopoDS_Vertex V12 = sae.FirstVertex(edge2);
1097 gp_Pnt PV12 = BRep_Tool::Pnt(V12);
1098 TopoDS_Vertex V22 = sae.LastVertex(edge2);
1099 gp_Pnt PV22 = BRep_Tool::Pnt(V22);
1100 //tol1 = BRep_Tool::Tolerance(V1);
1101 //tol2 = BRep_Tool::Tolerance(V2);
1102 //maxtol = Max(tol1,tol2);
1103 dist1 = Pnt21.Distance(PV12);
1104 dist2 = Pnt22.Distance(PV12);
1105 maxdist = Max(dist1,dist2);
1106 if(edge2.Orientation()==TopAbs_REVERSED)
1107 pdist = Max(Abs(b2-p21),Abs(b2-p22));
1108 else
1109 pdist = Max(Abs(a2-p21),Abs(a2-p22));
1110 //if(maxdist<maxtol || pdist<Abs(b2-a2)*0.01) {
1111 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1112 newtol = maxdist;
1113 NewV = V12;
1114 IsModified2 = Standard_True;
1115 }
1116 dist1 = Pnt21.Distance(PV22);
1117 dist2 = Pnt22.Distance(PV22);
1118 maxdist = Max(dist1,dist2);
1119 if(edge2.Orientation()==TopAbs_REVERSED)
1120 pdist = Max(Abs(a2-p21),Abs(a2-p22));
1121 else
1122 pdist = Max(Abs(b2-p21),Abs(b2-p22));
1123 //if(maxdist<maxtol || pdist<Abs(b2-a2)*0.01) {
1124 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1125 if( ( IsModified2 && maxdist<newtol ) || !IsModified2 ) {
1126 newtol = maxdist;
1127 NewV = V22;
1128 IsModified2 = Standard_True;
1129 }
1130 }
1131 if(IsModified2) {
1132 // cut edge1 and update tolerance NewV
1133 Standard_Real dista = Abs(a2-p21)+Abs(a2-p22);
1134 Standard_Real distb = Abs(b2-p21)+Abs(b2-p22);
1135 Standard_Real pend,cut;
1136 if(dista>distb) pend=a2;
1137 else pend=b2;
1138 if(Abs(pend-p21)>Abs(pend-p22)) cut=p22;
1139 else cut=p21;
1140 Standard_Boolean IsCutLine;
9cbe6290 1141 if (CutEdge(edge2, pend, cut, face, IsCutLine))
1142 NbCut++;
7fd59977 1143 if(newtol>BRep_Tool::Tolerance(NewV)) {
1144 B.UpdateVertex(NewV,newtol);
1145 }
1146 else newtol = BRep_Tool::Tolerance(NewV);
1147 }
1148
1149 if( IsModified1 && !IsModified2 ) {
1150 if(SplitEdge2(sewd, face, num2, p21, p22, NewV, newtol, boxes)) {
1151 NbSplit++;
1152 num2--;
1153 continue;
1154 }
1155 }
1156 if( !IsModified1 && IsModified2 ) {
1157 if(SplitEdge2(sewd, face, num1, p11, p12, NewV, newtol, boxes)) {
1158 NbSplit++;
1159 num1--;
1160 break;
1161 }
1162 }
1163 if( !IsModified1 && !IsModified2 ) {
1164 Standard_Real param1 = (p11+p12)/2;
1165 Standard_Real param2 = (p21+p22)/2;
94f71cad 1166 gp_Pnt Pnt10 = GetPointOnEdge(edge1,sas,C1,param1);
1167 gp_Pnt Pnt20 = GetPointOnEdge(edge2,sas,C2,param2);
7fd59977 1168 gp_Pnt P0( (Pnt10.X()+Pnt20.X())/2, (Pnt10.Y()+Pnt20.Y())/2,
1169 (Pnt10.Z()+Pnt20.Z())/2 );
1170 dist1 = Max(Pnt11.Distance(P0),Pnt12.Distance(P0));
1171 dist2 = Max(Pnt21.Distance(P0),Pnt22.Distance(P0));
1172 Standard_Real tolV = Max(dist1,dist2);
1173 tolV = Max(tolV,Pnt10.Distance(Pnt20))*1.00001;
1174 Standard_Boolean FixSegment = Standard_True;
1175 if(tolV<MaxTolVert) {
1176 // create new vertex and split each intersecting edge on two edges
1177 B.MakeVertex(NewV,Pnt10,tolV);
1178 if(SplitEdge2(sewd, face, num2, p21, p22, NewV, tolV, boxes)) {
1179 NbSplit++;
1180 num2--;
1181 }
1182 if(SplitEdge2(sewd, face, num1, p11, p12, NewV, tolV, boxes)) {
1183 NbSplit++;
1184 num1--;
1185 break;
1186 }
1187 }
1188 else if(FixSegment) {
1189 //if( Abs(p12-p11)>Abs(b1-a1)/2 || Abs(p22-p21)>Abs(b2-a2)/2 ) {
1190 // segment is big and we have to split each intersecting edge
1191 // on 3 edges --> middle edge - edge based on segment
1192 // after we can remove edges maked from segment
1193 gp_Pnt P01( (Pnt11.X()+Pnt21.X())/2, (Pnt11.Y()+Pnt21.Y())/2,
1194 (Pnt11.Z()+Pnt21.Z())/2 );
1195 gp_Pnt P02( (Pnt12.X()+Pnt22.X())/2, (Pnt12.Y()+Pnt22.Y())/2,
1196 (Pnt12.Z()+Pnt22.Z())/2 );
1197 Standard_Real tolV1 = Max(Pnt11.Distance(P01),Pnt21.Distance(P01));
1198 tolV1 = Max(tolV1,Precision::Confusion())*1.00001;
1199 Standard_Real tolV2 = Max(Pnt12.Distance(P02),Pnt22.Distance(P02));
1200 tolV2 = Max(tolV2,Precision::Confusion())*1.00001;
1201 if( tolV1>MaxTolVert || tolV2>MaxTolVert ) continue;
1202 TopoDS_Vertex NewV1,NewV2;
1203/*
1204 // parameters for splitting: a1..p11..p12..b1 and a2..p21..p22..b2 ???
1205 Standard_Integer nbseg1=3, nbseg2=3, kv1=0, kv2=0;
1206 if(P01.Distance(PV1)<Max(tolV1,BRep_Tool::Tolerance(V1))) {
1207 NewV1 = V1;
1208 if(tolV1>BRep_Tool::Tolerance(V1))
1209 B.UpdateVertex(NewV1,tolV1);
1210 //akey1++;
1211 nbseg1--;
1212 kv1 = 1;
1213 }
1214 else if(P01.Distance(PV2)<Max(tolV1,BRep_Tool::Tolerance(V2))) {
1215 NewV1 = V2;
1216 if(tolV1>BRep_Tool::Tolerance(V2))
1217 B.UpdateVertex(NewV1,tolV1);
1218 //akey1++;
1219 nbseg1--;
1220 kv1 = 1;
1221 }
1222*/
1223 TopoDS_Edge tmpE,SegE;
1224 // split edge1
1225 Standard_Integer akey1=0, akey2=0;
163ef250 1226 Standard_Real newTolerance;
7fd59977 1227 // analysis fo P01
163ef250 1228 newTolerance = Max(tolV1,BRep_Tool::Tolerance(V1));
1229 if(P01.Distance(PV1)<newTolerance) {
1230 B.MakeVertex(NewV1,BRep_Tool::Pnt(V1),newTolerance);
1231 NewV1.Orientation(V1.Orientation());
7fd59977 1232 akey1++;
1233 }
163ef250 1234 newTolerance = Max(tolV1,BRep_Tool::Tolerance(V2));
1235 if(P01.Distance(PV2)<newTolerance) {
1236 B.MakeVertex(NewV1,BRep_Tool::Pnt(V2),newTolerance);
1237 NewV1.Orientation(V2.Orientation());
7fd59977 1238 akey1++;
1239 }
1240 // analysis fo P02
163ef250 1241 newTolerance = Max(tolV2,BRep_Tool::Tolerance(V1));
1242 if(P02.Distance(PV1)<newTolerance) {
1243 B.MakeVertex(NewV2,BRep_Tool::Pnt(V1),newTolerance);
1244 NewV2.Orientation(V1.Orientation());
7fd59977 1245 akey2++;
1246 }
163ef250 1247 newTolerance = Max(tolV2,BRep_Tool::Tolerance(V2));
1248 if(P02.Distance(PV2)<newTolerance) {
1249 B.MakeVertex(NewV2,BRep_Tool::Pnt(V2),newTolerance);
1250 NewV2.Orientation(V2.Orientation());
7fd59977 1251 akey2++;
1252 }
1253 if( akey1>1 || akey2>1 ) continue;
1254 Standard_Integer dnum1=0, numseg1=num1;
1255 // prepare vertices
1256 if(akey1==0) B.MakeVertex(NewV1,P01,tolV1);
1257 if(akey2==0) B.MakeVertex(NewV2,P02,tolV2);
1258 // split
1259 if( akey1==0 && akey2>0 ) {
1260 if(SplitEdge1(sewd, face, num1, p11, NewV1, tolV1, boxes)) {
1261 NbSplit++;
1262 dnum1=1;
1263 numseg1=num1+1;
1264 }
1265 }
1266 if( akey1>0 && akey2==0 ) {
1267 if(SplitEdge1(sewd, face, num1, p12, NewV2, tolV2, boxes) ) {
1268 NbSplit++;
1269 dnum1=1;
1270 numseg1=num1;
1271 }
1272 }
1273 if( akey1==0 && akey2==0 ) {
1274 if(SplitEdge1(sewd, face, num1, p11, NewV1, tolV1, boxes)) {
1275 NbSplit++;
1276 dnum1=1;
1277 }
1278 tmpE = sewd->Edge(num1);
1279 Standard_Real a,b;
1280 Handle(Geom2d_Curve) c2d;
1281 sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1282 if( (a-p12)*(b-p12)>0 ) { // p12 - external for [a,b] => split next edge
1283 if(SplitEdge1(sewd, face, num1+1, p12, NewV2, tolV2, boxes) ) {
1284 NbSplit++;
1285 dnum1++;
1286 numseg1=num1+1;
1287 }
1288 }
1289 else {
1290 if(SplitEdge1(sewd, face, num1, p12, NewV2, tolV2, boxes) ) {
1291 NbSplit++;
1292 dnum1++;
1293 numseg1=num1+1;
1294 }
1295 }
1296 }
1297 //SegE = sewd->Edge(numseg1); // get edge from segment
1298 // split edge2
1299 // replace vertices if it is necessary
1300 ShapeBuild_Edge sbe;
1301 akey1=0, akey2=0;
1302
1303 if(P01.Distance(PV12)<tolV1) {
1304 tolV1 += P01.Distance(PV12);
1305 B.UpdateVertex(NewV1,tolV1);
1306 if(V12.Orientation()==NewV1.Orientation()) {
1307 myContext->Replace(V12,NewV1);
1308 V12 = NewV1;
1309 }
1310 else {
1311 myContext->Replace(V12,NewV1.Reversed());
1312 V12 = TopoDS::Vertex(NewV1.Reversed());
1313 }
1314 nbReplaced++; //gka 06.09.04
1315 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV1,V22);
1316 myContext->Replace(edge2,NewE);
1317 sewd->Set(NewE,num2+dnum1);
1318 boxes.Bind(NewE,B2); // update boxes
1319 edge2 = NewE;
1320 akey1 = 1;
1321 }
1322 if(P01.Distance(PV22)<tolV1) {
1323 tolV1 += P01.Distance(PV22);
1324 B.UpdateVertex(NewV1,tolV1);
1325 if(V22.Orientation()==NewV1.Orientation()) {
1326 myContext->Replace(V22,NewV1);
1327 V22 = NewV1;
1328 }
1329 else {
1330 myContext->Replace(V22,NewV1.Reversed());
1331 V22 = TopoDS::Vertex(NewV1.Reversed());
1332 }
1333 nbReplaced++; //gka 06.09.04
1334 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV1);
1335 myContext->Replace(edge2,NewE);
1336 sewd->Set(NewE,num2+dnum1);
1337 boxes.Bind(NewE,B2); // update boxes
1338 edge2 = NewE;
1339 akey1 = 2;
1340 }
1341 if(P02.Distance(PV12)<tolV2) {
1342 tolV2 += P02.Distance(PV12);
1343 B.UpdateVertex(NewV2,tolV2);
1344 if(V12.Orientation()==NewV2.Orientation()) {
1345 myContext->Replace(V12,NewV2);
1346 V12 = NewV2;
1347 }
1348 else {
1349 myContext->Replace(V12,NewV2.Reversed());
1350 V12 = TopoDS::Vertex(NewV2.Reversed());
1351 }
1352 nbReplaced++; //gka 06.09.04
1353 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV2,V22);
1354 myContext->Replace(edge2,NewE);
1355 sewd->Set(NewE,num2+dnum1);
1356 boxes.Bind(NewE,B2); // update boxes
1357 edge2 = NewE;
1358 akey2 = 1;
1359 }
1360 if(P02.Distance(PV22)<tolV2) {
1361 tolV2 += P02.Distance(PV22);
1362 B.UpdateVertex(NewV2,tolV2);
1363 if(V22.Orientation()==NewV2.Orientation()) {
1364 myContext->Replace(V22,NewV2);
1365 V22 = NewV2;
1366 }
1367 else {
1368 myContext->Replace(V22,NewV2.Reversed());
1369 V22 = TopoDS::Vertex(NewV2.Reversed());
1370 }
1371 nbReplaced++; //gka 06.09.04
1372 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV2);
1373 myContext->Replace(edge2,NewE);
1374 sewd->Set(NewE,num2+dnum1);
1375 boxes.Bind(NewE,B2); // update boxes
1376 edge2 = NewE;
1377 akey2 = 2;
1378 }
1379 Standard_Integer dnum2=0, numseg2=num2+dnum1;
1380 // split
1381 if( akey1==0 && akey2>0 ) {
1382 if(SplitEdge1(sewd, face, num2+dnum1, p21, NewV1, tolV1, boxes)) {
1383 NbSplit++;
1384 dnum2=1;
1385 //numseg2=num2+dnum1+1;
1386 numseg2=num2+dnum1;
1387 }
1388 }
1389 if( akey1>0 && akey2==0 ) {
1390 if(SplitEdge1(sewd, face, num2+dnum1, p22, NewV2, tolV2, boxes)) {
1391 NbSplit++;
1392 dnum2=1;
1393 //numseg2=num2+dnum1;
1394 numseg2=num2+dnum1+1;
1395 }
1396 }
1397 if( akey1==0 && akey2==0 ) {
1398 if(SplitEdge1(sewd, face, num2+dnum1, p21, NewV1, tolV1, boxes)) {
1399 NbSplit++;
1400 dnum2=1;
1401 }
1402 tmpE = sewd->Edge(num2+dnum1);
1403 Standard_Real a,b;
1404 Handle(Geom2d_Curve) c2d;
1405 sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1406 if( (a-p22)*(b-p22)>0 ) { // p22 - external for [a,b] => split next edge
1407 if(SplitEdge1(sewd, face, num2+dnum1+dnum2, p22, NewV2, tolV2, boxes) ) {
1408 NbSplit++;
1409 numseg2=num2+dnum1+dnum2;
1410 dnum2++;
1411 }
1412 }
1413 else {
1414 if(SplitEdge1(sewd, face, num2+dnum1, p22, NewV2, tolV2, boxes) ) {
1415 NbSplit++;
1416 dnum2++;
1417 numseg2=num2+dnum1+1;
1418 }
1419 }
1420 }
1421 // remove segment
1422 sewd->Remove(numseg2);
1423 sewd->Remove(numseg1);
1424 NbRemoved = NbRemoved+2;
1425 //num1--;
1426 //break;
1427 }
1428 }
1429 }
1430 }
1431 }
1432 }
1433 }
1434 isDone = (NbSplit || NbCut || nbReplaced || NbRemoved);
1435 return isDone;
1436}
1437
1438
1439//=======================================================================
1440//function : FixIntersectingWires
1441//purpose :
1442//=======================================================================
1443
1444Standard_Boolean ShapeFix_IntersectionTool::FixIntersectingWires
1445 (TopoDS_Face& face) const
1446{
1447 if(myContext.IsNull() || face.IsNull()) return Standard_False;
1448 //TopoDS_Shape S = context->Apply(face);
1449 //TopoDS_Shape SF = TopoDS::Face(S);
1450 TopoDS_Shape SF = face;
1451 TopAbs_Orientation ori = face.Orientation();
1452 TopTools_SequenceOfShape SeqWir;
1453 TopTools_SequenceOfShape SeqNMShapes;
1454 for( TopoDS_Iterator iter(SF,Standard_False); iter.More(); iter.Next() ) {
1455 if(iter.Value().ShapeType() != TopAbs_WIRE ||
1456 (iter.Value().Orientation() != TopAbs_FORWARD &&
1457 iter.Value().Orientation() != TopAbs_REVERSED)) {
1458 SeqNMShapes.Append(iter.Value());
1459 continue;
1460 }
1461 TopoDS_Wire wire = TopoDS::Wire(iter.Value());
1462 SeqWir.Append(wire);
1463 }
1464 if(SeqWir.Length()<2) return Standard_False;//gka 06.09.04
1465
1466 Standard_Real MaxTolVert=0.0;
1467 for(TopExp_Explorer exp(SF,TopAbs_VERTEX); exp.More(); exp.Next()) {
1468 Standard_Real tolV = BRep_Tool::Tolerance(TopoDS::Vertex(exp.Current()));
1469 MaxTolVert = Max(MaxTolVert,tolV);
1470 }
1471 Standard_Boolean isDone = Standard_False; //gka 06.09.04
1472 ShapeAnalysis_Edge sae;
7c8090aa 1473 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface (BRep_Tool::Surface (face));
1474
1475 // precompute edge boxes for all wires
1476 NCollection_Sequence<ShapeFix_DataMapOfShapeBox2d> aSeqWirEdgeBoxes;
1477 NCollection_Sequence<Bnd_Box2d> aSeqWirBoxes;
1478 for (Standard_Integer n = 1; n <= SeqWir.Length(); n++)
1479 {
1480 const TopoDS_Wire& aWire = TopoDS::Wire (SeqWir.Value (n));
1481 Handle(ShapeExtend_WireData) aSewd = new ShapeExtend_WireData (aWire);
1482 ShapeFix_DataMapOfShapeBox2d aBoxes;
1483 Bnd_Box2d aTotalBox = CreateBoxes2d (aSewd, face, aBoxes);
1484 aSeqWirEdgeBoxes.Append (aBoxes);
1485 aSeqWirBoxes.Append (aTotalBox);
1486 }
7fd59977 1487
1488 for(Standard_Integer n1=1; n1<=SeqWir.Length()-1; n1++) {
1489 TopoDS_Wire wire1 = TopoDS::Wire(SeqWir.Value(n1));
1490 Handle(ShapeExtend_WireData) sewd1 = new ShapeExtend_WireData(wire1);
7c8090aa 1491 ShapeFix_DataMapOfShapeBox2d& boxes1 = aSeqWirEdgeBoxes.ChangeValue (n1);
1492 Bnd_Box2d aBox1 = aSeqWirBoxes (n1);
7fd59977 1493 for(Standard_Integer n2=n1+1; n2<=SeqWir.Length(); n2++) {
1494 TopoDS_Wire wire2 = TopoDS::Wire(SeqWir.Value(n2));
1495 Handle(ShapeExtend_WireData) sewd2 = new ShapeExtend_WireData(wire2);
7c8090aa 1496 ShapeFix_DataMapOfShapeBox2d& boxes2 = aSeqWirEdgeBoxes.ChangeValue (n2);
1497 Bnd_Box2d aBox2 = aSeqWirBoxes (n2);
1498 if (!aBox1.IsVoid() && !aBox2.IsVoid() && aBox1.IsOut (aBox2))
1499 {
1500 continue;
1501 }
7fd59977 1502 // detect possible intersections:
7fd59977 1503 Standard_Integer NbModif=0;
1504 Standard_Integer nbReplaced =0;//gka 06.09.04
1505 Standard_Boolean hasModifWire = Standard_False; //gka 06.09.04
1506 for(Standard_Integer num1 = 1; num1<=sewd1->NbEdges() && NbModif<30; num1++) {
1507 // for each edge from first wire
1508 TopoDS_Edge edge1 = sewd1->Edge(num1); //gka 06.09.04
1509
1510 for(Standard_Integer num2 = 1; num2<=sewd2->NbEdges() && NbModif<30; num2++) {
1511 // for each edge from second wire
1512 TopoDS_Edge edge2 = sewd2->Edge(num2);
1513 if(edge1.IsSame(edge2)) continue;
1514 if( BRep_Tool::Degenerated(edge1) || BRep_Tool::Degenerated(edge2) ) continue;
1515 if( !boxes1.IsBound(edge1) || !boxes2.IsBound(edge2) ) continue;
1516 Bnd_Box2d B1 = boxes1.Find(edge1);
1517 Bnd_Box2d B2 = boxes2.Find(edge2);
1518 if(!B1.IsOut(B2)) {
1519 // intersection is possible...
1520 Standard_Real a1, b1, a2, b2;
1521 Handle(Geom2d_Curve) Crv1, Crv2;
1522 if( !sae.PCurve(edge1, face, Crv1, a1, b1, Standard_False) )
1523 continue; //return Standard_False; gka 06.09.04
1524 if( !sae.PCurve(edge2, face, Crv2, a2, b2, Standard_False) )
1525 continue; //return Standard_False;gka 06.09.04
1526 Standard_Real tolint = 1.0e-10;
7fd59977 1527 Geom2dAdaptor_Curve C1(Crv1), C2(Crv2);
94f71cad 1528 IntRes2d_Domain d1(C1.Value(a1),a1,tolint,C1.Value(b1),b1,tolint);
1529 IntRes2d_Domain d2(C2.Value(a2),a2,tolint,C2.Value(b2),b2,tolint);
7fd59977 1530 Geom2dInt_GInter Inter;
1531 Inter.Perform( C1, d1, C2, d2, tolint, tolint );
1532 if(!Inter.IsDone()) continue;
1533 // intersection is point
1534 if( Inter.NbPoints()>0 && Inter.NbPoints()<3 ) {
1535 IntRes2d_IntersectionPoint IP;
1536 IntRes2d_Transition Tr1, Tr2;
1537 SelectIntPnt(Inter,IP,Tr1,Tr2);
1538 if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
1539 Tr2.PositionOnCurve() == IntRes2d_Middle ) {
1540 // create new vertex and split both edges
1541 Standard_Real param1 = IP.ParamOnFirst();
1542 Standard_Real param2 = IP.ParamOnSecond();
94f71cad 1543 gp_Pnt pi1 = GetPointOnEdge(edge1,sas,C1,param1);
1544 gp_Pnt pi2 = GetPointOnEdge(edge2,sas,C2,param2);
7fd59977 1545 gp_Pnt P0( (pi1.X()+pi2.X())/2, (pi1.Y()+pi2.Y())/2, (pi1.Z()+pi2.Z())/2 );
1546 BRep_Builder B;
1547 TopoDS_Vertex V;
1548 Standard_Real tolV = Max( (pi1.Distance(pi2)/2)*1.00001, Precision::Confusion() );
1549 B.MakeVertex(V,P0,tolV);
1550 MaxTolVert = Max(MaxTolVert,tolV);
1551 Standard_Boolean isSplitEdge2 = SplitEdge1(sewd2, face, num2, param2,
1552 V, tolV, boxes2);
1553 if(isSplitEdge2) {
1554 NbModif++;
1555 num2--;
1556 }
1557 if(SplitEdge1(sewd1, face, num1, param1, V, tolV, boxes1)) {
1558 NbModif++;
1559 num1--;
1560 break;
1561 }
1562 if(isSplitEdge2)
1563 continue;
1564 }
1565 if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
1566 Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1567 // find needed vertex from edge2 and split edge1 using it
1568 Standard_Real param1 = IP.ParamOnFirst();
1569 if(FindVertAndSplitEdge(param1, edge1, edge2, Crv1, MaxTolVert,
1570 num1, sewd1, face, boxes1, Standard_True) ) {
1571 NbModif++;
1572 break;
1573 }
1574 }
1575 if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1576 Tr2.PositionOnCurve() == IntRes2d_Middle ) {
1577 // find needed vertex from edge1 and split edge2 using it
1578 Standard_Real param2 = IP.ParamOnSecond();
1579 if(FindVertAndSplitEdge(param2, edge2, edge1, Crv2, MaxTolVert,
1580 num2, sewd2, face, boxes2, Standard_True) ) {
1581 NbModif++;
1582 continue;
1583 }
1584 }
1585 if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1586 Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1587 // union vertexes
1588 if( UnionVertexes(sewd2, edge1, edge2, num2, boxes2, B2) )
1589 nbReplaced ++; //gka 06.09.04
1590 }
1591 }
1592 hasModifWire = (hasModifWire || NbModif || nbReplaced);
1593 // intersection is segment
1594 if( Inter.NbSegments()==1 ) {
1595 IntRes2d_IntersectionSegment IS = Inter.Segment(1);
1596 if ( IS.HasFirstPoint() && IS.HasLastPoint() ) {
1597 Standard_Boolean IsModified1 = Standard_False;
1598 Standard_Boolean IsModified2 = Standard_False;
1599 TopoDS_Vertex NewV;
1600 BRep_Builder B;
1601 Standard_Real newtol=0.0;
1602 IntRes2d_IntersectionPoint IPF = IS.FirstPoint();
1603 Standard_Real p11 = IPF.ParamOnFirst();
1604 Standard_Real p21 = IPF.ParamOnSecond();
1605 IntRes2d_IntersectionPoint IPL = IS.LastPoint();
1606 Standard_Real p12 = IPL.ParamOnFirst();
1607 Standard_Real p22 = IPL.ParamOnSecond();
94f71cad 1608 gp_Pnt Pnt11 = GetPointOnEdge(edge1,sas,C1,p11);
1609 gp_Pnt Pnt12 = GetPointOnEdge(edge1,sas,C1,p12);
1610 gp_Pnt Pnt21 = GetPointOnEdge(edge2,sas,C2,p21);
1611 gp_Pnt Pnt22 = GetPointOnEdge(edge2,sas,C2,p22);
7fd59977 1612
1613 // analysis for edge1
1614 TopoDS_Vertex V1 = sae.FirstVertex(edge1);
1615 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
1616 TopoDS_Vertex V2 = sae.LastVertex(edge1);
1617 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
1618 Standard_Real dist1 = Pnt11.Distance(PV1);
1619 Standard_Real dist2 = Pnt12.Distance(PV1);
1620 Standard_Real maxdist = Max(dist1,dist2);
1621 Standard_Real pdist;
1622 if(edge1.Orientation()==TopAbs_REVERSED)
1623 pdist = Max(Abs(b1-p11),Abs(b1-p12));
1624 else
1625 pdist = Max(Abs(a1-p11),Abs(a1-p12));
1626 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1627 newtol = maxdist;
1628 NewV = V1;
1629 IsModified1 = Standard_True;
1630 }
1631 dist1 = Pnt11.Distance(PV2);
1632 dist2 = Pnt12.Distance(PV2);
1633 maxdist = Max(dist1,dist2);
1634 if(edge1.Orientation()==TopAbs_REVERSED)
1635 pdist = Max(Abs(a1-p11),Abs(a1-p12));
1636 else
1637 pdist = Max(Abs(b1-p11),Abs(b1-p12));
1638 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1639 if( ( IsModified1 && maxdist<newtol ) || !IsModified1 ) {
1640 newtol = maxdist;
1641 NewV = V2;
1642 IsModified1 = Standard_True;
1643 }
1644 }
1645 if(IsModified1) {
1646 // cut edge1 and update tolerance NewV
1647 Standard_Real dista = Abs(a1-p11)+Abs(a1-p12);
1648 Standard_Real distb = Abs(b1-p11)+Abs(b1-p12);
1649 Standard_Real pend,cut;
1650 if(dista>distb) pend=a1;
1651 else pend=b1;
1652 if(Abs(pend-p11)>Abs(pend-p12)) cut=p12;
1653 else cut=p11;
1654 Standard_Boolean IsCutLine;
0d3d226e 1655 if(!CutEdge(edge1, pend, cut, face, IsCutLine))
1656 {
1657 IsModified1 = Standard_False;
1658 continue;
1659 }
7fd59977 1660 if(newtol>BRep_Tool::Tolerance(NewV)) {
1661 B.UpdateVertex(NewV,newtol*1.00001);
1662 }
1663 }
1664
1665 // analysis for edge2
1666 TopoDS_Vertex V12 = sae.FirstVertex(edge2);
1667 gp_Pnt PV12 = BRep_Tool::Pnt(V12);
1668 TopoDS_Vertex V22 = sae.LastVertex(edge2);
1669 gp_Pnt PV22 = BRep_Tool::Pnt(V22);
1670 dist1 = Pnt21.Distance(PV12);
1671 dist2 = Pnt22.Distance(PV12);
1672 maxdist = Max(dist1,dist2);
1673 if(edge2.Orientation()==TopAbs_REVERSED)
1674 pdist = Max(Abs(b2-p21),Abs(b2-p22));
1675 else
1676 pdist = Max(Abs(a2-p21),Abs(a2-p22));
1677 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1678 newtol = maxdist;
1679 NewV = V12;
1680 IsModified2 = Standard_True;
1681 }
1682 dist1 = Pnt21.Distance(PV22);
1683 dist2 = Pnt22.Distance(PV22);
1684 maxdist = Max(dist1,dist2);
1685 if(edge2.Orientation()==TopAbs_REVERSED)
1686 pdist = Max(Abs(a2-p21),Abs(a2-p22));
1687 else
1688 pdist = Max(Abs(b2-p21),Abs(b2-p22));
1689 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1690 if( ( IsModified2 && maxdist<newtol ) || !IsModified2 ) {
1691 newtol = maxdist;
1692 NewV = V22;
1693 IsModified2 = Standard_True;
1694 }
1695 }
1696 if(IsModified2) {
1697 // cut edge1 and update tolerance NewV
1698 Standard_Real dista = Abs(a2-p21)+Abs(a2-p22);
1699 Standard_Real distb = Abs(b2-p21)+Abs(b2-p22);
1700 Standard_Real pend,cut;
1701 if(dista>distb) pend=a2;
1702 else pend=b2;
1703 if(Abs(pend-p21)>Abs(pend-p22)) cut=p22;
1704 else cut=p21;
1705 Standard_Boolean IsCutLine;
0d3d226e 1706 if(!CutEdge(edge2, pend, cut, face, IsCutLine))
1707 {
1708 IsModified2 = Standard_False;
1709 continue;
1710
1711 }
7fd59977 1712 if(newtol>BRep_Tool::Tolerance(NewV)) {
1713 B.UpdateVertex(NewV,newtol*1.00001);
1714 }
1715 }
1716
1717 if( IsModified1 || IsModified2 ) {
0d3d226e 1718 //necessary to make intersect with the same pair of the edges once again with modified ranges
1719 num2--;
7fd59977 1720 hasModifWire = Standard_True; //gka 06.09.04
1721 continue;
1722 }
1723 else {
1724 // create new vertex and split edge1 and edge2 using it
1725 if( Abs(p12-p11)>Abs(b1-a1)/2 || Abs(p22-p21)>Abs(b2-a2)/2 ) {
1726 // segment is big and we have to split each intersecting edge
1727 // on 3 edges --> middle edge - edge based on segment
1728 gp_Pnt P01( (Pnt11.X()+Pnt21.X())/2, (Pnt11.Y()+Pnt21.Y())/2,
1729 (Pnt11.Z()+Pnt21.Z())/2 );
1730 gp_Pnt P02( (Pnt12.X()+Pnt22.X())/2, (Pnt12.Y()+Pnt22.Y())/2,
1731 (Pnt12.Z()+Pnt22.Z())/2 );
1732 Standard_Real tolV1 = Max(Pnt11.Distance(P01),Pnt21.Distance(P01));
1733 tolV1 = Max(tolV1,Precision::Confusion())*1.00001;
1734 Standard_Real tolV2 = Max(Pnt12.Distance(P02),Pnt22.Distance(P02));
1735 tolV2 = Max(tolV2,Precision::Confusion())*1.00001;
1736 if( tolV1>MaxTolVert || tolV2>MaxTolVert ) continue;
1737
1738 hasModifWire = Standard_True; //gka 06.09.04
1739 TopoDS_Vertex NewV1,NewV2;
1740 TopoDS_Edge tmpE,SegE;
1741 // split edge1
1742 Standard_Integer akey1=0, akey2=0;
1743 // analysis fo P01
1744 if(P01.Distance(PV1)<Max(tolV1,BRep_Tool::Tolerance(V1))) {
1745 NewV1 = V1;
1746 if(tolV1>BRep_Tool::Tolerance(V1))
1747 B.UpdateVertex(NewV1,tolV1);
1748 akey1++;
1749 }
1750 if(P01.Distance(PV2)<Max(tolV1,BRep_Tool::Tolerance(V2))) {
1751 NewV1 = V2;
1752 if(tolV1>BRep_Tool::Tolerance(V2))
1753 B.UpdateVertex(NewV1,tolV1);
1754 akey1++;
1755 }
1756 // analysis fo P02
1757 if(P02.Distance(PV1)<Max(tolV2,BRep_Tool::Tolerance(V1))) {
1758 NewV2 = V1;
1759 if(tolV2>BRep_Tool::Tolerance(V1))
1760 B.UpdateVertex(NewV2,tolV2);
1761 akey2++;
1762 }
1763 if(P02.Distance(PV2)<Max(tolV2,BRep_Tool::Tolerance(V2))) {
1764 NewV2 = V2;
1765 if(tolV2>BRep_Tool::Tolerance(V2))
1766 B.UpdateVertex(NewV2,tolV2);
1767 akey2++;
1768 }
1769 if( akey1>1 || akey2>1 ) continue;
1770 // prepare vertices
1771 if(akey1==0) B.MakeVertex(NewV1,P01,tolV1);
1772 if(akey2==0) B.MakeVertex(NewV2,P02,tolV2);
1773 // split
1774 Standard_Integer numseg1=num1;
1775 if( akey1==0 && akey2>0 ) {
1776 if(SplitEdge1(sewd1, face, num1, p11, NewV1, tolV1, boxes1)) {
1777 NbModif++;
1778 numseg1=num1+1;
1779 }
1780 }
1781 if( akey1>0 && akey2==0 ) {
1782 if(SplitEdge1(sewd1, face, num1, p12, NewV2, tolV2, boxes1) ) {
1783 NbModif++;
1784 numseg1=num1;
1785 }
1786 }
1787 if( akey1==0 && akey2==0 ) {
1788 if(SplitEdge1(sewd1, face, num1, p11, NewV1, tolV1, boxes1)) {
1789 NbModif++;
1790 }
1791 tmpE = sewd1->Edge(num1);
1792 Standard_Real a,b;
1793 Handle(Geom2d_Curve) c2d;
1794 sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1795 if( (a-p12)*(b-p12)>0 ) { // p12 - external for [a,b] => split next edge
1796 if(SplitEdge1(sewd1, face, num1+1, p12, NewV2, tolV2, boxes1) ) {
1797 NbModif++;
1798 numseg1=num1+1;
1799 }
1800 }
1801 else {
1802 if(SplitEdge1(sewd1, face, num1, p12, NewV2, tolV2, boxes1) ) {
1803 NbModif++;
1804 numseg1=num1+1;
1805 }
1806 }
1807 }
1808 SegE = sewd1->Edge(numseg1); // get edge from segment
1809 // split edge2
1810 // replace vertices if it is necessary
1811 ShapeBuild_Edge sbe;
1812 akey1=0, akey2=0;
1813 if(P01.Distance(PV12)<tolV1) {
1814 tolV1 += P01.Distance(PV12);
1815 B.UpdateVertex(NewV1,tolV1);
1816 V12 = NewV1;
1817 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV1,V22);
1818 myContext->Replace(edge2,NewE);
1819 sewd2->Set(NewE,num2);
1820 boxes2.Bind(NewE,B2); // update boxes2
1821 edge2 = NewE;
1822 akey1 = 1;
1823 }
1824 if(P01.Distance(PV22)<tolV1) {
1825 tolV1 += P01.Distance(PV22);
1826 B.UpdateVertex(NewV1,tolV1);
1827 V22 = NewV1;
1828 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV1);
1829 myContext->Replace(edge2,NewE);
1830 sewd2->Set(NewE,num2);
1831 boxes2.Bind(NewE,B2); // update boxes2
1832 edge2 = NewE;
1833 akey1 = 2;
1834 }
1835 if(P02.Distance(PV12)<tolV2) {
1836 tolV2 += P02.Distance(PV12);
1837 B.UpdateVertex(NewV2,tolV2);
1838 V12 = NewV2;
1839 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV2,V22);
1840 myContext->Replace(edge2,NewE);
1841 sewd2->Set(NewE,num2);
1842 boxes2.Bind(NewE,B2); // update boxes2
1843 edge2 = NewE;
1844 akey2 = 1;
1845 }
1846 if(P02.Distance(PV22)<tolV2) {
1847 tolV2 += P02.Distance(PV22);
1848 B.UpdateVertex(NewV2,tolV2);
1849 V22 = NewV2;
1850 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV2);
1851 myContext->Replace(edge2,NewE);
1852 sewd2->Set(NewE,num2);
1853 boxes2.Bind(NewE,B2); // update boxes2
1854 edge2 = NewE;
1855 akey2 = 2;
1856 }
1857 // split
1858 Standard_Integer numseg2=num2;
1859 if( akey1==0 && akey2>0 ) {
1860 if(SplitEdge1(sewd2, face, num2, p21, NewV1, tolV1, boxes2)) {
1861 NbModif++;
1862 numseg2=num2+1;
1863 }
1864 }
1865 if( akey1>0 && akey2==0 ) {
1866 if(SplitEdge1(sewd2, face, num2, p22, NewV2, tolV2, boxes2)) {
1867 NbModif++;
1868 numseg2=num2;
1869 }
1870 }
1871 if( akey1==0 && akey2==0 ) {
1872 if(SplitEdge1(sewd2, face, num2, p21, NewV1, tolV1, boxes2)) {
1873 NbModif++;
1874 numseg2=num2+1;
1875 }
1876 tmpE = sewd2->Edge(num2);
1877 Standard_Real a,b;
1878 Handle(Geom2d_Curve) c2d;
1879 sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1880 if( (a-p22)*(b-p22)>0 ) { // p22 - external for [a,b] => split next edge
1881 if(SplitEdge1(sewd2, face, num2+1, p22, NewV2, tolV2, boxes2) ) {
1882 NbModif++;
1883 numseg2=num2+1;
1884 }
1885 }
1886 else {
1887 if(SplitEdge1(sewd2, face, num2, p22, NewV2, tolV2, boxes2) ) {
1888 NbModif++;
1889 numseg2=num2+1;
1890 }
1891 }
1892 }
1893 tmpE = sewd2->Edge(numseg2);
1894 boxes2.Bind(tmpE,boxes1.Find(SegE)); // update boxes2
1895 if(!sae.FirstVertex(SegE).IsSame(sae.FirstVertex(tmpE))) {
1896 SegE.Reverse();
1897 }
1898 myContext->Replace(tmpE,SegE);
1899 sewd2->Set(SegE,numseg2);
1900 num1--;
1901 break;
1902 }
1903 else {
1904 // split each intersecting edge on two edges
1905 gp_Pnt P0( (Pnt11.X()+Pnt12.X())/2, (Pnt11.Y()+Pnt12.Y())/2,
1906 (Pnt11.Z()+Pnt12.Z())/2 );
1907 Standard_Real param1 = (p11+p12)/2;
1908 Standard_Real param2 = (p21+p22)/2;
94f71cad 1909 gp_Pnt Pnt10 = GetPointOnEdge(edge1,sas,C1,param1);
1910 gp_Pnt Pnt20 = GetPointOnEdge(edge2,sas,C2,param2);
7fd59977 1911 dist1 = Max(Pnt11.Distance(P0),Pnt12.Distance(Pnt10));
1912 dist2 = Max(Pnt21.Distance(P0),Pnt22.Distance(Pnt10));
1913 Standard_Real tolV = Max(dist1,dist2);
1914 tolV = Max(tolV,Pnt10.Distance(Pnt20))*1.00001;
1915 B.MakeVertex(NewV,Pnt10,tolV);
1916 MaxTolVert = Max(MaxTolVert,tolV);
1917 hasModifWire = Standard_True;
1918 if(SplitEdge2(sewd2, face, num2, p21, p22, NewV, tolV, boxes2)) {
1919 NbModif++;
1920 num2--;
1921 }
1922 if(SplitEdge2(sewd1, face, num1, p11, p12, NewV, tolV, boxes1)) {
1923 NbModif++;
1924 num1--;
1925 break;
1926 }
1927 }
1928 }
1929 }
1930 } // end if(Inter.NbSegments()==1)
1931
1932 }
1933 }
1934 }
1935 if(hasModifWire) {
1936 isDone = Standard_True;
1937 SeqWir.SetValue(n1,sewd1->Wire());
1938 myContext->Replace( wire1, sewd1->Wire() );
1939 wire1 = sewd1->Wire();
7c8090aa 1940 //recompute boxes for wire1
1941 boxes1.Clear();
1942 Bnd_Box2d aNewBox1 = CreateBoxes2d (sewd1, face, boxes1);
1943 aSeqWirBoxes.SetValue (n1, aNewBox1);
7fd59977 1944 SeqWir.SetValue(n2,sewd2->Wire());
1945 myContext->Replace( wire2, sewd2->Wire() );
1946 wire2 = sewd2->Wire();
7c8090aa 1947 //recompute boxes for wire2
1948 boxes2.Clear();
1949 Bnd_Box2d aNewBox2 = CreateBoxes2d (sewd2, face, boxes2);
1950 aSeqWirBoxes.SetValue (n2, aNewBox2);
7fd59977 1951 }
1952
1953 }
1954 }
1955
1956 if(isDone) {
1957 // update face
1958 TopoDS_Shape emptyCopied = face.EmptyCopied();
1959 TopoDS_Face newface = TopoDS::Face (emptyCopied);
1960 newface.Orientation(TopAbs_FORWARD);
1961 BRep_Builder B;
1962 Standard_Integer i=1;
9cbe6290 1963 for(i=1 ; i<=SeqWir.Length(); i++) {
7fd59977 1964 TopoDS_Wire wire = TopoDS::Wire(SeqWir.Value(i));
1965 B.Add(newface,wire);
1966 }
9cbe6290 1967 for(i=1 ; i<=SeqNMShapes.Length(); i++) {
7fd59977 1968 TopoDS_Shape aNMS = SeqNMShapes.Value(i);
1969 B.Add(newface,aNMS);
1970 }
1971 newface.Orientation(ori);
1972 myContext->Replace(face,newface);
1973 face = newface;
1974 }
1975 return isDone;
1976}
1977