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
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 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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // Modified by skv - Mon May 5 15:06:39 2003 OCC616
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>
38 #include <Draw_Appli.hxx>
39 #include <DrawTrSurf_Curve2d.hxx>
40 #include <Draw_Marker2D.hxx>
41 static Standard_Boolean Affich = Standard_False;
44 //===================================================================================
47 //===================================================================================
48 Bisector_Inter::Bisector_Inter()
52 //===================================================================================
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)
64 Perform (C1,D1,C2,D2,TolConf,Tol,ComunElement);
67 //===================================================================================
68 // function : ConstructSegment
70 //===================================================================================
71 static Handle(Geom2d_Line) ConstructSegment(const gp_Pnt2d& PMin,
73 const Standard_Real UMin,
74 // const Standard_Real UMax)
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);
83 //===================================================================================
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)
95 Handle(Bisector_Curve) Bis1 = Handle(Bisector_Curve)::DownCast( C1.Value()->BasisCurve());
96 Handle(Bisector_Curve) Bis2 = Handle(Bisector_Curve)::DownCast( C2.Value()->BasisCurve());
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];
103 Standard_Integer NB1 = 0; Standard_Integer NB2 = 0;
104 Standard_Real MinDomain,MaxDomain;
105 Standard_Real UMin,UMax;
108 //------------------------------------------------------
109 // Return Min Max domain1.
110 //------------------------------------------------------
111 if (D1.HasFirstPoint()) {MinDomain = D1.FirstParameter();}
112 else {MinDomain = RealFirst(); }
114 if (D1.HasLastPoint()) {MaxDomain = D1.LastParameter();}
115 else {MaxDomain = RealLast(); }
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());
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);
148 //------------------------------------------------------
149 // Return Min Max domain2.
150 //------------------------------------------------------
151 if (D2.HasFirstPoint()) {MinDomain = D2.FirstParameter();}
152 else {MinDomain = RealFirst(); }
154 if (D2.HasLastPoint()) {MaxDomain = D2.LastParameter();}
155 else {MaxDomain = RealLast(); }
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());
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);
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);
203 //===================================================================================
204 // function : SinglePerform
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)
215 Handle(Geom2d_Curve) Bis1 = CBis1;
216 Handle(Geom2d_Curve) Bis2 = CBis2;
218 Handle(Standard_Type) Type1 = Bis1->DynamicType();
219 Handle(Standard_Type) Type2 = Bis2->DynamicType();
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();
229 if (Type2 == STANDARD_TYPE(Bisector_BisecAna)) {
230 C2Bis2 = Handle(Bisector_BisecAna)::DownCast(Bis2)->Geom2dCurve();
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);
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);
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());
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());
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);
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.
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);
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);
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());
288 Handle(DrawTrSurf_Curve2d) dr;
289 Draw_Color Couleur = Draw_bleu;
291 dr = new DrawTrSurf_Curve2d(Bis1,Couleur,100);
293 dr = new DrawTrSurf_Curve2d(Bis2,Couleur,100);
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);
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.
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)
324 Standard_Real USol,U1,U2,Dist;
325 Standard_Real UMin =0.,UMax =0.;
326 Standard_Real Eps = Precision::PConfusion();
329 Handle(Geom2d_Curve) Guide;
330 Handle(Bisector_BisecCC) BisTemp;
332 // Change guiedline on Bis2.
333 BisTemp = Bis2->ChangeGuide();
334 Guide = Bis2->Curve(2);
336 gp_Pnt2d P2S = Bis2->ValueAndDist(D2.FirstParameter(),U1,UMax,Dist);
337 gp_Pnt2d P2E = Bis2->ValueAndDist(D2.LastParameter() ,U1,UMin,Dist);
339 Bis2->ValueAndDist(D2.FirstParameter(),U1,UMax,Dist);
340 Bis2->ValueAndDist(D2.LastParameter() ,U1,UMin,Dist);
342 // Calculate the domain of intersection on the guideline.
343 UMin = Max (D1.FirstParameter(),UMin);
344 UMax = Min (D1.LastParameter() ,UMax);
346 done = Standard_True;
348 if (UMin - Eps > UMax + Eps) {return;}
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);
358 PSol = BisTemp ->ValueAndDist(USol,U1,U2,Dist);
360 IntRes2d_Transition Trans1,Trans2;
361 IntRes2d_IntersectionPoint PointInterSol(PSol,USol,U2,
362 Trans1,Trans2,Standard_False);
363 Append (PointInterSol);
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)
379 IntRes2d_Transition Trans1,Trans2;
380 IntRes2d_IntersectionPoint PointInterSol;
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());
388 Standard_Real Tol = TolConf;
389 // Modified by skv - Mon May 5 14:43:30 2003 OCC616 End
391 Standard_Boolean BisecAlgo = Standard_False;
392 if (Bis2->DynamicType() == STANDARD_TYPE(Bisector_BisecCC))
394 BisecAlgo = Standard_True;
395 // Modified by skv - Mon May 5 14:43:45 2003 OCC616 Begin
397 // Modified by skv - Mon May 5 14:43:46 2003 OCC616 End
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
410 PF = ElCLib::Value( U1 , L1 );
411 PointInterSol.SetValues (PF, U1, D2.FirstParameter(),
412 Trans1, Trans2, Reverse);
413 Append (PointInterSol);
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
426 PL = ElCLib::Value( U1 , L1 );
427 PointInterSol.SetValues (PL, U1, D2.LastParameter(),
428 Trans1, Trans2, Reverse);
429 Append (PointInterSol);