0023634: Eliminate Polyline and Polygon usage in drawers
[occt.git] / src / StdPrs / StdPrs_WFSurface.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
23 #include <StdPrs_WFSurface.ixx>
24
25
26 #include <Graphic3d_Group.hxx>
27 #include <Graphic3d_ArrayOfPolylines.hxx>
28 #include <GeomAbs_IsoType.hxx>
29 #include <Prs3d_IsoAspect.hxx>
30 #include <Bnd_Box.hxx>
31 #include <Precision.hxx>
32 #include <BndLib_AddSurface.hxx>
33 #include <Adaptor3d_IsoCurve.hxx>
34 #include <StdPrs_Curve.hxx>
35 #include <TColgp_SequenceOfPnt.hxx>
36
37 #include <Prs3d_NListOfSequenceOfPnt.hxx>
38 #include <Prs3d_NListIteratorOfListOfSequenceOfPnt.hxx>
39
40
41 static void FindLimits(const Handle(Adaptor3d_HSurface)& surf ,
42                        const Standard_Real             aLimit,
43                        Standard_Real&                  UFirst,
44                        Standard_Real&                  ULast,
45                        Standard_Real&                  VFirst,
46                        Standard_Real&                  VLast)
47 {
48   UFirst = surf->FirstUParameter();
49   ULast = surf->LastUParameter();
50   VFirst = surf->FirstVParameter();
51   VLast = surf->LastVParameter();
52   
53   Standard_Boolean UfirstInf = Precision::IsNegativeInfinite(UFirst);
54   Standard_Boolean UlastInf  = Precision::IsPositiveInfinite(ULast);
55   Standard_Boolean VfirstInf = Precision::IsNegativeInfinite(VFirst);
56   Standard_Boolean VlastInf  = Precision::IsPositiveInfinite(VLast);
57   
58   if (UfirstInf || UlastInf) {
59     gp_Pnt P1,P2;
60     Standard_Real v;
61     if (VfirstInf && VlastInf) 
62       v = 0;
63     else if (VfirstInf)
64       v = VLast;
65     else if (VlastInf)
66       v = VFirst;
67     else
68       v = (VFirst + VLast) / 2;
69     
70     Standard_Real delta = aLimit * 2;
71
72     if (UfirstInf && UlastInf) {
73       do {
74         delta /= 2;
75         UFirst = - delta;
76         ULast  =   delta;
77         surf->D0(UFirst,v,P1);
78         surf->D0(ULast,v,P2);
79       } while (P1.Distance(P2) > aLimit);
80     }
81     else if (UfirstInf) {
82       surf->D0(ULast,v,P2);
83       do {
84         delta /= 2;
85         UFirst = ULast - delta;
86         surf->D0(UFirst,v,P1);
87       } while (P1.Distance(P2) > aLimit);
88     }
89     else if (UlastInf) {
90       surf->D0(UFirst,v,P1);
91       do {
92         delta /= 2;
93         ULast = UFirst + delta;
94         surf->D0(ULast,v,P2);
95       } while (P1.Distance(P2) > aLimit);
96     }
97   }
98
99   if (VfirstInf || VlastInf) {
100     gp_Pnt P1,P2;
101     Standard_Real u = (UFirst + ULast) /2 ;
102
103     Standard_Real delta = aLimit * 2;
104
105     if (VfirstInf && VlastInf) {
106       do {
107         delta /= 2;
108         VFirst = - delta;
109         VLast  =   delta;
110         surf->D0(u,VFirst,P1);
111         surf->D0(u,VLast,P2);
112       } while (P1.Distance(P2) > aLimit);
113     }
114     else if (VfirstInf) {
115       surf->D0(u,VLast,P2);
116       do {
117         delta /= 2;
118         VFirst = VLast - delta;
119         surf->D0(u,VFirst,P1);
120       } while (P1.Distance(P2) > aLimit);
121     }
122     else if (VlastInf) {
123       surf->D0(u,VFirst,P1);
124       do {
125         delta /= 2;
126         VLast = VFirst + delta;
127         surf->D0(u,VLast,P2);
128       } while (P1.Distance(P2) > aLimit);
129     }
130   }
131 }
132
133
134 //=======================================================================
135 //function : Add
136 //purpose  : 
137 //=======================================================================
138
139 void StdPrs_WFSurface::Add (const Handle(Prs3d_Presentation)& aPresentation,
140                             const Handle(Adaptor3d_HSurface)&   aSurface,
141                             const Handle(Prs3d_Drawer)&       aDrawer)
142 {
143   
144     Standard_Real  U1, U2, V1, V2;
145     Standard_Real MaxP = aDrawer->MaximalParameterValue();
146
147     FindLimits(aSurface, MaxP, U1, U2, V1, V2);
148
149     Prs3d_NListOfSequenceOfPnt freeCurves; 
150     Prs3d_NListOfSequenceOfPnt UIsoCurves; 
151     Prs3d_NListOfSequenceOfPnt VIsoCurves; 
152     TColgp_SequenceOfPnt Pnts;
153     
154     Standard_Boolean UClosed = aSurface->IsUClosed();
155     Standard_Boolean VClosed = aSurface->IsVClosed();
156       
157     Standard_Real TheDeflection;
158     Aspect_TypeOfDeflection TOD = aDrawer->TypeOfDeflection();    
159     if (TOD == Aspect_TOD_RELATIVE) {
160 // On calcule la fleche en fonction des min max globaux de la piece:
161        Bnd_Box Total;
162        BndLib_AddSurface::Add(aSurface->Surface(),U1, U2, V1, V2, 0.,Total);
163        Standard_Real m = aDrawer->MaximalChordialDeviation()/
164          aDrawer->DeviationCoefficient();
165        Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
166        Total.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
167        if ( ! (Total.IsOpenXmin() || Total.IsOpenXmax() ))
168           m = Min ( m , Abs (aXmax-aXmin));
169        if ( ! (Total.IsOpenYmin() || Total.IsOpenYmax() ))
170           m = Min ( m , Abs (aYmax-aYmin));
171        if ( ! (Total.IsOpenZmin() || Total.IsOpenZmax() ))
172           m = Min ( m , Abs (aZmax-aZmin));
173
174        TheDeflection = m * aDrawer->DeviationCoefficient();
175     }
176     else
177       TheDeflection = aDrawer->MaximalChordialDeviation();  
178
179     Adaptor3d_IsoCurve anIso;
180     anIso.Load(aSurface);
181
182     // Trace des frontieres.
183     // *********************
184     //
185     if ( !(UClosed && VClosed) ) {
186         
187       (Prs3d_Root::CurrentGroup(aPresentation))->SetPrimitivesAspect
188         (aDrawer->FreeBoundaryAspect()->Aspect());
189       if ( !UClosed ) 
190         { 
191           anIso.Load(GeomAbs_IsoU,U1,V1,V2);
192           StdPrs_Curve::Add(aPresentation,anIso,TheDeflection, aDrawer, Pnts, Standard_False);
193           freeCurves.Append(Pnts);
194           Pnts.Clear();
195           anIso.Load(GeomAbs_IsoU,U2,V1,V2);
196           StdPrs_Curve::Add(aPresentation,anIso,TheDeflection, aDrawer, Pnts, Standard_False);
197           freeCurves.Append(Pnts);
198           Pnts.Clear();
199         }
200       if ( !VClosed )
201         {
202           anIso.Load(GeomAbs_IsoV,V1,U1,U2);
203           StdPrs_Curve::Add(aPresentation,anIso,TheDeflection, aDrawer, Pnts, Standard_False);
204           freeCurves.Append(Pnts);
205           Pnts.Clear();
206           anIso.Load(GeomAbs_IsoV,V2,U1,U2);
207           StdPrs_Curve::Add(aPresentation,anIso,TheDeflection, aDrawer, Pnts, Standard_False);
208           freeCurves.Append(Pnts);
209           Pnts.Clear();
210         }
211     }
212     //
213     // Trace des isoparametriques.
214     // ***************************
215     //
216     Standard_Integer fin = aDrawer->UIsoAspect()->Number();
217     if ( fin != 0) {
218       
219       (Prs3d_Root::CurrentGroup(aPresentation))->SetPrimitivesAspect
220         (aDrawer->UIsoAspect()->Aspect());
221       
222       Standard_Real du= UClosed ? (U2-U1)/fin : (U2-U1)/(1+fin);
223       for (Standard_Integer i=1; i<=fin;i++){
224         anIso.Load(GeomAbs_IsoU,U1+du*i,V1,V2);
225         StdPrs_Curve::Add(aPresentation,anIso,TheDeflection, aDrawer, Pnts, Standard_False);
226         UIsoCurves.Append(Pnts);
227         Pnts.Clear();
228       }
229     }
230     fin = aDrawer->VIsoAspect()->Number();
231     if ( fin != 0) {
232       
233       (Prs3d_Root::CurrentGroup(aPresentation))->SetPrimitivesAspect
234         (aDrawer->VIsoAspect()->Aspect());
235       
236       Standard_Real dv= VClosed ?(V2-V1)/fin : (V2-V1)/(1+fin);
237       for (Standard_Integer i=1; i<=fin;i++){
238         anIso.Load(GeomAbs_IsoV,V1+dv*i,U1,U2);
239         StdPrs_Curve::Add(aPresentation,anIso,TheDeflection, aDrawer, Pnts, Standard_False);
240         VIsoCurves.Append(Pnts);
241         Pnts.Clear();
242       }
243     }
244     
245     Standard_Integer nbVertices = 0, nbBounds = 0; 
246     //Draw surface via primitive array
247     if(UIsoCurves.Size() > 0) {
248       nbBounds = UIsoCurves.Size();
249       Prs3d_NListIteratorOfListOfSequenceOfPnt It;
250       for( It.Init(UIsoCurves); It.More(); It.Next())
251         nbVertices += It.Value().Length();
252       Handle(Graphic3d_ArrayOfPolylines) UIsoArray =
253         new Graphic3d_ArrayOfPolylines(nbVertices,nbBounds);
254       for( It.Init(UIsoCurves); It.More(); It.Next()) {
255         TColgp_SequenceOfPnt Pnts;
256         Pnts.Assign(It.Value());
257         UIsoArray->AddBound(Pnts.Length());
258         for(int i=1; i<=Pnts.Length(); i++)
259           UIsoArray->AddVertex(Pnts.Value(i));
260       }      
261       Handle(Graphic3d_Group) TheGroup = Prs3d_Root::NewGroup(aPresentation);
262       TheGroup->SetPrimitivesAspect(aDrawer->UIsoAspect()->Aspect());
263       TheGroup->AddPrimitiveArray(UIsoArray);
264     }
265     
266     if(VIsoCurves.Size() > 0) {
267       nbBounds = VIsoCurves.Size();
268       Prs3d_NListIteratorOfListOfSequenceOfPnt It;
269       for( It.Init(VIsoCurves); It.More(); It.Next())
270         nbVertices += It.Value().Length();
271       Handle(Graphic3d_ArrayOfPolylines) VIsoArray =
272         new Graphic3d_ArrayOfPolylines(nbVertices,nbBounds);
273       for( It.Init(VIsoCurves); It.More(); It.Next()) {
274         TColgp_SequenceOfPnt Pnts;
275         Pnts.Assign(It.Value());
276         VIsoArray->AddBound(Pnts.Length());
277         for(int i=1; i<=Pnts.Length(); i++)
278           VIsoArray->AddVertex(Pnts.Value(i));
279       }
280       Handle(Graphic3d_Group) TheGroup = Prs3d_Root::NewGroup(aPresentation);
281       TheGroup->SetPrimitivesAspect(aDrawer->VIsoAspect()->Aspect());
282       TheGroup->AddPrimitiveArray(VIsoArray);
283     } 
284     if(freeCurves.Size() > 0) {
285       nbBounds = freeCurves.Size();
286       Prs3d_NListIteratorOfListOfSequenceOfPnt It;
287       for( It.Init(freeCurves); It.More(); It.Next())
288         nbVertices += It.Value().Length();
289       Handle(Graphic3d_ArrayOfPolylines) freeArray =
290         new Graphic3d_ArrayOfPolylines(nbVertices,nbBounds);
291       for( It.Init(freeCurves); It.More(); It.Next()) {
292         TColgp_SequenceOfPnt Pnts;
293         Pnts.Assign(It.Value());
294         freeArray->AddBound(Pnts.Length());
295         for(int i=1; i<=Pnts.Length(); i++)
296           freeArray->AddVertex(Pnts.Value(i));
297       }
298       Handle(Graphic3d_Group) TheGroup = Prs3d_Root::NewGroup(aPresentation);
299       TheGroup->SetPrimitivesAspect(aDrawer->FreeBoundaryAspect()->Aspect());
300       TheGroup->AddPrimitiveArray(freeArray);
301     }
302   }
303
304