1 // Created on: 1992-10-13
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and / or modify it
9 // under the terms of the GNU Lesser General Public version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // Modified by skv - Tue Mar 1 14:22:09 2005 OCC8169
21 #define No_Standard_RangeError
22 #define No_Standard_OutOfRange
26 #include <Standard_ConstructionError.hxx>
28 #include <IntRes2d_Domain.hxx>
29 #include <IntRes2d_Position.hxx>
30 #include <IntRes2d_Transition.hxx>
31 #include <IntRes2d_IntersectionPoint.hxx>
32 #include <IntRes2d_IntersectionSegment.hxx>
35 #include <IntImpParGen.hxx>
37 #include <Intf_SectionPoint.hxx>
38 #include <Intf_SectionLine.hxx>
39 #include <Intf_TangentZone.hxx>
40 #include <Intf_InterferencePolygon2d.hxx>
42 #include <gp_Vec2d.hxx>
44 #include <math_Vector.hxx>
45 #include <math_FunctionSetRoot.hxx>
46 #include <math_NewtonFunctionSetRoot.hxx>
47 #include <NCollection_Handle.hxx>
49 //======================================================================
51 // Modified by skv - Tue Mar 1 14:22:09 2005 OCC8169 Begin
52 // #define NBITER_MAX_POLYGON 3
53 #define NBITER_MAX_POLYGON 10
54 // Modified by skv - Tue Mar 1 14:22:09 2005 OCC8169 End
55 #define TOL_CONF_MINI 0.0000000001
56 #define TOL_MINI 0.0000000001
58 //----------------------------------------------------------------------
64 Standard_Boolean HeadOrEndPoint( const IntRes2d_Domain& D1
66 ,const Standard_Real u
67 ,const IntRes2d_Domain& D2
69 ,const Standard_Real v
70 ,const Standard_Real TolConf
71 ,IntRes2d_IntersectionPoint& IntPt
72 ,Standard_Boolean& HeadOn1
73 ,Standard_Boolean& HeadOn2
74 ,Standard_Boolean& EndOn1
75 ,Standard_Boolean& EndOn2
76 ,Standard_Integer PosSegment);
79 //======================================================================
80 IntCurve_IntPolyPolyGen::IntCurve_IntPolyPolyGen(void) {
81 done = Standard_False;
83 //======================================================================
84 void IntCurve_IntPolyPolyGen::Perform( const TheCurve& C1
85 ,const IntRes2d_Domain& D1
87 ,const IntRes2d_Domain& D2
88 ,const Standard_Real TheTolConf
89 ,const Standard_Real TheTol)
94 Standard_Real DU = D1.LastParameter()-D1.FirstParameter();
95 Standard_Real DV = D2.LastParameter()-D2.FirstParameter();
96 Standard_Real Tl=(TheTol < TOL_MINI)? TOL_MINI : TheTol;
97 Standard_Real TlConf=(TheTolConf < TOL_CONF_MINI)? TOL_CONF_MINI : TheTolConf;
98 Perform(C1,D1,C2,D2,TlConf,Tl,0,DU,DV);
99 //----------------------------------------------------------------------
100 //-- Traitement des points en bouts
101 //----------------------------------------------------------------------
102 Standard_Boolean HeadOn1 = Standard_False;
103 Standard_Boolean HeadOn2 = Standard_False;
104 Standard_Boolean EndOn1 = Standard_False;
105 Standard_Boolean EndOn2 = Standard_False;
107 Standard_Integer n=this->NbPoints();
110 //--------------------------------------------------------------------
111 //-- On ne rejette les points Head Head ... End End
112 //-- si ils figurent deja dans un bout de segment
113 //-- ( On ne peut pas tester les egalites sur les parametres)
114 //-- ( ces points n etant pas trouves a EpsX pres )
115 //-- PosSegment = 1 si Head Head
119 //--------------------------------------------------------------------
120 Standard_Integer PosSegment = 0;
123 IntRes2d_Position Pos1 = this->Point(i).TransitionOfFirst().PositionOnCurve();
124 if(Pos1 == IntRes2d_Head) HeadOn1 = Standard_True;
125 else if(Pos1 == IntRes2d_End) EndOn1 = Standard_True;
127 IntRes2d_Position Pos2 = this->Point(i).TransitionOfSecond().PositionOnCurve();
128 if(Pos2 == IntRes2d_Head) HeadOn2 = Standard_True;
129 else if(Pos2 == IntRes2d_End) EndOn2 = Standard_True;
131 if(Pos1 == IntRes2d_Head) {
132 if(Pos2 == IntRes2d_Head) PosSegment|=1;
133 else if(Pos2 == IntRes2d_End) PosSegment|=2;
135 else if(Pos1 == IntRes2d_End) {
136 if(Pos2 == IntRes2d_Head) PosSegment|=4;
137 else if(Pos2 == IntRes2d_End) PosSegment|=8;
141 n=this->NbSegments();
143 IntRes2d_Position Pos1 = this->Segment(i).FirstPoint().TransitionOfFirst().PositionOnCurve();
144 if(Pos1 == IntRes2d_Head) HeadOn1 = Standard_True;
145 else if(Pos1 == IntRes2d_End) EndOn1 = Standard_True;
147 IntRes2d_Position Pos2 = this->Segment(i).FirstPoint().TransitionOfSecond().PositionOnCurve();
148 if(Pos2 == IntRes2d_Head) HeadOn2 = Standard_True;
149 else if(Pos2 == IntRes2d_End) EndOn2 = Standard_True;
151 if(Pos1 == IntRes2d_Head) {
152 if(Pos2 == IntRes2d_Head) PosSegment|=1;
153 else if(Pos2 == IntRes2d_End) PosSegment|=2;
155 else if(Pos1 == IntRes2d_End) {
156 if(Pos2 == IntRes2d_Head) PosSegment|=4;
157 else if(Pos2 == IntRes2d_End) PosSegment|=8;
160 Pos1 = this->Segment(i).LastPoint().TransitionOfFirst().PositionOnCurve();
161 if(Pos1 == IntRes2d_Head) HeadOn1 = Standard_True;
162 else if(Pos1 == IntRes2d_End) EndOn1 = Standard_True;
164 Pos2 = this->Segment(i).LastPoint().TransitionOfSecond().PositionOnCurve();
165 if(Pos2 == IntRes2d_Head) HeadOn2 = Standard_True;
166 else if(Pos2 == IntRes2d_End) EndOn2 = Standard_True;
168 if(Pos1 == IntRes2d_Head) {
169 if(Pos2 == IntRes2d_Head) PosSegment|=1;
170 else if(Pos2 == IntRes2d_End) PosSegment|=2;
172 else if(Pos1 == IntRes2d_End) {
173 if(Pos2 == IntRes2d_Head) PosSegment|=4;
174 else if(Pos2 == IntRes2d_End) PosSegment|=8;
178 Standard_Real U0 = D1.FirstParameter();
179 Standard_Real U1 = D1.LastParameter();
180 Standard_Real V0 = D2.FirstParameter();
181 Standard_Real V1 = D2.LastParameter();
182 IntRes2d_IntersectionPoint IntPt;
184 if(D1.FirstTolerance() || D2.FirstTolerance()) {
185 if(HeadOrEndPoint(D1,C1,U0,D2,C2,V0,TheTolConf,IntPt,HeadOn1,HeadOn2,EndOn1,EndOn2,PosSegment))
188 if(D1.FirstTolerance() || D2.LastTolerance()) {
189 if(HeadOrEndPoint(D1,C1,U0,D2,C2,V1,TheTolConf,IntPt,HeadOn1,HeadOn2,EndOn1,EndOn2,PosSegment))
192 if(D1.LastTolerance() || D2.FirstTolerance()) {
193 if(HeadOrEndPoint(D1,C1,U1,D2,C2,V0,TheTolConf,IntPt,HeadOn1,HeadOn2,EndOn1,EndOn2,PosSegment))
196 if(D1.LastTolerance() || D2.LastTolerance()) {
197 if(HeadOrEndPoint(D1,C1,U1,D2,C2,V1,TheTolConf,IntPt,HeadOn1,HeadOn2,EndOn1,EndOn2,PosSegment))
203 //======================================================================
204 //== A u t o I n t e r s e c t i o n
205 //======================================================================
206 void IntCurve_IntPolyPolyGen::Perform( const TheCurve& C1
207 ,const IntRes2d_Domain& D1
208 ,const Standard_Real TheTolConf
209 ,const Standard_Real TheTol)
215 Standard_Real DU = D1.LastParameter()-D1.FirstParameter();
216 Standard_Real Tl=(TheTol < TOL_MINI)? TOL_MINI : TheTol;
217 Standard_Real TlConf=(TheTolConf < TOL_CONF_MINI)? TOL_CONF_MINI : TheTolConf;
218 Perform(C1,D1,TlConf,Tl,0,DU,DU);
220 Standard_Integer n=this->NbPoints();
222 //--------------------------------------------------------------------
223 //-- On ne rejette les points Head Head ... End End
224 //-- si ils figurent deja dans un bout de segment
225 //-- ( On ne peut pas tester les egalites sur les parametres)
226 //-- ( ces points n etant pas trouves a EpsX pres )
227 //-- PosSegment = 1 si Head Head
231 //--------------------------------------------------------------------
232 Standard_Integer PosSegment = 0;
235 IntRes2d_Position Pos1 = this->Point(i).TransitionOfFirst().PositionOnCurve();
236 IntRes2d_Position Pos2 = this->Point(i).TransitionOfSecond().PositionOnCurve();
238 if(Pos1 == IntRes2d_Head) {
239 if(Pos2 == IntRes2d_Head) PosSegment|=1;
240 else if(Pos2 == IntRes2d_End) PosSegment|=2;
242 else if(Pos1 == IntRes2d_End) {
243 if(Pos2 == IntRes2d_Head) PosSegment|=4;
244 else if(Pos2 == IntRes2d_End) PosSegment|=8;
248 n=this->NbSegments();
250 IntRes2d_Position Pos1 = this->Segment(i).FirstPoint().TransitionOfFirst().PositionOnCurve();
251 IntRes2d_Position Pos2 = this->Segment(i).FirstPoint().TransitionOfSecond().PositionOnCurve();
253 if(Pos1 == IntRes2d_Head) {
254 if(Pos2 == IntRes2d_Head) PosSegment|=1;
255 else if(Pos2 == IntRes2d_End) PosSegment|=2;
257 else if(Pos1 == IntRes2d_End) {
258 if(Pos2 == IntRes2d_Head) PosSegment|=4;
259 else if(Pos2 == IntRes2d_End) PosSegment|=8;
262 Pos1 = this->Segment(i).LastPoint().TransitionOfFirst().PositionOnCurve();
263 Pos2 = this->Segment(i).LastPoint().TransitionOfSecond().PositionOnCurve();
265 if(Pos1 == IntRes2d_Head) {
266 if(Pos2 == IntRes2d_Head) PosSegment|=1;
267 else if(Pos2 == IntRes2d_End) PosSegment|=2;
269 else if(Pos1 == IntRes2d_End) {
270 if(Pos2 == IntRes2d_Head) PosSegment|=4;
271 else if(Pos2 == IntRes2d_End) PosSegment|=8;
275 //======================================================================
277 void IntCurve_IntPolyPolyGen::Perform( const TheCurve& C1
278 ,const IntRes2d_Domain& D1
279 ,const Standard_Real TolConf
280 ,const Standard_Real Tol
281 ,const Standard_Integer NbIter
282 ,const Standard_Real /*DeltaU*/
283 ,const Standard_Real) {
285 gp_Vec2d Tan1,Tan2,Norm1,Norm2;
287 Standard_Integer nbsamples;
288 done = Standard_False;
290 nbsamples = TheCurveTool::NbSamples(C1,D1.FirstParameter(),D1.LastParameter());
292 if(NbIter>3 || (NbIter>2 && nbsamples>100)) return;
294 nbsamples*=2; //--- On prend systematiquement 2 fois plus de points que
295 //-- sur une courbe normale.
296 //-- Les courbes auto-intersectantes donne souvent des
297 //-- polygones assez loin de la courbe a parametre ct.
300 nbsamples=(3*(nbsamples*NbIter))/2;
302 IntCurve_ThePolygon2d Poly1(C1,nbsamples,D1,Tol);
303 if(!Poly1.AutoIntersectionIsPossible()) {
304 done = Standard_True;
308 //----------------------------------------------------------------------
309 //-- Si la deflection est inferieure a la Tolerance de Confusion
310 //-- Alors la deflection du polygone est fixee a TolConf
311 //-- (Detection des Zones de Tangence)
312 //----------------------------------------------------------------------
313 if(Poly1.DeflectionOverEstimation() < TolConf) {
314 Poly1.SetDeflectionOverEstimation(TolConf);
317 Intf_InterferencePolygon2d InterPP(Poly1);
318 IntCurve_ExactIntersectionPoint EIP(C1,C1,TolConf);
321 //----------------------------------------------------------------------
322 //-- Traitement des SectionPoint
323 //----------------------------------------------------------------------
324 Standard_Integer Nbsp = InterPP.NbSectionPoints();
327 //-- ---------------------------------------------------------------------
328 //-- tri tri tri tri tri tri tri tri tri tri tri tri tri tri
330 Standard_Integer* TriIndex = new Standard_Integer [Nbsp+1];
331 Standard_Integer* PtrSegIndex1 = new Standard_Integer [Nbsp+1];
332 Standard_Integer* PtrSegIndex2 = new Standard_Integer [Nbsp+1];
333 Standard_Boolean Triok;
334 Standard_Integer SegIndex1,SegIndex2,SegIndex_1,SegIndex_2;
335 // Standard_Real ParamOn1,ParamOn2,ParamOn_1,ParamOn_2;
336 Standard_Real ParamOn1,ParamOn2;
339 for( i=1;i<=Nbsp;i++) {
341 const Intf_SectionPoint& SPnt1 = InterPP.PntValue(i);
342 SPnt1.InfoFirst(Type,PtrSegIndex1[i],ParamOn1);
343 SPnt1.InfoSecond(Type,PtrSegIndex2[i],ParamOn2);
350 for(Standard_Integer tr=1;tr<Nbsp;tr++) {
351 SegIndex1=PtrSegIndex1[TriIndex[tr]];
352 SegIndex_1=PtrSegIndex1[TriIndex[tr+1]];
354 SegIndex2=PtrSegIndex2[TriIndex[tr]];
355 SegIndex_2=PtrSegIndex2[TriIndex[tr+1]];
357 if(SegIndex1 > SegIndex_1) {
358 Standard_Integer q=TriIndex[tr];
359 TriIndex[tr]=TriIndex[tr+1];
361 Triok=Standard_False;
363 else if(SegIndex1 == SegIndex_1) {
364 if(SegIndex2 > SegIndex_2) {
365 Standard_Integer q=TriIndex[tr];
366 TriIndex[tr]=TriIndex[tr+1];
368 Triok=Standard_False;
373 while(Triok==Standard_False);
375 //-- supression des doublons Si Si !
376 for(i=1; i<Nbsp;i++) {
377 if( (PtrSegIndex1[TriIndex[i]] == PtrSegIndex1[TriIndex[i+1]])
378 && (PtrSegIndex2[TriIndex[i]] == PtrSegIndex2[TriIndex[i+1]])) {
383 Standard_Integer Nelarg=(Poly1.NbSegments()/20);
384 if(Nelarg<2) Nelarg=2;
386 for(Standard_Integer sp=1; sp <= Nbsp; sp++) {
388 const Intf_SectionPoint& SPnt = InterPP.PntValue(TriIndex[sp]);
390 SPnt.InfoFirst(Type,SegIndex1,ParamOn1);
391 SPnt.InfoSecond(Type,SegIndex2,ParamOn2);
393 if(Abs(SegIndex1-SegIndex2)>1) {
395 EIP.Perform(Poly1,Poly1,SegIndex1,SegIndex2,ParamOn1,ParamOn2);
396 if(EIP.NbRoots()==0) {
397 //-- On supprime tous les segments voisins
398 for(Standard_Integer k=sp+1;k<=Nbsp;k++) {
399 Standard_Integer kk=TriIndex[k];
400 // --- avoid negative indicies as well as in outer done
402 if( Abs(SegIndex1-PtrSegIndex1[kk])< Nelarg
403 && Abs(SegIndex2-PtrSegIndex2[kk])< Nelarg) {
409 else if(EIP.NbRoots()>=1) {
410 //--------------------------------------------------------------------
411 //-- On verifie que le point trouve est bien une racine
412 //--------------------------------------------------------------------
415 TheCurveTool::D1(C1,U,P1,Tan1);
416 TheCurveTool::D1(C1,V,P2,Tan2);
417 Standard_Real Dist = P1.Distance(P2);
418 Standard_Real EpsX1 = 10.0*TheCurveTool::EpsX(C1);
420 if(Abs(U-V)<=EpsX1) {
421 //-----------------------------------------
422 //-- Solution non valide
423 //-- Les maths ont du converger vers une
424 //-- solution triviale ( point U = V )
425 //-----------------------------------------
429 //-----------------------------------------------------------------
430 //-- On verifie que le point (u,v) n existe pas deja
432 done = Standard_True;
433 Standard_Integer nbp=NbPoints();
435 for(Standard_Integer p=1; p<=nbp; p++) {
436 const IntRes2d_IntersectionPoint& P=Point(p);
437 if(Abs(U-P.ParamOnFirst()) <= EpsX1) {
438 if(Abs(V-P.ParamOnSecond()) <= EpsX1) {
439 Dist = TolConf+1.0; p+=nbp;
444 if(Dist <= TolConf) { //-- Ou le point est deja present
445 IntRes2d_Position Pos1 = IntRes2d_Middle;
446 IntRes2d_Position Pos2 = IntRes2d_Middle;
447 IntRes2d_Transition Trans1,Trans2;
448 //-----------------------------------------------------------------
449 //-- Calcul des Positions des Points sur la courbe
451 if(P1.Distance(DomainOnCurve1.FirstPoint())<=DomainOnCurve1.FirstTolerance())
452 Pos1 = IntRes2d_Head;
453 else if(P1.Distance(DomainOnCurve1.LastPoint())<=DomainOnCurve1.LastTolerance())
456 if(P2.Distance(DomainOnCurve2.FirstPoint())<=DomainOnCurve2.FirstTolerance())
457 Pos2 = IntRes2d_Head;
458 else if(P2.Distance(DomainOnCurve2.LastPoint())<=DomainOnCurve2.LastTolerance())
460 //-----------------------------------------------------------------
461 if(IntImpParGen::DetermineTransition( Pos1,Tan1,Trans1
463 ,TolConf) == Standard_False)
465 TheCurveTool::D2(C1,U,P1,Tan1,Norm1);
466 TheCurveTool::D2(C1,V,P2,Tan2,Norm2);
467 IntImpParGen::DetermineTransition( Pos1,Tan1,Norm1,Trans1
468 ,Pos2,Tan2,Norm2,Trans2
471 IntRes2d_IntersectionPoint IP(P1,U,V,Trans1,Trans2,Standard_False);
479 delete [] PtrSegIndex1;
480 delete [] PtrSegIndex2;
482 done = Standard_True;
486 Standard_Boolean HeadOrEndPoint( const IntRes2d_Domain& D1
488 ,const Standard_Real tu
489 ,const IntRes2d_Domain& D2
491 ,const Standard_Real tv
492 ,const Standard_Real TolConf
493 ,IntRes2d_IntersectionPoint& IntPt
494 ,Standard_Boolean& HeadOn1
495 ,Standard_Boolean& HeadOn2
496 ,Standard_Boolean& EndOn1
497 ,Standard_Boolean& EndOn2
498 ,Standard_Integer PosSegment) {
500 gp_Pnt2d P1,P2,SP1,SP2;
501 gp_Vec2d T1,T2,N1,N2;
504 Standard_Real svu = u;
505 Standard_Real svv = v;
507 TheCurveTool::D1(C1,u,P1,T1);
508 TheCurveTool::D1(C2,v,P2,T2);
510 IntRes2d_Position Pos1 = IntRes2d_Middle;
511 IntRes2d_Position Pos2 = IntRes2d_Middle;
512 IntRes2d_Transition Trans1,Trans2;
514 //----------------------------------------------------------------------
515 //-- Head On 1 : Head1 <-> P2
516 if(P2.Distance(D1.FirstPoint())<=D1.FirstTolerance()) {
517 Pos1 = IntRes2d_Head;
518 HeadOn1 = Standard_True;
519 SP1 = D1.FirstPoint();
520 u = D1.FirstParameter();
522 //----------------------------------------------------------------------
523 //-- End On 1 : End1 <-> P2
524 else if(P2.Distance(D1.LastPoint())<=D1.LastTolerance()) {
526 EndOn1 = Standard_True;
527 SP1 = D1.LastPoint();
528 u = D1.LastParameter();
531 //----------------------------------------------------------------------
532 //-- Head On 2 : Head2 <-> P1
533 else if(P1.Distance(D2.FirstPoint())<=D2.FirstTolerance()) {
534 Pos2 = IntRes2d_Head;
535 HeadOn2 = Standard_True;
536 SP2 = D2.FirstPoint();
537 v = D2.FirstParameter();
539 //----------------------------------------------------------------------
540 //-- End On 2 : End2 <-> P1
541 else if(P1.Distance(D2.LastPoint())<=D2.LastTolerance()) {
543 EndOn2 = Standard_True;
544 SP2 = D2.LastPoint();
545 v = D2.LastParameter();
548 Standard_Real EpsX1 = TheCurveTool::EpsX(C1);
549 Standard_Real EpsX2 = TheCurveTool::EpsX(C2);
551 if((Pos1 != IntRes2d_Middle)||(Pos2 != IntRes2d_Middle)) {
552 if(Pos1 == IntRes2d_Middle) {
553 if(Abs(u-D1.FirstParameter()) <= EpsX1) {
554 Pos1 = IntRes2d_Head;
555 P1 = D1.FirstPoint();
556 HeadOn1 = Standard_True;
558 else if(Abs(u-D1.LastParameter()) <= EpsX1) {
561 EndOn1 = Standard_True;
569 if(Pos2 == IntRes2d_Middle) {
570 if(Abs(v-D2.FirstParameter()) <= EpsX2) {
571 Pos2 = IntRes2d_Head;
572 HeadOn2 = Standard_True;
573 P2 = D2.FirstPoint();
574 if(Pos1 != IntRes2d_Middle) {
575 P1.SetCoord(0.5*(P1.X()+P2.X()),0.5*(P1.Y()+P2.Y()));
581 else if(Abs(v-D2.LastParameter()) <= EpsX2) {
583 EndOn2 = Standard_True;
585 if(Pos1 != IntRes2d_Middle) {
586 P1.SetCoord(0.5*(P1.X()+P2.X()),0.5*(P1.Y()+P2.Y()));
594 //--------------------------------------------------------------------
595 //-- On Teste si un point de bout de segment a deja ces trnasitions
596 //-- Si Oui, on ne cree pas de nouveau point
598 //-- PosSegment = 1 si Head Head
602 //--------------------------------------------------------------------
603 if(Pos1 == IntRes2d_Head) {
604 if((Pos2 == IntRes2d_Head)&&(PosSegment & 1)) return(Standard_False);
605 if((Pos2 == IntRes2d_End )&&(PosSegment & 2)) return(Standard_False);
607 else if(Pos1 == IntRes2d_End) {
608 if((Pos2 == IntRes2d_Head)&&(PosSegment & 4)) return(Standard_False);
609 if((Pos2 == IntRes2d_End )&&(PosSegment & 8)) return(Standard_False);
613 if(IntImpParGen::DetermineTransition( Pos1,T1,Trans1,Pos2,T2,Trans2,TolConf)
615 TheCurveTool::D2(C1,svu,P1,T1,N1);
616 TheCurveTool::D2(C2,svv,P2,T2,N2);
617 IntImpParGen::DetermineTransition(Pos1,T1,N1,Trans1,
618 Pos2,T2,N2,Trans2,TolConf);
620 IntPt.SetValues(P1,u,v,Trans1,Trans2,Standard_False);
621 return(Standard_True);
624 return(Standard_False);
628 //======================================================================
629 void IntCurve_IntPolyPolyGen::Perform( const TheCurve& C1
630 ,const IntRes2d_Domain& D1
632 ,const IntRes2d_Domain& D2
633 ,const Standard_Real TolConf
634 ,const Standard_Real Tol
635 ,const Standard_Integer NbIter
636 ,const Standard_Real DeltaU
637 ,const Standard_Real DeltaV) {
639 Standard_Integer nbsamplesOnC1,nbsamplesOnC2;
640 done = Standard_False;
642 if(NbIter>NBITER_MAX_POLYGON) return;
644 nbsamplesOnC1 = TheCurveTool::NbSamples(C1,D1.FirstParameter(),D1.LastParameter());
646 if (NbIter == 0) // first time
648 if (nbsamplesOnC1 < 20)
653 nbsamplesOnC1=(5*(nbsamplesOnC1*NbIter))/4;
655 /////////////////////////////////////////////
657 nbsamplesOnC2 = TheCurveTool::NbSamples(C2,D2.FirstParameter(),D2.LastParameter());
659 if (NbIter == 0) // first time
661 if (nbsamplesOnC2 < 20)
666 nbsamplesOnC2=(5*(nbsamplesOnC2*NbIter))/4;
668 /////////////////////////////////////////////
671 NCollection_Handle<IntCurve_ThePolygon2d> aPoly1 ,aPoly2;
672 if(nbsamplesOnC2 > nbsamplesOnC1) {
673 aPoly1 = new IntCurve_ThePolygon2d(C1,nbsamplesOnC1,D1,Tol);
674 if(aPoly1->DeflectionOverEstimation() < TolConf) {
675 aPoly2 = new IntCurve_ThePolygon2d(C2,nbsamplesOnC2,D2,Tol);
678 aPoly2 = new IntCurve_ThePolygon2d(C2,nbsamplesOnC2,D2,Tol,aPoly1->Bounding());
679 aPoly1->SetDeflectionOverEstimation( aPoly2->DeflectionOverEstimation()
680 + aPoly1->DeflectionOverEstimation());
681 aPoly1->ComputeWithBox(C1,aPoly2->Bounding());
685 aPoly2 = new IntCurve_ThePolygon2d(C2,nbsamplesOnC2,D2,Tol);
686 if(aPoly2->DeflectionOverEstimation() < TolConf) {
687 aPoly1 = new IntCurve_ThePolygon2d(C1,nbsamplesOnC1,D1,Tol);
690 aPoly1 = new IntCurve_ThePolygon2d(C1,nbsamplesOnC1,D1,Tol,aPoly2->Bounding());
691 aPoly2->SetDeflectionOverEstimation( aPoly2->DeflectionOverEstimation()
692 + aPoly1->DeflectionOverEstimation());
693 aPoly2->ComputeWithBox(C2,aPoly1->Bounding());
696 //----------------------------------------------------------------------
697 //-- Si la deflection est inferieure a la Tolerance de Confusion
698 //-- Alors la deflection du polygone est fixee a TolConf
699 //-- (Detection des Zones de Tangence)
700 //----------------------------------------------------------------------
702 if(aPoly1->DeflectionOverEstimation() < TolConf) {
703 aPoly1->SetDeflectionOverEstimation(TolConf);
705 if(aPoly2->DeflectionOverEstimation() < TolConf) {
706 aPoly2->SetDeflectionOverEstimation(TolConf);
708 //for case when a few polygon points were replaced by line
709 //if exact solution was not found
710 //then search of precise solution will be repeat
711 //for polygon conatins all initial points
712 //secondary search will be performed only for case when initial points
714 Standard_Boolean isFullRepresentation = ( aPoly1->NbSegments() == nbsamplesOnC1 &&
715 aPoly2->NbSegments() == nbsamplesOnC2 );
717 if( !findIntersect( C1, D1, C2, D2, TolConf, Tol, NbIter,
718 DeltaU, DeltaV, *aPoly1, *aPoly2, isFullRepresentation ) && !isFullRepresentation )
720 if(aPoly1->NbSegments() < nbsamplesOnC1)
722 aPoly1 = new IntCurve_ThePolygon2d(C1,nbsamplesOnC1,D1,Tol);
724 if(aPoly2->NbSegments() < nbsamplesOnC2)
726 aPoly2 = new IntCurve_ThePolygon2d(C2,nbsamplesOnC2,D2,Tol);
729 findIntersect( C1, D1, C2, D2, TolConf, Tol, NbIter,
730 DeltaU, DeltaV, *aPoly1, *aPoly2,
735 done = Standard_True;
738 //======================================================================
739 // Purpose : findIntersect
740 //======================================================================
742 Standard_Boolean IntCurve_IntPolyPolyGen::findIntersect(
744 const IntRes2d_Domain& D1,
746 const IntRes2d_Domain& D2,
747 const Standard_Real TolConf,
748 const Standard_Real Tol,
749 const Standard_Integer NbIter,
750 const Standard_Real DeltaU,
751 const Standard_Real DeltaV,
752 const IntCurve_ThePolygon2d& thePoly1,
753 const IntCurve_ThePolygon2d& thePoly2,
754 Standard_Boolean isFullPolygon )
757 gp_Vec2d Tan1,Tan2,Norm1,Norm2;
759 Intf_InterferencePolygon2d InterPP(thePoly1,thePoly2);
760 IntCurve_ExactIntersectionPoint EIP(C1,C2,TolConf);
761 Standard_Real U = 0., V = 0.;
762 Standard_Boolean AnErrorOccurred = Standard_False;
763 done = Standard_True; // To prevent exception in nbp=NbPoints();
764 //----------------------------------------------------------------------
765 //-- Traitement des SectionPoint
766 //----------------------------------------------------------------------
767 Standard_Integer Nbsp = InterPP.NbSectionPoints();
768 for(Standard_Integer sp=1; sp <= Nbsp; sp++) {
769 const Intf_SectionPoint& SPnt = InterPP.PntValue(sp);
770 Standard_Integer SegIndex1,SegIndex2;
771 Standard_Real ParamOn1,ParamOn2;
774 SPnt.InfoFirst(Type,SegIndex1,ParamOn1);
775 SPnt.InfoSecond(Type,SegIndex2,ParamOn2);
776 EIP.Perform(thePoly1,thePoly2,SegIndex1,SegIndex2,ParamOn1,ParamOn2);
777 AnErrorOccurred = EIP.AnErrorOccurred();
779 if( !EIP.NbRoots() && !isFullPolygon)
780 return Standard_False;
787 //--------------------------------------------------------------------
788 //-- On verifie que le point trouve est bien une racine
789 //--------------------------------------------------------------------
791 TheCurveTool::D1(C1,U,P1,Tan1);
792 TheCurveTool::D1(C2,V,P2,Tan2);
793 Standard_Real Dist = P1.Distance(P2);
794 //-----------------------------------------------------------------
795 //-- On verifie que le point (u,v) n existe pas deja
797 Standard_Integer nbp=NbPoints();
798 Standard_Real EpsX1 = 10.0*TheCurveTool::EpsX(C1);
799 Standard_Real EpsX2 = 10.0*TheCurveTool::EpsX(C2);
800 for(Standard_Integer p=1; p<=nbp; p++) {
801 const IntRes2d_IntersectionPoint& P=Point(p);
802 if(Abs(U-P.ParamOnFirst()) <= EpsX1) {
803 if(Abs(V-P.ParamOnSecond()) <= EpsX2) {
804 Dist = TolConf+1.0; p+=nbp;
809 if(Dist <= TolConf) { //-- Ou le point est deja present
810 IntRes2d_Position Pos1 = IntRes2d_Middle;
811 IntRes2d_Position Pos2 = IntRes2d_Middle;
812 IntRes2d_Transition Trans1,Trans2;
813 //-----------------------------------------------------------------
814 //-- Calcul des Positions des Points sur la courbe
816 if(P1.Distance(DomainOnCurve1.FirstPoint())<=DomainOnCurve1.FirstTolerance())
817 Pos1 = IntRes2d_Head;
818 else if(P1.Distance(DomainOnCurve1.LastPoint())<=DomainOnCurve1.LastTolerance())
821 if(P2.Distance(DomainOnCurve2.FirstPoint())<=DomainOnCurve2.FirstTolerance())
822 Pos2 = IntRes2d_Head;
823 else if(P2.Distance(DomainOnCurve2.LastPoint())<=DomainOnCurve2.LastTolerance())
825 //-----------------------------------------------------------------
826 //-- Calcul des Transitions (Voir IntImpParGen.cxx)
828 if(IntImpParGen::DetermineTransition (Pos1, Tan1, Trans1, Pos2, Tan2, Trans2, TolConf) == Standard_False) {
829 TheCurveTool::D2(C1,U,P1,Tan1,Norm1);
830 TheCurveTool::D2(C2,V,P2,Tan2,Norm2);
831 IntImpParGen::DetermineTransition (Pos1, Tan1, Norm1, Trans1, Pos2, Tan2, Norm2, Trans2, TolConf);
833 IntRes2d_IntersectionPoint IP(P1,U,V,Trans1,Trans2,Standard_False);
838 //----------------------------------------------------------------------
839 //-- Traitement des TangentZone
840 //----------------------------------------------------------------------
841 Standard_Integer Nbtz = InterPP.NbTangentZones();
842 for(Standard_Integer tz=1; tz <= Nbtz; tz++) {
843 Standard_Integer NbPnts = InterPP.ZoneValue(tz).NumberOfPoints();
844 //====================================================================
845 //== Recherche du premier et du dernier point dans la zone de tg.
846 //====================================================================
847 Standard_Real ParamSupOnCurve2,ParamInfOnCurve2;
848 Standard_Real ParamSupOnCurve1,ParamInfOnCurve1;
849 // Standard_Integer SegIndex,SegIndex1onP1,SegIndex1onP2,SegIndex2onP1,SegIndex2onP2;
850 Standard_Integer SegIndex1onP1,SegIndex1onP2;
852 Standard_Real ParamOnLine;
853 Standard_Real PolyUInf,PolyUSup,PolyVInf,PolyVSup;
854 ParamSupOnCurve2=ParamSupOnCurve1=PolyUSup=PolyVSup=-RealLast();
855 ParamInfOnCurve2=ParamInfOnCurve1=PolyUInf=PolyVInf= RealLast();
856 for(Standard_Integer qq=1;qq<=NbPnts;qq++) {
857 const Intf_SectionPoint& SPnt1 = InterPP.ZoneValue(tz).GetPoint(qq);
858 //====================================================================
859 //== On discretise sur les zones de tangence
862 //== Deflection < Tolerance
863 //== OU Echantillon < EpsX (normalement la premiere condition est
865 //====================================================================
866 // Standard_Real _PolyUInf,_PolyUSup,_PolyVInf,_PolyVSup;
867 Standard_Real _PolyUInf,_PolyVInf;
869 SPnt1.InfoFirst(Type,SegIndex1onP1,ParamOnLine);
870 if(SegIndex1onP1 > thePoly1.NbSegments()) { SegIndex1onP1--; ParamOnLine = 1.0; }
871 if(SegIndex1onP1 <= 0) { SegIndex1onP1=1; ParamOnLine = 0.0; }
872 _PolyUInf = thePoly1.ApproxParamOnCurve(SegIndex1onP1,ParamOnLine);
874 SPnt1.InfoSecond(Type,SegIndex1onP2,ParamOnLine);
875 if(SegIndex1onP2 > thePoly2.NbSegments()) { SegIndex1onP2--; ParamOnLine = 1.0; }
876 if(SegIndex1onP2 <= 0) { SegIndex1onP2=1; ParamOnLine = 0.0; }
877 _PolyVInf = thePoly2.ApproxParamOnCurve(SegIndex1onP2,ParamOnLine);
879 //----------------------------------------------------------------------
881 if(ParamInfOnCurve1 > _PolyUInf) ParamInfOnCurve1=_PolyUInf;
882 if(ParamInfOnCurve2 > _PolyVInf) ParamInfOnCurve2=_PolyVInf;
884 if(ParamSupOnCurve1 < _PolyUInf) ParamSupOnCurve1=_PolyUInf;
885 if(ParamSupOnCurve2 < _PolyVInf) ParamSupOnCurve2=_PolyVInf;
888 PolyUInf= ParamInfOnCurve1;
889 PolyUSup= ParamSupOnCurve1;
890 PolyVInf= ParamInfOnCurve2;
891 PolyVSup= ParamSupOnCurve2;
893 TheCurveTool::D0(C1,PolyUInf,P1);
894 TheCurveTool::D0(C2,PolyVInf,P2);
895 Standard_Real distmemesens = P1.SquareDistance(P2);
896 TheCurveTool::D0(C2,PolyVSup,P2);
897 Standard_Real distdiffsens = P1.SquareDistance(P2);
898 if(distmemesens > distdiffsens) {
899 Standard_Real qwerty=PolyVInf; PolyVInf=PolyVSup; PolyVSup=qwerty;
902 if( ( (thePoly1.DeflectionOverEstimation() > TolConf)
903 ||(thePoly2.DeflectionOverEstimation() > TolConf))
904 &&(NbIter<NBITER_MAX_POLYGON)) {
906 IntRes2d_Domain RecursD1( TheCurveTool::Value(C1,ParamInfOnCurve1)
907 ,ParamInfOnCurve1,TolConf
908 ,TheCurveTool::Value(C1,ParamSupOnCurve1)
909 ,ParamSupOnCurve1,TolConf);
910 IntRes2d_Domain RecursD2( TheCurveTool::Value(C2,ParamInfOnCurve2)
911 ,ParamInfOnCurve2,TolConf
912 ,TheCurveTool::Value(C2,ParamSupOnCurve2)
913 ,ParamSupOnCurve2,TolConf);
914 //-- On ne delete pas thePoly1(2) ,
915 //-- ils sont detruits enfin de fct.
916 //-- !! Pas de return intempestif !!
917 Perform(C1,RecursD1,C2,RecursD2,Tol,TolConf,NbIter+1,DeltaU,DeltaV);
920 //-----------------------------------------------------------------
921 //-- Calcul des Positions des Points sur la courbe et des
922 //-- Transitions sur chaque borne du segment
924 IntRes2d_Position Pos1 = IntRes2d_Middle;
925 IntRes2d_Position Pos2 = IntRes2d_Middle;
926 IntRes2d_Transition Trans1,Trans2;
928 TheCurveTool::D1(C1,PolyUInf,P1,Tan1);
929 TheCurveTool::D1(C2,PolyVInf,P2,Tan2);
931 if(P1.Distance(DomainOnCurve1.FirstPoint())<=DomainOnCurve1.FirstTolerance()) {
932 Pos1 = IntRes2d_Head;
934 else if(P1.Distance(DomainOnCurve1.LastPoint())<=DomainOnCurve1.LastTolerance()) {
937 if(P2.Distance(DomainOnCurve2.FirstPoint())<=DomainOnCurve2.FirstTolerance()) {
938 Pos2 = IntRes2d_Head;
940 else if(P2.Distance(DomainOnCurve2.LastPoint())<=DomainOnCurve2.LastTolerance()) {
944 if(Pos1==IntRes2d_Middle && Pos2!=IntRes2d_Middle) {
945 PolyUInf=TheProjPCur::FindParameter( C1,P2,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
947 else if(Pos1!=IntRes2d_Middle && Pos2==IntRes2d_Middle) {
948 PolyVInf=TheProjPCur::FindParameter( C2,P1,D2.FirstParameter(),D2.LastParameter(),TheCurveTool::EpsX(C2));
950 else if(Abs(ParamInfOnCurve1-ParamSupOnCurve1) > Abs(ParamInfOnCurve2-ParamSupOnCurve2)) {
951 PolyVInf=TheProjPCur::FindParameter( C2,P1,D2.FirstParameter(),D2.LastParameter(),TheCurveTool::EpsX(C2));
954 PolyUInf=TheProjPCur::FindParameter( C1,P2,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
959 if(IntImpParGen::DetermineTransition( Pos1,Tan1,Trans1,Pos2,Tan2,Trans2,TolConf)
962 TheCurveTool::D2(C1,PolyUInf,P1,Tan1,Norm1);
963 TheCurveTool::D2(C2,PolyVInf,P2,Tan2,Norm2);
964 IntImpParGen::DetermineTransition(Pos1,Tan1,Norm1,Trans1,
965 Pos2,Tan2,Norm2,Trans2,TolConf);
967 IntRes2d_IntersectionPoint PtSeg1(P1,PolyUInf,PolyVInf
968 ,Trans1,Trans2,Standard_False);
969 //----------------------------------------------------------------------
971 if((Abs(PolyUInf-PolyUSup) <= TheCurveTool::EpsX(C1))
972 || (Abs(PolyVInf-PolyVSup) <= TheCurveTool::EpsX(C2)))
978 TheCurveTool::D1(C1,PolyUSup,P1,Tan1);
979 TheCurveTool::D1(C2,PolyVSup,P2,Tan2);
980 Pos1 = IntRes2d_Middle; Pos2 = IntRes2d_Middle;
982 if(P1.Distance(DomainOnCurve1.FirstPoint())<=DomainOnCurve1.FirstTolerance()) {
983 Pos1 = IntRes2d_Head;
985 else if(P1.Distance(DomainOnCurve1.LastPoint())<=DomainOnCurve1.LastTolerance()) {
988 if(P2.Distance(DomainOnCurve2.FirstPoint())<=DomainOnCurve2.FirstTolerance()) {
989 Pos2 = IntRes2d_Head;
991 else if(P2.Distance(DomainOnCurve2.LastPoint())<=DomainOnCurve2.LastTolerance()) {
996 if(Pos1==IntRes2d_Middle && Pos2!=IntRes2d_Middle) {
997 PolyUSup=TheProjPCur::FindParameter( C1,P2,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
999 else if(Pos1!=IntRes2d_Middle && Pos2==IntRes2d_Middle) {
1000 PolyVSup=TheProjPCur::FindParameter( C2,P1,D2.FirstParameter(),D2.LastParameter(),TheCurveTool::EpsX(C2));
1002 else if(Abs(ParamInfOnCurve1-ParamSupOnCurve1) > Abs(ParamInfOnCurve2-ParamSupOnCurve2)) {
1003 PolyVSup=TheProjPCur::FindParameter( C2,P1,D2.FirstParameter(),D2.LastParameter(),TheCurveTool::EpsX(C2));
1006 PolyUSup=TheProjPCur::FindParameter( C1,P2,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
1009 if(IntImpParGen::DetermineTransition( Pos1,Tan1,Trans1,Pos2,Tan2,Trans2,TolConf)
1011 TheCurveTool::D2(C1,PolyUSup,P1,Tan1,Norm1);
1012 TheCurveTool::D2(C2,PolyVSup,P2,Tan2,Norm2);
1013 IntImpParGen::DetermineTransition(Pos1,Tan1,Norm1,Trans1,
1014 Pos2,Tan2,Norm2,Trans2,TolConf);
1016 IntRes2d_IntersectionPoint PtSeg2(P1,PolyUSup,PolyVSup
1017 ,Trans1,Trans2,Standard_False);
1019 Standard_Boolean Oppos = (Tan1.Dot(Tan2) > 0.0)? Standard_False : Standard_True;
1020 if(ParamInfOnCurve1 > ParamSupOnCurve1) {
1021 IntRes2d_IntersectionSegment Seg(PtSeg2,PtSeg1,Oppos,Standard_False);
1025 IntRes2d_IntersectionSegment Seg(PtSeg1,PtSeg2,Oppos,Standard_False);
1031 return Standard_True;