a4c690faa1db701d7a697433f7be37e3cd7990a8
[occt.git] / src / Bisector / Bisector_Inter.cxx
1 // Created on: 1994-06-24
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1994-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 //  Modified by skv - Mon May  5 15:06:39 2003 OCC616
18
19 #include <Bisector_Bisec.hxx>
20 #include <Bisector_BisecAna.hxx>
21 #include <Bisector_BisecCC.hxx>
22 #include <Bisector_BisecPC.hxx>
23 #include <Bisector_Curve.hxx>
24 #include <Bisector_FunctionInter.hxx>
25 #include <Bisector_Inter.hxx>
26 #include <ElCLib.hxx>
27 #include <Geom2d_Curve.hxx>
28 #include <Geom2d_Line.hxx>
29 #include <Geom2d_TrimmedCurve.hxx>
30 #include <Geom2dAdaptor_Curve.hxx>
31 #include <Geom2dInt_GInter.hxx>
32 #include <IntRes2d_Domain.hxx>
33 #include <IntRes2d_Intersection.hxx>
34 #include <IntRes2d_IntersectionPoint.hxx>
35 #include <IntRes2d_Transition.hxx>
36 #include <math_BissecNewton.hxx>
37 #include <Precision.hxx>
38 #include <Standard_ConstructionError.hxx>
39
40 #ifdef OCCT_DEBUG
41 //#define DRAW
42 #ifdef DRAW
43 #include <DrawTrSurf.hxx>
44 static char name[100];
45 static Standard_Boolean Affich = Standard_False;
46 static Standard_Integer nbint = 0;
47 #endif
48 #endif
49
50 //===================================================================================
51 // function :
52 // putpose  :
53 //===================================================================================
54 Bisector_Inter::Bisector_Inter() 
55 {
56 }
57
58 //===================================================================================
59 // function :
60 // putpose  :
61 //===================================================================================
62 Bisector_Inter::Bisector_Inter(const Bisector_Bisec&  C1, 
63                                const IntRes2d_Domain& D1, 
64                                const Bisector_Bisec&  C2, 
65                                const IntRes2d_Domain& D2, 
66                                const Standard_Real    TolConf, 
67                                const Standard_Real    Tol,
68                                const Standard_Boolean ComunElement) 
69 {
70   Perform (C1,D1,C2,D2,TolConf,Tol,ComunElement);
71 }
72
73 //===================================================================================
74 // function : ConstructSegment
75 // putpose  :
76 //===================================================================================
77 static Handle(Geom2d_Line) ConstructSegment(const gp_Pnt2d&     PMin,
78                                             const gp_Pnt2d&     PMax,
79                                             const Standard_Real UMin,
80 //                                          const Standard_Real UMax)
81                                             const Standard_Real )
82 {
83   gp_Dir2d Dir(PMax.X() - PMin.X(),PMax.Y() - PMin.Y());
84   Handle(Geom2d_Line) L = new Geom2d_Line (gp_Pnt2d(PMin.X() - UMin*Dir.X(),
85                                                     PMin.Y() - UMin*Dir.Y()),Dir);
86   return L;
87 }
88
89 //===================================================================================
90 // function : Perform
91 // putpose  :
92 //===================================================================================
93 void Bisector_Inter::Perform(const Bisector_Bisec&  C1,
94                              const IntRes2d_Domain& D1, 
95                              const Bisector_Bisec&  C2,
96                              const IntRes2d_Domain& D2,
97                              const Standard_Real    TolConf,
98                              const Standard_Real    Tol,
99                              const Standard_Boolean ComunElement) 
100 {
101   Handle(Bisector_Curve)    Bis1  = Handle(Bisector_Curve)::DownCast( C1.Value()->BasisCurve()); 
102   Handle(Bisector_Curve)    Bis2  = Handle(Bisector_Curve)::DownCast( C2.Value()->BasisCurve());
103
104   Handle(Geom2d_Curve)*  SBis1 = new Handle(Geom2d_Curve) [Bis1->NbIntervals()+1];
105   Handle(Geom2d_Curve)*  SBis2 = new Handle(Geom2d_Curve) [Bis2->NbIntervals()+1];
106   IntRes2d_Domain*       SD1   = new IntRes2d_Domain [Bis1->NbIntervals()+1];
107   IntRes2d_Domain*       SD2   = new IntRes2d_Domain [Bis2->NbIntervals()+1];
108
109   Standard_Integer NB1 = 0; Standard_Integer NB2 = 0;
110   Standard_Real    MinDomain,MaxDomain;
111   Standard_Real    UMin,UMax;
112   gp_Pnt2d         PMin,PMax;
113
114   //------------------------------------------------------
115   // Return Min Max domain1.
116   //------------------------------------------------------
117   if (D1.HasFirstPoint()) {MinDomain = D1.FirstParameter();}
118   else                    {MinDomain = RealFirst();        }
119
120   if (D1.HasLastPoint())  {MaxDomain = D1.LastParameter();}
121   else                    {MaxDomain = RealLast();        }
122
123   //----------------------------------------------------------
124   // Cutting the first curve by the intervals of
125   // continuity taking account of D1
126   //----------------------------------------------------------
127 //for (Standard_Integer IB1 = 1; IB1 <= Bis1->NbIntervals(); IB1++) {
128   Standard_Integer IB1;
129   for ( IB1 = 1; IB1 <= Bis1->NbIntervals(); IB1++) {
130     UMin = Bis1->IntervalFirst(IB1);
131     UMax = Bis1->IntervalLast (IB1);
132     if (UMax > MinDomain && UMin < MaxDomain) {
133       UMin = Max (UMin,MinDomain);
134       UMax = Min (UMax,MaxDomain);
135       PMin = Bis1->Value(UMin);
136       PMax = Bis1->Value(UMax);
137       SD1 [IB1].SetValues(PMin,UMin,D1.FirstTolerance(),
138                           PMax,UMax,D1.LastTolerance());
139
140       if ((IB1 == 1                   && Bis1->IsExtendAtStart()) || 
141           (IB1 == Bis1->NbIntervals() && Bis1->IsExtendAtEnd())    ){
142         //--------------------------------------------------------
143         // Part corresponding to an extension is a segment.     
144         //--------------------------------------------------------
145         SBis1 [IB1] = ConstructSegment (PMin,PMax,UMin,UMax);
146       }
147       else {
148         SBis1 [IB1] = Bis1;
149       }
150       NB1++;
151     }
152   }
153
154   //------------------------------------------------------
155   // Return Min Max domain2.
156   //------------------------------------------------------
157   if (D2.HasFirstPoint()) {MinDomain = D2.FirstParameter();}
158   else                    {MinDomain = RealFirst();        }
159
160   if (D2.HasLastPoint())  {MaxDomain = D2.LastParameter();}
161   else                    {MaxDomain = RealLast();        }
162
163   //----------------------------------------------------------
164   // Cut the second curve following the intervals of
165   // continuity taking account of D2
166   //----------------------------------------------------------
167 //for (Standard_Integer IB2 = 1; IB2 <= Bis2->NbIntervals(); IB2++) {
168   Standard_Integer IB2;
169   for ( IB2 = 1; IB2 <= Bis2->NbIntervals(); IB2++) {
170     UMin = Bis2->IntervalFirst(IB2);
171     UMax = Bis2->IntervalLast  (IB2);
172     if (UMax > MinDomain && UMin < MaxDomain) {
173       UMin = Max (UMin,MinDomain);
174       UMax = Min (UMax,MaxDomain);
175       PMin = Bis2->Value(UMin);
176       PMax = Bis2->Value(UMax);
177       SD2 [IB2].SetValues(PMin,UMin,D2.FirstTolerance(),
178                           PMax,UMax,D2.LastTolerance());
179
180       if ((IB2 == 1                   && Bis2->IsExtendAtStart()) || 
181                (IB2 == Bis1->NbIntervals() && Bis2->IsExtendAtEnd())    ){
182           //--------------------------------------------------------
183           // Part corresponding to an extension is a segment.   
184           //--------------------------------------------------------
185         SBis2 [IB2] = ConstructSegment (PMin,PMax,UMin,UMax);
186       }
187       else {
188               SBis2 [IB2] = Bis2;
189       }
190       NB2++;
191     }
192   }
193
194   //--------------------------------------------------------------
195   // Loop on the intersections of parts of each curve.
196   //--------------------------------------------------------------
197   for ( IB1 = 1; IB1 <= NB1; IB1++) {
198     for ( IB2 = 1; IB2 <= NB2; IB2++) {
199       SinglePerform(SBis1[IB1],SD1[IB1],
200                     SBis2[IB2],SD2[IB2],TolConf,Tol,ComunElement);
201     }
202   }
203   delete [] SBis1;
204   delete [] SBis2;
205   delete [] SD1;
206   delete [] SD2;
207 }
208
209 //===================================================================================
210 // function : SinglePerform
211 // putpose  :
212 //===================================================================================
213 void Bisector_Inter::SinglePerform(const Handle(Geom2d_Curve)&    CBis1,
214                                    const IntRes2d_Domain&         D1, 
215                                    const Handle(Geom2d_Curve)&    CBis2,
216                                    const IntRes2d_Domain&         D2,
217                                    const Standard_Real            TolConf,
218                                    const Standard_Real            Tol,
219                                    const Standard_Boolean         ComunElement) 
220 {
221   Handle(Geom2d_Curve)   Bis1 = CBis1;
222   Handle(Geom2d_Curve)   Bis2 = CBis2;
223
224   Handle(Standard_Type)  Type1 = Bis1->DynamicType();
225   Handle(Standard_Type)  Type2 = Bis2->DynamicType();
226
227   if (Type1 == STANDARD_TYPE(Bisector_BisecAna) || Type2 ==  STANDARD_TYPE(Bisector_BisecAna)) {      
228     Handle(Geom2d_Curve) C2Bis1,C2Bis2;
229     if (Type1 == STANDARD_TYPE(Bisector_BisecAna)) {
230       C2Bis1 = Handle(Bisector_BisecAna)::DownCast(Bis1)->Geom2dCurve();
231     }
232     else {
233       C2Bis1 = Bis1;
234     }
235     if (Type2 == STANDARD_TYPE(Bisector_BisecAna)) {
236       C2Bis2 = Handle(Bisector_BisecAna)::DownCast(Bis2)->Geom2dCurve();
237     }   
238     else {
239       C2Bis2 = Bis2;
240     }
241     Type1 = C2Bis1->DynamicType();
242     Type2 = C2Bis2->DynamicType();
243     if (Type1 == STANDARD_TYPE(Geom2d_Line) && Type2 != STANDARD_TYPE(Geom2d_Line)) {
244       TestBound(Handle(Geom2d_Line)::DownCast(C2Bis1),
245                 D1,C2Bis2,D2,TolConf,Standard_False);
246     }
247     else if (Type2 == STANDARD_TYPE(Geom2d_Line)&& Type1 != STANDARD_TYPE(Geom2d_Line)) {
248       TestBound(Handle(Geom2d_Line)::DownCast(C2Bis2),
249                 D2,C2Bis1,D1,TolConf,Standard_True);
250     }
251     Geom2dInt_GInter Intersect;
252     Geom2dAdaptor_Curve AC2Bis1(C2Bis1);
253     Geom2dAdaptor_Curve AC2Bis2(C2Bis2);
254     Intersect.Perform(AC2Bis1,D1,AC2Bis2,D2,TolConf,Tol);
255     Append (Intersect,D1.FirstParameter(),D1.LastParameter(),
256                       D2.FirstParameter(),D2.LastParameter());
257   }
258   else if (Type1 == STANDARD_TYPE(Bisector_BisecPC) || Type2 == STANDARD_TYPE(Bisector_BisecPC)) {
259     Geom2dInt_GInter Intersect;
260     Geom2dAdaptor_Curve ABis1(Bis1);
261     Geom2dAdaptor_Curve ABis2(Bis2);
262     Intersect.Perform(ABis1,D1,ABis2,D2,TolConf,Tol);
263     Append (Intersect,D1.FirstParameter(),D1.LastParameter(),
264                       D2.FirstParameter(),D2.LastParameter());
265   }
266   else if (ComunElement &&
267            Type1 == STANDARD_TYPE(Bisector_BisecCC) &&  Type2 == STANDARD_TYPE(Bisector_BisecCC)) {
268     NeighbourPerform(Handle(Bisector_BisecCC)::DownCast(Bis1),D1,
269                      Handle(Bisector_BisecCC)::DownCast(Bis2),D2,Tol);
270   }
271   else {
272     // If we are here one of two bissectrices is a segment.
273     // If one of bissectrices is not a segment, it is tested if 
274     // its extremities are on the straight line.
275
276     if (Type1 == STANDARD_TYPE(Geom2d_Line) && Type2 != STANDARD_TYPE(Geom2d_Line)) {
277       TestBound(Handle(Geom2d_Line)::DownCast(Bis1),
278                                    D1,Bis2,D2,TolConf,Standard_False);
279     }
280     else if (Type2 == STANDARD_TYPE(Geom2d_Line)&& Type1 != STANDARD_TYPE(Geom2d_Line)) {
281       TestBound(Handle(Geom2d_Line)::DownCast(Bis2),
282                                    D2,Bis1,D1,TolConf,Standard_True);
283     }
284     Geom2dInt_GInter Intersect;
285     Geom2dAdaptor_Curve ABis1(Bis1);
286     Geom2dAdaptor_Curve ABis2(Bis2);
287     Intersect.Perform(ABis1,D1,ABis2,D2,TolConf,Tol);
288     Append (Intersect,D1.FirstParameter(),D1.LastParameter(),
289                       D2.FirstParameter(),D2.LastParameter());
290   }
291
292 #ifdef DRAW
293   if (Affich) {
294     sprintf( name, "i1_%d", ++nbint);
295     DrawTrSurf::Set(name, Bis1);
296     sprintf( name, "i2_%d", nbint);
297     DrawTrSurf::Set(name, Bis2);
298    if (IsDone() && !IsEmpty()) {
299       for (Standard_Integer k = 1; k <= NbPoints(); k++) {
300               gp_Pnt2d P =  Point(k).Value();
301         sprintf( name, "ip_%d_%d", nbint, k);
302               DrawTrSurf::Set(name, P); 
303       }
304     }
305   }
306 #endif  
307 }
308
309 //===================================================================================
310 // function : NeighbourPerform
311 // putpose  : Find the intersection of 2 neighbor bissectrices curve/curve
312 //            (ie Bis1 separates A and B and Bis2 separates B and C).
313 //            Bis1 is parameterized by B and Bis2 by C.
314 //
315 //            Method : Bis2 is parameterized by B 
316 //            2 bissectrices are thus parameterized by the same curve.
317 //            Let D1(u) = d(Bis1(u),B(u)) and D2(U) = d(Bis2(u),B(U))
318 //            Parameter U0 for which D1(U0)-D2(U0) = 0 is found.
319 //===================================================================================
320 void Bisector_Inter::NeighbourPerform(const Handle(Bisector_BisecCC)&  Bis1,
321                                       const IntRes2d_Domain&           D1, 
322                                       const Handle(Bisector_BisecCC)&  Bis2,
323                                       const IntRes2d_Domain&           D2,
324                                       const Standard_Real              Tol)
325 {
326   Standard_Real USol,U1,U2,Dist;
327   Standard_Real UMin =0.,UMax =0.;  
328   Standard_Real Eps = Precision::PConfusion();
329   gp_Pnt2d PSol;
330   
331   Handle(Geom2d_Curve)     Guide;
332   Handle(Bisector_BisecCC) BisTemp;
333
334   // Change guiedline on Bis2.
335   BisTemp      = Bis2->ChangeGuide();
336   Guide        = Bis2->Curve(2);
337 #ifdef OCCT_DEBUG
338   gp_Pnt2d P2S = Bis2->ValueAndDist(D2.FirstParameter(),U1,UMax,Dist);
339   gp_Pnt2d P2E = Bis2->ValueAndDist(D2.LastParameter() ,U1,UMin,Dist);
340 #else
341   Bis2->ValueAndDist(D2.FirstParameter(),U1,UMax,Dist);
342   Bis2->ValueAndDist(D2.LastParameter() ,U1,UMin,Dist);
343 #endif
344   // Calculate the domain of intersection on the guideline.
345   UMin = Max (D1.FirstParameter(),UMin);
346   UMax = Min (D1.LastParameter() ,UMax);
347
348   done = Standard_True;
349
350   if (UMin - Eps > UMax + Eps) {return;}
351
352   // Solution F = 0 to find the common point.
353   Bisector_FunctionInter Fint(Guide,Bis1,BisTemp);
354
355   math_BissecNewton aSolution(Tol);
356   aSolution.Perform(Fint, UMin, UMax, 20);
357
358   if (aSolution.IsDone())
359     USol = aSolution.Root();
360   else return;
361
362   PSol    = BisTemp ->ValueAndDist(USol,U1,U2,Dist);
363   
364   IntRes2d_Transition        Trans1,Trans2;
365   IntRes2d_IntersectionPoint PointInterSol(PSol,USol,U2,
366                                            Trans1,Trans2,Standard_False);
367   Append (PointInterSol);
368 }
369
370
371
372 //=====================================================================================
373 // function : TestBound
374 // putpose  : Test if the extremities of Bis2 are on the segment cooresponding to Bis1.
375 //=====================================================================================
376 void Bisector_Inter::TestBound (const Handle(Geom2d_Line)&   Bis1,
377                                 const IntRes2d_Domain&       D1,
378                                 const Handle(Geom2d_Curve)&  Bis2,
379                                 const IntRes2d_Domain&       D2,
380                                 const Standard_Real          TolConf,
381                                 const Standard_Boolean       Reverse)
382 {
383   IntRes2d_Transition Trans1,Trans2;
384   IntRes2d_IntersectionPoint PointInterSol;
385
386   gp_Lin2d L1       = Bis1->Lin2d();
387   gp_Pnt2d PF       = Bis2->Value(D2.FirstParameter());
388   gp_Pnt2d PL       = Bis2->Value(D2.LastParameter());
389 //  Modified by skv - Mon May  5 14:43:28 2003 OCC616 Begin
390 //   Standard_Real Tol = Min(TolConf,Precision::Confusion());
391 //   Tol = 10*Tol;
392   Standard_Real Tol = TolConf;
393 //  Modified by skv - Mon May  5 14:43:30 2003 OCC616 End
394
395   Standard_Boolean BisecAlgo = Standard_False;
396   if (Bis2->DynamicType() == STANDARD_TYPE(Bisector_BisecCC))
397     {
398       BisecAlgo = Standard_True;
399 //  Modified by skv - Mon May  5 14:43:45 2003 OCC616 Begin
400 //       Tol = 1.e-5;
401 //  Modified by skv - Mon May  5 14:43:46 2003 OCC616 End
402     }
403
404   if (L1.Distance(PF) < Tol) {
405     Standard_Real U1 = ElCLib::Parameter(L1,PF);
406 //  Modified by skv - Mon May  5 14:48:12 2003 OCC616 Begin
407 //     if ( D1.FirstParameter() - Tol <= U1 &&
408 //       D1.LastParameter () + Tol >= U1   ) {
409     if ( D1.FirstParameter() - D1.FirstTolerance() < U1 &&
410          D1.LastParameter () + D1.LastTolerance()  > U1   ) {
411 //  Modified by skv - Mon May  5 14:48:14 2003 OCC616 End
412       // PF est sur L1
413       if (BisecAlgo)
414         PF = ElCLib::Value( U1 , L1 );
415       PointInterSol.SetValues (PF, U1, D2.FirstParameter(), 
416                                Trans1, Trans2, Reverse);
417       Append (PointInterSol);
418     }
419   }  
420
421   if (L1.Distance(PL) < Tol) {
422     Standard_Real U1 = ElCLib::Parameter(L1,PL);
423 //  Modified by skv - Mon May  5 15:05:48 2003 OCC616 Begin
424 //     if ( D1.FirstParameter() - Tol <= U1 &&
425 //       D1.LastParameter () + Tol >= U1   ) {
426     if ( D1.FirstParameter() - D1.FirstTolerance() < U1 &&
427          D1.LastParameter () + D1.LastTolerance()  > U1   ) {
428 //  Modified by skv - Mon May  5 15:05:49 2003 OCC616 End
429       if (BisecAlgo)
430         PL = ElCLib::Value( U1 , L1 );
431       PointInterSol.SetValues (PL, U1, D2.LastParameter(), 
432                                Trans1, Trans2, Reverse);
433       Append (PointInterSol);
434     }
435   }     
436 }