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