0026664: Triangulating a very small polygon fails
[occt.git] / src / BRepMesh / BRepMesh_FaceAttribute.cxx
1 // Created by: Ekaterina SMIRNOVA
2 // Copyright (c) 2008-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <BRepMesh_FaceAttribute.hxx>
16 #include <TopoDS_Vertex.hxx>
17 #include <BRepAdaptor_HSurface.hxx>
18 #include <BRepMesh_ShapeTool.hxx>
19 #include <BRepMesh_Classifier.hxx>
20 #include <BRepTools.hxx>
21 #include <TopExp_Explorer.hxx>
22 #include <TopoDS_Wire.hxx>
23 #include <TopoDS_Edge.hxx>
24 #include <TopoDS.hxx>
25 #include <TopoDS_Iterator.hxx>
26 #include <BRep_Tool.hxx>
27
28
29 //=======================================================================
30 //function : Constructor
31 //purpose  : 
32 //=======================================================================
33 BRepMesh_FaceAttribute::BRepMesh_FaceAttribute()
34   : myDefFace         (0.),
35     myUMin            (0.),
36     myUMax            (0.),
37     myVMin            (0.),
38     myVMax            (0.),
39     myDeltaX          (1.),
40     myDeltaY          (1.),
41     myMinStep         (-1.),
42     myStatus          (BRepMesh_NoError),
43     myAdaptiveMin     (Standard_False)
44 {
45   init();
46 }
47
48 //=======================================================================
49 //function : Constructor
50 //purpose  : 
51 //=======================================================================
52 BRepMesh_FaceAttribute::BRepMesh_FaceAttribute(
53   const TopoDS_Face&                    theFace,
54   const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices,
55   const BRepMesh::HDMapOfIntegerPnt&    theBoundaryPoints,
56   const Standard_Boolean theAdaptiveMin)
57   : myDefFace         (0.),
58     myUMin            (0.),
59     myUMax            (0.),
60     myVMin            (0.),
61     myVMax            (0.),
62     myDeltaX          (1.),
63     myDeltaY          (1.),
64     myMinStep         (-1.),
65     myStatus          (BRepMesh_NoError),
66     myAdaptiveMin     (theAdaptiveMin),
67     myBoundaryVertices(theBoundaryVertices),
68     myBoundaryPoints  (theBoundaryPoints),
69     myFace            (theFace)
70 {
71   init();
72 }
73
74 //=======================================================================
75 //function : Destructor
76 //purpose  : 
77 //=======================================================================
78 BRepMesh_FaceAttribute::~BRepMesh_FaceAttribute()
79 {
80 }
81
82 //=======================================================================
83 //function : init
84 //purpose  : 
85 //=======================================================================
86 void BRepMesh_FaceAttribute::init()
87 {
88   myVertexEdgeMap = new BRepMesh::IMapOfInteger;
89   myInternalEdges = new BRepMesh::DMapOfShapePairOfPolygon;
90   myLocation2D    = new BRepMesh::DMapOfIntegerListOfXY;
91   myClassifier    = new BRepMesh_Classifier;
92
93   if (myFace.IsNull())
94     return;
95
96   BRepTools::Update(myFace);
97   myFace.Orientation(TopAbs_FORWARD);
98   BRepTools::UVBounds(myFace, myUMin, myUMax, myVMin, myVMax);
99
100   if (myAdaptiveMin) 
101   {
102     // compute minimal UV distance
103     // between vertices
104
105     myMinStep = RealLast();
106     for (TopExp_Explorer anExp(myFace, TopAbs_WIRE); anExp.More(); anExp.Next()) 
107     {
108       TopoDS_Wire aWire = TopoDS::Wire(anExp.Current());
109
110       for (TopoDS_Iterator aWireExp(aWire); aWireExp.More(); aWireExp.Next()) 
111       {
112         TopoDS_Edge anEdge = TopoDS::Edge(aWireExp.Value());
113         if (BRep_Tool::IsClosed(anEdge))
114           continue;
115
116         // Get end points on 2d curve
117         gp_Pnt2d aFirst2d, aLast2d;
118         BRep_Tool::UVPoints(anEdge, myFace, aFirst2d, aLast2d);
119         Standard_Real aDist =aFirst2d.Distance(aLast2d);
120         if (aDist < myMinStep) 
121           myMinStep = aDist;
122       }
123     }
124   }
125   
126   BRepAdaptor_Surface aSurfAdaptor(myFace, Standard_False);
127   mySurface = new BRepAdaptor_HSurface(aSurfAdaptor);
128 }
129
130 //=======================================================================
131 //function : Clear
132 //purpose  : 
133 //=======================================================================
134 void BRepMesh_FaceAttribute::Clear()
135 {
136   myStructure.Nullify();
137   myLocation2D->Clear();
138   myInternalEdges->Clear();
139   myVertexEdgeMap->Clear();
140 }
141
142 //=======================================================================
143 //function : computeParametricTolerance
144 //purpose  : 
145 //=======================================================================
146 Standard_Real BRepMesh_FaceAttribute::computeParametricTolerance(
147   const Standard_Real theFirstParam,
148   const Standard_Real theLastParam) const
149 {
150   const Standard_Real aDeflectionUV = 1.e-05;
151   Standard_Real aPreci = (theLastParam - theFirstParam) * aDeflectionUV;
152   if(myAdaptiveMin && myMinStep < aPreci)
153     aPreci = myMinStep;
154
155   return Max(Precision::PConfusion(), aPreci);
156 }
157
158 //=======================================================================
159 //function : getVertexIndex
160 //purpose  : 
161 //=======================================================================
162 Standard_Boolean BRepMesh_FaceAttribute::getVertexIndex(
163   const TopoDS_Vertex& theVertex,
164   Standard_Integer&    theVertexIndex) const
165 {
166   if (!myBoundaryVertices.IsNull() && myBoundaryVertices->IsBound(theVertex))
167     theVertexIndex = myBoundaryVertices->Find(theVertex);
168   else if (!mySurfaceVertices.IsNull() && mySurfaceVertices->IsBound(theVertex))
169     theVertexIndex = mySurfaceVertices->Find(theVertex);
170   else
171     return Standard_False;
172
173   return Standard_True;
174 }
175
176 //=======================================================================
177 //function : AddNode
178 //purpose  : 
179 //=======================================================================
180 void BRepMesh_FaceAttribute::AddNode(
181   const Standard_Integer         theIndex,
182   const gp_XY&                   theUV,
183   const BRepMesh_DegreeOfFreedom theMovability,
184   Standard_Integer&              theNodeIndex,
185   Standard_Integer&              theNodeOnEdgeIndex)
186 {
187   BRepMesh_Vertex aNode(theUV, theIndex, theMovability);
188   theNodeIndex = myStructure->AddNode(aNode);
189   theNodeOnEdgeIndex = myVertexEdgeMap->FindIndex(theNodeIndex);
190   if (theNodeOnEdgeIndex == 0)
191     theNodeOnEdgeIndex = myVertexEdgeMap->Add(theNodeIndex);
192 }
193
194 //=======================================================================
195 //function : Scale
196 //purpose  : 
197 //=======================================================================
198 gp_XY BRepMesh_FaceAttribute::Scale(const gp_XY&           thePoint2d,
199                                     const Standard_Boolean isToFaceBasis)
200 {
201   return isToFaceBasis ?
202     gp_XY((thePoint2d.X() - myUMin) / myDeltaX, (thePoint2d.Y() - myVMin) / myDeltaY) :
203     gp_XY(thePoint2d.X() * myDeltaX + myUMin, thePoint2d.Y() * myDeltaY + myVMin);
204 }
205
206 //=======================================================================
207 //function : ToleranceU
208 //purpose  : 
209 //=======================================================================
210 Standard_Real BRepMesh_FaceAttribute::ToleranceU() const
211 {
212   return computeParametricTolerance(myUMin, myUMax);
213 }
214
215 //=======================================================================
216 //function : ToleranceV
217 //purpose  : 
218 //=======================================================================
219 Standard_Real BRepMesh_FaceAttribute::ToleranceV() const
220 {
221   return computeParametricTolerance(myVMin, myVMax);
222 }