b311480e |
1 | // Created on: 2004-07-14 |
2 | // Created by: Sergey KUUL |
973c2be1 |
3 | // Copyright (c) 2004-2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
7fd59977 |
15 | |
7fd59977 |
16 | |
42cf5bc1 |
17 | #include <BRep_Builder.hxx> |
18 | #include <BRep_Tool.hxx> |
19 | #include <BRepTools.hxx> |
20 | #include <Geom2d_Curve.hxx> |
21 | #include <Geom2d_Line.hxx> |
22 | #include <Geom2d_TrimmedCurve.hxx> |
23 | #include <Geom_Curve.hxx> |
24 | #include <gp_Pnt.hxx> |
25 | #include <ShapeAnalysis_Curve.hxx> |
7fd59977 |
26 | #include <ShapeAnalysis_Edge.hxx> |
27 | #include <ShapeAnalysis_Surface.hxx> |
28 | #include <ShapeAnalysis_TransferParametersProj.hxx> |
7fd59977 |
29 | #include <ShapeBuild_Edge.hxx> |
42cf5bc1 |
30 | #include <ShapeBuild_ReShape.hxx> |
7fd59977 |
31 | #include <ShapeExtend_WireData.hxx> |
42cf5bc1 |
32 | #include <ShapeFix_Edge.hxx> |
33 | #include <ShapeFix_SplitTool.hxx> |
34 | #include <TopExp_Explorer.hxx> |
7fd59977 |
35 | #include <TopoDS.hxx> |
42cf5bc1 |
36 | #include <TopoDS_Edge.hxx> |
37 | #include <TopoDS_Face.hxx> |
38 | #include <TopoDS_Vertex.hxx> |
7fd59977 |
39 | #include <TopoDS_Wire.hxx> |
7fd59977 |
40 | |
41 | //======================================================================= |
42 | //function : ShapeFix_SplitTool() |
43 | //purpose : Constructor |
44 | //======================================================================= |
7fd59977 |
45 | ShapeFix_SplitTool::ShapeFix_SplitTool() |
46 | { |
47 | } |
48 | |
49 | |
50 | //======================================================================= |
51 | //function : SplitEdge |
52 | //purpose : |
53 | //======================================================================= |
54 | |
55 | Standard_Boolean ShapeFix_SplitTool::SplitEdge(const TopoDS_Edge& edge, |
56 | const Standard_Real param, |
57 | const TopoDS_Vertex& vert, |
58 | const TopoDS_Face& face, |
59 | TopoDS_Edge& newE1, |
60 | TopoDS_Edge& newE2, |
61 | const Standard_Real tol3d, |
62 | const Standard_Real tol2d) const |
63 | { |
64 | Standard_Real a, b; |
65 | ShapeAnalysis_Edge sae; |
66 | Handle(Geom2d_Curve) c2d; |
67 | sae.PCurve(edge,face,c2d,a,b,Standard_True ); |
68 | if( Abs(a-param)<tol2d || Abs(b-param)<tol2d ) |
69 | return Standard_False; |
70 | // check distanse between edge and new vertex |
71 | gp_Pnt P1; |
72 | TopLoc_Location L; |
73 | if(BRep_Tool::SameParameter(edge)) { |
74 | Standard_Real f,l; |
75 | const Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,L,f,l); |
76 | if(c3d.IsNull()) |
77 | return Standard_False; |
78 | P1 = c3d->Value(param); |
79 | if(!L.IsIdentity()) P1 = P1.Transformed(L.Transformation()); |
80 | } |
81 | else { |
82 | Handle(Geom_Surface) surf = BRep_Tool::Surface(face,L); |
83 | Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(surf); |
84 | P1 = sas->Value(c2d->Value(param)); |
85 | if(!L.IsIdentity()) P1 = P1.Transformed(L.Transformation()); |
86 | } |
87 | gp_Pnt P2 = BRep_Tool::Pnt(vert); |
88 | if(P1.Distance(P2)>tol3d) { |
89 | //return Standard_False; |
90 | BRep_Builder B; |
91 | B.UpdateVertex(vert,P1.Distance(P2)); |
92 | } |
93 | |
94 | Handle(ShapeAnalysis_TransferParametersProj) transferParameters = |
95 | new ShapeAnalysis_TransferParametersProj; |
96 | transferParameters->SetMaxTolerance(tol3d); |
97 | transferParameters->Init(edge,face); |
98 | Standard_Real first, last; |
99 | if (a < b ) { |
100 | first = a; |
101 | last = b; |
102 | } |
103 | else { |
104 | first = b; |
105 | last = a; |
106 | } |
107 | |
108 | ShapeBuild_Edge sbe; |
109 | Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge; |
110 | TopAbs_Orientation orient = edge.Orientation(); |
111 | BRep_Builder B; |
112 | TopoDS_Edge wE = edge; |
113 | wE.Orientation ( TopAbs_FORWARD ); |
114 | TopoDS_Shape aTmpShape = vert.Oriented(TopAbs_REVERSED); //for porting |
115 | newE1 = sbe.CopyReplaceVertices ( wE, sae.FirstVertex(wE), TopoDS::Vertex(aTmpShape) ); |
116 | sbe.CopyPCurves ( newE1, wE ); |
117 | transferParameters->TransferRange(newE1,first,param,Standard_True); |
118 | B.SameRange(newE1,Standard_False); |
119 | sfe->FixSameParameter(newE1); |
120 | //B.SameParameter(newE1,Standard_False); |
121 | aTmpShape = vert.Oriented(TopAbs_FORWARD); |
122 | newE2 = sbe.CopyReplaceVertices ( wE, TopoDS::Vertex(aTmpShape),sae.LastVertex(wE) ); |
123 | sbe.CopyPCurves ( newE2, wE ); |
124 | transferParameters->TransferRange(newE2,param,last,Standard_True); |
125 | B.SameRange(newE2,Standard_False); |
126 | sfe->FixSameParameter(newE2); |
127 | //B.SameParameter(newE2,Standard_False); |
128 | |
129 | newE1.Orientation(orient); |
130 | newE2.Orientation(orient); |
131 | if (orient==TopAbs_REVERSED) { |
132 | TopoDS_Edge tmp = newE2; newE2 = newE1; newE1=tmp; |
133 | } |
134 | |
135 | return Standard_True; |
136 | } |
137 | |
138 | |
139 | //======================================================================= |
140 | //function : SplitEdge |
141 | //purpose : |
142 | //======================================================================= |
143 | |
144 | Standard_Boolean ShapeFix_SplitTool::SplitEdge(const TopoDS_Edge& edge, |
145 | const Standard_Real param1, |
146 | const Standard_Real param2, |
147 | const TopoDS_Vertex& vert, |
148 | const TopoDS_Face& face, |
149 | TopoDS_Edge& newE1, |
150 | TopoDS_Edge& newE2, |
151 | const Standard_Real tol3d, |
152 | const Standard_Real tol2d) const |
153 | { |
154 | Standard_Real param = (param1+param2)/2; |
155 | if(SplitEdge(edge,param,vert,face,newE1,newE2,tol3d,tol2d)) { |
156 | // cut new edges by param1 and param2 |
157 | Standard_Boolean IsCutLine; |
158 | Handle(Geom2d_Curve) Crv1, Crv2; |
159 | Standard_Real fp1,lp1,fp2,lp2; |
160 | ShapeAnalysis_Edge sae; |
161 | if(sae.PCurve ( newE1, face, Crv1, fp1, lp1, Standard_False )) { |
162 | if(sae.PCurve ( newE2, face, Crv2, fp2, lp2, Standard_False )) { |
163 | if(lp1==param) { |
164 | if( (lp1-fp1)*(lp1-param1)>0 ) { |
165 | CutEdge(newE1, fp1, param1, face, IsCutLine); |
166 | CutEdge(newE2, lp2, param2, face, IsCutLine); |
167 | } |
168 | else { |
169 | CutEdge(newE1, fp1, param2, face, IsCutLine); |
170 | CutEdge(newE2, lp2, param1, face, IsCutLine); |
171 | } |
172 | } |
173 | else { |
174 | if( (fp1-lp1)*(fp1-param1)>0 ) { |
175 | CutEdge(newE1, lp1, param1, face, IsCutLine); |
176 | CutEdge(newE2, fp2, param2, face, IsCutLine); |
177 | } |
178 | else { |
179 | CutEdge(newE1, lp1, param2, face, IsCutLine); |
180 | CutEdge(newE2, fp2, param1, face, IsCutLine); |
181 | } |
182 | } |
183 | } |
184 | } |
185 | return Standard_True; |
186 | } |
187 | return Standard_False; |
188 | } |
189 | |
190 | |
191 | //======================================================================= |
192 | //function : CutEdge |
193 | //purpose : |
194 | //======================================================================= |
195 | |
196 | Standard_Boolean ShapeFix_SplitTool::CutEdge(const TopoDS_Edge &edge, |
197 | const Standard_Real pend, |
198 | const Standard_Real cut, |
199 | const TopoDS_Face &face, |
200 | Standard_Boolean &iscutline) const |
201 | { |
202 | if( Abs(cut-pend)<10.*Precision::PConfusion() ) return Standard_False; |
203 | Standard_Real aRange = Abs(cut-pend); |
204 | Standard_Real a, b; |
205 | BRep_Tool::Range(edge, a, b); |
206 | iscutline = Standard_False; |
207 | if( aRange<10.*Precision::PConfusion() ) return Standard_False; |
208 | |
209 | // case pcurve is trimm of line |
210 | if( !BRep_Tool::SameParameter(edge) ) { |
211 | ShapeAnalysis_Edge sae; |
212 | Handle(Geom2d_Curve) Crv; |
213 | Standard_Real fp,lp; |
214 | if ( sae.PCurve(edge,face,Crv,fp,lp,Standard_False) ) { |
215 | if(Crv->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) { |
216 | Handle(Geom2d_TrimmedCurve) tc = Handle(Geom2d_TrimmedCurve)::DownCast(Crv); |
217 | if(tc->BasisCurve()->IsKind(STANDARD_TYPE(Geom2d_Line))) { |
218 | BRep_Builder B; |
219 | B.Range(edge,Min(pend,cut),Max(pend,cut)); |
220 | if( Abs(pend-lp)<Precision::PConfusion() ) { // cut from the begining |
221 | Standard_Real cut3d = (cut-fp)*(b-a)/(lp-fp); |
222 | if(cut3d <= Precision::PConfusion()) |
223 | return Standard_False; |
224 | B.Range(edge, a+cut3d, b, Standard_True); |
225 | iscutline = Standard_True; |
226 | } |
227 | else if( Abs(pend-fp)<Precision::PConfusion() ) { // cut from the end |
228 | Standard_Real cut3d = (lp-cut)*(b-a)/(lp-fp); |
229 | if(cut3d <= Precision::PConfusion()) |
230 | return Standard_False; |
231 | B.Range(edge, a, b-cut3d, Standard_True); |
232 | iscutline = Standard_True; |
233 | } |
234 | } |
235 | } |
236 | } |
237 | return Standard_True; |
238 | } |
239 | |
240 | // det-study on 03/12/01 checking the old and new ranges |
241 | if( Abs(Abs(a-b)-aRange) < Precision::PConfusion() ) return Standard_False; |
242 | if( aRange<10.*Precision::PConfusion() ) return Standard_False; |
243 | |
c471a1ba |
244 | Handle(Geom_Curve) c = BRep_Tool::Curve(edge, a, b); |
245 | ShapeAnalysis_Curve sac; |
246 | a = Min(pend,cut); |
247 | b = Max(pend,cut); |
248 | Standard_Real na = a, nb = b; |
249 | |
7fd59977 |
250 | BRep_Builder B; |
c471a1ba |
251 | if (!BRep_Tool::Degenerated(edge) && !c.IsNull() && sac.ValidateRange(c, na, nb, Precision::PConfusion()) && (na != a || nb != b) ) |
252 | { |
253 | B.Range( edge, na, nb, Standard_True ); |
254 | ShapeAnalysis_Edge sae; |
255 | if(sae.HasPCurve(edge,face)) |
256 | { |
257 | B.SameRange(edge,Standard_False); |
258 | } |
259 | |
260 | ShapeFix_Edge sfe; |
261 | sfe.FixSameParameter(edge); |
262 | } |
263 | else |
264 | { |
265 | B.Range( edge, a, b, Standard_False ); |
266 | } |
7fd59977 |
267 | |
268 | return Standard_True; |
269 | } |
270 | |
271 | |
272 | //======================================================================= |
273 | //function : SplitEdge |
274 | //purpose : |
275 | //======================================================================= |
276 | |
277 | Standard_Boolean ShapeFix_SplitTool::SplitEdge(const TopoDS_Edge& edge, |
278 | const Standard_Real fp, |
279 | const TopoDS_Vertex& V1, |
280 | const Standard_Real lp, |
281 | const TopoDS_Vertex& V2, |
282 | const TopoDS_Face& face, |
283 | TopTools_SequenceOfShape& SeqE, |
284 | Standard_Integer& aNum, |
285 | const Handle(ShapeBuild_ReShape)& context, |
286 | const Standard_Real tol3d, |
287 | const Standard_Real tol2d) const |
288 | { |
289 | if(fabs(lp-fp)<tol2d) |
290 | return Standard_False; |
291 | aNum = 0; |
292 | SeqE.Clear(); |
293 | BRep_Builder B; |
294 | Standard_Real a, b; |
295 | ShapeAnalysis_Edge sae; |
296 | Handle(Geom2d_Curve) c2d; |
297 | sae.PCurve(edge,face,c2d,a,b,Standard_True); |
298 | TopoDS_Vertex VF = sae.FirstVertex(edge); |
299 | TopoDS_Vertex VL = sae.LastVertex(edge); |
300 | Standard_Real tolVF = BRep_Tool::Tolerance(VF); |
301 | Standard_Real tolVL = BRep_Tool::Tolerance(VL); |
302 | Standard_Real tolV1 = BRep_Tool::Tolerance(V1); |
303 | Standard_Real tolV2 = BRep_Tool::Tolerance(V2); |
304 | gp_Pnt PVF = BRep_Tool::Pnt(VF); |
305 | gp_Pnt PVL = BRep_Tool::Pnt(VL); |
306 | gp_Pnt PV1 = BRep_Tool::Pnt(V1); |
307 | gp_Pnt PV2 = BRep_Tool::Pnt(V2); |
308 | |
309 | Standard_Real par1,par2; |
310 | Standard_Boolean IsReverse = Standard_False; |
311 | if( (b-a)*(lp-fp)>0 ) { |
312 | par1 = fp; |
313 | par2 = lp; |
314 | } |
315 | else { |
316 | par1 = lp; |
317 | par2 = fp; |
318 | IsReverse = Standard_True; |
319 | } |
320 | |
321 | if( fabs(a-par1)<=tol2d && fabs(b-par2)<=tol2d ) { |
322 | if(IsReverse) { |
323 | Standard_Real newtol = tolVF + PVF.Distance(PV2); |
324 | if(tolV2<newtol) B.UpdateVertex(V2,newtol); |
325 | if(VF.Orientation()==V2.Orientation()) { |
326 | context->Replace(VF,V2); |
327 | VF = V2; |
328 | } |
329 | else { |
330 | context->Replace(VF,V2.Reversed()); |
331 | VF = TopoDS::Vertex(V2.Reversed()); |
332 | } |
333 | newtol = tolVL + PVL.Distance(PV1); |
334 | if(tolV1<newtol) B.UpdateVertex(V1,newtol); |
335 | if(VL.Orientation()==V1.Orientation()) { |
336 | context->Replace(VL,V1); |
337 | VL = V1; |
338 | } |
339 | else { |
340 | context->Replace(VL,V1.Reversed()); |
341 | VL = TopoDS::Vertex(V1.Reversed()); |
342 | } |
343 | } |
344 | else { |
345 | Standard_Real newtol = tolVF + PVF.Distance(PV1); |
346 | if(tolV1<newtol) B.UpdateVertex(V1,newtol); |
347 | if(VF.Orientation()==V1.Orientation()) { |
348 | context->Replace(VF,V1); |
349 | VF = V1; |
350 | } |
351 | else { |
352 | context->Replace(VF,V1.Reversed()); |
353 | VF = TopoDS::Vertex(V1.Reversed()); |
354 | } |
355 | newtol = tolVL + PVL.Distance(PV2); |
356 | if(tolV2<newtol) B.UpdateVertex(V2,newtol); |
357 | if(VL.Orientation()==V2.Orientation()) { |
358 | context->Replace(VL,V2); |
359 | VL = V2; |
360 | } |
361 | else { |
362 | context->Replace(VL,V2.Reversed()); |
363 | VL = TopoDS::Vertex(V2.Reversed()); |
364 | } |
365 | } |
366 | SeqE.Append(edge); |
367 | aNum = 1; |
368 | } |
369 | |
370 | if( fabs(a-par1)<=tol2d && fabs(b-par2)>tol2d ) { |
371 | TopoDS_Edge newE1, newE2; |
372 | if(IsReverse) { |
373 | if(!SplitEdge(edge,par2,V1,face,newE1,newE2,tol3d,tol2d)) |
374 | return Standard_False; |
375 | Standard_Real newtol = tolVF + PVF.Distance(PV2); |
376 | if(tolV2<newtol) B.UpdateVertex(V2,newtol); |
377 | if(VF.Orientation()==V2.Orientation()) { |
378 | context->Replace(VF,V2); |
379 | VF = V2; |
380 | } |
381 | else { |
382 | context->Replace(VF,V2.Reversed()); |
383 | VF = TopoDS::Vertex(V2.Reversed()); |
384 | } |
385 | } |
386 | else { |
387 | if(!SplitEdge(edge,par2,V2,face,newE1,newE2,tol3d,tol2d)) |
388 | return Standard_False; |
389 | Standard_Real newtol = tolVF + PVF.Distance(PV1); |
390 | if(tolV1<newtol) B.UpdateVertex(V1,newtol); |
391 | if(VF.Orientation()==V1.Orientation()) { |
392 | context->Replace(VF,V1); |
393 | VF = V1; |
394 | } |
395 | else { |
396 | context->Replace(VF,V1.Reversed()); |
397 | VF = TopoDS::Vertex(V1.Reversed()); |
398 | } |
399 | } |
400 | SeqE.Append(newE1); |
401 | SeqE.Append(newE2); |
402 | aNum = 1; |
403 | } |
404 | |
405 | if( fabs(a-par1)>tol2d && fabs(b-par2)<=tol2d ) { |
406 | TopoDS_Edge newE1, newE2; |
407 | if(IsReverse) { |
408 | if(!SplitEdge(edge,par1,V2,face,newE1,newE2,tol3d,tol2d)) |
409 | return Standard_False; |
410 | Standard_Real newtol = tolVL + PVL.Distance(PV1); |
411 | if(tolV1<newtol) B.UpdateVertex(V1,newtol); |
412 | if(VL.Orientation()==V1.Orientation()) { |
413 | context->Replace(VL,V1); |
414 | VL = V1; |
415 | } |
416 | else { |
417 | context->Replace(VL,V1.Reversed()); |
418 | VL = TopoDS::Vertex(V1.Reversed()); |
419 | } |
420 | } |
421 | else { |
422 | if(!SplitEdge(edge,par1,V1,face,newE1,newE2,tol3d,tol2d)) |
423 | return Standard_False; |
424 | Standard_Real newtol = tolVL + PVL.Distance(PV2); |
425 | if(tolV2<newtol) B.UpdateVertex(V2,newtol); |
426 | if(VL.Orientation()==V2.Orientation()) { |
427 | context->Replace(VL,V2); |
428 | VL = V2; |
429 | } |
430 | else { |
431 | context->Replace(VL,V2.Reversed()); |
432 | VL = TopoDS::Vertex(V2.Reversed()); |
433 | } |
434 | } |
435 | SeqE.Append(newE1); |
436 | SeqE.Append(newE2); |
437 | aNum = 2; |
438 | } |
439 | |
440 | if( fabs(a-par1)>tol2d && fabs(b-par2)>tol2d ) { |
441 | TopoDS_Edge newE1,newE2,newE3,newE4; |
442 | if(IsReverse) { |
443 | if(!SplitEdge(edge,par1,V2,face,newE1,newE2,tol3d,tol2d)) |
444 | return Standard_False; |
445 | if(!SplitEdge(newE2,par2,V1,face,newE3,newE4,tol3d,tol2d)) |
446 | return Standard_False; |
447 | } |
448 | else { |
449 | if(!SplitEdge(edge,par1,V1,face,newE1,newE2,tol3d,tol2d)) |
450 | return Standard_False; |
451 | if(!SplitEdge(newE2,par2,V2,face,newE3,newE4,tol3d,tol2d)) |
452 | return Standard_False; |
453 | } |
454 | SeqE.Append(newE1); |
455 | SeqE.Append(newE3); |
456 | SeqE.Append(newE4); |
457 | aNum = 2; |
458 | } |
459 | |
460 | if(aNum==0) return Standard_False; |
461 | |
462 | Handle(ShapeExtend_WireData) sewd = new ShapeExtend_WireData; |
463 | for(Standard_Integer i=1; i<=SeqE.Length(); i++) { |
464 | sewd->Add(SeqE.Value(i)); |
465 | } |
466 | context->Replace(edge,sewd->Wire()); |
467 | for (TopExp_Explorer exp ( sewd->Wire(), TopAbs_EDGE ); exp.More(); exp.Next() ) { |
468 | TopoDS_Edge E = TopoDS::Edge ( exp.Current() ); |
469 | BRepTools::Update(E); |
470 | } |
471 | |
472 | return Standard_True; |
473 | } |
474 | |
475 | |