0027596: Visualization, StdPrs_WFShape - pack isolines into single group of primitives
[occt.git] / src / StdPrs / StdPrs_WFShape.cxx
CommitLineData
5ad8c033 1// Created on: 2014-10-14
2// Created by: Anton POLETAEV
3// Copyright (c) 2013-2014 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16#include <StdPrs_WFShape.hxx>
17
18#include <BRep_Tool.hxx>
19#include <BRepAdaptor_Curve.hxx>
20#include <BRepAdaptor_Surface.hxx>
21#include <BRepAdaptor_HSurface.hxx>
22#include <StdPrs_DeflectionCurve.hxx>
23#include <StdPrs_ToolTriangulatedShape.hxx>
24#include <StdPrs_Isolines.hxx>
25#include <Standard_ErrorHandler.hxx>
26#include <Prs3d_ShapeTool.hxx>
27#include <Prs3d_IsoAspect.hxx>
5ad8c033 28#include <Prs3d.hxx>
29#include <Poly_Connect.hxx>
30#include <Poly_PolygonOnTriangulation.hxx>
31#include <Poly_Polygon3D.hxx>
32#include <Poly_Triangulation.hxx>
33#include <Graphic3d_AspectLine3d.hxx>
5ad8c033 34#include <Graphic3d_ArrayOfSegments.hxx>
35#include <Graphic3d_ArrayOfPoints.hxx>
36#include <gp_Pnt.hxx>
37#include <TColgp_HSequenceOfPnt.hxx>
38#include <TColStd_Array1OfInteger.hxx>
39#include <TopoDS_Edge.hxx>
40#include <TopoDS_Face.hxx>
41#include <TopoDS.hxx>
42#include <TopTools_ListIteratorOfListOfShape.hxx>
5ad8c033 43
44// =========================================================================
45// function : Add
46// purpose :
47// =========================================================================
48void StdPrs_WFShape::Add (const Handle (Prs3d_Presentation)& thePresentation,
49 const TopoDS_Shape& theShape,
50 const Handle (Prs3d_Drawer)& theDrawer)
51{
52 if (theShape.IsNull())
53 {
54 return;
55 }
56
57 Prs3d_ShapeTool aTool (theShape, theDrawer->VertexDrawMode() == Prs3d_VDM_All);
58
59 // Explore shape elements.
60 TopTools_ListOfShape aLFree, aLUnFree, aLWire;
61 for (aTool.InitCurve(); aTool.MoreCurve(); aTool.NextCurve())
62 {
63 const TopoDS_Edge& anEdge = aTool.GetCurve();
64 switch (aTool.Neighbours())
65 {
66 case 0: aLWire.Append (anEdge); break;
67 case 1: aLFree.Append (anEdge); break;
68 default: aLUnFree.Append (anEdge); break;
69 }
70 }
71
5ad8c033 72 Standard_Real aShapeDeflection = Prs3d::GetDeflection (theShape, theDrawer);
73
1b9f5d95 74 // Draw shape elements
5ad8c033 75 {
1b9f5d95 76 TopTools_ListOfShape aDiscreteFaces;
77 for (aTool.InitFace(); aTool.MoreFace(); aTool.NextFace())
5ad8c033 78 {
1b9f5d95 79 if (!aTool.HasSurface())
80 {
81 aDiscreteFaces.Append (aTool.GetFace());
82 }
5ad8c033 83 }
1b9f5d95 84 addEdgesOnTriangulation (thePresentation, aDiscreteFaces, theDrawer->FreeBoundaryAspect());
5ad8c033 85 }
5ad8c033 86
1b9f5d95 87 Prs3d_NListOfSequenceOfPnt aCommonPolylines;
88 const Handle(Prs3d_LineAspect)& aWireAspect = theDrawer->WireAspect();
89
90 // Draw isolines
5ad8c033 91 {
1b9f5d95 92 Prs3d_NListOfSequenceOfPnt aUPolylines, aVPolylines;
93 Prs3d_NListOfSequenceOfPnt* aUPolylinesPtr = &aUPolylines;
94 Prs3d_NListOfSequenceOfPnt* aVPolylinesPtr = &aVPolylines;
95
96 const Handle(Prs3d_LineAspect)& anIsoAspectU = theDrawer->UIsoAspect();
97 const Handle(Prs3d_LineAspect)& anIsoAspectV = theDrawer->VIsoAspect();
98 if (anIsoAspectV->Aspect()->IsEqual (*anIsoAspectU->Aspect()))
99 {
100 aVPolylinesPtr = aUPolylinesPtr;
101 }
102 if (anIsoAspectU->Aspect()->IsEqual (*aWireAspect->Aspect()))
103 {
104 aUPolylinesPtr = &aCommonPolylines;
105 }
106 if (anIsoAspectV->Aspect()->IsEqual (*aWireAspect->Aspect()))
107 {
108 aVPolylinesPtr = &aCommonPolylines;
109 }
110
111 for (aTool.InitFace(); aTool.MoreFace(); aTool.NextFace())
112 {
113 if (aTool.IsPlanarFace() && !theDrawer->IsoOnPlane())
114 {
115 continue;
116 }
117
118 StdPrs_Isolines::Add (aTool.GetFace(), theDrawer, aShapeDeflection, *aUPolylinesPtr, *aVPolylinesPtr);
119 }
120
121 Prs3d::AddPrimitivesGroup (thePresentation, anIsoAspectU, aUPolylines);
122 Prs3d::AddPrimitivesGroup (thePresentation, anIsoAspectV, aVPolylines);
5ad8c033 123 }
124
1b9f5d95 125 if (!aLWire.IsEmpty() && theDrawer->WireDraw())
5ad8c033 126 {
1b9f5d95 127 addEdges (aLWire, theDrawer, aShapeDeflection, aCommonPolylines);
5ad8c033 128 }
129
130 if (!aLUnFree.IsEmpty() && theDrawer->UnFreeBoundaryDraw())
131 {
1b9f5d95 132 const Handle(Prs3d_LineAspect)& aLineAspect = theDrawer->UnFreeBoundaryAspect();
133 if (!aLineAspect->Aspect()->IsEqual (*aWireAspect->Aspect()))
134 {
135 Prs3d_NListOfSequenceOfPnt aPolylines;
136 addEdges (aLUnFree, theDrawer, aShapeDeflection, aPolylines);
137 Prs3d::AddPrimitivesGroup (thePresentation, aLineAspect, aPolylines);
138 }
139 else
140 {
141 addEdges (aLUnFree, theDrawer, aShapeDeflection, aCommonPolylines);
142 }
5ad8c033 143 }
144
1b9f5d95 145 if (!aLFree.IsEmpty() && theDrawer->FreeBoundaryDraw())
5ad8c033 146 {
1b9f5d95 147 const Handle(Prs3d_LineAspect)& aLineAspect = theDrawer->FreeBoundaryAspect();
148 if (!aLineAspect->Aspect()->IsEqual (*aWireAspect->Aspect()))
149 {
150 Prs3d_NListOfSequenceOfPnt aPolylines;
151 addEdges (aLFree, theDrawer, aShapeDeflection, aPolylines);
152 Prs3d::AddPrimitivesGroup (thePresentation, aLineAspect, aPolylines);
153 }
154 else
155 {
156 addEdges (aLFree, theDrawer, aShapeDeflection, aCommonPolylines);
157 }
5ad8c033 158 }
159
1b9f5d95 160 Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->WireAspect(), aCommonPolylines);
161
5ad8c033 162 {
1b9f5d95 163 TColgp_SequenceOfPnt aShapeVertices;
164 for (aTool.InitVertex(); aTool.MoreVertex(); aTool.NextVertex())
5ad8c033 165 {
1b9f5d95 166 aShapeVertices.Append (BRep_Tool::Pnt (aTool.GetVertex()));
167 }
168 if (!aShapeVertices.IsEmpty())
169 {
170 addVertices (thePresentation, aShapeVertices, theDrawer->PointAspect());
5ad8c033 171 }
5ad8c033 172 }
173}
174
175// =========================================================================
176// function : AddEdges
177// purpose :
178// =========================================================================
1b9f5d95 179void StdPrs_WFShape::addEdges (const TopTools_ListOfShape& theEdges,
180 const Handle (Prs3d_Drawer)& theDrawer,
181 const Standard_Real theShapeDeflection,
182 Prs3d_NListOfSequenceOfPnt& thePolylines)
5ad8c033 183{
5ad8c033 184 TopTools_ListIteratorOfListOfShape anEdgesIter;
185 for (anEdgesIter.Initialize (theEdges); anEdgesIter.More(); anEdgesIter.Next())
186 {
187 const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgesIter.Value());
188 if (BRep_Tool::Degenerated (anEdge))
189 {
190 continue;
191 }
192
193 Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt;
194
195 TopLoc_Location aLocation;
196 Handle(Poly_Triangulation) aTriangulation;
197 Handle(Poly_PolygonOnTriangulation) anEdgeIndicies;
198 BRep_Tool::PolygonOnTriangulation (anEdge, anEdgeIndicies, aTriangulation, aLocation);
199 Handle(Poly_Polygon3D) aPolygon;
200
201 if (!anEdgeIndicies.IsNull())
202 {
203 // Presentation based on triangulation of a face.
204 const TColStd_Array1OfInteger& anIndices = anEdgeIndicies->Nodes();
205 const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
206
207 Standard_Integer anIndex = anIndices.Lower();
208 if (aLocation.IsIdentity())
209 {
210 for (; anIndex <= anIndices.Upper(); ++anIndex)
211 {
212 aPoints->Append (aNodes (anIndices (anIndex)));
213 }
214 }
215 else
216 {
217 for (; anIndex <= anIndices.Upper(); ++anIndex)
218 {
219 aPoints->Append (aNodes (anIndices (anIndex)).Transformed (aLocation));
220 }
221 }
222 }
223 else if (!(aPolygon = BRep_Tool::Polygon3D (anEdge, aLocation)).IsNull())
224 {
225 // Presentation based on triangulation of the free edge on a surface.
226 const TColgp_Array1OfPnt& aNodes = aPolygon->Nodes();
227 Standard_Integer anIndex = aNodes.Lower();
228 if (aLocation.IsIdentity())
229 {
230 for (; anIndex <= aNodes.Upper(); ++anIndex)
231 {
232 aPoints->Append (aNodes.Value (anIndex));
233 }
234 }
235 else
236 {
237 for (; anIndex <= aNodes.Upper(); ++anIndex)
238 {
239 aPoints->Append (aNodes.Value (anIndex).Transformed (aLocation));
240 }
241 }
242 }
243 else if (BRep_Tool::IsGeometric (anEdge))
244 {
245 // Default presentation for edges without triangulation.
246 BRepAdaptor_Curve aCurve (anEdge);
1b9f5d95 247 StdPrs_DeflectionCurve::Add (Handle(Prs3d_Presentation)(),
5ad8c033 248 aCurve,
249 theShapeDeflection,
250 theDrawer,
251 aPoints->ChangeSequence(),
252 Standard_False);
253 }
254
255 if (!aPoints->IsEmpty())
256 {
1b9f5d95 257 thePolylines.Append (aPoints);
5ad8c033 258 }
259 }
5ad8c033 260}
261
262// =========================================================================
263// function : AddEdgesOnTriangulation
264// purpose :
265// =========================================================================
266void StdPrs_WFShape::addEdgesOnTriangulation (const Handle(Prs3d_Presentation)& thePresentation,
267 const TopTools_ListOfShape& theFaces,
268 const Handle (Prs3d_LineAspect)& theAspect)
269{
270 TColgp_SequenceOfPnt aSurfPoints;
271
272 TopLoc_Location aLocation;
273 TopTools_ListIteratorOfListOfShape aFaceIter;
274 for (aFaceIter.Initialize (theFaces); aFaceIter.More(); aFaceIter.Next())
275 {
276 const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Value());
277
278 Handle(Poly_Triangulation) T = BRep_Tool::Triangulation (aFace, aLocation);
279 if (T.IsNull())
280 {
281 continue;
282 }
283
284 const TColgp_Array1OfPnt& aNodes = T->Nodes();
285
286 // Build the connect tool.
287 Poly_Connect aPolyConnect (T);
288
289 Standard_Integer aNbTriangles = T->NbTriangles();
290 Standard_Integer aT[3];
291 Standard_Integer aN[3];
292
293 // Count the free edges.
294 Standard_Integer aNbFree = 0;
295 for (Standard_Integer anI = 1; anI <= aNbTriangles; ++anI)
296 {
297 aPolyConnect.Triangles (anI, aT[0], aT[1], aT[2]);
298 for (Standard_Integer aJ = 0; aJ < 3; ++aJ)
299 {
300 if (aT[aJ] == 0)
301 {
302 ++aNbFree;
303 }
304 }
305 }
306
307 // Allocate the arrays.
308 TColStd_Array1OfInteger aFree (1, 2 * aNbFree);
309 Standard_Integer aNbInternal = (3 * aNbTriangles - aNbFree) / 2;
310 TColStd_Array1OfInteger anInternal (0, 2 * aNbInternal);
311
312 Standard_Integer aFreeIndex = 1, anIntIndex = 1;
313 const Poly_Array1OfTriangle& aTriangles = T->Triangles();
314 for (Standard_Integer anI = 1; anI <= aNbTriangles; ++anI)
315 {
316 aPolyConnect.Triangles (anI, aT[0], aT[1], aT[2]);
317 aTriangles (anI).Get (aN[0], aN[1], aN[2]);
318 for (Standard_Integer aJ = 0; aJ < 3; aJ++)
319 {
320 Standard_Integer k = (aJ + 1) % 3;
321 if (aT[aJ] == 0)
322 {
323 aFree (aFreeIndex) = aN[aJ];
324 aFree (aFreeIndex + 1) = aN[k];
325 aFreeIndex += 2;
326 }
327 // internal edge if this triangle has a lower index than the adjacent.
328 else if (anI < aT[aJ])
329 {
330 anInternal (anIntIndex) = aN[aJ];
331 anInternal (anIntIndex + 1) = aN[k];
332 anIntIndex += 2;
333 }
334 }
335 }
336
337 // free edges
338 Standard_Integer aFreeHalfNb = aFree.Length() / 2;
339 for (Standard_Integer anI = 1; anI <= aFreeHalfNb; ++anI)
340 {
341 gp_Pnt aPoint1 = aNodes (aFree (2 * anI - 1)).Transformed (aLocation);
342 gp_Pnt aPoint2 = aNodes (aFree (2 * anI )).Transformed (aLocation);
343 aSurfPoints.Append (aPoint1);
344 aSurfPoints.Append (aPoint2);
345 }
346 }
347
348 if (aSurfPoints.Length() < 2)
349 {
350 return;
351 }
352
353 Standard_Integer aNbVertices = aSurfPoints.Length();
1b9f5d95 354 Handle(Graphic3d_ArrayOfSegments) aSurfArray = new Graphic3d_ArrayOfSegments (aNbVertices);
5ad8c033 355 for (Standard_Integer anI = 1; anI <= aNbVertices; anI += 2)
356 {
5ad8c033 357 aSurfArray->AddVertex (aSurfPoints.Value (anI));
358 aSurfArray->AddVertex (aSurfPoints.Value (anI + 1));
359 }
360 Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePresentation);
361 aGroup->SetPrimitivesAspect (theAspect->Aspect());
362 aGroup->AddPrimitiveArray (aSurfArray);
363}
364
365// =========================================================================
366// function : AddPoints
367// purpose :
368// =========================================================================
369void StdPrs_WFShape::addVertices (const Handle (Prs3d_Presentation)& thePresentation,
370 const TColgp_SequenceOfPnt& theVertices,
371 const Handle (Prs3d_PointAspect)& theAspect)
372{
373 Standard_Integer aNbVertices = theVertices.Length();
374 if (aNbVertices < 1)
375 {
376 return;
377 }
378
379 Handle(Graphic3d_ArrayOfPoints) aVertexArray = new Graphic3d_ArrayOfPoints (aNbVertices);
380 for (Standard_Integer anI = 1; anI <= aNbVertices; ++anI)
381 {
382 aVertexArray->AddVertex (theVertices.Value (anI));
383 }
384
385 Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePresentation);
386 aGroup->SetPrimitivesAspect (theAspect->Aspect());
387 aGroup->AddPrimitiveArray (aVertexArray);
388}