0023948: Wrong intersection between a surface of revolution and a plane.
[occt.git] / src / IntRes2d / IntRes2d_Intersection.cxx
1 // Created on: 1992-04-28
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License 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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <IntRes2d_Intersection.ixx>
18
19 #include <StdFail_NotDone.hxx>
20 #include <Standard_OutOfRange.hxx>
21 #include <IntRes2d_SequenceOfIntersectionPoint.hxx>
22 #include <IntRes2d_SequenceOfIntersectionSegment.hxx>
23 #include <IntRes2d_Position.hxx>
24
25
26 #define PARAMEQUAL(a,b) (Abs((a)-(b))< (1e-8))
27
28
29 static void InternalVerifyPosition(IntRes2d_Transition& T1,
30                                    IntRes2d_Transition& T2,
31                                    const Standard_Real PParamOnFirst,
32                                    const Standard_Real PParamOnSecond,
33                                    const Standard_Real FirstParam1,
34                                    const Standard_Real LastParam1,
35                                    const Standard_Real FirstParam2,
36                                    const Standard_Real LastParam2);
37
38
39
40 //----------------------------------------------------------------------
41 static Standard_Boolean TransitionEqual( const IntRes2d_Transition& T1
42                                         ,const IntRes2d_Transition& T2); 
43
44
45 Standard_Boolean TransitionEqual( const IntRes2d_Transition& T1
46                                  ,const IntRes2d_Transition& T2) {
47   
48   if(T1.PositionOnCurve() == T2.PositionOnCurve())  {
49     if(T1.TransitionType() == T2.TransitionType()) {
50       if(T1.TransitionType() == IntRes2d_Touch) {
51         if(T1.IsTangent()==T2.IsTangent()) {
52           if(T1.Situation() == T2.Situation()) {
53             if(T1.IsOpposite() == T2.IsOpposite()) {
54               return(Standard_True);
55             }
56           }
57         }
58       }
59       else {
60         return(Standard_True);
61       }
62     }
63   }
64   return(Standard_False);
65 }
66
67
68
69 void IntRes2d_Intersection::Insert(const IntRes2d_IntersectionPoint& Pnt) {
70   Standard_Integer n = lpnt.Length();
71   if(n==0) {
72     lpnt.Append(Pnt);
73   }
74   else {
75     Standard_Real u = Pnt.ParamOnFirst();
76     Standard_Integer i = 1;
77     Standard_Integer b = n+1;                    
78     while(i<=n) {
79       const IntRes2d_IntersectionPoint& Pnti=lpnt(i);
80       Standard_Real ui = Pnti.ParamOnFirst();
81       if(ui >= u) { b=i; i=n; }
82       if(PARAMEQUAL(ui,u)) {
83         if(PARAMEQUAL((Pnt.ParamOnSecond()),(Pnti.ParamOnSecond()))) {
84           if(   (TransitionEqual(Pnt.TransitionOfFirst(),Pnti.TransitionOfFirst()))
85              && (TransitionEqual(Pnt.TransitionOfSecond(),Pnti.TransitionOfSecond()))) {
86             b=0;
87             i=n;
88           }
89         }
90       }
91       //----------------------------------------------------------------
92
93       i++;
94     }
95     if(b>n)          { lpnt.Append(Pnt); } 
96     else if(b>0)     { lpnt.InsertBefore(b,Pnt); } 
97   }
98 }
99
100 void IntRes2d_Intersection::SetValues(const IntRes2d_Intersection& Other) {
101   Standard_Integer i ;
102   if(Other.done) {
103     lseg.Clear();
104     lpnt.Clear();
105     Standard_Integer N = Other.lpnt.Length();
106     for( i=1; i<= N ; i++) { 
107       lpnt.Append(Other.lpnt(i));
108     }
109     N = Other.lseg.Length();
110     for(i=1; i<= N ; i++) { 
111       lseg.Append(Other.lseg(i));
112     } 
113     //-----------------------
114     //lpnt=Other.lpnt;  Pose des problemes 
115     //lseg=Other.lseg;  pour des objets composites
116     //-----------------------
117     done=Standard_True;
118   }
119   else {
120     done=Standard_False;
121   }
122 }
123
124 //----------------------------------------------------------------------
125 //-- Function used to Merge the results of two Intersections .
126 //-- for Composite Curves only. FirstParam and LastParam are the
127 //--  parameter of the bounds of the composite Curve
128 //-- Merge of two Intersection Segments S1 and S2 when :
129 //--  
130 //--     S1 : U1First,PosU1Fisrt   -->  U1Last,PosU1Last
131 //--          V1First,PosV1Fisrt   -->  V1Last,PosV1Last
132 //--     S2 : U2First,PosU2Fisrt   -->  U2Last,PosU2Last
133 //--          V2First,PosV2Fisrt   -->  V2Last,PosV2Last
134 //--
135 //--   1       U :      X------1-------E H-----2-------X   U -->
136 //--           V :      X------1-------X X-----2-------X  <- V -> ?
137 //--
138 //--      PosU1Last == End    &&  PosU2First == Head
139 //--      && U1Last == U2First
140 //--      && V1Last == V2First
141 //--
142 //--   OR  
143 //--
144 //--   2       U :      X------1-------H E-----2-------X   U <--
145 //--           V :      X------1-------X X-----2-------X  <- V -> ?
146 //--
147 //--      PosU1Last == Head   &&  PosU2First == End
148 //--      && U1Last == U2First
149 //--      && V1Last == V2First
150 //--
151 //--  merge the two Segment in :
152 //--
153 //--           U :      X------1----------2-------X     U 
154 //--           V :      X------1----------2-------X  <- V -> ?
155 //--
156 //--        
157 //--  
158 //--  The Position of Intersection Point is set to Middle 
159 //--  when the Parameters U et V are between FirstParam1, EndParam1
160 //--  and FirstParam2, EndParam2
161 //--  
162 void IntRes2d_Intersection::Append( const IntRes2d_Intersection& Other
163                                    ,const Standard_Real FirstParam1
164                                    ,const Standard_Real LastParam1
165                                    ,const Standard_Real FirstParam2
166                                    ,const Standard_Real LastParam2) {
167   
168   
169   if(Other.done) {
170     //-- Verification of the Position of the IntersectionPoints
171     Standard_Integer n=Other.lpnt.Length();
172     Standard_Integer i ;
173     for( i=1; i<=n ; i++) {
174       
175       const IntRes2d_IntersectionPoint& P=Other.lpnt(i);
176       Standard_Real PParamOnFirst=P.ParamOnFirst();
177       Standard_Real PParamOnSecond=P.ParamOnSecond();
178       IntRes2d_Transition T1=P.TransitionOfFirst();
179       IntRes2d_Transition T2=P.TransitionOfSecond();
180       gp_Pnt2d Pt=P.Value();
181       
182       
183       InternalVerifyPosition(T1,T2
184                              ,PParamOnFirst,PParamOnSecond
185                              ,FirstParam1,LastParam1
186                              ,FirstParam2,LastParam2);
187           
188       this->Insert(IntRes2d_IntersectionPoint(Pt,
189                                               PParamOnFirst,
190                                               PParamOnSecond,
191                                               T1,T2,
192                                               Standard_False));
193     }
194     
195     //--------------------------------------------------
196     //-- IntersectionSegment 
197     //-- (we assume that a composite curve is always bounded)
198     //-- (a segment has always a FirstPoint and a LastPoint)
199     //--------------------------------------------------
200     n=Other.lseg.Length();
201     Standard_Real SegModif_P1First=0,SegModif_P1Second=0;
202     Standard_Real SegModif_P2First=0,SegModif_P2Second=0;
203
204     for(i=1; i<=n ; i++) {
205       
206       const IntRes2d_IntersectionPoint& P1=Other.lseg(i).FirstPoint();
207       
208       Standard_Real P1PParamOnFirst=P1.ParamOnFirst();
209       Standard_Real P1PParamOnSecond=P1.ParamOnSecond();
210       IntRes2d_Transition P1T1=P1.TransitionOfFirst();
211       IntRes2d_Transition P1T2=P1.TransitionOfSecond();
212       const gp_Pnt2d& P1Pt=P1.Value();
213       
214       InternalVerifyPosition(P1T1,P1T2
215                              ,P1PParamOnFirst,P1PParamOnSecond
216                              ,FirstParam1,LastParam1
217                              ,FirstParam2,LastParam2);
218
219       const IntRes2d_IntersectionPoint& P2=Other.lseg(i).LastPoint();
220
221       Standard_Real P2PParamOnFirst=P2.ParamOnFirst();
222       Standard_Real P2PParamOnSecond=P2.ParamOnSecond();
223       IntRes2d_Transition P2T1=P2.TransitionOfFirst();
224       IntRes2d_Transition P2T2=P2.TransitionOfSecond();
225       const gp_Pnt2d& P2Pt=P2.Value();
226       
227       Standard_Boolean Opposite=Other.lseg(i).IsOpposite();
228       
229       InternalVerifyPosition(P2T1,P2T2
230                              ,P2PParamOnFirst,P2PParamOnSecond
231                              ,FirstParam1,LastParam1
232                              ,FirstParam2,LastParam2);
233
234
235
236       //-- Loop on the previous segments 
237       //--
238       Standard_Integer an=lseg.Length();
239       Standard_Boolean NotYetModified=Standard_True;
240
241       for(Standard_Integer j=1;(j<=an)&&(NotYetModified);j++) {
242
243         const IntRes2d_IntersectionPoint& AnP1=lseg(j).FirstPoint();
244         Standard_Real AnP1PParamOnFirst=AnP1.ParamOnFirst();
245         Standard_Real AnP1PParamOnSecond=AnP1.ParamOnSecond();
246         
247         const IntRes2d_IntersectionPoint& AnP2=lseg(j).LastPoint();
248         Standard_Real AnP2PParamOnFirst=AnP2.ParamOnFirst();
249         Standard_Real AnP2PParamOnSecond=AnP2.ParamOnSecond();
250
251         if(Opposite == lseg(j).IsOpposite()) {
252           //---------------------------------------------------------------
253           //--    AnP1---------AnP2
254           //--                  P1-------------P2
255           //--
256           if(  PARAMEQUAL(P1PParamOnFirst,AnP2PParamOnFirst)
257              &&PARAMEQUAL(P1PParamOnSecond,AnP2PParamOnSecond)) {
258             NotYetModified=Standard_False;
259             lseg(j)=IntRes2d_IntersectionSegment(AnP1,P2,
260                                                  Opposite,Standard_False);
261             SegModif_P1First   = AnP1PParamOnFirst;
262             SegModif_P1Second  = AnP1PParamOnSecond;
263             SegModif_P2First   = P2PParamOnFirst;
264             SegModif_P2Second  = P2PParamOnSecond;
265           }
266           //---------------------------------------------------------------
267           //--                                AnP1---------AnP2
268           //--                  P1-------------P2
269           //--
270           else if(  PARAMEQUAL(P2PParamOnFirst,AnP1PParamOnFirst)
271                   &&PARAMEQUAL(P2PParamOnSecond,AnP1PParamOnSecond)) {
272             NotYetModified=Standard_False;
273             lseg(j)=IntRes2d_IntersectionSegment(P1,AnP2,
274                                                  Opposite,Standard_False);
275             SegModif_P1First   = P1PParamOnFirst;
276             SegModif_P1Second  = P1PParamOnSecond;
277             SegModif_P2First   = AnP2PParamOnFirst;
278             SegModif_P2Second  = AnP2PParamOnSecond;
279           }
280           //---------------------------------------------------------------
281           //--    AnP2---------AnP1
282           //--                  P1-------------P2
283           //--
284           if(  PARAMEQUAL(P1PParamOnFirst,AnP1PParamOnFirst)
285              &&PARAMEQUAL(P1PParamOnSecond,AnP1PParamOnSecond)) {
286             NotYetModified=Standard_False;
287             lseg(j)=IntRes2d_IntersectionSegment(AnP2,P2,
288                                                  Opposite,Standard_False);
289             SegModif_P1First   = P2PParamOnFirst;
290             SegModif_P1Second  = P2PParamOnSecond;
291             SegModif_P2First   = AnP2PParamOnFirst;
292             SegModif_P2Second  = AnP2PParamOnSecond;
293           }
294           //---------------------------------------------------------------
295           //--                                AnP2---------AnP1
296           //--                  P1-------------P2
297           //--
298           else if(  PARAMEQUAL(P2PParamOnFirst,AnP2PParamOnFirst)
299                   &&PARAMEQUAL(P2PParamOnSecond,AnP2PParamOnSecond)) {
300             NotYetModified=Standard_False;
301             lseg(j)=IntRes2d_IntersectionSegment(P1,AnP1,
302                                                  Opposite,Standard_False);
303             SegModif_P1First   = P1PParamOnFirst;
304             SegModif_P1Second  = P1PParamOnSecond;
305             SegModif_P2First   = AnP1PParamOnFirst;
306             SegModif_P2Second  = AnP1PParamOnSecond;
307           }
308         }
309       }
310       if(NotYetModified) {
311         this->Append(IntRes2d_IntersectionSegment(
312                             IntRes2d_IntersectionPoint(P1Pt,
313                                                        P1PParamOnFirst,
314                                                        P1PParamOnSecond,
315                                                        P1T1,P1T2,
316                                                        Standard_False),
317                             IntRes2d_IntersectionPoint(P2Pt,
318                                                        P2PParamOnFirst,
319                                                        P2PParamOnSecond,
320                                                        P2T1,P2T2,
321                                                        Standard_False),
322                                                   Opposite,Standard_False));
323         
324       }    //-- if(NotYetModified) 
325       else {
326         //--------------------------------------------------------------
327         //-- Are some Existing Points in this segment ? 
328         //--------------------------------------------------------------
329         Standard_Integer rnbpts=lpnt.Length();
330         for(Standard_Integer rp=1; (rp<=rnbpts)&&(rp>=1); rp++) {
331           Standard_Real PonFirst=lpnt(rp).ParamOnFirst();
332           Standard_Real PonSecond=lpnt(rp).ParamOnSecond();
333           
334           if(  ((PonFirst  >=   SegModif_P1First    &&    PonFirst  <=  SegModif_P2First)
335               ||(PonFirst  <=   SegModif_P1First    &&    PonFirst  >=  SegModif_P2First))
336             && ((PonSecond >=   SegModif_P1Second   &&    PonSecond <=  SegModif_P2Second)
337               ||(PonSecond<=    SegModif_P1Second   &&    PonSecond >=  SegModif_P2Second))) {
338             lpnt.Remove(rp);
339             rp--;
340             rnbpts--;
341           }
342         }  //-- for(Standard_Integer rp=1; (rp<=rnbpts)&&(rp>=1); rp++) 
343       }
344     }
345     //--------------------------------------------------
346     //-- Remove some Points ? 
347     //-- Example : Points which lie in a segment.
348     //--------------------------------------------------
349     
350     done=Standard_True;
351   }
352   else {
353     done=Standard_False;
354   }
355 }
356
357
358 //----------------------------------------------------------------------
359 //--
360 #define DEBUGPOSITION 0 
361
362 #if DEBUGPOSITION
363 void AffPosition(IntRes2d_Transition& T,const Standard_Real u,const char *Texte);
364 void AffPosition(IntRes2d_Transition& T,const Standard_Real u,const char *Texte) { 
365   if(T.PositionOnCurve() == IntRes2d_End) { cout <<Texte<<" Param :"<<u<<" End "<<endl; } 
366   if(T.PositionOnCurve() == IntRes2d_Middle) { cout <<Texte<<" Param :"<<u<<" Middle "<<endl; } 
367   if(T.PositionOnCurve() == IntRes2d_Head) { cout <<Texte<<" Param :"<<u<<" Head "<<endl; }
368
369 #endif
370
371 void InternalVerifyPosition(IntRes2d_Transition& T1,
372                             IntRes2d_Transition& T2,
373                             const Standard_Real PParamOnFirst,
374                             const Standard_Real PParamOnSecond,
375                             const Standard_Real FirstParam1,
376                             const Standard_Real LastParam1,
377                             const Standard_Real FirstParam2,
378                             const Standard_Real LastParam2) {
379 #if DEBUGPOSITION
380 AffPosition(T1,PParamOnFirst," Point 1 ");
381 AffPosition(T2,PParamOnSecond," Point 2 ");
382 #endif
383   if(T1.PositionOnCurve() != IntRes2d_Middle) {
384     if(!(   PARAMEQUAL(PParamOnFirst,FirstParam1)  
385          || PARAMEQUAL(PParamOnFirst,LastParam1)))  {
386       //-- Middle on the Curve 1
387
388       // modified by NIZHNY-MKK  Tue Nov 26 14:23:24 2002.BEGIN
389       if((PParamOnFirst > FirstParam1) && (PParamOnFirst < LastParam1))
390       // modified by NIZHNY-MKK  Tue Nov 26 14:23:27 2002.END
391         T1.SetPosition(IntRes2d_Middle);
392     }
393   }
394   if(T2.PositionOnCurve() != IntRes2d_Middle) {
395     if(!(   PARAMEQUAL(PParamOnSecond,FirstParam2)
396          || PARAMEQUAL(PParamOnSecond,LastParam2))) {
397
398       // modified by NIZHNY-MKK  Tue Nov 26 14:24:15 2002.BEGIN
399       if((PParamOnSecond > FirstParam2) && (PParamOnSecond < LastParam2))
400       // modified by NIZHNY-MKK  Tue Nov 26 14:24:19 2002.END
401         T2.SetPosition(IntRes2d_Middle);
402     }
403   }
404 }
405 //----------------------------------------------------------------------
406      
407
408
409
410
411      
412
413 #if 0 
414 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
415 #define Debug(q) cout<<"IntRes2d_Intersection"<<"q ="<<q<<endl;
416
417 char *DebugPos(const IntRes2d_Position P);
418
419 Debug(FirstParam1);
420 Debug(LastParam1);
421 Debug(FirstParam2);
422 Debug(LastParam2);
423 Debug(PParamOnFirst);
424 Debug(PParamOnSecond);
425 cout<<" ##### T1  <> Middle ###### "<<DebugPos(T1.PositionOnCurve())<<endl;
426 char *DebugPos(const IntRes2d_Position P) {
427   if(P==IntRes2d_Middle) return(" Middle ");
428   if(P==IntRes2d_Head) return(" Head ");
429   if(P==IntRes2d_End) return(" End ");
430 }
431 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
432 #endif
433