b311480e |
1 | // Copyright (c) 1995-1999 Matra Datavision |
2 | // Copyright (c) 1999-2012 OPEN CASCADE SAS |
3 | // |
4 | // The content of this file is subject to the Open CASCADE Technology Public |
5 | // License Version 6.5 (the "License"). You may not use the content of this file |
6 | // except in compliance with the License. Please obtain a copy of the License |
7 | // at http://www.opencascade.org and read it completely before using this file. |
8 | // |
9 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
10 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
11 | // |
12 | // The Original Code and all software distributed under the License is |
13 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
14 | // Initial Developer hereby disclaims all such warranties, including without |
15 | // limitation, any warranties of merchantability, fitness for a particular |
16 | // purpose or non-infringement. Please see the License for the specific terms |
17 | // and conditions governing the rights and limitations under the License. |
18 | |
7fd59977 |
19 | // Great zoom leads to non-coincidence of |
20 | // a point and non-infinite lines passing throught this point: |
21 | #define OCC64 |
22 | |
23 | #include <StdPrs_DeflectionCurve.ixx> |
24 | |
b8ddfc2f |
25 | #include <Graphic3d_ArrayOfSegments.hxx> |
26 | #include <Graphic3d_ArrayOfPolylines.hxx> |
7fd59977 |
27 | #include <Graphic3d_Group.hxx> |
28 | #include <Prs3d_LineAspect.hxx> |
29 | #include <Prs3d_Arrow.hxx> |
30 | #include <Prs3d_ArrowAspect.hxx> |
31 | #include <gp_Pnt.hxx> |
32 | #include <gp_Circ.hxx> |
33 | #include <gp_Dir.hxx> |
34 | #include <gp_Vec.hxx> |
35 | #include <Prs3d.hxx> |
36 | #include <Bnd_Box.hxx> |
37 | #include <BndLib_Add3dCurve.hxx> |
38 | #include <Precision.hxx> |
39 | #include <GCPnts_QuasiUniformDeflection.hxx> |
40 | #include <GCPnts_TangentialDeflection.hxx> |
41 | #include <TColgp_SequenceOfPnt.hxx> |
42 | #include <TColStd_Array1OfReal.hxx> |
43 | |
44 | |
45 | //================================================================== |
46 | // function: GetDeflection |
47 | // purpose: |
48 | //================================================================== |
49 | static Standard_Real GetDeflection(const Adaptor3d_Curve& aCurve, |
b8ddfc2f |
50 | const Standard_Real U1, |
51 | const Standard_Real U2, |
52 | const Handle(Prs3d_Drawer)& aDrawer) |
53 | { |
54 | Standard_Real TheDeflection; |
55 | |
56 | if (aDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE) |
57 | { |
58 | // On calcule la fleche en fonction des min max globaux de la piece: |
59 | Bnd_Box Total; |
60 | BndLib_Add3dCurve::Add(aCurve, U1, U2, 0.,Total); |
61 | Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; |
62 | Total.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); |
63 | Standard_Real m = RealLast(); |
64 | if ( ! (Total.IsOpenXmin() || Total.IsOpenXmax() )) |
65 | m = Abs (aXmax-aXmin); |
66 | if ( ! (Total.IsOpenYmin() || Total.IsOpenYmax() )) |
67 | m = Max ( m , Abs (aYmax-aYmin)); |
68 | if ( ! (Total.IsOpenZmin() || Total.IsOpenZmax() )) |
69 | m = Max ( m , Abs (aZmax-aZmin)); |
7fd59977 |
70 | |
b8ddfc2f |
71 | m = Min ( m , aDrawer->MaximalParameterValue()); |
72 | m = Max(m, Precision::Confusion()); |
7fd59977 |
73 | |
b8ddfc2f |
74 | TheDeflection = m * aDrawer->DeviationCoefficient(); |
7fd59977 |
75 | } |
b8ddfc2f |
76 | else |
77 | TheDeflection = aDrawer->MaximalChordialDeviation(); |
78 | |
79 | return TheDeflection; |
80 | } |
7fd59977 |
81 | |
82 | //================================================================== |
83 | // function: FindLimits |
84 | // purpose: |
85 | //================================================================== |
b8ddfc2f |
86 | static Standard_Boolean FindLimits(const Adaptor3d_Curve& aCurve, |
87 | const Standard_Real aLimit, |
88 | Standard_Real& First, |
89 | Standard_Real& Last) |
7fd59977 |
90 | { |
91 | First = aCurve.FirstParameter(); |
92 | Last = aCurve.LastParameter(); |
93 | Standard_Boolean firstInf = Precision::IsNegativeInfinite(First); |
94 | Standard_Boolean lastInf = Precision::IsPositiveInfinite(Last); |
95 | |
96 | if (firstInf || lastInf) { |
97 | gp_Pnt P1,P2; |
98 | Standard_Real delta = 1; |
99 | Standard_Integer count = 0; |
100 | if (firstInf && lastInf) { |
101 | do { |
b8ddfc2f |
102 | if (count++ == 100000) return Standard_False; |
103 | delta *= 2; |
104 | First = - delta; |
105 | Last = delta; |
106 | aCurve.D0(First,P1); |
107 | aCurve.D0(Last,P2); |
7fd59977 |
108 | } while (P1.Distance(P2) < aLimit); |
109 | } |
110 | else if (firstInf) { |
111 | aCurve.D0(Last,P2); |
112 | do { |
b8ddfc2f |
113 | if (count++ == 100000) return Standard_False; |
114 | delta *= 2; |
115 | First = Last - delta; |
116 | aCurve.D0(First,P1); |
7fd59977 |
117 | } while (P1.Distance(P2) < aLimit); |
118 | } |
119 | else if (lastInf) { |
120 | aCurve.D0(First,P1); |
121 | do { |
b8ddfc2f |
122 | if (count++ == 100000) return Standard_False; |
123 | delta *= 2; |
124 | Last = First + delta; |
125 | aCurve.D0(Last,P2); |
7fd59977 |
126 | } while (P1.Distance(P2) < aLimit); |
127 | } |
128 | } |
129 | return Standard_True; |
130 | } |
131 | |
132 | |
7fd59977 |
133 | //================================================================== |
134 | // function: DrawCurve |
135 | // purpose: |
136 | //================================================================== |
b8ddfc2f |
137 | static void DrawCurve (Adaptor3d_Curve& aCurve, |
7fd59977 |
138 | const Handle(Graphic3d_Group) aGroup, |
139 | const Quantity_Length TheDeflection, |
b8ddfc2f |
140 | const Standard_Real anAngle, |
7fd59977 |
141 | const Standard_Real U1, |
142 | const Standard_Real U2, |
b8ddfc2f |
143 | TColgp_SequenceOfPnt& Points, |
144 | const Standard_Boolean drawCurve) |
7fd59977 |
145 | { |
b8ddfc2f |
146 | switch (aCurve.GetType()) |
147 | { |
148 | case GeomAbs_Line: |
7fd59977 |
149 | { |
b8ddfc2f |
150 | gp_Pnt p1 = aCurve.Value(U1); |
151 | gp_Pnt p2 = aCurve.Value(U2); |
152 | Points.Append(p1); |
153 | Points.Append(p2); |
154 | if(drawCurve) |
155 | { |
156 | Handle(Graphic3d_ArrayOfSegments) aPrims = new Graphic3d_ArrayOfSegments(2); |
157 | aPrims->AddVertex(p1); |
158 | aPrims->AddVertex(p2); |
159 | aGroup->AddPrimitiveArray(aPrims); |
160 | } |
161 | break; |
162 | } |
163 | default: |
7fd59977 |
164 | { |
b8ddfc2f |
165 | const Standard_Integer nbinter = aCurve.NbIntervals(GeomAbs_C1); |
7fd59977 |
166 | TColStd_Array1OfReal T(1, nbinter+1); |
167 | aCurve.Intervals(T, GeomAbs_C1); |
b8ddfc2f |
168 | |
7fd59977 |
169 | Standard_Real theU1, theU2; |
b8ddfc2f |
170 | Standard_Integer NumberOfPoints, i, j; |
7fd59977 |
171 | TColgp_SequenceOfPnt SeqP; |
172 | |
173 | for (j = 1; j <= nbinter; j++) { |
b8ddfc2f |
174 | theU1 = T(j); theU2 = T(j+1); |
175 | if (theU2 > U1 && theU1 < U2) { |
176 | theU1 = Max(theU1, U1); |
177 | theU2 = Min(theU2, U2); |
7fd59977 |
178 | |
b8ddfc2f |
179 | GCPnts_TangentialDeflection Algo(aCurve, theU1, theU2, anAngle, TheDeflection); |
180 | NumberOfPoints = Algo.NbPoints(); |
181 | |
182 | if (NumberOfPoints > 0) { |
183 | for (i=1;i<NumberOfPoints;i++) { |
184 | SeqP.Append(Algo.Value(i)); |
185 | } |
186 | if (j == nbinter) { |
187 | SeqP.Append(Algo.Value(NumberOfPoints)); |
188 | } |
189 | } |
190 | } |
7fd59977 |
191 | } |
192 | |
b8ddfc2f |
193 | Handle(Graphic3d_ArrayOfPolylines) aPrims; |
194 | if(drawCurve) |
195 | aPrims = new Graphic3d_ArrayOfPolylines(SeqP.Length()); |
7fd59977 |
196 | |
7fd59977 |
197 | for (i = 1; i <= SeqP.Length(); i++) { |
b8ddfc2f |
198 | const gp_Pnt& p = SeqP.Value(i); |
199 | Points.Append(p); |
200 | if(drawCurve) |
201 | aPrims->AddVertex(p); |
7fd59977 |
202 | } |
b8ddfc2f |
203 | if(drawCurve) |
204 | aGroup->AddPrimitiveArray(aPrims); |
7fd59977 |
205 | } |
206 | } |
7fd59977 |
207 | } |
208 | |
209 | |
210 | //================================================================== |
211 | // function: MatchCurve |
212 | // purpose: |
213 | //================================================================== |
214 | static Standard_Boolean MatchCurve ( |
215 | const Quantity_Length X, |
216 | const Quantity_Length Y, |
217 | const Quantity_Length Z, |
218 | const Quantity_Length aDistance, |
219 | const Adaptor3d_Curve& aCurve, |
b8ddfc2f |
220 | const Quantity_Length TheDeflection, |
7fd59977 |
221 | const Standard_Real anAngle, |
b8ddfc2f |
222 | const Standard_Real U1, |
223 | const Standard_Real U2) |
7fd59977 |
224 | { |
225 | Quantity_Length retdist; |
b8ddfc2f |
226 | switch (aCurve.GetType()) |
227 | { |
228 | case GeomAbs_Line: |
7fd59977 |
229 | { |
b8ddfc2f |
230 | gp_Pnt p1 = aCurve.Value(U1); |
231 | if ( Abs(X-p1.X()) + Abs(Y-p1.Y()) + Abs(Z-p1.Z()) <= aDistance) |
232 | return Standard_True; |
233 | gp_Pnt p2 = aCurve.Value(U2); |
234 | if ( Abs(X-p2.X()) + Abs(Y-p2.Y()) + Abs(Z-p2.Z()) <= aDistance) |
235 | return Standard_True; |
236 | return Prs3d::MatchSegment(X,Y,Z,aDistance,p1,p2,retdist); |
237 | } |
238 | case GeomAbs_Circle: |
7fd59977 |
239 | { |
b8ddfc2f |
240 | const Standard_Real Radius = aCurve.Circle().Radius(); |
7fd59977 |
241 | if (!Precision::IsInfinite(Radius)) { |
b8ddfc2f |
242 | const Standard_Real DU = Sqrt(8.0 * TheDeflection / Radius); |
243 | const Standard_Real Er = Abs( U2 - U1) / DU; |
244 | const Standard_Integer N = Max(2, (Standard_Integer)IntegerPart(Er)); |
245 | if ( N > 0) { |
246 | gp_Pnt p1,p2; |
247 | for (Standard_Integer Index = 1; Index <= N+1; Index++) { |
248 | p2 = aCurve.Value(U1 + (Index - 1) * DU); |
249 | if ( Abs(X-p2.X()) + Abs(Y-p2.Y()) + Abs(Z-p2.Z()) <= aDistance) |
250 | return Standard_True; |
251 | |
252 | if (Index>1) { |
253 | if (Prs3d::MatchSegment(X,Y,Z,aDistance,p1,p2,retdist)) |
254 | return Standard_True; |
255 | } |
256 | p1=p2; |
257 | } |
258 | } |
7fd59977 |
259 | } |
b8ddfc2f |
260 | break; |
261 | } |
262 | default: |
7fd59977 |
263 | { |
264 | GCPnts_TangentialDeflection Algo(aCurve,U1, U2, anAngle, TheDeflection); |
b8ddfc2f |
265 | const Standard_Integer NumberOfPoints = Algo.NbPoints(); |
7fd59977 |
266 | if (NumberOfPoints > 0) { |
b8ddfc2f |
267 | gp_Pnt p1,p2; |
268 | for (Standard_Integer i=1;i<=NumberOfPoints;i++) { |
269 | p2 = Algo.Value(i); |
270 | if ( Abs(X-p2.X()) + Abs(Y-p2.Y()) + Abs(Z-p2.Z()) <= aDistance) |
271 | return Standard_True; |
272 | if (i>1) { |
273 | if (Prs3d::MatchSegment(X,Y,Z,aDistance,p1,p2,retdist)) |
274 | return Standard_True; |
275 | } |
276 | p1=p2; |
277 | } |
7fd59977 |
278 | } |
7fd59977 |
279 | } |
280 | } |
281 | return Standard_False; |
282 | } |
283 | |
284 | |
285 | //================================================================== |
286 | // function: Add |
287 | // purpose: |
288 | //================================================================== |
289 | void StdPrs_DeflectionCurve::Add (const Handle (Prs3d_Presentation)& aPresentation, |
b8ddfc2f |
290 | Adaptor3d_Curve& aCurve, |
291 | const Handle (Prs3d_Drawer)& aDrawer, |
292 | const Standard_Boolean drawCurve) |
293 | { |
7fd59977 |
294 | Prs3d_Root::CurrentGroup(aPresentation)->SetPrimitivesAspect(aDrawer->LineAspect()->Aspect()); |
295 | |
b8ddfc2f |
296 | Standard_Real V1, V2; |
297 | if (FindLimits(aCurve, aDrawer->MaximalParameterValue(), V1, V2)) |
298 | { |
299 | TColgp_SequenceOfPnt Points; |
7fd59977 |
300 | DrawCurve(aCurve, |
b8ddfc2f |
301 | Prs3d_Root::CurrentGroup(aPresentation), |
302 | GetDeflection(aCurve, V1, V2, aDrawer), |
303 | aDrawer->DeviationAngle(), |
304 | V1, V2, Points, drawCurve); |
305 | |
7fd59977 |
306 | if (aDrawer->LineArrowDraw()) { |
307 | gp_Pnt Location; |
308 | gp_Vec Direction; |
309 | aCurve.D1(V2, Location,Direction); |
310 | Prs3d_Arrow::Draw (aPresentation, |
b8ddfc2f |
311 | Location, |
312 | gp_Dir(Direction), |
313 | aDrawer->ArrowAspect()->Angle(), |
314 | aDrawer->ArrowAspect()->Length()); |
7fd59977 |
315 | } |
316 | } |
317 | } |
318 | |
319 | |
320 | //================================================================== |
321 | // function: Add |
322 | // purpose: |
323 | //================================================================== |
324 | void StdPrs_DeflectionCurve::Add (const Handle (Prs3d_Presentation)& aPresentation, |
b8ddfc2f |
325 | Adaptor3d_Curve& aCurve, |
326 | const Standard_Real U1, |
327 | const Standard_Real U2, |
328 | const Handle (Prs3d_Drawer)& aDrawer, |
329 | const Standard_Boolean drawCurve) |
330 | { |
7fd59977 |
331 | Prs3d_Root::CurrentGroup(aPresentation)->SetPrimitivesAspect(aDrawer->LineAspect()->Aspect()); |
332 | |
333 | Standard_Real V1 = U1; |
334 | Standard_Real V2 = U2; |
335 | |
7fd59977 |
336 | if (Precision::IsNegativeInfinite(V1)) V1 = -aDrawer->MaximalParameterValue(); |
337 | if (Precision::IsPositiveInfinite(V2)) V2 = aDrawer->MaximalParameterValue(); |
338 | |
7fd59977 |
339 | TColgp_SequenceOfPnt Points; |
340 | DrawCurve(aCurve, |
b8ddfc2f |
341 | Prs3d_Root::CurrentGroup(aPresentation), |
342 | GetDeflection(aCurve, V1, V2, aDrawer), |
343 | aDrawer->DeviationAngle(), |
344 | V1 , V2, Points, drawCurve); |
7fd59977 |
345 | |
346 | if (aDrawer->LineArrowDraw()) { |
347 | gp_Pnt Location; |
348 | gp_Vec Direction; |
349 | aCurve.D1(V2, Location,Direction); |
350 | Prs3d_Arrow::Draw (aPresentation, |
b8ddfc2f |
351 | Location, |
352 | gp_Dir(Direction), |
353 | aDrawer->ArrowAspect()->Angle(), |
354 | aDrawer->ArrowAspect()->Length()); |
7fd59977 |
355 | } |
356 | } |
357 | |
358 | //================================================================== |
359 | // function: Add |
360 | // purpose: |
361 | //================================================================== |
362 | void StdPrs_DeflectionCurve::Add (const Handle (Prs3d_Presentation)& aPresentation, |
b8ddfc2f |
363 | Adaptor3d_Curve& aCurve, |
364 | const Standard_Real U1, |
365 | const Standard_Real U2, |
366 | const Standard_Real aDeflection, |
367 | TColgp_SequenceOfPnt& Points, |
368 | const Standard_Real anAngle, |
369 | const Standard_Boolean drawCurve) |
7fd59977 |
370 | { |
371 | DrawCurve(aCurve, Prs3d_Root::CurrentGroup(aPresentation), |
372 | aDeflection, anAngle, U1, U2, Points, drawCurve); |
373 | } |
374 | |
7fd59977 |
375 | //================================================================== |
376 | // function: Add |
377 | // purpose: |
378 | //================================================================== |
379 | void StdPrs_DeflectionCurve::Add (const Handle (Prs3d_Presentation)& aPresentation, |
b8ddfc2f |
380 | Adaptor3d_Curve& aCurve, |
381 | const Standard_Real aDeflection, |
382 | const Standard_Real aLimit, |
383 | const Standard_Real anAngle, |
384 | const Standard_Boolean drawCurve) |
7fd59977 |
385 | { |
386 | Standard_Real V1, V2; |
b8ddfc2f |
387 | if (FindLimits(aCurve, aLimit, V1, V2)) |
388 | { |
389 | TColgp_SequenceOfPnt Points; |
390 | DrawCurve(aCurve, Prs3d_Root::CurrentGroup(aPresentation), |
391 | aDeflection, anAngle, V1, V2, Points, drawCurve); |
392 | } |
7fd59977 |
393 | } |
394 | |
395 | |
396 | //================================================================================ |
397 | // function: Add |
398 | // purpose: |
399 | //================================================================================ |
400 | void StdPrs_DeflectionCurve::Add (const Handle (Prs3d_Presentation)& aPresentation, |
b8ddfc2f |
401 | Adaptor3d_Curve& aCurve, |
402 | const Standard_Real aDeflection, |
403 | const Handle(Prs3d_Drawer)& aDrawer, |
404 | TColgp_SequenceOfPnt& Points, |
405 | const Standard_Boolean drawCurve) |
7fd59977 |
406 | { |
7fd59977 |
407 | Standard_Real V1, V2; |
b8ddfc2f |
408 | if (FindLimits(aCurve, aDrawer->MaximalParameterValue(), V1, V2)) |
409 | DrawCurve(aCurve, Prs3d_Root::CurrentGroup(aPresentation), |
410 | aDeflection, aDrawer->DeviationAngle(), V1, V2, Points, drawCurve); |
7fd59977 |
411 | } |
412 | |
413 | |
414 | //================================================================== |
415 | // function: Match |
416 | // purpose: |
417 | //================================================================== |
418 | Standard_Boolean StdPrs_DeflectionCurve::Match |
419 | (const Quantity_Length X, |
420 | const Quantity_Length Y, |
421 | const Quantity_Length Z, |
422 | const Quantity_Length aDistance, |
423 | const Adaptor3d_Curve& aCurve, |
424 | const Handle (Prs3d_Drawer)& aDrawer) |
425 | { |
426 | Standard_Real V1, V2; |
b8ddfc2f |
427 | if (FindLimits(aCurve, aDrawer->MaximalParameterValue(), V1, V2)) |
428 | { |
7fd59977 |
429 | return MatchCurve(X,Y,Z,aDistance,aCurve, |
b8ddfc2f |
430 | GetDeflection(aCurve, V1, V2, aDrawer), |
431 | aDrawer->DeviationAngle(), |
432 | V1, V2); |
7fd59977 |
433 | } |
b8ddfc2f |
434 | return Standard_False; |
7fd59977 |
435 | } |
436 | |
7fd59977 |
437 | //================================================================== |
438 | // function: Match |
439 | // purpose: |
440 | //================================================================== |
441 | Standard_Boolean StdPrs_DeflectionCurve::Match |
442 | (const Quantity_Length X, |
443 | const Quantity_Length Y, |
444 | const Quantity_Length Z, |
445 | const Quantity_Length aDistance, |
446 | const Adaptor3d_Curve& aCurve, |
447 | const Standard_Real U1, |
448 | const Standard_Real U2, |
449 | const Handle (Prs3d_Drawer)& aDrawer) |
450 | { |
451 | Standard_Real V1 = U1; |
b8ddfc2f |
452 | Standard_Real V2 = U2; |
7fd59977 |
453 | |
454 | if (Precision::IsNegativeInfinite(V1)) V1 = -aDrawer->MaximalParameterValue(); |
455 | if (Precision::IsPositiveInfinite(V2)) V2 = aDrawer->MaximalParameterValue(); |
456 | |
457 | return MatchCurve(X,Y,Z,aDistance,aCurve, |
b8ddfc2f |
458 | GetDeflection(aCurve, V1, V2, aDrawer), |
459 | aDrawer->DeviationAngle(), V1, V2); |
7fd59977 |
460 | } |
461 | |
7fd59977 |
462 | //================================================================== |
463 | // function: Match |
464 | // purpose: |
465 | //================================================================== |
466 | Standard_Boolean StdPrs_DeflectionCurve::Match |
467 | (const Quantity_Length X, |
b8ddfc2f |
468 | const Quantity_Length Y, |
469 | const Quantity_Length Z, |
470 | const Quantity_Length aDistance, |
471 | const Adaptor3d_Curve& aCurve, |
472 | const Standard_Real U1, |
473 | const Standard_Real U2, |
474 | const Standard_Real aDeflection, |
475 | const Standard_Real anAngle) |
476 | { |
7fd59977 |
477 | return MatchCurve(X,Y,Z,aDistance,aCurve,aDeflection,anAngle,U1,U2); |
7fd59977 |
478 | } |
479 | |
480 | //================================================================== |
481 | // function: Match |
482 | // purpose: |
483 | //================================================================== |
484 | Standard_Boolean StdPrs_DeflectionCurve::Match |
485 | (const Quantity_Length X, |
486 | const Quantity_Length Y, |
487 | const Quantity_Length Z, |
488 | const Quantity_Length aDistance, |
489 | const Adaptor3d_Curve& aCurve, |
490 | const Standard_Real aDeflection, |
491 | const Standard_Real aLimit, |
b8ddfc2f |
492 | const Standard_Real anAngle) |
493 | { |
7fd59977 |
494 | Standard_Real V1, V2; |
b8ddfc2f |
495 | if (FindLimits(aCurve, aLimit, V1, V2)) |
496 | { |
497 | return MatchCurve(X,Y,Z,aDistance,aCurve,aDeflection,anAngle,V1,V2); |
7fd59977 |
498 | } |
b8ddfc2f |
499 | return Standard_False; |
7fd59977 |
500 | } |