b311480e |
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 | |
7fd59977 |
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> |
7fd59977 |
43 | #include <BRepClass_FaceClassifier.hxx> |
44 | #include <BRepClass_Edge.hxx> |
45 | #include <BRepBndLib.hxx> |
46 | |
47 | #include <Graphic3d_Group.hxx> |
b8ddfc2f |
48 | #include <Graphic3d_ArrayOfSegments.hxx> |
7fd59977 |
49 | #include <Prs3d_Arrow.hxx> |
50 | #include <Prs3d_LineAspect.hxx> |
51 | |
52 | #include <Quantity_Length.hxx> |
53 | #include <TColgp_Array1OfPnt2d.hxx> |
54 | |
55 | |
7fd59977 |
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()); |
6e6cd5d9 |
132 | |
7fd59977 |
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()); |
b8ddfc2f |
155 | lProps.SetParameter((mode == 0)? last : first); |
156 | if (!lProps.IsTangentDefined()) |
7fd59977 |
157 | return Standard_False; |
7fd59977 |
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 { |
b8ddfc2f |
170 | if (!FindPointOnFace(TopoDS::Face(shape), pt2d)) |
171 | return Standard_False; |
7fd59977 |
172 | } |
173 | |
174 | GeomLProp_SLProps lProps(surface, pt2d.X(), pt2d.Y(), 1, gp::Resolution()); |
b8ddfc2f |
175 | if (!lProps.IsNormalDefined()) |
7fd59977 |
176 | return Standard_False; |
7fd59977 |
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 | { |
b8ddfc2f |
200 | if ((mode != 0) && (mode != 1)) |
7fd59977 |
201 | return; |
7fd59977 |
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++; |
b8ddfc2f |
222 | if (nb <=3) |
223 | BRepBndLib::Add(edge, box); |
7fd59977 |
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 | |
b8ddfc2f |
260 | gp_Pnt pt2(pt.XYZ()+leng*dir.XYZ()); |
261 | |
7fd59977 |
262 | Prs3d_Root::CurrentGroup(prs)->SetPrimitivesAspect(drawer->LineAspect()->Aspect()); |
b8ddfc2f |
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); |
7fd59977 |
268 | |
c6541a0c |
269 | Prs3d_Arrow::Draw(prs, pt2, dir, M_PI/180.*10., leng*0.3); |
7fd59977 |
270 | } |