1 // Created on: 2004-07-14
2 // Created by: Sergey KUUL
3 // Copyright (c) 2004-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <ShapeFix_SplitTool.ixx>
18 #include <ShapeAnalysis_Edge.hxx>
19 #include <ShapeAnalysis_Surface.hxx>
20 #include <ShapeAnalysis_TransferParametersProj.hxx>
21 #include <ShapeFix_Edge.hxx>
22 #include <ShapeBuild_Edge.hxx>
23 #include <ShapeExtend_WireData.hxx>
24 #include <Geom_Curve.hxx>
25 #include <Geom2d_Curve.hxx>
26 #include <Geom2d_TrimmedCurve.hxx>
27 #include <Geom2d_Line.hxx>
29 #include <BRep_Tool.hxx>
30 #include <BRep_Builder.hxx>
31 #include <BRepTools.hxx>
33 #include <TopoDS_Wire.hxx>
34 #include <TopExp_Explorer.hxx>
35 #include <ShapeAnalysis_Curve.hxx>
38 //=======================================================================
39 //function : ShapeFix_SplitTool()
40 //purpose : Constructor
41 //=======================================================================
43 ShapeFix_SplitTool::ShapeFix_SplitTool()
48 //=======================================================================
49 //function : SplitEdge
51 //=======================================================================
53 Standard_Boolean ShapeFix_SplitTool::SplitEdge(const TopoDS_Edge& edge,
54 const Standard_Real param,
55 const TopoDS_Vertex& vert,
56 const TopoDS_Face& face,
59 const Standard_Real tol3d,
60 const Standard_Real tol2d) const
63 ShapeAnalysis_Edge sae;
64 Handle(Geom2d_Curve) c2d;
65 sae.PCurve(edge,face,c2d,a,b,Standard_True );
66 if( Abs(a-param)<tol2d || Abs(b-param)<tol2d )
67 return Standard_False;
68 // check distanse between edge and new vertex
71 if(BRep_Tool::SameParameter(edge)) {
73 const Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,L,f,l);
75 return Standard_False;
76 P1 = c3d->Value(param);
77 if(!L.IsIdentity()) P1 = P1.Transformed(L.Transformation());
80 Handle(Geom_Surface) surf = BRep_Tool::Surface(face,L);
81 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(surf);
82 P1 = sas->Value(c2d->Value(param));
83 if(!L.IsIdentity()) P1 = P1.Transformed(L.Transformation());
85 gp_Pnt P2 = BRep_Tool::Pnt(vert);
86 if(P1.Distance(P2)>tol3d) {
87 //return Standard_False;
89 B.UpdateVertex(vert,P1.Distance(P2));
92 Handle(ShapeAnalysis_TransferParametersProj) transferParameters =
93 new ShapeAnalysis_TransferParametersProj;
94 transferParameters->SetMaxTolerance(tol3d);
95 transferParameters->Init(edge,face);
96 Standard_Real first, last;
107 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
108 TopAbs_Orientation orient = edge.Orientation();
110 TopoDS_Edge wE = edge;
111 wE.Orientation ( TopAbs_FORWARD );
112 TopoDS_Shape aTmpShape = vert.Oriented(TopAbs_REVERSED); //for porting
113 newE1 = sbe.CopyReplaceVertices ( wE, sae.FirstVertex(wE), TopoDS::Vertex(aTmpShape) );
114 sbe.CopyPCurves ( newE1, wE );
115 transferParameters->TransferRange(newE1,first,param,Standard_True);
116 B.SameRange(newE1,Standard_False);
117 sfe->FixSameParameter(newE1);
118 //B.SameParameter(newE1,Standard_False);
119 aTmpShape = vert.Oriented(TopAbs_FORWARD);
120 newE2 = sbe.CopyReplaceVertices ( wE, TopoDS::Vertex(aTmpShape),sae.LastVertex(wE) );
121 sbe.CopyPCurves ( newE2, wE );
122 transferParameters->TransferRange(newE2,param,last,Standard_True);
123 B.SameRange(newE2,Standard_False);
124 sfe->FixSameParameter(newE2);
125 //B.SameParameter(newE2,Standard_False);
127 newE1.Orientation(orient);
128 newE2.Orientation(orient);
129 if (orient==TopAbs_REVERSED) {
130 TopoDS_Edge tmp = newE2; newE2 = newE1; newE1=tmp;
133 return Standard_True;
137 //=======================================================================
138 //function : SplitEdge
140 //=======================================================================
142 Standard_Boolean ShapeFix_SplitTool::SplitEdge(const TopoDS_Edge& edge,
143 const Standard_Real param1,
144 const Standard_Real param2,
145 const TopoDS_Vertex& vert,
146 const TopoDS_Face& face,
149 const Standard_Real tol3d,
150 const Standard_Real tol2d) const
152 Standard_Real param = (param1+param2)/2;
153 if(SplitEdge(edge,param,vert,face,newE1,newE2,tol3d,tol2d)) {
154 // cut new edges by param1 and param2
155 Standard_Boolean IsCutLine;
156 Handle(Geom2d_Curve) Crv1, Crv2;
157 Standard_Real fp1,lp1,fp2,lp2;
158 ShapeAnalysis_Edge sae;
159 if(sae.PCurve ( newE1, face, Crv1, fp1, lp1, Standard_False )) {
160 if(sae.PCurve ( newE2, face, Crv2, fp2, lp2, Standard_False )) {
162 if( (lp1-fp1)*(lp1-param1)>0 ) {
163 CutEdge(newE1, fp1, param1, face, IsCutLine);
164 CutEdge(newE2, lp2, param2, face, IsCutLine);
167 CutEdge(newE1, fp1, param2, face, IsCutLine);
168 CutEdge(newE2, lp2, param1, face, IsCutLine);
172 if( (fp1-lp1)*(fp1-param1)>0 ) {
173 CutEdge(newE1, lp1, param1, face, IsCutLine);
174 CutEdge(newE2, fp2, param2, face, IsCutLine);
177 CutEdge(newE1, lp1, param2, face, IsCutLine);
178 CutEdge(newE2, fp2, param1, face, IsCutLine);
183 return Standard_True;
185 return Standard_False;
189 //=======================================================================
192 //=======================================================================
194 Standard_Boolean ShapeFix_SplitTool::CutEdge(const TopoDS_Edge &edge,
195 const Standard_Real pend,
196 const Standard_Real cut,
197 const TopoDS_Face &face,
198 Standard_Boolean &iscutline) const
200 if( Abs(cut-pend)<10.*Precision::PConfusion() ) return Standard_False;
201 Standard_Real aRange = Abs(cut-pend);
203 BRep_Tool::Range(edge, a, b);
204 iscutline = Standard_False;
205 if( aRange<10.*Precision::PConfusion() ) return Standard_False;
207 // case pcurve is trimm of line
208 if( !BRep_Tool::SameParameter(edge) ) {
209 ShapeAnalysis_Edge sae;
210 Handle(Geom2d_Curve) Crv;
212 if ( sae.PCurve(edge,face,Crv,fp,lp,Standard_False) ) {
213 if(Crv->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
214 Handle(Geom2d_TrimmedCurve) tc = Handle(Geom2d_TrimmedCurve)::DownCast(Crv);
215 if(tc->BasisCurve()->IsKind(STANDARD_TYPE(Geom2d_Line))) {
217 B.Range(edge,Min(pend,cut),Max(pend,cut));
218 if( Abs(pend-lp)<Precision::PConfusion() ) { // cut from the begining
219 Standard_Real cut3d = (cut-fp)*(b-a)/(lp-fp);
220 if(cut3d <= Precision::PConfusion())
221 return Standard_False;
222 B.Range(edge, a+cut3d, b, Standard_True);
223 iscutline = Standard_True;
225 else if( Abs(pend-fp)<Precision::PConfusion() ) { // cut from the end
226 Standard_Real cut3d = (lp-cut)*(b-a)/(lp-fp);
227 if(cut3d <= Precision::PConfusion())
228 return Standard_False;
229 B.Range(edge, a, b-cut3d, Standard_True);
230 iscutline = Standard_True;
235 return Standard_True;
238 // det-study on 03/12/01 checking the old and new ranges
239 if( Abs(Abs(a-b)-aRange) < Precision::PConfusion() ) return Standard_False;
240 if( aRange<10.*Precision::PConfusion() ) return Standard_False;
242 Handle(Geom_Curve) c = BRep_Tool::Curve(edge, a, b);
243 ShapeAnalysis_Curve sac;
246 Standard_Real na = a, nb = b;
249 if (!BRep_Tool::Degenerated(edge) && !c.IsNull() && sac.ValidateRange(c, na, nb, Precision::PConfusion()) && (na != a || nb != b) )
251 B.Range( edge, na, nb, Standard_True );
252 ShapeAnalysis_Edge sae;
253 if(sae.HasPCurve(edge,face))
255 B.SameRange(edge,Standard_False);
259 sfe.FixSameParameter(edge);
263 B.Range( edge, a, b, Standard_False );
266 return Standard_True;
270 //=======================================================================
271 //function : SplitEdge
273 //=======================================================================
275 Standard_Boolean ShapeFix_SplitTool::SplitEdge(const TopoDS_Edge& edge,
276 const Standard_Real fp,
277 const TopoDS_Vertex& V1,
278 const Standard_Real lp,
279 const TopoDS_Vertex& V2,
280 const TopoDS_Face& face,
281 TopTools_SequenceOfShape& SeqE,
282 Standard_Integer& aNum,
283 const Handle(ShapeBuild_ReShape)& context,
284 const Standard_Real tol3d,
285 const Standard_Real tol2d) const
287 if(fabs(lp-fp)<tol2d)
288 return Standard_False;
293 ShapeAnalysis_Edge sae;
294 Handle(Geom2d_Curve) c2d;
295 sae.PCurve(edge,face,c2d,a,b,Standard_True);
296 TopoDS_Vertex VF = sae.FirstVertex(edge);
297 TopoDS_Vertex VL = sae.LastVertex(edge);
298 Standard_Real tolVF = BRep_Tool::Tolerance(VF);
299 Standard_Real tolVL = BRep_Tool::Tolerance(VL);
300 Standard_Real tolV1 = BRep_Tool::Tolerance(V1);
301 Standard_Real tolV2 = BRep_Tool::Tolerance(V2);
302 gp_Pnt PVF = BRep_Tool::Pnt(VF);
303 gp_Pnt PVL = BRep_Tool::Pnt(VL);
304 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
305 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
307 Standard_Real par1,par2;
308 Standard_Boolean IsReverse = Standard_False;
309 if( (b-a)*(lp-fp)>0 ) {
316 IsReverse = Standard_True;
319 if( fabs(a-par1)<=tol2d && fabs(b-par2)<=tol2d ) {
321 Standard_Real newtol = tolVF + PVF.Distance(PV2);
322 if(tolV2<newtol) B.UpdateVertex(V2,newtol);
323 if(VF.Orientation()==V2.Orientation()) {
324 context->Replace(VF,V2);
328 context->Replace(VF,V2.Reversed());
329 VF = TopoDS::Vertex(V2.Reversed());
331 newtol = tolVL + PVL.Distance(PV1);
332 if(tolV1<newtol) B.UpdateVertex(V1,newtol);
333 if(VL.Orientation()==V1.Orientation()) {
334 context->Replace(VL,V1);
338 context->Replace(VL,V1.Reversed());
339 VL = TopoDS::Vertex(V1.Reversed());
343 Standard_Real newtol = tolVF + PVF.Distance(PV1);
344 if(tolV1<newtol) B.UpdateVertex(V1,newtol);
345 if(VF.Orientation()==V1.Orientation()) {
346 context->Replace(VF,V1);
350 context->Replace(VF,V1.Reversed());
351 VF = TopoDS::Vertex(V1.Reversed());
353 newtol = tolVL + PVL.Distance(PV2);
354 if(tolV2<newtol) B.UpdateVertex(V2,newtol);
355 if(VL.Orientation()==V2.Orientation()) {
356 context->Replace(VL,V2);
360 context->Replace(VL,V2.Reversed());
361 VL = TopoDS::Vertex(V2.Reversed());
368 if( fabs(a-par1)<=tol2d && fabs(b-par2)>tol2d ) {
369 TopoDS_Edge newE1, newE2;
371 if(!SplitEdge(edge,par2,V1,face,newE1,newE2,tol3d,tol2d))
372 return Standard_False;
373 Standard_Real newtol = tolVF + PVF.Distance(PV2);
374 if(tolV2<newtol) B.UpdateVertex(V2,newtol);
375 if(VF.Orientation()==V2.Orientation()) {
376 context->Replace(VF,V2);
380 context->Replace(VF,V2.Reversed());
381 VF = TopoDS::Vertex(V2.Reversed());
385 if(!SplitEdge(edge,par2,V2,face,newE1,newE2,tol3d,tol2d))
386 return Standard_False;
387 Standard_Real newtol = tolVF + PVF.Distance(PV1);
388 if(tolV1<newtol) B.UpdateVertex(V1,newtol);
389 if(VF.Orientation()==V1.Orientation()) {
390 context->Replace(VF,V1);
394 context->Replace(VF,V1.Reversed());
395 VF = TopoDS::Vertex(V1.Reversed());
403 if( fabs(a-par1)>tol2d && fabs(b-par2)<=tol2d ) {
404 TopoDS_Edge newE1, newE2;
406 if(!SplitEdge(edge,par1,V2,face,newE1,newE2,tol3d,tol2d))
407 return Standard_False;
408 Standard_Real newtol = tolVL + PVL.Distance(PV1);
409 if(tolV1<newtol) B.UpdateVertex(V1,newtol);
410 if(VL.Orientation()==V1.Orientation()) {
411 context->Replace(VL,V1);
415 context->Replace(VL,V1.Reversed());
416 VL = TopoDS::Vertex(V1.Reversed());
420 if(!SplitEdge(edge,par1,V1,face,newE1,newE2,tol3d,tol2d))
421 return Standard_False;
422 Standard_Real newtol = tolVL + PVL.Distance(PV2);
423 if(tolV2<newtol) B.UpdateVertex(V2,newtol);
424 if(VL.Orientation()==V2.Orientation()) {
425 context->Replace(VL,V2);
429 context->Replace(VL,V2.Reversed());
430 VL = TopoDS::Vertex(V2.Reversed());
438 if( fabs(a-par1)>tol2d && fabs(b-par2)>tol2d ) {
439 TopoDS_Edge newE1,newE2,newE3,newE4;
441 if(!SplitEdge(edge,par1,V2,face,newE1,newE2,tol3d,tol2d))
442 return Standard_False;
443 if(!SplitEdge(newE2,par2,V1,face,newE3,newE4,tol3d,tol2d))
444 return Standard_False;
447 if(!SplitEdge(edge,par1,V1,face,newE1,newE2,tol3d,tol2d))
448 return Standard_False;
449 if(!SplitEdge(newE2,par2,V2,face,newE3,newE4,tol3d,tol2d))
450 return Standard_False;
458 if(aNum==0) return Standard_False;
460 Handle(ShapeExtend_WireData) sewd = new ShapeExtend_WireData;
461 for(Standard_Integer i=1; i<=SeqE.Length(); i++) {
462 sewd->Add(SeqE.Value(i));
464 context->Replace(edge,sewd->Wire());
465 for (TopExp_Explorer exp ( sewd->Wire(), TopAbs_EDGE ); exp.More(); exp.Next() ) {
466 TopoDS_Edge E = TopoDS::Edge ( exp.Current() );
467 BRepTools::Update(E);
470 return Standard_True;