0027555: Visualization, AIS_Shape - own deviation coefficient change is not considere...
[occt.git] / src / StdPrs / StdPrs_WFShape.cxx
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>
28 #include <Prs3d_NListOfSequenceOfPnt.hxx>
29 #include <Prs3d_NListIteratorOfListOfSequenceOfPnt.hxx>
30 #include <Prs3d.hxx>
31 #include <Poly_Connect.hxx>
32 #include <Poly_PolygonOnTriangulation.hxx>
33 #include <Poly_Polygon3D.hxx>
34 #include <Poly_Triangulation.hxx>
35 #include <Graphic3d_AspectLine3d.hxx>
36 #include <Graphic3d_ArrayOfPolylines.hxx>
37 #include <Graphic3d_ArrayOfSegments.hxx>
38 #include <Graphic3d_ArrayOfPoints.hxx>
39 #include <gp_Pnt.hxx>
40 #include <TColgp_HSequenceOfPnt.hxx>
41 #include <TColStd_Array1OfInteger.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Face.hxx>
44 #include <TopoDS.hxx>
45 #include <TopTools_ListIteratorOfListOfShape.hxx>
46 #include <NCollection_List.hxx>
47
48 namespace
49 {
50   typedef NCollection_List<Handle(TColgp_HSequenceOfPnt)> ListOfSequenceOfPnt;
51 }
52
53 // =========================================================================
54 // function : Add
55 // purpose  :
56 // =========================================================================
57 void StdPrs_WFShape::Add (const Handle (Prs3d_Presentation)& thePresentation,
58                           const TopoDS_Shape&                theShape,
59                           const Handle (Prs3d_Drawer)&       theDrawer)
60 {
61   if (theShape.IsNull())
62   {
63     return;
64   }
65
66   Prs3d_ShapeTool aTool (theShape, theDrawer->VertexDrawMode() == Prs3d_VDM_All);
67
68   // Explore shape elements.
69   TopTools_ListOfShape aLFree, aLUnFree, aLWire;
70   for (aTool.InitCurve(); aTool.MoreCurve(); aTool.NextCurve())
71   {
72     const TopoDS_Edge& anEdge = aTool.GetCurve();
73     switch (aTool.Neighbours())
74     {
75       case 0:  aLWire.Append (anEdge);   break;
76       case 1:  aLFree.Append (anEdge);   break;
77       default: aLUnFree.Append (anEdge); break;
78     }
79   }
80
81   TColgp_SequenceOfPnt aShapeVertices;
82   for (aTool.InitVertex(); aTool.MoreVertex(); aTool.NextVertex())
83   {
84     aShapeVertices.Append (BRep_Tool::Pnt (aTool.GetVertex()));
85   }
86
87   Standard_Real aShapeDeflection = Prs3d::GetDeflection (theShape, theDrawer);
88
89   // Draw shape elements.
90   TopTools_ListOfShape aDiscreteFaces;
91   for (aTool.InitFace(); aTool.MoreFace(); aTool.NextFace())
92   {
93     if (!aTool.HasSurface())
94     {
95       aDiscreteFaces.Append (aTool.GetFace());
96     }
97   }
98   addEdgesOnTriangulation (thePresentation, aDiscreteFaces, theDrawer->FreeBoundaryAspect());
99
100   if (!aLWire.IsEmpty() && theDrawer->WireDraw())
101   {
102     addEdges (thePresentation, aLWire, theDrawer->WireAspect(), theDrawer, aShapeDeflection);
103   }
104
105   if (!aLFree.IsEmpty() && theDrawer->FreeBoundaryDraw())
106   {
107     addEdges (thePresentation, aLFree, theDrawer->FreeBoundaryAspect(), theDrawer, aShapeDeflection);
108   }
109
110   if (!aLUnFree.IsEmpty() && theDrawer->UnFreeBoundaryDraw())
111   {
112     addEdges (thePresentation, aLUnFree, theDrawer->UnFreeBoundaryAspect(), theDrawer, aShapeDeflection);
113   }
114
115   if (!aShapeVertices.IsEmpty())
116   {
117     addVertices (thePresentation, aShapeVertices, theDrawer->PointAspect());
118   }
119
120   // Draw isolines.
121   for (aTool.InitFace(); aTool.MoreFace(); aTool.NextFace())
122   {
123     if (aTool.IsPlanarFace() && !theDrawer->IsoOnPlane())
124     {
125       continue;
126     }
127
128     StdPrs_Isolines::Add (thePresentation, aTool.GetFace(), theDrawer, aShapeDeflection);
129   }
130 }
131
132 // =========================================================================
133 // function : AddEdges
134 // purpose  :
135 // =========================================================================
136 void StdPrs_WFShape::addEdges (const Handle (Prs3d_Presentation)& thePresentation,
137                                const TopTools_ListOfShape&        theEdges,
138                                const Handle (Prs3d_LineAspect)&   theAspect,
139                                const Handle (Prs3d_Drawer)&       theDrawer,
140                                const Standard_Real                theShapeDeflection)
141 {
142   ListOfSequenceOfPnt aPointsOfEdges;
143
144   TopTools_ListIteratorOfListOfShape anEdgesIter;
145   for (anEdgesIter.Initialize (theEdges); anEdgesIter.More(); anEdgesIter.Next())
146   {
147     const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgesIter.Value());
148     if (BRep_Tool::Degenerated (anEdge))
149     {
150       continue;
151     }
152
153     Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt;
154
155     TopLoc_Location aLocation;
156     Handle(Poly_Triangulation)          aTriangulation;
157     Handle(Poly_PolygonOnTriangulation) anEdgeIndicies;
158     BRep_Tool::PolygonOnTriangulation (anEdge, anEdgeIndicies, aTriangulation, aLocation);
159     Handle(Poly_Polygon3D) aPolygon;
160
161     if (!anEdgeIndicies.IsNull())
162     {
163       // Presentation based on triangulation of a face.
164       const TColStd_Array1OfInteger& anIndices = anEdgeIndicies->Nodes();
165       const TColgp_Array1OfPnt&      aNodes    = aTriangulation->Nodes();
166
167       Standard_Integer anIndex = anIndices.Lower();
168       if (aLocation.IsIdentity())
169       {
170         for (; anIndex <= anIndices.Upper(); ++anIndex)
171         {
172           aPoints->Append (aNodes (anIndices (anIndex)));
173         }
174       }
175       else
176       {
177         for (; anIndex <= anIndices.Upper(); ++anIndex)
178         {
179           aPoints->Append (aNodes (anIndices (anIndex)).Transformed (aLocation));
180         }
181       }
182     }
183     else if (!(aPolygon = BRep_Tool::Polygon3D (anEdge, aLocation)).IsNull())
184     {
185       // Presentation based on triangulation of the free edge on a surface.
186       const TColgp_Array1OfPnt& aNodes = aPolygon->Nodes();
187       Standard_Integer anIndex = aNodes.Lower();
188       if (aLocation.IsIdentity())
189       {
190         for (; anIndex <= aNodes.Upper(); ++anIndex)
191         {
192           aPoints->Append (aNodes.Value (anIndex));
193         }
194       }
195       else
196       {
197         for (; anIndex <= aNodes.Upper(); ++anIndex)
198         {
199           aPoints->Append (aNodes.Value (anIndex).Transformed (aLocation));
200         }
201       }
202     }
203     else if (BRep_Tool::IsGeometric (anEdge))
204     {
205       // Default presentation for edges without triangulation.
206       BRepAdaptor_Curve aCurve (anEdge);
207       StdPrs_DeflectionCurve::Add (thePresentation,
208                                    aCurve,
209                                    theShapeDeflection,
210                                    theDrawer,
211                                    aPoints->ChangeSequence(),
212                                    Standard_False);
213     }
214
215     if (!aPoints->IsEmpty())
216     {
217       aPointsOfEdges.Append (aPoints);
218     }
219   }
220
221   Standard_Integer aNbBounds   = aPointsOfEdges.Size();
222   Standard_Integer aNbVertices = 0;
223
224   ListOfSequenceOfPnt::Iterator aPolylineIter;
225   for (aPolylineIter.Initialize (aPointsOfEdges); aPolylineIter.More(); aPolylineIter.Next())
226   {
227     aNbVertices += aPolylineIter.Value()->Length();
228   }
229
230   if (aNbBounds < 1 || aNbVertices < 2)
231   {
232     return;
233   }
234
235   // Construct array of primitives.
236   Handle(Graphic3d_ArrayOfPolylines) aPrimitiveArray = new Graphic3d_ArrayOfPolylines (aNbVertices, aNbBounds);
237   for (aPolylineIter.Initialize (aPointsOfEdges); aPolylineIter.More(); aPolylineIter.Next())
238   {
239     const Handle(TColgp_HSequenceOfPnt)& aPoints = aPolylineIter.Value();
240     aPrimitiveArray->AddBound (aPoints->Length());
241     for (Standard_Integer anI = 1; anI <= aPoints->Length(); ++anI)
242     {
243       aPrimitiveArray->AddVertex (aPoints->Value (anI));
244     }
245   }
246
247   // Add array of primitives to presentation.
248   Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePresentation);
249   aGroup->SetPrimitivesAspect (theAspect->Aspect());
250   aGroup->AddPrimitiveArray (aPrimitiveArray);
251 }
252
253 // =========================================================================
254 // function : AddEdgesOnTriangulation
255 // purpose  :
256 // =========================================================================
257 void StdPrs_WFShape::addEdgesOnTriangulation (const Handle(Prs3d_Presentation)& thePresentation,
258                                               const TopTools_ListOfShape&       theFaces,
259                                               const Handle (Prs3d_LineAspect)&  theAspect)
260 {
261   TColgp_SequenceOfPnt aSurfPoints;
262
263   TopLoc_Location aLocation;
264   TopTools_ListIteratorOfListOfShape aFaceIter;
265   for (aFaceIter.Initialize (theFaces); aFaceIter.More(); aFaceIter.Next())
266   {
267     const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Value());
268
269     Handle(Poly_Triangulation) T = BRep_Tool::Triangulation (aFace, aLocation);
270     if (T.IsNull())
271     {
272       continue;
273     }
274
275     const TColgp_Array1OfPnt& aNodes = T->Nodes();
276
277     // Build the connect tool.
278     Poly_Connect aPolyConnect (T);
279
280     Standard_Integer aNbTriangles = T->NbTriangles();
281     Standard_Integer aT[3];
282     Standard_Integer aN[3];
283
284     // Count the free edges.
285     Standard_Integer aNbFree = 0;
286     for (Standard_Integer anI = 1; anI <= aNbTriangles; ++anI)
287     {
288       aPolyConnect.Triangles (anI, aT[0], aT[1], aT[2]);
289       for (Standard_Integer aJ = 0; aJ < 3; ++aJ)
290       {
291         if (aT[aJ] == 0)
292         {
293           ++aNbFree;
294         }
295       }
296     }
297
298     // Allocate the arrays.
299     TColStd_Array1OfInteger aFree (1, 2 * aNbFree);
300     Standard_Integer aNbInternal = (3 * aNbTriangles - aNbFree) / 2;
301     TColStd_Array1OfInteger anInternal (0, 2 * aNbInternal);
302
303     Standard_Integer aFreeIndex = 1, anIntIndex = 1;
304     const Poly_Array1OfTriangle& aTriangles = T->Triangles();
305     for (Standard_Integer anI = 1; anI <= aNbTriangles; ++anI)
306     {
307       aPolyConnect.Triangles (anI, aT[0], aT[1], aT[2]);
308       aTriangles (anI).Get (aN[0], aN[1], aN[2]);
309       for (Standard_Integer aJ = 0; aJ < 3; aJ++)
310       {
311         Standard_Integer k = (aJ + 1) % 3;
312         if (aT[aJ] == 0)
313         {
314           aFree (aFreeIndex)     = aN[aJ];
315           aFree (aFreeIndex + 1) = aN[k];
316           aFreeIndex += 2;
317         }
318         // internal edge if this triangle has a lower index than the adjacent.
319         else if (anI < aT[aJ])
320         {
321           anInternal (anIntIndex)     = aN[aJ];
322           anInternal (anIntIndex + 1) = aN[k];
323           anIntIndex += 2;
324         }
325       }
326     }
327
328     // free edges
329     Standard_Integer aFreeHalfNb = aFree.Length() / 2;
330     for (Standard_Integer anI = 1; anI <= aFreeHalfNb; ++anI)
331     {
332       gp_Pnt aPoint1 = aNodes (aFree (2 * anI - 1)).Transformed (aLocation);
333       gp_Pnt aPoint2 = aNodes (aFree (2 * anI    )).Transformed (aLocation);
334       aSurfPoints.Append (aPoint1);
335       aSurfPoints.Append (aPoint2);
336     }
337   }
338
339   if (aSurfPoints.Length() < 2)
340   {
341     return;
342   }
343
344   Standard_Integer aNbVertices = aSurfPoints.Length();
345   Standard_Integer aNbBounds   = aNbVertices / 2;
346   Handle(Graphic3d_ArrayOfSegments) aSurfArray = new Graphic3d_ArrayOfSegments (aNbVertices, aNbBounds);
347   for (Standard_Integer anI = 1; anI <= aNbVertices; anI += 2)
348   {
349     aSurfArray->AddBound (2);
350     aSurfArray->AddVertex (aSurfPoints.Value (anI));
351     aSurfArray->AddVertex (aSurfPoints.Value (anI + 1));
352   }
353   Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePresentation);
354   aGroup->SetPrimitivesAspect (theAspect->Aspect());
355   aGroup->AddPrimitiveArray (aSurfArray);
356 }
357
358 // =========================================================================
359 // function : AddPoints
360 // purpose  :
361 // =========================================================================
362 void StdPrs_WFShape::addVertices (const Handle (Prs3d_Presentation)& thePresentation,
363                                   const TColgp_SequenceOfPnt&        theVertices,
364                                   const Handle (Prs3d_PointAspect)&  theAspect)
365 {
366   Standard_Integer aNbVertices = theVertices.Length();
367   if (aNbVertices < 1)
368   {
369     return;
370   }
371
372   Handle(Graphic3d_ArrayOfPoints) aVertexArray = new Graphic3d_ArrayOfPoints (aNbVertices);
373   for (Standard_Integer anI = 1; anI <= aNbVertices; ++anI)
374   {
375     aVertexArray->AddVertex (theVertices.Value (anI));
376   }
377
378   Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePresentation);
379   aGroup->SetPrimitivesAspect (theAspect->Aspect());
380   aGroup->AddPrimitiveArray (aVertexArray);
381 }