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