0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / IntTools / IntTools_WLineTool.cxx
CommitLineData
d33a8cde 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
2//
3// This file is part of Open CASCADE Technology software library.
4//
5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
10//
11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
13
14#include <IntTools_WLineTool.hxx>
15
d33a8cde 16#include <BRep_Tool.hxx>
17#include <Extrema_ExtCC.hxx>
d33a8cde 18#include <Geom2dAPI_InterCurveCurve.hxx>
19#include <Geom2d_Circle.hxx>
20#include <Geom2d_Line.hxx>
21#include <Geom2d_TrimmedCurve.hxx>
4e14c88f 22#include <GeomAPI_ProjectPointOnSurf.hxx>
23#include <GeomAdaptor_Curve.hxx>
24#include <GeomAdaptor_HSurface.hxx>
25#include <GeomAdaptor_Surface.hxx>
26#include <GeomInt.hxx>
27#include <GeomInt_LineConstructor.hxx>
d33a8cde 28#include <Geom_Circle.hxx>
29#include <Geom_Surface.hxx>
30#include <gp_Circ.hxx>
31#include <IntTools_Context.hxx>
d33a8cde 32#include <TColStd_Array1OfListOfInteger.hxx>
4e14c88f 33#include <TColStd_SequenceOfReal.hxx>
34#include <TColgp_SequenceOfPnt2d.hxx>
d33a8cde 35
36/////////////////////// NotUseSurfacesForApprox /////////////////////////
37
38// The block is dedicated to determine whether WLine [ifprm, ilprm]
39// crosses the degenerated zone on each given surface or not.
40// If Yes -> We will not use info about surfaces during approximation
41// because inside degenerated zone of the surface the approx. algo.
42// uses wrong values of normal, etc., and resulting curve will have
43// oscillations that we would not like to have.
44
45//=======================================================================
46//function : IsDegeneratedZone
47//purpose : static subfunction in IsDegeneratedZone
48//=======================================================================
49static
50Standard_Boolean IsDegeneratedZone(const gp_Pnt2d& aP2d,
51 const Handle(Geom_Surface)& aS,
52 const Standard_Integer iDir)
53{
54 Standard_Boolean bFlag=Standard_True;
55 Standard_Real US1, US2, VS1, VS2, dY, dX, d1, d2, dD;
56 Standard_Real aXm, aYm, aXb, aYb, aXe, aYe;
57 aS->Bounds(US1, US2, VS1, VS2);
58
59 gp_Pnt aPm, aPb, aPe;
60
61 aXm=aP2d.X();
62 aYm=aP2d.Y();
63
64 aS->D0(aXm, aYm, aPm);
65
66 dX=1.e-5;
67 dY=1.e-5;
68 dD=1.e-12;
69
70 if (iDir==1) {
71 aXb=aXm;
72 aXe=aXm;
73 aYb=aYm-dY;
74 if (aYb < VS1) {
75 aYb=VS1;
76 }
77 aYe=aYm+dY;
78 if (aYe > VS2) {
79 aYe=VS2;
80 }
81 aS->D0(aXb, aYb, aPb);
82 aS->D0(aXe, aYe, aPe);
83
84 d1=aPm.Distance(aPb);
85 d2=aPm.Distance(aPe);
86 if (d1 < dD && d2 < dD) {
87 return bFlag;
88 }
89 return !bFlag;
90 }
91 //
92 else if (iDir==2) {
93 aYb=aYm;
94 aYe=aYm;
95 aXb=aXm-dX;
96 if (aXb < US1) {
97 aXb=US1;
98 }
99 aXe=aXm+dX;
100 if (aXe > US2) {
101 aXe=US2;
102 }
103 aS->D0(aXb, aYb, aPb);
104 aS->D0(aXe, aYe, aPe);
105
106 d1=aPm.Distance(aPb);
107 d2=aPm.Distance(aPe);
108 if (d1 < dD && d2 < dD) {
109 return bFlag;
110 }
111 return !bFlag;
112 }
113 return !bFlag;
114}
115
116//=======================================================================
117//function : IsPointInDegeneratedZone
118//purpose : static subfunction in NotUseSurfacesForApprox
119//=======================================================================
120static
121Standard_Boolean IsPointInDegeneratedZone(const IntSurf_PntOn2S& aP2S,
122 const TopoDS_Face& aF1,
123 const TopoDS_Face& aF2)
124
125{
126 Standard_Boolean bFlag=Standard_True;
127 Standard_Real US11, US12, VS11, VS12, US21, US22, VS21, VS22;
128 Standard_Real U1, V1, U2, V2, aDelta, aD;
129 gp_Pnt2d aP2d;
130
131 Handle(Geom_Surface)aS1 = BRep_Tool::Surface(aF1);
132 aS1->Bounds(US11, US12, VS11, VS12);
133 GeomAdaptor_Surface aGAS1(aS1);
134
135 Handle(Geom_Surface)aS2 = BRep_Tool::Surface(aF2);
136 aS1->Bounds(US21, US22, VS21, VS22);
137 GeomAdaptor_Surface aGAS2(aS2);
138 //
139 //const gp_Pnt& aP=aP2S.Value();
140 aP2S.Parameters(U1, V1, U2, V2);
141 //
142 aDelta=1.e-7;
143 // Check on Surf 1
144 aD=aGAS1.UResolution(aDelta);
145 aP2d.SetCoord(U1, V1);
146 if (fabs(U1-US11) < aD) {
147 bFlag=IsDegeneratedZone(aP2d, aS1, 1);
148 if (bFlag) {
149 return bFlag;
150 }
151 }
152 if (fabs(U1-US12) < aD) {
153 bFlag=IsDegeneratedZone(aP2d, aS1, 1);
154 if (bFlag) {
155 return bFlag;
156 }
157 }
158 aD=aGAS1.VResolution(aDelta);
159 if (fabs(V1-VS11) < aDelta) {
160 bFlag=IsDegeneratedZone(aP2d, aS1, 2);
161 if (bFlag) {
162 return bFlag;
163 }
164 }
165 if (fabs(V1-VS12) < aDelta) {
166 bFlag=IsDegeneratedZone(aP2d, aS1, 2);
167 if (bFlag) {
168 return bFlag;
169 }
170 }
171 // Check on Surf 2
172 aD=aGAS2.UResolution(aDelta);
173 aP2d.SetCoord(U2, V2);
174 if (fabs(U2-US21) < aDelta) {
175 bFlag=IsDegeneratedZone(aP2d, aS2, 1);
176 if (bFlag) {
177 return bFlag;
178 }
179 }
180 if (fabs(U2-US22) < aDelta) {
181 bFlag=IsDegeneratedZone(aP2d, aS2, 1);
182 if (bFlag) {
183 return bFlag;
184 }
185 }
186 aD=aGAS2.VResolution(aDelta);
187 if (fabs(V2-VS21) < aDelta) {
188 bFlag=IsDegeneratedZone(aP2d, aS2, 2);
189 if (bFlag) {
190 return bFlag;
191 }
192 }
193 if (fabs(V2-VS22) < aDelta) {
194 bFlag=IsDegeneratedZone(aP2d, aS2, 2);
195 if (bFlag) {
196 return bFlag;
197 }
198 }
199 return !bFlag;
200}
201
202//=======================================================================
203//function : NotUseSurfacesForApprox
204//purpose :
205//=======================================================================
206Standard_Boolean IntTools_WLineTool::NotUseSurfacesForApprox(const TopoDS_Face& aF1,
207 const TopoDS_Face& aF2,
208 const Handle(IntPatch_WLine)& WL,
209 const Standard_Integer ifprm,
210 const Standard_Integer ilprm)
211{
212 Standard_Boolean bPInDZ;
213
214 Handle(IntSurf_LineOn2S) aLineOn2S=WL->Curve();
215
216 const IntSurf_PntOn2S& aP2Sfprm=aLineOn2S->Value(ifprm);
217 bPInDZ=IsPointInDegeneratedZone(aP2Sfprm, aF1, aF2);
218 if (bPInDZ) {
219 return bPInDZ;
220 }
221
222 const IntSurf_PntOn2S& aP2Slprm=aLineOn2S->Value(ilprm);
223 bPInDZ=IsPointInDegeneratedZone(aP2Slprm, aF1, aF2);
224
225 return bPInDZ;
226}
227
228/////////////////////// end of NotUseSurfacesForApprox //////////////////
229
d33a8cde 230/////////////////////// DecompositionOfWLine ////////////////////////////
231
232//=======================================================================
233//function : CheckTangentZonesExist
234//purpose : static subfunction in ComputeTangentZones
235//=======================================================================
236static
237Standard_Boolean CheckTangentZonesExist(const Handle(GeomAdaptor_HSurface)& theSurface1,
238 const Handle(GeomAdaptor_HSurface)& theSurface2)
239{
240 if ( ( theSurface1->GetType() != GeomAbs_Torus ) ||
241 ( theSurface2->GetType() != GeomAbs_Torus ) )
242 return Standard_False;
243
244 gp_Torus aTor1 = theSurface1->Torus();
245 gp_Torus aTor2 = theSurface2->Torus();
246
247 if ( aTor1.Location().Distance( aTor2.Location() ) > Precision::Confusion() )
248 return Standard_False;
249
250 if ( ( fabs( aTor1.MajorRadius() - aTor2.MajorRadius() ) > Precision::Confusion() ) ||
251 ( fabs( aTor1.MinorRadius() - aTor2.MinorRadius() ) > Precision::Confusion() ) )
252 return Standard_False;
253
254 if ( ( aTor1.MajorRadius() < aTor1.MinorRadius() ) ||
255 ( aTor2.MajorRadius() < aTor2.MinorRadius() ) )
256 return Standard_False;
257
258 return Standard_True;
259}
260
261
262//=======================================================================
263//function : ComputeTangentZones
264//purpose : static subfunction in DecompositionOfWLine
265//=======================================================================
266static
267Standard_Integer ComputeTangentZones( const Handle(GeomAdaptor_HSurface)& theSurface1,
268 const Handle(GeomAdaptor_HSurface)& theSurface2,
269 const TopoDS_Face& theFace1,
270 const TopoDS_Face& theFace2,
271 Handle(TColgp_HArray1OfPnt2d)& theResultOnS1,
272 Handle(TColgp_HArray1OfPnt2d)& theResultOnS2,
273 Handle(TColStd_HArray1OfReal)& theResultRadius,
274 const Handle(IntTools_Context)& aContext)
275{
276 Standard_Integer aResult = 0;
277 if ( !CheckTangentZonesExist( theSurface1, theSurface2 ) )
278 return aResult;
279
280
281 TColgp_SequenceOfPnt2d aSeqResultS1, aSeqResultS2;
282 TColStd_SequenceOfReal aSeqResultRad;
283
284 gp_Torus aTor1 = theSurface1->Torus();
285 gp_Torus aTor2 = theSurface2->Torus();
286
287 gp_Ax2 anax1( aTor1.Location(), aTor1.Axis().Direction() );
288 gp_Ax2 anax2( aTor2.Location(), aTor2.Axis().Direction() );
289 Standard_Integer j = 0;
290
291 for ( j = 0; j < 2; j++ ) {
292 Standard_Real aCoef = ( j == 0 ) ? -1 : 1;
293 Standard_Real aRadius1 = fabs(aTor1.MajorRadius() + aCoef * aTor1.MinorRadius());
294 Standard_Real aRadius2 = fabs(aTor2.MajorRadius() + aCoef * aTor2.MinorRadius());
295
296 gp_Circ aCircle1( anax1, aRadius1 );
297 gp_Circ aCircle2( anax2, aRadius2 );
298
299 // roughly compute radius of tangent zone for perpendicular case
300 Standard_Real aCriteria = Precision::Confusion() * 0.5;
301
302 Standard_Real aT1 = aCriteria;
303 Standard_Real aT2 = aCriteria;
304 if ( j == 0 ) {
305 // internal tangency
306 Standard_Real aR = ( aRadius1 > aTor2.MinorRadius() ) ? aRadius1 : aTor2.MinorRadius();
307 //aT1 = aCriteria * aCriteria + aR * aR - ( aR - aCriteria ) * ( aR - aCriteria );
308 aT1 = 2. * aR * aCriteria;
309 aT2 = aT1;
310 }
311 else {
312 // external tangency
313 Standard_Real aRb = ( aRadius1 > aTor2.MinorRadius() ) ? aRadius1 : aTor2.MinorRadius();
314 Standard_Real aRm = ( aRadius1 < aTor2.MinorRadius() ) ? aRadius1 : aTor2.MinorRadius();
315 Standard_Real aDelta = aRb - aCriteria;
316 aDelta *= aDelta;
317 aDelta -= aRm * aRm;
318 aDelta /= 2. * (aRb - aRm);
319 aDelta -= 0.5 * (aRb - aRm);
320
321 aT1 = 2. * aRm * (aRm - aDelta);
322 aT2 = aT1;
323 }
324 aCriteria = ( aT1 > aT2) ? aT1 : aT2;
325 if ( aCriteria > 0 )
326 aCriteria = sqrt( aCriteria );
327
328 if ( aCriteria > 0.5 * aTor1.MinorRadius() ) {
329 // too big zone -> drop to minimum
330 aCriteria = Precision::Confusion();
331 }
332
333 GeomAdaptor_Curve aC1( new Geom_Circle(aCircle1) );
334 GeomAdaptor_Curve aC2( new Geom_Circle(aCircle2) );
335 Extrema_ExtCC anExtrema(aC1, aC2, 0, 2. * M_PI, 0, 2. * M_PI,
336 Precision::PConfusion(), Precision::PConfusion());
337
338 if ( anExtrema.IsDone() ) {
339
340 Standard_Integer i = 0;
341 for ( i = 1; i <= anExtrema.NbExt(); i++ ) {
342 if ( anExtrema.SquareDistance(i) > aCriteria * aCriteria )
343 continue;
344
345 Extrema_POnCurv P1, P2;
346 anExtrema.Points( i, P1, P2 );
347
348 Standard_Boolean bFoundResult = Standard_True;
349 gp_Pnt2d pr1, pr2;
350
351 Standard_Integer surfit = 0;
352 for ( surfit = 0; surfit < 2; surfit++ ) {
353 GeomAPI_ProjectPointOnSurf& aProjector =
354 (surfit == 0) ? aContext->ProjPS(theFace1) : aContext->ProjPS(theFace2);
355
356 gp_Pnt aP3d = (surfit == 0) ? P1.Value() : P2.Value();
357 aProjector.Perform(aP3d);
358
359 if(!aProjector.IsDone())
360 bFoundResult = Standard_False;
361 else {
362 if(aProjector.LowerDistance() > aCriteria) {
363 bFoundResult = Standard_False;
364 }
365 else {
366 Standard_Real foundU = 0, foundV = 0;
367 aProjector.LowerDistanceParameters(foundU, foundV);
368 if ( surfit == 0 )
369 pr1 = gp_Pnt2d( foundU, foundV );
370 else
371 pr2 = gp_Pnt2d( foundU, foundV );
372 }
373 }
374 }
375 if ( bFoundResult ) {
376 aSeqResultS1.Append( pr1 );
377 aSeqResultS2.Append( pr2 );
378 aSeqResultRad.Append( aCriteria );
379
380 // torus is u and v periodic
381 const Standard_Real twoPI = M_PI + M_PI;
382 Standard_Real arr1tmp[2] = {pr1.X(), pr1.Y()};
383 Standard_Real arr2tmp[2] = {pr2.X(), pr2.Y()};
384
385 // iteration on period bounds
386 for ( Standard_Integer k1 = 0; k1 < 2; k1++ ) {
387 Standard_Real aBound = ( k1 == 0 ) ? 0 : twoPI;
388 Standard_Real aShift = ( k1 == 0 ) ? twoPI : -twoPI;
389
390 // iteration on surfaces
391 for ( Standard_Integer k2 = 0; k2 < 2; k2++ ) {
392 Standard_Real* arr1 = ( k2 == 0 ) ? arr1tmp : arr2tmp;
393 Standard_Real* arr2 = ( k2 != 0 ) ? arr1tmp : arr2tmp;
394 TColgp_SequenceOfPnt2d& aSeqS1 = ( k2 == 0 ) ? aSeqResultS1 : aSeqResultS2;
395 TColgp_SequenceOfPnt2d& aSeqS2 = ( k2 != 0 ) ? aSeqResultS1 : aSeqResultS2;
396
397 if (fabs(arr1[0] - aBound) < Precision::PConfusion()) {
398 aSeqS1.Append( gp_Pnt2d( arr1[0] + aShift, arr1[1] ) );
399 aSeqS2.Append( gp_Pnt2d( arr2[0], arr2[1] ) );
400 aSeqResultRad.Append( aCriteria );
401 }
402 if (fabs(arr1[1] - aBound) < Precision::PConfusion()) {
403 aSeqS1.Append( gp_Pnt2d( arr1[0], arr1[1] + aShift) );
404 aSeqS2.Append( gp_Pnt2d( arr2[0], arr2[1] ) );
405 aSeqResultRad.Append( aCriteria );
406 }
407 }
408 } //
409 }
410 }
411 }
412 }
413 aResult = aSeqResultRad.Length();
414
415 if ( aResult > 0 ) {
416 theResultOnS1 = new TColgp_HArray1OfPnt2d( 1, aResult );
417 theResultOnS2 = new TColgp_HArray1OfPnt2d( 1, aResult );
418 theResultRadius = new TColStd_HArray1OfReal( 1, aResult );
419
420 for ( Standard_Integer i = 1 ; i <= aResult; i++ ) {
421 theResultOnS1->SetValue( i, aSeqResultS1.Value(i) );
422 theResultOnS2->SetValue( i, aSeqResultS2.Value(i) );
423 theResultRadius->SetValue( i, aSeqResultRad.Value(i) );
424 }
425 }
426 return aResult;
427}
428
429//=======================================================================
430//function : IsPointOnBoundary
431//purpose : static subfunction in DecompositionOfWLine
432//=======================================================================
433static
434Standard_Boolean IsPointOnBoundary(const Standard_Real theParameter,
435 const Standard_Real theFirstBoundary,
436 const Standard_Real theSecondBoundary,
437 const Standard_Real theResolution,
438 Standard_Boolean& IsOnFirstBoundary)
439{
440 Standard_Boolean bRet;
441 Standard_Integer i;
442 Standard_Real adist;
443 //
444 bRet=Standard_False;
445 for(i = 0; i < 2; ++i) {
446 IsOnFirstBoundary = (i == 0);
447 if (IsOnFirstBoundary) {
448 adist = fabs(theParameter - theFirstBoundary);
449 }
450 else {
451 adist = fabs(theParameter - theSecondBoundary);
452 }
453 if(adist < theResolution) {
454 return !bRet;
455 }
456 }
457 return bRet;
458}
459
460//=======================================================================
461//function : IsInsideTanZone
462//purpose : Check if point is inside a radial tangent zone.
463// static subfunction in DecompositionOfWLine and FindPoint
464//=======================================================================
465static
466Standard_Boolean IsInsideTanZone(const gp_Pnt2d& thePoint,
467 const gp_Pnt2d& theTanZoneCenter,
468 const Standard_Real theZoneRadius,
469 Handle(GeomAdaptor_HSurface) theGASurface)
470{
471 Standard_Real aUResolution = theGASurface->UResolution( theZoneRadius );
472 Standard_Real aVResolution = theGASurface->VResolution( theZoneRadius );
473 Standard_Real aRadiusSQR = ( aUResolution < aVResolution ) ? aUResolution : aVResolution;
474 aRadiusSQR *= aRadiusSQR;
475 if ( thePoint.SquareDistance( theTanZoneCenter ) <= aRadiusSQR )
476 return Standard_True;
477
478 return Standard_False;
479}
480
481//=======================================================================
482//function : AdjustByNeighbour
483//purpose : static subfunction in DecompositionOfWLine
484//=======================================================================
485static
486gp_Pnt2d AdjustByNeighbour(const gp_Pnt2d& theaNeighbourPoint,
487 const gp_Pnt2d& theOriginalPoint,
488 Handle(GeomAdaptor_HSurface) theGASurface)
489{
490 gp_Pnt2d ap1 = theaNeighbourPoint;
491 gp_Pnt2d ap2 = theOriginalPoint;
492
493 if ( theGASurface->IsUPeriodic() ) {
494 Standard_Real aPeriod = theGASurface->UPeriod();
495 gp_Pnt2d aPTest = ap2;
496 Standard_Real aSqDistMin = 1.e+100;
497
498 for ( Standard_Integer pIt = -1; pIt <= 1; pIt++) {
499 aPTest.SetX( theOriginalPoint.X() + aPeriod * pIt );
500 Standard_Real dd = ap1.SquareDistance( aPTest );
501
502 if ( dd < aSqDistMin ) {
503 ap2 = aPTest;
504 aSqDistMin = dd;
505 }
506 }
507 }
508 if ( theGASurface->IsVPeriodic() ) {
509 Standard_Real aPeriod = theGASurface->VPeriod();
510 gp_Pnt2d aPTest = ap2;
511 Standard_Real aSqDistMin = 1.e+100;
512
513 for ( Standard_Integer pIt = -1; pIt <= 1; pIt++) {
514 aPTest.SetY( theOriginalPoint.Y() + aPeriod * pIt );
515 Standard_Real dd = ap1.SquareDistance( aPTest );
516
517 if ( dd < aSqDistMin ) {
518 ap2 = aPTest;
519 aSqDistMin = dd;
520 }
521 }
522 }
523 return ap2;
524}
525
526//=======================================================================
527//function : RefineVector
528//purpose : static subfunction in FindPoint
529//=======================================================================
530static
531void RefineVector(gp_Vec2d& aV2D)
532{
533 Standard_Integer k,m;
534 Standard_Real aC[2], aEps, aR1, aR2, aNum;
535 //
536 aEps=RealEpsilon();
537 aR1=1.-aEps;
538 aR2=1.+aEps;
539 //
540 aV2D.Coord(aC[0], aC[1]);
541 //
542 for (k=0; k<2; ++k) {
543 m=(k+1)%2;
544 aNum=fabs(aC[k]);
545 if (aNum>aR1 && aNum<aR2) {
546 if (aC[k]<0.) {
547 aC[k]=-1.;
548 }
549 else {
550 aC[k]=1.;
551 }
552 aC[m]=0.;
553 break;
554 }
555 }
556 aV2D.SetCoord(aC[0], aC[1]);
557}
558
559//=======================================================================
560//function : FindPoint
561//purpose : static subfunction in DecompositionOfWLine
562//=======================================================================
563static
564Standard_Boolean FindPoint(const gp_Pnt2d& theFirstPoint,
565 const gp_Pnt2d& theLastPoint,
566 const Standard_Real theUmin,
567 const Standard_Real theUmax,
568 const Standard_Real theVmin,
569 const Standard_Real theVmax,
570 gp_Pnt2d& theNewPoint)
571{
572 gp_Vec2d aVec(theFirstPoint, theLastPoint);
573 Standard_Integer i = 0, j = 0;
574
575 for(i = 0; i < 4; i++) {
576 gp_Vec2d anOtherVec;
577 gp_Vec2d anOtherVecNormal;
578 gp_Pnt2d aprojpoint = theLastPoint;
579
580 if((i % 2) == 0) {
581 anOtherVec.SetX(0.);
582 anOtherVec.SetY(1.);
583 anOtherVecNormal.SetX(1.);
584 anOtherVecNormal.SetY(0.);
585
586 if(i < 2)
587 aprojpoint.SetX(theUmin);
588 else
589 aprojpoint.SetX(theUmax);
590 }
591 else {
592 anOtherVec.SetX(1.);
593 anOtherVec.SetY(0.);
594 anOtherVecNormal.SetX(0.);
595 anOtherVecNormal.SetY(1.);
596
597 if(i < 2)
598 aprojpoint.SetY(theVmin);
599 else
600 aprojpoint.SetY(theVmax);
601 }
602 gp_Vec2d anormvec = aVec;
603 anormvec.Normalize();
604 RefineVector(anormvec);
605 Standard_Real adot1 = anormvec.Dot(anOtherVecNormal);
606
607 if(fabs(adot1) < Precision::Angular())
608 continue;
609 Standard_Real adist = 0.;
610 Standard_Boolean bIsOut = Standard_False;
611
612 if((i % 2) == 0) {
613 adist = (i < 2) ? fabs(theLastPoint.X() - theUmin) : fabs(theLastPoint.X() - theUmax);
614 bIsOut = (i < 2) ? (theLastPoint.X() < theUmin) : (theLastPoint.X() > theUmax);
615 }
616 else {
617 adist = (i < 2) ? fabs(theLastPoint.Y() - theVmin) : fabs(theLastPoint.Y() - theVmax);
618 bIsOut = (i < 2) ? (theLastPoint.Y() < theVmin) : (theLastPoint.Y() > theVmax);
619 }
620 Standard_Real anoffset = adist * anOtherVec.Dot(anormvec) / adot1;
621
622 for(j = 0; j < 2; j++) {
623 anoffset = (j == 0) ? anoffset : -anoffset;
624 gp_Pnt2d acurpoint(aprojpoint.XY() + (anOtherVec.XY()*anoffset));
625 gp_Vec2d acurvec(theLastPoint, acurpoint);
626 if ( bIsOut )
627 acurvec.Reverse();
628
629 Standard_Real aDotX, anAngleX;
630 //
631 aDotX = aVec.Dot(acurvec);
632 anAngleX = aVec.Angle(acurvec);
633 //
634 if(aDotX > 0. && fabs(anAngleX) < Precision::PConfusion()) {
635 if((i % 2) == 0) {
636 if((acurpoint.Y() >= theVmin) &&
637 (acurpoint.Y() <= theVmax)) {
638 theNewPoint = acurpoint;
639 return Standard_True;
640 }
641 }
642 else {
643 if((acurpoint.X() >= theUmin) &&
644 (acurpoint.X() <= theUmax)) {
645 theNewPoint = acurpoint;
646 return Standard_True;
647 }
648 }
649 }
650 }
651 }
652 return Standard_False;
653}
654
655//=======================================================================
656//function : FindPoint
657//purpose : Find point on the boundary of radial tangent zone
658// static subfunction in DecompositionOfWLine
659//=======================================================================
660static
661Standard_Boolean FindPoint(const gp_Pnt2d& theFirstPoint,
662 const gp_Pnt2d& theLastPoint,
663 const Standard_Real theUmin,
664 const Standard_Real theUmax,
665 const Standard_Real theVmin,
666 const Standard_Real theVmax,
667 const gp_Pnt2d& theTanZoneCenter,
668 const Standard_Real theZoneRadius,
669 Handle(GeomAdaptor_HSurface) theGASurface,
670 gp_Pnt2d& theNewPoint) {
671 theNewPoint = theLastPoint;
672
673 if ( !IsInsideTanZone( theLastPoint, theTanZoneCenter, theZoneRadius, theGASurface) )
674 return Standard_False;
675
676 Standard_Real aUResolution = theGASurface->UResolution( theZoneRadius );
677 Standard_Real aVResolution = theGASurface->VResolution( theZoneRadius );
678
679 Standard_Real aRadius = ( aUResolution < aVResolution ) ? aUResolution : aVResolution;
680 gp_Ax22d anAxis( theTanZoneCenter, gp_Dir2d(1, 0), gp_Dir2d(0, 1) );
681 gp_Circ2d aCircle( anAxis, aRadius );
682
683 //
684 gp_Vec2d aDir( theLastPoint.XY() - theFirstPoint.XY() );
685 Standard_Real aLength = aDir.Magnitude();
686 if ( aLength <= gp::Resolution() )
687 return Standard_False;
688 gp_Lin2d aLine( theFirstPoint, aDir );
689
690 //
691 Handle(Geom2d_Line) aCLine = new Geom2d_Line( aLine );
692 Handle(Geom2d_TrimmedCurve) aC1 = new Geom2d_TrimmedCurve( aCLine, 0, aLength );
693 Handle(Geom2d_Circle) aC2 = new Geom2d_Circle( aCircle );
694
695 Standard_Real aTol = aRadius * 0.001;
696 aTol = ( aTol < Precision::PConfusion() ) ? Precision::PConfusion() : aTol;
697
698 Geom2dAPI_InterCurveCurve anIntersector;
699 anIntersector.Init( aC1, aC2, aTol );
700
701 if ( anIntersector.NbPoints() == 0 )
702 return Standard_False;
703
704 Standard_Boolean aFound = Standard_False;
705 Standard_Real aMinDist = aLength * aLength;
706 Standard_Integer i = 0;
707 for ( i = 1; i <= anIntersector.NbPoints(); i++ ) {
708 gp_Pnt2d aPInt = anIntersector.Point( i );
709 if ( aPInt.SquareDistance( theFirstPoint ) < aMinDist ) {
710 if ( ( aPInt.X() >= theUmin ) && ( aPInt.X() <= theUmax ) &&
711 ( aPInt.Y() >= theVmin ) && ( aPInt.Y() <= theVmax ) ) {
712 theNewPoint = aPInt;
713 aFound = Standard_True;
714 }
715 }
716 }
717
718 return aFound;
719}
720
721//=======================================================================
722//function : DecompositionOfWLine
723//purpose :
724//=======================================================================
725Standard_Boolean IntTools_WLineTool::
726 DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
727 const Handle(GeomAdaptor_HSurface)& theSurface1,
728 const Handle(GeomAdaptor_HSurface)& theSurface2,
729 const TopoDS_Face& theFace1,
730 const TopoDS_Face& theFace2,
731 const GeomInt_LineConstructor& theLConstructor,
732 const Standard_Boolean theAvoidLConstructor,
0d0481c7 733 const Standard_Real theTol,
d33a8cde 734 IntPatch_SequenceOfLine& theNewLines,
735 Standard_Real& theReachedTol3d,
736 const Handle(IntTools_Context)& aContext)
737{
d33a8cde 738 Standard_Boolean bRet, bAvoidLineConstructor;
739 Standard_Integer aNbPnts, aNbParts;
740 //
741 bRet=Standard_False;
742 aNbPnts=theWLine->NbPnts();
743 bAvoidLineConstructor=theAvoidLConstructor;
744 //
745 if(!aNbPnts){
746 return bRet;
747 }
748 if (!bAvoidLineConstructor) {
749 aNbParts=theLConstructor.NbParts();
750 if (!aNbParts) {
751 return bRet;
752 }
753 }
754 //
755 Standard_Boolean bIsPrevPointOnBoundary, bIsPointOnBoundary, bIsCurrentPointOnBoundary;
756 Standard_Integer nblines, pit, i, j;
757 Standard_Real aTol;
758 TColStd_Array1OfListOfInteger anArrayOfLines(1, aNbPnts);
759 TColStd_Array1OfInteger anArrayOfLineType(1, aNbPnts);
760 TColStd_ListOfInteger aListOfPointIndex;
761
762 Handle(TColgp_HArray1OfPnt2d) aTanZoneS1;
763 Handle(TColgp_HArray1OfPnt2d) aTanZoneS2;
764 Handle(TColStd_HArray1OfReal) aTanZoneRadius;
765 Standard_Integer aNbZone = ComputeTangentZones( theSurface1, theSurface2, theFace1, theFace2,
766 aTanZoneS1, aTanZoneS2, aTanZoneRadius, aContext);
767
768 //
769 nblines=0;
770 aTol=Precision::Confusion();
771 aTol=0.5*aTol;
772 bIsPrevPointOnBoundary=Standard_False;
773 bIsPointOnBoundary=Standard_False;
774 //
775 // 1. ...
776 //
777 // Points
778 for(pit = 1; pit <= aNbPnts; ++pit) {
779 Standard_Boolean bIsOnFirstBoundary, isperiodic;
780 Standard_Real aResolution, aPeriod, alowerboundary, aupperboundary, U, V;
781 Standard_Real aParameter, anoffset, anAdjustPar;
782 Standard_Real umin, umax, vmin, vmax;
783 //
784 bIsCurrentPointOnBoundary = Standard_False;
785 const IntSurf_PntOn2S& aPoint = theWLine->Point(pit);
786 //
787 // Surface
788 for(i = 0; i < 2; ++i) {
789 Handle(GeomAdaptor_HSurface) aGASurface = (!i) ? theSurface1 : theSurface2;
790 aGASurface->ChangeSurface().Surface()->Bounds(umin, umax, vmin, vmax);
791 if(!i) {
792 aPoint.ParametersOnS1(U, V);
793 }
794 else {
795 aPoint.ParametersOnS2(U, V);
796 }
797 // U, V
798 for(j = 0; j < 2; j++) {
799 isperiodic = (!j) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
800 if(!isperiodic){
801 continue;
802 }
803 //
804 if (!j) {
805 aResolution=aGASurface->UResolution(aTol);
806 aPeriod=aGASurface->UPeriod();
807 alowerboundary=umin;
808 aupperboundary=umax;
809 aParameter=U;
810 }
811 else {
812 aResolution=aGASurface->VResolution(aTol);
813 aPeriod=aGASurface->VPeriod();
814 alowerboundary=vmin;
815 aupperboundary=vmax;
816 aParameter=V;
817 }
818
819 GeomInt::AdjustPeriodic(aParameter,
820 alowerboundary,
821 aupperboundary,
822 aPeriod,
823 anAdjustPar,
824 anoffset);
825 //
826 bIsOnFirstBoundary = Standard_True;// ?
827 bIsPointOnBoundary=
828 IsPointOnBoundary(anAdjustPar,
829 alowerboundary,
830 aupperboundary,
831 aResolution,
832 bIsOnFirstBoundary);
833 //
834 if(bIsPointOnBoundary) {
835 bIsCurrentPointOnBoundary = Standard_True;
836 break;
837 }
838 else {
839 // check if a point belong to a tangent zone. Begin
840 Standard_Integer zIt = 0;
841 for ( zIt = 1; zIt <= aNbZone; zIt++ ) {
842 gp_Pnt2d aPZone = (i == 0) ? aTanZoneS1->Value(zIt) : aTanZoneS2->Value(zIt);
843 Standard_Real aZoneRadius = aTanZoneRadius->Value(zIt);
844
845 if ( IsInsideTanZone(gp_Pnt2d( U, V ), aPZone, aZoneRadius, aGASurface ) ) {
846 // set boundary flag to split the curve by a tangent zone
847 bIsPointOnBoundary = Standard_True;
848 bIsCurrentPointOnBoundary = Standard_True;
849 if ( theReachedTol3d < aZoneRadius ) {
850 theReachedTol3d = aZoneRadius;
851 }
852 break;
853 }
854 }
855 }
856 }//for(j = 0; j < 2; j++) {
857
858 if(bIsCurrentPointOnBoundary){
859 break;
860 }
861 }//for(i = 0; i < 2; ++i) {
862 //
863 if((bIsCurrentPointOnBoundary != bIsPrevPointOnBoundary)) {
864 if(!aListOfPointIndex.IsEmpty()) {
865 nblines++;
866 anArrayOfLines.SetValue(nblines, aListOfPointIndex);
867 anArrayOfLineType.SetValue(nblines, bIsPrevPointOnBoundary);
868 aListOfPointIndex.Clear();
869 }
870 bIsPrevPointOnBoundary = bIsCurrentPointOnBoundary;
871 }
872 aListOfPointIndex.Append(pit);
873 } //for(pit = 1; pit <= aNbPnts; ++pit) {
874 //
875 if(!aListOfPointIndex.IsEmpty()) {
876 nblines++;
877 anArrayOfLines.SetValue(nblines, aListOfPointIndex);
878 anArrayOfLineType.SetValue(nblines, bIsPrevPointOnBoundary);
879 aListOfPointIndex.Clear();
880 }
881 //
882 if(nblines<=1) {
883 return bRet; //Standard_False;
884 }
885 //
886 //
887 // 2. Correct wlines.begin
888 TColStd_Array1OfListOfInteger anArrayOfLineEnds(1, nblines);
889 Handle(IntSurf_LineOn2S) aSeqOfPntOn2S = new IntSurf_LineOn2S();
890 //
891 for(i = 1; i <= nblines; i++) {
892 if(anArrayOfLineType.Value(i) != 0) {
893 continue;
894 }
895 const TColStd_ListOfInteger& aListOfIndex = anArrayOfLines.Value(i);
896 TColStd_ListOfInteger aListOfFLIndex;
897
898 for(j = 0; j < 2; j++) {
899 Standard_Integer aneighbourindex = (j == 0) ? (i - 1) : (i + 1);
900
901 if((aneighbourindex < 1) || (aneighbourindex > nblines))
902 continue;
903
904 if(anArrayOfLineType.Value(aneighbourindex) == 0)
905 continue;
906 const TColStd_ListOfInteger& aNeighbour = anArrayOfLines.Value(aneighbourindex);
907 Standard_Integer anIndex = (j == 0) ? aNeighbour.Last() : aNeighbour.First();
908 const IntSurf_PntOn2S& aPoint = theWLine->Point(anIndex);
909
910 IntSurf_PntOn2S aNewP = aPoint;
911 if(aListOfIndex.Extent() < 2) {
912 aSeqOfPntOn2S->Add(aNewP);
913 aListOfFLIndex.Append(aSeqOfPntOn2S->NbPoints());
914 continue;
915 }
916 //
917 Standard_Integer iFirst = aListOfIndex.First();
918 Standard_Integer iLast = aListOfIndex.Last();
919 //
920 for(Standard_Integer surfit = 0; surfit < 2; surfit++) {
921
922 Handle(GeomAdaptor_HSurface) aGASurface = (surfit == 0) ? theSurface1 : theSurface2;
923 Standard_Real umin=0., umax=0., vmin=0., vmax=0.;
924 aGASurface->ChangeSurface().Surface()->Bounds(umin, umax, vmin, vmax);
925 Standard_Real U=0., V=0.;
926
927 if(surfit == 0)
928 aNewP.ParametersOnS1(U, V);
929 else
930 aNewP.ParametersOnS2(U, V);
931 Standard_Integer nbboundaries = 0;
932
933 Standard_Boolean bIsNearBoundary = Standard_False;
934 Standard_Integer aZoneIndex = 0;
935 Standard_Integer bIsUBoundary = Standard_False; // use if nbboundaries == 1
936 Standard_Integer bIsFirstBoundary = Standard_False; // use if nbboundaries == 1
937
938
939 for(Standard_Integer parit = 0; parit < 2; parit++) {
940 Standard_Boolean isperiodic = (parit == 0) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
941
942 Standard_Real aResolution = (parit == 0) ? aGASurface->UResolution(aTol) : aGASurface->VResolution(aTol);
943 Standard_Real alowerboundary = (parit == 0) ? umin : vmin;
944 Standard_Real aupperboundary = (parit == 0) ? umax : vmax;
945
946 Standard_Real aParameter = (parit == 0) ? U : V;
947 Standard_Boolean bIsOnFirstBoundary = Standard_True;
948
949 if(!isperiodic) {
950 bIsPointOnBoundary=
951 IsPointOnBoundary(aParameter, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary);
952 if(bIsPointOnBoundary) {
953 bIsUBoundary = (parit == 0);
954 bIsFirstBoundary = bIsOnFirstBoundary;
955 nbboundaries++;
956 }
957 }
958 else {
959 Standard_Real aPeriod = (parit == 0) ? aGASurface->UPeriod() : aGASurface->VPeriod();
960 Standard_Real anoffset, anAdjustPar;
961 GeomInt::AdjustPeriodic(aParameter, alowerboundary, aupperboundary,
962 aPeriod, anAdjustPar, anoffset);
963
964 bIsPointOnBoundary=
965 IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary);
966 if(bIsPointOnBoundary) {
967 bIsUBoundary = (parit == 0);
968 bIsFirstBoundary = bIsOnFirstBoundary;
969 nbboundaries++;
970 }
971 else {
972 //check neighbourhood of boundary
973 Standard_Real anEpsilon = aResolution * 100.;
974 Standard_Real aPart = ( aupperboundary - alowerboundary ) * 0.1;
975 anEpsilon = ( anEpsilon > aPart ) ? aPart : anEpsilon;
976
977 bIsNearBoundary = IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary,
978 anEpsilon, bIsOnFirstBoundary);
979
980 }
981 }
982 }
983
984 // check if a point belong to a tangent zone. Begin
985 for ( Standard_Integer zIt = 1; zIt <= aNbZone; zIt++ ) {
986 gp_Pnt2d aPZone = (surfit == 0) ? aTanZoneS1->Value(zIt) : aTanZoneS2->Value(zIt);
987 Standard_Real aZoneRadius = aTanZoneRadius->Value(zIt);
988
989 Standard_Integer aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
990 const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
991 Standard_Real nU1, nV1;
992
993 if(surfit == 0)
994 aNeighbourPoint.ParametersOnS1(nU1, nV1);
995 else
996 aNeighbourPoint.ParametersOnS2(nU1, nV1);
997 gp_Pnt2d ap1(nU1, nV1);
998 gp_Pnt2d ap2 = AdjustByNeighbour( ap1, gp_Pnt2d( U, V ), aGASurface );
999
1000
1001 if ( IsInsideTanZone( ap2, aPZone, aZoneRadius, aGASurface ) ) {
1002 aZoneIndex = zIt;
1003 bIsNearBoundary = Standard_True;
1004 if ( theReachedTol3d < aZoneRadius ) {
1005 theReachedTol3d = aZoneRadius;
1006 }
1007 }
1008 }
1009 // check if a point belong to a tangent zone. End
1010 Standard_Boolean bComputeLineEnd = Standard_False;
1011
1012 if(nbboundaries == 2) {
1013 //xf
1014 bComputeLineEnd = Standard_True;
1015 //xt
1016 }
1017 else if(nbboundaries == 1) {
1018 Standard_Boolean isperiodic = (bIsUBoundary) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
1019
1020 if(isperiodic) {
1021 Standard_Real alowerboundary = (bIsUBoundary) ? umin : vmin;
1022 Standard_Real aupperboundary = (bIsUBoundary) ? umax : vmax;
1023 Standard_Real aPeriod = (bIsUBoundary) ? aGASurface->UPeriod() : aGASurface->VPeriod();
1024 Standard_Real aParameter = (bIsUBoundary) ? U : V;
1025 Standard_Real anoffset, anAdjustPar;
1026 GeomInt::AdjustPeriodic(aParameter, alowerboundary, aupperboundary,
1027 aPeriod, anAdjustPar, anoffset);
1028
1029 Standard_Real adist = (bIsFirstBoundary) ? fabs(anAdjustPar - alowerboundary) : fabs(anAdjustPar - aupperboundary);
1030 Standard_Real anotherPar = (bIsFirstBoundary) ? (aupperboundary - adist) : (alowerboundary + adist);
1031 anotherPar += anoffset;
1032 Standard_Integer aneighbourpointindex = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
1033 const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex);
1034 Standard_Real nU1, nV1;
1035
1036 if(surfit == 0)
1037 aNeighbourPoint.ParametersOnS1(nU1, nV1);
1038 else
1039 aNeighbourPoint.ParametersOnS2(nU1, nV1);
1040
1041 Standard_Real adist1 = (bIsUBoundary) ? fabs(nU1 - U) : fabs(nV1 - V);
1042 Standard_Real adist2 = (bIsUBoundary) ? fabs(nU1 - anotherPar) : fabs(nV1 - anotherPar);
1043 bComputeLineEnd = Standard_True;
1044 Standard_Boolean bCheckAngle1 = Standard_False;
1045 Standard_Boolean bCheckAngle2 = Standard_False;
1046 gp_Vec2d aNewVec;
1047 Standard_Real anewU = (bIsUBoundary) ? anotherPar : U;
1048 Standard_Real anewV = (bIsUBoundary) ? V : anotherPar;
1049
1050 if(((adist1 - adist2) > Precision::PConfusion()) &&
1051 (adist2 < (aPeriod / 4.))) {
1052 bCheckAngle1 = Standard_True;
1053 aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(anewU, anewV));
1054
1055 if(aNewVec.SquareMagnitude() < gp::Resolution()) {
1056 aNewP.SetValue((surfit == 0), anewU, anewV);
1057 bCheckAngle1 = Standard_False;
1058 }
1059 }
1060 else if(adist1 < (aPeriod / 4.)) {
1061 bCheckAngle2 = Standard_True;
1062 aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(U, V));
1063
1064 if(aNewVec.SquareMagnitude() < gp::Resolution()) {
1065 bCheckAngle2 = Standard_False;
1066 }
1067 }
1068
1069 if(bCheckAngle1 || bCheckAngle2) {
1070 // assume there are at least two points in line (see "if" above)
1071 Standard_Integer anindexother = aneighbourpointindex;
1072
1073 while((anindexother <= iLast) && (anindexother >= iFirst)) {
1074 anindexother = (j == 0) ? (anindexother + 1) : (anindexother - 1);
1075 const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(anindexother);
1076 Standard_Real nU2, nV2;
1077
1078 if(surfit == 0)
1079 aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
1080 else
1081 aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
1082 gp_Vec2d aVecOld(gp_Pnt2d(nU2, nV2), gp_Pnt2d(nU1, nV1));
1083
1084 if(aVecOld.SquareMagnitude() <= gp::Resolution()) {
1085 continue;
1086 }
1087 else {
1088 Standard_Real anAngle = aNewVec.Angle(aVecOld);
1089
1090 if((fabs(anAngle) < (M_PI * 0.25)) && (aNewVec.Dot(aVecOld) > 0.)) {
1091
1092 if(bCheckAngle1) {
1093 Standard_Real U1, U2, V1, V2;
1094 IntSurf_PntOn2S atmppoint = aNewP;
1095 atmppoint.SetValue((surfit == 0), anewU, anewV);
1096 atmppoint.Parameters(U1, V1, U2, V2);
1097 gp_Pnt P1 = theSurface1->Value(U1, V1);
1098 gp_Pnt P2 = theSurface2->Value(U2, V2);
1099 gp_Pnt P0 = aPoint.Value();
1100
1101 if(P0.IsEqual(P1, aTol) &&
1102 P0.IsEqual(P2, aTol) &&
1103 P1.IsEqual(P2, aTol)) {
1104 bComputeLineEnd = Standard_False;
1105 aNewP.SetValue((surfit == 0), anewU, anewV);
1106 }
1107 }
1108
1109 if(bCheckAngle2) {
1110 bComputeLineEnd = Standard_False;
1111 }
1112 }
1113 break;
1114 }
1115 } // end while(anindexother...)
1116 }
1117 }
1118 }
1119 else if ( bIsNearBoundary ) {
1120 bComputeLineEnd = Standard_True;
1121 }
1122
1123 if(bComputeLineEnd) {
1124
1125 gp_Pnt2d anewpoint;
1126 Standard_Boolean found = Standard_False;
1127
1128 if ( bIsNearBoundary ) {
1129 // re-compute point near natural boundary or near tangent zone
1130 Standard_Real u1, v1, u2, v2;
1131 aNewP.Parameters( u1, v1, u2, v2 );
1132 if(surfit == 0)
1133 anewpoint = gp_Pnt2d( u1, v1 );
1134 else
1135 anewpoint = gp_Pnt2d( u2, v2 );
1136
1137 Standard_Integer aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
1138 const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
1139 Standard_Real nU1, nV1;
1140
1141 if(surfit == 0)
1142 aNeighbourPoint.ParametersOnS1(nU1, nV1);
1143 else
1144 aNeighbourPoint.ParametersOnS2(nU1, nV1);
1145 gp_Pnt2d ap1(nU1, nV1);
1146 gp_Pnt2d ap2;
1147
1148
1149 if ( aZoneIndex ) {
1150 // exclude point from a tangent zone
1151 anewpoint = AdjustByNeighbour( ap1, anewpoint, aGASurface );
1152 gp_Pnt2d aPZone = (surfit == 0) ? aTanZoneS1->Value(aZoneIndex) : aTanZoneS2->Value(aZoneIndex);
1153 Standard_Real aZoneRadius = aTanZoneRadius->Value(aZoneIndex);
1154
1155 if ( FindPoint(ap1, anewpoint, umin, umax, vmin, vmax,
1156 aPZone, aZoneRadius, aGASurface, ap2) ) {
1157 anewpoint = ap2;
1158 found = Standard_True;
1159 }
1160 }
1161 else if ( aGASurface->IsUPeriodic() || aGASurface->IsVPeriodic() ) {
1162 // re-compute point near boundary if shifted on a period
1163 ap2 = AdjustByNeighbour( ap1, anewpoint, aGASurface );
1164
1165 if ( ( ap2.X() < umin ) || ( ap2.X() > umax ) ||
1166 ( ap2.Y() < vmin ) || ( ap2.Y() > vmax ) ) {
1167 found = FindPoint(ap1, ap2, umin, umax, vmin, vmax, anewpoint);
1168 }
1169 else {
1170 anewpoint = ap2;
1171 aNewP.SetValue( (surfit == 0), anewpoint.X(), anewpoint.Y() );
1172 }
1173 }
1174 }
1175 else {
1176
1177 Standard_Integer aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
1178 const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
1179 Standard_Real nU1, nV1;
1180
1181 if(surfit == 0)
1182 aNeighbourPoint.ParametersOnS1(nU1, nV1);
1183 else
1184 aNeighbourPoint.ParametersOnS2(nU1, nV1);
1185 gp_Pnt2d ap1(nU1, nV1);
1186 gp_Pnt2d ap2(nU1, nV1);
1187 Standard_Integer aneighbourpointindex2 = aneighbourpointindex1;
1188
1189 while((aneighbourpointindex2 <= iLast) && (aneighbourpointindex2 >= iFirst)) {
1190 aneighbourpointindex2 = (j == 0) ? (aneighbourpointindex2 + 1) : (aneighbourpointindex2 - 1);
1191 const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(aneighbourpointindex2);
1192 Standard_Real nU2, nV2;
1193
1194 if(surfit == 0)
1195 aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
1196 else
1197 aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
1198 ap2.SetX(nU2);
1199 ap2.SetY(nV2);
1200
1201 if(ap1.SquareDistance(ap2) > gp::Resolution()) {
1202 break;
1203 }
1204 }
1205 found = FindPoint(ap2, ap1, umin, umax, vmin, vmax, anewpoint);
1206 }
1207
1208 if(found) {
1209 // check point
0d0481c7 1210 Standard_Real aCriteria = theTol;
d33a8cde 1211 GeomAPI_ProjectPointOnSurf& aProjector =
1212 (surfit == 0) ? aContext->ProjPS(theFace2) : aContext->ProjPS(theFace1);
1213 Handle(GeomAdaptor_HSurface) aSurface = (surfit == 0) ? theSurface1 : theSurface2;
1214
1215 Handle(GeomAdaptor_HSurface) aSurfaceOther = (surfit == 0) ? theSurface2 : theSurface1;
1216
1217 gp_Pnt aP3d = aSurface->Value(anewpoint.X(), anewpoint.Y());
1218 aProjector.Perform(aP3d);
1219
1220 if(aProjector.IsDone()) {
1221 if(aProjector.LowerDistance() < aCriteria) {
1222 Standard_Real foundU = U, foundV = V;
1223 aProjector.LowerDistanceParameters(foundU, foundV);
1224
1225 //Correction of projected coordinates. Begin
1226 //Note, it may be shifted on a period
1227 Standard_Integer aneindex1 = (j == 0) ? iFirst : iLast;
1228 const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneindex1);
1229 Standard_Real nUn, nVn;
1230
1231 if(surfit == 0)
1232 aNeighbourPoint.ParametersOnS2(nUn, nVn);
1233 else
1234 aNeighbourPoint.ParametersOnS1(nUn, nVn);
1235 gp_Pnt2d aNeighbour2d(nUn, nVn);
1236 gp_Pnt2d anAdjustedPoint = AdjustByNeighbour( aNeighbour2d, gp_Pnt2d(foundU, foundV), aSurfaceOther );
1237 foundU = anAdjustedPoint.X();
1238 foundV = anAdjustedPoint.Y();
1239
1240 if ( ( anAdjustedPoint.X() < umin ) && ( anAdjustedPoint.X() > umax ) &&
1241 ( anAdjustedPoint.Y() < vmin ) && ( anAdjustedPoint.Y() > vmax ) ) {
1242 // attempt to roughly re-compute point
1243 foundU = ( foundU < umin ) ? umin : foundU;
1244 foundU = ( foundU > umax ) ? umax : foundU;
1245 foundV = ( foundV < vmin ) ? vmin : foundV;
1246 foundV = ( foundV > vmax ) ? vmax : foundV;
1247
1248 GeomAPI_ProjectPointOnSurf& aProjector2 =
1249 (surfit == 0) ? aContext->ProjPS(theFace1) : aContext->ProjPS(theFace2);
1250
1251 aP3d = aSurfaceOther->Value(foundU, foundV);
1252 aProjector2.Perform(aP3d);
1253
1254 if(aProjector2.IsDone()) {
1255 if(aProjector2.LowerDistance() < aCriteria) {
1256 Standard_Real foundU2 = anewpoint.X(), foundV2 = anewpoint.Y();
1257 aProjector2.LowerDistanceParameters(foundU2, foundV2);
1258 anewpoint.SetX(foundU2);
1259 anewpoint.SetY(foundV2);
1260 }
1261 }
1262 }
1263 //Correction of projected coordinates. End
1264
1265 if(surfit == 0)
1266 aNewP.SetValue(aP3d, anewpoint.X(), anewpoint.Y(), foundU, foundV);
1267 else
1268 aNewP.SetValue(aP3d, foundU, foundV, anewpoint.X(), anewpoint.Y());
1269 }
1270 }
1271 }
1272 }
1273 }
1274 aSeqOfPntOn2S->Add(aNewP);
1275 aListOfFLIndex.Append(aSeqOfPntOn2S->NbPoints());
1276 }
1277 anArrayOfLineEnds.SetValue(i, aListOfFLIndex);
1278 }
1279 // Correct wlines.end
1280
1281 // Split wlines.begin
1282 Standard_Integer nbiter;
1283 //
1284 nbiter=1;
1285 if (!bAvoidLineConstructor) {
1286 nbiter=theLConstructor.NbParts();
1287 }
1288 //
1289 for(j = 1; j <= nbiter; ++j) {
1290 Standard_Real fprm, lprm;
1291 Standard_Integer ifprm, ilprm;
1292 //
1293 if(bAvoidLineConstructor) {
1294 ifprm = 1;
1295 ilprm = theWLine->NbPnts();
1296 }
1297 else {
1298 theLConstructor.Part(j, fprm, lprm);
1299 ifprm = (Standard_Integer)fprm;
1300 ilprm = (Standard_Integer)lprm;
1301 }
1302
1303 Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
1304 //
1305 for(i = 1; i <= nblines; i++) {
1306 if(anArrayOfLineType.Value(i) != 0) {
1307 continue;
1308 }
1309 const TColStd_ListOfInteger& aListOfIndex = anArrayOfLines.Value(i);
1310 const TColStd_ListOfInteger& aListOfFLIndex = anArrayOfLineEnds.Value(i);
1311 Standard_Boolean bhasfirstpoint = (aListOfFLIndex.Extent() == 2);
1312 Standard_Boolean bhaslastpoint = (aListOfFLIndex.Extent() == 2);
1313
1314 if(!bhasfirstpoint && !aListOfFLIndex.IsEmpty()) {
1315 bhasfirstpoint = (i != 1);
1316 }
1317
1318 if(!bhaslastpoint && !aListOfFLIndex.IsEmpty()) {
1319 bhaslastpoint = (i != nblines);
1320 }
1321
1322 Standard_Integer iFirst = aListOfIndex.First();
1323 Standard_Integer iLast = aListOfIndex.Last();
1324 Standard_Boolean bIsFirstInside = ((ifprm >= iFirst) && (ifprm <= iLast));
1325 Standard_Boolean bIsLastInside = ((ilprm >= iFirst) && (ilprm <= iLast));
1326
1327 if(!bIsFirstInside && !bIsLastInside) {
1328 if((ifprm < iFirst) && (ilprm > iLast)) {
1329 // append whole line, and boundaries if neccesary
1330 if(bhasfirstpoint) {
1331 pit = aListOfFLIndex.First();
1332 const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
1333 aLineOn2S->Add(aP);
1334 }
1335 TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
1336
1337 for(; anIt.More(); anIt.Next()) {
1338 pit = anIt.Value();
1339 const IntSurf_PntOn2S& aP = theWLine->Point(pit);
1340 aLineOn2S->Add(aP);
1341 }
1342
1343 if(bhaslastpoint) {
1344 pit = aListOfFLIndex.Last();
1345 const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
1346 aLineOn2S->Add(aP);
1347 }
1348
1349 // check end of split line (end is almost always)
1350 Standard_Integer aneighbour = i + 1;
1351 Standard_Boolean bIsEndOfLine = Standard_True;
1352
1353 if(aneighbour <= nblines) {
1354 const TColStd_ListOfInteger& aListOfNeighbourIndex = anArrayOfLines.Value(aneighbour);
1355
1356 if((anArrayOfLineType.Value(aneighbour) != 0) &&
1357 (aListOfNeighbourIndex.IsEmpty())) {
1358 bIsEndOfLine = Standard_False;
1359 }
1360 }
1361
1362 if(bIsEndOfLine) {
1363 if(aLineOn2S->NbPoints() > 1) {
1364 Handle(IntPatch_WLine) aNewWLine =
1365 new IntPatch_WLine(aLineOn2S, Standard_False);
98974dcc 1366 aNewWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
d33a8cde 1367 theNewLines.Append(aNewWLine);
1368 }
1369 aLineOn2S = new IntSurf_LineOn2S();
1370 }
1371 }
1372 continue;
1373 }
1374 // end if(!bIsFirstInside && !bIsLastInside)
1375
1376 if(bIsFirstInside && bIsLastInside) {
1377 // append inside points between ifprm and ilprm
1378 TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
1379
1380 for(; anIt.More(); anIt.Next()) {
1381 pit = anIt.Value();
1382 if((pit < ifprm) || (pit > ilprm))
1383 continue;
1384 const IntSurf_PntOn2S& aP = theWLine->Point(pit);
1385 aLineOn2S->Add(aP);
1386 }
1387 }
1388 else {
1389
1390 if(bIsFirstInside) {
1391 // append points from ifprm to last point + boundary point
1392 TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
1393
1394 for(; anIt.More(); anIt.Next()) {
1395 pit = anIt.Value();
1396 if(pit < ifprm)
1397 continue;
1398 const IntSurf_PntOn2S& aP = theWLine->Point(pit);
1399 aLineOn2S->Add(aP);
1400 }
1401
1402 if(bhaslastpoint) {
1403 pit = aListOfFLIndex.Last();
1404 const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
1405 aLineOn2S->Add(aP);
1406 }
1407 // check end of split line (end is almost always)
1408 Standard_Integer aneighbour = i + 1;
1409 Standard_Boolean bIsEndOfLine = Standard_True;
1410
1411 if(aneighbour <= nblines) {
1412 const TColStd_ListOfInteger& aListOfNeighbourIndex = anArrayOfLines.Value(aneighbour);
1413
1414 if((anArrayOfLineType.Value(aneighbour) != 0) &&
1415 (aListOfNeighbourIndex.IsEmpty())) {
1416 bIsEndOfLine = Standard_False;
1417 }
1418 }
1419
1420 if(bIsEndOfLine) {
1421 if(aLineOn2S->NbPoints() > 1) {
1422 Handle(IntPatch_WLine) aNewWLine =
1423 new IntPatch_WLine(aLineOn2S, Standard_False);
98974dcc 1424 aNewWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
d33a8cde 1425 theNewLines.Append(aNewWLine);
1426 }
1427 aLineOn2S = new IntSurf_LineOn2S();
1428 }
1429 }
1430 // end if(bIsFirstInside)
1431
1432 if(bIsLastInside) {
1433 // append points from first boundary point to ilprm
1434 if(bhasfirstpoint) {
1435 pit = aListOfFLIndex.First();
1436 const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
1437 aLineOn2S->Add(aP);
1438 }
1439 TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
1440
1441 for(; anIt.More(); anIt.Next()) {
1442 pit = anIt.Value();
1443 if(pit > ilprm)
1444 continue;
1445 const IntSurf_PntOn2S& aP = theWLine->Point(pit);
1446 aLineOn2S->Add(aP);
1447 }
1448 }
1449 //end if(bIsLastInside)
1450 }
1451 }
1452
1453 if(aLineOn2S->NbPoints() > 1) {
1454 Handle(IntPatch_WLine) aNewWLine =
1455 new IntPatch_WLine(aLineOn2S, Standard_False);
98974dcc 1456 aNewWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
d33a8cde 1457 theNewLines.Append(aNewWLine);
1458 }
1459 }
1460 // Split wlines.end
1461
1462 return Standard_True;
1463}
1464
4e14c88f 1465///////////////////// end of DecompositionOfWLine ///////////////////////