811fcba9a95eaff74f282ad7edace4d0795df0e0
[occt.git] / src / IVtkOCC / IVtkOCC_ShapeMesher.cxx
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 <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
48
49
50 //================================================================
51 // Function : internalBuild
52 // Purpose  : 
53 //================================================================
54 void 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 //================================================================
78 const 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 //================================================================
87 Standard_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 //================================================================
104 void 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 //================================================================
143 void 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 //================================================================
172 void 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 //================================================================
210 void 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 //================================================================
237 void 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 //================================================================
252 void 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 //================================================================
273 void 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 //================================================================
313 void 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 //================================================================
399 static 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 //================================================================
458 static 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 //================================================================
520 void 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 //================================================================
799 void 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 //================================================================
917 void 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 }