0027555: Visualization, AIS_Shape - own deviation coefficient change is not considere...
[occt.git] / src / StdPrs / StdPrs_Curve.cxx
1 // Created on: 1995-08-04
2 // Created by: Modelistation
3 // Copyright (c) 1995-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 // Great zoom leads to non-coincidence of
18 // a point and non-infinite lines passing throught this point:
19
20 #include <Adaptor3d_Curve.hxx>
21 #include <Bnd_Box.hxx>
22 #include <gp_Circ.hxx>
23 #include <gp_Dir.hxx>
24 #include <gp_Pnt.hxx>
25 #include <gp_Vec.hxx>
26 #include <Graphic3d_ArrayOfPolylines.hxx>
27 #include <Graphic3d_ArrayOfSegments.hxx>
28 #include <Graphic3d_Group.hxx>
29 #include <Precision.hxx>
30 #include <Prs3d.hxx>
31 #include <Prs3d_Arrow.hxx>
32 #include <Prs3d_ArrowAspect.hxx>
33 #include <Prs3d_LineAspect.hxx>
34 #include <Prs3d_Presentation.hxx>
35 #include <StdPrs_Curve.hxx>
36 #include <TColgp_SequenceOfPnt.hxx>
37
38 //==================================================================
39 // function: FindLimits
40 // purpose:
41 //==================================================================
42 static void FindLimits(const Adaptor3d_Curve& aCurve,
43                        const Standard_Real  aLimit,
44                        Standard_Real&       First,
45                        Standard_Real&       Last)
46 {
47   First = aCurve.FirstParameter();
48   Last  = aCurve.LastParameter();
49   Standard_Boolean firstInf = Precision::IsNegativeInfinite(First);
50   Standard_Boolean lastInf  = Precision::IsPositiveInfinite(Last);
51
52   if (firstInf || lastInf) {
53     gp_Pnt P1,P2;
54     Standard_Real delta = 1;
55     if (firstInf && lastInf) {
56       do {
57         delta *= 2;
58         First = - delta;
59         Last  =   delta;
60         aCurve.D0(First,P1);
61         aCurve.D0(Last,P2);
62       } while (P1.Distance(P2) < aLimit);
63     }
64     else if (firstInf) {
65       aCurve.D0(Last,P2);
66       do {
67         delta *= 2;
68         First = Last - delta;
69         aCurve.D0(First,P1);
70       } while (P1.Distance(P2) < aLimit);
71     }
72     else if (lastInf) {
73       aCurve.D0(First,P1);
74       do {
75         delta *= 2;
76         Last = First + delta;
77         aCurve.D0(Last,P2);
78       } while (P1.Distance(P2) < aLimit);
79     }
80   }    
81 }
82
83
84 //==================================================================
85 // function: DrawCurve
86 // purpose:
87 //==================================================================
88 static void DrawCurve (const Adaptor3d_Curve&        aCurve,
89                        const Handle(Graphic3d_Group) aGroup,
90                        const Standard_Integer        NbP,
91                        const Standard_Real           U1,
92                        const Standard_Real           U2,
93                        TColgp_SequenceOfPnt&         Points,
94                        const Standard_Boolean drawCurve)
95 {
96   Standard_Integer nbintervals = 1;
97
98   if (aCurve.GetType() == GeomAbs_BSplineCurve) {
99     nbintervals = aCurve.NbKnots() - 1;
100     nbintervals = Max(1, nbintervals/3);
101   }
102
103   switch (aCurve.GetType())
104   {
105     case GeomAbs_Line:
106     {
107       gp_Pnt p1 = aCurve.Value(U1);
108       gp_Pnt p2 = aCurve.Value(U2);
109       Points.Append(p1);
110       Points.Append(p2);
111       if(drawCurve)
112       {
113         Handle(Graphic3d_ArrayOfSegments) aPrims = new Graphic3d_ArrayOfSegments(2);
114         aPrims->AddVertex(p1);
115         aPrims->AddVertex(p2);
116         aGroup->AddPrimitiveArray(aPrims);
117       }
118     }
119     break;
120     default:
121     {
122       const Standard_Integer N = Max(2, NbP*nbintervals);
123       const Standard_Real DU = (U2-U1) / (N-1);
124       gp_Pnt p;
125
126       Handle(Graphic3d_ArrayOfPolylines) aPrims;
127       if(drawCurve)
128         aPrims = new Graphic3d_ArrayOfPolylines(N);
129
130       for (Standard_Integer i = 1; i <= N;i++) {
131         p = aCurve.Value(U1 + (i-1)*DU);
132         Points.Append(p);
133         if(drawCurve)
134           aPrims->AddVertex(p);
135       }
136       if(drawCurve)
137         aGroup->AddPrimitiveArray(aPrims);
138     }
139   }
140 }
141
142
143 //==================================================================
144 // function: MatchCurve
145 // purpose:
146 //==================================================================
147 static Standard_Boolean MatchCurve (
148                        const Quantity_Length  X,
149                        const Quantity_Length  Y,
150                        const Quantity_Length  Z,
151                        const Quantity_Length  aDistance,
152                        const Adaptor3d_Curve&   aCurve,
153                        const Quantity_Length  TheDeflection,
154                        const Standard_Integer NbP,
155                        const Standard_Real    U1,
156                        const Standard_Real    U2)
157 {
158   Quantity_Length retdist;
159   switch (aCurve.GetType())
160   {
161     case GeomAbs_Line:
162     {
163       gp_Pnt p1 = aCurve.Value(U1);
164       if ( Abs(X-p1.X()) + Abs(Y-p1.Y()) + Abs(Z-p1.Z()) <= aDistance)
165         return Standard_True;
166       gp_Pnt p2 = aCurve.Value(U2);
167       if ( Abs(X-p2.X()) + Abs(Y-p2.Y()) + Abs(Z-p2.Z()) <= aDistance)
168         return Standard_True;
169       return Prs3d::MatchSegment(X,Y,Z,aDistance,p1,p2,retdist);
170     }
171     case GeomAbs_Circle:
172     {
173       const Standard_Real Radius = aCurve.Circle().Radius();
174       const Standard_Real DU = Sqrt(8.0 * TheDeflection / Radius);
175       const Standard_Real Er = Abs( U2 - U1) / DU;
176       const Standard_Integer N = Max(2, (Standard_Integer)IntegerPart(Er));
177       if ( N > 0) {
178         gp_Pnt p1,p2;
179         for (Standard_Integer Index = 1; Index <= N+1; Index++) {
180           p2 = aCurve.Value(U1 + (Index - 1) * DU);
181           if ( Abs(X-p2.X()) + Abs(Y-p2.Y()) + Abs(Z-p2.Z()) <= aDistance)
182             return Standard_True;
183
184           if (Index>1) { 
185             if (Prs3d::MatchSegment(X,Y,Z,aDistance,p1,p2,retdist)) 
186               return Standard_True;
187           }
188           p1=p2;
189         }
190       }
191       break;
192     }
193     default:
194     {
195       const Standard_Real DU = (U2-U1) / (NbP-1);
196       gp_Pnt p1,p2;
197       for (Standard_Integer i=1;i<=NbP;i++) {
198         p2 = aCurve.Value(U1 + (i-1)*DU);
199         if ( Abs(X-p2.X()) + Abs(Y-p2.Y()) + Abs(Z-p2.Z()) <= aDistance)
200           return Standard_True;
201         if (i>1) { 
202           if (Prs3d::MatchSegment(X,Y,Z,aDistance,p1,p2,retdist)) 
203             return Standard_True;
204         }
205         p1=p2;
206       }
207     }
208   }
209   return Standard_False;
210 }
211
212
213 //==================================================================
214 // function: Add
215 // purpose:
216 //==================================================================
217 void StdPrs_Curve::Add (const Handle (Prs3d_Presentation)& aPresentation,
218                         const Adaptor3d_Curve&                    aCurve,
219                         const Handle (Prs3d_Drawer)&       aDrawer,
220                         const Standard_Boolean drawCurve)
221 {
222   Prs3d_Root::CurrentGroup(aPresentation)->SetPrimitivesAspect(aDrawer->LineAspect()->Aspect());
223
224   Standard_Real V1, V2;
225   FindLimits(aCurve, aDrawer->MaximalParameterValue(), V1, V2);
226
227   const Standard_Integer NbPoints =  aDrawer->Discretisation();
228   TColgp_SequenceOfPnt Pnts;
229   DrawCurve(aCurve,Prs3d_Root::CurrentGroup(aPresentation),NbPoints,V1,V2,Pnts,drawCurve);
230
231   if (aDrawer->LineArrowDraw()) {
232     gp_Pnt Location;
233     gp_Vec Direction;
234     aCurve.D1(aCurve.LastParameter(),Location,Direction);
235     Prs3d_Arrow::Draw (aPresentation,Location,gp_Dir(Direction),
236                        aDrawer->ArrowAspect()->Angle(),
237                        aDrawer->ArrowAspect()->Length());
238   }
239 }
240
241
242 //==================================================================
243 // function: Add
244 // purpose:
245 //==================================================================
246 void StdPrs_Curve::Add (const Handle (Prs3d_Presentation)& aPresentation,
247                         const Adaptor3d_Curve&             aCurve,
248                         const Handle(Prs3d_Drawer)&        aDrawer,
249                         TColgp_SequenceOfPnt&              Points,
250                         const Standard_Boolean             drawCurve)
251 {
252   Standard_Real V1, V2;
253   FindLimits(aCurve, aDrawer->MaximalParameterValue(), V1, V2);
254
255   const Standard_Integer NbPoints =  aDrawer->Discretisation();
256   DrawCurve(aCurve,Prs3d_Root::CurrentGroup(aPresentation),NbPoints,V1,V2,Points,drawCurve);
257 }
258
259 //==================================================================
260 // function: Add
261 // purpose:
262 //==================================================================
263 void StdPrs_Curve::Add (const Handle (Prs3d_Presentation)& aPresentation,
264                         const Adaptor3d_Curve&             aCurve,
265                         const Standard_Real                U1,
266                         const Standard_Real                U2,
267                         TColgp_SequenceOfPnt&              Points,
268                         const Standard_Integer             NbPoints,
269                         const Standard_Boolean             drawCurve)
270 {
271   DrawCurve(aCurve,Prs3d_Root::CurrentGroup(aPresentation),NbPoints,U1,U2,Points,drawCurve);
272 }
273
274 //==================================================================
275 // function: Add
276 // purpose:
277 //==================================================================
278 void StdPrs_Curve::Add (const Handle (Prs3d_Presentation)& aPresentation,
279                         const Adaptor3d_Curve&             aCurve,
280                         const Standard_Real                U1,
281                         const Standard_Real                U2,
282                         const Handle (Prs3d_Drawer)&       aDrawer,
283                         const Standard_Boolean drawCurve)
284 {
285   Prs3d_Root::CurrentGroup(aPresentation)->SetPrimitivesAspect(aDrawer->LineAspect()->Aspect());
286
287   Standard_Real V1 = U1;
288   Standard_Real V2 = U2;  
289
290   if (Precision::IsNegativeInfinite(V1)) V1 = -aDrawer->MaximalParameterValue();
291   if (Precision::IsPositiveInfinite(V2)) V2 = aDrawer->MaximalParameterValue();
292
293   const Standard_Integer NbPoints = aDrawer->Discretisation();
294   TColgp_SequenceOfPnt Pnts;
295   DrawCurve(aCurve,Prs3d_Root::CurrentGroup(aPresentation),NbPoints,V1,V2,Pnts,drawCurve);
296     
297   if (aDrawer->LineArrowDraw()) {
298     gp_Pnt Location;
299     gp_Vec Direction;
300     aCurve.D1(aCurve.LastParameter(),Location,Direction);
301     Prs3d_Arrow::Draw (aPresentation,Location,gp_Dir(Direction),
302                        aDrawer->ArrowAspect()->Angle(),
303                        aDrawer->ArrowAspect()->Length());
304   }
305 }
306
307
308 //==================================================================
309 // function: Match
310 // purpose:
311 //==================================================================
312 Standard_Boolean StdPrs_Curve::Match 
313                       (const Quantity_Length        X,
314                        const Quantity_Length        Y,
315                        const Quantity_Length        Z,
316                        const Quantity_Length        aDistance,
317                        const Adaptor3d_Curve&       aCurve,
318                        const Handle (Prs3d_Drawer)& aDrawer)
319 {
320   Standard_Real V1, V2;
321   FindLimits(aCurve, aDrawer->MaximalParameterValue(), V1, V2);
322
323   const Standard_Integer NbPoints = aDrawer->Discretisation();
324   return MatchCurve(X,Y,Z,aDistance,aCurve,
325                     aDrawer->MaximalChordialDeviation(),NbPoints,V1,V2);
326
327 }
328
329
330 //==================================================================
331 // function: Match
332 // purpose:
333 //==================================================================
334 Standard_Boolean StdPrs_Curve::Match 
335                       (const Quantity_Length  X,
336                        const Quantity_Length  Y,
337                        const Quantity_Length  Z,
338                        const Quantity_Length  aDistance,
339                        const Adaptor3d_Curve&   aCurve,
340                        const Quantity_Length  aDeflection,
341                        const Standard_Real    aLimit,
342                        const Standard_Integer NbPoints)
343 {
344   Standard_Real V1, V2;
345   FindLimits(aCurve, aLimit, V1, V2);
346
347   return MatchCurve(X,Y,Z,aDistance,aCurve,
348                     aDeflection,NbPoints,V1,V2);
349 }
350
351
352 //==================================================================
353 // function: Match
354 // purpose:
355 //==================================================================
356 Standard_Boolean StdPrs_Curve::Match 
357                         (const Quantity_Length        X,
358                          const Quantity_Length        Y,
359                          const Quantity_Length        Z,
360                          const Quantity_Length        aDistance,
361                          const Adaptor3d_Curve&         aCurve,
362                          const Standard_Real          U1,
363                          const Standard_Real          U2,
364                          const Handle (Prs3d_Drawer)& aDrawer)
365 {
366   Standard_Real V1 = U1;
367   Standard_Real V2 = U2;  
368
369   if (Precision::IsNegativeInfinite(V1)) V1 = -aDrawer->MaximalParameterValue();
370   if (Precision::IsPositiveInfinite(V2)) V2 = aDrawer->MaximalParameterValue();
371
372   return MatchCurve(X,Y,Z,aDistance,aCurve,
373                     aDrawer->MaximalChordialDeviation(),
374                     aDrawer->Discretisation(),V1,V2);
375 }
376
377
378 //==================================================================
379 // function: Match
380 // purpose:
381 //==================================================================
382 Standard_Boolean StdPrs_Curve::Match 
383                         (const Quantity_Length  X,
384                          const Quantity_Length  Y,
385                          const Quantity_Length  Z,
386                          const Quantity_Length  aDistance,
387                          const Adaptor3d_Curve&   aCurve,
388                          const Standard_Real    U1,
389                          const Standard_Real    U2,
390                          const Quantity_Length  aDeflection,
391                          const Standard_Integer aNbPoints) 
392 {
393   return MatchCurve(X,Y,Z,aDistance,aCurve,aDeflection,aNbPoints,U1,U2);
394 }