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