973c2be1 |
1 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
2 | // |
973c2be1 |
3 | // This file is part of Open CASCADE Technology software library. |
b311480e |
4 | // |
d5f74e42 |
5 | // This library is free software; you can redistribute it and/or modify it under |
6 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
7 | // by the Free Software Foundation, with special exception defined in the file |
8 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
9 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
10 | // |
973c2be1 |
11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. |
b311480e |
13 | |
7fd59977 |
14 | // szv 19.08.99: new methods for fixing gaps between edges (3d curves and pcurves) |
15 | #include <ShapeFix_Wire.hxx> |
16 | #include <Standard_ErrorHandler.hxx> |
17 | #include <Standard_Failure.hxx> |
18 | |
19 | #include <Precision.hxx> |
20 | #include <Bnd_Box2d.hxx> |
21 | #include <Geom_Curve.hxx> |
22 | #include <Geom2d_Curve.hxx> |
23 | #include <Geom2d_Line.hxx> |
24 | |
25 | #include <IntRes2d_SequenceOfIntersectionPoint.hxx> |
26 | #include <IntRes2d_IntersectionPoint.hxx> |
27 | #include <TColgp_SequenceOfPnt.hxx> |
28 | |
29 | #include <TopoDS.hxx> |
30 | #include <TopoDS_Vertex.hxx> |
31 | #include <TopoDS_Edge.hxx> |
32 | #include <TopTools_HSequenceOfShape.hxx> |
33 | |
34 | #include <BRep_Tool.hxx> |
35 | #include <BRep_Builder.hxx> |
36 | |
37 | #include <ShapeExtend.hxx> |
38 | #include <ShapeBuild_Edge.hxx> |
39 | #include <ShapeBuild_Vertex.hxx> |
40 | #include <ShapeAnalysis_Curve.hxx> |
41 | #include <ShapeAnalysis_Edge.hxx> |
42 | #include <ShapeAnalysis_Surface.hxx> |
43 | #include <ShapeAnalysis.hxx> |
44 | #include <GeomConvert_CompCurveToBSplineCurve.hxx> |
45 | #include <Geom_TrimmedCurve.hxx> |
46 | #include <gp_Pln.hxx> |
47 | #include <GeomAPI.hxx> |
48 | #include <TColgp_Array1OfPnt.hxx> |
49 | #include <TColStd_Array1OfReal.hxx> |
50 | #include <TColStd_Array1OfInteger.hxx> |
51 | #include <Geom_BSplineCurve.hxx> |
52 | #include <Geom_SphericalSurface.hxx> //S4135 |
53 | #include <Geom2d_BSplineCurve.hxx> |
54 | #include <GeomAdaptor_Curve.hxx> |
55 | #include <GeomAdaptor_HSurface.hxx> |
56 | #include <GeomAdaptor_Surface.hxx> |
57 | #include <TopTools_Array1OfShape.hxx> |
58 | #include <BRepTools.hxx> |
59 | #include <Bnd_Array1OfBox2d.hxx> |
60 | #include <BndLib_Add2dCurve.hxx> |
61 | #include <Geom2dAdaptor_Curve.hxx> |
62 | #include <Geom2dConvert.hxx> |
63 | #include <Geom2d_TrimmedCurve.hxx> |
64 | #include <ShapeBuild_ReShape.hxx> |
b311480e |
65 | |
7fd59977 |
66 | //szv |
67 | #include <TColgp_Array1OfPnt2d.hxx> |
68 | #include <Geom2d_Circle.hxx> |
69 | #include <Geom2d_Ellipse.hxx> |
70 | #include <Geom2d_Parabola.hxx> |
71 | #include <Geom2d_Hyperbola.hxx> |
72 | #include <Geom2d_OffsetCurve.hxx> |
73 | #include <Geom2dInt_GInter.hxx> |
74 | #include <IntRes2d_Domain.hxx> |
75 | #include <IntRes2d_IntersectionSegment.hxx> |
76 | #include <Geom2dAPI_ExtremaCurveCurve.hxx> |
77 | #include <Geom2dAPI_ProjectPointOnCurve.hxx> |
78 | #include <Geom2dAdaptor_HCurve.hxx> |
79 | #include <Approx_Curve2d.hxx> |
80 | #include <Geom2dConvert.hxx> |
81 | |
82 | #include <Geom_Line.hxx> |
83 | #include <Geom_Circle.hxx> |
84 | #include <Geom_Ellipse.hxx> |
85 | #include <Geom_Parabola.hxx> |
86 | #include <Geom_Hyperbola.hxx> |
87 | #include <Geom_OffsetCurve.hxx> |
88 | #include <GeomAPI_ExtremaCurveCurve.hxx> |
89 | #include <GeomAPI_ProjectPointOnCurve.hxx> |
90 | #include <GeomAdaptor_HCurve.hxx> |
91 | #include <Approx_Curve3d.hxx> |
92 | #include <GeomConvert.hxx> |
93 | #include <TopoDS_Iterator.hxx> |
94 | #include <ShapeFix_ShapeTolerance.hxx> |
95 | #include <ShapeAnalysis_TransferParametersProj.hxx> |
ec357c5c |
96 | #include <Geom_Conic.hxx> |
97 | #include <Geom_BezierCurve.hxx> |
98 | #include <Geom2d_Conic.hxx> |
99 | #include <Geom2d_BezierCurve.hxx> |
7fd59977 |
100 | //======================================================================= |
101 | //function : FixGaps3d |
102 | //purpose : |
103 | //======================================================================= |
104 | |
b311480e |
105 | Standard_Boolean ShapeFix_Wire::FixGaps3d () |
7fd59977 |
106 | { |
107 | myStatusGaps3d = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); |
108 | // if ( !IsReady() ) return Standard_False; |
109 | |
110 | Standard_Integer i, start = ( myClosedMode ? 1 : 2 ); |
111 | if (myFixGapsByRanges) |
112 | { |
113 | for ( i = start; i <= NbEdges(); i++ ) |
114 | { |
115 | FixGap3d ( i ); |
116 | myStatusGaps3d |= myLastFixStatus; |
117 | } |
118 | } |
119 | for ( i = start; i <= NbEdges(); i++ ) |
120 | { |
121 | FixGap3d ( i, Standard_True ); |
122 | myStatusGaps3d |= myLastFixStatus; |
123 | } |
124 | |
125 | return StatusGaps3d ( ShapeExtend_DONE ); |
126 | } |
127 | |
128 | //======================================================================= |
129 | //function : FixGaps2d |
130 | //purpose : |
131 | //======================================================================= |
132 | |
133 | Standard_Boolean ShapeFix_Wire::FixGaps2d () |
134 | { |
135 | myStatusGaps2d = ShapeExtend::EncodeStatus ( ShapeExtend_OK ); |
136 | // if ( !IsReady() ) return Standard_False; |
137 | |
138 | Standard_Integer i, start = ( myClosedMode ? 1 : 2 ); |
139 | if (myFixGapsByRanges) |
140 | { |
141 | for ( i = start; i <= NbEdges(); i++ ) |
142 | { |
143 | FixGap2d ( i ); |
144 | myStatusGaps2d |= myLastFixStatus; |
145 | } |
146 | } |
147 | for ( i = start; i <= NbEdges(); i++ ) |
148 | { |
149 | FixGap2d ( i, Standard_True ); |
150 | myStatusGaps2d |= myLastFixStatus; |
151 | } |
152 | |
153 | return StatusGaps2d ( ShapeExtend_DONE ); |
154 | } |
155 | |
156 | //======================================================================= |
157 | //function : FixGap3d |
158 | //purpose : |
159 | //======================================================================= |
160 | |
161 | static Standard_Real AdjustOnPeriodic3d (const Handle(Geom_Curve)& c, |
162 | const Standard_Boolean takefirst, |
163 | const Standard_Real first, |
164 | const Standard_Real last, |
165 | const Standard_Real param) |
166 | { |
167 | // 15.11.2002 PTV OCC966 |
168 | if (ShapeAnalysis_Curve::IsPeriodic(c)) |
169 | { |
170 | Standard_Real T = c->Period(); |
171 | Standard_Real shift = -IntegerPart(first/T)*T; if (first<0.) shift += T; |
172 | Standard_Real sfirst = first+shift, slast = last+shift; |
173 | if ( takefirst && (param>slast) && (param>sfirst)) return param-T-shift; |
174 | if (!takefirst && (param<slast) && (param<sfirst)) return param+T-shift; |
175 | } |
176 | return param; |
177 | } |
178 | |
179 | Standard_Boolean ShapeFix_Wire::FixGap3d (const Standard_Integer num, |
180 | const Standard_Boolean convert) |
181 | { |
182 | myLastFixStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK ); |
183 | // if ( !IsReady() ) return Standard_False; |
184 | |
185 | //============= |
186 | // First phase: analysis whether the problem (gap) exists |
187 | //============= |
188 | |
189 | if (Context().IsNull()) SetContext(new ShapeBuild_ReShape); |
190 | |
191 | Standard_Real preci = Precision(); |
192 | |
193 | Handle(ShapeExtend_WireData) sbwd = WireData(); |
194 | Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() ); |
195 | Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() ); |
196 | //smh#8 |
197 | TopoDS_Shape tmp1 = Context()->Apply(sbwd->Edge(n1)), |
198 | tmp2 = Context()->Apply(sbwd->Edge(n2)); |
199 | TopoDS_Edge E1 = TopoDS::Edge(tmp1), |
200 | E2 = TopoDS::Edge(tmp2); |
201 | // TopoDS_Face face = myAnalyzer->Face(); // comment by enk |
202 | |
203 | // Retrieve curves on edges |
204 | Standard_Real cfirst1, clast1, cfirst2, clast2; |
205 | Handle(Geom_Curve) C1, C2; |
206 | ShapeAnalysis_Edge SAE; |
207 | if (!SAE.Curve3d(E1,C1,cfirst1,clast1) || |
208 | !SAE.Curve3d(E2,C2,cfirst2,clast2)) |
209 | { |
210 | myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 ); |
211 | return Standard_False; |
212 | } |
213 | |
214 | // Check gap in 3d space |
215 | gp_Pnt cpnt1 = C1->Value(clast1), cpnt2 = C2->Value(cfirst2); |
216 | Standard_Real gap = cpnt1.Distance(cpnt2); |
217 | if (!convert && gap<=preci) return Standard_False; |
218 | |
219 | //============= |
220 | // Second phase: collecting data necessary for further analysis |
221 | //============= |
222 | |
223 | Standard_Boolean reversed1 = (E1.Orientation()==TopAbs_REVERSED), |
224 | reversed2 = (E2.Orientation()==TopAbs_REVERSED); |
225 | |
226 | TopoDS_Vertex V1 = SAE.LastVertex(E1), V2 = SAE.FirstVertex(E2); |
227 | gp_Pnt vpnt = (V1.IsSame(V2))? BRep_Tool::Pnt(V1) : |
228 | gp_Pnt((BRep_Tool::Pnt(V1).XYZ()+BRep_Tool::Pnt(V2).XYZ())*0.5); |
229 | |
230 | Standard_Real first1, last1, first2, last2; |
231 | if (reversed1) |
232 | { |
233 | first1 = clast1; last1 = cfirst1; |
234 | } |
235 | else |
236 | { |
237 | first1 = cfirst1; last1 = clast1; |
238 | } |
239 | if (reversed2) |
240 | { |
241 | first2 = clast2; last2 = cfirst2; |
242 | } |
243 | else |
244 | { |
245 | first2 = cfirst2; last2 = clast2; |
246 | } |
247 | |
248 | Handle(Geom_Curve) c1 = C1, c2 = C2; |
249 | |
250 | // Extract basic curves from trimmed and offset |
251 | Standard_Boolean basic = Standard_False; |
252 | Standard_Boolean trimmed1 = Standard_False, offset1 = Standard_False; |
253 | gp_XYZ offval1(0.,0.,0.); |
254 | while (!basic) |
255 | { |
256 | if (c1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) |
257 | { |
258 | c1 = Handle(Geom_TrimmedCurve)::DownCast(c1)->BasisCurve(); |
259 | trimmed1 = Standard_True; |
260 | } |
261 | else if (c1->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) |
262 | { |
263 | Handle(Geom_OffsetCurve) oc = Handle(Geom_OffsetCurve)::DownCast(c1); |
264 | c1 = oc->BasisCurve(); |
265 | offval1 += oc->Offset()*oc->Direction().XYZ(); |
266 | offset1 = Standard_True; |
267 | } |
268 | else basic = Standard_True; |
269 | } |
270 | basic = Standard_False; |
271 | Standard_Boolean trimmed2 = Standard_False, offset2 = Standard_False; |
272 | gp_XYZ offval2(0.,0.,0.); |
273 | while (!basic) |
274 | { |
275 | if (c2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) |
276 | { |
277 | c2 = Handle(Geom_TrimmedCurve)::DownCast(c2)->BasisCurve(); |
278 | trimmed2 = Standard_True; |
279 | } |
280 | else if (c2->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) |
281 | { |
282 | Handle(Geom_OffsetCurve) oc = Handle(Geom_OffsetCurve)::DownCast(c2); |
283 | c2 = oc->BasisCurve(); |
284 | offval2 += oc->Offset()*oc->Direction().XYZ(); |
285 | offset2 = Standard_True; |
286 | } |
287 | else basic = Standard_True; |
288 | } |
289 | // Restore offset curves |
290 | if (offset1) c1 = new Geom_OffsetCurve(c1,offval1.Modulus(),gp_Dir(offval1)); |
291 | if (offset2) c2 = new Geom_OffsetCurve(c2,offval2.Modulus(),gp_Dir(offval2)); |
292 | |
293 | Standard_Boolean done1 = Standard_False, done2 = Standard_False; |
294 | |
295 | if (convert) |
296 | { |
2bfe59b6 |
297 | // Check that gap satisfies the precision - in this case no convertation produced |
298 | if (cpnt1.Distance(vpnt) < preci && cpnt2.Distance(vpnt) < preci) |
299 | return Standard_False; |
7fd59977 |
300 | |
301 | Handle(Geom_BSplineCurve) bsp1, bsp2; |
302 | Handle(Geom_Curve) c; |
303 | Standard_Real first, last; |
304 | |
305 | // iterate on curves |
306 | Standard_Integer nbcurv = (n1==n2? 1 : 2); |
307 | for (Standard_Integer j=1; j<=nbcurv; j++) |
308 | { |
309 | //Standard_Boolean trim = Standard_False; // skl |
310 | if (j==1) |
311 | { |
312 | if (cpnt1.Distance(vpnt)<preci) |
313 | { |
314 | if (n1==n2) |
315 | { |
316 | if (cpnt2.Distance(vpnt)<preci) continue; |
317 | } |
318 | else continue; |
319 | } |
320 | c = c1; first = first1; last = last1; /*trim = trimmed1;*/ // skl |
321 | } |
322 | else |
323 | { |
324 | if (cpnt2.Distance(vpnt)<preci) continue; |
325 | c = c2; first = first2; last = last2; /*trim = trimmed2;*/ // skl |
326 | } |
327 | |
328 | Handle(Geom_BSplineCurve) bsp; |
329 | |
330 | // Convert curve to bspline |
331 | if (c->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) |
332 | { |
333 | bsp = Handle(Geom_BSplineCurve)::DownCast(c->Copy()); |
334 | // take segment if trim and range differ |
335 | Standard_Real fbsp = bsp->FirstParameter(), lbsp = bsp->LastParameter(); |
336 | Standard_Boolean segment = Standard_False; |
337 | if (first>fbsp) |
338 | { |
339 | fbsp = first; segment = Standard_True; |
340 | } |
341 | if (last<lbsp) |
342 | { |
343 | lbsp = last; segment = Standard_True; |
344 | } |
345 | if (segment) |
346 | bsp = GeomConvert::SplitBSplineCurve(bsp,fbsp,lbsp, |
347 | ::Precision::Confusion()); |
348 | } |
349 | else if (c->IsKind(STANDARD_TYPE(Geom_Conic))) |
350 | { |
351 | Approx_Curve3d Conv(new GeomAdaptor_HCurve(c,first,last), |
352 | myAnalyzer->Precision(),GeomAbs_C1,9,1000); |
353 | if (Conv.IsDone() || Conv.HasResult()) bsp = Conv.Curve(); |
354 | } |
355 | else |
356 | { |
357 | // Restore trim for pcurve |
358 | Handle(Geom_Curve) tc ; |
359 | try |
360 | { |
361 | OCC_CATCH_SIGNALS |
362 | // 15.11.2002 PTV OCC966 |
363 | if(!ShapeAnalysis_Curve::IsPeriodic(c)) |
364 | tc = new Geom_TrimmedCurve(c,Max(first,c->FirstParameter()),Min(last,c->LastParameter())); |
365 | else tc = new Geom_TrimmedCurve(c,first,last); |
366 | bsp = GeomConvert::CurveToBSplineCurve(tc); |
367 | } |
368 | catch (Standard_Failure) |
369 | { |
0797d9d3 |
370 | #ifdef OCCT_DEBUG |
7fd59977 |
371 | cout << "Warning: ShapeFix_Wire_1::FixGap3d: Exception in TrimmedCurve" <<first<<" " <<last<<endl; |
372 | Standard_Failure::Caught()->Print(cout); cout << endl; |
373 | #endif |
374 | } |
375 | } |
376 | |
377 | if (j==1) bsp1 = bsp; else bsp2 = bsp; |
378 | } |
379 | |
380 | // Take curves ends if could not convert |
381 | if (bsp1.IsNull()) vpnt = cpnt1; |
382 | else if (bsp2.IsNull()) vpnt = cpnt2; |
383 | |
384 | if (!bsp1.IsNull()) |
385 | { |
386 | if(bsp1->Degree() == 1) bsp1->IncreaseDegree(2); //gka |
387 | if (n1==n2) |
388 | { |
389 | bsp1->SetPole(1,vpnt); bsp1->SetPole(bsp1->NbPoles(),vpnt); |
390 | } |
391 | else |
392 | { |
393 | if (reversed1) bsp1->SetPole(1,vpnt); |
394 | else bsp1->SetPole(bsp1->NbPoles(),vpnt); |
395 | } |
396 | first1 = bsp1->FirstParameter(); last1 = bsp1->LastParameter(); |
397 | c1 = bsp1; |
398 | done1 = Standard_True; |
399 | } |
400 | if (!bsp2.IsNull()) |
401 | { |
402 | if(bsp2->Degree() == 1) bsp2->IncreaseDegree(2); //gka |
403 | if (reversed2) bsp2->SetPole(bsp2->NbPoles(),vpnt); |
404 | else bsp2->SetPole(1,vpnt); |
405 | first2 = bsp2->FirstParameter(); last2 = bsp2->LastParameter(); |
406 | c2 = bsp2; |
407 | done2 = Standard_True; |
408 | } |
409 | } |
410 | else |
411 | { |
412 | |
413 | if (n1==n2) |
414 | { |
415 | if (c1->IsKind(STANDARD_TYPE(Geom_Circle)) || |
416 | c1->IsKind(STANDARD_TYPE(Geom_Ellipse))) |
417 | { |
c6541a0c |
418 | Standard_Real diff = M_PI - Abs(clast1-cfirst2)*0.5; |
7fd59977 |
419 | first1 -= diff; last1 += diff; |
420 | done1 = Standard_True; |
421 | } |
422 | } |
423 | else |
424 | { |
425 | |
426 | // Determine domains for extremal points locating |
427 | Standard_Real domfirst1 = first1, domlast1 = last1; |
428 | if (c1->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) || |
429 | c1->IsKind(STANDARD_TYPE(Geom_BezierCurve))) |
430 | { |
431 | domfirst1 = c1->FirstParameter(); |
432 | domlast1 = c1->LastParameter(); |
433 | } |
434 | else if (c1->IsKind(STANDARD_TYPE(Geom_Line)) || |
435 | c1->IsKind(STANDARD_TYPE(Geom_Parabola)) || |
436 | c1->IsKind(STANDARD_TYPE(Geom_Hyperbola))) |
437 | { |
438 | Standard_Real diff = domlast1 - domfirst1; |
439 | if (reversed1) domfirst1 -= 10.*diff; |
440 | else domlast1 += 10.*diff; |
441 | } |
442 | else if (c1->IsKind(STANDARD_TYPE(Geom_Circle)) || |
443 | c1->IsKind(STANDARD_TYPE(Geom_Ellipse))) |
444 | { |
c6541a0c |
445 | domfirst1 = 0.; domlast1 = 2*M_PI; |
7fd59977 |
446 | } |
447 | Standard_Real domfirst2 = first2, domlast2 = last2; |
448 | if (c2->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) || |
449 | c2->IsKind(STANDARD_TYPE(Geom_BezierCurve))) |
450 | { |
451 | domfirst2 = c2->FirstParameter(); |
452 | domlast2 = c2->LastParameter(); |
453 | } |
454 | else if (c2->IsKind(STANDARD_TYPE(Geom_Line)) || |
455 | c2->IsKind(STANDARD_TYPE(Geom_Parabola)) || |
456 | c2->IsKind(STANDARD_TYPE(Geom_Hyperbola))) |
457 | { |
458 | Standard_Real diff = domlast2 - domfirst2; |
459 | if (reversed2) domlast2 += 10.*diff; |
460 | else domfirst2 -= 10.*diff; |
461 | } |
462 | else if (c2->IsKind(STANDARD_TYPE(Geom_Circle)) || |
463 | c2->IsKind(STANDARD_TYPE(Geom_Ellipse))) |
464 | { |
c6541a0c |
465 | domfirst2 = 0.; domlast2 = 2*M_PI; |
7fd59977 |
466 | } |
467 | |
468 | Standard_Real ipar1 = clast1, ipar2 = cfirst2; |
469 | |
470 | // Try to find projections of vertex point |
471 | GeomAPI_ProjectPointOnCurve Proj; |
472 | Standard_Real u1 = ipar1, u2 = ipar2; |
473 | Proj.Init(vpnt,c1,domfirst1,domlast1); |
474 | if (Proj.NbPoints()) |
475 | { |
476 | Standard_Integer index = 1; |
477 | Standard_Real dist, mindist=-1.; |
478 | for (Standard_Integer i=1; i<=Proj.NbPoints(); i++) |
479 | { |
480 | dist = vpnt.Distance(Proj.Point(i)); |
481 | if (mindist>dist || mindist<0.) |
482 | { |
483 | index = i; mindist = dist; |
484 | } |
485 | u1 = Proj.Parameter(index); |
486 | } |
487 | } |
488 | Proj.Init(vpnt,c2,domfirst2,domlast2); |
489 | if (Proj.NbPoints()) |
490 | { |
491 | Standard_Integer index = 1; |
492 | Standard_Real dist, mindist=-1.; |
493 | for (Standard_Integer i=1; i<=Proj.NbPoints(); i++) |
494 | { |
495 | dist = vpnt.Distance(Proj.Point(i)); |
496 | if (mindist>dist || mindist<0.) |
497 | { |
498 | index = i; mindist = dist; |
499 | } |
500 | u2 = Proj.Parameter(index); |
501 | } |
502 | } |
503 | // Ajust parameters on periodic curves |
504 | u1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,u1); |
505 | u2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,u2); |
506 | // Check points to satisfy distance criterium |
507 | gp_Pnt p1 = c1->Value(u1), p2 = c2->Value(u2); |
508 | if (p1.Distance(p2)<=gap && |
509 | Abs(cfirst1-u1) > ::Precision::PConfusion() && |
510 | Abs(clast2-u2) > ::Precision::PConfusion() && |
511 | (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) || |
512 | (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap))) |
513 | { |
514 | ipar1 = u1; ipar2 = u2; |
515 | done1 = done2 = Standard_True; |
516 | } |
517 | |
518 | // Try to find closest points if nothing yet found |
519 | if (!done1) |
520 | { |
521 | |
522 | // Recompute domains |
523 | if (reversed1) |
524 | { |
525 | domfirst1 = ipar1; domlast1 = last1; |
526 | } |
527 | else |
528 | { |
529 | domfirst1 = first1; domlast1 = ipar1; |
530 | } |
531 | if (reversed2) |
532 | { |
533 | domfirst2 = first2; domlast2 = ipar2; |
534 | } |
535 | else |
536 | { |
537 | domfirst2 = ipar2; domlast2 = last2; |
538 | } |
539 | |
540 | GeomAPI_ExtremaCurveCurve Extr(c1,c2,domfirst1,domlast1,domfirst2,domlast2); |
541 | if (Extr.NbExtrema()) |
542 | { |
543 | try |
544 | { |
545 | OCC_CATCH_SIGNALS |
546 | // First find all intersections |
547 | gp_Pnt pp1, pp2; |
548 | Standard_Integer index1=0, index2=0; |
549 | Standard_Real uu1, uu2, pardist, pardist1=-1., pardist2=-1.; |
550 | for (Standard_Integer i=1; i<=Extr.NbExtrema(); i++) |
551 | { |
552 | Extr.Parameters(i,uu1,uu2); |
553 | // Ajust parameters on periodic curves |
554 | uu1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,uu1); |
555 | uu2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,uu2); |
556 | pp1 = c1->Value(uu1); pp2 = c2->Value(uu2); |
557 | if (pp1.Distance(pp2) < ::Precision::Confusion()) |
558 | { |
559 | // assume intersection |
560 | pardist = Abs(cfirst1-uu1); |
561 | if (pardist1>pardist || pardist1<0.) |
562 | { |
563 | index1 = i; pardist1 = pardist; |
564 | } |
565 | pardist = Abs(clast2-uu2); |
566 | if (pardist2>pardist || pardist2<0.) |
567 | { |
568 | index2 = i; pardist2 = pardist; |
569 | } |
570 | } |
571 | } |
572 | if (index1!=0 && index2!=0) |
573 | { |
574 | if (index1!=index2) |
575 | { |
576 | // take intersection closer to vertex point |
577 | Extr.Parameters(index1,uu1,uu2); |
578 | pp1 = gp_Pnt((c1->Value(uu1).XYZ()+c2->Value(uu2).XYZ())*0.5); |
579 | Extr.Parameters(index2,uu1,uu2); |
580 | pp2 = gp_Pnt((c1->Value(uu1).XYZ()+c2->Value(uu2).XYZ())*0.5); |
581 | if (pp2.Distance(vpnt) < pp1.Distance(vpnt)) index1 = index2; |
582 | } |
583 | Extr.Parameters(index1,uu1,uu2); |
584 | } |
585 | else Extr.LowerDistanceParameters(uu1,uu2); |
586 | // Ajust parameters on periodic curves |
587 | uu1 = AdjustOnPeriodic3d(c1,reversed1,first1,last1,uu1); |
588 | uu2 = AdjustOnPeriodic3d(c2,!reversed2,first2,last2,uu2); |
589 | // Check points to satisfy distance criterium |
590 | pp1 = c1->Value(uu1), pp2 = c2->Value(uu2); |
591 | if (pp1.Distance(pp2)<=gap && |
592 | Abs(cfirst1-uu1) > ::Precision::PConfusion() && |
593 | Abs(clast2-uu2) > ::Precision::PConfusion() && |
594 | (((uu1>first1) && (uu1<last1)) || ((uu2>first2) && (uu2<last2)) || |
595 | (cpnt1.Distance(pp1)<=gap) || (cpnt2.Distance(pp2)<=gap))) |
596 | { |
597 | ipar1 = uu1; ipar2 = uu2; |
598 | done1 = done2 = Standard_True; |
599 | } |
600 | } |
601 | catch ( Standard_Failure ) |
602 | { |
603 | } |
604 | } |
605 | } |
606 | |
607 | try |
608 | { |
609 | OCC_CATCH_SIGNALS |
610 | if (done1) |
611 | { |
612 | if (ipar1==clast1) done1 = Standard_False; |
613 | else |
614 | { |
615 | // Set up new bounds for curve |
616 | if (reversed1) first1 = ipar1; else last1 = ipar1; |
617 | // Set new trim for old curve |
618 | if (trimmed1) |
619 | { |
620 | // Standard_Real ff1 = c1->FirstParameter(); |
621 | // Standard_Real ll1 = c1->LastParameter(); |
622 | c1 = new Geom_TrimmedCurve(c1,first1,last1); |
623 | } |
624 | } |
625 | } |
626 | if (done2) |
627 | { |
628 | if (ipar2==cfirst2) done2 = Standard_False; |
629 | else |
630 | { |
631 | // Set up new bounds for curve |
632 | if (reversed2) last2 = ipar2; else first2 = ipar2; |
633 | // Set new trim for old curve |
634 | if (trimmed2) |
635 | { |
636 | // Standard_Real ff2 = c2->FirstParameter(); |
637 | // Standard_Real ll2 = c2->LastParameter(); |
638 | c2 = new Geom_TrimmedCurve(c2,first2,last2); |
639 | } |
640 | } |
641 | } |
642 | } |
643 | catch (Standard_Failure) |
644 | { |
0797d9d3 |
645 | #ifdef OCCT_DEBUG |
7fd59977 |
646 | cout << "Warning: ShapeFix_Wire_1::FixGap3d: Exception in TrimmedCurve :"<<endl; |
647 | Standard_Failure::Caught()->Print(cout); cout << endl; |
648 | #endif |
649 | } |
650 | } |
651 | } |
652 | |
653 | if (done1 || done2) |
654 | { |
655 | |
656 | BRep_Builder B; |
657 | ShapeBuild_Edge SBE; |
658 | ShapeFix_ShapeTolerance SFST; |
659 | |
660 | // Update vertices |
661 | TopoDS_Vertex nullV, newV1; |
662 | //smh#8 |
663 | TopoDS_Shape emptyCopiedV2 = V2.EmptyCopied(); |
664 | TopoDS_Vertex newV2 = TopoDS::Vertex(emptyCopiedV2); |
665 | SFST.SetTolerance(newV2,::Precision::Confusion()); |
666 | Context()->Replace(V2,newV2); |
667 | if (V1.IsSame(V2)) |
668 | //smh#8 |
669 | { |
670 | TopoDS_Shape tmpV2 = newV2.Oriented(TopAbs_REVERSED); |
671 | newV1 = TopoDS::Vertex(tmpV2); |
672 | } |
673 | else |
674 | { |
675 | //smh#8 |
676 | TopoDS_Shape emptyCopied = V1.EmptyCopied(); |
677 | newV1 = TopoDS::Vertex(emptyCopied); |
678 | SFST.SetTolerance(newV1,::Precision::Confusion()); |
679 | Context()->Replace(V1,newV1); |
680 | } |
681 | |
682 | if (done1) |
683 | { |
684 | // Update first edge |
685 | TopoDS_Edge newE1 = SBE.CopyReplaceVertices(E1,nullV,newV1); |
686 | //smh#8 |
687 | TopoDS_Shape tmpE1 = newE1.Oriented(TopAbs_FORWARD); |
688 | B.UpdateEdge(TopoDS::Edge(tmpE1),c1,0.); |
689 | SBE.SetRange3d(TopoDS::Edge(tmpE1),first1,last1); |
690 | SFST.SetTolerance(newE1,::Precision::Confusion(),TopAbs_EDGE); |
691 | B.SameRange(newE1,Standard_False); |
692 | // B.SameParameter(newE1,Standard_False); |
693 | |
694 | //To keep NM vertices belonging initial edges |
695 | TopoDS_Iterator aItv(E1,Standard_False); |
696 | for( ; aItv.More(); aItv.Next()) { |
697 | if(aItv.Value().Orientation() == TopAbs_INTERNAL || |
698 | aItv.Value().Orientation() == TopAbs_EXTERNAL) { |
699 | TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value()); |
700 | TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE1,E1); |
701 | B.Add(newE1,anewV); |
702 | Context()->Replace(aOldV,anewV); |
703 | } |
704 | } |
705 | |
706 | Context()->Replace(E1,newE1); |
707 | sbwd->Set(newE1,n1); |
708 | } |
709 | |
710 | if (done2) |
711 | { |
712 | // Update second edge |
713 | TopoDS_Edge newE2 = SBE.CopyReplaceVertices(E2,newV2,nullV); |
714 | //smh#8 |
715 | TopoDS_Shape tmpE2 = newE2.Oriented(TopAbs_FORWARD); |
716 | B.UpdateEdge(TopoDS::Edge(tmpE2),c2,0.); |
717 | SBE.SetRange3d(TopoDS::Edge(tmpE2),first2,last2); |
718 | SFST.SetTolerance(newE2,::Precision::Confusion(),TopAbs_EDGE); |
719 | B.SameRange(newE2,Standard_False); |
720 | // B.SameParameter(newE2,Standard_False); |
721 | |
722 | //To keep NM vertices belonging initial edges |
723 | TopoDS_Iterator aItv(E2,Standard_False); |
724 | for( ; aItv.More(); aItv.Next()) { |
725 | if(aItv.Value().Orientation() == TopAbs_INTERNAL || |
726 | aItv.Value().Orientation() == TopAbs_EXTERNAL) { |
727 | TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value()); |
728 | TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE2,E2); |
729 | B.Add(newE2,anewV); |
730 | Context()->Replace(aOldV,anewV); |
731 | } |
732 | } |
733 | Context()->Replace(E2,newE2); |
734 | sbwd->Set(newE2,n2); |
735 | } |
736 | |
737 | myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 ); |
738 | } |
739 | else |
740 | if (convert) |
741 | myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 ); |
742 | |
743 | return (done1 || done2); |
744 | } |
745 | |
746 | //======================================================================= |
747 | //function : FixGap2d |
748 | //purpose : |
749 | //======================================================================= |
750 | |
751 | static Standard_Real AdjustOnPeriodic2d (const Handle(Geom2d_Curve)& pc, |
752 | const Standard_Boolean takefirst, |
753 | const Standard_Real first, |
754 | const Standard_Real last, |
755 | const Standard_Real param) |
756 | { |
757 | // 15.11.2002 PTV OCC966 |
758 | if (ShapeAnalysis_Curve::IsPeriodic(pc)) |
759 | { |
760 | Standard_Real T = pc->Period(); |
761 | Standard_Real shift = -IntegerPart(first/T)*T; if (first<0.) shift += T; |
762 | Standard_Real sfirst = first+shift, slast = last+shift; |
763 | if ( takefirst && (param>slast) && (param>sfirst)) return param-T-shift; |
764 | if (!takefirst && (param<slast) && (param<sfirst)) return param+T-shift; |
765 | } |
766 | return param; |
767 | } |
768 | |
769 | Standard_Boolean ShapeFix_Wire::FixGap2d (const Standard_Integer num, |
770 | const Standard_Boolean convert) |
771 | { |
772 | myLastFixStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK ); |
773 | if ( !IsReady() ) return Standard_False; |
774 | |
775 | //============= |
776 | // First phase: analysis whether the problem (gap) exists |
777 | //============= |
778 | |
779 | if (Context().IsNull()) SetContext(new ShapeBuild_ReShape); |
780 | |
781 | Standard_Real preci = ::Precision::PConfusion(); |
782 | //Standard_Real preci = Precision(); |
783 | //GeomAdaptor_Surface& SA = Analyzer().Surface()->Adaptor()->ChangeSurface(); |
784 | //preci = Max(SA.UResolution(preci), SA.VResolution(preci)); |
785 | |
786 | Handle(ShapeExtend_WireData) sbwd = WireData(); |
787 | Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() ); |
788 | Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() ); |
789 | //smh#8 |
790 | TopoDS_Shape tmp1 = Context()->Apply(sbwd->Edge(n1)), |
791 | tmp2 = Context()->Apply(sbwd->Edge(n2)); |
792 | TopoDS_Edge E1 = TopoDS::Edge(tmp1), |
793 | E2 = TopoDS::Edge(tmp2); |
794 | TopoDS_Face face = myAnalyzer->Face(); |
795 | |
796 | // Retrieve pcurves on edges |
797 | Standard_Real cfirst1, clast1, cfirst2, clast2; |
798 | Handle(Geom2d_Curve) PC1, PC2; |
799 | ShapeAnalysis_Edge SAE; |
800 | if (!SAE.PCurve(E1,face,PC1,cfirst1,clast1) || |
801 | !SAE.PCurve(E2,face,PC2,cfirst2,clast2) || |
802 | sbwd->IsSeam(n1) || sbwd->IsSeam(n2)) |
803 | { |
804 | myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 ); |
805 | return Standard_False; |
806 | } |
807 | |
808 | // Check gap in 2d space |
809 | gp_Pnt2d cpnt1 = PC1->Value(clast1), cpnt2 = PC2->Value(cfirst2); |
810 | Standard_Real gap = cpnt1.Distance(cpnt2); |
811 | if (gap<=preci) return Standard_False; |
812 | |
813 | //============= |
814 | // Second phase: collecting data necessary for further analysis |
815 | //============= |
816 | |
817 | Standard_Boolean reversed1 = (E1.Orientation()==TopAbs_REVERSED), |
818 | reversed2 = (E2.Orientation()==TopAbs_REVERSED); |
819 | |
820 | Standard_Real first1, last1, first2, last2; |
821 | if (reversed1) |
822 | { |
823 | first1 = clast1; last1 = cfirst1; |
824 | } |
825 | else |
826 | { |
827 | first1 = cfirst1; last1 = clast1; |
828 | } |
829 | if (reversed2) |
830 | { |
831 | first2 = clast2; last2 = cfirst2; |
832 | } |
833 | else |
834 | { |
835 | first2 = cfirst2; last2 = clast2; |
836 | } |
837 | |
838 | Handle(Geom2d_Curve) pc1 = PC1, pc2 = PC2; |
839 | |
840 | // Extract basic curves from trimmed and offset |
841 | Standard_Boolean basic = Standard_False; |
842 | Standard_Boolean trimmed1 = Standard_False, offset1 = Standard_False; |
843 | Standard_Real offval1 = 0.; |
844 | while (!basic) |
845 | { |
846 | if (pc1->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) |
847 | { |
848 | pc1 = Handle(Geom2d_TrimmedCurve)::DownCast(pc1)->BasisCurve(); |
849 | trimmed1 = Standard_True; |
850 | } |
851 | else if (pc1->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))) |
852 | { |
853 | Handle(Geom2d_OffsetCurve) oc = Handle(Geom2d_OffsetCurve)::DownCast(pc1); |
854 | pc1 = oc->BasisCurve(); |
855 | offval1 += oc->Offset(); |
856 | offset1 = Standard_True; |
857 | } |
858 | else basic = Standard_True; |
859 | } |
860 | basic = Standard_False; |
861 | Standard_Boolean trimmed2 = Standard_False, offset2 = Standard_False; |
862 | Standard_Real offval2 = 0.; |
863 | while (!basic) |
864 | { |
865 | if (pc2->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) |
866 | { |
867 | pc2 = Handle(Geom2d_TrimmedCurve)::DownCast(pc2)->BasisCurve(); |
868 | trimmed2 = Standard_True; |
869 | } |
870 | else if (pc2->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))) |
871 | { |
872 | Handle(Geom2d_OffsetCurve) oc = Handle(Geom2d_OffsetCurve)::DownCast(pc2); |
873 | pc2 = oc->BasisCurve(); |
874 | offval2 += oc->Offset(); |
875 | offset2 = Standard_True; |
876 | } |
877 | else basic = Standard_True; |
878 | } |
879 | // Restore offset curves |
880 | if (offset1) pc1 = new Geom2d_OffsetCurve(pc1,offval1); |
881 | if (offset2) pc2 = new Geom2d_OffsetCurve(pc2,offval2); |
882 | |
883 | Standard_Boolean done1 = Standard_False, done2 = Standard_False; |
884 | |
885 | // Determine same edge case |
886 | if (convert) |
887 | { |
888 | |
889 | Handle(Geom2d_BSplineCurve) bsp1, bsp2; |
890 | Handle(Geom2d_Curve) pc; |
891 | Standard_Real first, last; |
892 | |
893 | // iterate on pcurves |
894 | Standard_Integer nbcurv = (n1==n2? 1 : 2); |
895 | for (Standard_Integer j=1; j<=nbcurv; j++) |
896 | { |
897 | //Standard_Integer trim = Standard_False; // skl |
898 | Handle(Geom2d_BSplineCurve) bsp; |
899 | |
900 | if (j==1) |
901 | { |
902 | pc = pc1; first = first1; last = last1; /*trim = trimmed1;*/ |
903 | } // skl |
904 | else |
905 | { |
906 | pc = pc2; first = first2; last = last2; /*trim = trimmed2;*/ |
907 | } // skl |
908 | |
909 | // Convert pcurve to bspline |
910 | if (pc->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) |
911 | { |
912 | bsp = Handle(Geom2d_BSplineCurve)::DownCast(pc->Copy()); |
913 | // take segment if trim and range differ |
914 | Standard_Real fbsp = bsp->FirstParameter(), lbsp = bsp->LastParameter(); |
915 | Standard_Boolean segment = Standard_False; |
916 | if (first>fbsp) |
917 | { |
918 | fbsp = first; segment = Standard_True; |
919 | } |
920 | if (last<lbsp) |
921 | { |
922 | lbsp = last; segment = Standard_True; |
923 | } |
924 | if (segment) |
925 | bsp = Geom2dConvert::SplitBSplineCurve(bsp,fbsp,lbsp, |
926 | ::Precision::PConfusion()); |
927 | } |
928 | else if (pc->IsKind(STANDARD_TYPE(Geom2d_Conic))) |
929 | { |
930 | GeomAdaptor_Surface& AS = myAnalyzer->Surface()->Adaptor3d()->ChangeSurface(); |
931 | Standard_Real tolu = AS.UResolution(myAnalyzer->Precision()), |
932 | tolv = AS.VResolution(myAnalyzer->Precision()); |
933 | Approx_Curve2d Conv(new Geom2dAdaptor_HCurve(pc,first,last), |
934 | first,last,tolu,tolv,GeomAbs_C1,9,1000); |
935 | if (Conv.IsDone() || Conv.HasResult()) bsp = Conv.Curve(); |
936 | } |
937 | else |
938 | { |
939 | // Restore trim for pcurve |
940 | try |
941 | { |
942 | OCC_CATCH_SIGNALS |
943 | Handle(Geom2d_Curve) c; |
944 | // 15.11.2002 PTV OCC966 |
945 | if(!ShapeAnalysis_Curve::IsPeriodic(pc)) |
946 | c = new Geom2d_TrimmedCurve(pc,Max(first,pc->FirstParameter()),Min(last,pc->LastParameter())); |
947 | else |
948 | c = new Geom2d_TrimmedCurve(pc,first,last); |
949 | bsp = Geom2dConvert::CurveToBSplineCurve(c); |
950 | } |
951 | catch (Standard_Failure) |
952 | { |
0797d9d3 |
953 | #ifdef OCCT_DEBUG |
7fd59977 |
954 | cout << "Warning: ShapeFix_Wire_1::FixGap2d: Exception in TrimmedCurve2d" <<first<<" " <<last<<endl; |
955 | Standard_Failure::Caught()->Print(cout); cout << endl; |
956 | #endif |
957 | } |
958 | } |
959 | |
960 | if (j==1) bsp1 = bsp; else bsp2 = bsp; |
961 | } |
962 | |
963 | // Take curves ends if could not convert |
964 | gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5); |
965 | if (bsp1.IsNull()) mpnt = cpnt1; |
966 | else if (bsp2.IsNull()) mpnt = cpnt2; |
967 | |
968 | if (!bsp1.IsNull()) |
969 | { |
970 | if(bsp1->Degree() == 1) bsp1->IncreaseDegree(2); |
971 | if (n1==n2) |
972 | { |
973 | bsp1->SetPole(1,mpnt); bsp1->SetPole(bsp1->NbPoles(),mpnt); |
974 | } |
975 | else |
976 | { |
977 | if (reversed1) bsp1->SetPole(1,mpnt); |
978 | else bsp1->SetPole(bsp1->NbPoles(),mpnt); |
979 | } |
980 | first1 = bsp1->FirstParameter(); last1 = bsp1->LastParameter(); |
981 | pc1 = bsp1; |
982 | done1 = Standard_True; |
983 | } |
984 | if (!bsp2.IsNull()) |
985 | { |
986 | if(bsp2->Degree() == 1) bsp2->IncreaseDegree(2); |
987 | if (reversed2) bsp2->SetPole(bsp2->NbPoles(),mpnt); |
988 | else bsp2->SetPole(1,mpnt); |
989 | first2 = bsp2->FirstParameter(); last2 = bsp2->LastParameter(); |
990 | pc2 = bsp2; |
991 | done2 = Standard_True; |
992 | } |
993 | } |
994 | else |
995 | { |
996 | |
997 | if (n1==n2) |
998 | { |
999 | if (pc1->IsKind(STANDARD_TYPE(Geom2d_Circle)) || |
1000 | pc1->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) |
1001 | { |
c6541a0c |
1002 | Standard_Real diff = M_PI - Abs(clast1-cfirst2)*0.5; |
7fd59977 |
1003 | first1 -= diff; last1 += diff; |
1004 | done1 = Standard_True; |
1005 | } |
1006 | } |
1007 | else |
1008 | { |
1009 | |
1010 | // Determine domains for extremal points locating |
1011 | Standard_Real domfirst1 = first1, domlast1 = last1; |
1012 | if (pc1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) || |
1013 | pc1->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) |
1014 | { |
1015 | domfirst1 = pc1->FirstParameter(); |
1016 | domlast1 = pc1->LastParameter(); |
1017 | } |
1018 | else if (pc1->IsKind(STANDARD_TYPE(Geom2d_Line)) || |
1019 | pc1->IsKind(STANDARD_TYPE(Geom2d_Parabola)) || |
1020 | pc1->IsKind(STANDARD_TYPE(Geom2d_Hyperbola))) |
1021 | { |
1022 | Standard_Real diff = domlast1 - domfirst1; |
1023 | if (reversed1) domfirst1 -= 10.*diff; |
1024 | else domlast1 += 10.*diff; |
1025 | } |
1026 | else if (pc1->IsKind(STANDARD_TYPE(Geom2d_Circle)) || |
1027 | pc1->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) |
1028 | { |
c6541a0c |
1029 | domfirst1 = 0.; domlast1 = 2*M_PI; |
7fd59977 |
1030 | } |
1031 | Standard_Real domfirst2 = first2, domlast2 = last2; |
1032 | if (pc2->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) || |
1033 | pc2->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) |
1034 | { |
1035 | domfirst2 = pc2->FirstParameter(); |
1036 | domlast2 = pc2->LastParameter(); |
1037 | } |
1038 | else if (pc2->IsKind(STANDARD_TYPE(Geom2d_Line)) || |
1039 | pc2->IsKind(STANDARD_TYPE(Geom2d_Parabola)) || |
1040 | pc2->IsKind(STANDARD_TYPE(Geom2d_Hyperbola))) |
1041 | { |
1042 | Standard_Real diff = domlast2 - domfirst2; |
1043 | if (reversed2) domlast2 += 10.*diff; |
1044 | else domfirst2 -= 10.*diff; |
1045 | } |
1046 | else if (pc2->IsKind(STANDARD_TYPE(Geom2d_Circle)) || |
1047 | pc2->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) |
1048 | { |
c6541a0c |
1049 | domfirst2 = 0.; domlast2 = 2*M_PI; |
7fd59977 |
1050 | } |
1051 | |
1052 | Standard_Real ipar1 = clast1, ipar2 = cfirst2; |
1053 | |
1054 | Geom2dInt_GInter Inter; |
1055 | Standard_Real tolint = ::Precision::PConfusion(); |
1056 | |
1057 | Geom2dAdaptor_Curve AC1(pc1), AC2(pc2); |
1058 | |
1059 | // Try to find intersection points |
1060 | IntRes2d_Domain dom1(pc1->Value(domfirst1),domfirst1,tolint, |
1061 | pc1->Value(domlast1),domlast1,tolint); |
1062 | IntRes2d_Domain dom2(pc2->Value(domfirst2),domfirst2,tolint, |
1063 | pc2->Value(domlast2),domlast2,tolint); |
1064 | Inter.Perform( AC1, dom1, AC2, dom2, tolint, tolint ); |
1065 | if (Inter.IsDone()) |
1066 | { |
1067 | if (Inter.NbPoints() || Inter.NbSegments()) |
1068 | { |
1069 | Standard_Integer i, index1 = 0, index2 = 0; |
1070 | Standard_Real pardist, pardist1=-1., pardist2=-1.; |
1071 | // iterate on intersection points |
1072 | IntRes2d_IntersectionPoint IP; |
1073 | for ( i=1; i<=Inter.NbPoints(); i++ ) |
1074 | { |
1075 | IP = Inter.Point(i); |
1076 | // Adjust parameters on periodic curves |
1077 | Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1, |
1078 | IP.ParamOnFirst()); |
1079 | Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2, |
1080 | IP.ParamOnSecond()); |
1081 | pardist = Abs(cfirst1-u1); |
1082 | if (pardist1>pardist || pardist1<0.) |
1083 | { |
1084 | index1 = i; pardist1 = pardist; |
1085 | } |
1086 | pardist = Abs(clast2-u2); |
1087 | if (pardist2>pardist || pardist2<0.) |
1088 | { |
1089 | index2 = i; pardist2 = pardist; |
1090 | } |
1091 | } |
1092 | Standard_Integer flag1 = 0, flag2 = 0; |
1093 | // iterate on intersection segments |
1094 | IntRes2d_IntersectionSegment IS; |
1095 | for ( i=1; i<=Inter.NbSegments(); i++ ) |
1096 | { |
1097 | IS = Inter.Segment(i); |
1098 | for (Standard_Integer j=1; j<=2; j++) |
1099 | { |
1100 | if ((j==1 && IS.HasFirstPoint()) || |
1101 | (j==2 && IS.HasLastPoint())) |
1102 | { |
1103 | if (j==1) IP = IS.FirstPoint(); |
1104 | else IP = IS.LastPoint(); |
1105 | // Adjust parameters on periodic curves |
1106 | Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1, |
1107 | IP.ParamOnFirst()); |
1108 | Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2, |
1109 | IP.ParamOnSecond()); |
1110 | pardist = Abs(cfirst1-u1); |
1111 | if (pardist1>pardist || pardist1<0.) |
1112 | { |
1113 | flag1 = j; index1 = i; pardist1 = pardist; |
1114 | } |
1115 | pardist = Abs(clast2-u2); |
1116 | if (pardist2>pardist || pardist2<0.) |
1117 | { |
1118 | flag2 = j; index2 = i; pardist2 = pardist; |
1119 | } |
1120 | } |
1121 | } |
1122 | } |
1123 | if (index1!=index2 || flag1!=flag2) |
1124 | { |
1125 | // take intersection closer to mean point |
1126 | gp_Pnt2d pt1, pt2; |
1127 | if (flag1==0) pt1 = Inter.Point(index1).Value(); |
1128 | else |
1129 | { |
1130 | IS = Inter.Segment(index1); |
1131 | if (flag1==1) pt1 = IS.FirstPoint().Value(); |
1132 | else pt1 = IS.LastPoint().Value(); |
1133 | } |
1134 | if (flag2==0) pt2 = Inter.Point(index2).Value(); |
1135 | else |
1136 | { |
1137 | IS = Inter.Segment(index2); |
1138 | if (flag2==1) pt2 = IS.FirstPoint().Value(); |
1139 | else pt2 = IS.LastPoint().Value(); |
1140 | } |
1141 | gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5); |
1142 | if (pt2.Distance(mpnt) < pt1.Distance(mpnt)) |
1143 | { |
1144 | index1 = index2; flag1 = flag2; |
1145 | } |
1146 | } |
1147 | if (flag1==0) IP = Inter.Point(index1); |
1148 | else |
1149 | { |
1150 | IS = Inter.Segment(index1); |
1151 | if (flag1==1) IP = IS.FirstPoint(); |
1152 | else IP = IS.LastPoint(); |
1153 | } |
1154 | // Ajust parameters on periodic curves |
1155 | Standard_Real u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1, |
1156 | IP.ParamOnFirst()); |
1157 | Standard_Real u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2, |
1158 | IP.ParamOnSecond()); |
1159 | // Check points to satisfy distance criterium |
1160 | gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2); |
1161 | if (p1.Distance(p2)<=gap && |
1162 | Abs(cfirst1-u1) > ::Precision::PConfusion() && |
1163 | Abs(clast2 -u2) > ::Precision::PConfusion() && |
1164 | (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) || |
1165 | (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap))) |
1166 | { |
1167 | ipar1 = u1; ipar2 = u2; |
1168 | done1 = done2 = Standard_True; |
1169 | } |
1170 | } |
1171 | } |
1172 | |
1173 | // Try to find closest points if nothing yet found |
1174 | if (!done1) |
1175 | { |
1176 | Geom2dAPI_ExtremaCurveCurve Extr(pc1,pc2,domfirst1,domlast1,domfirst2,domlast2); |
1177 | if (Extr.NbExtrema()) |
1178 | { |
1179 | Standard_Real u1, u2; |
1180 | Extr.LowerDistanceParameters(u1,u2); |
1181 | // Ajust parameters on periodic curves |
1182 | u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1); |
1183 | u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2); |
1184 | // Check points to satisfy distance criterium |
1185 | gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2); |
1186 | if (p1.Distance(p2)<=gap && |
1187 | Abs(cfirst1-u1) > ::Precision::PConfusion() && |
1188 | Abs(clast2 -u2) > ::Precision::PConfusion() && |
1189 | (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) || |
1190 | (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap))) |
1191 | { |
1192 | ipar1 = u1; ipar2 = u2; |
1193 | done1 = done2 = Standard_True; |
1194 | } |
1195 | } |
1196 | } |
1197 | |
1198 | // Try to find projections if nothing yet found |
1199 | if (!done1) |
1200 | { |
1201 | Geom2dAPI_ProjectPointOnCurve Proj; |
1202 | gp_Pnt2d ipnt1 = cpnt1, ipnt2 = cpnt2; |
1203 | Standard_Real u1 = ipar1, u2 = ipar2; |
1204 | Proj.Init(cpnt2,pc1,domfirst1,domlast1); |
1205 | if (Proj.NbPoints()) |
1206 | { |
1207 | Standard_Integer index = 1; |
1208 | Standard_Real dist, mindist=-1.; |
1209 | for (Standard_Integer i=1; i<=Proj.NbPoints(); i++) |
1210 | { |
1211 | dist = cpnt2.Distance(Proj.Point(i)); |
1212 | if (mindist>dist || mindist<0.) |
1213 | { |
1214 | index = i; mindist = dist; |
1215 | } |
1216 | ipnt1 = Proj.Point(index); |
1217 | u1 = Proj.Parameter(index); |
1218 | } |
1219 | } |
1220 | Proj.Init(cpnt1,pc2,domfirst2,domlast2); |
1221 | if (Proj.NbPoints()) |
1222 | { |
1223 | Standard_Integer index = 1; |
1224 | Standard_Real dist, mindist=-1.; |
1225 | for (Standard_Integer i=1; i<=Proj.NbPoints(); i++) |
1226 | { |
1227 | dist = cpnt1.Distance(Proj.Point(i)); |
1228 | if (mindist>dist || mindist<0.) |
1229 | { |
1230 | index = i; mindist = dist; |
1231 | } |
1232 | ipnt2 = Proj.Point(index); |
1233 | u2 = Proj.Parameter(index); |
1234 | } |
1235 | } |
1236 | // Ajust parameters on periodic curves |
1237 | u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1); |
1238 | u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2); |
1239 | // Process special case of projection |
1240 | if ((((reversed1 && u1>clast1) || (!reversed1 && u1<clast1)) && |
1241 | ((reversed2 && u2<cfirst2) || (!reversed2 && u2>cfirst2))) || |
1242 | (((reversed1 && u1<clast1) || (!reversed1 && u1>clast1)) && |
1243 | ((reversed2 && u2>cfirst2) || (!reversed2 && u2<cfirst2)))) |
1244 | { |
1245 | // both projections lie inside/outside initial domains |
1246 | // project mean point |
1247 | gp_Pnt2d mpnt((cpnt1.XY()+cpnt2.XY())*0.5); |
1248 | u1 = ipar1; u2 = ipar2; |
1249 | Proj.Init(mpnt,pc1,domfirst1,domlast1); |
1250 | if (Proj.NbPoints()) |
1251 | { |
1252 | Standard_Integer index = 1; |
1253 | Standard_Real dist, mindist=-1.; |
1254 | for (Standard_Integer i=1; i<=Proj.NbPoints(); i++) |
1255 | { |
1256 | dist = mpnt.Distance(Proj.Point(i)); |
1257 | if (mindist>dist || mindist<0.) |
1258 | { |
1259 | index = i; mindist = dist; |
1260 | } |
1261 | ipnt1 = Proj.Point(index); |
1262 | u1 = Proj.Parameter(index); |
1263 | } |
1264 | } |
1265 | Proj.Init(mpnt,pc2,domfirst2,domlast2); |
1266 | if (Proj.NbPoints()) |
1267 | { |
1268 | Standard_Integer index = 1; |
1269 | Standard_Real dist, mindist=-1.; |
1270 | for (Standard_Integer i=1; i<=Proj.NbPoints(); i++) |
1271 | { |
1272 | dist = mpnt.Distance(Proj.Point(i)); |
1273 | if (mindist>dist || mindist<0.) |
1274 | { |
1275 | index = i; mindist = dist; |
1276 | } |
1277 | ipnt2 = Proj.Point(index); |
1278 | u2 = Proj.Parameter(index); |
1279 | } |
1280 | } |
1281 | } |
1282 | else |
1283 | { |
1284 | if (cpnt1.Distance(ipnt2)<cpnt2.Distance(ipnt1)) u1 = ipar1; |
1285 | else u2 = ipar2; |
1286 | } |
1287 | // Ajust parameters on periodic curves |
1288 | u1 = AdjustOnPeriodic2d(pc1,reversed1,first1,last1,u1); |
1289 | u2 = AdjustOnPeriodic2d(pc2,!reversed2,first2,last2,u2); |
1290 | // Check points to satisfy distance criterium |
1291 | gp_Pnt2d p1 = pc1->Value(u1), p2 = pc2->Value(u2); |
1292 | if (p1.Distance(p2)<=gap && |
1293 | Abs(cfirst1-u1) > ::Precision::PConfusion() && |
1294 | Abs(clast2 -u2) > ::Precision::PConfusion() && |
1295 | (((u1>first1) && (u1<last1)) || ((u2>first2) && (u2<last2)) || |
1296 | (cpnt1.Distance(p1)<=gap) || (cpnt2.Distance(p2)<=gap))) |
1297 | { |
1298 | ipar1 = u1; ipar2 = u2; |
1299 | done1 = done2 = Standard_True; |
1300 | } |
1301 | } |
1302 | |
1303 | if (done1) |
1304 | { |
1305 | |
1306 | if (ipar1<first1 || ipar1>last1 || ipar2<first2 || ipar2>last2) |
1307 | { |
1308 | |
1309 | // Check whether new points lie inside the surface bounds |
1310 | Standard_Real umin, umax, vmin, vmax; |
1311 | myAnalyzer->Surface()->Surface()->Bounds(umin,umax,vmin,vmax); |
1312 | if (::Precision::IsInfinite(umin) || ::Precision::IsInfinite(umax) || |
1313 | ::Precision::IsInfinite(vmin) || ::Precision::IsInfinite(vmax)) |
1314 | { |
1315 | Standard_Real fumin, fumax, fvmin, fvmax; |
1316 | BRepTools::UVBounds(face,fumin,fumax,fvmin,fvmax); |
1317 | if (::Precision::IsInfinite(umin)) umin = fumin-preci; |
1318 | if (::Precision::IsInfinite(umax)) umax = fumax+preci; |
1319 | if (::Precision::IsInfinite(vmin)) vmin = fvmin-preci; |
1320 | if (::Precision::IsInfinite(vmax)) vmax = fvmax+preci; |
1321 | } |
1322 | |
1323 | gp_Pnt2d ipnt, P1, P2; |
1324 | Standard_Real u, v; |
1325 | Standard_Boolean out; |
1326 | // iterate on curves |
1327 | for (Standard_Integer j=1; j<=2; j++) |
1328 | { |
1329 | |
1330 | if (j==1) |
1331 | { |
1332 | if (ipar1>=first1 && ipar1<=last1) continue; |
1333 | ipnt = pc1->Value(ipar1); |
1334 | } |
1335 | else |
1336 | { |
1337 | if (ipar2>=first2 && ipar2<=last2) continue; |
1338 | ipnt = pc2->Value(ipar2); |
1339 | } |
1340 | |
1341 | // iterate on bounding lines |
1342 | for (Standard_Integer k=1; k<=2; k++) |
1343 | { |
1344 | |
1345 | u = ipnt.X(); v = ipnt.Y(); |
1346 | |
1347 | out = Standard_True; |
1348 | if (k==1) |
1349 | { |
1350 | if (u<umin) |
1351 | { |
1352 | P1 = gp_Pnt2d(umin,vmin); P2 = gp_Pnt2d(umin,vmax); |
1353 | } |
1354 | else if (u>umax) |
1355 | { |
1356 | P1 = gp_Pnt2d(umax,vmin); P2 = gp_Pnt2d(umax,vmax); |
1357 | } |
1358 | else out = Standard_False; |
1359 | } |
1360 | else |
1361 | { |
1362 | if (v<vmin) |
1363 | { |
1364 | P1 = gp_Pnt2d(umin,vmin); P2 = gp_Pnt2d(umax,vmin); |
1365 | } |
1366 | else if (v>vmax) |
1367 | { |
1368 | P1 = gp_Pnt2d(umin,vmax); P2 = gp_Pnt2d(umax,vmax); |
1369 | } |
1370 | else out = Standard_False; |
1371 | } |
1372 | |
1373 | if (out) |
1374 | { |
1375 | // Intersect pcurve with bounding line |
1376 | Handle(Geom2d_Line) lin = new Geom2d_Line(P1,gp_Dir2d(gp_Vec2d(P1,P2))); |
1377 | Geom2dAdaptor_Curve ACL(lin); |
1378 | IntRes2d_Domain dlin(P1,0.,tolint,P2,P1.Distance(P2),tolint); |
1379 | |
1380 | Handle(Geom2d_Curve) pc; |
1381 | Standard_Real fpar, lpar; |
1382 | if (j==1) |
1383 | { |
1384 | if (cfirst1<ipar1) |
1385 | { |
1386 | fpar = cfirst1, lpar = ipar1; |
1387 | } |
1388 | else |
1389 | { |
1390 | fpar = ipar1, lpar = cfirst1; |
1391 | } |
1392 | pc = pc1; |
1393 | } |
1394 | else |
1395 | { |
1396 | if (clast2<ipar2) |
1397 | { |
1398 | fpar = clast2, lpar = ipar2; |
1399 | } |
1400 | else |
1401 | { |
1402 | fpar = ipar2, lpar = clast2; |
1403 | } |
1404 | pc = pc2; |
1405 | } |
1406 | Geom2dAdaptor_Curve ACC(pc); |
1407 | IntRes2d_Domain domc(pc->Value(fpar),fpar,tolint, |
1408 | pc->Value(lpar),lpar,tolint); |
1409 | |
1410 | // Intersect line with the pcurve |
1411 | Inter.Perform( ACL, dlin, ACC, domc, tolint, tolint ); |
1412 | if (Inter.IsDone()) |
1413 | { |
1414 | if (Inter.NbPoints() || Inter.NbSegments()) |
1415 | { |
1416 | Standard_Integer i, index = 1; |
1417 | Standard_Real uu, dist, mindist=-1.; |
1418 | // iterate on intersection points |
1419 | for ( i=1; i<=Inter.NbPoints(); i++ ) |
1420 | { |
1421 | // Adjust parameters on periodic curve |
1422 | uu = AdjustOnPeriodic2d(pc,(j==1? reversed1 : !reversed2), |
1423 | fpar,lpar,Inter.Point(i).ParamOnSecond()); |
1424 | dist = Abs((j==1? cfirst1 : clast2)-uu); |
1425 | if (mindist>dist || mindist<0.) |
1426 | { |
1427 | index = i; mindist = dist; |
1428 | } |
1429 | } |
1430 | // iterate on intersection segments |
1431 | Standard_Integer flag = 0; |
1432 | IntRes2d_IntersectionPoint IP; |
1433 | IntRes2d_IntersectionSegment IS; |
1434 | for ( i=1; i<=Inter.NbSegments(); i++ ) |
1435 | { |
1436 | IS = Inter.Segment(i); |
1437 | for (Standard_Integer jj=1; jj<=2; jj++) |
1438 | { |
1439 | if ((jj==1 && IS.HasFirstPoint()) || |
1440 | (jj==2 && IS.HasLastPoint())) |
1441 | { |
1442 | if (jj==1) IP = IS.FirstPoint(); |
1443 | else IP = IS.LastPoint(); |
1444 | // Adjust parameters on periodic curve |
1445 | uu = AdjustOnPeriodic2d(pc,(jj==1? reversed1 : !reversed2), |
1446 | fpar,lpar,IP.ParamOnSecond()); |
1447 | dist = Abs((jj==1? cfirst1 : clast2)-uu); |
1448 | if (mindist>dist || mindist<0.) |
1449 | { |
1450 | flag = jj; index = i; mindist = dist; |
1451 | } |
1452 | } |
1453 | } |
1454 | } |
1455 | if (flag==0) IP = Inter.Point(index); |
1456 | else |
1457 | { |
1458 | IS = Inter.Segment(index); |
1459 | if (flag==1) IP = IS.FirstPoint(); |
1460 | else IP = IS.LastPoint(); |
1461 | } |
1462 | // Ajust parameters on periodic curve |
1463 | uu = AdjustOnPeriodic2d(pc,(j==1? reversed1 : !reversed2), |
1464 | fpar,lpar,IP.ParamOnSecond()); |
1465 | if (j==1 && Abs(cfirst1-uu) > ::Precision::PConfusion()) |
1466 | { |
1467 | ipar1 = uu; ipnt = IP.Value(); |
1468 | } |
1469 | if (j==2 && Abs(clast2-uu) > ::Precision::PConfusion()) |
1470 | { |
1471 | ipar2 = uu; ipnt = IP.Value(); |
1472 | } |
1473 | } |
1474 | } |
1475 | } |
1476 | } |
1477 | |
1478 | // Adjust if intersection lies inside old bounds |
1479 | if (j==1) |
1480 | { |
1481 | if (reversed1) |
1482 | { |
1483 | if (ipar1>first1) ipar1 = first1; |
1484 | } |
1485 | else |
1486 | { |
1487 | if (ipar1<last1) ipar1 = last1; |
1488 | } |
1489 | } |
1490 | else |
1491 | { |
1492 | if (reversed2) |
1493 | { |
1494 | if (ipar2<last2) ipar2 = last2; |
1495 | } |
1496 | else |
1497 | { |
1498 | if (ipar2>first2) ipar2 = first2; |
1499 | } |
1500 | } |
1501 | } |
1502 | } |
1503 | } |
1504 | try |
1505 | { |
1506 | OCC_CATCH_SIGNALS |
1507 | if (done1) |
1508 | { |
1509 | if (ipar1==clast1) done1 = Standard_False; |
1510 | else |
1511 | { |
1512 | // Set up new bounds for pcurve |
1513 | if (reversed1) first1 = ipar1; else last1 = ipar1; |
1514 | // Set new trim for old pcurve |
1515 | if (trimmed1) pc1 = new Geom2d_TrimmedCurve(pc1,first1,last1); |
1516 | } |
1517 | } |
1518 | if (done2) |
1519 | { |
1520 | if (ipar2==cfirst2) done2 = Standard_False; |
1521 | else |
1522 | { |
1523 | // Set up new bounds for pcurve |
1524 | if (reversed2) last2 = ipar2; else first2 = ipar2; |
1525 | // Set new trim for old pcurve |
1526 | if (trimmed2) pc2 = new Geom2d_TrimmedCurve(pc2,first2,last2); |
1527 | } |
1528 | } |
1529 | } |
1530 | catch (Standard_Failure) |
1531 | { |
1532 | |
0797d9d3 |
1533 | #ifdef OCCT_DEBUG |
7fd59977 |
1534 | cout << "Warning: ShapeFix_Wire_1::FixGap2d: Exception in TrimmedCurve2d :"<<endl; |
1535 | Standard_Failure::Caught()->Print(cout); cout << endl; |
1536 | #endif |
1537 | } |
1538 | } |
1539 | } |
1540 | |
1541 | if (done1 || done2) |
1542 | { |
1543 | |
1544 | BRep_Builder B; |
1545 | ShapeBuild_Edge SBE; |
1546 | ShapeFix_ShapeTolerance SFST; |
1547 | |
1548 | // Update vertices |
1549 | TopoDS_Vertex V1 = SAE.LastVertex(E1), V2 = SAE.FirstVertex(E2); |
1550 | TopoDS_Vertex nullV, newV1; |
1551 | //smh#8 |
1552 | TopoDS_Shape emptyCopiedV2 = V2.EmptyCopied(); |
1553 | TopoDS_Vertex newV2 = TopoDS::Vertex(emptyCopiedV2); |
1554 | SFST.SetTolerance(newV2,::Precision::Confusion()); |
1555 | Context()->Replace(V2,newV2); |
1556 | if (V1.IsSame(V2)) |
1557 | //smh#8 |
1558 | { |
1559 | TopoDS_Shape tmpVertexRev = newV2.Oriented(TopAbs_REVERSED); |
1560 | newV1 = TopoDS::Vertex(tmpVertexRev); |
1561 | } |
1562 | else |
1563 | { |
1564 | //smh#8 |
1565 | TopoDS_Shape emptyCopiedV1 = V1.EmptyCopied(); |
1566 | newV1 = TopoDS::Vertex(emptyCopiedV1); |
1567 | SFST.SetTolerance(newV1,::Precision::Confusion()); |
1568 | Context()->Replace(V1,newV1); |
1569 | } |
1570 | |
1571 | if (done1) |
1572 | { |
1573 | // Update first edge |
1574 | TopoDS_Edge newE1 = SBE.CopyReplaceVertices(E1,nullV,newV1); |
1575 | //smh#8 |
1576 | TopoDS_Shape tmpE1 = newE1.Oriented(TopAbs_FORWARD); |
1577 | B.UpdateEdge(TopoDS::Edge(tmpE1),pc1,face,0.); |
1578 | B.Range(TopoDS::Edge(tmpE1),face,first1,last1); |
1579 | SFST.SetTolerance(newE1,::Precision::Confusion(),TopAbs_EDGE); |
1580 | B.SameRange(newE1,Standard_False); |
1581 | // B.SameParameter(newE1,Standard_False); |
1582 | |
1583 | //To keep NM vertices belonging initial edges |
1584 | TopoDS_Iterator aItv(E1,Standard_False); |
1585 | for( ; aItv.More(); aItv.Next()) { |
1586 | if(aItv.Value().Orientation() == TopAbs_INTERNAL || |
1587 | aItv.Value().Orientation() == TopAbs_EXTERNAL) { |
1588 | TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value()); |
1589 | TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE1,E1); |
1590 | B.Add(newE1,anewV); |
1591 | Context()->Replace(aOldV,anewV); |
1592 | } |
1593 | } |
1594 | |
1595 | Context()->Replace(E1,newE1); |
1596 | sbwd->Set(newE1,n1); |
1597 | } |
1598 | |
1599 | if (done2) |
1600 | { |
1601 | // Update second edge |
1602 | TopoDS_Edge newE2 = SBE.CopyReplaceVertices(E2,newV2,nullV); |
1603 | //smh#8 |
1604 | TopoDS_Shape tmpE2 = newE2.Oriented(TopAbs_FORWARD); |
1605 | B.UpdateEdge(TopoDS::Edge(tmpE2),pc2,face,0.); |
1606 | B.Range(TopoDS::Edge(tmpE2),face,first2,last2); |
1607 | SFST.SetTolerance(newE2,::Precision::Confusion(),TopAbs_EDGE); |
1608 | B.SameRange(newE2,Standard_False); |
1609 | // B.SameParameter(newE2,Standard_False); |
1610 | //To keep NM vertices belonging initial edges |
1611 | TopoDS_Iterator aItv(E2,Standard_False); |
1612 | for( ; aItv.More(); aItv.Next()) { |
1613 | if(aItv.Value().Orientation() == TopAbs_INTERNAL || |
1614 | aItv.Value().Orientation() == TopAbs_EXTERNAL) { |
1615 | TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value()); |
1616 | TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,newE2,E2); |
1617 | B.Add(newE2,anewV); |
1618 | Context()->Replace(aOldV,anewV); |
1619 | } |
1620 | } |
1621 | Context()->Replace(E2,newE2); |
1622 | sbwd->Set(newE2,n2); |
1623 | } |
1624 | |
1625 | myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 ); |
1626 | } |
1627 | else |
1628 | if (convert) |
1629 | myLastFixStatus |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 ); |
1630 | |
1631 | return (done1 || done2); |
1632 | } |