0031668: Visualization - WebGL sample doesn't work on Emscripten 1.39
[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);
913a4c4a 183 int aNbFaces;
184 IVtk_MeshType aType;
185 myEdgesTypes.Clear();
186
2ba1172b 187 TopTools_IndexedDataMapOfShapeListOfShape::Iterator aEdgeIt(anEdgesMap);
188 for (; aEdgeIt.More(); aEdgeIt.Next())
913a4c4a 189 {
2ba1172b 190 const TopoDS_Edge& anOcctEdge = TopoDS::Edge (aEdgeIt.Key());
191 const TopTools_ListOfShape& aFaceList = aEdgeIt.Value();
192 aNbFaces = aFaceList.Extent();
913a4c4a 193 if (aNbFaces == 0)
194 {
195 aType = MT_FreeEdge;
196 }
197 else if (aNbFaces == 1)
198 {
199 aType = MT_BoundaryEdge;
200 }
201 else
202 {
2ba1172b 203 aType = (aNbFaces >= 2) && (BRep_Tool::MaxContinuity(anOcctEdge) > GeomAbs_G2) ?
204 MT_SeamEdge : MT_SharedEdge;
913a4c4a 205 }
206 addEdge (anOcctEdge, GetShapeObj()->GetSubShapeId (anOcctEdge), aType);
207 myEdgesTypes.Bind (anOcctEdge, aType);
208 }
209}
210
211//================================================================
212// Function : addWireFrameFaces
213// Purpose :
214//================================================================
215void IVtkOCC_ShapeMesher::addWireFrameFaces()
216{
217 // Check the deflection value once for all faces
218 if (GetDeflection() < Precision::Confusion())
219 {
220 return;
221 }
222
223 TopExp_Explorer aFaceIter (GetShapeObj()->GetShape(), TopAbs_FACE);
224 for (; aFaceIter.More(); aFaceIter.Next())
225 {
a2f76b15 226 const TopoDS_Face& anOcctFace = TopoDS::Face (aFaceIter.Current());
913a4c4a 227 try
228 {
229 OCC_CATCH_SIGNALS
230 addWFFace (anOcctFace,
231 GetShapeObj()->GetSubShapeId (anOcctFace));
232 }
233 catch (Standard_Failure)
234 { }
235 }
236}
237
238//================================================================
239// Function : addShadedFaces
240// Purpose :
241//================================================================
242void IVtkOCC_ShapeMesher::addShadedFaces()
243{
244 TopExp_Explorer aFaceIter (GetShapeObj()->GetShape(), TopAbs_FACE);
245 for (; aFaceIter.More(); aFaceIter.Next())
246 {
a2f76b15 247 const TopoDS_Face& anOcctFace = TopoDS::Face (aFaceIter.Current());
913a4c4a 248 addShadedFace (anOcctFace,
249 GetShapeObj()->GetSubShapeId (anOcctFace));
250 }
251}
252
253//================================================================
254// Function : addVertex
255// Purpose :
256//================================================================
257void IVtkOCC_ShapeMesher::addVertex (const TopoDS_Vertex& theVertex,
258 const IVtk_IdType theShapeId,
259 const IVtk_MeshType theMeshType)
260{
261 if (theVertex.IsNull())
262 {
263 return;
264 }
265
266 gp_Pnt aPnt3d = BRep_Tool::Pnt (theVertex);
267
268 IVtk_PointId anId =
269 myShapeData->InsertCoordinate (aPnt3d.X(), aPnt3d.Y(), aPnt3d.Z());
270 myShapeData->InsertVertex (theShapeId, anId, theMeshType);
271
272}
273
274//================================================================
275// Function : processPolyline
276// Purpose :
277//================================================================
278void IVtkOCC_ShapeMesher::processPolyline (Standard_Integer theNbNodes,
279 const TColgp_Array1OfPnt& thePoints,
280 const TColStd_Array1OfInteger& thePointIds,
281 const IVtk_IdType theOcctId,
282 bool theNoTransform,
283 gp_Trsf theTransformation,
284 const IVtk_MeshType theMeshType)
285{
286 if (theNbNodes < 2)
287 {
288 return;
289 }
290
a2f76b15 291 IVtk_PointIdList aPolyPointIds;
913a4c4a 292
293 IVtk_PointId anId;
294 for (Standard_Integer aJ = 0; aJ < theNbNodes; aJ++)
295 {
296 Standard_Integer aPntId = thePointIds (aJ + 1);
297 gp_Pnt point = thePoints (aPntId);
298
299 if (!theNoTransform)
300 {
301 // Apply the transformation to points
302 point.Transform (theTransformation);
303 }
304
305 anId = myShapeData->InsertCoordinate (point.X(), point.Y(), point.Z());
a2f76b15 306 aPolyPointIds.Append (anId);
913a4c4a 307 }
308
a2f76b15 309 myShapeData->InsertLine (theOcctId, &aPolyPointIds, theMeshType);
913a4c4a 310}
311
312//================================================================
313// Function : addEdge
314// Purpose :
315//================================================================
316void IVtkOCC_ShapeMesher::addEdge (const TopoDS_Edge& theEdge,
317 const IVtk_IdType theShapeId,
318 const IVtk_MeshType theMeshType)
319{
320 if (theEdge.IsNull() || BRep_Tool::Degenerated (theEdge))
321 {
322 return;
323 }
324
325 // Two discrete representations of an OCCT edge are possible:
326 // 1. Polygon on trinagulation - holds Ids of points
327 // contained in Poly_Triangulation object
328 Handle(Poly_PolygonOnTriangulation) aPolyOnTriangulation;
329 Handle(Poly_Triangulation) aTriangulation;
330 TopLoc_Location aLocation;
331 BRep_Tool::PolygonOnTriangulation (theEdge,
332 aPolyOnTriangulation,
333 aTriangulation,
334 aLocation,
335 1);
336
337 // 2. 3D polygon - holds 3D points
338 Handle(Poly_Polygon3D) aPoly3d;
339 if (aPolyOnTriangulation.IsNull())
340 {
341 aPoly3d = BRep_Tool::Polygon3D (theEdge, aLocation);
342 }
343
344 if (aPoly3d.IsNull() && aPolyOnTriangulation.IsNull())
345 {
346 return;
347 }
348
349 // Handle a non-identity transofmation applied to the edge
350 gp_Trsf anEdgeTransf;
351 bool noTransform = true;
352 if (!aLocation.IsIdentity())
353 {
354 noTransform = false;
355 anEdgeTransf = aLocation.Transformation();
356 }
357
358 if (!aPoly3d.IsNull())
359 {
360 Standard_Integer aNbNodes = aPoly3d->NbNodes();
361 const TColgp_Array1OfPnt& aPoints = aPoly3d->Nodes();
362 TColStd_Array1OfInteger aPointIds (1, aNbNodes);
363
364 for (Standard_Integer anI = 1; anI <= aNbNodes; anI++)
365 {
366 aPointIds.SetValue (anI, anI);
367 }
368
369 processPolyline (aNbNodes,
370 aPoints,
371 aPointIds,
372 theShapeId,
373 noTransform,
374 anEdgeTransf,
375 theMeshType);
376 }
377 else
378 {
379 Standard_Integer aNbNodes = aPolyOnTriangulation->NbNodes();
380 const TColStd_Array1OfInteger& aPointIds = aPolyOnTriangulation->Nodes();
381 const TColgp_Array1OfPnt& aPoints = aTriangulation->Nodes();
382
383 processPolyline (aNbNodes,
384 aPoints,
385 aPointIds,
386 theShapeId,
387 noTransform,
388 anEdgeTransf,
389 theMeshType);
390 }
391}
392
913a4c4a 393//================================================================
394// Function : addWFFace
395// Purpose :
396//================================================================
397void IVtkOCC_ShapeMesher::addWFFace (const TopoDS_Face& theFace,
398 const IVtk_IdType theShapeId)
399{
400 if (theFace.IsNull())
401 {
402 return;
403 }
404
405 TopoDS_Face aFaceToMesh = theFace;
406 aFaceToMesh.Orientation (TopAbs_FORWARD);
407
408 // The code that builds wireframe representation for a TopoDS_Face
409 // has been adapted from some OCCT 6.5.1 methods:
410 // - Prs3d_WFShape::Add()
411 // - StdPrs_WFDeflectionRestrictedFace::Add()
412 // - StdPrs_DeflectionCurve::Add()
413
414 // Add face's edges here but with the face ID
98eb4489 415 for (TopExp_Explorer anEdgeIter (aFaceToMesh, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next())
913a4c4a 416 {
a2f76b15 417 const TopoDS_Edge& anOcctEdge = TopoDS::Edge (anEdgeIter.Current());
913a4c4a 418 addEdge (anOcctEdge, theShapeId, myEdgesTypes (anOcctEdge));
419 }
420
421 TopLoc_Location aLoc;
422 const Handle(Geom_Surface)& aGeomSurf = BRep_Tool::Surface (aFaceToMesh, aLoc);
423 if (aGeomSurf.IsNull())
424 {
425 return;
426 }
427
98eb4489 428 const Standard_Real aDeflection = GetDeflection();
429 Handle(Prs3d_Drawer) aDrawer = new Prs3d_Drawer();
430 aDrawer->SetUIsoAspect (new Prs3d_IsoAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0f, myNbIsos[0]));
431 aDrawer->SetVIsoAspect (new Prs3d_IsoAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0f, myNbIsos[1]));
432 aDrawer->SetDeviationAngle (myDevAngle);
433 aDrawer->SetDeviationCoefficient (myDevCoeff);
434 aDrawer->SetMaximalChordialDeviation (aDeflection);
913a4c4a 435
98eb4489 436 Prs3d_NListOfSequenceOfPnt aPolylines;
437 StdPrs_Isolines::Add (theFace, aDrawer, aDeflection, aPolylines, aPolylines);
438 for (Prs3d_NListOfSequenceOfPnt::Iterator aPolyIter (aPolylines); aPolyIter.More(); aPolyIter.Next())
913a4c4a 439 {
98eb4489 440 const Handle(TColgp_HSequenceOfPnt)& aPoints = aPolyIter.Value();
441 const Standard_Integer theNbNodes = aPoints->Length();
442 if (theNbNodes < 2)
913a4c4a 443 {
98eb4489 444 continue;
913a4c4a 445 }
913a4c4a 446
98eb4489 447 IVtk_PointIdList aPolyPointIds;
448 for (TColgp_HSequenceOfPnt::Iterator aNodeIter (*aPoints); aNodeIter.More(); aNodeIter.Next())
913a4c4a 449 {
98eb4489 450 const gp_Pnt& aPnt = aNodeIter.Value();
451 const IVtk_PointId anId = myShapeData->InsertCoordinate (aPnt.X(), aPnt.Y(), aPnt.Z());
452 aPolyPointIds.Append (anId);
913a4c4a 453 }
98eb4489 454
455 myShapeData->InsertLine (theShapeId, &aPolyPointIds, MT_IsoLine);
913a4c4a 456 }
457}
458
459//================================================================
460// Function : addShadedFace
461// Purpose :
462//================================================================
463void IVtkOCC_ShapeMesher::addShadedFace (const TopoDS_Face& theFace,
464 const IVtk_IdType theShapeId)
465{
466 if (theFace.IsNull())
467 {
468 return;
469 }
470
471 // Build triangulation of the face.
472 TopLoc_Location aLoc;
473 Handle(Poly_Triangulation) anOcctTriangulation = BRep_Tool::Triangulation (theFace, aLoc);
474 if (anOcctTriangulation.IsNull())
475 {
476 return;
477 }
478
479 gp_Trsf aPntTransform;
480 Standard_Boolean noTransform = Standard_True;
481 if (!aLoc.IsIdentity())
482 {
483 noTransform = Standard_False;
484 aPntTransform = aLoc.Transformation();
485 }
486
487 // Get triangulation points.
488 const TColgp_Array1OfPnt& aPoints = anOcctTriangulation->Nodes();
489 Standard_Integer aNbPoints = anOcctTriangulation->NbNodes();
490
491 // Keep inserted points id's of triangulation in an array.
492 NCollection_Array1<IVtk_PointId> aPointIds (1, aNbPoints);
493 IVtk_PointId anId;
494
495 Standard_Integer anI;
496 for (anI = 1; anI <= aNbPoints; anI++)
497 {
498 gp_Pnt aPoint = aPoints (anI);
499
500 if (!noTransform)
501 {
502 aPoint.Transform (aPntTransform);
503 }
504
505 // Add a point into output shape data and keep its id in the array.
506 anId = myShapeData->InsertCoordinate (aPoint.X(), aPoint.Y(), aPoint.Z());
507 aPointIds.SetValue (anI, anId);
508 }
509
510 // Create triangles on the created triangulation points.
511 const Poly_Array1OfTriangle& aTriangles = anOcctTriangulation->Triangles();
512 Standard_Integer aNbTriangles = anOcctTriangulation->NbTriangles();
513 Standard_Integer aN1, aN2, aN3;
514 for (anI = 1; anI <= aNbTriangles; anI++)
515 {
516 aTriangles(anI).Get (aN1, aN2, aN3); // get indexes of triangle's points
517 // Insert new triangle on these points into output shape data.
518 myShapeData->InsertTriangle (
519 theShapeId, aPointIds(aN1), aPointIds(aN2), aPointIds(aN3), MT_ShadedFace);
520 }
521}