0031580: Visualization, TKOpenGl - cubemap initialization error on OpenGL ES 2.0
[occt.git] / src / IVtkOCC / IVtkOCC_ShapeMesher.cxx
CommitLineData
913a4c4a 1// Created on: 2011-10-14
2// Created by: Roman KOZLOV
3// Copyright (c) 2011-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
913a4c4a 16#include <Adaptor3d_IsoCurve.hxx>
17#include <Bnd_Box.hxx>
18#include <BRep_Tool.hxx>
913a4c4a 19#include <BRepBndLib.hxx>
20#include <BRepMesh_DiscretFactory.hxx>
21#include <BRepMesh_DiscretRoot.hxx>
913a4c4a 22#include <BRepTools.hxx>
23#include <Hatch_Hatcher.hxx>
24#include <GCPnts_QuasiUniformDeflection.hxx>
25#include <GCPnts_TangentialDeflection.hxx>
c04c30b3 26#include <Geom_BezierSurface.hxx>
27#include <Geom_BSplineSurface.hxx>
913a4c4a 28#include <Geom2dAdaptor_Curve.hxx>
29#include <GeomAdaptor_Curve.hxx>
30#include <gp_Dir2d.hxx>
31#include <gp_Pnt2d.hxx>
32#include <IVtkOCC_ShapeMesher.hxx>
33#include <NCollection_Array1.hxx>
34#include <Poly_Polygon3D.hxx>
35#include <Poly_PolygonOnTriangulation.hxx>
36#include <Poly_Triangulation.hxx>
37#include <Precision.hxx>
38#include <Prs3d.hxx>
39#include <Prs3d_Drawer.hxx>
98eb4489 40#include <Prs3d_IsoAspect.hxx>
913a4c4a 41#include <Standard_ErrorHandler.hxx>
98eb4489 42#include <StdPrs_Isolines.hxx>
7f24b768 43#include <StdPrs_ToolTriangulatedShape.hxx>
913a4c4a 44#include <TColgp_SequenceOfPnt2d.hxx>
45#include <TColStd_Array1OfReal.hxx>
46#include <TopExp.hxx>
47#include <TopExp_Explorer.hxx>
48
92efcf78 49IMPLEMENT_STANDARD_RTTIEXT(IVtkOCC_ShapeMesher,IVtk_IShapeMesher)
50
913a4c4a 51// Handle implementation
ec357c5c 52
913a4c4a 53
54//================================================================
55// Function : internalBuild
56// Purpose :
57//================================================================
58void IVtkOCC_ShapeMesher::internalBuild()
59{
60 // TODO: do we need any protection here so as not to triangualte
61 // the shape twice??? This can be done e.g. by checking if
62 // triangulation exists for TopoDS_Shape..
63 meshShape();
64
65 // Free vertices and free edges should always be shown.
66 // Shared edges are needed in WF representation only.
67 // TODO: how to filter free edges at visualization level????
68 addFreeVertices();
69 addEdges();
70
71 // Build wireframe points and cells (lines for isolines)
72 addWireFrameFaces();
73
74 // Build shaded representation (based on Poly_Triangulation)
75 addShadedFaces();
76}
77
78//================================================================
79// Function : GetShapeObj
80// Purpose :
81//================================================================
82const IVtkOCC_Shape::Handle IVtkOCC_ShapeMesher::GetShapeObj() const
83{
84 return (IVtkOCC_Shape::Handle::DownCast(myShapeObj));
85}
86
87//================================================================
88// Function : GetDeflection
89// Purpose : Returns absolute deflection used by this algorithm.
90//================================================================
91Standard_Real IVtkOCC_ShapeMesher::GetDeflection() const
92{
93 if (myDeflection < Precision::Confusion()) // if not yet initialized
94 {
95 Handle(Prs3d_Drawer) aDefDrawer = new Prs3d_Drawer();
96 aDefDrawer->SetTypeOfDeflection (Aspect_TOD_RELATIVE);
97 aDefDrawer->SetDeviationCoefficient (GetDeviationCoeff());
7f24b768 98 myDeflection = StdPrs_ToolTriangulatedShape::GetDeflection (GetShapeObj()->GetShape(), aDefDrawer);
913a4c4a 99 }
100
101 return myDeflection;
102}
103
104//================================================================
105// Function : meshShape
106// Purpose :
107//================================================================
108void IVtkOCC_ShapeMesher::meshShape()
109{
a2f76b15 110 const TopoDS_Shape& anOcctShape = GetShapeObj()->GetShape();
913a4c4a 111 if (anOcctShape.IsNull())
112 {
113 return;
114 }
115
116 //Clean triangulation before compute incremental mesh
117 BRepTools::Clean (anOcctShape);
118
119 //Compute triangulation
120 Standard_Real aDeflection = GetDeflection();
121 if (aDeflection < Precision::Confusion())
122 {
123 return;
124 }
125
126 try
127 {
128 OCC_CATCH_SIGNALS
129
130 Handle(BRepMesh_DiscretRoot) anAlgo;
131 anAlgo = BRepMesh_DiscretFactory::Get().Discret (anOcctShape,
132 aDeflection,
133 GetDeviationAngle());
134 if (!anAlgo.IsNull())
135 {
136 anAlgo->Perform();
137 }
138 }
139 catch (Standard_Failure)
140 { }
141}
142
143//================================================================
144// Function : addFreeVertices
145// Purpose :
146//================================================================
147void IVtkOCC_ShapeMesher::addFreeVertices()
148{
149 TopTools_IndexedDataMapOfShapeListOfShape aVertexMap;
150 TopExp::MapShapesAndAncestors (GetShapeObj()->GetShape(),
151 TopAbs_VERTEX,
152 TopAbs_EDGE,
153 aVertexMap);
154
155 Standard_Integer aVertNum = aVertexMap.Extent();
156 IVtk_MeshType aType;
157 for (Standard_Integer anIt = 1; anIt <= aVertNum; anIt++)
158 {
159 if (aVertexMap.FindFromIndex(anIt).IsEmpty())
160 {
161 aType = MT_FreeVertex;
162 }
163 else
164 {
165 aType = MT_SharedVertex;
166 }
a2f76b15 167 const TopoDS_Vertex& aVertex = TopoDS::Vertex (aVertexMap.FindKey (anIt));
913a4c4a 168 addVertex (aVertex, GetShapeObj()->GetSubShapeId (aVertex), aType);
169 }
170}
171
172//================================================================
173// Function : addEdges
174// Purpose :
175//================================================================
176void IVtkOCC_ShapeMesher::addEdges()
177{
178 TopTools_IndexedDataMapOfShapeListOfShape anEdgesMap;
179 TopExp::MapShapesAndAncestors (GetShapeObj()->GetShape(),
180 TopAbs_EDGE,
181 TopAbs_FACE,
182 anEdgesMap);
183
184 int aNbFaces;
185 IVtk_MeshType aType;
186 myEdgesTypes.Clear();
187
188 TopExp_Explorer anEdgeIter (GetShapeObj()->GetShape(), TopAbs_EDGE);
189 for (; anEdgeIter.More(); anEdgeIter.Next())
190 {
a2f76b15 191 const TopoDS_Edge& anOcctEdge = TopoDS::Edge (anEdgeIter.Current());
913a4c4a 192 aNbFaces = anEdgesMap.FindFromKey (anOcctEdge).Extent();
193 if (aNbFaces == 0)
194 {
195 aType = MT_FreeEdge;
196 }
197 else if (aNbFaces == 1)
198 {
199 aType = MT_BoundaryEdge;
200 }
201 else
202 {
203 aType = MT_SharedEdge;
204 }
205 addEdge (anOcctEdge, GetShapeObj()->GetSubShapeId (anOcctEdge), aType);
206 myEdgesTypes.Bind (anOcctEdge, aType);
207 }
208}
209
210//================================================================
211// Function : addWireFrameFaces
212// Purpose :
213//================================================================
214void IVtkOCC_ShapeMesher::addWireFrameFaces()
215{
216 // Check the deflection value once for all faces
217 if (GetDeflection() < Precision::Confusion())
218 {
219 return;
220 }
221
222 TopExp_Explorer aFaceIter (GetShapeObj()->GetShape(), TopAbs_FACE);
223 for (; aFaceIter.More(); aFaceIter.Next())
224 {
a2f76b15 225 const TopoDS_Face& anOcctFace = TopoDS::Face (aFaceIter.Current());
913a4c4a 226 try
227 {
228 OCC_CATCH_SIGNALS
229 addWFFace (anOcctFace,
230 GetShapeObj()->GetSubShapeId (anOcctFace));
231 }
232 catch (Standard_Failure)
233 { }
234 }
235}
236
237//================================================================
238// Function : addShadedFaces
239// Purpose :
240//================================================================
241void IVtkOCC_ShapeMesher::addShadedFaces()
242{
243 TopExp_Explorer aFaceIter (GetShapeObj()->GetShape(), TopAbs_FACE);
244 for (; aFaceIter.More(); aFaceIter.Next())
245 {
a2f76b15 246 const TopoDS_Face& anOcctFace = TopoDS::Face (aFaceIter.Current());
913a4c4a 247 addShadedFace (anOcctFace,
248 GetShapeObj()->GetSubShapeId (anOcctFace));
249 }
250}
251
252//================================================================
253// Function : addVertex
254// Purpose :
255//================================================================
256void IVtkOCC_ShapeMesher::addVertex (const TopoDS_Vertex& theVertex,
257 const IVtk_IdType theShapeId,
258 const IVtk_MeshType theMeshType)
259{
260 if (theVertex.IsNull())
261 {
262 return;
263 }
264
265 gp_Pnt aPnt3d = BRep_Tool::Pnt (theVertex);
266
267 IVtk_PointId anId =
268 myShapeData->InsertCoordinate (aPnt3d.X(), aPnt3d.Y(), aPnt3d.Z());
269 myShapeData->InsertVertex (theShapeId, anId, theMeshType);
270
271}
272
273//================================================================
274// Function : processPolyline
275// Purpose :
276//================================================================
277void IVtkOCC_ShapeMesher::processPolyline (Standard_Integer theNbNodes,
278 const TColgp_Array1OfPnt& thePoints,
279 const TColStd_Array1OfInteger& thePointIds,
280 const IVtk_IdType theOcctId,
281 bool theNoTransform,
282 gp_Trsf theTransformation,
283 const IVtk_MeshType theMeshType)
284{
285 if (theNbNodes < 2)
286 {
287 return;
288 }
289
a2f76b15 290 IVtk_PointIdList aPolyPointIds;
913a4c4a 291
292 IVtk_PointId anId;
293 for (Standard_Integer aJ = 0; aJ < theNbNodes; aJ++)
294 {
295 Standard_Integer aPntId = thePointIds (aJ + 1);
296 gp_Pnt point = thePoints (aPntId);
297
298 if (!theNoTransform)
299 {
300 // Apply the transformation to points
301 point.Transform (theTransformation);
302 }
303
304 anId = myShapeData->InsertCoordinate (point.X(), point.Y(), point.Z());
a2f76b15 305 aPolyPointIds.Append (anId);
913a4c4a 306 }
307
a2f76b15 308 myShapeData->InsertLine (theOcctId, &aPolyPointIds, theMeshType);
913a4c4a 309}
310
311//================================================================
312// Function : addEdge
313// Purpose :
314//================================================================
315void IVtkOCC_ShapeMesher::addEdge (const TopoDS_Edge& theEdge,
316 const IVtk_IdType theShapeId,
317 const IVtk_MeshType theMeshType)
318{
319 if (theEdge.IsNull() || BRep_Tool::Degenerated (theEdge))
320 {
321 return;
322 }
323
324 // Two discrete representations of an OCCT edge are possible:
325 // 1. Polygon on trinagulation - holds Ids of points
326 // contained in Poly_Triangulation object
327 Handle(Poly_PolygonOnTriangulation) aPolyOnTriangulation;
328 Handle(Poly_Triangulation) aTriangulation;
329 TopLoc_Location aLocation;
330 BRep_Tool::PolygonOnTriangulation (theEdge,
331 aPolyOnTriangulation,
332 aTriangulation,
333 aLocation,
334 1);
335
336 // 2. 3D polygon - holds 3D points
337 Handle(Poly_Polygon3D) aPoly3d;
338 if (aPolyOnTriangulation.IsNull())
339 {
340 aPoly3d = BRep_Tool::Polygon3D (theEdge, aLocation);
341 }
342
343 if (aPoly3d.IsNull() && aPolyOnTriangulation.IsNull())
344 {
345 return;
346 }
347
348 // Handle a non-identity transofmation applied to the edge
349 gp_Trsf anEdgeTransf;
350 bool noTransform = true;
351 if (!aLocation.IsIdentity())
352 {
353 noTransform = false;
354 anEdgeTransf = aLocation.Transformation();
355 }
356
357 if (!aPoly3d.IsNull())
358 {
359 Standard_Integer aNbNodes = aPoly3d->NbNodes();
360 const TColgp_Array1OfPnt& aPoints = aPoly3d->Nodes();
361 TColStd_Array1OfInteger aPointIds (1, aNbNodes);
362
363 for (Standard_Integer anI = 1; anI <= aNbNodes; anI++)
364 {
365 aPointIds.SetValue (anI, anI);
366 }
367
368 processPolyline (aNbNodes,
369 aPoints,
370 aPointIds,
371 theShapeId,
372 noTransform,
373 anEdgeTransf,
374 theMeshType);
375 }
376 else
377 {
378 Standard_Integer aNbNodes = aPolyOnTriangulation->NbNodes();
379 const TColStd_Array1OfInteger& aPointIds = aPolyOnTriangulation->Nodes();
380 const TColgp_Array1OfPnt& aPoints = aTriangulation->Nodes();
381
382 processPolyline (aNbNodes,
383 aPoints,
384 aPointIds,
385 theShapeId,
386 noTransform,
387 anEdgeTransf,
388 theMeshType);
389 }
390}
391
913a4c4a 392//================================================================
393// Function : addWFFace
394// Purpose :
395//================================================================
396void IVtkOCC_ShapeMesher::addWFFace (const TopoDS_Face& theFace,
397 const IVtk_IdType theShapeId)
398{
399 if (theFace.IsNull())
400 {
401 return;
402 }
403
404 TopoDS_Face aFaceToMesh = theFace;
405 aFaceToMesh.Orientation (TopAbs_FORWARD);
406
407 // The code that builds wireframe representation for a TopoDS_Face
408 // has been adapted from some OCCT 6.5.1 methods:
409 // - Prs3d_WFShape::Add()
410 // - StdPrs_WFDeflectionRestrictedFace::Add()
411 // - StdPrs_DeflectionCurve::Add()
412
413 // Add face's edges here but with the face ID
98eb4489 414 for (TopExp_Explorer anEdgeIter (aFaceToMesh, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next())
913a4c4a 415 {
a2f76b15 416 const TopoDS_Edge& anOcctEdge = TopoDS::Edge (anEdgeIter.Current());
913a4c4a 417 addEdge (anOcctEdge, theShapeId, myEdgesTypes (anOcctEdge));
418 }
419
420 TopLoc_Location aLoc;
421 const Handle(Geom_Surface)& aGeomSurf = BRep_Tool::Surface (aFaceToMesh, aLoc);
422 if (aGeomSurf.IsNull())
423 {
424 return;
425 }
426
98eb4489 427 const Standard_Real aDeflection = GetDeflection();
428 Handle(Prs3d_Drawer) aDrawer = new Prs3d_Drawer();
429 aDrawer->SetUIsoAspect (new Prs3d_IsoAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0f, myNbIsos[0]));
430 aDrawer->SetVIsoAspect (new Prs3d_IsoAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0f, myNbIsos[1]));
431 aDrawer->SetDeviationAngle (myDevAngle);
432 aDrawer->SetDeviationCoefficient (myDevCoeff);
433 aDrawer->SetMaximalChordialDeviation (aDeflection);
913a4c4a 434
98eb4489 435 Prs3d_NListOfSequenceOfPnt aPolylines;
436 StdPrs_Isolines::Add (theFace, aDrawer, aDeflection, aPolylines, aPolylines);
437 for (Prs3d_NListOfSequenceOfPnt::Iterator aPolyIter (aPolylines); aPolyIter.More(); aPolyIter.Next())
913a4c4a 438 {
98eb4489 439 const Handle(TColgp_HSequenceOfPnt)& aPoints = aPolyIter.Value();
440 const Standard_Integer theNbNodes = aPoints->Length();
441 if (theNbNodes < 2)
913a4c4a 442 {
98eb4489 443 continue;
913a4c4a 444 }
913a4c4a 445
98eb4489 446 IVtk_PointIdList aPolyPointIds;
447 for (TColgp_HSequenceOfPnt::Iterator aNodeIter (*aPoints); aNodeIter.More(); aNodeIter.Next())
913a4c4a 448 {
98eb4489 449 const gp_Pnt& aPnt = aNodeIter.Value();
450 const IVtk_PointId anId = myShapeData->InsertCoordinate (aPnt.X(), aPnt.Y(), aPnt.Z());
451 aPolyPointIds.Append (anId);
913a4c4a 452 }
98eb4489 453
454 myShapeData->InsertLine (theShapeId, &aPolyPointIds, MT_IsoLine);
913a4c4a 455 }
456}
457
458//================================================================
459// Function : addShadedFace
460// Purpose :
461//================================================================
462void IVtkOCC_ShapeMesher::addShadedFace (const TopoDS_Face& theFace,
463 const IVtk_IdType theShapeId)
464{
465 if (theFace.IsNull())
466 {
467 return;
468 }
469
470 // Build triangulation of the face.
471 TopLoc_Location aLoc;
472 Handle(Poly_Triangulation) anOcctTriangulation = BRep_Tool::Triangulation (theFace, aLoc);
473 if (anOcctTriangulation.IsNull())
474 {
475 return;
476 }
477
478 gp_Trsf aPntTransform;
479 Standard_Boolean noTransform = Standard_True;
480 if (!aLoc.IsIdentity())
481 {
482 noTransform = Standard_False;
483 aPntTransform = aLoc.Transformation();
484 }
485
486 // Get triangulation points.
487 const TColgp_Array1OfPnt& aPoints = anOcctTriangulation->Nodes();
488 Standard_Integer aNbPoints = anOcctTriangulation->NbNodes();
489
490 // Keep inserted points id's of triangulation in an array.
491 NCollection_Array1<IVtk_PointId> aPointIds (1, aNbPoints);
492 IVtk_PointId anId;
493
494 Standard_Integer anI;
495 for (anI = 1; anI <= aNbPoints; anI++)
496 {
497 gp_Pnt aPoint = aPoints (anI);
498
499 if (!noTransform)
500 {
501 aPoint.Transform (aPntTransform);
502 }
503
504 // Add a point into output shape data and keep its id in the array.
505 anId = myShapeData->InsertCoordinate (aPoint.X(), aPoint.Y(), aPoint.Z());
506 aPointIds.SetValue (anI, anId);
507 }
508
509 // Create triangles on the created triangulation points.
510 const Poly_Array1OfTriangle& aTriangles = anOcctTriangulation->Triangles();
511 Standard_Integer aNbTriangles = anOcctTriangulation->NbTriangles();
512 Standard_Integer aN1, aN2, aN3;
513 for (anI = 1; anI <= aNbTriangles; anI++)
514 {
515 aTriangles(anI).Get (aN1, aN2, aN3); // get indexes of triangle's points
516 // Insert new triangle on these points into output shape data.
517 myShapeData->InsertTriangle (
518 theShapeId, aPointIds(aN1), aPointIds(aN2), aPointIds(aN3), MT_ShadedFace);
519 }
520}