0026106: BRepMesh - revision of data model
[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>
913a4c4a 40#include <Standard_ErrorHandler.hxx>
41#include <TColgp_SequenceOfPnt2d.hxx>
42#include <TColStd_Array1OfReal.hxx>
43#include <TopExp.hxx>
44#include <TopExp_Explorer.hxx>
45
92efcf78 46IMPLEMENT_STANDARD_RTTIEXT(IVtkOCC_ShapeMesher,IVtk_IShapeMesher)
47
913a4c4a 48// Handle implementation
ec357c5c 49
913a4c4a 50
51//================================================================
52// Function : internalBuild
53// Purpose :
54//================================================================
55void IVtkOCC_ShapeMesher::internalBuild()
56{
57 // TODO: do we need any protection here so as not to triangualte
58 // the shape twice??? This can be done e.g. by checking if
59 // triangulation exists for TopoDS_Shape..
60 meshShape();
61
62 // Free vertices and free edges should always be shown.
63 // Shared edges are needed in WF representation only.
64 // TODO: how to filter free edges at visualization level????
65 addFreeVertices();
66 addEdges();
67
68 // Build wireframe points and cells (lines for isolines)
69 addWireFrameFaces();
70
71 // Build shaded representation (based on Poly_Triangulation)
72 addShadedFaces();
73}
74
75//================================================================
76// Function : GetShapeObj
77// Purpose :
78//================================================================
79const IVtkOCC_Shape::Handle IVtkOCC_ShapeMesher::GetShapeObj() const
80{
81 return (IVtkOCC_Shape::Handle::DownCast(myShapeObj));
82}
83
84//================================================================
85// Function : GetDeflection
86// Purpose : Returns absolute deflection used by this algorithm.
87//================================================================
88Standard_Real IVtkOCC_ShapeMesher::GetDeflection() const
89{
90 if (myDeflection < Precision::Confusion()) // if not yet initialized
91 {
92 Handle(Prs3d_Drawer) aDefDrawer = new Prs3d_Drawer();
93 aDefDrawer->SetTypeOfDeflection (Aspect_TOD_RELATIVE);
94 aDefDrawer->SetDeviationCoefficient (GetDeviationCoeff());
95 myDeflection = Prs3d::GetDeflection (GetShapeObj()->GetShape(), aDefDrawer);
96 }
97
98 return myDeflection;
99}
100
101//================================================================
102// Function : meshShape
103// Purpose :
104//================================================================
105void IVtkOCC_ShapeMesher::meshShape()
106{
a2f76b15 107 const TopoDS_Shape& anOcctShape = GetShapeObj()->GetShape();
913a4c4a 108 if (anOcctShape.IsNull())
109 {
110 return;
111 }
112
113 //Clean triangulation before compute incremental mesh
114 BRepTools::Clean (anOcctShape);
115
116 //Compute triangulation
117 Standard_Real aDeflection = GetDeflection();
118 if (aDeflection < Precision::Confusion())
119 {
120 return;
121 }
122
123 try
124 {
125 OCC_CATCH_SIGNALS
126
127 Handle(BRepMesh_DiscretRoot) anAlgo;
128 anAlgo = BRepMesh_DiscretFactory::Get().Discret (anOcctShape,
129 aDeflection,
130 GetDeviationAngle());
131 if (!anAlgo.IsNull())
132 {
133 anAlgo->Perform();
134 }
135 }
136 catch (Standard_Failure)
137 { }
138}
139
140//================================================================
141// Function : addFreeVertices
142// Purpose :
143//================================================================
144void IVtkOCC_ShapeMesher::addFreeVertices()
145{
146 TopTools_IndexedDataMapOfShapeListOfShape aVertexMap;
147 TopExp::MapShapesAndAncestors (GetShapeObj()->GetShape(),
148 TopAbs_VERTEX,
149 TopAbs_EDGE,
150 aVertexMap);
151
152 Standard_Integer aVertNum = aVertexMap.Extent();
153 IVtk_MeshType aType;
154 for (Standard_Integer anIt = 1; anIt <= aVertNum; anIt++)
155 {
156 if (aVertexMap.FindFromIndex(anIt).IsEmpty())
157 {
158 aType = MT_FreeVertex;
159 }
160 else
161 {
162 aType = MT_SharedVertex;
163 }
a2f76b15 164 const TopoDS_Vertex& aVertex = TopoDS::Vertex (aVertexMap.FindKey (anIt));
913a4c4a 165 addVertex (aVertex, GetShapeObj()->GetSubShapeId (aVertex), aType);
166 }
167}
168
169//================================================================
170// Function : addEdges
171// Purpose :
172//================================================================
173void IVtkOCC_ShapeMesher::addEdges()
174{
175 TopTools_IndexedDataMapOfShapeListOfShape anEdgesMap;
176 TopExp::MapShapesAndAncestors (GetShapeObj()->GetShape(),
177 TopAbs_EDGE,
178 TopAbs_FACE,
179 anEdgesMap);
180
181 int aNbFaces;
182 IVtk_MeshType aType;
183 myEdgesTypes.Clear();
184
185 TopExp_Explorer anEdgeIter (GetShapeObj()->GetShape(), TopAbs_EDGE);
186 for (; anEdgeIter.More(); anEdgeIter.Next())
187 {
a2f76b15 188 const TopoDS_Edge& anOcctEdge = TopoDS::Edge (anEdgeIter.Current());
913a4c4a 189 aNbFaces = anEdgesMap.FindFromKey (anOcctEdge).Extent();
190 if (aNbFaces == 0)
191 {
192 aType = MT_FreeEdge;
193 }
194 else if (aNbFaces == 1)
195 {
196 aType = MT_BoundaryEdge;
197 }
198 else
199 {
200 aType = MT_SharedEdge;
201 }
202 addEdge (anOcctEdge, GetShapeObj()->GetSubShapeId (anOcctEdge), aType);
203 myEdgesTypes.Bind (anOcctEdge, aType);
204 }
205}
206
207//================================================================
208// Function : addWireFrameFaces
209// Purpose :
210//================================================================
211void IVtkOCC_ShapeMesher::addWireFrameFaces()
212{
213 // Check the deflection value once for all faces
214 if (GetDeflection() < Precision::Confusion())
215 {
216 return;
217 }
218
219 TopExp_Explorer aFaceIter (GetShapeObj()->GetShape(), TopAbs_FACE);
220 for (; aFaceIter.More(); aFaceIter.Next())
221 {
a2f76b15 222 const TopoDS_Face& anOcctFace = TopoDS::Face (aFaceIter.Current());
913a4c4a 223 try
224 {
225 OCC_CATCH_SIGNALS
226 addWFFace (anOcctFace,
227 GetShapeObj()->GetSubShapeId (anOcctFace));
228 }
229 catch (Standard_Failure)
230 { }
231 }
232}
233
234//================================================================
235// Function : addShadedFaces
236// Purpose :
237//================================================================
238void IVtkOCC_ShapeMesher::addShadedFaces()
239{
240 TopExp_Explorer aFaceIter (GetShapeObj()->GetShape(), TopAbs_FACE);
241 for (; aFaceIter.More(); aFaceIter.Next())
242 {
a2f76b15 243 const TopoDS_Face& anOcctFace = TopoDS::Face (aFaceIter.Current());
913a4c4a 244 addShadedFace (anOcctFace,
245 GetShapeObj()->GetSubShapeId (anOcctFace));
246 }
247}
248
249//================================================================
250// Function : addVertex
251// Purpose :
252//================================================================
253void IVtkOCC_ShapeMesher::addVertex (const TopoDS_Vertex& theVertex,
254 const IVtk_IdType theShapeId,
255 const IVtk_MeshType theMeshType)
256{
257 if (theVertex.IsNull())
258 {
259 return;
260 }
261
262 gp_Pnt aPnt3d = BRep_Tool::Pnt (theVertex);
263
264 IVtk_PointId anId =
265 myShapeData->InsertCoordinate (aPnt3d.X(), aPnt3d.Y(), aPnt3d.Z());
266 myShapeData->InsertVertex (theShapeId, anId, theMeshType);
267
268}
269
270//================================================================
271// Function : processPolyline
272// Purpose :
273//================================================================
274void IVtkOCC_ShapeMesher::processPolyline (Standard_Integer theNbNodes,
275 const TColgp_Array1OfPnt& thePoints,
276 const TColStd_Array1OfInteger& thePointIds,
277 const IVtk_IdType theOcctId,
278 bool theNoTransform,
279 gp_Trsf theTransformation,
280 const IVtk_MeshType theMeshType)
281{
282 if (theNbNodes < 2)
283 {
284 return;
285 }
286
a2f76b15 287 IVtk_PointIdList aPolyPointIds;
913a4c4a 288
289 IVtk_PointId anId;
290 for (Standard_Integer aJ = 0; aJ < theNbNodes; aJ++)
291 {
292 Standard_Integer aPntId = thePointIds (aJ + 1);
293 gp_Pnt point = thePoints (aPntId);
294
295 if (!theNoTransform)
296 {
297 // Apply the transformation to points
298 point.Transform (theTransformation);
299 }
300
301 anId = myShapeData->InsertCoordinate (point.X(), point.Y(), point.Z());
a2f76b15 302 aPolyPointIds.Append (anId);
913a4c4a 303 }
304
a2f76b15 305 myShapeData->InsertLine (theOcctId, &aPolyPointIds, theMeshType);
913a4c4a 306}
307
308//================================================================
309// Function : addEdge
310// Purpose :
311//================================================================
312void IVtkOCC_ShapeMesher::addEdge (const TopoDS_Edge& theEdge,
313 const IVtk_IdType theShapeId,
314 const IVtk_MeshType theMeshType)
315{
316 if (theEdge.IsNull() || BRep_Tool::Degenerated (theEdge))
317 {
318 return;
319 }
320
321 // Two discrete representations of an OCCT edge are possible:
322 // 1. Polygon on trinagulation - holds Ids of points
323 // contained in Poly_Triangulation object
324 Handle(Poly_PolygonOnTriangulation) aPolyOnTriangulation;
325 Handle(Poly_Triangulation) aTriangulation;
326 TopLoc_Location aLocation;
327 BRep_Tool::PolygonOnTriangulation (theEdge,
328 aPolyOnTriangulation,
329 aTriangulation,
330 aLocation,
331 1);
332
333 // 2. 3D polygon - holds 3D points
334 Handle(Poly_Polygon3D) aPoly3d;
335 if (aPolyOnTriangulation.IsNull())
336 {
337 aPoly3d = BRep_Tool::Polygon3D (theEdge, aLocation);
338 }
339
340 if (aPoly3d.IsNull() && aPolyOnTriangulation.IsNull())
341 {
342 return;
343 }
344
345 // Handle a non-identity transofmation applied to the edge
346 gp_Trsf anEdgeTransf;
347 bool noTransform = true;
348 if (!aLocation.IsIdentity())
349 {
350 noTransform = false;
351 anEdgeTransf = aLocation.Transformation();
352 }
353
354 if (!aPoly3d.IsNull())
355 {
356 Standard_Integer aNbNodes = aPoly3d->NbNodes();
357 const TColgp_Array1OfPnt& aPoints = aPoly3d->Nodes();
358 TColStd_Array1OfInteger aPointIds (1, aNbNodes);
359
360 for (Standard_Integer anI = 1; anI <= aNbNodes; anI++)
361 {
362 aPointIds.SetValue (anI, anI);
363 }
364
365 processPolyline (aNbNodes,
366 aPoints,
367 aPointIds,
368 theShapeId,
369 noTransform,
370 anEdgeTransf,
371 theMeshType);
372 }
373 else
374 {
375 Standard_Integer aNbNodes = aPolyOnTriangulation->NbNodes();
376 const TColStd_Array1OfInteger& aPointIds = aPolyOnTriangulation->Nodes();
377 const TColgp_Array1OfPnt& aPoints = aTriangulation->Nodes();
378
379 processPolyline (aNbNodes,
380 aPoints,
381 aPointIds,
382 theShapeId,
383 noTransform,
384 anEdgeTransf,
385 theMeshType);
386 }
387}
388
389
390//================================================================
391// Function : FindLimits
392// Purpose : Static internal function, finds parametrical limits of the curve.
393//! @param [in] theCurve 3D curve adaptor used to retrieve the curve geometry
394//! @param [in] theLimit maximum allowed absolute parameter value
395//! @param [out] theFirst minimum parameter value for the curve
396//! @param [out] theLast maximum parameter value for the curve
397//================================================================
398static void FindLimits (const Adaptor3d_Curve& theCurve,
399 const Standard_Real& theLimit,
400 Standard_Real& theFirst,
401 Standard_Real& theLast)
402{
403 theFirst = Max(theCurve.FirstParameter(), theFirst);
404 theLast = Min(theCurve.LastParameter(), theLast);
405 Standard_Boolean isFirstInf = Precision::IsNegativeInfinite (theFirst);
406 Standard_Boolean isLastInf = Precision::IsPositiveInfinite (theLast);
407
408 if (isFirstInf || isLastInf)
409 {
410 gp_Pnt aP1, aP2;
411 Standard_Real aDelta = 1;
412 if (isFirstInf && isLastInf)
413 {
414 do
415 {
416 aDelta *= 2;
417 theFirst = - aDelta;
418 theLast = aDelta;
419 theCurve.D0 (theFirst, aP1);
420 theCurve.D0 (theLast, aP2);
421 } while (aP1.Distance (aP2) < theLimit);
422 }
423 else if (isFirstInf)
424 {
425 theCurve.D0 (theLast, aP2);
426 do {
427 aDelta *= 2;
428 theFirst = theLast - aDelta;
429 theCurve.D0 (theFirst, aP1);
430 } while (aP1.Distance(aP2) < theLimit);
431 }
432 else if (isLastInf)
433 {
434 theCurve.D0 (theFirst, aP1);
435 do
436 {
437 aDelta *= 2;
438 theLast = theFirst + aDelta;
439 theCurve.D0 (theLast, aP2);
440 } while (aP1.Distance (aP2) < theLimit);
441 }
442 }
443}
444
445//================================================================
446// Function : FindLimits
447// Purpose :Static helper function, builds a discrete representation
448//! (sequence of points) for the given curve.
449//!
450//! @param [in] theCurve 3D curve adaptor used to retrieve the curve geometry
451//! @param [in] theDeflection absolute deflection value
452//! @param [in] theAngle deviation angle value
453//! @param [in] theU1 minimal curve parameter value
454//! @param [in] theU2 maximal curve parameter value
455//! @param [out] thePoints the container for generated polyline
456//================================================================
ee2be2a8 457static void DrawCurve (Adaptor3d_Curve& theCurve,
458 const Standard_Real theDeflection,
459 const Standard_Real theAngle,
460 const Standard_Real theU1,
461 const Standard_Real theU2,
462 IVtk_Polyline& thePoints)
913a4c4a 463{
464 switch (theCurve.GetType())
465 {
466 case GeomAbs_Line:
467 {
468 gp_Pnt aPnt = theCurve.Value(theU1);
469 thePoints.Append (aPnt);
470
471 aPnt = theCurve.Value(0.5 * (theU1 + theU2));
472 thePoints.Append (aPnt);
473
474 aPnt = theCurve.Value (theU2);
475 thePoints.Append(aPnt);
476 }
477 break;
478 default:
479 {
480 Standard_Integer aNbInter = theCurve.NbIntervals(GeomAbs_C1);
481 Standard_Integer anI, aJ;
482 TColStd_Array1OfReal aParams(1, aNbInter+1);
483 theCurve.Intervals(aParams, GeomAbs_C1);
464cd2fb 484 Standard_Real anU1, anU2;
913a4c4a 485 Standard_Integer NumberOfPoints;
486
487 for (aJ = 1; aJ <= aNbInter; aJ++)
488 {
464cd2fb 489 anU1 = aParams (aJ); anU2 = aParams (aJ + 1);
490 if (anU2 > anU1 && anU1 < anU2)
913a4c4a 491 {
464cd2fb 492 anU1 = Max(anU1, anU1);
493 anU2 = Min(anU2, anU2);
913a4c4a 494
464cd2fb 495 GCPnts_TangentialDeflection anAlgo (theCurve, anU1, anU2, theAngle, theDeflection);
913a4c4a 496 NumberOfPoints = anAlgo.NbPoints();
497
498 if (NumberOfPoints > 0)
499 {
500 for (anI = 1; anI < NumberOfPoints; anI++)
501 {
502 thePoints.Append(anAlgo.Value (anI));
503 }
504 if (aJ == aNbInter)
505 {
506 thePoints.Append (anAlgo.Value (NumberOfPoints));
507 }
508 }
509 }
510 }
511 }
512 }
513}
514
515//================================================================
516// Function : buildIsoLines
517// Purpose :
518//================================================================
519void IVtkOCC_ShapeMesher::buildIsoLines (const Handle(BRepAdaptor_HSurface)& theFace,
520 const Standard_Boolean theIsDrawUIso,
521 const Standard_Boolean theIsDrawVIso,
522 const Standard_Integer theNBUiso,
523 const Standard_Integer theNBViso,
524 IVtk_PolylineList& thePolylines)
525{
526 Standard_Real anUF, anUL, aVF, aVL;
527 anUF = theFace->FirstUParameter();
528 anUL = theFace->LastUParameter();
529 aVF = theFace->FirstVParameter();
530 aVL = theFace->LastVParameter();
531
532 // Restrict maximal parameter value
533 // in OCCT it's 5e+5 by default
534 const Standard_Real aLimit = 5e+5;
535
536 // compute bounds of the restriction
537 Standard_Real anUMin, anUMax, aVMin, aVMax;
538 Standard_Integer anI;
539
540 anUMin = Max (anUF, -aLimit);
541 anUMax = Min (anUL, aLimit);
542 aVMin = Max (aVF, -aLimit);
543 aVMax = Min (aVL, aLimit);
544
545 // update min max for the hatcher.
546 gp_Pnt2d aP1,aP2;
547 gp_Pnt aDummyPnt;
548
549 Standard_Real aDdefle = Max (anUMax - anUMin, aVMax - aVMin) * GetDeviationCoeff();
550 TColgp_SequenceOfPnt2d aTabPoints;
551
552 anUMin = aVMin = 1.e100;
553 anUMax = aVMax = -1.e100;
554
555 // Process the edges
556 TopExp_Explorer aToolRst;
557 TopoDS_Face aTopoFace (((BRepAdaptor_Surface*)&(theFace->Surface()))->Face());
558 for (aToolRst.Init (aTopoFace, TopAbs_EDGE); aToolRst.More(); aToolRst.Next())
559 {
560 TopAbs_Orientation anOrient = aToolRst.Current().Orientation();
561 // Skip INTERNAL and EXTERNAL edges
562 if (anOrient == TopAbs_FORWARD || anOrient == TopAbs_REVERSED)
563 {
564 Standard_Real anU1, anU2;
565 const Handle(Geom2d_Curve)& aCurve =
566 BRep_Tool::CurveOnSurface (TopoDS::Edge (aToolRst.Current()),
567 aTopoFace,
568 anU1, anU2);
569 if (aCurve.IsNull())
570 {
571 continue;
572 }
573
574 Geom2dAdaptor_Curve aRCurve;
575 aRCurve.Load (aCurve, anU1, anU2);
576 if (aRCurve.GetType() != GeomAbs_Line)
577 {
578 GCPnts_QuasiUniformDeflection aUDP(aRCurve, aDdefle);
579 if (aUDP.IsDone())
580 {
581 Standard_Integer NumberOfPoints = aUDP.NbPoints();
582 if ( NumberOfPoints >= 2 )
583 {
584 aDummyPnt = aUDP.Value (1);
585 aP2.SetCoord (aDummyPnt.X(), aDummyPnt.Y());
586 anUMin = Min (aP2.X(), anUMin);
587 anUMax = Max (aP2.X(), anUMax);
588 aVMin = Min (aP2.Y(), aVMin);
589 aVMax = Max (aP2.Y(), aVMax);
590 for (anI = 2; anI <= NumberOfPoints; anI++)
591 {
592 aP1 = aP2;
593 aDummyPnt = aUDP.Value (anI);
594 aP2.SetCoord (aDummyPnt.X(), aDummyPnt.Y());
595 anUMin = Min(aP2.X(), anUMin);
596 anUMax = Max(aP2.X(), anUMax);
597 aVMin = Min(aP2.Y(), aVMin);
598 aVMax = Max(aP2.Y(), aVMax);
599
600 if(anOrient == TopAbs_FORWARD )
601 {
602 //isobuild.Trim(P1,P2);
603 aTabPoints.Append (aP1);
604 aTabPoints.Append (aP2);
605 }
606 else
607 {
608 //isobuild.Trim(P2,P1);
609 aTabPoints.Append (aP2);
610 aTabPoints.Append (aP1);
611 }
612 }
613 }
614 }
615 else
616 {
617 cout << "Cannot evaluate curve on surface"<<endl;
618 }
619 }
620 else
621 {
622 anU1 = aRCurve.FirstParameter();
623 anU2 = aRCurve.LastParameter();
624 // MSV 17.08.06 OCC13144: U2 occured less than U1, to overcome it
625 // ensure that distance U2-U1 is not greater than aLimit*2,
626 // if greater then choose an origin and use aLimit to define
627 // U1 and U2 anew
628 Standard_Real aOrigin = 0.;
629 if (!Precision::IsNegativeInfinite(anU1) || !Precision::IsPositiveInfinite (anU2))
630 {
631 if (Precision::IsNegativeInfinite (anU1))
632 {
633 aOrigin = anU2 - aLimit;
634 }
635 else if (Precision::IsPositiveInfinite (anU2))
636 {
637 aOrigin = anU1 + aLimit;
638 }
639 else
640 {
641 aOrigin = (anU1 + anU2) * 0.5;
642 }
643 }
644
645 anU1 = Max (aOrigin - aLimit, anU1);
646 anU2 = Min (aOrigin + aLimit, anU2);
647 aP1 = aRCurve.Value (anU1);
648 aP2 = aRCurve.Value (anU2);
649 anUMin = Min(aP1.X(), anUMin);
650 anUMax = Max(aP1.X(), anUMax);
651 aVMin = Min(aP1.Y(), aVMin);
652 aVMax = Max(aP1.Y(), aVMax);
653 anUMin = Min(aP2.X(), anUMin);
654 anUMax = Max(aP2.X(), anUMax);
655 aVMin = Min(aP2.Y(), aVMin);
656 aVMax = Max(aP2.Y(), aVMax);
657 if(anOrient == TopAbs_FORWARD )
658 {
659 // isobuild.Trim(P1,P2);
660 aTabPoints.Append (aP1);
661 aTabPoints.Append (aP2);
662 }
663 else
664 {
665 //isobuild.Trim(P2,P1);
666 aTabPoints.Append (aP2);
667 aTabPoints.Append (aP1);
668 }
669 }
670 }
671 }
672
673 // load the isos
674 const Standard_Real anIntersectionTolerance = 1.e-5;
675 Hatch_Hatcher anIsoBuild (anIntersectionTolerance, Standard_True );
676
677 Standard_Boolean isUClosed = theFace->IsUClosed();
678 Standard_Boolean isVClosed = theFace->IsVClosed();
679
680 if (!isUClosed)
681 {
682 anUMin = anUMin + (anUMax - anUMin) / 1000.0;
683 anUMax = anUMax - (anUMax - anUMin) /1000.0;
684 }
685
686 if (!isVClosed)
687 {
688 aVMin = aVMin + (aVMax - aVMin) /1000.0;
689 aVMax = aVMax - (aVMax - aVMin) /1000.0;
690 }
691
692 if (theIsDrawUIso)
693 {
694 if (theNBUiso > 0)
695 {
696 isUClosed = Standard_False;
697 Standard_Real aDu= isUClosed ? (anUMax - anUMin) / theNBUiso : (anUMax - anUMin) / (1 + theNBUiso);
698 for (anI = 1; anI <= theNBUiso; anI++)
699 {
700 anIsoBuild.AddXLine (anUMin + aDu*anI);
701 }
702 }
703 }
704 if (theIsDrawVIso)
705 {
706 if (theNBViso > 0)
707 {
708 isVClosed = Standard_False;
709 Standard_Real aDv= isVClosed ? (aVMax - aVMin) / theNBViso : (aVMax - aVMin) / (1 + theNBViso);
710 for (anI = 1; anI <= theNBViso; anI++)
711 {
712 anIsoBuild.AddYLine (aVMin + aDv*anI);
713 }
714 }
715 }
716
717 Standard_Integer aLength = aTabPoints.Length();
718 for (anI = 1; anI <= aLength; anI += 2)
719 {
720 anIsoBuild.Trim (aTabPoints (anI),aTabPoints (anI + 1));
721 }
722
723 // Create the polylines for isos
724 Adaptor3d_IsoCurve anIso;
725 anIso.Load(theFace);
726 Handle(Geom_Curve) aBCurve;
727 const BRepAdaptor_Surface& aBSurf = *(BRepAdaptor_Surface*)&(theFace->Surface());
728 GeomAbs_SurfaceType aType = theFace->GetType();
729
730 Standard_Integer aNumberOfLines = anIsoBuild.NbLines();
731 Handle(Geom_Surface) aGeomSurf;
732 if (aType == GeomAbs_BezierSurface)
733 {
734 aGeomSurf = aBSurf.Bezier();
735 }
736 else if (aType == GeomAbs_BSplineSurface)
737 {
738 aGeomSurf = aBSurf.BSpline();
739 }
740
741 Standard_Real aDeflection = GetDeflection();
742 Standard_Real anAngle = GetDeviationAngle();
743 for (anI = 1; anI <= aNumberOfLines; anI++)
744 {
745 Standard_Integer aNumberOfIntervals = anIsoBuild.NbIntervals(anI);
746 Standard_Real aCoord = anIsoBuild.Coordinate(anI);
747 for (Standard_Integer aJ = 1; aJ <= aNumberOfIntervals; aJ++)
748 {
749 Standard_Real aB1 = anIsoBuild.Start (anI, aJ);
750 Standard_Real aB2 = anIsoBuild.End(anI, aJ);
751
752 if (!aGeomSurf.IsNull())
753 {
754 if (anIsoBuild.IsXLine (anI))
755 {
756 aBCurve = aGeomSurf->UIso (aCoord);
757 }
758 else
759 {
760 aBCurve = aGeomSurf->VIso (aCoord);
761 }
762
763 GeomAdaptor_Curve aGeomCurve (aBCurve);
764 FindLimits (aGeomCurve, aLimit, aB1, aB2);
765 if (aB2 - aB1 > Precision::Confusion())
766 {
767 IVtk_Polyline aPoints;
768 DrawCurve (aGeomCurve, aDeflection, anAngle, aB1, aB2, aPoints);
769 thePolylines.Append (aPoints);
770 }
771 }
772 else
773 {
774 if (anIsoBuild.IsXLine (anI))
775 {
776 anIso.Load (GeomAbs_IsoU, aCoord, aB1, aB2);
777 }
778 else
779 {
780 anIso.Load (GeomAbs_IsoV, aCoord, aB1, aB2);
781 }
782 FindLimits (anIso, aLimit, aB1, aB2);
783 if (aB2 - aB1>Precision::Confusion())
784 {
785 IVtk_Polyline aPoints;
786 DrawCurve (anIso, aDeflection, anAngle, aB1, aB2, aPoints);
787 thePolylines.Append (aPoints);
788 }
789 }
790 }
791 }
792}
793
794//================================================================
795// Function : addWFFace
796// Purpose :
797//================================================================
798void IVtkOCC_ShapeMesher::addWFFace (const TopoDS_Face& theFace,
799 const IVtk_IdType theShapeId)
800{
801 if (theFace.IsNull())
802 {
803 return;
804 }
805
806 TopoDS_Face aFaceToMesh = theFace;
807 aFaceToMesh.Orientation (TopAbs_FORWARD);
808
809 // The code that builds wireframe representation for a TopoDS_Face
810 // has been adapted from some OCCT 6.5.1 methods:
811 // - Prs3d_WFShape::Add()
812 // - StdPrs_WFDeflectionRestrictedFace::Add()
813 // - StdPrs_DeflectionCurve::Add()
814
815 // Add face's edges here but with the face ID
816 TopExp_Explorer anEdgeIter (aFaceToMesh, TopAbs_EDGE );
817 for (; anEdgeIter.More(); anEdgeIter.Next())
818 {
a2f76b15 819 const TopoDS_Edge& anOcctEdge = TopoDS::Edge (anEdgeIter.Current());
913a4c4a 820 addEdge (anOcctEdge, theShapeId, myEdgesTypes (anOcctEdge));
821 }
822
823 TopLoc_Location aLoc;
824 const Handle(Geom_Surface)& aGeomSurf = BRep_Tool::Surface (aFaceToMesh, aLoc);
825 if (aGeomSurf.IsNull())
826 {
827 return;
828 }
829
830 BRepAdaptor_Surface aSurf;
831 aSurf.Initialize (aFaceToMesh);
832 Handle(BRepAdaptor_HSurface) aSurfAdaptor = new BRepAdaptor_HSurface (aSurf);
833
834 IVtk_PolylineList aPolylines;
835 gp_Trsf aDummyTrsf;
836
837 // Building U isolines
838 // Introducing a local scope here to simplify variable naming
839 {
840 buildIsoLines (aSurfAdaptor,
dde68833 841 myNbIsos[0] != 0,
913a4c4a 842 Standard_False,
843 myNbIsos[0],
844 0,
845 aPolylines);
846
847 IVtk_PolylineList::Iterator anIt (aPolylines);
848 for (; anIt.More(); anIt.Next())
849 {
850 const IVtk_Polyline& aPntSeq = anIt.Value();
851 Standard_Integer aNbNodes = aPntSeq.Length();
852 TColgp_Array1OfPnt aPoints (1, aNbNodes);
853 for (Standard_Integer aJ = 1; aJ <= aNbNodes; aJ++)
854 {
855 aPoints.SetValue (aJ, aPntSeq.Value(aJ));
856 }
857
858 TColStd_Array1OfInteger aPointIds (1, aNbNodes);
859 for (Standard_Integer anI = 1; anI <= aNbNodes; anI++)
860 {
861 aPointIds.SetValue (anI, anI);
862 }
863
864 processPolyline (aNbNodes,
865 aPoints,
866 aPointIds,
867 theShapeId,
868 true,
869 aDummyTrsf,
870 MT_IsoLine);
871 }
872 }
873
874 // Building V isolines
875 {
876 aPolylines.Clear();
877 buildIsoLines (aSurfAdaptor,
878 Standard_False,
dde68833 879 myNbIsos[1] != 0,
913a4c4a 880 0,
881 myNbIsos[1],
882 aPolylines);
883
884 IVtk_PolylineList::Iterator anIt (aPolylines);
885 for (; anIt.More(); anIt.Next())
886 {
887 const IVtk_Polyline& aPntSeq = anIt.Value();
888 Standard_Integer aNbNodes = aPntSeq.Length();
889 TColgp_Array1OfPnt aPoints (1, aNbNodes);
890 for (int aJ = 1; aJ <= aNbNodes; aJ++)
891 {
892 aPoints.SetValue (aJ, aPntSeq.Value (aJ));
893 }
894
895 TColStd_Array1OfInteger aPointIds (1, aNbNodes);
896 for (Standard_Integer anI = 1; anI <= aNbNodes; anI++)
897 {
898 aPointIds.SetValue (anI, anI);
899 }
900
901 processPolyline (aNbNodes,
902 aPoints,
903 aPointIds,
904 theShapeId,
905 true,
906 aDummyTrsf,
907 MT_IsoLine);
908 }
909 }
910}
911
912//================================================================
913// Function : addShadedFace
914// Purpose :
915//================================================================
916void IVtkOCC_ShapeMesher::addShadedFace (const TopoDS_Face& theFace,
917 const IVtk_IdType theShapeId)
918{
919 if (theFace.IsNull())
920 {
921 return;
922 }
923
924 // Build triangulation of the face.
925 TopLoc_Location aLoc;
926 Handle(Poly_Triangulation) anOcctTriangulation = BRep_Tool::Triangulation (theFace, aLoc);
927 if (anOcctTriangulation.IsNull())
928 {
929 return;
930 }
931
932 gp_Trsf aPntTransform;
933 Standard_Boolean noTransform = Standard_True;
934 if (!aLoc.IsIdentity())
935 {
936 noTransform = Standard_False;
937 aPntTransform = aLoc.Transformation();
938 }
939
940 // Get triangulation points.
941 const TColgp_Array1OfPnt& aPoints = anOcctTriangulation->Nodes();
942 Standard_Integer aNbPoints = anOcctTriangulation->NbNodes();
943
944 // Keep inserted points id's of triangulation in an array.
945 NCollection_Array1<IVtk_PointId> aPointIds (1, aNbPoints);
946 IVtk_PointId anId;
947
948 Standard_Integer anI;
949 for (anI = 1; anI <= aNbPoints; anI++)
950 {
951 gp_Pnt aPoint = aPoints (anI);
952
953 if (!noTransform)
954 {
955 aPoint.Transform (aPntTransform);
956 }
957
958 // Add a point into output shape data and keep its id in the array.
959 anId = myShapeData->InsertCoordinate (aPoint.X(), aPoint.Y(), aPoint.Z());
960 aPointIds.SetValue (anI, anId);
961 }
962
963 // Create triangles on the created triangulation points.
964 const Poly_Array1OfTriangle& aTriangles = anOcctTriangulation->Triangles();
965 Standard_Integer aNbTriangles = anOcctTriangulation->NbTriangles();
966 Standard_Integer aN1, aN2, aN3;
967 for (anI = 1; anI <= aNbTriangles; anI++)
968 {
969 aTriangles(anI).Get (aN1, aN2, aN3); // get indexes of triangle's points
970 // Insert new triangle on these points into output shape data.
971 myShapeData->InsertTriangle (
972 theShapeId, aPointIds(aN1), aPointIds(aN2), aPointIds(aN3), MT_ShadedFace);
973 }
974}