973c2be1 |
1 | // Created on: 1993-09-23 |
2 | // Created by: Jean-Louis FRENKEL |
3 | // Copyright (c) 1993-1999 Matra Datavision |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
5 | // |
6 | // This file is part of Open CASCADE Technology software library. |
7 | // |
d5f74e42 |
8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
13 | // |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
2bd4c032 |
16 | |
17 | #include <StdPrs_ShadedShape.hxx> |
18 | |
19 | #include <Bnd_Box.hxx> |
20 | #include <BRep_Builder.hxx> |
21 | #include <BRepBndLib.hxx> |
22 | #include <BRepMesh_DiscretFactory.hxx> |
23 | #include <BRepMesh_DiscretRoot.hxx> |
24 | #include <BRepTools.hxx> |
31c0e219 |
25 | #include <Graphic3d_ArrayOfSegments.hxx> |
2bd4c032 |
26 | #include <Graphic3d_ArrayOfTriangles.hxx> |
27 | #include <Graphic3d_AspectFillArea3d.hxx> |
28 | #include <Graphic3d_Group.hxx> |
29 | #include <gp_Dir.hxx> |
30 | #include <gp_Vec.hxx> |
31 | #include <gp_Pnt.hxx> |
31c0e219 |
32 | #include <NCollection_List.hxx> |
2bd4c032 |
33 | #include <Precision.hxx> |
9dba391d |
34 | #include <Prs3d.hxx> |
2bd4c032 |
35 | #include <Prs3d_Drawer.hxx> |
31c0e219 |
36 | #include <Prs3d_LineAspect.hxx> |
2bd4c032 |
37 | #include <Prs3d_Presentation.hxx> |
38 | #include <Prs3d_ShadingAspect.hxx> |
39 | #include <Poly_Connect.hxx> |
31c0e219 |
40 | #include <Poly_PolygonOnTriangulation.hxx> |
2bd4c032 |
41 | #include <Poly_Triangulation.hxx> |
42 | #include <StdPrs_ToolShadedShape.hxx> |
43 | #include <StdPrs_WFShape.hxx> |
31c0e219 |
44 | #include <TopExp.hxx> |
fc9b36d6 |
45 | #include <TopExp_Explorer.hxx> |
46 | #include <TopoDS.hxx> |
31c0e219 |
47 | #include <TopoDS_Compound.hxx> |
2bd4c032 |
48 | #include <TopoDS_Face.hxx> |
31c0e219 |
49 | #include <TopoDS_Shape.hxx> |
2bd4c032 |
50 | #include <TColgp_Array1OfDir.hxx> |
51 | #include <TColgp_Array1OfPnt2d.hxx> |
31c0e219 |
52 | #include <TColgp_HArray1OfPnt.hxx> |
a2d5ab2e |
53 | #include <TopTools_ListOfShape.hxx> |
54 | #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> |
2bd4c032 |
55 | |
56 | namespace |
57 | { |
31c0e219 |
58 | |
59 | //! Computes wireframe presentation for free wires and vertices |
60 | void wireframeFromShape (const Handle (Prs3d_Presentation)& thePrs, |
61 | const TopoDS_Shape& theShape, |
62 | const Handle (Prs3d_Drawer)& theDrawer) |
63 | { |
53b15292 |
64 | Standard_Boolean aDrawAllVerticesFlag = (theDrawer->VertexDrawMode() == Prs3d_VDM_All); |
65 | |
66 | if (!aDrawAllVerticesFlag && theShape.ShapeType() != TopAbs_COMPOUND) |
31c0e219 |
67 | { |
68 | return; |
69 | } |
70 | |
71 | TopExp_Explorer aShapeIter (theShape, TopAbs_FACE); |
72 | if (!aShapeIter.More()) |
73 | { |
74 | // compound contains no shaded elements at all |
75 | StdPrs_WFShape::Add (thePrs, theShape, theDrawer); |
76 | return; |
77 | } |
78 | |
53b15292 |
79 | // We have to create a compound and collect all subshapes not drawn by the shading algo. |
80 | // This includes: |
81 | // - isolated edges |
82 | // - isolated vertices, if aDrawAllVerticesFlag == Standard_False |
83 | // - all shape's vertices, if aDrawAllVerticesFlag == Standard_True |
31c0e219 |
84 | TopoDS_Compound aCompoundWF; |
85 | BRep_Builder aBuilder; |
86 | aBuilder.MakeCompound (aCompoundWF); |
87 | Standard_Boolean hasElement = Standard_False; |
88 | |
89 | // isolated edges |
90 | for (aShapeIter.Init (theShape, TopAbs_EDGE, TopAbs_FACE); aShapeIter.More(); aShapeIter.Next()) |
91 | { |
92 | hasElement = Standard_True; |
93 | aBuilder.Add (aCompoundWF, aShapeIter.Current()); |
94 | } |
53b15292 |
95 | // isolated or all vertices |
96 | aShapeIter.Init (theShape, TopAbs_VERTEX, aDrawAllVerticesFlag ? TopAbs_SHAPE : TopAbs_EDGE); |
97 | for (; aShapeIter.More(); aShapeIter.Next()) |
31c0e219 |
98 | { |
99 | hasElement = Standard_True; |
100 | aBuilder.Add (aCompoundWF, aShapeIter.Current()); |
101 | } |
102 | if (hasElement) |
103 | { |
104 | StdPrs_WFShape::Add (thePrs, aCompoundWF, theDrawer); |
105 | } |
106 | } |
107 | |
31c0e219 |
108 | //! Gets triangulation of every face of shape and fills output array of triangles |
109 | static Handle(Graphic3d_ArrayOfTriangles) fillTriangles (const TopoDS_Shape& theShape, |
110 | const Standard_Boolean theHasTexels, |
111 | const gp_Pnt2d& theUVOrigin, |
112 | const gp_Pnt2d& theUVRepeat, |
113 | const gp_Pnt2d& theUVScale) |
2bd4c032 |
114 | { |
31c0e219 |
115 | Handle(Poly_Triangulation) aT; |
2bd4c032 |
116 | TopLoc_Location aLoc; |
31c0e219 |
117 | gp_Pnt aPoint; |
118 | Standard_Integer aNbTriangles = 0; |
119 | Standard_Integer aNbVertices = 0; |
2bd4c032 |
120 | |
31c0e219 |
121 | // Precision for compare square distances |
3b1817a9 |
122 | const Standard_Real aPreci = Precision::SquareConfusion(); |
2bd4c032 |
123 | |
fc9b36d6 |
124 | TopExp_Explorer aFaceIt(theShape, TopAbs_FACE); |
125 | for (; aFaceIt.More(); aFaceIt.Next()) |
2bd4c032 |
126 | { |
fc9b36d6 |
127 | const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current()); |
128 | aT = StdPrs_ToolShadedShape::Triangulation (aFace, aLoc); |
31c0e219 |
129 | if (!aT.IsNull()) |
2bd4c032 |
130 | { |
31c0e219 |
131 | aNbTriangles += aT->NbTriangles(); |
132 | aNbVertices += aT->NbNodes(); |
2bd4c032 |
133 | } |
2bd4c032 |
134 | } |
31c0e219 |
135 | if (aNbVertices < 3 || aNbTriangles <= 0) |
2bd4c032 |
136 | { |
31c0e219 |
137 | return Handle(Graphic3d_ArrayOfTriangles)(); |
3b1817a9 |
138 | } |
2bd4c032 |
139 | |
31c0e219 |
140 | Handle(Graphic3d_ArrayOfTriangles) anArray = new Graphic3d_ArrayOfTriangles (aNbVertices, 3 * aNbTriangles, |
871fa103 |
141 | Standard_True, Standard_False, theHasTexels); |
31c0e219 |
142 | Standard_Real aUmin (0.0), aUmax (0.0), aVmin (0.0), aVmax (0.0), dUmax (0.0), dVmax (0.0); |
fc9b36d6 |
143 | for (aFaceIt.Init (theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next()) |
2bd4c032 |
144 | { |
fc9b36d6 |
145 | const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current()); |
146 | aT = StdPrs_ToolShadedShape::Triangulation (aFace, aLoc); |
31c0e219 |
147 | if (aT.IsNull()) |
3b1817a9 |
148 | { |
149 | continue; |
150 | } |
151 | const gp_Trsf& aTrsf = aLoc.Transformation(); |
7d9e854b |
152 | |
153 | // Determinant of transform matrix less then 0 means that mirror transform applied. |
154 | Standard_Boolean isMirrored = aTrsf.VectorialPart().Determinant() < 0; |
155 | |
31c0e219 |
156 | Poly_Connect aPolyConnect (aT); |
3b1817a9 |
157 | // Extracts vertices & normals from nodes |
31c0e219 |
158 | const TColgp_Array1OfPnt& aNodes = aT->Nodes(); |
159 | const TColgp_Array1OfPnt2d& aUVNodes = aT->UVNodes(); |
3b1817a9 |
160 | TColgp_Array1OfDir aNormals (aNodes.Lower(), aNodes.Upper()); |
fc9b36d6 |
161 | StdPrs_ToolShadedShape::Normal (aFace, aPolyConnect, aNormals); |
3b1817a9 |
162 | |
163 | if (theHasTexels) |
2bd4c032 |
164 | { |
3b1817a9 |
165 | BRepTools::UVBounds (aFace, aUmin, aUmax, aVmin, aVmax); |
166 | dUmax = (aUmax - aUmin); |
167 | dVmax = (aVmax - aVmin); |
168 | } |
169 | |
31c0e219 |
170 | const Standard_Integer aDecal = anArray->VertexNumber(); |
3b1817a9 |
171 | for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) |
172 | { |
31c0e219 |
173 | aPoint = aNodes (aNodeIter); |
3b1817a9 |
174 | if (!aLoc.IsIdentity()) |
2bd4c032 |
175 | { |
31c0e219 |
176 | aPoint.Transform (aTrsf); |
7d9e854b |
177 | |
178 | aNormals (aNodeIter) = aNormals (aNodeIter).Transformed (aTrsf); |
2bd4c032 |
179 | } |
3b1817a9 |
180 | |
181 | if (theHasTexels && aUVNodes.Upper() == aNodes.Upper()) |
2bd4c032 |
182 | { |
3b1817a9 |
183 | const gp_Pnt2d aTexel = gp_Pnt2d ((-theUVOrigin.X() + (theUVRepeat.X() * (aUVNodes (aNodeIter).X() - aUmin)) / dUmax) / theUVScale.X(), |
184 | (-theUVOrigin.Y() + (theUVRepeat.Y() * (aUVNodes (aNodeIter).Y() - aVmin)) / dVmax) / theUVScale.Y()); |
31c0e219 |
185 | anArray->AddVertex (aPoint, aNormals (aNodeIter), aTexel); |
2bd4c032 |
186 | } |
3b1817a9 |
187 | else |
2bd4c032 |
188 | { |
31c0e219 |
189 | anArray->AddVertex (aPoint, aNormals (aNodeIter)); |
2bd4c032 |
190 | } |
3b1817a9 |
191 | } |
2bd4c032 |
192 | |
3b1817a9 |
193 | // Fill array with vertex and edge visibility info |
31c0e219 |
194 | const Poly_Array1OfTriangle& aTriangles = aT->Triangles(); |
195 | Standard_Integer anIndex[3]; |
196 | for (Standard_Integer aTriIter = 1; aTriIter <= aT->NbTriangles(); ++aTriIter) |
3b1817a9 |
197 | { |
7d9e854b |
198 | if ((aFace.Orientation() == TopAbs_REVERSED) ^ isMirrored) |
31c0e219 |
199 | { |
200 | aTriangles (aTriIter).Get (anIndex[0], anIndex[2], anIndex[1]); |
201 | } |
3b1817a9 |
202 | else |
31c0e219 |
203 | { |
204 | aTriangles (aTriIter).Get (anIndex[0], anIndex[1], anIndex[2]); |
205 | } |
3b1817a9 |
206 | |
31c0e219 |
207 | gp_Pnt aP1 = aNodes (anIndex[0]); |
208 | gp_Pnt aP2 = aNodes (anIndex[1]); |
209 | gp_Pnt aP3 = aNodes (anIndex[2]); |
3b1817a9 |
210 | |
31c0e219 |
211 | gp_Vec aV1 (aP1, aP2); |
212 | if (aV1.SquareMagnitude() <= aPreci) |
3b1817a9 |
213 | { |
214 | continue; |
215 | } |
31c0e219 |
216 | gp_Vec aV2 (aP2, aP3); |
217 | if (aV2.SquareMagnitude() <= aPreci) |
3b1817a9 |
218 | { |
219 | continue; |
220 | } |
31c0e219 |
221 | gp_Vec aV3 (aP3, aP1); |
222 | if (aV3.SquareMagnitude() <= aPreci) |
3b1817a9 |
223 | { |
224 | continue; |
225 | } |
31c0e219 |
226 | aV1.Normalize(); |
227 | aV2.Normalize(); |
228 | aV1.Cross (aV2); |
229 | if (aV1.SquareMagnitude() > aPreci) |
2bd4c032 |
230 | { |
31c0e219 |
231 | anArray->AddEdge (anIndex[0] + aDecal); |
232 | anArray->AddEdge (anIndex[1] + aDecal); |
233 | anArray->AddEdge (anIndex[2] + aDecal); |
2bd4c032 |
234 | } |
235 | } |
2bd4c032 |
236 | } |
31c0e219 |
237 | return anArray; |
238 | } |
239 | |
31c0e219 |
240 | //! Prepare shaded presentation for specified shape |
241 | static Standard_Boolean shadeFromShape (const TopoDS_Shape& theShape, |
242 | const Handle(Prs3d_Presentation)& thePrs, |
243 | const Handle(Prs3d_Drawer)& theDrawer, |
244 | const Standard_Boolean theHasTexels, |
245 | const gp_Pnt2d& theUVOrigin, |
246 | const gp_Pnt2d& theUVRepeat, |
247 | const gp_Pnt2d& theUVScale, |
248 | const Standard_Boolean theIsClosed) |
249 | { |
250 | Handle(Graphic3d_ArrayOfTriangles) aPArray = fillTriangles (theShape, theHasTexels, theUVOrigin, theUVRepeat, theUVScale); |
251 | if (aPArray.IsNull()) |
252 | { |
253 | return Standard_False; |
254 | } |
3b1817a9 |
255 | |
31c0e219 |
256 | Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePrs); |
257 | aGroup->SetClosed (theIsClosed); |
258 | if (!theDrawer->ShadingAspectGlobal()) |
259 | { |
260 | Handle(Graphic3d_AspectFillArea3d) anAsp = theDrawer->ShadingAspect()->Aspect(); |
261 | theIsClosed ? anAsp->SuppressBackFace() : anAsp->AllowBackFace(); |
262 | aGroup->SetGroupPrimitivesAspect (anAsp); |
263 | } |
264 | aGroup->AddPrimitiveArray (aPArray); |
2bd4c032 |
265 | return Standard_True; |
266 | } |
a2d5ab2e |
267 | |
31c0e219 |
268 | //! Compute boundary presentation for faces of the shape. |
269 | static void computeFaceBoundaries (const TopoDS_Shape& theShape, |
270 | const Handle(Prs3d_Presentation)& thePrs, |
271 | const Handle(Prs3d_Drawer)& theDrawer) |
a2d5ab2e |
272 | { |
273 | // collection of all triangulation nodes on edges |
274 | // for computing boundaries presentation |
275 | NCollection_List<Handle(TColgp_HArray1OfPnt)> aNodeCollection; |
276 | Standard_Integer aNodeNumber = 0; |
277 | |
278 | TopLoc_Location aTrsf; |
279 | |
280 | // explore all boundary edges |
281 | TopTools_IndexedDataMapOfShapeListOfShape anEdgesMap; |
282 | TopExp::MapShapesAndAncestors ( |
283 | theShape, TopAbs_EDGE, TopAbs_FACE, anEdgesMap); |
284 | |
285 | Standard_Integer anEdgeIdx = 1; |
286 | for ( ; anEdgeIdx <= anEdgesMap.Extent (); anEdgeIdx++) |
287 | { |
288 | // reject free edges |
289 | const TopTools_ListOfShape& aFaceList = anEdgesMap.FindFromIndex (anEdgeIdx); |
290 | if (aFaceList.Extent() == 0) |
291 | continue; |
292 | |
293 | // take one of the shared edges and get edge triangulation |
294 | const TopoDS_Face& aFace = TopoDS::Face (aFaceList.First ()); |
295 | const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgesMap.FindKey (anEdgeIdx)); |
296 | |
297 | Handle(Poly_Triangulation) aTriangulation = |
298 | BRep_Tool::Triangulation (aFace, aTrsf); |
299 | |
300 | if (aTriangulation.IsNull ()) |
301 | continue; |
302 | |
303 | Handle(Poly_PolygonOnTriangulation) anEdgePoly = |
304 | BRep_Tool::PolygonOnTriangulation (anEdge, aTriangulation, aTrsf); |
305 | |
306 | if (anEdgePoly.IsNull ()) |
307 | continue; |
308 | |
309 | // get edge nodes indexes from face triangulation |
310 | const TColgp_Array1OfPnt& aTriNodes = aTriangulation->Nodes (); |
311 | const TColStd_Array1OfInteger& anEdgeNodes = anEdgePoly->Nodes (); |
312 | |
313 | if (anEdgeNodes.Length () < 2) |
314 | continue; |
315 | |
316 | // collect the edge nodes |
317 | Handle(TColgp_HArray1OfPnt) aCollected = |
318 | new TColgp_HArray1OfPnt (anEdgeNodes.Lower (), anEdgeNodes.Upper ()); |
319 | |
320 | Standard_Integer aNodeIdx = anEdgeNodes.Lower (); |
321 | for ( ; aNodeIdx <= anEdgeNodes.Upper (); aNodeIdx++) |
322 | { |
323 | // node index in face triangulation |
324 | Standard_Integer aTriIndex = anEdgeNodes.Value (aNodeIdx); |
325 | |
326 | // get node and apply location transformation to the node |
327 | gp_Pnt aTriNode = aTriNodes.Value (aTriIndex); |
328 | if (!aTrsf.IsIdentity ()) |
329 | aTriNode.Transform (aTrsf); |
330 | |
331 | // add node to the boundary array |
332 | aCollected->SetValue (aNodeIdx, aTriNode); |
333 | } |
334 | |
335 | aNodeNumber += anEdgeNodes.Length (); |
336 | aNodeCollection.Append (aCollected); |
337 | } |
338 | |
339 | // check if it possible to continue building the presentation |
340 | if (aNodeNumber == 0) |
341 | return; |
342 | |
343 | // allocate polyline array for presentation |
344 | Standard_Integer aSegmentEdgeNb = |
345 | (aNodeNumber - aNodeCollection.Extent()) * 2; |
346 | |
347 | Handle(Graphic3d_ArrayOfSegments) aSegments = |
348 | new Graphic3d_ArrayOfSegments (aNodeNumber, aSegmentEdgeNb); |
349 | |
350 | // build presentation for edge bondaries |
351 | NCollection_List<Handle(TColgp_HArray1OfPnt)>::Iterator |
352 | aCollIt (aNodeCollection); |
353 | |
354 | // the edge index is increased in each iteration step to |
355 | // avoid contiguous segments between different face edges. |
356 | for ( ; aCollIt.More(); aCollIt.Next () ) |
357 | { |
358 | const Handle(TColgp_HArray1OfPnt)& aNodeArray = aCollIt.Value (); |
359 | |
360 | Standard_Integer aNodeIdx = aNodeArray->Lower (); |
361 | |
362 | // add first node (this node is not shared with previous segment). |
363 | // for each face edge, indices for sharing nodes |
364 | // between segments begin from the first added node. |
365 | Standard_Integer aSegmentEdge = |
366 | aSegments->AddVertex (aNodeArray->Value (aNodeIdx)); |
367 | |
368 | // add subsequent nodes and provide edge indexes for sharing |
369 | // the nodes between the sequential segments. |
370 | for ( aNodeIdx++; aNodeIdx <= aNodeArray->Upper (); aNodeIdx++ ) |
371 | { |
372 | aSegments->AddVertex (aNodeArray->Value (aNodeIdx)); |
373 | aSegments->AddEdge ( aSegmentEdge); |
374 | aSegments->AddEdge (++aSegmentEdge); |
375 | } |
376 | } |
377 | |
378 | // set up aspect and add polyline data |
379 | Handle(Graphic3d_AspectLine3d) aBoundaryAspect = |
380 | theDrawer->FaceBoundaryAspect ()->Aspect (); |
381 | |
31c0e219 |
382 | Handle(Graphic3d_Group) aPrsGrp = Prs3d_Root::CurrentGroup (thePrs); |
a2d5ab2e |
383 | aPrsGrp->SetGroupPrimitivesAspect (aBoundaryAspect); |
a2d5ab2e |
384 | aPrsGrp->AddPrimitiveArray (aSegments); |
a2d5ab2e |
385 | } |
2bd4c032 |
386 | }; |
387 | |
5bffb882 |
388 | // ======================================================================= |
389 | // function : ExploreSolids |
390 | // purpose : |
391 | // ======================================================================= |
392 | void StdPrs_ShadedShape::ExploreSolids (const TopoDS_Shape& theShape, |
393 | const BRep_Builder& theBuilder, |
394 | TopoDS_Compound& theClosed, |
395 | TopoDS_Compound& theOpened, |
396 | const Standard_Boolean theIgnore1DSubShape) |
397 | { |
398 | if (theShape.IsNull()) |
399 | { |
400 | return; |
401 | } |
402 | |
403 | switch (theShape.ShapeType()) |
404 | { |
405 | case TopAbs_COMPOUND: |
406 | case TopAbs_COMPSOLID: |
407 | { |
408 | for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next()) |
409 | { |
410 | ExploreSolids (anIter.Value(), theBuilder, theClosed, theOpened, theIgnore1DSubShape); |
411 | } |
412 | return; |
413 | } |
414 | case TopAbs_SOLID: |
415 | { |
416 | for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next()) |
417 | { |
418 | const TopoDS_Shape& aSubShape = anIter.Value(); |
419 | const Standard_Boolean isClosed = aSubShape.ShapeType() == TopAbs_SHELL && |
420 | BRep_Tool::IsClosed (aSubShape) && |
421 | StdPrs_ToolShadedShape::IsTriangulated (aSubShape); |
422 | theBuilder.Add (isClosed ? theClosed : theOpened, aSubShape); |
423 | } |
424 | return; |
425 | } |
426 | case TopAbs_SHELL: |
427 | case TopAbs_FACE: |
428 | { |
429 | theBuilder.Add (theOpened, theShape); |
430 | return; |
431 | } |
432 | case TopAbs_WIRE: |
433 | case TopAbs_EDGE: |
434 | case TopAbs_VERTEX: |
435 | { |
436 | if (!theIgnore1DSubShape) |
437 | { |
438 | theBuilder.Add (theOpened, theShape); |
439 | } |
440 | return; |
441 | } |
442 | case TopAbs_SHAPE: |
443 | default: |
444 | return; |
445 | } |
446 | } |
447 | |
2bd4c032 |
448 | // ======================================================================= |
449 | // function : Add |
450 | // purpose : |
451 | // ======================================================================= |
31c0e219 |
452 | void StdPrs_ShadedShape::Add (const Handle(Prs3d_Presentation)& thePrs, |
453 | const TopoDS_Shape& theShape, |
454 | const Handle(Prs3d_Drawer)& theDrawer, |
5bffb882 |
455 | const StdPrs_Volume theVolume) |
2bd4c032 |
456 | { |
457 | gp_Pnt2d aDummy; |
31c0e219 |
458 | StdPrs_ShadedShape::Add (thePrs, theShape, theDrawer, |
5bffb882 |
459 | Standard_False, aDummy, aDummy, aDummy, theVolume); |
2bd4c032 |
460 | } |
461 | |
ad3217cd |
462 | // ======================================================================= |
463 | // function : Tessellate |
464 | // purpose : |
465 | // ======================================================================= |
466 | void StdPrs_ShadedShape::Tessellate (const TopoDS_Shape& theShape, |
467 | const Handle (Prs3d_Drawer)& theDrawer) |
468 | { |
31c0e219 |
469 | // Check if it is possible to avoid unnecessary recomputation of shape triangulation |
9dba391d |
470 | Standard_Real aDeflection = Prs3d::GetDeflection (theShape, theDrawer); |
ad3217cd |
471 | if (BRepTools::Triangulation (theShape, aDeflection)) |
472 | { |
473 | return; |
474 | } |
475 | |
476 | // retrieve meshing tool from Factory |
ad3217cd |
477 | Handle(BRepMesh_DiscretRoot) aMeshAlgo = BRepMesh_DiscretFactory::Get().Discret (theShape, |
478 | aDeflection, |
479 | theDrawer->HLRAngle()); |
480 | if (!aMeshAlgo.IsNull()) |
481 | { |
482 | aMeshAlgo->Perform(); |
483 | } |
484 | } |
485 | |
2bd4c032 |
486 | // ======================================================================= |
487 | // function : Add |
488 | // purpose : |
489 | // ======================================================================= |
31c0e219 |
490 | void StdPrs_ShadedShape::Add (const Handle (Prs3d_Presentation)& thePrs, |
2bd4c032 |
491 | const TopoDS_Shape& theShape, |
492 | const Handle (Prs3d_Drawer)& theDrawer, |
493 | const Standard_Boolean theHasTexels, |
494 | const gp_Pnt2d& theUVOrigin, |
495 | const gp_Pnt2d& theUVRepeat, |
31c0e219 |
496 | const gp_Pnt2d& theUVScale, |
5bffb882 |
497 | const StdPrs_Volume theVolume) |
2bd4c032 |
498 | { |
499 | if (theShape.IsNull()) |
500 | { |
501 | return; |
502 | } |
503 | |
31c0e219 |
504 | // add wireframe presentation for isolated edges and vertices |
505 | wireframeFromShape (thePrs, theShape, theDrawer); |
506 | |
4769a395 |
507 | // Triangulation completeness is important for "open-closed" analysis - perform tessellation beforehand |
31c0e219 |
508 | Tessellate (theShape, theDrawer); |
4769a395 |
509 | |
510 | // The shape types listed below need advanced analysis as potentially containing |
511 | // both closed and open parts. Solids are also included, because they might |
512 | // contain non-manifold parts inside (internal open shells) |
31c0e219 |
513 | if ((theShape.ShapeType() == TopAbs_COMPOUND |
4769a395 |
514 | || theShape.ShapeType() == TopAbs_COMPSOLID |
515 | || theShape.ShapeType() == TopAbs_SOLID) |
5bffb882 |
516 | && theVolume == StdPrs_Volume_Autodetection) |
2bd4c032 |
517 | { |
31c0e219 |
518 | // collect two compounds: for opened and closed (solid) sub-shapes |
519 | TopoDS_Compound anOpened, aClosed; |
520 | BRep_Builder aBuilder; |
521 | aBuilder.MakeCompound (aClosed); |
522 | aBuilder.MakeCompound (anOpened); |
5bffb882 |
523 | ExploreSolids (theShape, aBuilder, aClosed, anOpened, Standard_True); |
31c0e219 |
524 | |
525 | TopoDS_Iterator aShapeIter (aClosed); |
526 | if (aShapeIter.More()) |
2bd4c032 |
527 | { |
31c0e219 |
528 | shadeFromShape (aClosed, thePrs, theDrawer, |
529 | theHasTexels, theUVOrigin, theUVRepeat, theUVScale, Standard_True); |
2bd4c032 |
530 | } |
31c0e219 |
531 | |
532 | aShapeIter.Initialize (anOpened); |
533 | if (aShapeIter.More()) |
2bd4c032 |
534 | { |
31c0e219 |
535 | shadeFromShape (anOpened, thePrs, theDrawer, |
536 | theHasTexels, theUVOrigin, theUVRepeat, theUVScale, Standard_False); |
2bd4c032 |
537 | } |
538 | } |
31c0e219 |
539 | else |
540 | { |
5bffb882 |
541 | // if the shape type is not compound, composolid or solid, use autodetection back-facing filled |
31c0e219 |
542 | shadeFromShape (theShape, thePrs, theDrawer, |
4769a395 |
543 | theHasTexels, theUVOrigin, theUVRepeat, theUVScale, |
5bffb882 |
544 | (theVolume == StdPrs_Volume_Closed ? Standard_True : Standard_False)); |
31c0e219 |
545 | } |
2bd4c032 |
546 | |
31c0e219 |
547 | if (theDrawer->IsFaceBoundaryDraw()) |
a2d5ab2e |
548 | { |
31c0e219 |
549 | computeFaceBoundaries (theShape, thePrs, theDrawer); |
a2d5ab2e |
550 | } |
551 | } |