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> |
2bd4c032 |
20 | #include <BRepTools.hxx> |
5ad8c033 |
21 | #include <BRepBndLib.hxx> |
22 | #include <BRep_Builder.hxx> |
23 | #include <BRep_Tool.hxx> |
31c0e219 |
24 | #include <Graphic3d_ArrayOfSegments.hxx> |
2bd4c032 |
25 | #include <Graphic3d_ArrayOfTriangles.hxx> |
26 | #include <Graphic3d_AspectFillArea3d.hxx> |
27 | #include <Graphic3d_Group.hxx> |
28 | #include <gp_Dir.hxx> |
29 | #include <gp_Vec.hxx> |
30 | #include <gp_Pnt.hxx> |
8f08e231 |
31 | #include <NCollection_IncAllocator.hxx> |
31c0e219 |
32 | #include <NCollection_List.hxx> |
8f08e231 |
33 | #include <NCollection_Shared.hxx> |
2bd4c032 |
34 | #include <Precision.hxx> |
35 | #include <Prs3d_Drawer.hxx> |
4c513386 |
36 | #include <Prs3d_IsoAspect.hxx> |
31c0e219 |
37 | #include <Prs3d_LineAspect.hxx> |
2bd4c032 |
38 | #include <Prs3d_Presentation.hxx> |
39 | #include <Prs3d_ShadingAspect.hxx> |
40 | #include <Poly_Connect.hxx> |
31c0e219 |
41 | #include <Poly_PolygonOnTriangulation.hxx> |
2bd4c032 |
42 | #include <Poly_Triangulation.hxx> |
5ad8c033 |
43 | #include <StdPrs_ToolTriangulatedShape.hxx> |
2bd4c032 |
44 | #include <StdPrs_WFShape.hxx> |
31c0e219 |
45 | #include <TopExp.hxx> |
fc9b36d6 |
46 | #include <TopExp_Explorer.hxx> |
47 | #include <TopoDS.hxx> |
31c0e219 |
48 | #include <TopoDS_Compound.hxx> |
2bd4c032 |
49 | #include <TopoDS_Face.hxx> |
31c0e219 |
50 | #include <TopoDS_Shape.hxx> |
2bd4c032 |
51 | #include <TColgp_Array1OfDir.hxx> |
52 | #include <TColgp_Array1OfPnt2d.hxx> |
31c0e219 |
53 | #include <TColgp_HArray1OfPnt.hxx> |
a2d5ab2e |
54 | #include <TopTools_ListOfShape.hxx> |
55 | #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> |
2bd4c032 |
56 | |
57 | namespace |
58 | { |
31c0e219 |
59 | |
60 | //! Computes wireframe presentation for free wires and vertices |
61 | void wireframeFromShape (const Handle (Prs3d_Presentation)& thePrs, |
62 | const TopoDS_Shape& theShape, |
63 | const Handle (Prs3d_Drawer)& theDrawer) |
64 | { |
b6826918 |
65 | TopExp_Explorer aShapeIter (theShape, TopAbs_FACE); |
66 | if (!aShapeIter.More()) |
31c0e219 |
67 | { |
b6826918 |
68 | StdPrs_WFShape::Add (thePrs, theShape, theDrawer); |
31c0e219 |
69 | return; |
70 | } |
71 | |
b6826918 |
72 | const Standard_Boolean aDrawAllVerticesFlag = (theDrawer->VertexDrawMode() == Prs3d_VDM_All); |
73 | if (!aDrawAllVerticesFlag && theShape.ShapeType() != TopAbs_COMPOUND) |
31c0e219 |
74 | { |
31c0e219 |
75 | return; |
76 | } |
77 | |
53b15292 |
78 | // We have to create a compound and collect all subshapes not drawn by the shading algo. |
79 | // This includes: |
80 | // - isolated edges |
81 | // - isolated vertices, if aDrawAllVerticesFlag == Standard_False |
82 | // - all shape's vertices, if aDrawAllVerticesFlag == Standard_True |
31c0e219 |
83 | TopoDS_Compound aCompoundWF; |
84 | BRep_Builder aBuilder; |
85 | aBuilder.MakeCompound (aCompoundWF); |
86 | Standard_Boolean hasElement = Standard_False; |
87 | |
88 | // isolated edges |
89 | for (aShapeIter.Init (theShape, TopAbs_EDGE, TopAbs_FACE); aShapeIter.More(); aShapeIter.Next()) |
90 | { |
91 | hasElement = Standard_True; |
92 | aBuilder.Add (aCompoundWF, aShapeIter.Current()); |
93 | } |
53b15292 |
94 | // isolated or all vertices |
95 | aShapeIter.Init (theShape, TopAbs_VERTEX, aDrawAllVerticesFlag ? TopAbs_SHAPE : TopAbs_EDGE); |
96 | for (; aShapeIter.More(); aShapeIter.Next()) |
31c0e219 |
97 | { |
98 | hasElement = Standard_True; |
99 | aBuilder.Add (aCompoundWF, aShapeIter.Current()); |
100 | } |
101 | if (hasElement) |
102 | { |
5ad8c033 |
103 | StdPrs_WFShape::Add (thePrs, aCompoundWF, theDrawer); |
31c0e219 |
104 | } |
105 | } |
106 | |
4c513386 |
107 | //! Computes special wireframe presentation for faces without triangulation. |
108 | void wireframeNoTriangFacesFromShape (const Handle(Prs3d_Presentation)& thePrs, |
109 | const TopoDS_Shape& theShape, |
110 | const Handle(Prs3d_Drawer)& theDrawer) |
111 | { |
112 | TopoDS_Compound aCompoundWF; |
113 | BRep_Builder aBuilder; |
114 | aBuilder.MakeCompound (aCompoundWF); |
115 | TopLoc_Location aLoc; |
116 | Standard_Boolean hasElement = Standard_False; |
117 | |
118 | for (TopExp_Explorer aShapeIter(theShape, TopAbs_FACE); aShapeIter.More(); aShapeIter.Next()) |
119 | { |
120 | const TopoDS_Face& aFace = TopoDS::Face (aShapeIter.Current()); |
121 | const Handle(Poly_Triangulation) aTriang = BRep_Tool::Triangulation (aFace, aLoc); |
122 | if (aTriang.IsNull()) |
123 | { |
124 | hasElement = Standard_True; |
125 | aBuilder.Add (aCompoundWF, aFace); |
126 | } |
127 | } |
128 | |
129 | if (hasElement) |
130 | { |
131 | Standard_Integer aPrevUIsoNb = theDrawer->UIsoAspect()->Number(); |
132 | Standard_Integer aPrevVIsoNb = theDrawer->VIsoAspect()->Number(); |
133 | theDrawer->UIsoAspect()->SetNumber (5); |
134 | theDrawer->VIsoAspect()->SetNumber (5); |
135 | |
5ad8c033 |
136 | StdPrs_WFShape::Add (thePrs, aCompoundWF, theDrawer); |
4c513386 |
137 | |
138 | theDrawer->UIsoAspect()->SetNumber (aPrevUIsoNb); |
139 | theDrawer->VIsoAspect()->SetNumber (aPrevVIsoNb); |
140 | } |
141 | } |
142 | |
31c0e219 |
143 | //! Gets triangulation of every face of shape and fills output array of triangles |
144 | static Handle(Graphic3d_ArrayOfTriangles) fillTriangles (const TopoDS_Shape& theShape, |
145 | const Standard_Boolean theHasTexels, |
146 | const gp_Pnt2d& theUVOrigin, |
147 | const gp_Pnt2d& theUVRepeat, |
148 | const gp_Pnt2d& theUVScale) |
2bd4c032 |
149 | { |
31c0e219 |
150 | Handle(Poly_Triangulation) aT; |
2bd4c032 |
151 | TopLoc_Location aLoc; |
31c0e219 |
152 | gp_Pnt aPoint; |
153 | Standard_Integer aNbTriangles = 0; |
154 | Standard_Integer aNbVertices = 0; |
2bd4c032 |
155 | |
31c0e219 |
156 | // Precision for compare square distances |
3b1817a9 |
157 | const Standard_Real aPreci = Precision::SquareConfusion(); |
2bd4c032 |
158 | |
fc9b36d6 |
159 | TopExp_Explorer aFaceIt(theShape, TopAbs_FACE); |
160 | for (; aFaceIt.More(); aFaceIt.Next()) |
2bd4c032 |
161 | { |
fc9b36d6 |
162 | const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current()); |
5ad8c033 |
163 | aT = BRep_Tool::Triangulation (aFace, aLoc); |
31c0e219 |
164 | if (!aT.IsNull()) |
2bd4c032 |
165 | { |
31c0e219 |
166 | aNbTriangles += aT->NbTriangles(); |
167 | aNbVertices += aT->NbNodes(); |
2bd4c032 |
168 | } |
2bd4c032 |
169 | } |
31c0e219 |
170 | if (aNbVertices < 3 || aNbTriangles <= 0) |
2bd4c032 |
171 | { |
31c0e219 |
172 | return Handle(Graphic3d_ArrayOfTriangles)(); |
3b1817a9 |
173 | } |
2bd4c032 |
174 | |
31c0e219 |
175 | Handle(Graphic3d_ArrayOfTriangles) anArray = new Graphic3d_ArrayOfTriangles (aNbVertices, 3 * aNbTriangles, |
871fa103 |
176 | Standard_True, Standard_False, theHasTexels); |
31c0e219 |
177 | Standard_Real aUmin (0.0), aUmax (0.0), aVmin (0.0), aVmax (0.0), dUmax (0.0), dVmax (0.0); |
fc9b36d6 |
178 | for (aFaceIt.Init (theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next()) |
2bd4c032 |
179 | { |
fc9b36d6 |
180 | const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current()); |
5ad8c033 |
181 | aT = BRep_Tool::Triangulation (aFace, aLoc); |
31c0e219 |
182 | if (aT.IsNull()) |
3b1817a9 |
183 | { |
184 | continue; |
185 | } |
186 | const gp_Trsf& aTrsf = aLoc.Transformation(); |
7d9e854b |
187 | |
188 | // Determinant of transform matrix less then 0 means that mirror transform applied. |
189 | Standard_Boolean isMirrored = aTrsf.VectorialPart().Determinant() < 0; |
190 | |
3b1817a9 |
191 | // Extracts vertices & normals from nodes |
31c0e219 |
192 | const TColgp_Array1OfPnt& aNodes = aT->Nodes(); |
aff73fd5 |
193 | const TColgp_Array1OfPnt2d* aUVNodes = theHasTexels && aT->HasUVNodes() && aT->UVNodes().Upper() == aNodes.Upper() |
194 | ? &aT->UVNodes() |
195 | : NULL; |
450c83ad |
196 | StdPrs_ToolTriangulatedShape::ComputeNormals (aFace, aT); |
f4064435 |
197 | const TShort_Array1OfShortReal& aNormals = aT->Normals(); |
198 | const Standard_ShortReal* aNormArr = &aNormals.First(); |
3b1817a9 |
199 | |
200 | if (theHasTexels) |
2bd4c032 |
201 | { |
3b1817a9 |
202 | BRepTools::UVBounds (aFace, aUmin, aUmax, aVmin, aVmax); |
203 | dUmax = (aUmax - aUmin); |
204 | dVmax = (aVmax - aVmin); |
205 | } |
206 | |
31c0e219 |
207 | const Standard_Integer aDecal = anArray->VertexNumber(); |
3b1817a9 |
208 | for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) |
209 | { |
31c0e219 |
210 | aPoint = aNodes (aNodeIter); |
f4064435 |
211 | const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower()); |
212 | gp_Dir aNorm (aNormArr[anId + 0], aNormArr[anId + 1], aNormArr[anId + 2]); |
6b9b7e3c |
213 | if ((aFace.Orientation() == TopAbs_REVERSED) ^ isMirrored) |
f4064435 |
214 | { |
215 | aNorm.Reverse(); |
216 | } |
3b1817a9 |
217 | if (!aLoc.IsIdentity()) |
2bd4c032 |
218 | { |
31c0e219 |
219 | aPoint.Transform (aTrsf); |
f4064435 |
220 | aNorm.Transform (aTrsf); |
2bd4c032 |
221 | } |
3b1817a9 |
222 | |
aff73fd5 |
223 | if (aUVNodes != NULL) |
2bd4c032 |
224 | { |
d0510644 |
225 | const gp_Pnt2d aTexel = (dUmax == 0.0 || dVmax == 0.0) |
aff73fd5 |
226 | ? aUVNodes->Value (aNodeIter) |
227 | : gp_Pnt2d ((-theUVOrigin.X() + (theUVRepeat.X() * (aUVNodes->Value (aNodeIter).X() - aUmin)) / dUmax) / theUVScale.X(), |
228 | (-theUVOrigin.Y() + (theUVRepeat.Y() * (aUVNodes->Value (aNodeIter).Y() - aVmin)) / dVmax) / theUVScale.Y()); |
f4064435 |
229 | anArray->AddVertex (aPoint, aNorm, aTexel); |
2bd4c032 |
230 | } |
3b1817a9 |
231 | else |
2bd4c032 |
232 | { |
f4064435 |
233 | anArray->AddVertex (aPoint, aNorm); |
2bd4c032 |
234 | } |
3b1817a9 |
235 | } |
2bd4c032 |
236 | |
3b1817a9 |
237 | // Fill array with vertex and edge visibility info |
31c0e219 |
238 | const Poly_Array1OfTriangle& aTriangles = aT->Triangles(); |
239 | Standard_Integer anIndex[3]; |
240 | for (Standard_Integer aTriIter = 1; aTriIter <= aT->NbTriangles(); ++aTriIter) |
3b1817a9 |
241 | { |
6b9b7e3c |
242 | if ((aFace.Orientation() == TopAbs_REVERSED)) |
31c0e219 |
243 | { |
244 | aTriangles (aTriIter).Get (anIndex[0], anIndex[2], anIndex[1]); |
245 | } |
3b1817a9 |
246 | else |
31c0e219 |
247 | { |
248 | aTriangles (aTriIter).Get (anIndex[0], anIndex[1], anIndex[2]); |
249 | } |
3b1817a9 |
250 | |
31c0e219 |
251 | gp_Pnt aP1 = aNodes (anIndex[0]); |
252 | gp_Pnt aP2 = aNodes (anIndex[1]); |
253 | gp_Pnt aP3 = aNodes (anIndex[2]); |
3b1817a9 |
254 | |
31c0e219 |
255 | gp_Vec aV1 (aP1, aP2); |
256 | if (aV1.SquareMagnitude() <= aPreci) |
3b1817a9 |
257 | { |
258 | continue; |
259 | } |
31c0e219 |
260 | gp_Vec aV2 (aP2, aP3); |
261 | if (aV2.SquareMagnitude() <= aPreci) |
3b1817a9 |
262 | { |
263 | continue; |
264 | } |
31c0e219 |
265 | gp_Vec aV3 (aP3, aP1); |
266 | if (aV3.SquareMagnitude() <= aPreci) |
3b1817a9 |
267 | { |
268 | continue; |
269 | } |
31c0e219 |
270 | aV1.Normalize(); |
271 | aV2.Normalize(); |
272 | aV1.Cross (aV2); |
273 | if (aV1.SquareMagnitude() > aPreci) |
2bd4c032 |
274 | { |
fb60181a |
275 | anArray->AddEdges (anIndex[0] + aDecal, |
276 | anIndex[1] + aDecal, |
277 | anIndex[2] + aDecal); |
2bd4c032 |
278 | } |
279 | } |
2bd4c032 |
280 | } |
31c0e219 |
281 | return anArray; |
282 | } |
283 | |
31c0e219 |
284 | //! Prepare shaded presentation for specified shape |
285 | static Standard_Boolean shadeFromShape (const TopoDS_Shape& theShape, |
286 | const Handle(Prs3d_Presentation)& thePrs, |
287 | const Handle(Prs3d_Drawer)& theDrawer, |
288 | const Standard_Boolean theHasTexels, |
289 | const gp_Pnt2d& theUVOrigin, |
290 | const gp_Pnt2d& theUVRepeat, |
291 | const gp_Pnt2d& theUVScale, |
b6472664 |
292 | const bool theIsClosed) |
31c0e219 |
293 | { |
294 | Handle(Graphic3d_ArrayOfTriangles) aPArray = fillTriangles (theShape, theHasTexels, theUVOrigin, theUVRepeat, theUVScale); |
295 | if (aPArray.IsNull()) |
296 | { |
297 | return Standard_False; |
298 | } |
3b1817a9 |
299 | |
31c0e219 |
300 | Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePrs); |
301 | aGroup->SetClosed (theIsClosed); |
6887652a |
302 | aGroup->SetGroupPrimitivesAspect (theDrawer->ShadingAspect()->Aspect()); |
31c0e219 |
303 | aGroup->AddPrimitiveArray (aPArray); |
2bd4c032 |
304 | return Standard_True; |
305 | } |
a2d5ab2e |
306 | |
31c0e219 |
307 | //! Compute boundary presentation for faces of the shape. |
0493ffd0 |
308 | static Handle(Graphic3d_ArrayOfSegments) fillFaceBoundaries (const TopoDS_Shape& theShape, |
309 | GeomAbs_Shape theUpperContinuity) |
a2d5ab2e |
310 | { |
311 | // collection of all triangulation nodes on edges |
312 | // for computing boundaries presentation |
a2d5ab2e |
313 | Standard_Integer aNodeNumber = 0; |
1b9f5d95 |
314 | Standard_Integer aNbPolylines = 0; |
a2d5ab2e |
315 | |
316 | TopLoc_Location aTrsf; |
8f08e231 |
317 | |
318 | Handle(NCollection_Shared<TColgp_SequenceOfPnt>) aSeqPntsExtra; |
0a863061 |
319 | for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next()) |
320 | { |
321 | const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current()); |
b2d1851c |
322 | if (aFace.NbChildren() == 0) |
0a863061 |
323 | { |
324 | // handle specifically faces without boundary definition (triangulation-only) |
8f08e231 |
325 | if (aSeqPntsExtra.IsNull()) |
326 | { |
327 | Handle(NCollection_IncAllocator) anIncAlloc = new NCollection_IncAllocator(); |
328 | aSeqPntsExtra = new NCollection_Shared<TColgp_SequenceOfPnt> (anIncAlloc); |
329 | } |
330 | StdPrs_WFShape::AddEdgesOnTriangulation (*aSeqPntsExtra, aFace, Standard_False); |
0a863061 |
331 | } |
332 | } |
a2d5ab2e |
333 | |
334 | // explore all boundary edges |
335 | TopTools_IndexedDataMapOfShapeListOfShape anEdgesMap; |
1b9f5d95 |
336 | TopExp::MapShapesAndAncestors (theShape, TopAbs_EDGE, TopAbs_FACE, anEdgesMap); |
337 | for (TopTools_IndexedDataMapOfShapeListOfShape::Iterator anEdgeIter (anEdgesMap); anEdgeIter.More(); anEdgeIter.Next()) |
a2d5ab2e |
338 | { |
339 | // reject free edges |
1b9f5d95 |
340 | if (anEdgeIter.Value().Extent() == 0) |
341 | { |
a2d5ab2e |
342 | continue; |
1b9f5d95 |
343 | } |
a2d5ab2e |
344 | |
345 | // take one of the shared edges and get edge triangulation |
1b9f5d95 |
346 | const TopoDS_Face& aFace = TopoDS::Face (anEdgeIter.Value().First()); |
347 | Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aTrsf); |
348 | if (aTriangulation.IsNull()) |
349 | { |
350 | continue; |
351 | } |
a2d5ab2e |
352 | |
1b9f5d95 |
353 | const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Key()); |
0493ffd0 |
354 | if (theUpperContinuity < GeomAbs_CN |
355 | && anEdgeIter.Value().Extent() >= 2 |
356 | && BRep_Tool::MaxContinuity (anEdge) > theUpperContinuity) |
357 | { |
358 | continue; |
359 | } |
360 | |
1b9f5d95 |
361 | Handle(Poly_PolygonOnTriangulation) anEdgePoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTriangulation, aTrsf); |
362 | if (!anEdgePoly.IsNull() |
363 | && anEdgePoly->Nodes().Length() >= 2) |
364 | { |
365 | aNodeNumber += anEdgePoly->Nodes().Length(); |
366 | ++aNbPolylines; |
367 | } |
368 | } |
8f08e231 |
369 | const Standard_Integer aNbExtra = !aSeqPntsExtra.IsNull() ? aSeqPntsExtra->Size() : 0; |
1b9f5d95 |
370 | if (aNodeNumber == 0) |
371 | { |
8f08e231 |
372 | if (aNbExtra < 2) |
0a863061 |
373 | { |
374 | return Handle(Graphic3d_ArrayOfSegments)(); |
375 | } |
376 | |
8f08e231 |
377 | Handle(Graphic3d_ArrayOfSegments) aSegments = new Graphic3d_ArrayOfSegments (aNbExtra); |
378 | for (TColgp_SequenceOfPnt::Iterator aPntIter (*aSeqPntsExtra); aPntIter.More(); aPntIter.Next()) |
0a863061 |
379 | { |
8f08e231 |
380 | aSegments->AddVertex (aPntIter.Value()); |
0a863061 |
381 | } |
382 | return aSegments; |
1b9f5d95 |
383 | } |
a2d5ab2e |
384 | |
1b9f5d95 |
385 | // create indexed segments array to pack polylines from different edges into single array |
386 | const Standard_Integer aSegmentEdgeNb = (aNodeNumber - aNbPolylines) * 2; |
8f08e231 |
387 | Handle(Graphic3d_ArrayOfSegments) aSegments = new Graphic3d_ArrayOfSegments (aNodeNumber + aNbExtra, aSegmentEdgeNb + aNbExtra); |
1b9f5d95 |
388 | for (TopTools_IndexedDataMapOfShapeListOfShape::Iterator anEdgeIter (anEdgesMap); anEdgeIter.More(); anEdgeIter.Next()) |
389 | { |
390 | if (anEdgeIter.Value().Extent() == 0) |
391 | { |
a2d5ab2e |
392 | continue; |
1b9f5d95 |
393 | } |
a2d5ab2e |
394 | |
1b9f5d95 |
395 | const TopoDS_Face& aFace = TopoDS::Face (anEdgeIter.Value().First()); |
396 | Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aTrsf); |
397 | if (aTriangulation.IsNull()) |
398 | { |
399 | continue; |
400 | } |
a2d5ab2e |
401 | |
1b9f5d95 |
402 | const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Key()); |
0493ffd0 |
403 | if (theUpperContinuity < GeomAbs_CN |
404 | && anEdgeIter.Value().Extent() >= 2 |
405 | && BRep_Tool::MaxContinuity (anEdge) > theUpperContinuity) |
406 | { |
407 | continue; |
408 | } |
409 | |
1b9f5d95 |
410 | Handle(Poly_PolygonOnTriangulation) anEdgePoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTriangulation, aTrsf); |
411 | if (anEdgePoly.IsNull() |
412 | || anEdgePoly->Nodes().Length () < 2) |
413 | { |
a2d5ab2e |
414 | continue; |
1b9f5d95 |
415 | } |
a2d5ab2e |
416 | |
417 | // get edge nodes indexes from face triangulation |
1b9f5d95 |
418 | const TColgp_Array1OfPnt& aTriNodes = aTriangulation->Nodes(); |
419 | const TColStd_Array1OfInteger& anEdgeNodes = anEdgePoly->Nodes(); |
a2d5ab2e |
420 | |
421 | // collect the edge nodes |
1b9f5d95 |
422 | Standard_Integer aSegmentEdge = aSegments->VertexNumber() + 1; |
423 | for (Standard_Integer aNodeIdx = anEdgeNodes.Lower(); aNodeIdx <= anEdgeNodes.Upper(); ++aNodeIdx) |
a2d5ab2e |
424 | { |
425 | // node index in face triangulation |
a2d5ab2e |
426 | // get node and apply location transformation to the node |
1b9f5d95 |
427 | const Standard_Integer aTriIndex = anEdgeNodes.Value (aNodeIdx); |
a2d5ab2e |
428 | gp_Pnt aTriNode = aTriNodes.Value (aTriIndex); |
1b9f5d95 |
429 | if (!aTrsf.IsIdentity()) |
430 | { |
a2d5ab2e |
431 | aTriNode.Transform (aTrsf); |
1b9f5d95 |
432 | } |
a2d5ab2e |
433 | |
1b9f5d95 |
434 | aSegments->AddVertex (aTriNode); |
435 | if (aNodeIdx != anEdgeNodes.Lower()) |
436 | { |
437 | aSegments->AddEdge ( aSegmentEdge); |
438 | aSegments->AddEdge (++aSegmentEdge); |
439 | } |
a2d5ab2e |
440 | } |
441 | } |
0a863061 |
442 | |
8f08e231 |
443 | if (!aSeqPntsExtra.IsNull()) |
0a863061 |
444 | { |
445 | Standard_Integer aSegmentEdge = aSegments->VertexNumber(); |
8f08e231 |
446 | for (TColgp_SequenceOfPnt::Iterator aPntIter (*aSeqPntsExtra); aPntIter.More(); aPntIter.Next()) |
0a863061 |
447 | { |
8f08e231 |
448 | aSegments->AddVertex (aPntIter.Value()); |
0a863061 |
449 | aSegments->AddEdge (++aSegmentEdge); |
450 | } |
451 | } |
452 | |
9c86076b |
453 | return aSegments; |
a2d5ab2e |
454 | } |
68858c7d |
455 | |
456 | } // anonymous namespace |
2bd4c032 |
457 | |
5bffb882 |
458 | // ======================================================================= |
459 | // function : ExploreSolids |
460 | // purpose : |
461 | // ======================================================================= |
462 | void StdPrs_ShadedShape::ExploreSolids (const TopoDS_Shape& theShape, |
463 | const BRep_Builder& theBuilder, |
464 | TopoDS_Compound& theClosed, |
465 | TopoDS_Compound& theOpened, |
466 | const Standard_Boolean theIgnore1DSubShape) |
467 | { |
468 | if (theShape.IsNull()) |
469 | { |
470 | return; |
471 | } |
472 | |
473 | switch (theShape.ShapeType()) |
474 | { |
475 | case TopAbs_COMPOUND: |
476 | case TopAbs_COMPSOLID: |
477 | { |
478 | for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next()) |
479 | { |
480 | ExploreSolids (anIter.Value(), theBuilder, theClosed, theOpened, theIgnore1DSubShape); |
481 | } |
482 | return; |
483 | } |
484 | case TopAbs_SOLID: |
485 | { |
486 | for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next()) |
487 | { |
488 | const TopoDS_Shape& aSubShape = anIter.Value(); |
489 | const Standard_Boolean isClosed = aSubShape.ShapeType() == TopAbs_SHELL && |
490 | BRep_Tool::IsClosed (aSubShape) && |
5ad8c033 |
491 | StdPrs_ToolTriangulatedShape::IsTriangulated (aSubShape); |
5bffb882 |
492 | theBuilder.Add (isClosed ? theClosed : theOpened, aSubShape); |
493 | } |
494 | return; |
495 | } |
496 | case TopAbs_SHELL: |
497 | case TopAbs_FACE: |
498 | { |
499 | theBuilder.Add (theOpened, theShape); |
500 | return; |
501 | } |
502 | case TopAbs_WIRE: |
503 | case TopAbs_EDGE: |
504 | case TopAbs_VERTEX: |
505 | { |
506 | if (!theIgnore1DSubShape) |
507 | { |
508 | theBuilder.Add (theOpened, theShape); |
509 | } |
510 | return; |
511 | } |
512 | case TopAbs_SHAPE: |
513 | default: |
514 | return; |
515 | } |
516 | } |
517 | |
2bd4c032 |
518 | // ======================================================================= |
519 | // function : Add |
520 | // purpose : |
521 | // ======================================================================= |
31c0e219 |
522 | void StdPrs_ShadedShape::Add (const Handle(Prs3d_Presentation)& thePrs, |
523 | const TopoDS_Shape& theShape, |
524 | const Handle(Prs3d_Drawer)& theDrawer, |
5bffb882 |
525 | const StdPrs_Volume theVolume) |
2bd4c032 |
526 | { |
527 | gp_Pnt2d aDummy; |
31c0e219 |
528 | StdPrs_ShadedShape::Add (thePrs, theShape, theDrawer, |
5bffb882 |
529 | Standard_False, aDummy, aDummy, aDummy, theVolume); |
2bd4c032 |
530 | } |
531 | |
532 | // ======================================================================= |
533 | // function : Add |
534 | // purpose : |
535 | // ======================================================================= |
31c0e219 |
536 | void StdPrs_ShadedShape::Add (const Handle (Prs3d_Presentation)& thePrs, |
2bd4c032 |
537 | const TopoDS_Shape& theShape, |
538 | const Handle (Prs3d_Drawer)& theDrawer, |
539 | const Standard_Boolean theHasTexels, |
540 | const gp_Pnt2d& theUVOrigin, |
541 | const gp_Pnt2d& theUVRepeat, |
31c0e219 |
542 | const gp_Pnt2d& theUVScale, |
5bffb882 |
543 | const StdPrs_Volume theVolume) |
2bd4c032 |
544 | { |
545 | if (theShape.IsNull()) |
546 | { |
547 | return; |
548 | } |
549 | |
4c513386 |
550 | // Use automatic re-triangulation with deflection-check logic only if this feature is enable |
551 | if (theDrawer->IsAutoTriangulation()) |
552 | { |
553 | // Triangulation completeness is important for "open-closed" analysis - perform tessellation beforehand |
5ad8c033 |
554 | StdPrs_ToolTriangulatedShape::Tessellate (theShape, theDrawer); |
4c513386 |
555 | } |
556 | |
29263c94 |
557 | // add wireframe presentation for isolated edges and vertices |
558 | wireframeFromShape (thePrs, theShape, theDrawer); |
559 | |
4c513386 |
560 | // add special wireframe presentation for faces without triangulation |
561 | wireframeNoTriangFacesFromShape (thePrs, theShape, theDrawer); |
4769a395 |
562 | |
563 | // The shape types listed below need advanced analysis as potentially containing |
564 | // both closed and open parts. Solids are also included, because they might |
565 | // contain non-manifold parts inside (internal open shells) |
31c0e219 |
566 | if ((theShape.ShapeType() == TopAbs_COMPOUND |
4769a395 |
567 | || theShape.ShapeType() == TopAbs_COMPSOLID |
568 | || theShape.ShapeType() == TopAbs_SOLID) |
5bffb882 |
569 | && theVolume == StdPrs_Volume_Autodetection) |
2bd4c032 |
570 | { |
31c0e219 |
571 | // collect two compounds: for opened and closed (solid) sub-shapes |
572 | TopoDS_Compound anOpened, aClosed; |
573 | BRep_Builder aBuilder; |
574 | aBuilder.MakeCompound (aClosed); |
575 | aBuilder.MakeCompound (anOpened); |
5bffb882 |
576 | ExploreSolids (theShape, aBuilder, aClosed, anOpened, Standard_True); |
31c0e219 |
577 | |
b2d1851c |
578 | if (aClosed.NbChildren() > 0) |
2bd4c032 |
579 | { |
31c0e219 |
580 | shadeFromShape (aClosed, thePrs, theDrawer, |
b6472664 |
581 | theHasTexels, theUVOrigin, theUVRepeat, theUVScale, true); |
2bd4c032 |
582 | } |
31c0e219 |
583 | |
b2d1851c |
584 | if (anOpened.NbChildren() > 0) |
2bd4c032 |
585 | { |
31c0e219 |
586 | shadeFromShape (anOpened, thePrs, theDrawer, |
b6472664 |
587 | theHasTexels, theUVOrigin, theUVRepeat, theUVScale, false); |
2bd4c032 |
588 | } |
589 | } |
31c0e219 |
590 | else |
591 | { |
5bffb882 |
592 | // if the shape type is not compound, composolid or solid, use autodetection back-facing filled |
31c0e219 |
593 | shadeFromShape (theShape, thePrs, theDrawer, |
4769a395 |
594 | theHasTexels, theUVOrigin, theUVRepeat, theUVScale, |
b6472664 |
595 | theVolume == StdPrs_Volume_Closed); |
31c0e219 |
596 | } |
2bd4c032 |
597 | |
6262338c |
598 | if (theDrawer->FaceBoundaryDraw()) |
a2d5ab2e |
599 | { |
0493ffd0 |
600 | if (Handle(Graphic3d_ArrayOfSegments) aBndSegments = fillFaceBoundaries (theShape, theDrawer->FaceBoundaryUpperContinuity())) |
9c86076b |
601 | { |
bf5f0ca2 |
602 | Handle(Graphic3d_Group) aPrsGrp = thePrs->NewGroup(); |
0493ffd0 |
603 | aPrsGrp->SetGroupPrimitivesAspect (theDrawer->FaceBoundaryAspect()->Aspect()); |
9c86076b |
604 | aPrsGrp->AddPrimitiveArray (aBndSegments); |
605 | } |
a2d5ab2e |
606 | } |
607 | } |
9c86076b |
608 | |
609 | // ======================================================================= |
610 | // function : FillTriangles |
611 | // purpose : |
612 | // ======================================================================= |
613 | Handle(Graphic3d_ArrayOfTriangles) StdPrs_ShadedShape::FillTriangles (const TopoDS_Shape& theShape, |
614 | const Standard_Boolean theHasTexels, |
615 | const gp_Pnt2d& theUVOrigin, |
616 | const gp_Pnt2d& theUVRepeat, |
617 | const gp_Pnt2d& theUVScale) |
618 | { |
619 | return fillTriangles (theShape, theHasTexels, theUVOrigin, theUVRepeat, theUVScale); |
620 | } |
621 | |
622 | // ======================================================================= |
623 | // function : FillFaceBoundaries |
624 | // purpose : |
625 | // ======================================================================= |
0493ffd0 |
626 | Handle(Graphic3d_ArrayOfSegments) StdPrs_ShadedShape::FillFaceBoundaries (const TopoDS_Shape& theShape, |
627 | GeomAbs_Shape theUpperContinuity) |
9c86076b |
628 | { |
0493ffd0 |
629 | return fillFaceBoundaries (theShape, theUpperContinuity); |
9c86076b |
630 | } |
631 | |
632 | // ======================================================================= |
633 | // function : AddWireframeForFreeElements |
634 | // purpose : |
635 | // ======================================================================= |
636 | void StdPrs_ShadedShape::AddWireframeForFreeElements (const Handle (Prs3d_Presentation)& thePrs, |
637 | const TopoDS_Shape& theShape, |
638 | const Handle (Prs3d_Drawer)& theDrawer) |
639 | { |
640 | wireframeFromShape (thePrs, theShape, theDrawer); |
641 | } |
642 | |
643 | // ======================================================================= |
644 | // function : AddWireframeForFacesWithoutTriangles |
645 | // purpose : |
646 | // ======================================================================= |
647 | void StdPrs_ShadedShape::AddWireframeForFacesWithoutTriangles (const Handle(Prs3d_Presentation)& thePrs, |
648 | const TopoDS_Shape& theShape, |
649 | const Handle(Prs3d_Drawer)& theDrawer) |
650 | { |
651 | wireframeNoTriangFacesFromShape (thePrs, theShape, theDrawer); |
652 | } |