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