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