0026583: Eliminate compile warnings obtained by building occt with vc14: declaration...
[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 <Geom_BezierSurface.hxx>
29 #include <Geom_BSplineSurface.hxx>
30 #include <Geom2dAdaptor_Curve.hxx>
31 #include <GeomAdaptor_Curve.hxx>
32 #include <gp_Dir2d.hxx>
33 #include <gp_Pnt2d.hxx>
34 #include <IVtkOCC_ShapeMesher.hxx>
35 #include <NCollection_Array1.hxx>
36 #include <Poly_Polygon3D.hxx>
37 #include <Poly_PolygonOnTriangulation.hxx>
38 #include <Poly_Triangulation.hxx>
39 #include <Precision.hxx>
40 #include <Prs3d.hxx>
41 #include <Prs3d_Drawer.hxx>
42 #include <Quantity_Length.hxx>
43 #include <Standard_ErrorHandler.hxx>
44 #include <TColgp_SequenceOfPnt2d.hxx>
45 #include <TColStd_Array1OfReal.hxx>
46 #include <TopExp.hxx>
47 #include <TopExp_Explorer.hxx>
48
49 // Handle implementation
50
51
52 //================================================================
53 // Function : internalBuild
54 // Purpose  : 
55 //================================================================
56 void 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 //================================================================
80 const 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 //================================================================
89 Standard_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 //================================================================
106 void 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 //================================================================
145 void 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 //================================================================
174 void 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 //================================================================
212 void 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 //================================================================
239 void 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 //================================================================
254 void 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 //================================================================
275 void 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 //================================================================
315 void 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 //================================================================
401 static 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 //================================================================
460 static 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 anU1, anU2;
488       Standard_Integer NumberOfPoints;
489
490       for (aJ = 1; aJ <= aNbInter; aJ++)
491       {
492         anU1 = aParams (aJ); anU2 = aParams (aJ + 1);
493         if (anU2 > anU1 && anU1 < anU2)
494         {
495           anU1 = Max(anU1, anU1);
496           anU2 = Min(anU2, anU2);
497
498           GCPnts_TangentialDeflection anAlgo (theCurve, anU1, anU2, 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 //================================================================
522 void 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 //================================================================
801 void 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 //================================================================
919 void 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 }