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.
14 #include <ShapeFix_IntersectionTool.ixx>
16 #include <BRep_Builder.hxx>
17 #include <BRep_Tool.hxx>
18 #include <BRepTools.hxx>
19 #include <Bnd_Box2d.hxx>
20 #include <BndLib_Add2dCurve.hxx>
21 #include <GeomAdaptor_Curve.hxx>
22 #include <GeomAdaptor_HSurface.hxx>
23 #include <Geom_Curve.hxx>
24 #include <Geom_Surface.hxx>
25 #include <Geom2d_BSplineCurve.hxx>
26 #include <Geom2d_Curve.hxx>
27 #include <Geom2d_Line.hxx>
28 #include <Geom2d_TrimmedCurve.hxx>
29 #include <Geom2dAdaptor_Curve.hxx>
30 #include <Geom2dInt_GInter.hxx>
32 #include <IntRes2d_Domain.hxx>
33 #include <IntRes2d_IntersectionPoint.hxx>
34 #include <IntRes2d_IntersectionSegment.hxx>
35 #include <IntRes2d_Position.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 <ShapeFix_DataMapOfShapeBox2d.hxx>
42 #include <TopExp_Explorer.hxx>
44 #include <TopoDS_Iterator.hxx>
45 #include <TopoDS_Wire.hxx>
46 #include <TopTools_SequenceOfShape.hxx>
47 #include <NCollection_Sequence.hxx>
49 //gka 06.09.04 BUG 6555 shape is modified always independently either intersection was fixed or not
50 //=======================================================================
51 //function : ShapeFix_IntersectionTool
53 //=======================================================================
55 ShapeFix_IntersectionTool::ShapeFix_IntersectionTool(const Handle(ShapeBuild_ReShape)& context,
56 const Standard_Real preci,
57 const Standard_Real maxtol)
65 //=======================================================================
66 //function : GetPointOnEdge
68 //:h0 abv 29 May 98: PRO10105 1949: like in BRepCheck, point is to be taken
69 // from 3d curve (but only if edge is SameParameter)
70 //=======================================================================
71 static gp_Pnt GetPointOnEdge(const TopoDS_Edge &edge,
72 const Handle(ShapeAnalysis_Surface) &surf,
73 const Geom2dAdaptor_Curve &Crv2d,
74 const Standard_Real param )
76 if( BRep_Tool::SameParameter(edge) ) {
79 const Handle(Geom_Curve) ConS = BRep_Tool::Curve ( edge, L, f, l );
81 return ConS->Value(param).Transformed(L.Transformation());
83 gp_Pnt2d aP2d = Crv2d.Value(param);
84 return surf->Adaptor3d()->Value(aP2d.X(), aP2d.Y());
88 //=======================================================================
89 //function : SplitEdge
91 //=======================================================================
93 Standard_Boolean ShapeFix_IntersectionTool::SplitEdge(const TopoDS_Edge& edge,
94 const Standard_Real param,
95 const TopoDS_Vertex& vert,
96 const TopoDS_Face& face,
99 const Standard_Real preci) const
102 ShapeAnalysis_Edge sae;
104 TopoDS_Vertex V1 = sae.FirstVertex(edge);
105 TopoDS_Vertex V2 = sae.LastVertex(edge);
106 if( V1.IsSame(vert) || V2.IsSame(vert) )
107 return Standard_False;
109 Handle(Geom2d_Curve) c2d;
110 sae.PCurve(edge,face,c2d,a,b,Standard_True );
111 if( Abs(a-param)<0.01*preci || Abs(b-param)<0.01*preci )
112 return Standard_False;
113 // check distanse between edge and new vertex
116 if(BRep_Tool::SameParameter(edge) && !BRep_Tool::Degenerated(edge)) {
118 const Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,L,f,l);
120 return Standard_False;
121 P1 = c3d->Value(param);
122 if(!L.IsIdentity()) P1 = P1.Transformed(L.Transformation());
125 Handle(Geom_Surface) surf = BRep_Tool::Surface(face,L);
126 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(surf);
127 P1 = sas->Value(c2d->Value(param));
128 if(!L.IsIdentity()) P1 = P1.Transformed(L.Transformation());
130 gp_Pnt P2 = BRep_Tool::Pnt(vert);
131 if(P1.Distance(P2)>preci) {
132 //return Standard_False;
134 B.UpdateVertex(vert,P1.Distance(P2));
137 Handle(ShapeAnalysis_TransferParametersProj) transferParameters =
138 new ShapeAnalysis_TransferParametersProj;
139 transferParameters->SetMaxTolerance(preci);
140 transferParameters->Init(edge,face);
141 Standard_Real first, last;
152 TopAbs_Orientation orient = edge.Orientation();
154 TopoDS_Edge wE = edge;
155 wE.Orientation ( TopAbs_FORWARD );
156 TopoDS_Shape aTmpShape = vert.Oriented(TopAbs_REVERSED); //for porting
157 newE1 = sbe.CopyReplaceVertices ( wE, sae.FirstVertex(wE), TopoDS::Vertex(aTmpShape) );
158 sbe.CopyPCurves ( newE1, wE );
159 transferParameters->TransferRange(newE1,first,param,Standard_True);
160 B.SameRange(newE1,Standard_False);
161 B.SameParameter(newE1,Standard_False);
162 aTmpShape = vert.Oriented(TopAbs_FORWARD);
163 newE2 = sbe.CopyReplaceVertices ( wE, TopoDS::Vertex(aTmpShape),sae.LastVertex(wE) );
164 sbe.CopyPCurves ( newE2, wE );
165 transferParameters->TransferRange(newE2,param,last,Standard_True);
166 B.SameRange(newE2,Standard_False);
167 B.SameParameter(newE2,Standard_False);
169 newE1.Orientation(orient);
170 newE2.Orientation(orient);
171 if (orient==TopAbs_REVERSED) {
172 TopoDS_Edge tmp = newE2; newE2 = newE1; newE1=tmp;
175 return Standard_True;
179 //=======================================================================
182 //=======================================================================
184 Standard_Boolean ShapeFix_IntersectionTool::CutEdge(const TopoDS_Edge &edge,
185 const Standard_Real pend,
186 const Standard_Real cut,
187 const TopoDS_Face &face,
188 Standard_Boolean &iscutline) const
190 if( Abs(cut-pend)<10.*Precision::PConfusion() ) return Standard_False;
191 Standard_Real aRange = Abs(cut-pend);
193 BRep_Tool::Range(edge, a, b);
195 if( aRange<10.*Precision::PConfusion() ) return Standard_False;
197 // case pcurve is trimm of line
198 if( !BRep_Tool::SameParameter(edge) ) {
199 ShapeAnalysis_Edge sae;
200 Handle(Geom2d_Curve) Crv;
202 if ( sae.PCurve(edge,face,Crv,fp,lp,Standard_False) ) {
203 if(Crv->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
204 Handle(Geom2d_TrimmedCurve) tc = Handle(Geom2d_TrimmedCurve)::DownCast(Crv);
205 if(tc->BasisCurve()->IsKind(STANDARD_TYPE(Geom2d_Line))) {
207 B.Range(edge,Min(pend,cut),Max(pend,cut));
208 if( Abs(pend-lp)<Precision::PConfusion() ) { // cut from the begining
209 Standard_Real cut3d = (cut-fp)*(b-a)/(lp-fp);
210 B.Range(edge, a+cut3d, b, Standard_True);
211 iscutline = Standard_True;
213 else if( Abs(pend-fp)<Precision::PConfusion() ) { // cut from the end
214 Standard_Real cut3d = (lp-cut)*(b-a)/(lp-fp);
215 B.Range(edge, a, b-cut3d, Standard_True);
216 iscutline = Standard_True;
220 return Standard_True;
223 return Standard_False;
226 // det-study on 03/12/01 checking the old and new ranges
227 if( Abs(Abs(a-b)-aRange) < Precision::PConfusion() ) return Standard_False;
228 if( aRange<10.*Precision::PConfusion() ) return Standard_False;
231 B.Range( edge, Min(pend,cut), Max(pend,cut) );
233 return Standard_True;
237 //=======================================================================
238 //function : SplitEdge1
239 //purpose : split edge[a,b] om two part e1[a,param]
240 // and e2[param,b] using vertex vert
241 //=======================================================================
243 Standard_Boolean ShapeFix_IntersectionTool::SplitEdge1(const Handle(ShapeExtend_WireData)& sewd,
244 const TopoDS_Face& face,
245 const Standard_Integer num,
246 const Standard_Real param,
247 const TopoDS_Vertex& vert,
248 const Standard_Real preci,
249 ShapeFix_DataMapOfShapeBox2d& boxes) const
251 TopoDS_Edge edge = sewd->Edge(num);
252 TopoDS_Edge newE1, newE2;
253 if(!SplitEdge(edge,param,vert,face,newE1,newE2,preci)) return Standard_False;
256 Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData;
259 if(!myContext.IsNull()) myContext->Replace( edge, wd->Wire() );
260 for (TopExp_Explorer exp ( wd->Wire(), TopAbs_EDGE ); exp.More(); exp.Next() ) {
261 TopoDS_Edge E = TopoDS::Edge ( exp.Current() );
262 BRepTools::Update(E);
266 sewd->Set(newE1,num);
267 if(num==sewd->NbEdges())
270 sewd->Add(newE2,num+1);
275 const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L);
276 Handle(Geom2d_Curve) c2d;
278 ShapeAnalysis_Edge sae;
279 if(sae.PCurve(newE1,S,L,c2d,cf,cl,Standard_False)) {
281 Geom2dAdaptor_Curve gac;
282 Standard_Real aFirst = c2d->FirstParameter();
283 Standard_Real aLast = c2d->LastParameter();
284 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
285 && (cf < aFirst || cl > aLast)) {
286 //pdn avoiding problems with segment in Bnd_Box
291 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
292 boxes.Bind(newE1,box);
294 if(sae.PCurve(newE2,S,L,c2d,cf,cl,Standard_False)) {
296 Geom2dAdaptor_Curve gac;
297 Standard_Real aFirst = c2d->FirstParameter();
298 Standard_Real aLast = c2d->LastParameter();
299 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
300 && (cf < aFirst || cl > aLast)) {
301 //pdn avoiding problems with segment in Bnd_Box
306 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
307 boxes.Bind(newE2,box);
310 return Standard_True;
314 //=======================================================================
315 //function : SplitEdge2
316 //purpose : auxilary: split edge[a,b] om two part e1[a,param1]
317 // and e2[param2,b] using vertex vert
318 // (remove segment (param1,param2) from edge)
319 //=======================================================================
321 Standard_Boolean ShapeFix_IntersectionTool::SplitEdge2(const Handle(ShapeExtend_WireData)& sewd,
322 const TopoDS_Face& face,
323 const Standard_Integer num,
324 const Standard_Real param1,
325 const Standard_Real param2,
326 const TopoDS_Vertex& vert,
327 const Standard_Real preci,
328 ShapeFix_DataMapOfShapeBox2d& boxes) const
330 TopoDS_Edge edge = sewd->Edge(num);
331 TopoDS_Edge newE1, newE2;
332 Standard_Real param = (param1+param2)/2;
333 if(!SplitEdge(edge,param,vert,face,newE1,newE2,preci)) return Standard_False;
334 // cut new edges by param1 and param2
335 Standard_Boolean IsCutLine;
336 Handle(Geom2d_Curve) Crv1, Crv2;
337 Standard_Real fp1,lp1,fp2,lp2;
338 ShapeAnalysis_Edge sae;
339 if(sae.PCurve ( newE1, face, Crv1, fp1, lp1, Standard_False )) {
340 if(sae.PCurve ( newE2, face, Crv2, fp2, lp2, Standard_False )) {
342 if( (lp1-fp1)*(lp1-param1)>0 ) {
343 CutEdge(newE1, fp1, param1, face, IsCutLine);
344 CutEdge(newE2, lp2, param2, face, IsCutLine);
347 CutEdge(newE1, fp1, param2, face, IsCutLine);
348 CutEdge(newE2, lp2, param1, face, IsCutLine);
352 if( (fp1-lp1)*(fp1-param1)>0 ) {
353 CutEdge(newE1, lp1, param1, face, IsCutLine);
354 CutEdge(newE2, fp2, param2, face, IsCutLine);
357 CutEdge(newE1, lp1, param2, face, IsCutLine);
358 CutEdge(newE2, fp2, param1, face, IsCutLine);
365 Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData;
368 if(!myContext.IsNull()) myContext->Replace( edge, wd->Wire() );
369 for (TopExp_Explorer exp ( wd->Wire(), TopAbs_EDGE ); exp.More(); exp.Next() ) {
370 TopoDS_Edge E = TopoDS::Edge ( exp.Current() );
371 BRepTools::Update(E);
375 sewd->Set(newE1,num);
376 if(num==sewd->NbEdges())
379 sewd->Add(newE2,num+1);
384 const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L);
385 Handle(Geom2d_Curve) c2d;
387 if(sae.PCurve(newE1,S,L,c2d,cf,cl,Standard_False)) {
389 Geom2dAdaptor_Curve gac;
390 Standard_Real aFirst = c2d->FirstParameter();
391 Standard_Real aLast = c2d->LastParameter();
392 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
393 && (cf < aFirst || cl > aLast)) {
394 //pdn avoiding problems with segment in Bnd_Box
399 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
400 boxes.Bind(newE1,box);
402 if(sae.PCurve(newE2,S,L,c2d,cf,cl,Standard_False)) {
404 Geom2dAdaptor_Curve gac;
405 Standard_Real aFirst = c2d->FirstParameter();
406 Standard_Real aLast = c2d->LastParameter();
407 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
408 && (cf < aFirst || cl > aLast)) {
409 //pdn avoiding problems with segment in Bnd_Box
414 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
415 boxes.Bind(newE2,box);
418 return Standard_True;
422 //=======================================================================
423 //function : UnionVertexes
425 //=======================================================================
427 Standard_Boolean ShapeFix_IntersectionTool::UnionVertexes(const Handle(ShapeExtend_WireData)& sewd,
430 const Standard_Integer num2,
431 ShapeFix_DataMapOfShapeBox2d& boxes,
432 const Bnd_Box2d& B2) const
435 Standard_Boolean res = Standard_False;
437 ShapeAnalysis_Edge sae;
440 TopoDS_Vertex V1F = sae.FirstVertex(edge1);
441 gp_Pnt PV1F = BRep_Tool::Pnt(V1F);
442 TopoDS_Vertex V1L = sae.LastVertex(edge1);
443 gp_Pnt PV1L = BRep_Tool::Pnt(V1L);
444 TopoDS_Vertex V2F = sae.FirstVertex(edge2);
445 gp_Pnt PV2F = BRep_Tool::Pnt(V2F);
446 TopoDS_Vertex V2L = sae.LastVertex(edge2);
447 gp_Pnt PV2L = BRep_Tool::Pnt(V2L);
448 Standard_Real d11 = PV1F.Distance(PV2F);
449 Standard_Real d12 = PV1F.Distance(PV2L);
450 Standard_Real d21 = PV1L.Distance(PV2F);
451 Standard_Real d22 = PV1L.Distance(PV2L);
452 if(d11<d12 && d11<d21 && d11<d22) {
453 Standard_Real tolv = Max(BRep_Tool::Tolerance(V1F),BRep_Tool::Tolerance(V2F));
454 if( !V2F.IsSame(V1F) && d11<tolv ) {
455 // union vertexes V1F and V2F
456 B.UpdateVertex(V1F,tolv);
457 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V1F,V2L);
458 // cout<<"union vertexes V1F and V2F"<<endl;
459 // gp_Pnt Ptmp = BRep_Tool::Pnt(V1F);
460 // B.MakeVertex(V,Ptmp,tolv);
461 // myContext->Replace(V1F,V);
462 // myContext->Replace(V2F,V);
463 // TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V,V2L);
464 myContext->Replace(edge2,NewE);
465 sewd->Set(NewE,num2);
467 boxes.Bind(NewE,B2); // update boxes
468 // replace vertex in other edge
469 Standard_Integer num21,num22;
470 if(num2>1) num21=num2-1;
471 else num21=sewd->NbEdges();
472 if(num2<sewd->NbEdges()) num22=num2+1;
474 TopoDS_Edge edge21 = sewd->Edge(num21);
475 TopoDS_Edge edge22 = sewd->Edge(num22);
476 TopoDS_Vertex V21F = sae.FirstVertex(edge21);
477 TopoDS_Vertex V21L = sae.LastVertex(edge21);
478 TopoDS_Vertex V22F = sae.FirstVertex(edge22);
479 TopoDS_Vertex V22L = sae.LastVertex(edge22);
480 if(V21F.IsSame(V2F)) {
481 NewE = sbe.CopyReplaceVertices(edge21,V1F,V21L);
482 //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
483 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
484 myContext->Replace(edge21,NewE);
485 sewd->Set(NewE,num21);
487 if(V21L.IsSame(V2F)) {
488 NewE = sbe.CopyReplaceVertices(edge21,V21F,V1F);
489 //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
490 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
491 myContext->Replace(edge21,NewE);
492 sewd->Set(NewE,num21);
494 if(V22F.IsSame(V2F)) {
495 NewE = sbe.CopyReplaceVertices(edge22,V1F,V22L);
496 //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
497 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
498 myContext->Replace(edge22,NewE);
499 sewd->Set(NewE,num22);
501 if(V22L.IsSame(V2F)) {
502 NewE = sbe.CopyReplaceVertices(edge22,V22F,V1F);
503 //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
504 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
505 myContext->Replace(edge22,NewE);
506 sewd->Set(NewE,num22);
511 else if(d12<d21 && d12<d22) {
512 Standard_Real tolv = Max(BRep_Tool::Tolerance(V1F),BRep_Tool::Tolerance(V2L));
513 if( !V2L.IsSame(V1F) && d12<tolv ) {
514 // union vertexes V1F and V2L
515 B.UpdateVertex(V1F,tolv);
516 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V1F);
517 // cout<<"union vertexes V1F and V2L"<<endl;
518 // gp_Pnt Ptmp = BRep_Tool::Pnt(V1F);
519 // B.MakeVertex(V,Ptmp,tolv);
520 // myContext->Replace(V1F,V);
521 // myContext->Replace(V2L,V);
522 // TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V);
523 myContext->Replace(edge2,NewE);
524 sewd->Set(NewE,num2);
526 //boxes.Bind(NewE,boxes.Find(edge2)); // update boxes
527 boxes.Bind(NewE,B2); // update boxes
528 // replace vertex in other edge
529 Standard_Integer num21,num22;
530 if(num2>1) num21=num2-1;
531 else num21=sewd->NbEdges();
532 if(num2<sewd->NbEdges()) num22=num2+1;
534 TopoDS_Edge edge21 = sewd->Edge(num21);
535 TopoDS_Edge edge22 = sewd->Edge(num22);
536 TopoDS_Vertex V21F = sae.FirstVertex(edge21);
537 TopoDS_Vertex V21L = sae.LastVertex(edge21);
538 TopoDS_Vertex V22F = sae.FirstVertex(edge22);
539 TopoDS_Vertex V22L = sae.LastVertex(edge22);
540 if(V21F.IsSame(V2L)) {
541 NewE = sbe.CopyReplaceVertices(edge21,V1F,V21L);
542 //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
543 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
544 myContext->Replace(edge21,NewE);
545 sewd->Set(NewE,num21);
547 if(V21L.IsSame(V2L)) {
548 NewE = sbe.CopyReplaceVertices(edge21,V21F,V1F);
549 //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
550 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
551 myContext->Replace(edge21,NewE);
552 sewd->Set(NewE,num21);
554 if(V22F.IsSame(V2L)) {
555 NewE = sbe.CopyReplaceVertices(edge22,V1F,V22L);
556 //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
557 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
558 myContext->Replace(edge22,NewE);
559 sewd->Set(NewE,num22);
561 if(V22L.IsSame(V2L)) {
562 NewE = sbe.CopyReplaceVertices(edge22,V22F,V1F);
563 //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
564 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
565 myContext->Replace(edge22,NewE);
566 sewd->Set(NewE,num22);
572 Standard_Real tolv = Max(BRep_Tool::Tolerance(V1L),BRep_Tool::Tolerance(V2F));
573 if( !V2F.IsSame(V1L) && d21<tolv ) {
574 // union vertexes V1L and V2F
575 B.UpdateVertex(V1L,tolv);
576 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V1L,V2L);
577 // cout<<"union vertexes V1L and V2F"<<endl;
578 // gp_Pnt Ptmp = BRep_Tool::Pnt(V1L);
579 // B.MakeVertex(V,Ptmp,tolv);
580 // myContext->Replace(V1L,V);
581 // myContext->Replace(V2F,V);
582 // TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V,V2L);
583 myContext->Replace(edge2,NewE);
584 sewd->Set(NewE,num2);
586 boxes.Bind(NewE,B2); // update boxes
587 // replace vertex in other edge
588 Standard_Integer num21,num22;
589 if(num2>1) num21=num2-1;
590 else num21=sewd->NbEdges();
591 if(num2<sewd->NbEdges()) num22=num2+1;
593 TopoDS_Edge edge21 = sewd->Edge(num21);
594 TopoDS_Edge edge22 = sewd->Edge(num22);
595 TopoDS_Vertex V21F = sae.FirstVertex(edge21);
596 TopoDS_Vertex V21L = sae.LastVertex(edge21);
597 TopoDS_Vertex V22F = sae.FirstVertex(edge22);
598 TopoDS_Vertex V22L = sae.LastVertex(edge22);
599 if(V21F.IsSame(V2F)) {
600 NewE = sbe.CopyReplaceVertices(edge21,V1L,V21L);
601 //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
602 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
603 myContext->Replace(edge21,NewE);
604 sewd->Set(NewE,num21);
606 if(V21L.IsSame(V2F)) {
607 NewE = sbe.CopyReplaceVertices(edge21,V21F,V1L);
608 //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
609 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
610 myContext->Replace(edge21,NewE);
611 sewd->Set(NewE,num21);
613 if(V22F.IsSame(V2F)) {
614 NewE = sbe.CopyReplaceVertices(edge22,V1L,V22L);
615 //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
616 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
617 myContext->Replace(edge22,NewE);
618 sewd->Set(NewE,num22);
620 if(V22L.IsSame(V2F)) {
621 NewE = sbe.CopyReplaceVertices(edge22,V22F,V1L);
622 //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
623 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
624 myContext->Replace(edge22,NewE);
625 sewd->Set(NewE,num22);
631 Standard_Real tolv = Max(BRep_Tool::Tolerance(V1L),BRep_Tool::Tolerance(V2L));
632 if( !V2L.IsSame(V1L) && d22<tolv ) {
633 // union vertexes V1L and V2L
634 B.UpdateVertex(V1L,tolv);
635 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V1L);
636 // cout<<"union vertexes V1L and V2L"<<endl;
637 // gp_Pnt Ptmp = BRep_Tool::Pnt(V1L);
638 // B.MakeVertex(V,Ptmp,tolv);
639 // myContext->Replace(V1L,V);
640 // myContext->Replace(V2L,V);
641 // TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V);
642 myContext->Replace(edge2,NewE);
643 sewd->Set(NewE,num2);
645 boxes.Bind(NewE,B2); // update boxes
646 // replace vertex in other edge
647 Standard_Integer num21,num22;
648 if(num2>1) num21=num2-1;
649 else num21=sewd->NbEdges();
650 if(num2<sewd->NbEdges()) num22=num2+1;
652 TopoDS_Edge edge21 = sewd->Edge(num21);
653 TopoDS_Edge edge22 = sewd->Edge(num22);
654 TopoDS_Vertex V21F = sae.FirstVertex(edge21);
655 TopoDS_Vertex V21L = sae.LastVertex(edge21);
656 TopoDS_Vertex V22F = sae.FirstVertex(edge22);
657 TopoDS_Vertex V22L = sae.LastVertex(edge22);
658 if(V21F.IsSame(V2L)) {
659 NewE = sbe.CopyReplaceVertices(edge21,V1L,V21L);
660 //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
661 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
662 myContext->Replace(edge21,NewE);
663 sewd->Set(NewE,num21);
665 if(V21L.IsSame(V2L)) {
666 NewE = sbe.CopyReplaceVertices(edge21,V21F,V1L);
667 //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
668 boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
669 myContext->Replace(edge21,NewE);
670 sewd->Set(NewE,num21);
672 if(V22F.IsSame(V2L)) {
673 NewE = sbe.CopyReplaceVertices(edge22,V1L,V22L);
674 //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
675 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
676 myContext->Replace(edge22,NewE);
677 sewd->Set(NewE,num22);
679 if(V22L.IsSame(V2L)) {
680 NewE = sbe.CopyReplaceVertices(edge22,V22F,V1L);
681 //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
682 boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
683 myContext->Replace(edge22,NewE);
684 sewd->Set(NewE,num22);
694 //=======================================================================
695 //function : CreateBoxes2d
697 //=======================================================================
698 static Bnd_Box2d CreateBoxes2d(const Handle(ShapeExtend_WireData)& sewd,
699 const TopoDS_Face& face,
700 ShapeFix_DataMapOfShapeBox2d& boxes)
702 // create box2d for edges from wire
705 const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L);
706 Handle(Geom2d_Curve) c2d;
708 ShapeAnalysis_Edge sae;
709 for(Standard_Integer i=1; i<=sewd->NbEdges(); i++){
710 TopoDS_Edge E = sewd->Edge(i);
711 if(sae.PCurve(E,S,L,c2d,cf,cl,Standard_False)) {
713 Geom2dAdaptor_Curve gac;
714 Standard_Real aFirst = c2d->FirstParameter();
715 Standard_Real aLast = c2d->LastParameter();
716 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
717 && (cf < aFirst || cl > aLast)) {
718 //pdn avoiding problems with segment in Bnd_Box
723 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
732 //=======================================================================
733 //function : SelectIntPnt
735 //=======================================================================
736 static void SelectIntPnt(const Geom2dInt_GInter& Inter,
737 IntRes2d_IntersectionPoint& IP,
738 IntRes2d_Transition& Tr1,
739 IntRes2d_Transition& Tr2)
742 Tr1 = IP.TransitionOfFirst();
743 Tr2 = IP.TransitionOfSecond();
744 if(Inter.NbPoints()==2) {
745 // possible second point is better?
746 Standard_Integer status1=0,status2=0;
747 if(Tr1.PositionOnCurve()==IntRes2d_Middle) status1+=1;
748 if(Tr2.PositionOnCurve()==IntRes2d_Middle) status1+=2;
749 IntRes2d_IntersectionPoint IP2;
750 IntRes2d_Transition Tr12, Tr22;
751 IP2 = Inter.Point(2);
752 Tr12 = IP2.TransitionOfFirst();
753 Tr22 = IP2.TransitionOfSecond();
754 if(Tr12.PositionOnCurve()==IntRes2d_Middle) status2+=1;
755 if(Tr22.PositionOnCurve()==IntRes2d_Middle) status2+=2;
756 if(status2>status1) {
757 IP=IP2; Tr1=Tr12; Tr2=Tr22;
763 //=======================================================================
764 //function : FindVertAndSplitEdge
766 //=======================================================================
767 Standard_Boolean ShapeFix_IntersectionTool::FindVertAndSplitEdge
768 (const Standard_Real param1,
769 const TopoDS_Edge& edge1, const TopoDS_Edge& edge2,
770 const Handle(Geom2d_Curve)& Crv1,
771 Standard_Real& MaxTolVert,
772 Standard_Integer& num1,
773 const Handle(ShapeExtend_WireData)& sewd,
774 const TopoDS_Face& face,
775 ShapeFix_DataMapOfShapeBox2d& boxes,
776 const Standard_Boolean aTmpKey) const
778 // find needed vertex from edge2 and split edge1 using it
779 ShapeAnalysis_Edge sae;
780 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(BRep_Tool::Surface(face));
781 gp_Pnt pi1 = GetPointOnEdge(edge1,sas,Crv1,param1);
785 TopoDS_Vertex V1 = sae.FirstVertex(edge2);
786 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
787 TopoDS_Vertex V2 = sae.LastVertex(edge2);
788 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
789 TopoDS_Vertex V11 = sae.FirstVertex(edge1);
790 TopoDS_Vertex V12 = sae.LastVertex(edge1);
791 Standard_Boolean NeedSplit = Standard_True;
792 if(pi1.Distance(PV1)<pi1.Distance(PV2)) {
793 if( V1.IsSame(V11) || V1.IsSame(V12) ) {
794 NeedSplit = Standard_False;
797 tolV = Max( (pi1.Distance(PV1)/2)*1.00001, BRep_Tool::Tolerance(V1) );
800 if( V2.IsSame(V11) || V2.IsSame(V12) ) {
801 NeedSplit = Standard_False;
804 tolV = Max( (pi1.Distance(PV2)/2)*1.00001, BRep_Tool::Tolerance(V2) );
806 if( NeedSplit || aTmpKey ) {
807 if(SplitEdge1(sewd, face, num1, param1, V, tolV, boxes)) {
808 B.UpdateVertex(V,tolV);
809 MaxTolVert = Max(MaxTolVert,tolV);
812 return Standard_True;
816 return Standard_False;
820 //=======================================================================
821 //function : FixSelfIntersectWire
823 //=======================================================================
825 Standard_Boolean ShapeFix_IntersectionTool::FixSelfIntersectWire
826 (Handle(ShapeExtend_WireData)& sewd, const TopoDS_Face& face,
827 Standard_Integer& NbSplit, Standard_Integer& NbCut,
828 Standard_Integer& NbRemoved) const
830 if(myContext.IsNull() || face.IsNull()) return Standard_False;
832 //Standard_Real area2d = ShapeAnalysis::TotCross2D(sewd,face);
833 //if(area2d<Precision::PConfusion()*Precision::PConfusion()) return Standard_False; //gka 06.09.04 BUG 6555
835 TopoDS_Shape SF = face;
836 Standard_Real MaxTolVert=0.0;
837 for(TopExp_Explorer exp(SF,TopAbs_VERTEX); exp.More(); exp.Next()) {
838 Standard_Real tolV = BRep_Tool::Tolerance(TopoDS::Vertex(exp.Current()));
839 MaxTolVert = Max(MaxTolVert,tolV);
841 MaxTolVert = Min(MaxTolVert,myMaxTol);
842 ShapeAnalysis_Edge sae;
844 // step 1 : intersection of adjacent edges
846 // step 2 : intersection of non-adjacent edges
847 ShapeFix_DataMapOfShapeBox2d boxes;
848 (void)CreateBoxes2d(sewd,face,boxes);
849 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(BRep_Tool::Surface(face));
853 Standard_Integer nbReplaced =0;
854 Standard_Boolean isDone = Standard_False;
855 for(Standard_Integer num1=1; num1<sewd->NbEdges() && NbSplit<30; num1++) {
856 // for each edge from first wire
857 for(Standard_Integer num2=num1+2; num2<=sewd->NbEdges() && NbSplit<30; num2++) {
858 // for each edge from second wire
859 if( num1==1 && num2==sewd->NbEdges() ) continue;
860 TopoDS_Edge edge1 = sewd->Edge(num1);
861 TopoDS_Edge edge2 = sewd->Edge(num2);
862 if(edge1.IsSame(edge2)) continue;
863 if( BRep_Tool::Degenerated(edge1) || BRep_Tool::Degenerated(edge2) ) continue;
864 if( !boxes.IsBound(edge1) || !boxes.IsBound(edge2) ) continue;
865 Bnd_Box2d B1 = boxes.Find(edge1);
866 Bnd_Box2d B2 = boxes.Find(edge2);
868 // intersection is possible...
869 Standard_Real a1, b1, a2, b2;
870 Handle(Geom2d_Curve) Crv1, Crv2;
871 if( !sae.PCurve(edge1, face, Crv1, a1, b1, Standard_False) ) return Standard_False;
872 if( !sae.PCurve(edge2, face, Crv2, a2, b2, Standard_False) ) return Standard_False;
873 Standard_Real tolint = 1.0e-10;
874 Geom2dAdaptor_Curve C1(Crv1), C2(Crv2);
875 IntRes2d_Domain d1(C1.Value(a1),a1,tolint,C1.Value(b1),b1,tolint);
876 IntRes2d_Domain d2(C2.Value(a2),a2,tolint,C2.Value(b2),b2,tolint);
877 Geom2dInt_GInter Inter;
878 Inter.Perform( C1, d1, C2, d2, tolint, tolint );
879 if(!Inter.IsDone()) continue;
880 // intersection is point
881 if( Inter.NbPoints()>0 && Inter.NbPoints()<3 ) {
882 IntRes2d_IntersectionPoint IP;
883 IntRes2d_Transition Tr1, Tr2;
884 SelectIntPnt(Inter,IP,Tr1,Tr2);
885 if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
886 Tr2.PositionOnCurve() == IntRes2d_Middle ) {
887 Standard_Real param1 = IP.ParamOnFirst();
888 Standard_Real param2 = IP.ParamOnSecond();
889 gp_Pnt pi1 = GetPointOnEdge(edge1,sas,C1,param1);
890 gp_Pnt pi2 = GetPointOnEdge(edge2,sas,C2,param2);
893 Standard_Real tolV=0;
894 // analysis for edge1
895 Standard_Boolean ModifE1 = Standard_False;
896 TopoDS_Vertex VF1 = sae.FirstVertex(edge1);
897 gp_Pnt PVF1 = BRep_Tool::Pnt(VF1);
898 TopoDS_Vertex VL1 = sae.LastVertex(edge1);
899 gp_Pnt PVL1 = BRep_Tool::Pnt(VL1);
900 Standard_Real dist1 = pi1.Distance(PVF1);
901 Standard_Real dist2 = pi1.Distance(PVL1);
902 Standard_Real distmin = Min(dist1, dist2);
903 if( dist1 != dist2 && distmin < MaxTolVert ) {
905 tolV = Max( dist1*1.00001, BRep_Tool::Tolerance(VF1) );
906 B.UpdateVertex(VF1,tolV);
909 tolV = Max( dist2*1.00001, BRep_Tool::Tolerance(VL1) );
910 B.UpdateVertex(VL1,tolV);
914 Standard_Real dista = Abs(a1-param1);
915 Standard_Real distb = Abs(b1-param1);
916 Standard_Boolean IsCutLine;
917 ModifE1 = CutEdge(edge1, (( dista > distb ) ? a1 : b1 ), param1, face, IsCutLine);
920 //not needed split edge, if one of parts is too small
921 ModifE1 = ModifE1 || distmin < Precision::Confusion();
923 // analysis for edge2
924 Standard_Boolean ModifE2 = Standard_False;
925 TopoDS_Vertex VF2 = sae.FirstVertex(edge2);
926 gp_Pnt PVF2 = BRep_Tool::Pnt(VF2);
927 TopoDS_Vertex VL2 = sae.LastVertex(edge2);
928 gp_Pnt PVL2 = BRep_Tool::Pnt(VL2);
929 dist1 = pi2.Distance(PVF2);
930 dist2 = pi2.Distance(PVL2);
931 distmin = Min(dist1, dist2);
932 if( dist1 != dist2 && distmin < MaxTolVert ) {
934 tolV = Max( dist1*1.00001, BRep_Tool::Tolerance(VF2) );
935 B.UpdateVertex(VF2,tolV);
938 tolV = Max( dist2*1.00001, BRep_Tool::Tolerance(VL2) );
939 B.UpdateVertex(VL2,tolV);
943 Standard_Real dista = Abs(a2-param2);
944 Standard_Real distb = Abs(b2-param2);
945 Standard_Boolean IsCutLine;
946 ModifE2 = CutEdge(edge2, (( dista > distb ) ? a2 : b2 ), param2, face, IsCutLine);
949 //not needed split edge, if one of parts is too small
950 ModifE2 = ModifE2 || distmin < Precision::Confusion();
952 if( ModifE1 && !ModifE2 ) {
953 if(SplitEdge1(sewd, face, num2, param2, V, tolV, boxes)) {
960 if( !ModifE1 && ModifE2 ) {
961 if(SplitEdge1(sewd, face, num1, param1, V, tolV, boxes)) {
967 if( !ModifE1 && !ModifE2 ) {
968 gp_Pnt P0( (pi1.X()+pi2.X())/2, (pi1.Y()+pi2.Y())/2, (pi1.Z()+pi2.Z())/2 );
969 tolV = Max( (pi1.Distance(pi2)/2)*1.00001, Precision::Confusion() );
970 B.MakeVertex(V,P0,tolV);
971 MaxTolVert = Max(MaxTolVert,tolV);
972 Standard_Boolean isEdgeSplit2 = SplitEdge1(sewd, face, num2, param2,
978 if(SplitEdge1(sewd, face, num1, param1, V, tolV, boxes)) {
987 if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
988 Tr2.PositionOnCurve() != IntRes2d_Middle ) {
989 // find needed vertex from edge2 and split edge1 using it
990 Standard_Real param1 = IP.ParamOnFirst();
991 if(FindVertAndSplitEdge(param1, edge1, edge2, Crv1, MaxTolVert,
992 num1, sewd, face, boxes, Standard_False) ) {
997 if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
998 Tr2.PositionOnCurve() == IntRes2d_Middle ) {
999 // find needed vertex from edge1 and split edge2 using it
1000 Standard_Real param2 = IP.ParamOnSecond();
1001 if(FindVertAndSplitEdge(param2, edge2, edge1, Crv2, MaxTolVert,
1002 num2, sewd, face, boxes, Standard_False) ) {
1007 if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1008 Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1010 if( UnionVertexes(sewd, edge1, edge2, num2, boxes, B2) )
1011 nbReplaced ++; //gka 06.09.04
1014 // intersection is segment
1015 if( Inter.NbSegments()==1 ) {
1016 IntRes2d_IntersectionSegment IS = Inter.Segment(1);
1017 if ( IS.HasFirstPoint() && IS.HasLastPoint() ) {
1018 Standard_Boolean IsModified1 = Standard_False;
1019 Standard_Boolean IsModified2 = Standard_False;
1022 Standard_Real newtol=0.0;
1023 IntRes2d_IntersectionPoint IPF = IS.FirstPoint();
1024 Standard_Real p11 = IPF.ParamOnFirst();
1025 Standard_Real p21 = IPF.ParamOnSecond();
1026 IntRes2d_IntersectionPoint IPL = IS.LastPoint();
1027 Standard_Real p12 = IPL.ParamOnFirst();
1028 Standard_Real p22 = IPL.ParamOnSecond();
1029 gp_Pnt Pnt11 = GetPointOnEdge(edge1,sas,C1,p11);
1030 gp_Pnt Pnt12 = GetPointOnEdge(edge1,sas,C1,p12);
1031 gp_Pnt Pnt21 = GetPointOnEdge(edge2,sas,C2,p21);
1032 gp_Pnt Pnt22 = GetPointOnEdge(edge2,sas,C2,p22);
1033 // next string commented by skl 29.12.2004 for OCC7624
1034 //if( Pnt11.Distance(Pnt21)>myPreci || Pnt12.Distance(Pnt22)>myPreci ) continue;
1035 if( Pnt11.Distance(Pnt21)>MaxTolVert || Pnt12.Distance(Pnt22)>MaxTolVert ) continue;
1036 // analysis for edge1
1037 TopoDS_Vertex V1 = sae.FirstVertex(edge1);
1038 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
1039 TopoDS_Vertex V2 = sae.LastVertex(edge1);
1040 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
1041 //Standard_Real tol1 = BRep_Tool::Tolerance(V1);
1042 //Standard_Real tol2 = BRep_Tool::Tolerance(V2);
1043 //Standard_Real maxtol = Max(tol1,tol2);
1044 Standard_Real dist1 = Pnt11.Distance(PV1);
1045 Standard_Real dist2 = Pnt12.Distance(PV1);
1046 Standard_Real maxdist = Max(dist1,dist2);
1047 Standard_Real pdist;
1048 if(edge1.Orientation()==TopAbs_REVERSED)
1049 pdist = Max(Abs(b1-p11),Abs(b1-p12));
1051 pdist = Max(Abs(a1-p11),Abs(a1-p12));
1052 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1053 //if(maxdist<maxtol || pdist<Abs(b1-a1)*0.01) {
1056 IsModified1 = Standard_True;
1058 dist1 = Pnt11.Distance(PV2);
1059 dist2 = Pnt12.Distance(PV2);
1060 maxdist = Max(dist1,dist2);
1061 if(edge1.Orientation()==TopAbs_REVERSED)
1062 pdist = Max(Abs(a1-p11),Abs(a1-p12));
1064 pdist = Max(Abs(b1-p11),Abs(b1-p12));
1065 //if(maxdist<maxtol || pdist<Abs(b1-a1)*0.01) {
1066 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1067 if( ( IsModified1 && maxdist<newtol ) || !IsModified1 ) {
1070 IsModified1 = Standard_True;
1074 // cut edge1 and update tolerance NewV
1075 Standard_Real dista = Abs(a1-p11)+Abs(a1-p12);
1076 Standard_Real distb = Abs(b1-p11)+Abs(b1-p12);
1077 Standard_Real pend,cut;
1078 if(dista>distb) pend=a1;
1080 if(Abs(pend-p11)>Abs(pend-p12)) cut=p12;
1082 Standard_Boolean IsCutLine;
1083 if (CutEdge(edge1, pend, cut, face, IsCutLine))
1085 if(newtol>BRep_Tool::Tolerance(NewV)) {
1086 B.UpdateVertex(NewV,newtol);
1088 else newtol = BRep_Tool::Tolerance(NewV);
1090 // analysis for edge2
1091 TopoDS_Vertex V12 = sae.FirstVertex(edge2);
1092 gp_Pnt PV12 = BRep_Tool::Pnt(V12);
1093 TopoDS_Vertex V22 = sae.LastVertex(edge2);
1094 gp_Pnt PV22 = BRep_Tool::Pnt(V22);
1095 //tol1 = BRep_Tool::Tolerance(V1);
1096 //tol2 = BRep_Tool::Tolerance(V2);
1097 //maxtol = Max(tol1,tol2);
1098 dist1 = Pnt21.Distance(PV12);
1099 dist2 = Pnt22.Distance(PV12);
1100 maxdist = Max(dist1,dist2);
1101 if(edge2.Orientation()==TopAbs_REVERSED)
1102 pdist = Max(Abs(b2-p21),Abs(b2-p22));
1104 pdist = Max(Abs(a2-p21),Abs(a2-p22));
1105 //if(maxdist<maxtol || pdist<Abs(b2-a2)*0.01) {
1106 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1109 IsModified2 = Standard_True;
1111 dist1 = Pnt21.Distance(PV22);
1112 dist2 = Pnt22.Distance(PV22);
1113 maxdist = Max(dist1,dist2);
1114 if(edge2.Orientation()==TopAbs_REVERSED)
1115 pdist = Max(Abs(a2-p21),Abs(a2-p22));
1117 pdist = Max(Abs(b2-p21),Abs(b2-p22));
1118 //if(maxdist<maxtol || pdist<Abs(b2-a2)*0.01) {
1119 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1120 if( ( IsModified2 && maxdist<newtol ) || !IsModified2 ) {
1123 IsModified2 = Standard_True;
1127 // cut edge1 and update tolerance NewV
1128 Standard_Real dista = Abs(a2-p21)+Abs(a2-p22);
1129 Standard_Real distb = Abs(b2-p21)+Abs(b2-p22);
1130 Standard_Real pend,cut;
1131 if(dista>distb) pend=a2;
1133 if(Abs(pend-p21)>Abs(pend-p22)) cut=p22;
1135 Standard_Boolean IsCutLine;
1136 if (CutEdge(edge2, pend, cut, face, IsCutLine))
1138 if(newtol>BRep_Tool::Tolerance(NewV)) {
1139 B.UpdateVertex(NewV,newtol);
1141 else newtol = BRep_Tool::Tolerance(NewV);
1144 if( IsModified1 && !IsModified2 ) {
1145 if(SplitEdge2(sewd, face, num2, p21, p22, NewV, newtol, boxes)) {
1151 if( !IsModified1 && IsModified2 ) {
1152 if(SplitEdge2(sewd, face, num1, p11, p12, NewV, newtol, boxes)) {
1158 if( !IsModified1 && !IsModified2 ) {
1159 Standard_Real param1 = (p11+p12)/2;
1160 Standard_Real param2 = (p21+p22)/2;
1161 gp_Pnt Pnt10 = GetPointOnEdge(edge1,sas,C1,param1);
1162 gp_Pnt Pnt20 = GetPointOnEdge(edge2,sas,C2,param2);
1163 gp_Pnt P0( (Pnt10.X()+Pnt20.X())/2, (Pnt10.Y()+Pnt20.Y())/2,
1164 (Pnt10.Z()+Pnt20.Z())/2 );
1165 dist1 = Max(Pnt11.Distance(P0),Pnt12.Distance(P0));
1166 dist2 = Max(Pnt21.Distance(P0),Pnt22.Distance(P0));
1167 Standard_Real tolV = Max(dist1,dist2);
1168 tolV = Max(tolV,Pnt10.Distance(Pnt20))*1.00001;
1169 Standard_Boolean FixSegment = Standard_True;
1170 if(tolV<MaxTolVert) {
1171 // create new vertex and split each intersecting edge on two edges
1172 B.MakeVertex(NewV,Pnt10,tolV);
1173 if(SplitEdge2(sewd, face, num2, p21, p22, NewV, tolV, boxes)) {
1177 if(SplitEdge2(sewd, face, num1, p11, p12, NewV, tolV, boxes)) {
1183 else if(FixSegment) {
1184 //if( Abs(p12-p11)>Abs(b1-a1)/2 || Abs(p22-p21)>Abs(b2-a2)/2 ) {
1185 // segment is big and we have to split each intersecting edge
1186 // on 3 edges --> middle edge - edge based on segment
1187 // after we can remove edges maked from segment
1188 gp_Pnt P01( (Pnt11.X()+Pnt21.X())/2, (Pnt11.Y()+Pnt21.Y())/2,
1189 (Pnt11.Z()+Pnt21.Z())/2 );
1190 gp_Pnt P02( (Pnt12.X()+Pnt22.X())/2, (Pnt12.Y()+Pnt22.Y())/2,
1191 (Pnt12.Z()+Pnt22.Z())/2 );
1192 Standard_Real tolV1 = Max(Pnt11.Distance(P01),Pnt21.Distance(P01));
1193 tolV1 = Max(tolV1,Precision::Confusion())*1.00001;
1194 Standard_Real tolV2 = Max(Pnt12.Distance(P02),Pnt22.Distance(P02));
1195 tolV2 = Max(tolV2,Precision::Confusion())*1.00001;
1196 if( tolV1>MaxTolVert || tolV2>MaxTolVert ) continue;
1197 TopoDS_Vertex NewV1,NewV2;
1199 // parameters for splitting: a1..p11..p12..b1 and a2..p21..p22..b2 ???
1200 Standard_Integer nbseg1=3, nbseg2=3, kv1=0, kv2=0;
1201 if(P01.Distance(PV1)<Max(tolV1,BRep_Tool::Tolerance(V1))) {
1203 if(tolV1>BRep_Tool::Tolerance(V1))
1204 B.UpdateVertex(NewV1,tolV1);
1209 else if(P01.Distance(PV2)<Max(tolV1,BRep_Tool::Tolerance(V2))) {
1211 if(tolV1>BRep_Tool::Tolerance(V2))
1212 B.UpdateVertex(NewV1,tolV1);
1218 TopoDS_Edge tmpE,SegE;
1220 Standard_Integer akey1=0, akey2=0;
1221 Standard_Real newTolerance;
1223 newTolerance = Max(tolV1,BRep_Tool::Tolerance(V1));
1224 if(P01.Distance(PV1)<newTolerance) {
1225 B.MakeVertex(NewV1,BRep_Tool::Pnt(V1),newTolerance);
1226 NewV1.Orientation(V1.Orientation());
1229 newTolerance = Max(tolV1,BRep_Tool::Tolerance(V2));
1230 if(P01.Distance(PV2)<newTolerance) {
1231 B.MakeVertex(NewV1,BRep_Tool::Pnt(V2),newTolerance);
1232 NewV1.Orientation(V2.Orientation());
1236 newTolerance = Max(tolV2,BRep_Tool::Tolerance(V1));
1237 if(P02.Distance(PV1)<newTolerance) {
1238 B.MakeVertex(NewV2,BRep_Tool::Pnt(V1),newTolerance);
1239 NewV2.Orientation(V1.Orientation());
1242 newTolerance = Max(tolV2,BRep_Tool::Tolerance(V2));
1243 if(P02.Distance(PV2)<newTolerance) {
1244 B.MakeVertex(NewV2,BRep_Tool::Pnt(V2),newTolerance);
1245 NewV2.Orientation(V2.Orientation());
1248 if( akey1>1 || akey2>1 ) continue;
1249 Standard_Integer dnum1=0, numseg1=num1;
1251 if(akey1==0) B.MakeVertex(NewV1,P01,tolV1);
1252 if(akey2==0) B.MakeVertex(NewV2,P02,tolV2);
1254 if( akey1==0 && akey2>0 ) {
1255 if(SplitEdge1(sewd, face, num1, p11, NewV1, tolV1, boxes)) {
1261 if( akey1>0 && akey2==0 ) {
1262 if(SplitEdge1(sewd, face, num1, p12, NewV2, tolV2, boxes) ) {
1268 if( akey1==0 && akey2==0 ) {
1269 if(SplitEdge1(sewd, face, num1, p11, NewV1, tolV1, boxes)) {
1273 tmpE = sewd->Edge(num1);
1275 Handle(Geom2d_Curve) c2d;
1276 sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1277 if( (a-p12)*(b-p12)>0 ) { // p12 - external for [a,b] => split next edge
1278 if(SplitEdge1(sewd, face, num1+1, p12, NewV2, tolV2, boxes) ) {
1285 if(SplitEdge1(sewd, face, num1, p12, NewV2, tolV2, boxes) ) {
1292 //SegE = sewd->Edge(numseg1); // get edge from segment
1294 // replace vertices if it is necessary
1295 ShapeBuild_Edge sbe;
1298 if(P01.Distance(PV12)<tolV1) {
1299 tolV1 += P01.Distance(PV12);
1300 B.UpdateVertex(NewV1,tolV1);
1301 if(V12.Orientation()==NewV1.Orientation()) {
1302 myContext->Replace(V12,NewV1);
1306 myContext->Replace(V12,NewV1.Reversed());
1307 V12 = TopoDS::Vertex(NewV1.Reversed());
1309 nbReplaced++; //gka 06.09.04
1310 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV1,V22);
1311 myContext->Replace(edge2,NewE);
1312 sewd->Set(NewE,num2+dnum1);
1313 boxes.Bind(NewE,B2); // update boxes
1317 if(P01.Distance(PV22)<tolV1) {
1318 tolV1 += P01.Distance(PV22);
1319 B.UpdateVertex(NewV1,tolV1);
1320 if(V22.Orientation()==NewV1.Orientation()) {
1321 myContext->Replace(V22,NewV1);
1325 myContext->Replace(V22,NewV1.Reversed());
1326 V22 = TopoDS::Vertex(NewV1.Reversed());
1328 nbReplaced++; //gka 06.09.04
1329 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV1);
1330 myContext->Replace(edge2,NewE);
1331 sewd->Set(NewE,num2+dnum1);
1332 boxes.Bind(NewE,B2); // update boxes
1336 if(P02.Distance(PV12)<tolV2) {
1337 tolV2 += P02.Distance(PV12);
1338 B.UpdateVertex(NewV2,tolV2);
1339 if(V12.Orientation()==NewV2.Orientation()) {
1340 myContext->Replace(V12,NewV2);
1344 myContext->Replace(V12,NewV2.Reversed());
1345 V12 = TopoDS::Vertex(NewV2.Reversed());
1347 nbReplaced++; //gka 06.09.04
1348 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV2,V22);
1349 myContext->Replace(edge2,NewE);
1350 sewd->Set(NewE,num2+dnum1);
1351 boxes.Bind(NewE,B2); // update boxes
1355 if(P02.Distance(PV22)<tolV2) {
1356 tolV2 += P02.Distance(PV22);
1357 B.UpdateVertex(NewV2,tolV2);
1358 if(V22.Orientation()==NewV2.Orientation()) {
1359 myContext->Replace(V22,NewV2);
1363 myContext->Replace(V22,NewV2.Reversed());
1364 V22 = TopoDS::Vertex(NewV2.Reversed());
1366 nbReplaced++; //gka 06.09.04
1367 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV2);
1368 myContext->Replace(edge2,NewE);
1369 sewd->Set(NewE,num2+dnum1);
1370 boxes.Bind(NewE,B2); // update boxes
1374 Standard_Integer dnum2=0, numseg2=num2+dnum1;
1376 if( akey1==0 && akey2>0 ) {
1377 if(SplitEdge1(sewd, face, num2+dnum1, p21, NewV1, tolV1, boxes)) {
1380 //numseg2=num2+dnum1+1;
1384 if( akey1>0 && akey2==0 ) {
1385 if(SplitEdge1(sewd, face, num2+dnum1, p22, NewV2, tolV2, boxes)) {
1388 //numseg2=num2+dnum1;
1389 numseg2=num2+dnum1+1;
1392 if( akey1==0 && akey2==0 ) {
1393 if(SplitEdge1(sewd, face, num2+dnum1, p21, NewV1, tolV1, boxes)) {
1397 tmpE = sewd->Edge(num2+dnum1);
1399 Handle(Geom2d_Curve) c2d;
1400 sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1401 if( (a-p22)*(b-p22)>0 ) { // p22 - external for [a,b] => split next edge
1402 if(SplitEdge1(sewd, face, num2+dnum1+dnum2, p22, NewV2, tolV2, boxes) ) {
1404 numseg2=num2+dnum1+dnum2;
1409 if(SplitEdge1(sewd, face, num2+dnum1, p22, NewV2, tolV2, boxes) ) {
1412 numseg2=num2+dnum1+1;
1417 sewd->Remove(numseg2);
1418 sewd->Remove(numseg1);
1419 NbRemoved = NbRemoved+2;
1429 isDone = (NbSplit || NbCut || nbReplaced || NbRemoved);
1434 //=======================================================================
1435 //function : FixIntersectingWires
1437 //=======================================================================
1439 Standard_Boolean ShapeFix_IntersectionTool::FixIntersectingWires
1440 (TopoDS_Face& face) const
1442 if(myContext.IsNull() || face.IsNull()) return Standard_False;
1443 //TopoDS_Shape S = context->Apply(face);
1444 //TopoDS_Shape SF = TopoDS::Face(S);
1445 TopoDS_Shape SF = face;
1446 TopAbs_Orientation ori = face.Orientation();
1447 TopTools_SequenceOfShape SeqWir;
1448 TopTools_SequenceOfShape SeqNMShapes;
1449 for( TopoDS_Iterator iter(SF,Standard_False); iter.More(); iter.Next() ) {
1450 if(iter.Value().ShapeType() != TopAbs_WIRE ||
1451 (iter.Value().Orientation() != TopAbs_FORWARD &&
1452 iter.Value().Orientation() != TopAbs_REVERSED)) {
1453 SeqNMShapes.Append(iter.Value());
1456 TopoDS_Wire wire = TopoDS::Wire(iter.Value());
1457 SeqWir.Append(wire);
1459 if(SeqWir.Length()<2) return Standard_False;//gka 06.09.04
1461 Standard_Real MaxTolVert=0.0;
1462 for(TopExp_Explorer exp(SF,TopAbs_VERTEX); exp.More(); exp.Next()) {
1463 Standard_Real tolV = BRep_Tool::Tolerance(TopoDS::Vertex(exp.Current()));
1464 MaxTolVert = Max(MaxTolVert,tolV);
1466 Standard_Boolean isDone = Standard_False; //gka 06.09.04
1467 ShapeAnalysis_Edge sae;
1468 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface (BRep_Tool::Surface (face));
1470 // precompute edge boxes for all wires
1471 NCollection_Sequence<ShapeFix_DataMapOfShapeBox2d> aSeqWirEdgeBoxes;
1472 NCollection_Sequence<Bnd_Box2d> aSeqWirBoxes;
1473 for (Standard_Integer n = 1; n <= SeqWir.Length(); n++)
1475 const TopoDS_Wire& aWire = TopoDS::Wire (SeqWir.Value (n));
1476 Handle(ShapeExtend_WireData) aSewd = new ShapeExtend_WireData (aWire);
1477 ShapeFix_DataMapOfShapeBox2d aBoxes;
1478 Bnd_Box2d aTotalBox = CreateBoxes2d (aSewd, face, aBoxes);
1479 aSeqWirEdgeBoxes.Append (aBoxes);
1480 aSeqWirBoxes.Append (aTotalBox);
1483 for(Standard_Integer n1=1; n1<=SeqWir.Length()-1; n1++) {
1484 TopoDS_Wire wire1 = TopoDS::Wire(SeqWir.Value(n1));
1485 Handle(ShapeExtend_WireData) sewd1 = new ShapeExtend_WireData(wire1);
1486 ShapeFix_DataMapOfShapeBox2d& boxes1 = aSeqWirEdgeBoxes.ChangeValue (n1);
1487 Bnd_Box2d aBox1 = aSeqWirBoxes (n1);
1488 for(Standard_Integer n2=n1+1; n2<=SeqWir.Length(); n2++) {
1489 TopoDS_Wire wire2 = TopoDS::Wire(SeqWir.Value(n2));
1490 Handle(ShapeExtend_WireData) sewd2 = new ShapeExtend_WireData(wire2);
1491 ShapeFix_DataMapOfShapeBox2d& boxes2 = aSeqWirEdgeBoxes.ChangeValue (n2);
1492 Bnd_Box2d aBox2 = aSeqWirBoxes (n2);
1493 if (!aBox1.IsVoid() && !aBox2.IsVoid() && aBox1.IsOut (aBox2))
1497 // detect possible intersections:
1498 Standard_Integer NbModif=0;
1499 Standard_Integer nbReplaced =0;//gka 06.09.04
1500 Standard_Boolean hasModifWire = Standard_False; //gka 06.09.04
1501 for(Standard_Integer num1 = 1; num1<=sewd1->NbEdges() && NbModif<30; num1++) {
1502 // for each edge from first wire
1503 TopoDS_Edge edge1 = sewd1->Edge(num1); //gka 06.09.04
1505 for(Standard_Integer num2 = 1; num2<=sewd2->NbEdges() && NbModif<30; num2++) {
1506 // for each edge from second wire
1507 TopoDS_Edge edge2 = sewd2->Edge(num2);
1508 if(edge1.IsSame(edge2)) continue;
1509 if( BRep_Tool::Degenerated(edge1) || BRep_Tool::Degenerated(edge2) ) continue;
1510 if( !boxes1.IsBound(edge1) || !boxes2.IsBound(edge2) ) continue;
1511 Bnd_Box2d B1 = boxes1.Find(edge1);
1512 Bnd_Box2d B2 = boxes2.Find(edge2);
1514 // intersection is possible...
1515 Standard_Real a1, b1, a2, b2;
1516 Handle(Geom2d_Curve) Crv1, Crv2;
1517 if( !sae.PCurve(edge1, face, Crv1, a1, b1, Standard_False) )
1518 continue; //return Standard_False; gka 06.09.04
1519 if( !sae.PCurve(edge2, face, Crv2, a2, b2, Standard_False) )
1520 continue; //return Standard_False;gka 06.09.04
1521 Standard_Real tolint = 1.0e-10;
1522 Geom2dAdaptor_Curve C1(Crv1), C2(Crv2);
1523 IntRes2d_Domain d1(C1.Value(a1),a1,tolint,C1.Value(b1),b1,tolint);
1524 IntRes2d_Domain d2(C2.Value(a2),a2,tolint,C2.Value(b2),b2,tolint);
1525 Geom2dInt_GInter Inter;
1526 Inter.Perform( C1, d1, C2, d2, tolint, tolint );
1527 if(!Inter.IsDone()) continue;
1528 // intersection is point
1529 if( Inter.NbPoints()>0 && Inter.NbPoints()<3 ) {
1530 IntRes2d_IntersectionPoint IP;
1531 IntRes2d_Transition Tr1, Tr2;
1532 SelectIntPnt(Inter,IP,Tr1,Tr2);
1533 if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
1534 Tr2.PositionOnCurve() == IntRes2d_Middle ) {
1535 // create new vertex and split both edges
1536 Standard_Real param1 = IP.ParamOnFirst();
1537 Standard_Real param2 = IP.ParamOnSecond();
1538 gp_Pnt pi1 = GetPointOnEdge(edge1,sas,C1,param1);
1539 gp_Pnt pi2 = GetPointOnEdge(edge2,sas,C2,param2);
1540 gp_Pnt P0( (pi1.X()+pi2.X())/2, (pi1.Y()+pi2.Y())/2, (pi1.Z()+pi2.Z())/2 );
1543 Standard_Real tolV = Max( (pi1.Distance(pi2)/2)*1.00001, Precision::Confusion() );
1544 B.MakeVertex(V,P0,tolV);
1545 MaxTolVert = Max(MaxTolVert,tolV);
1546 Standard_Boolean isSplitEdge2 = SplitEdge1(sewd2, face, num2, param2,
1552 if(SplitEdge1(sewd1, face, num1, param1, V, tolV, boxes1)) {
1560 if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
1561 Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1562 // find needed vertex from edge2 and split edge1 using it
1563 Standard_Real param1 = IP.ParamOnFirst();
1564 if(FindVertAndSplitEdge(param1, edge1, edge2, Crv1, MaxTolVert,
1565 num1, sewd1, face, boxes1, Standard_True) ) {
1570 if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1571 Tr2.PositionOnCurve() == IntRes2d_Middle ) {
1572 // find needed vertex from edge1 and split edge2 using it
1573 Standard_Real param2 = IP.ParamOnSecond();
1574 if(FindVertAndSplitEdge(param2, edge2, edge1, Crv2, MaxTolVert,
1575 num2, sewd2, face, boxes2, Standard_True) ) {
1580 if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1581 Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1583 if( UnionVertexes(sewd2, edge1, edge2, num2, boxes2, B2) )
1584 nbReplaced ++; //gka 06.09.04
1587 hasModifWire = (hasModifWire || NbModif || nbReplaced);
1588 // intersection is segment
1589 if( Inter.NbSegments()==1 ) {
1590 IntRes2d_IntersectionSegment IS = Inter.Segment(1);
1591 if ( IS.HasFirstPoint() && IS.HasLastPoint() ) {
1592 Standard_Boolean IsModified1 = Standard_False;
1593 Standard_Boolean IsModified2 = Standard_False;
1596 Standard_Real newtol=0.0;
1597 IntRes2d_IntersectionPoint IPF = IS.FirstPoint();
1598 Standard_Real p11 = IPF.ParamOnFirst();
1599 Standard_Real p21 = IPF.ParamOnSecond();
1600 IntRes2d_IntersectionPoint IPL = IS.LastPoint();
1601 Standard_Real p12 = IPL.ParamOnFirst();
1602 Standard_Real p22 = IPL.ParamOnSecond();
1603 gp_Pnt Pnt11 = GetPointOnEdge(edge1,sas,C1,p11);
1604 gp_Pnt Pnt12 = GetPointOnEdge(edge1,sas,C1,p12);
1605 gp_Pnt Pnt21 = GetPointOnEdge(edge2,sas,C2,p21);
1606 gp_Pnt Pnt22 = GetPointOnEdge(edge2,sas,C2,p22);
1608 // analysis for edge1
1609 TopoDS_Vertex V1 = sae.FirstVertex(edge1);
1610 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
1611 TopoDS_Vertex V2 = sae.LastVertex(edge1);
1612 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
1613 Standard_Real dist1 = Pnt11.Distance(PV1);
1614 Standard_Real dist2 = Pnt12.Distance(PV1);
1615 Standard_Real maxdist = Max(dist1,dist2);
1616 Standard_Real pdist;
1617 if(edge1.Orientation()==TopAbs_REVERSED)
1618 pdist = Max(Abs(b1-p11),Abs(b1-p12));
1620 pdist = Max(Abs(a1-p11),Abs(a1-p12));
1621 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1624 IsModified1 = Standard_True;
1626 dist1 = Pnt11.Distance(PV2);
1627 dist2 = Pnt12.Distance(PV2);
1628 maxdist = Max(dist1,dist2);
1629 if(edge1.Orientation()==TopAbs_REVERSED)
1630 pdist = Max(Abs(a1-p11),Abs(a1-p12));
1632 pdist = Max(Abs(b1-p11),Abs(b1-p12));
1633 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1634 if( ( IsModified1 && maxdist<newtol ) || !IsModified1 ) {
1637 IsModified1 = Standard_True;
1641 // cut edge1 and update tolerance NewV
1642 Standard_Real dista = Abs(a1-p11)+Abs(a1-p12);
1643 Standard_Real distb = Abs(b1-p11)+Abs(b1-p12);
1644 Standard_Real pend,cut;
1645 if(dista>distb) pend=a1;
1647 if(Abs(pend-p11)>Abs(pend-p12)) cut=p12;
1649 Standard_Boolean IsCutLine;
1650 CutEdge(edge1, pend, cut, face, IsCutLine);
1651 if(newtol>BRep_Tool::Tolerance(NewV)) {
1652 B.UpdateVertex(NewV,newtol*1.00001);
1656 // analysis for edge2
1657 TopoDS_Vertex V12 = sae.FirstVertex(edge2);
1658 gp_Pnt PV12 = BRep_Tool::Pnt(V12);
1659 TopoDS_Vertex V22 = sae.LastVertex(edge2);
1660 gp_Pnt PV22 = BRep_Tool::Pnt(V22);
1661 dist1 = Pnt21.Distance(PV12);
1662 dist2 = Pnt22.Distance(PV12);
1663 maxdist = Max(dist1,dist2);
1664 if(edge2.Orientation()==TopAbs_REVERSED)
1665 pdist = Max(Abs(b2-p21),Abs(b2-p22));
1667 pdist = Max(Abs(a2-p21),Abs(a2-p22));
1668 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1671 IsModified2 = Standard_True;
1673 dist1 = Pnt21.Distance(PV22);
1674 dist2 = Pnt22.Distance(PV22);
1675 maxdist = Max(dist1,dist2);
1676 if(edge2.Orientation()==TopAbs_REVERSED)
1677 pdist = Max(Abs(a2-p21),Abs(a2-p22));
1679 pdist = Max(Abs(b2-p21),Abs(b2-p22));
1680 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1681 if( ( IsModified2 && maxdist<newtol ) || !IsModified2 ) {
1684 IsModified2 = Standard_True;
1688 // cut edge1 and update tolerance NewV
1689 Standard_Real dista = Abs(a2-p21)+Abs(a2-p22);
1690 Standard_Real distb = Abs(b2-p21)+Abs(b2-p22);
1691 Standard_Real pend,cut;
1692 if(dista>distb) pend=a2;
1694 if(Abs(pend-p21)>Abs(pend-p22)) cut=p22;
1696 Standard_Boolean IsCutLine;
1697 CutEdge(edge2, pend, cut, face, IsCutLine);
1698 if(newtol>BRep_Tool::Tolerance(NewV)) {
1699 B.UpdateVertex(NewV,newtol*1.00001);
1703 if( IsModified1 || IsModified2 ) {
1705 hasModifWire = Standard_True; //gka 06.09.04
1709 // create new vertex and split edge1 and edge2 using it
1710 if( Abs(p12-p11)>Abs(b1-a1)/2 || Abs(p22-p21)>Abs(b2-a2)/2 ) {
1711 // segment is big and we have to split each intersecting edge
1712 // on 3 edges --> middle edge - edge based on segment
1713 gp_Pnt P01( (Pnt11.X()+Pnt21.X())/2, (Pnt11.Y()+Pnt21.Y())/2,
1714 (Pnt11.Z()+Pnt21.Z())/2 );
1715 gp_Pnt P02( (Pnt12.X()+Pnt22.X())/2, (Pnt12.Y()+Pnt22.Y())/2,
1716 (Pnt12.Z()+Pnt22.Z())/2 );
1717 Standard_Real tolV1 = Max(Pnt11.Distance(P01),Pnt21.Distance(P01));
1718 tolV1 = Max(tolV1,Precision::Confusion())*1.00001;
1719 Standard_Real tolV2 = Max(Pnt12.Distance(P02),Pnt22.Distance(P02));
1720 tolV2 = Max(tolV2,Precision::Confusion())*1.00001;
1721 if( tolV1>MaxTolVert || tolV2>MaxTolVert ) continue;
1723 hasModifWire = Standard_True; //gka 06.09.04
1724 TopoDS_Vertex NewV1,NewV2;
1725 TopoDS_Edge tmpE,SegE;
1727 Standard_Integer akey1=0, akey2=0;
1729 if(P01.Distance(PV1)<Max(tolV1,BRep_Tool::Tolerance(V1))) {
1731 if(tolV1>BRep_Tool::Tolerance(V1))
1732 B.UpdateVertex(NewV1,tolV1);
1735 if(P01.Distance(PV2)<Max(tolV1,BRep_Tool::Tolerance(V2))) {
1737 if(tolV1>BRep_Tool::Tolerance(V2))
1738 B.UpdateVertex(NewV1,tolV1);
1742 if(P02.Distance(PV1)<Max(tolV2,BRep_Tool::Tolerance(V1))) {
1744 if(tolV2>BRep_Tool::Tolerance(V1))
1745 B.UpdateVertex(NewV2,tolV2);
1748 if(P02.Distance(PV2)<Max(tolV2,BRep_Tool::Tolerance(V2))) {
1750 if(tolV2>BRep_Tool::Tolerance(V2))
1751 B.UpdateVertex(NewV2,tolV2);
1754 if( akey1>1 || akey2>1 ) continue;
1756 if(akey1==0) B.MakeVertex(NewV1,P01,tolV1);
1757 if(akey2==0) B.MakeVertex(NewV2,P02,tolV2);
1759 Standard_Integer numseg1=num1;
1760 if( akey1==0 && akey2>0 ) {
1761 if(SplitEdge1(sewd1, face, num1, p11, NewV1, tolV1, boxes1)) {
1766 if( akey1>0 && akey2==0 ) {
1767 if(SplitEdge1(sewd1, face, num1, p12, NewV2, tolV2, boxes1) ) {
1772 if( akey1==0 && akey2==0 ) {
1773 if(SplitEdge1(sewd1, face, num1, p11, NewV1, tolV1, boxes1)) {
1776 tmpE = sewd1->Edge(num1);
1778 Handle(Geom2d_Curve) c2d;
1779 sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1780 if( (a-p12)*(b-p12)>0 ) { // p12 - external for [a,b] => split next edge
1781 if(SplitEdge1(sewd1, face, num1+1, p12, NewV2, tolV2, boxes1) ) {
1787 if(SplitEdge1(sewd1, face, num1, p12, NewV2, tolV2, boxes1) ) {
1793 SegE = sewd1->Edge(numseg1); // get edge from segment
1795 // replace vertices if it is necessary
1796 ShapeBuild_Edge sbe;
1798 if(P01.Distance(PV12)<tolV1) {
1799 tolV1 += P01.Distance(PV12);
1800 B.UpdateVertex(NewV1,tolV1);
1802 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV1,V22);
1803 myContext->Replace(edge2,NewE);
1804 sewd2->Set(NewE,num2);
1805 boxes2.Bind(NewE,B2); // update boxes2
1809 if(P01.Distance(PV22)<tolV1) {
1810 tolV1 += P01.Distance(PV22);
1811 B.UpdateVertex(NewV1,tolV1);
1813 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV1);
1814 myContext->Replace(edge2,NewE);
1815 sewd2->Set(NewE,num2);
1816 boxes2.Bind(NewE,B2); // update boxes2
1820 if(P02.Distance(PV12)<tolV2) {
1821 tolV2 += P02.Distance(PV12);
1822 B.UpdateVertex(NewV2,tolV2);
1824 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV2,V22);
1825 myContext->Replace(edge2,NewE);
1826 sewd2->Set(NewE,num2);
1827 boxes2.Bind(NewE,B2); // update boxes2
1831 if(P02.Distance(PV22)<tolV2) {
1832 tolV2 += P02.Distance(PV22);
1833 B.UpdateVertex(NewV2,tolV2);
1835 TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV2);
1836 myContext->Replace(edge2,NewE);
1837 sewd2->Set(NewE,num2);
1838 boxes2.Bind(NewE,B2); // update boxes2
1843 Standard_Integer numseg2=num2;
1844 if( akey1==0 && akey2>0 ) {
1845 if(SplitEdge1(sewd2, face, num2, p21, NewV1, tolV1, boxes2)) {
1850 if( akey1>0 && akey2==0 ) {
1851 if(SplitEdge1(sewd2, face, num2, p22, NewV2, tolV2, boxes2)) {
1856 if( akey1==0 && akey2==0 ) {
1857 if(SplitEdge1(sewd2, face, num2, p21, NewV1, tolV1, boxes2)) {
1861 tmpE = sewd2->Edge(num2);
1863 Handle(Geom2d_Curve) c2d;
1864 sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1865 if( (a-p22)*(b-p22)>0 ) { // p22 - external for [a,b] => split next edge
1866 if(SplitEdge1(sewd2, face, num2+1, p22, NewV2, tolV2, boxes2) ) {
1872 if(SplitEdge1(sewd2, face, num2, p22, NewV2, tolV2, boxes2) ) {
1878 tmpE = sewd2->Edge(numseg2);
1879 boxes2.Bind(tmpE,boxes1.Find(SegE)); // update boxes2
1880 if(!sae.FirstVertex(SegE).IsSame(sae.FirstVertex(tmpE))) {
1883 myContext->Replace(tmpE,SegE);
1884 sewd2->Set(SegE,numseg2);
1889 // split each intersecting edge on two edges
1890 gp_Pnt P0( (Pnt11.X()+Pnt12.X())/2, (Pnt11.Y()+Pnt12.Y())/2,
1891 (Pnt11.Z()+Pnt12.Z())/2 );
1892 Standard_Real param1 = (p11+p12)/2;
1893 Standard_Real param2 = (p21+p22)/2;
1894 gp_Pnt Pnt10 = GetPointOnEdge(edge1,sas,C1,param1);
1895 gp_Pnt Pnt20 = GetPointOnEdge(edge2,sas,C2,param2);
1896 dist1 = Max(Pnt11.Distance(P0),Pnt12.Distance(Pnt10));
1897 dist2 = Max(Pnt21.Distance(P0),Pnt22.Distance(Pnt10));
1898 Standard_Real tolV = Max(dist1,dist2);
1899 tolV = Max(tolV,Pnt10.Distance(Pnt20))*1.00001;
1900 B.MakeVertex(NewV,Pnt10,tolV);
1901 MaxTolVert = Max(MaxTolVert,tolV);
1902 hasModifWire = Standard_True;
1903 if(SplitEdge2(sewd2, face, num2, p21, p22, NewV, tolV, boxes2)) {
1907 if(SplitEdge2(sewd1, face, num1, p11, p12, NewV, tolV, boxes1)) {
1915 } // end if(Inter.NbSegments()==1)
1921 isDone = Standard_True;
1922 SeqWir.SetValue(n1,sewd1->Wire());
1923 myContext->Replace( wire1, sewd1->Wire() );
1924 wire1 = sewd1->Wire();
1925 //recompute boxes for wire1
1927 Bnd_Box2d aNewBox1 = CreateBoxes2d (sewd1, face, boxes1);
1928 aSeqWirBoxes.SetValue (n1, aNewBox1);
1929 SeqWir.SetValue(n2,sewd2->Wire());
1930 myContext->Replace( wire2, sewd2->Wire() );
1931 wire2 = sewd2->Wire();
1932 //recompute boxes for wire2
1934 Bnd_Box2d aNewBox2 = CreateBoxes2d (sewd2, face, boxes2);
1935 aSeqWirBoxes.SetValue (n2, aNewBox2);
1943 TopoDS_Shape emptyCopied = face.EmptyCopied();
1944 TopoDS_Face newface = TopoDS::Face (emptyCopied);
1945 newface.Orientation(TopAbs_FORWARD);
1947 Standard_Integer i=1;
1948 for(i=1 ; i<=SeqWir.Length(); i++) {
1949 TopoDS_Wire wire = TopoDS::Wire(SeqWir.Value(i));
1950 B.Add(newface,wire);
1952 for(i=1 ; i<=SeqNMShapes.Length(); i++) {
1953 TopoDS_Shape aNMS = SeqNMShapes.Value(i);
1954 B.Add(newface,aNMS);
1956 newface.Orientation(ori);
1957 myContext->Replace(face,newface);