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_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>
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>
43 #include <DrawTrSurf.hxx>
44 static char name[100];
45 static Standard_Boolean Affich = Standard_False;
46 static Standard_Integer nbint = 0;
50 //===================================================================================
53 //===================================================================================
54 Bisector_Inter::Bisector_Inter()
58 //===================================================================================
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)
70 Perform (C1,D1,C2,D2,TolConf,Tol,ComunElement);
73 //===================================================================================
74 // function : ConstructSegment
76 //===================================================================================
77 static Handle(Geom2d_Line) ConstructSegment(const gp_Pnt2d& PMin,
79 const Standard_Real UMin,
80 // const Standard_Real UMax)
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);
89 //===================================================================================
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)
101 Handle(Bisector_Curve) Bis1 = Handle(Bisector_Curve)::DownCast( C1.Value()->BasisCurve());
102 Handle(Bisector_Curve) Bis2 = Handle(Bisector_Curve)::DownCast( C2.Value()->BasisCurve());
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];
109 Standard_Integer NB1 = 0; Standard_Integer NB2 = 0;
110 Standard_Real MinDomain,MaxDomain;
111 Standard_Real UMin,UMax;
114 //------------------------------------------------------
115 // Return Min Max domain1.
116 //------------------------------------------------------
117 if (D1.HasFirstPoint()) {MinDomain = D1.FirstParameter();}
118 else {MinDomain = RealFirst(); }
120 if (D1.HasLastPoint()) {MaxDomain = D1.LastParameter();}
121 else {MaxDomain = RealLast(); }
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());
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);
154 //------------------------------------------------------
155 // Return Min Max domain2.
156 //------------------------------------------------------
157 if (D2.HasFirstPoint()) {MinDomain = D2.FirstParameter();}
158 else {MinDomain = RealFirst(); }
160 if (D2.HasLastPoint()) {MaxDomain = D2.LastParameter();}
161 else {MaxDomain = RealLast(); }
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());
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);
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);
209 //===================================================================================
210 // function : SinglePerform
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)
221 Handle(Geom2d_Curve) Bis1 = CBis1;
222 Handle(Geom2d_Curve) Bis2 = CBis2;
224 Handle(Standard_Type) Type1 = Bis1->DynamicType();
225 Handle(Standard_Type) Type2 = Bis2->DynamicType();
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();
235 if (Type2 == STANDARD_TYPE(Bisector_BisecAna)) {
236 C2Bis2 = Handle(Bisector_BisecAna)::DownCast(Bis2)->Geom2dCurve();
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);
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);
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());
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());
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);
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.
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);
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);
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());
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);
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.
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)
326 Standard_Real USol,U1,U2,Dist;
327 Standard_Real UMin =0.,UMax =0.;
328 Standard_Real Eps = Precision::PConfusion();
331 Handle(Geom2d_Curve) Guide;
332 Handle(Bisector_BisecCC) BisTemp;
334 // Change guiedline on Bis2.
335 BisTemp = Bis2->ChangeGuide();
336 Guide = Bis2->Curve(2);
338 // note: returned points are not used in the code, but can be useful for consulting in debugger
339 gp_Pnt2d P2S = Bis2->ValueAndDist(D2.FirstParameter(),U1,UMax,Dist);
340 gp_Pnt2d P2E = Bis2->ValueAndDist(D2.LastParameter() ,U1,UMin,Dist);
344 // Calculate the domain of intersection on the guideline.
345 UMin = Max (D1.FirstParameter(),UMin);
346 UMax = Min (D1.LastParameter() ,UMax);
348 done = Standard_True;
350 if (UMin - Eps > UMax + Eps) {return;}
352 // Solution F = 0 to find the common point.
353 Bisector_FunctionInter Fint(Guide,Bis1,BisTemp);
355 math_BissecNewton aSolution(Tol);
356 aSolution.Perform(Fint, UMin, UMax, 20);
358 if (aSolution.IsDone())
359 USol = aSolution.Root();
362 PSol = BisTemp ->ValueAndDist(USol,U1,U2,Dist);
364 IntRes2d_Transition Trans1,Trans2;
365 IntRes2d_IntersectionPoint PointInterSol(PSol,USol,U2,
366 Trans1,Trans2,Standard_False);
367 Append (PointInterSol);
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)
383 IntRes2d_Transition Trans1,Trans2;
384 IntRes2d_IntersectionPoint PointInterSol;
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());
392 Standard_Real Tol = TolConf;
393 // Modified by skv - Mon May 5 14:43:30 2003 OCC616 End
395 Standard_Boolean BisecAlgo = Standard_False;
396 if (Bis2->DynamicType() == STANDARD_TYPE(Bisector_BisecCC))
398 BisecAlgo = Standard_True;
399 // Modified by skv - Mon May 5 14:43:45 2003 OCC616 Begin
401 // Modified by skv - Mon May 5 14:43:46 2003 OCC616 End
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
414 PF = ElCLib::Value( U1 , L1 );
415 PointInterSol.SetValues (PF, U1, D2.FirstParameter(),
416 Trans1, Trans2, Reverse);
417 Append (PointInterSol);
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
430 PL = ElCLib::Value( U1 , L1 );
431 PointInterSol.SetValues (PL, U1, D2.LastParameter(),
432 Trans1, Trans2, Reverse);
433 Append (PointInterSol);