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