1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
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
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.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
15 #include <Bnd_Box2d.hxx>
16 #include <BndLib_Add2dCurve.hxx>
17 #include <BRep_Builder.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepTools.hxx>
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>
26 #include <Geom_Curve.hxx>
27 #include <Geom_Surface.hxx>
28 #include <GeomAdaptor_Curve.hxx>
29 #include <GeomAdaptor_HSurface.hxx>
31 #include <IntRes2d_Domain.hxx>
32 #include <IntRes2d_IntersectionPoint.hxx>
33 #include <IntRes2d_IntersectionSegment.hxx>
34 #include <IntRes2d_Position.hxx>
35 #include <NCollection_Sequence.hxx>
36 #include <ShapeAnalysis.hxx>
37 #include <ShapeAnalysis_Edge.hxx>
38 #include <ShapeAnalysis_Surface.hxx>
39 #include <ShapeAnalysis_TransferParametersProj.hxx>
40 #include <ShapeBuild_Edge.hxx>
41 #include <ShapeBuild_ReShape.hxx>
42 #include <ShapeExtend_WireData.hxx>
43 #include <ShapeFix_DataMapOfShapeBox2d.hxx>
44 #include <ShapeFix_IntersectionTool.hxx>
45 #include <TopExp_Explorer.hxx>
47 #include <TopoDS_Edge.hxx>
48 #include <TopoDS_Face.hxx>
49 #include <TopoDS_Iterator.hxx>
50 #include <TopoDS_Vertex.hxx>
51 #include <TopoDS_Wire.hxx>
52 #include <TopTools_SequenceOfShape.hxx>
54 //gka 06.09.04 BUG 6555 shape is modified always independently either intersection was fixed or not
55 //=======================================================================
56 //function : ShapeFix_IntersectionTool
58 //=======================================================================
59 ShapeFix_IntersectionTool::ShapeFix_IntersectionTool(const Handle(ShapeBuild_ReShape)& context,
60 const Standard_Real preci,
61 const Standard_Real maxtol)
69 //=======================================================================
70 //function : GetPointOnEdge
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 //=======================================================================
75 static gp_Pnt GetPointOnEdge(const TopoDS_Edge &edge,
76 const Handle(ShapeAnalysis_Surface) &surf,
77 const Geom2dAdaptor_Curve &Crv2d,
78 const Standard_Real param )
80 if( BRep_Tool::SameParameter(edge) ) {
83 const Handle(Geom_Curve) ConS = BRep_Tool::Curve ( edge, L, f, l );
85 return ConS->Value(param).Transformed(L.Transformation());
87 gp_Pnt2d aP2d = Crv2d.Value(param);
88 return surf->Adaptor3d()->Value(aP2d.X(), aP2d.Y());
92 //=======================================================================
93 //function : SplitEdge
95 //=======================================================================
97 Standard_Boolean ShapeFix_IntersectionTool::SplitEdge(const TopoDS_Edge& edge,
98 const Standard_Real param,
99 const TopoDS_Vertex& vert,
100 const TopoDS_Face& face,
103 const Standard_Real preci) const
106 ShapeAnalysis_Edge sae;
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;
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
120 if(BRep_Tool::SameParameter(edge) && !BRep_Tool::Degenerated(edge)) {
122 const Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,L,f,l);
124 return Standard_False;
125 P1 = c3d->Value(param);
126 if(!L.IsIdentity()) P1 = P1.Transformed(L.Transformation());
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());
134 gp_Pnt P2 = BRep_Tool::Pnt(vert);
135 if(P1.Distance(P2)>preci) {
136 //return Standard_False;
138 B.UpdateVertex(vert,P1.Distance(P2));
141 Handle(ShapeAnalysis_TransferParametersProj) transferParameters =
142 new ShapeAnalysis_TransferParametersProj;
143 transferParameters->SetMaxTolerance(preci);
144 transferParameters->Init(edge,face);
145 Standard_Real first, last;
156 TopAbs_Orientation orient = edge.Orientation();
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);
173 newE1.Orientation(orient);
174 newE2.Orientation(orient);
175 if (orient==TopAbs_REVERSED) {
176 TopoDS_Edge tmp = newE2; newE2 = newE1; newE1=tmp;
179 return Standard_True;
183 //=======================================================================
186 //=======================================================================
188 Standard_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
194 if( Abs(cut-pend)<10.*Precision::PConfusion() ) return Standard_False;
195 Standard_Real aRange = Abs(cut-pend);
197 BRep_Tool::Range(edge, a, b);
199 if( aRange<10.*Precision::PConfusion() ) return Standard_False;
201 // case pcurve is trimm of line
202 if( !BRep_Tool::SameParameter(edge) ) {
203 ShapeAnalysis_Edge sae;
204 Handle(Geom2d_Curve) Crv;
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))) {
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;
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;
224 return Standard_True;
228 return Standard_False;
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;
236 B.Range( edge, Min(pend,cut), Max(pend,cut) );
238 return Standard_True;
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 //=======================================================================
248 Standard_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
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;
261 Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData;
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);
271 sewd->Set(newE1,num);
272 if(num==sewd->NbEdges())
275 sewd->Add(newE2,num+1);
280 const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L);
281 Handle(Geom2d_Curve) c2d;
283 ShapeAnalysis_Edge sae;
284 if(sae.PCurve(newE1,S,L,c2d,cf,cl,Standard_False)) {
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
296 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
297 boxes.Bind(newE1,box);
299 if(sae.PCurve(newE2,S,L,c2d,cf,cl,Standard_False)) {
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
311 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
312 boxes.Bind(newE2,box);
315 return Standard_True;
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 //=======================================================================
326 Standard_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
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 )) {
347 if( (lp1-fp1)*(lp1-param1)>0 ) {
348 CutEdge(newE1, fp1, param1, face, IsCutLine);
349 CutEdge(newE2, lp2, param2, face, IsCutLine);
352 CutEdge(newE1, fp1, param2, face, IsCutLine);
353 CutEdge(newE2, lp2, param1, face, IsCutLine);
357 if( (fp1-lp1)*(fp1-param1)>0 ) {
358 CutEdge(newE1, lp1, param1, face, IsCutLine);
359 CutEdge(newE2, fp2, param2, face, IsCutLine);
362 CutEdge(newE1, lp1, param2, face, IsCutLine);
363 CutEdge(newE2, fp2, param1, face, IsCutLine);
370 Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData;
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);
380 sewd->Set(newE1,num);
381 if(num==sewd->NbEdges())
384 sewd->Add(newE2,num+1);
389 const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L);
390 Handle(Geom2d_Curve) c2d;
392 if(sae.PCurve(newE1,S,L,c2d,cf,cl,Standard_False)) {
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
404 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
405 boxes.Bind(newE1,box);
407 if(sae.PCurve(newE2,S,L,c2d,cf,cl,Standard_False)) {
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
419 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
420 boxes.Bind(newE2,box);
423 return Standard_True;
427 //=======================================================================
428 //function : UnionVertexes
430 //=======================================================================
432 Standard_Boolean ShapeFix_IntersectionTool::UnionVertexes(const Handle(ShapeExtend_WireData)& sewd,
435 const Standard_Integer num2,
436 ShapeFix_DataMapOfShapeBox2d& boxes,
437 const Bnd_Box2d& B2) const
440 Standard_Boolean res = Standard_False;
442 ShapeAnalysis_Edge sae;
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);
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;
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 if (boxes.IsBound(edge21))
489 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
490 myContext->Replace(edge21,NewE);
491 sewd->Set(NewE,num21);
493 if(V21L.IsSame(V2F)) {
494 NewE = sbe.CopyReplaceVertices(edge21,V21F,V1F);
495 //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
496 if (boxes.IsBound(edge21))
497 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
498 myContext->Replace(edge21,NewE);
499 sewd->Set(NewE,num21);
501 if(V22F.IsSame(V2F)) {
502 NewE = sbe.CopyReplaceVertices(edge22,V1F,V22L);
503 //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
504 if (boxes.IsBound(edge22))
505 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
506 myContext->Replace(edge22,NewE);
507 sewd->Set(NewE,num22);
509 if(V22L.IsSame(V2F)) {
510 NewE = sbe.CopyReplaceVertices(edge22,V22F,V1F);
511 //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
512 if (boxes.IsBound(edge22))
513 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
514 myContext->Replace(edge22,NewE);
515 sewd->Set(NewE,num22);
520 else if(d12<d21 && d12<d22) {
521 Standard_Real tolv = Max(BRep_Tool::Tolerance(V1F),BRep_Tool::Tolerance(V2L));
522 if( !V2L.IsSame(V1F) && d12<tolv ) {
523 // union vertexes V1F and V2L
524 B.UpdateVertex(V1F,tolv);
525 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V1F);
526 // cout<<"union vertexes V1F and V2L"<<endl;
527 // gp_Pnt Ptmp = BRep_Tool::Pnt(V1F);
528 // B.MakeVertex(V,Ptmp,tolv);
529 // myContext->Replace(V1F,V);
530 // myContext->Replace(V2L,V);
531 // TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V);
532 myContext->Replace(edge2,NewE);
533 sewd->Set(NewE,num2);
535 //boxes.Bind(NewE,boxes.Find(edge2)); // update boxes
536 boxes.Bind(NewE,B2); // update boxes
537 // replace vertex in other edge
538 Standard_Integer num21,num22;
539 if(num2>1) num21=num2-1;
540 else num21=sewd->NbEdges();
541 if(num2<sewd->NbEdges()) num22=num2+1;
543 TopoDS_Edge edge21 = sewd->Edge(num21);
544 TopoDS_Edge edge22 = sewd->Edge(num22);
545 TopoDS_Vertex V21F = sae.FirstVertex(edge21);
546 TopoDS_Vertex V21L = sae.LastVertex(edge21);
547 TopoDS_Vertex V22F = sae.FirstVertex(edge22);
548 TopoDS_Vertex V22L = sae.LastVertex(edge22);
549 if(V21F.IsSame(V2L)) {
550 NewE = sbe.CopyReplaceVertices(edge21,V1F,V21L);
551 //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
552 if (boxes.IsBound(edge21))
553 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
554 myContext->Replace(edge21,NewE);
555 sewd->Set(NewE,num21);
557 if(V21L.IsSame(V2L)) {
558 NewE = sbe.CopyReplaceVertices(edge21,V21F,V1F);
559 //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
560 if (boxes.IsBound(edge21))
561 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
562 myContext->Replace(edge21,NewE);
563 sewd->Set(NewE,num21);
565 if(V22F.IsSame(V2L)) {
566 NewE = sbe.CopyReplaceVertices(edge22,V1F,V22L);
567 //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
568 if (boxes.IsBound(edge22))
569 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
570 myContext->Replace(edge22,NewE);
571 sewd->Set(NewE,num22);
573 if(V22L.IsSame(V2L)) {
574 NewE = sbe.CopyReplaceVertices(edge22,V22F,V1F);
575 //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
576 if (boxes.IsBound(edge22))
577 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
578 myContext->Replace(edge22,NewE);
579 sewd->Set(NewE,num22);
585 Standard_Real tolv = Max(BRep_Tool::Tolerance(V1L),BRep_Tool::Tolerance(V2F));
586 if( !V2F.IsSame(V1L) && d21<tolv ) {
587 // union vertexes V1L and V2F
588 B.UpdateVertex(V1L,tolv);
589 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V1L,V2L);
590 // cout<<"union vertexes V1L and V2F"<<endl;
591 // gp_Pnt Ptmp = BRep_Tool::Pnt(V1L);
592 // B.MakeVertex(V,Ptmp,tolv);
593 // myContext->Replace(V1L,V);
594 // myContext->Replace(V2F,V);
595 // TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V,V2L);
596 myContext->Replace(edge2,NewE);
597 sewd->Set(NewE,num2);
599 boxes.Bind(NewE,B2); // update boxes
600 // replace vertex in other edge
601 Standard_Integer num21,num22;
602 if(num2>1) num21=num2-1;
603 else num21=sewd->NbEdges();
604 if(num2<sewd->NbEdges()) num22=num2+1;
606 TopoDS_Edge edge21 = sewd->Edge(num21);
607 TopoDS_Edge edge22 = sewd->Edge(num22);
608 TopoDS_Vertex V21F = sae.FirstVertex(edge21);
609 TopoDS_Vertex V21L = sae.LastVertex(edge21);
610 TopoDS_Vertex V22F = sae.FirstVertex(edge22);
611 TopoDS_Vertex V22L = sae.LastVertex(edge22);
612 if(V21F.IsSame(V2F)) {
613 NewE = sbe.CopyReplaceVertices(edge21,V1L,V21L);
614 //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
615 if (boxes.IsBound(edge21))
616 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
617 myContext->Replace(edge21,NewE);
618 sewd->Set(NewE,num21);
620 if(V21L.IsSame(V2F)) {
621 NewE = sbe.CopyReplaceVertices(edge21,V21F,V1L);
622 //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
623 if (boxes.IsBound(edge21))
624 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
625 myContext->Replace(edge21,NewE);
626 sewd->Set(NewE,num21);
628 if(V22F.IsSame(V2F)) {
629 NewE = sbe.CopyReplaceVertices(edge22,V1L,V22L);
630 //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
631 if (boxes.IsBound(edge22))
632 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
633 myContext->Replace(edge22,NewE);
634 sewd->Set(NewE,num22);
636 if(V22L.IsSame(V2F)) {
637 NewE = sbe.CopyReplaceVertices(edge22,V22F,V1L);
638 //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
639 if (boxes.IsBound(edge22))
640 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
641 myContext->Replace(edge22,NewE);
642 sewd->Set(NewE,num22);
648 Standard_Real tolv = Max(BRep_Tool::Tolerance(V1L),BRep_Tool::Tolerance(V2L));
649 if( !V2L.IsSame(V1L) && d22<tolv ) {
650 // union vertexes V1L and V2L
651 B.UpdateVertex(V1L,tolv);
652 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V1L);
653 // cout<<"union vertexes V1L and V2L"<<endl;
654 // gp_Pnt Ptmp = BRep_Tool::Pnt(V1L);
655 // B.MakeVertex(V,Ptmp,tolv);
656 // myContext->Replace(V1L,V);
657 // myContext->Replace(V2L,V);
658 // TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V);
659 myContext->Replace(edge2,NewE);
660 sewd->Set(NewE,num2);
662 boxes.Bind(NewE,B2); // update boxes
663 // replace vertex in other edge
664 Standard_Integer num21,num22;
665 if(num2>1) num21=num2-1;
666 else num21=sewd->NbEdges();
667 if(num2<sewd->NbEdges()) num22=num2+1;
669 TopoDS_Edge edge21 = sewd->Edge(num21);
670 TopoDS_Edge edge22 = sewd->Edge(num22);
671 TopoDS_Vertex V21F = sae.FirstVertex(edge21);
672 TopoDS_Vertex V21L = sae.LastVertex(edge21);
673 TopoDS_Vertex V22F = sae.FirstVertex(edge22);
674 TopoDS_Vertex V22L = sae.LastVertex(edge22);
675 if(V21F.IsSame(V2L)) {
676 NewE = sbe.CopyReplaceVertices(edge21,V1L,V21L);
677 //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
678 if (boxes.IsBound(edge21))
679 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
680 myContext->Replace(edge21,NewE);
681 sewd->Set(NewE,num21);
683 if(V21L.IsSame(V2L)) {
684 NewE = sbe.CopyReplaceVertices(edge21,V21F,V1L);
685 //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
686 if (boxes.IsBound(edge21))
687 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
688 myContext->Replace(edge21,NewE);
689 sewd->Set(NewE,num21);
691 if(V22F.IsSame(V2L)) {
692 NewE = sbe.CopyReplaceVertices(edge22,V1L,V22L);
693 //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
694 if (boxes.IsBound(edge22))
695 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
696 myContext->Replace(edge22,NewE);
697 sewd->Set(NewE,num22);
699 if(V22L.IsSame(V2L)) {
700 NewE = sbe.CopyReplaceVertices(edge22,V22F,V1L);
701 //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
702 if (boxes.IsBound(edge22))
703 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
704 myContext->Replace(edge22,NewE);
705 sewd->Set(NewE,num22);
715 //=======================================================================
716 //function : CreateBoxes2d
718 //=======================================================================
719 static Bnd_Box2d CreateBoxes2d(const Handle(ShapeExtend_WireData)& sewd,
720 const TopoDS_Face& face,
721 ShapeFix_DataMapOfShapeBox2d& boxes)
723 // create box2d for edges from wire
726 const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L);
727 Handle(Geom2d_Curve) c2d;
729 ShapeAnalysis_Edge sae;
730 for(Standard_Integer i=1; i<=sewd->NbEdges(); i++){
731 TopoDS_Edge E = sewd->Edge(i);
732 if(sae.PCurve(E,S,L,c2d,cf,cl,Standard_False)) {
734 Geom2dAdaptor_Curve gac;
735 Standard_Real aFirst = c2d->FirstParameter();
736 Standard_Real aLast = c2d->LastParameter();
737 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
738 && (cf < aFirst || cl > aLast)) {
739 //pdn avoiding problems with segment in Bnd_Box
744 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
753 //=======================================================================
754 //function : SelectIntPnt
756 //=======================================================================
757 static void SelectIntPnt(const Geom2dInt_GInter& Inter,
758 IntRes2d_IntersectionPoint& IP,
759 IntRes2d_Transition& Tr1,
760 IntRes2d_Transition& Tr2)
763 Tr1 = IP.TransitionOfFirst();
764 Tr2 = IP.TransitionOfSecond();
765 if(Inter.NbPoints()==2) {
766 // possible second point is better?
767 Standard_Integer status1=0,status2=0;
768 if(Tr1.PositionOnCurve()==IntRes2d_Middle) status1+=1;
769 if(Tr2.PositionOnCurve()==IntRes2d_Middle) status1+=2;
770 IntRes2d_IntersectionPoint IP2;
771 IntRes2d_Transition Tr12, Tr22;
772 IP2 = Inter.Point(2);
773 Tr12 = IP2.TransitionOfFirst();
774 Tr22 = IP2.TransitionOfSecond();
775 if(Tr12.PositionOnCurve()==IntRes2d_Middle) status2+=1;
776 if(Tr22.PositionOnCurve()==IntRes2d_Middle) status2+=2;
777 if(status2>status1) {
778 IP=IP2; Tr1=Tr12; Tr2=Tr22;
784 //=======================================================================
785 //function : FindVertAndSplitEdge
787 //=======================================================================
788 Standard_Boolean ShapeFix_IntersectionTool::FindVertAndSplitEdge
789 (const Standard_Real param1,
790 const TopoDS_Edge& edge1, const TopoDS_Edge& edge2,
791 const Handle(Geom2d_Curve)& Crv1,
792 Standard_Real& MaxTolVert,
793 Standard_Integer& num1,
794 const Handle(ShapeExtend_WireData)& sewd,
795 const TopoDS_Face& face,
796 ShapeFix_DataMapOfShapeBox2d& boxes,
797 const Standard_Boolean aTmpKey) const
799 // find needed vertex from edge2 and split edge1 using it
800 ShapeAnalysis_Edge sae;
801 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(BRep_Tool::Surface(face));
802 gp_Pnt pi1 = GetPointOnEdge(edge1,sas,Crv1,param1);
806 TopoDS_Vertex V1 = sae.FirstVertex(edge2);
807 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
808 TopoDS_Vertex V2 = sae.LastVertex(edge2);
809 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
810 TopoDS_Vertex V11 = sae.FirstVertex(edge1);
811 TopoDS_Vertex V12 = sae.LastVertex(edge1);
812 Standard_Boolean NeedSplit = Standard_True;
813 if(pi1.Distance(PV1)<pi1.Distance(PV2)) {
814 if( V1.IsSame(V11) || V1.IsSame(V12) ) {
815 NeedSplit = Standard_False;
818 tolV = Max( (pi1.Distance(PV1)/2)*1.00001, BRep_Tool::Tolerance(V1) );
821 if( V2.IsSame(V11) || V2.IsSame(V12) ) {
822 NeedSplit = Standard_False;
825 tolV = Max( (pi1.Distance(PV2)/2)*1.00001, BRep_Tool::Tolerance(V2) );
827 if( NeedSplit || aTmpKey ) {
828 if(SplitEdge1(sewd, face, num1, param1, V, tolV, boxes)) {
829 B.UpdateVertex(V,tolV);
830 MaxTolVert = Max(MaxTolVert,tolV);
833 return Standard_True;
837 return Standard_False;
841 //=======================================================================
842 //function : FixSelfIntersectWire
844 //=======================================================================
846 Standard_Boolean ShapeFix_IntersectionTool::FixSelfIntersectWire
847 (Handle(ShapeExtend_WireData)& sewd, const TopoDS_Face& face,
848 Standard_Integer& NbSplit, Standard_Integer& NbCut,
849 Standard_Integer& NbRemoved) const
851 if(myContext.IsNull() || face.IsNull()) return Standard_False;
853 //Standard_Real area2d = ShapeAnalysis::TotCross2D(sewd,face);
854 //if(area2d<Precision::PConfusion()*Precision::PConfusion()) return Standard_False; //gka 06.09.04 BUG 6555
856 TopoDS_Shape SF = Context()->Apply(face);
857 Standard_Real MaxTolVert=0.0;
858 for(TopExp_Explorer exp(SF,TopAbs_VERTEX); exp.More(); exp.Next()) {
859 Standard_Real tolV = BRep_Tool::Tolerance(TopoDS::Vertex(exp.Current()));
860 MaxTolVert = Max(MaxTolVert,tolV);
862 MaxTolVert = Min(MaxTolVert,myMaxTol);
863 ShapeAnalysis_Edge sae;
865 // step 1 : intersection of adjacent edges
867 // step 2 : intersection of non-adjacent edges
868 ShapeFix_DataMapOfShapeBox2d boxes;
869 (void)CreateBoxes2d(sewd,face,boxes);
870 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(BRep_Tool::Surface(face));
874 Standard_Integer nbReplaced =0;
875 Standard_Boolean isDone = Standard_False;
876 for(Standard_Integer num1=1; num1<sewd->NbEdges() && NbSplit<30; num1++) {
877 // for each edge from first wire
878 for(Standard_Integer num2=num1+2; num2<=sewd->NbEdges() && NbSplit<30; num2++) {
879 // for each edge from second wire
880 if( num1==1 && num2==sewd->NbEdges() ) continue;
881 TopoDS_Edge edge1 = sewd->Edge(num1);
882 TopoDS_Edge edge2 = sewd->Edge(num2);
883 if(edge1.IsSame(edge2)) continue;
884 if( BRep_Tool::Degenerated(edge1) || BRep_Tool::Degenerated(edge2) ) continue;
885 if( !boxes.IsBound(edge1) || !boxes.IsBound(edge2) ) continue;
886 Bnd_Box2d B1 = boxes.Find(edge1);
887 Bnd_Box2d B2 = boxes.Find(edge2);
889 // intersection is possible...
890 Standard_Real a1, b1, a2, b2;
891 Handle(Geom2d_Curve) Crv1, Crv2;
892 if( !sae.PCurve(edge1, face, Crv1, a1, b1, Standard_False) ) return Standard_False;
893 if( !sae.PCurve(edge2, face, Crv2, a2, b2, Standard_False) ) return Standard_False;
894 Standard_Real tolint = 1.0e-10;
895 Geom2dAdaptor_Curve C1(Crv1), C2(Crv2);
896 IntRes2d_Domain d1(C1.Value(a1),a1,tolint,C1.Value(b1),b1,tolint);
897 IntRes2d_Domain d2(C2.Value(a2),a2,tolint,C2.Value(b2),b2,tolint);
898 Geom2dInt_GInter Inter;
899 Inter.Perform( C1, d1, C2, d2, tolint, tolint );
900 if(!Inter.IsDone()) continue;
901 // intersection is point
902 if( Inter.NbPoints()>0 && Inter.NbPoints()<3 ) {
903 IntRes2d_IntersectionPoint IP;
904 IntRes2d_Transition Tr1, Tr2;
905 SelectIntPnt(Inter,IP,Tr1,Tr2);
906 if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
907 Tr2.PositionOnCurve() == IntRes2d_Middle ) {
908 Standard_Real param1 = IP.ParamOnFirst();
909 Standard_Real param2 = IP.ParamOnSecond();
910 gp_Pnt pi1 = GetPointOnEdge(edge1,sas,C1,param1);
911 gp_Pnt pi2 = GetPointOnEdge(edge2,sas,C2,param2);
914 Standard_Real tolV=0;
915 // analysis for edge1
916 Standard_Boolean ModifE1 = Standard_False;
917 TopoDS_Vertex VF1 = sae.FirstVertex(edge1);
918 gp_Pnt PVF1 = BRep_Tool::Pnt(VF1);
919 TopoDS_Vertex VL1 = sae.LastVertex(edge1);
920 gp_Pnt PVL1 = BRep_Tool::Pnt(VL1);
921 Standard_Real dist1 = pi1.Distance(PVF1);
922 Standard_Real dist2 = pi1.Distance(PVL1);
923 Standard_Real distmin = Min(dist1, dist2);
924 if( dist1 != dist2 && distmin < MaxTolVert ) {
926 tolV = Max( dist1*1.00001, BRep_Tool::Tolerance(VF1) );
927 B.UpdateVertex(VF1,tolV);
930 tolV = Max( dist2*1.00001, BRep_Tool::Tolerance(VL1) );
931 B.UpdateVertex(VL1,tolV);
935 Standard_Real dista = Abs(a1-param1);
936 Standard_Real distb = Abs(b1-param1);
937 Standard_Boolean IsCutLine;
938 ModifE1 = CutEdge(edge1, (( dista > distb ) ? a1 : b1 ), param1, face, IsCutLine);
941 //not needed split edge, if one of parts is too small
942 ModifE1 = ModifE1 || distmin < Precision::Confusion();
944 // analysis for edge2
945 Standard_Boolean ModifE2 = Standard_False;
946 TopoDS_Vertex VF2 = sae.FirstVertex(edge2);
947 gp_Pnt PVF2 = BRep_Tool::Pnt(VF2);
948 TopoDS_Vertex VL2 = sae.LastVertex(edge2);
949 gp_Pnt PVL2 = BRep_Tool::Pnt(VL2);
950 dist1 = pi2.Distance(PVF2);
951 dist2 = pi2.Distance(PVL2);
952 distmin = Min(dist1, dist2);
953 if( dist1 != dist2 && distmin < MaxTolVert ) {
955 tolV = Max( dist1*1.00001, BRep_Tool::Tolerance(VF2) );
956 B.UpdateVertex(VF2,tolV);
959 tolV = Max( dist2*1.00001, BRep_Tool::Tolerance(VL2) );
960 B.UpdateVertex(VL2,tolV);
964 Standard_Real dista = Abs(a2-param2);
965 Standard_Real distb = Abs(b2-param2);
966 Standard_Boolean IsCutLine;
967 ModifE2 = CutEdge(edge2, (( dista > distb ) ? a2 : b2 ), param2, face, IsCutLine);
970 //not needed split edge, if one of parts is too small
971 ModifE2 = ModifE2 || distmin < Precision::Confusion();
973 if( ModifE1 && !ModifE2 ) {
974 if(SplitEdge1(sewd, face, num2, param2, V, tolV, boxes)) {
981 if( !ModifE1 && ModifE2 ) {
982 if(SplitEdge1(sewd, face, num1, param1, V, tolV, boxes)) {
988 if( !ModifE1 && !ModifE2 ) {
989 gp_Pnt P0( (pi1.X()+pi2.X())/2, (pi1.Y()+pi2.Y())/2, (pi1.Z()+pi2.Z())/2 );
990 tolV = Max( (pi1.Distance(pi2)/2)*1.00001, Precision::Confusion() );
991 B.MakeVertex(V,P0,tolV);
992 MaxTolVert = Max(MaxTolVert,tolV);
993 Standard_Boolean isEdgeSplit2 = SplitEdge1(sewd, face, num2, param2,
999 if(SplitEdge1(sewd, face, num1, param1, V, tolV, boxes)) {
1008 if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
1009 Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1010 // find needed vertex from edge2 and split edge1 using it
1011 Standard_Real param1 = IP.ParamOnFirst();
1012 if(FindVertAndSplitEdge(param1, edge1, edge2, Crv1, MaxTolVert,
1013 num1, sewd, face, boxes, Standard_False) ) {
1018 if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1019 Tr2.PositionOnCurve() == IntRes2d_Middle ) {
1020 // find needed vertex from edge1 and split edge2 using it
1021 Standard_Real param2 = IP.ParamOnSecond();
1022 if(FindVertAndSplitEdge(param2, edge2, edge1, Crv2, MaxTolVert,
1023 num2, sewd, face, boxes, Standard_False) ) {
1028 if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1029 Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1031 if( UnionVertexes(sewd, edge1, edge2, num2, boxes, B2) )
1032 nbReplaced ++; //gka 06.09.04
1035 // intersection is segment
1036 if( Inter.NbSegments()==1 ) {
1037 IntRes2d_IntersectionSegment IS = Inter.Segment(1);
1038 if ( IS.HasFirstPoint() && IS.HasLastPoint() ) {
1039 Standard_Boolean IsModified1 = Standard_False;
1040 Standard_Boolean IsModified2 = Standard_False;
1043 Standard_Real newtol=0.0;
1044 IntRes2d_IntersectionPoint IPF = IS.FirstPoint();
1045 Standard_Real p11 = IPF.ParamOnFirst();
1046 Standard_Real p21 = IPF.ParamOnSecond();
1047 IntRes2d_IntersectionPoint IPL = IS.LastPoint();
1048 Standard_Real p12 = IPL.ParamOnFirst();
1049 Standard_Real p22 = IPL.ParamOnSecond();
1050 gp_Pnt Pnt11 = GetPointOnEdge(edge1,sas,C1,p11);
1051 gp_Pnt Pnt12 = GetPointOnEdge(edge1,sas,C1,p12);
1052 gp_Pnt Pnt21 = GetPointOnEdge(edge2,sas,C2,p21);
1053 gp_Pnt Pnt22 = GetPointOnEdge(edge2,sas,C2,p22);
1054 // next string commented by skl 29.12.2004 for OCC7624
1055 //if( Pnt11.Distance(Pnt21)>myPreci || Pnt12.Distance(Pnt22)>myPreci ) continue;
1056 if( Pnt11.Distance(Pnt21)>MaxTolVert || Pnt12.Distance(Pnt22)>MaxTolVert ) continue;
1057 // analysis for edge1
1058 TopoDS_Vertex V1 = sae.FirstVertex(edge1);
1059 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
1060 TopoDS_Vertex V2 = sae.LastVertex(edge1);
1061 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
1062 //Standard_Real tol1 = BRep_Tool::Tolerance(V1);
1063 //Standard_Real tol2 = BRep_Tool::Tolerance(V2);
1064 //Standard_Real maxtol = Max(tol1,tol2);
1065 Standard_Real dist1 = Pnt11.Distance(PV1);
1066 Standard_Real dist2 = Pnt12.Distance(PV1);
1067 Standard_Real maxdist = Max(dist1,dist2);
1068 Standard_Real pdist;
1069 if(edge1.Orientation()==TopAbs_REVERSED)
1070 pdist = Max(Abs(b1-p11),Abs(b1-p12));
1072 pdist = Max(Abs(a1-p11),Abs(a1-p12));
1073 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1074 //if(maxdist<maxtol || pdist<Abs(b1-a1)*0.01) {
1077 IsModified1 = Standard_True;
1079 dist1 = Pnt11.Distance(PV2);
1080 dist2 = Pnt12.Distance(PV2);
1081 maxdist = Max(dist1,dist2);
1082 if(edge1.Orientation()==TopAbs_REVERSED)
1083 pdist = Max(Abs(a1-p11),Abs(a1-p12));
1085 pdist = Max(Abs(b1-p11),Abs(b1-p12));
1086 //if(maxdist<maxtol || pdist<Abs(b1-a1)*0.01) {
1087 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1088 if( ( IsModified1 && maxdist<newtol ) || !IsModified1 ) {
1091 IsModified1 = Standard_True;
1095 // cut edge1 and update tolerance NewV
1096 Standard_Real dista = Abs(a1-p11)+Abs(a1-p12);
1097 Standard_Real distb = Abs(b1-p11)+Abs(b1-p12);
1098 Standard_Real pend,cut;
1099 if(dista>distb) pend=a1;
1101 if(Abs(pend-p11)>Abs(pend-p12)) cut=p12;
1103 Standard_Boolean IsCutLine;
1104 if (CutEdge(edge1, pend, cut, face, IsCutLine))
1106 if(newtol>BRep_Tool::Tolerance(NewV)) {
1107 B.UpdateVertex(NewV,newtol);
1109 else newtol = BRep_Tool::Tolerance(NewV);
1111 // analysis for edge2
1112 TopoDS_Vertex V12 = sae.FirstVertex(edge2);
1113 gp_Pnt PV12 = BRep_Tool::Pnt(V12);
1114 TopoDS_Vertex V22 = sae.LastVertex(edge2);
1115 gp_Pnt PV22 = BRep_Tool::Pnt(V22);
1116 //tol1 = BRep_Tool::Tolerance(V1);
1117 //tol2 = BRep_Tool::Tolerance(V2);
1118 //maxtol = Max(tol1,tol2);
1119 dist1 = Pnt21.Distance(PV12);
1120 dist2 = Pnt22.Distance(PV12);
1121 maxdist = Max(dist1,dist2);
1122 if(edge2.Orientation()==TopAbs_REVERSED)
1123 pdist = Max(Abs(b2-p21),Abs(b2-p22));
1125 pdist = Max(Abs(a2-p21),Abs(a2-p22));
1126 //if(maxdist<maxtol || pdist<Abs(b2-a2)*0.01) {
1127 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1130 IsModified2 = Standard_True;
1132 dist1 = Pnt21.Distance(PV22);
1133 dist2 = Pnt22.Distance(PV22);
1134 maxdist = Max(dist1,dist2);
1135 if(edge2.Orientation()==TopAbs_REVERSED)
1136 pdist = Max(Abs(a2-p21),Abs(a2-p22));
1138 pdist = Max(Abs(b2-p21),Abs(b2-p22));
1139 //if(maxdist<maxtol || pdist<Abs(b2-a2)*0.01) {
1140 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1141 if( ( IsModified2 && maxdist<newtol ) || !IsModified2 ) {
1144 IsModified2 = Standard_True;
1148 // cut edge1 and update tolerance NewV
1149 Standard_Real dista = Abs(a2-p21)+Abs(a2-p22);
1150 Standard_Real distb = Abs(b2-p21)+Abs(b2-p22);
1151 Standard_Real pend,cut;
1152 if(dista>distb) pend=a2;
1154 if(Abs(pend-p21)>Abs(pend-p22)) cut=p22;
1156 Standard_Boolean IsCutLine;
1157 if (CutEdge(edge2, pend, cut, face, IsCutLine))
1159 if(newtol>BRep_Tool::Tolerance(NewV)) {
1160 B.UpdateVertex(NewV,newtol);
1162 else newtol = BRep_Tool::Tolerance(NewV);
1165 if( IsModified1 && !IsModified2 ) {
1166 if(SplitEdge2(sewd, face, num2, p21, p22, NewV, newtol, boxes)) {
1172 if( !IsModified1 && IsModified2 ) {
1173 if(SplitEdge2(sewd, face, num1, p11, p12, NewV, newtol, boxes)) {
1179 if( !IsModified1 && !IsModified2 ) {
1180 Standard_Real param1 = (p11+p12)/2;
1181 Standard_Real param2 = (p21+p22)/2;
1182 gp_Pnt Pnt10 = GetPointOnEdge(edge1,sas,C1,param1);
1183 gp_Pnt Pnt20 = GetPointOnEdge(edge2,sas,C2,param2);
1184 gp_Pnt P0( (Pnt10.X()+Pnt20.X())/2, (Pnt10.Y()+Pnt20.Y())/2,
1185 (Pnt10.Z()+Pnt20.Z())/2 );
1186 dist1 = Max(Pnt11.Distance(P0),Pnt12.Distance(P0));
1187 dist2 = Max(Pnt21.Distance(P0),Pnt22.Distance(P0));
1188 Standard_Real tolV = Max(dist1,dist2);
1189 tolV = Max(tolV,Pnt10.Distance(Pnt20))*1.00001;
1190 Standard_Boolean FixSegment = Standard_True;
1191 if(tolV<MaxTolVert) {
1192 // create new vertex and split each intersecting edge on two edges
1193 B.MakeVertex(NewV,Pnt10,tolV);
1194 if(SplitEdge2(sewd, face, num2, p21, p22, NewV, tolV, boxes)) {
1198 if(SplitEdge2(sewd, face, num1, p11, p12, NewV, tolV, boxes)) {
1204 else if(FixSegment) {
1205 //if( Abs(p12-p11)>Abs(b1-a1)/2 || Abs(p22-p21)>Abs(b2-a2)/2 ) {
1206 // segment is big and we have to split each intersecting edge
1207 // on 3 edges --> middle edge - edge based on segment
1208 // after we can remove edges maked from segment
1209 gp_Pnt P01( (Pnt11.X()+Pnt21.X())/2, (Pnt11.Y()+Pnt21.Y())/2,
1210 (Pnt11.Z()+Pnt21.Z())/2 );
1211 gp_Pnt P02( (Pnt12.X()+Pnt22.X())/2, (Pnt12.Y()+Pnt22.Y())/2,
1212 (Pnt12.Z()+Pnt22.Z())/2 );
1213 Standard_Real tolV1 = Max(Pnt11.Distance(P01),Pnt21.Distance(P01));
1214 tolV1 = Max(tolV1,Precision::Confusion())*1.00001;
1215 Standard_Real tolV2 = Max(Pnt12.Distance(P02),Pnt22.Distance(P02));
1216 tolV2 = Max(tolV2,Precision::Confusion())*1.00001;
1217 if( tolV1>MaxTolVert || tolV2>MaxTolVert ) continue;
1218 TopoDS_Vertex NewV1,NewV2;
1220 // parameters for splitting: a1..p11..p12..b1 and a2..p21..p22..b2 ???
1221 Standard_Integer nbseg1=3, nbseg2=3, kv1=0, kv2=0;
1222 if(P01.Distance(PV1)<Max(tolV1,BRep_Tool::Tolerance(V1))) {
1224 if(tolV1>BRep_Tool::Tolerance(V1))
1225 B.UpdateVertex(NewV1,tolV1);
1230 else if(P01.Distance(PV2)<Max(tolV1,BRep_Tool::Tolerance(V2))) {
1232 if(tolV1>BRep_Tool::Tolerance(V2))
1233 B.UpdateVertex(NewV1,tolV1);
1239 TopoDS_Edge tmpE,SegE;
1241 Standard_Integer akey1=0, akey2=0;
1242 Standard_Real newTolerance;
1244 newTolerance = Max(tolV1,BRep_Tool::Tolerance(V1));
1245 if(P01.Distance(PV1)<newTolerance) {
1246 B.MakeVertex(NewV1,BRep_Tool::Pnt(V1),newTolerance);
1247 NewV1.Orientation(V1.Orientation());
1250 newTolerance = Max(tolV1,BRep_Tool::Tolerance(V2));
1251 if(P01.Distance(PV2)<newTolerance) {
1252 B.MakeVertex(NewV1,BRep_Tool::Pnt(V2),newTolerance);
1253 NewV1.Orientation(V2.Orientation());
1257 newTolerance = Max(tolV2,BRep_Tool::Tolerance(V1));
1258 if(P02.Distance(PV1)<newTolerance) {
1259 B.MakeVertex(NewV2,BRep_Tool::Pnt(V1),newTolerance);
1260 NewV2.Orientation(V1.Orientation());
1263 newTolerance = Max(tolV2,BRep_Tool::Tolerance(V2));
1264 if(P02.Distance(PV2)<newTolerance) {
1265 B.MakeVertex(NewV2,BRep_Tool::Pnt(V2),newTolerance);
1266 NewV2.Orientation(V2.Orientation());
1269 if( akey1>1 || akey2>1 ) continue;
1270 Standard_Integer dnum1=0, numseg1=num1;
1272 if(akey1==0) B.MakeVertex(NewV1,P01,tolV1);
1273 if(akey2==0) B.MakeVertex(NewV2,P02,tolV2);
1275 if( akey1==0 && akey2>0 ) {
1276 if(SplitEdge1(sewd, face, num1, p11, NewV1, tolV1, boxes)) {
1282 if( akey1>0 && akey2==0 ) {
1283 if(SplitEdge1(sewd, face, num1, p12, NewV2, tolV2, boxes) ) {
1289 if( akey1==0 && akey2==0 ) {
1290 if(SplitEdge1(sewd, face, num1, p11, NewV1, tolV1, boxes)) {
1294 tmpE = sewd->Edge(num1);
1296 Handle(Geom2d_Curve) c2d;
1297 sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1298 if( (a-p12)*(b-p12)>0 ) { // p12 - external for [a,b] => split next edge
1299 if(SplitEdge1(sewd, face, num1+1, p12, NewV2, tolV2, boxes) ) {
1306 if(SplitEdge1(sewd, face, num1, p12, NewV2, tolV2, boxes) ) {
1313 //SegE = sewd->Edge(numseg1); // get edge from segment
1315 // replace vertices if it is necessary
1316 ShapeBuild_Edge sbe;
1319 if(P01.Distance(PV12)<tolV1) {
1320 tolV1 += P01.Distance(PV12);
1321 B.UpdateVertex(NewV1,tolV1);
1322 if(V12.Orientation()==NewV1.Orientation()) {
1323 myContext->Replace(V12,NewV1);
1327 myContext->Replace(V12,NewV1.Reversed());
1328 V12 = TopoDS::Vertex(NewV1.Reversed());
1330 nbReplaced++; //gka 06.09.04
1331 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV1,V22);
1332 myContext->Replace(edge2,NewE);
1333 sewd->Set(NewE,num2+dnum1);
1334 boxes.Bind(NewE,B2); // update boxes
1338 if(P01.Distance(PV22)<tolV1) {
1339 tolV1 += P01.Distance(PV22);
1340 B.UpdateVertex(NewV1,tolV1);
1341 if(V22.Orientation()==NewV1.Orientation()) {
1342 myContext->Replace(V22,NewV1);
1346 myContext->Replace(V22,NewV1.Reversed());
1347 V22 = TopoDS::Vertex(NewV1.Reversed());
1349 nbReplaced++; //gka 06.09.04
1350 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV1);
1351 myContext->Replace(edge2,NewE);
1352 sewd->Set(NewE,num2+dnum1);
1353 boxes.Bind(NewE,B2); // update boxes
1357 if(P02.Distance(PV12)<tolV2) {
1358 tolV2 += P02.Distance(PV12);
1359 B.UpdateVertex(NewV2,tolV2);
1360 if(V12.Orientation()==NewV2.Orientation()) {
1361 myContext->Replace(V12,NewV2);
1365 myContext->Replace(V12,NewV2.Reversed());
1366 V12 = TopoDS::Vertex(NewV2.Reversed());
1368 nbReplaced++; //gka 06.09.04
1369 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV2,V22);
1370 myContext->Replace(edge2,NewE);
1371 sewd->Set(NewE,num2+dnum1);
1372 boxes.Bind(NewE,B2); // update boxes
1376 if(P02.Distance(PV22)<tolV2) {
1377 tolV2 += P02.Distance(PV22);
1378 B.UpdateVertex(NewV2,tolV2);
1379 if(V22.Orientation()==NewV2.Orientation()) {
1380 myContext->Replace(V22,NewV2);
1384 myContext->Replace(V22,NewV2.Reversed());
1385 V22 = TopoDS::Vertex(NewV2.Reversed());
1387 nbReplaced++; //gka 06.09.04
1388 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV2);
1389 myContext->Replace(edge2,NewE);
1390 sewd->Set(NewE,num2+dnum1);
1391 boxes.Bind(NewE,B2); // update boxes
1395 Standard_Integer dnum2=0, numseg2=num2+dnum1;
1397 if( akey1==0 && akey2>0 ) {
1398 if(SplitEdge1(sewd, face, num2+dnum1, p21, NewV1, tolV1, boxes)) {
1401 //numseg2=num2+dnum1+1;
1405 if( akey1>0 && akey2==0 ) {
1406 if(SplitEdge1(sewd, face, num2+dnum1, p22, NewV2, tolV2, boxes)) {
1409 //numseg2=num2+dnum1;
1410 numseg2=num2+dnum1+1;
1413 if( akey1==0 && akey2==0 ) {
1414 if(SplitEdge1(sewd, face, num2+dnum1, p21, NewV1, tolV1, boxes)) {
1418 tmpE = sewd->Edge(num2+dnum1);
1420 Handle(Geom2d_Curve) c2d;
1421 sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1422 if( (a-p22)*(b-p22)>0 ) { // p22 - external for [a,b] => split next edge
1423 if(SplitEdge1(sewd, face, num2+dnum1+dnum2, p22, NewV2, tolV2, boxes) ) {
1425 numseg2=num2+dnum1+dnum2;
1430 if(SplitEdge1(sewd, face, num2+dnum1, p22, NewV2, tolV2, boxes) ) {
1433 numseg2=num2+dnum1+1;
1438 sewd->Remove(numseg2);
1439 sewd->Remove(numseg1);
1440 NbRemoved = NbRemoved+2;
1450 isDone = (NbSplit || NbCut || nbReplaced || NbRemoved);
1455 //=======================================================================
1456 //function : FixIntersectingWires
1458 //=======================================================================
1460 Standard_Boolean ShapeFix_IntersectionTool::FixIntersectingWires
1461 (TopoDS_Face& face) const
1463 if(myContext.IsNull() || face.IsNull()) return Standard_False;
1464 //TopoDS_Shape S = context->Apply(face);
1465 //TopoDS_Shape SF = TopoDS::Face(S);
1466 TopoDS_Shape SF = face;
1467 TopAbs_Orientation ori = face.Orientation();
1468 TopTools_SequenceOfShape SeqWir;
1469 TopTools_SequenceOfShape SeqNMShapes;
1470 for( TopoDS_Iterator iter(SF,Standard_False); iter.More(); iter.Next() ) {
1471 if(iter.Value().ShapeType() != TopAbs_WIRE ||
1472 (iter.Value().Orientation() != TopAbs_FORWARD &&
1473 iter.Value().Orientation() != TopAbs_REVERSED)) {
1474 SeqNMShapes.Append(iter.Value());
1477 TopoDS_Wire wire = TopoDS::Wire(iter.Value());
1478 SeqWir.Append(wire);
1480 if(SeqWir.Length()<2) return Standard_False;//gka 06.09.04
1482 Standard_Real MaxTolVert=0.0;
1483 for(TopExp_Explorer exp(SF,TopAbs_VERTEX); exp.More(); exp.Next()) {
1484 Standard_Real tolV = BRep_Tool::Tolerance(TopoDS::Vertex(exp.Current()));
1485 MaxTolVert = Max(MaxTolVert,tolV);
1487 Standard_Boolean isDone = Standard_False; //gka 06.09.04
1488 ShapeAnalysis_Edge sae;
1489 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface (BRep_Tool::Surface (face));
1491 // precompute edge boxes for all wires
1492 NCollection_Sequence<ShapeFix_DataMapOfShapeBox2d> aSeqWirEdgeBoxes;
1493 NCollection_Sequence<Bnd_Box2d> aSeqWirBoxes;
1494 for (Standard_Integer n = 1; n <= SeqWir.Length(); n++)
1496 const TopoDS_Wire& aWire = TopoDS::Wire (SeqWir.Value (n));
1497 Handle(ShapeExtend_WireData) aSewd = new ShapeExtend_WireData (aWire);
1498 ShapeFix_DataMapOfShapeBox2d aBoxes;
1499 Bnd_Box2d aTotalBox = CreateBoxes2d (aSewd, face, aBoxes);
1500 aSeqWirEdgeBoxes.Append (aBoxes);
1501 aSeqWirBoxes.Append (aTotalBox);
1504 for(Standard_Integer n1=1; n1<=SeqWir.Length()-1; n1++) {
1505 TopoDS_Wire wire1 = TopoDS::Wire(SeqWir.Value(n1));
1506 Handle(ShapeExtend_WireData) sewd1 = new ShapeExtend_WireData(wire1);
1507 ShapeFix_DataMapOfShapeBox2d& boxes1 = aSeqWirEdgeBoxes.ChangeValue (n1);
1508 Bnd_Box2d aBox1 = aSeqWirBoxes (n1);
1509 for(Standard_Integer n2=n1+1; n2<=SeqWir.Length(); n2++) {
1510 TopoDS_Wire wire2 = TopoDS::Wire(SeqWir.Value(n2));
1511 Handle(ShapeExtend_WireData) sewd2 = new ShapeExtend_WireData(wire2);
1512 ShapeFix_DataMapOfShapeBox2d& boxes2 = aSeqWirEdgeBoxes.ChangeValue (n2);
1513 Bnd_Box2d aBox2 = aSeqWirBoxes (n2);
1514 if (!aBox1.IsVoid() && !aBox2.IsVoid() && aBox1.IsOut (aBox2))
1518 // detect possible intersections:
1519 Standard_Integer NbModif=0;
1520 Standard_Integer nbReplaced =0;//gka 06.09.04
1521 Standard_Boolean hasModifWire = Standard_False; //gka 06.09.04
1522 for(Standard_Integer num1 = 1; num1<=sewd1->NbEdges() && NbModif<30; num1++) {
1523 // for each edge from first wire
1524 TopoDS_Edge edge1 = sewd1->Edge(num1); //gka 06.09.04
1526 for(Standard_Integer num2 = 1; num2<=sewd2->NbEdges() && NbModif<30; num2++) {
1527 // for each edge from second wire
1528 TopoDS_Edge edge2 = sewd2->Edge(num2);
1529 if(edge1.IsSame(edge2)) continue;
1530 if( BRep_Tool::Degenerated(edge1) || BRep_Tool::Degenerated(edge2) ) continue;
1531 if( !boxes1.IsBound(edge1) || !boxes2.IsBound(edge2) ) continue;
1532 Bnd_Box2d B1 = boxes1.Find(edge1);
1533 Bnd_Box2d B2 = boxes2.Find(edge2);
1535 // intersection is possible...
1536 Standard_Real a1, b1, a2, b2;
1537 Handle(Geom2d_Curve) Crv1, Crv2;
1538 if( !sae.PCurve(edge1, face, Crv1, a1, b1, Standard_False) )
1539 continue; //return Standard_False; gka 06.09.04
1540 if( !sae.PCurve(edge2, face, Crv2, a2, b2, Standard_False) )
1541 continue; //return Standard_False;gka 06.09.04
1542 Standard_Real tolint = 1.0e-10;
1543 Geom2dAdaptor_Curve C1(Crv1), C2(Crv2);
1544 IntRes2d_Domain d1(C1.Value(a1),a1,tolint,C1.Value(b1),b1,tolint);
1545 IntRes2d_Domain d2(C2.Value(a2),a2,tolint,C2.Value(b2),b2,tolint);
1546 Geom2dInt_GInter Inter;
1547 Inter.Perform( C1, d1, C2, d2, tolint, tolint );
1548 if(!Inter.IsDone()) continue;
1549 // intersection is point
1550 if( Inter.NbPoints()>0 && Inter.NbPoints()<3 ) {
1551 IntRes2d_IntersectionPoint IP;
1552 IntRes2d_Transition Tr1, Tr2;
1553 SelectIntPnt(Inter,IP,Tr1,Tr2);
1554 if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
1555 Tr2.PositionOnCurve() == IntRes2d_Middle ) {
1556 // create new vertex and split both edges
1557 Standard_Real param1 = IP.ParamOnFirst();
1558 Standard_Real param2 = IP.ParamOnSecond();
1559 gp_Pnt pi1 = GetPointOnEdge(edge1,sas,C1,param1);
1560 gp_Pnt pi2 = GetPointOnEdge(edge2,sas,C2,param2);
1561 gp_Pnt P0( (pi1.X()+pi2.X())/2, (pi1.Y()+pi2.Y())/2, (pi1.Z()+pi2.Z())/2 );
1564 Standard_Real tolV = Max( (pi1.Distance(pi2)/2)*1.00001, Precision::Confusion() );
1565 B.MakeVertex(V,P0,tolV);
1566 MaxTolVert = Max(MaxTolVert,tolV);
1567 Standard_Boolean isSplitEdge2 = SplitEdge1(sewd2, face, num2, param2,
1573 if(SplitEdge1(sewd1, face, num1, param1, V, tolV, boxes1)) {
1581 if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
1582 Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1583 // find needed vertex from edge2 and split edge1 using it
1584 Standard_Real param1 = IP.ParamOnFirst();
1585 if(FindVertAndSplitEdge(param1, edge1, edge2, Crv1, MaxTolVert,
1586 num1, sewd1, face, boxes1, Standard_True) ) {
1591 if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1592 Tr2.PositionOnCurve() == IntRes2d_Middle ) {
1593 // find needed vertex from edge1 and split edge2 using it
1594 Standard_Real param2 = IP.ParamOnSecond();
1595 if(FindVertAndSplitEdge(param2, edge2, edge1, Crv2, MaxTolVert,
1596 num2, sewd2, face, boxes2, Standard_True) ) {
1601 if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1602 Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1604 if( UnionVertexes(sewd2, edge1, edge2, num2, boxes2, B2) )
1605 nbReplaced ++; //gka 06.09.04
1608 hasModifWire = (hasModifWire || NbModif || nbReplaced);
1609 // intersection is segment
1610 if( Inter.NbSegments()==1 ) {
1611 IntRes2d_IntersectionSegment IS = Inter.Segment(1);
1612 if ( IS.HasFirstPoint() && IS.HasLastPoint() ) {
1613 Standard_Boolean IsModified1 = Standard_False;
1614 Standard_Boolean IsModified2 = Standard_False;
1617 Standard_Real newtol=0.0;
1618 IntRes2d_IntersectionPoint IPF = IS.FirstPoint();
1619 Standard_Real p11 = IPF.ParamOnFirst();
1620 Standard_Real p21 = IPF.ParamOnSecond();
1621 IntRes2d_IntersectionPoint IPL = IS.LastPoint();
1622 Standard_Real p12 = IPL.ParamOnFirst();
1623 Standard_Real p22 = IPL.ParamOnSecond();
1624 gp_Pnt Pnt11 = GetPointOnEdge(edge1,sas,C1,p11);
1625 gp_Pnt Pnt12 = GetPointOnEdge(edge1,sas,C1,p12);
1626 gp_Pnt Pnt21 = GetPointOnEdge(edge2,sas,C2,p21);
1627 gp_Pnt Pnt22 = GetPointOnEdge(edge2,sas,C2,p22);
1629 // analysis for edge1
1630 TopoDS_Vertex V1 = sae.FirstVertex(edge1);
1631 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
1632 TopoDS_Vertex V2 = sae.LastVertex(edge1);
1633 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
1634 Standard_Real dist1 = Pnt11.Distance(PV1);
1635 Standard_Real dist2 = Pnt12.Distance(PV1);
1636 Standard_Real maxdist = Max(dist1,dist2);
1637 Standard_Real pdist;
1638 if(edge1.Orientation()==TopAbs_REVERSED)
1639 pdist = Max(Abs(b1-p11),Abs(b1-p12));
1641 pdist = Max(Abs(a1-p11),Abs(a1-p12));
1642 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1645 IsModified1 = Standard_True;
1647 dist1 = Pnt11.Distance(PV2);
1648 dist2 = Pnt12.Distance(PV2);
1649 maxdist = Max(dist1,dist2);
1650 if(edge1.Orientation()==TopAbs_REVERSED)
1651 pdist = Max(Abs(a1-p11),Abs(a1-p12));
1653 pdist = Max(Abs(b1-p11),Abs(b1-p12));
1654 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1655 if( ( IsModified1 && maxdist<newtol ) || !IsModified1 ) {
1658 IsModified1 = Standard_True;
1662 // cut edge1 and update tolerance NewV
1663 Standard_Real dista = Abs(a1-p11)+Abs(a1-p12);
1664 Standard_Real distb = Abs(b1-p11)+Abs(b1-p12);
1665 Standard_Real pend,cut;
1666 if(dista>distb) pend=a1;
1668 if(Abs(pend-p11)>Abs(pend-p12)) cut=p12;
1670 Standard_Boolean IsCutLine;
1671 if(!CutEdge(edge1, pend, cut, face, IsCutLine))
1673 IsModified1 = Standard_False;
1676 if(newtol>BRep_Tool::Tolerance(NewV)) {
1677 B.UpdateVertex(NewV,newtol*1.00001);
1681 // analysis for edge2
1682 TopoDS_Vertex V12 = sae.FirstVertex(edge2);
1683 gp_Pnt PV12 = BRep_Tool::Pnt(V12);
1684 TopoDS_Vertex V22 = sae.LastVertex(edge2);
1685 gp_Pnt PV22 = BRep_Tool::Pnt(V22);
1686 dist1 = Pnt21.Distance(PV12);
1687 dist2 = Pnt22.Distance(PV12);
1688 maxdist = Max(dist1,dist2);
1689 if(edge2.Orientation()==TopAbs_REVERSED)
1690 pdist = Max(Abs(b2-p21),Abs(b2-p22));
1692 pdist = Max(Abs(a2-p21),Abs(a2-p22));
1693 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1696 IsModified2 = Standard_True;
1698 dist1 = Pnt21.Distance(PV22);
1699 dist2 = Pnt22.Distance(PV22);
1700 maxdist = Max(dist1,dist2);
1701 if(edge2.Orientation()==TopAbs_REVERSED)
1702 pdist = Max(Abs(a2-p21),Abs(a2-p22));
1704 pdist = Max(Abs(b2-p21),Abs(b2-p22));
1705 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1706 if( ( IsModified2 && maxdist<newtol ) || !IsModified2 ) {
1709 IsModified2 = Standard_True;
1713 // cut edge1 and update tolerance NewV
1714 Standard_Real dista = Abs(a2-p21)+Abs(a2-p22);
1715 Standard_Real distb = Abs(b2-p21)+Abs(b2-p22);
1716 Standard_Real pend,cut;
1717 if(dista>distb) pend=a2;
1719 if(Abs(pend-p21)>Abs(pend-p22)) cut=p22;
1721 Standard_Boolean IsCutLine;
1722 if(!CutEdge(edge2, pend, cut, face, IsCutLine))
1724 IsModified2 = Standard_False;
1728 if(newtol>BRep_Tool::Tolerance(NewV)) {
1729 B.UpdateVertex(NewV,newtol*1.00001);
1733 if( IsModified1 || IsModified2 ) {
1734 //necessary to make intersect with the same pair of the edges once again with modified ranges
1736 hasModifWire = Standard_True; //gka 06.09.04
1740 // create new vertex and split edge1 and edge2 using it
1741 if( Abs(p12-p11)>Abs(b1-a1)/2 || Abs(p22-p21)>Abs(b2-a2)/2 ) {
1742 // segment is big and we have to split each intersecting edge
1743 // on 3 edges --> middle edge - edge based on segment
1744 gp_Pnt P01( (Pnt11.X()+Pnt21.X())/2, (Pnt11.Y()+Pnt21.Y())/2,
1745 (Pnt11.Z()+Pnt21.Z())/2 );
1746 gp_Pnt P02( (Pnt12.X()+Pnt22.X())/2, (Pnt12.Y()+Pnt22.Y())/2,
1747 (Pnt12.Z()+Pnt22.Z())/2 );
1748 Standard_Real tolV1 = Max(Pnt11.Distance(P01),Pnt21.Distance(P01));
1749 tolV1 = Max(tolV1,Precision::Confusion())*1.00001;
1750 Standard_Real tolV2 = Max(Pnt12.Distance(P02),Pnt22.Distance(P02));
1751 tolV2 = Max(tolV2,Precision::Confusion())*1.00001;
1752 if( tolV1>MaxTolVert || tolV2>MaxTolVert ) continue;
1754 hasModifWire = Standard_True; //gka 06.09.04
1755 TopoDS_Vertex NewV1,NewV2;
1756 TopoDS_Edge tmpE,SegE;
1758 Standard_Integer akey1=0, akey2=0;
1760 if(P01.Distance(PV1)<Max(tolV1,BRep_Tool::Tolerance(V1))) {
1762 if(tolV1>BRep_Tool::Tolerance(V1))
1763 B.UpdateVertex(NewV1,tolV1);
1766 if(P01.Distance(PV2)<Max(tolV1,BRep_Tool::Tolerance(V2))) {
1768 if(tolV1>BRep_Tool::Tolerance(V2))
1769 B.UpdateVertex(NewV1,tolV1);
1773 if(P02.Distance(PV1)<Max(tolV2,BRep_Tool::Tolerance(V1))) {
1775 if(tolV2>BRep_Tool::Tolerance(V1))
1776 B.UpdateVertex(NewV2,tolV2);
1779 if(P02.Distance(PV2)<Max(tolV2,BRep_Tool::Tolerance(V2))) {
1781 if(tolV2>BRep_Tool::Tolerance(V2))
1782 B.UpdateVertex(NewV2,tolV2);
1785 if( akey1>1 || akey2>1 ) continue;
1787 if(akey1==0) B.MakeVertex(NewV1,P01,tolV1);
1788 if(akey2==0) B.MakeVertex(NewV2,P02,tolV2);
1790 Standard_Integer numseg1=num1;
1791 if( akey1==0 && akey2>0 ) {
1792 if(SplitEdge1(sewd1, face, num1, p11, NewV1, tolV1, boxes1)) {
1797 if( akey1>0 && akey2==0 ) {
1798 if(SplitEdge1(sewd1, face, num1, p12, NewV2, tolV2, boxes1) ) {
1803 if( akey1==0 && akey2==0 ) {
1804 if(SplitEdge1(sewd1, face, num1, p11, NewV1, tolV1, boxes1)) {
1807 tmpE = sewd1->Edge(num1);
1809 Handle(Geom2d_Curve) c2d;
1810 sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1811 if( (a-p12)*(b-p12)>0 ) { // p12 - external for [a,b] => split next edge
1812 if(SplitEdge1(sewd1, face, num1+1, p12, NewV2, tolV2, boxes1) ) {
1818 if(SplitEdge1(sewd1, face, num1, p12, NewV2, tolV2, boxes1) ) {
1824 SegE = sewd1->Edge(numseg1); // get edge from segment
1826 // replace vertices if it is necessary
1827 ShapeBuild_Edge sbe;
1829 if(P01.Distance(PV12)<tolV1) {
1830 tolV1 += P01.Distance(PV12);
1831 B.UpdateVertex(NewV1,tolV1);
1833 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV1,V22);
1834 myContext->Replace(edge2,NewE);
1835 sewd2->Set(NewE,num2);
1836 boxes2.Bind(NewE,B2); // update boxes2
1840 if(P01.Distance(PV22)<tolV1) {
1841 tolV1 += P01.Distance(PV22);
1842 B.UpdateVertex(NewV1,tolV1);
1844 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV1);
1845 myContext->Replace(edge2,NewE);
1846 sewd2->Set(NewE,num2);
1847 boxes2.Bind(NewE,B2); // update boxes2
1851 if(P02.Distance(PV12)<tolV2) {
1852 tolV2 += P02.Distance(PV12);
1853 B.UpdateVertex(NewV2,tolV2);
1855 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV2,V22);
1856 myContext->Replace(edge2,NewE);
1857 sewd2->Set(NewE,num2);
1858 boxes2.Bind(NewE,B2); // update boxes2
1862 if(P02.Distance(PV22)<tolV2) {
1863 tolV2 += P02.Distance(PV22);
1864 B.UpdateVertex(NewV2,tolV2);
1866 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV2);
1867 myContext->Replace(edge2,NewE);
1868 sewd2->Set(NewE,num2);
1869 boxes2.Bind(NewE,B2); // update boxes2
1874 Standard_Integer numseg2=num2;
1875 if( akey1==0 && akey2>0 ) {
1876 if(SplitEdge1(sewd2, face, num2, p21, NewV1, tolV1, boxes2)) {
1881 if( akey1>0 && akey2==0 ) {
1882 if(SplitEdge1(sewd2, face, num2, p22, NewV2, tolV2, boxes2)) {
1887 if( akey1==0 && akey2==0 ) {
1888 if(SplitEdge1(sewd2, face, num2, p21, NewV1, tolV1, boxes2)) {
1892 tmpE = sewd2->Edge(num2);
1894 Handle(Geom2d_Curve) c2d;
1895 sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1896 if( (a-p22)*(b-p22)>0 ) { // p22 - external for [a,b] => split next edge
1897 if(SplitEdge1(sewd2, face, num2+1, p22, NewV2, tolV2, boxes2) ) {
1903 if(SplitEdge1(sewd2, face, num2, p22, NewV2, tolV2, boxes2) ) {
1909 tmpE = sewd2->Edge(numseg2);
1910 boxes2.Bind(tmpE,boxes1.Find(SegE)); // update boxes2
1911 if(!sae.FirstVertex(SegE).IsSame(sae.FirstVertex(tmpE))) {
1914 myContext->Replace(tmpE,SegE);
1915 sewd2->Set(SegE,numseg2);
1920 // split each intersecting edge on two edges
1921 gp_Pnt P0( (Pnt11.X()+Pnt12.X())/2, (Pnt11.Y()+Pnt12.Y())/2,
1922 (Pnt11.Z()+Pnt12.Z())/2 );
1923 Standard_Real param1 = (p11+p12)/2;
1924 Standard_Real param2 = (p21+p22)/2;
1925 gp_Pnt Pnt10 = GetPointOnEdge(edge1,sas,C1,param1);
1926 gp_Pnt Pnt20 = GetPointOnEdge(edge2,sas,C2,param2);
1927 dist1 = Max(Pnt11.Distance(P0),Pnt12.Distance(Pnt10));
1928 dist2 = Max(Pnt21.Distance(P0),Pnt22.Distance(Pnt10));
1929 Standard_Real tolV = Max(dist1,dist2);
1930 tolV = Max(tolV,Pnt10.Distance(Pnt20))*1.00001;
1931 B.MakeVertex(NewV,Pnt10,tolV);
1932 MaxTolVert = Max(MaxTolVert,tolV);
1933 hasModifWire = Standard_True;
1934 if(SplitEdge2(sewd2, face, num2, p21, p22, NewV, tolV, boxes2)) {
1938 if(SplitEdge2(sewd1, face, num1, p11, p12, NewV, tolV, boxes1)) {
1946 } // end if(Inter.NbSegments()==1)
1952 isDone = Standard_True;
1953 SeqWir.SetValue(n1,sewd1->Wire());
1954 myContext->Replace( wire1, sewd1->Wire() );
1955 wire1 = sewd1->Wire();
1956 //recompute boxes for wire1
1958 Bnd_Box2d aNewBox1 = CreateBoxes2d (sewd1, face, boxes1);
1959 aSeqWirBoxes.SetValue (n1, aNewBox1);
1960 SeqWir.SetValue(n2,sewd2->Wire());
1961 myContext->Replace( wire2, sewd2->Wire() );
1962 wire2 = sewd2->Wire();
1963 //recompute boxes for wire2
1965 Bnd_Box2d aNewBox2 = CreateBoxes2d (sewd2, face, boxes2);
1966 aSeqWirBoxes.SetValue (n2, aNewBox2);
1974 TopoDS_Shape emptyCopied = face.EmptyCopied();
1975 TopoDS_Face newface = TopoDS::Face (emptyCopied);
1976 newface.Orientation(TopAbs_FORWARD);
1978 Standard_Integer i=1;
1979 for(i=1 ; i<=SeqWir.Length(); i++) {
1980 TopoDS_Wire wire = TopoDS::Wire(SeqWir.Value(i));
1981 B.Add(newface,wire);
1983 for(i=1 ; i<=SeqNMShapes.Length(); i++) {
1984 TopoDS_Shape aNMS = SeqNMShapes.Value(i);
1985 B.Add(newface,aNMS);
1987 newface.Orientation(ori);
1988 myContext->Replace(face,newface);