0023634: Eliminate Polyline and Polygon usage in drawers
[occt.git] / src / DsgPrs / DsgPrs_ShapeDirPresentation.cxx
1 // Created on: 1995-10-06
2 // Created by: Jing Cheng MEI
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 #include <DsgPrs_ShapeDirPresentation.ixx>
22
23 #include <gp.hxx>
24 #include <gp_Dir.hxx>
25 #include <Bnd_Box.hxx>
26
27 #include <Geom2d_Line.hxx>
28 #include <Geom_Curve.hxx>
29 #include <Geom_Surface.hxx>
30 #include <GeomLProp_CLProps.hxx>
31 #include <GeomLProp_SLProps.hxx>
32
33 #include <TopoDS_Shape.hxx>
34 #include <TopoDS.hxx>
35 #include <TopoDS_Face.hxx>
36 #include <TopLoc_Location.hxx>
37 #include <TopAbs_ShapeEnum.hxx>
38 #include <TopAbs_Orientation.hxx>
39 #include <TopExp_Explorer.hxx>
40 #include <TopTools_ListOfShape.hxx>
41 #include <BRep_Tool.hxx>
42 #include <BRepTools_WireExplorer.hxx>
43 #include <BRepClass_FaceClassifier.hxx>
44 #include <BRepClass_Edge.hxx>
45 #include <BRepBndLib.hxx>
46
47 #include <Graphic3d_Group.hxx>
48 #include <Graphic3d_ArrayOfSegments.hxx>
49 #include <Prs3d_Arrow.hxx>
50 #include <Prs3d_LineAspect.hxx>
51
52 #include <Quantity_Length.hxx>
53 #include <TColgp_Array1OfPnt2d.hxx>
54
55
56 //=======================================================================
57 //function : FindPointOnFace
58 //purpose  : internal use
59 //=======================================================================
60
61 static Standard_Boolean FindPointOnFace(const TopoDS_Face& face, gp_Pnt2d& pt2d)
62 {
63   // discredisation of the external contour and computing the center of gravity
64
65   TopExp_Explorer wireExp;
66   wireExp.Init(face, TopAbs_WIRE);
67   if (!wireExp.More()) {
68     return Standard_False;
69   }
70
71   Standard_Integer npoints, nptt = 21;
72   TColgp_Array1OfPnt2d points(1, nptt);
73   Standard_Real area=0., xcent=0., ycent=0.;
74   TopExp_Explorer edgeExp;
75
76   for (edgeExp.Init(wireExp.Current(), TopAbs_EDGE); edgeExp.More(); edgeExp.Next()) {    
77     // discretize the 2d curve
78     Standard_Real first, last;
79     Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(edgeExp.Current()), face, first, last);
80     if (TopoDS::Edge(edgeExp.Current()).Orientation() == TopAbs_REVERSED) {
81       Standard_Real change = first;
82       first = last;
83       last = change;
84     }
85     if (c2d->DynamicType() == STANDARD_TYPE(Geom2d_Line)) {
86       npoints = 2;
87       c2d->D0(first, points(1));
88       c2d->D0(last, points(2));
89     }
90     else {
91       Standard_Real deltaT, t;
92       npoints = nptt;
93       deltaT = (last - first) / (nptt-1);
94       for (Standard_Integer i=1; i<=nptt; i++) {
95         if (i == 1) {
96           t = first;
97         }
98         else if (i == nptt) {
99           t = last;
100         }
101         else {
102           t = first + (i-1) * deltaT;
103         }
104         c2d->D0(t, points(i));
105       } 
106     }
107       
108     // compute the contribution to the center of gravity
109
110     Standard_Real h, c, d;
111     for (Standard_Integer i=1; i<=npoints-1; i++) {
112
113       h = 0.5*(points(i).Y() + points(i+1).Y());
114       c = points(i+1).X() - points(i).X();
115       d = points(i+1).X() + points(i).X();
116       area += h*c;
117       xcent += 0.5*h*c*d;
118       ycent += 0.5*h*h*c;
119     }
120   }
121
122   if (Abs(area) < gp::Resolution()) {
123     pt2d.SetCoord(points(1).X(), points(1).Y());
124     return Standard_False;
125   }
126
127   pt2d.SetCoord(xcent / area, ycent / area);
128
129   // verify that (upar vpar) is a point on the face
130
131   BRepClass_FaceClassifier fClass(face, pt2d, gp::Resolution());
132
133   if ((fClass.State() == TopAbs_OUT) || (fClass.State() == TopAbs_UNKNOWN)) {
134     // try to find a point on face
135     pt2d=points(1);
136   }
137   return Standard_True;
138 }
139
140
141 //=======================================================================
142 //function : ComputeDir
143 //purpose  : internal use
144 //=======================================================================
145
146 static Standard_Boolean ComputeDir(const TopoDS_Shape& shape, gp_Pnt& pt, gp_Dir& dir, const Standard_Integer mode)
147 {
148   TopLoc_Location loc;
149   if (shape.ShapeType() == TopAbs_EDGE) {
150     Standard_Real first, last;
151     Handle(Geom_Curve) curv0 = BRep_Tool::Curve(TopoDS::Edge(shape), loc, first, last);
152     Handle(Geom_Curve) curve = Handle(Geom_Curve)::DownCast(curv0->Copy());
153     curve->Transform(loc.Transformation()); 
154     GeomLProp_CLProps lProps(curve, 1, gp::Resolution());
155     lProps.SetParameter((mode == 0)? last : first);
156     if (!lProps.IsTangentDefined())
157       return Standard_False;
158     pt = lProps.Value();
159     lProps.Tangent(dir);
160   }
161   else if (shape.ShapeType() == TopAbs_FACE) {
162     gp_Pnt2d pt2d;
163     Handle(Geom_Surface) surface = BRep_Tool::Surface(TopoDS::Face(shape));    
164     if (BRep_Tool::NaturalRestriction(TopoDS::Face(shape))) {
165       Standard_Real u1, u2, v1, v2;
166       surface->Bounds(u1, u2, v1, v2);
167       pt2d.SetCoord((u1+u2)*0.5, (v1+v2)*0.5);
168     }
169     else {
170       if (!FindPointOnFace(TopoDS::Face(shape), pt2d))
171         return Standard_False;
172     }
173     
174     GeomLProp_SLProps lProps(surface, pt2d.X(), pt2d.Y(), 1, gp::Resolution());
175     if (!lProps.IsNormalDefined())
176       return Standard_False;
177
178     pt = lProps.Value();
179     dir = lProps.Normal();
180   }
181   if ((shape.Orientation() == TopAbs_FORWARD) && (mode == 1) ||
182       (shape.Orientation() == TopAbs_REVERSED) && (mode == 0)) {
183     dir.Reverse();
184   }
185   return Standard_True;
186 }  
187
188
189 //=======================================================================
190 //function : Add
191 //purpose  : 
192 //=======================================================================
193
194 void DsgPrs_ShapeDirPresentation::Add(const Handle(Prs3d_Presentation)& prs,
195                                       const Handle(Prs3d_Drawer)& drawer,
196                                       const TopoDS_Shape& shape,
197                                       const Standard_Integer mode)
198      
199 {
200   if ((mode != 0) && (mode != 1))
201     return;
202   
203   gp_Dir dir;
204   gp_Pnt pt;
205   Bnd_Box box;
206
207   if (shape.ShapeType() == TopAbs_EDGE) {
208     ComputeDir(shape, pt, dir, mode);
209     BRepBndLib::Add(shape, box);
210   }
211   else if (shape.ShapeType() == TopAbs_FACE) {
212     ComputeDir(shape, pt, dir, mode);
213     BRepBndLib::Add(shape, box);
214   }    
215   else if (shape.ShapeType() == TopAbs_WIRE) {
216     TopTools_ListOfShape aList;
217     Standard_Integer nb = 0;
218     BRepTools_WireExplorer anExp;
219     for (anExp.Init(TopoDS::Wire(shape)); anExp.More(); anExp.Next()) {
220       const TopoDS_Edge& edge = anExp.Current();
221       nb++;
222       if (nb <=3)
223         BRepBndLib::Add(edge, box);
224       aList.Append(edge);
225     }
226
227     if (mode == 0) {
228       const TopoDS_Edge& edge = TopoDS::Edge(aList.Last());
229       ComputeDir(edge, pt, dir, mode);
230     }
231     else {
232       const TopoDS_Edge& edge = TopoDS::Edge(aList.First());
233       ComputeDir(edge, pt, dir, mode);
234     }
235   }
236   else {
237     TopExp_Explorer faceExp;
238     
239     TopTools_ListOfShape aList;
240     Standard_Integer nb = 0;
241     for (faceExp.Init(shape, TopAbs_FACE); faceExp.More(); faceExp.Next()) {
242       nb++;
243       const TopoDS_Face& face = TopoDS::Face(faceExp.Current());
244       aList.Append(face);
245       BRepBndLib::Add(face, box);
246       if (nb > 3) break;
247     }
248     const TopoDS_Face& face = TopoDS::Face(aList.Last());
249     ComputeDir(face, pt, dir, mode);
250   }  
251
252   Standard_Real c[6];
253   box.Get(c[0],c[1],c[2],c[3],c[4],c[5]);
254   
255   gp_Pnt ptmin(c[0], c[1], c[2]), ptmax(c[3], c[4], c[5]);
256   Quantity_Length leng = ptmin.Distance(ptmax)/3.;
257   // mei 19/09/96 extrusion infinie -> taille fixe
258   if (leng >= 20000.) leng = 50;
259
260   gp_Pnt pt2(pt.XYZ()+leng*dir.XYZ());
261
262   Prs3d_Root::CurrentGroup(prs)->SetPrimitivesAspect(drawer->LineAspect()->Aspect());
263
264   Handle(Graphic3d_ArrayOfSegments) aPrims = new Graphic3d_ArrayOfSegments(2);
265   aPrims->AddVertex(pt);
266   aPrims->AddVertex(pt2);
267   Prs3d_Root::CurrentGroup(prs)->AddPrimitiveArray(aPrims);
268
269   Prs3d_Arrow::Draw(prs, pt2, dir, M_PI/180.*10., leng*0.3);
270 }