ceb418e1 |
1 | // Created on: 2014-08-13 |
2 | // Created by: Oleg AGASHIN |
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 <BRepMesh_EdgeTessellator.hxx> |
17 | #include <Geom_Surface.hxx> |
18 | #include <Geom_Plane.hxx> |
19 | #include <Geom2d_Curve.hxx> |
20 | #include <TopoDS_Edge.hxx> |
21 | #include <TopoDS_Face.hxx> |
22 | #include <BRepAdaptor_HSurface.hxx> |
23 | #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> |
24 | #include <TopLoc_Location.hxx> |
25 | #include <BRep_Tool.hxx> |
26 | #include <TColStd_Array1OfReal.hxx> |
27 | #include <TopExp_Explorer.hxx> |
28 | #include <TopoDS_Vertex.hxx> |
29 | #include <TopoDS.hxx> |
30 | #include <TopTools_ListIteratorOfListOfShape.hxx> |
31 | #include <TopTools_ListOfShape.hxx> |
32 | #include <TColStd_Array1OfReal.hxx> |
33 | |
ceb418e1 |
34 | |
35 | //======================================================================= |
36 | //function : Constructor |
37 | //purpose : |
38 | //======================================================================= |
39 | BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator( |
40 | const TopoDS_Edge& theEdge, |
41 | const Handle(BRepMesh_FaceAttribute)& theFaceAttribute, |
42 | const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces, |
43 | const Standard_Real theLinDeflection, |
74da0216 |
44 | const Standard_Real theAngDeflection, |
45 | const Standard_Real theMinSize) |
ceb418e1 |
46 | : mySurface(theFaceAttribute->Surface()) |
47 | { |
48 | Standard_Real aPreciseAngDef = 0.5 * theAngDeflection; |
49 | Standard_Real aPreciseLinDef = 0.5 * theLinDeflection; |
50 | if (theEdge.Orientation() == TopAbs_INTERNAL) |
51 | aPreciseLinDef *= 0.5; |
52 | |
53 | mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef; |
74da0216 |
54 | mySquareMinSize = Max(mySquareEdgeDef, theMinSize * theMinSize); |
ceb418e1 |
55 | |
56 | Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge); |
57 | if (isSameParam) |
58 | myCOnS.Initialize(theEdge); |
59 | else |
60 | myCOnS.Initialize(theEdge, theFaceAttribute->Face()); |
61 | |
ceb418e1 |
62 | const GeomAbs_CurveType aCurveType = myCOnS.GetType(); |
63 | Standard_Integer aMinPntNb = (aCurveType == GeomAbs_Circle) ? 4 : 2; //OCC287 |
64 | |
65 | // Get range on 2d curve |
66 | Standard_Real aFirstParam, aLastParam; |
67 | BRep_Tool::Range(theEdge, theFaceAttribute->Face(), aFirstParam, aLastParam); |
68 | myTool = new BRepMesh_GeomTool(myCOnS, aFirstParam, aLastParam, |
74da0216 |
69 | aPreciseLinDef, aPreciseAngDef, aMinPntNb, theMinSize); |
ceb418e1 |
70 | |
71 | if (aCurveType == GeomAbs_BSplineCurve) |
72 | { |
77e39787 |
73 | // bug24220 |
ceb418e1 |
74 | const Standard_Integer aNbInt = myCOnS.NbIntervals(GeomAbs_C1); |
75 | if ( aNbInt > 0 ) |
76 | { |
77 | TColStd_Array1OfReal anIntervals( 1, aNbInt + 1 ); |
78 | myCOnS.Intervals(anIntervals, GeomAbs_C1); |
79 | for (Standard_Integer aIntIt = 1; aIntIt <= aNbInt; ++aIntIt) |
80 | { |
81 | const Standard_Real& aStartInt = anIntervals.Value( aIntIt ); |
82 | const Standard_Real& anEndInt = anIntervals.Value( aIntIt + 1 ); |
83 | |
84 | BRepMesh_GeomTool aDetalizator(myCOnS, aStartInt, anEndInt, |
74da0216 |
85 | aPreciseLinDef, aPreciseAngDef, aMinPntNb, theMinSize); |
ceb418e1 |
86 | |
87 | Standard_Integer aNbAddNodes = aDetalizator.NbPoints(); |
88 | for ( Standard_Integer aNodeIt = 1; aNodeIt <= aNbAddNodes; ++aNodeIt ) |
89 | { |
90 | Standard_Real aParam; |
91 | gp_Pnt aPoint3d; |
92 | gp_Pnt2d aPoint2d; |
93 | aDetalizator.Value( aNodeIt, mySurface, aParam, aPoint3d, aPoint2d ); |
94 | myTool->AddPoint( aPoint3d, aParam, Standard_False ); |
95 | } |
96 | } |
97 | } |
98 | } |
77e39787 |
99 | |
ceb418e1 |
100 | // PTv, chl/922/G9, Take into account internal vertices |
101 | // it is necessary for internal edges, which do not split other edges, by their vertex |
102 | TopExp_Explorer aVertexIt(theEdge, TopAbs_VERTEX); |
103 | for (; aVertexIt.More(); aVertexIt.Next()) |
104 | { |
105 | const TopoDS_Vertex& aVertex = TopoDS::Vertex(aVertexIt.Current()); |
106 | if (aVertex.Orientation() != TopAbs_INTERNAL) |
107 | continue; |
108 | |
109 | myTool->AddPoint(BRep_Tool::Pnt(aVertex), |
110 | BRep_Tool::Parameter(aVertex, theEdge), Standard_True); |
111 | } |
112 | |
113 | Standard_Integer aNodesNb = myTool->NbPoints(); |
114 | //Check deflection in 2d space for improvement of edge tesselation. |
115 | if( isSameParam && aNodesNb > 1) |
116 | { |
117 | const TopTools_ListOfShape& aSharedFaces = theMapOfSharedFaces.FindFromKey(theEdge); |
118 | TopTools_ListIteratorOfListOfShape aFaceIt(aSharedFaces); |
119 | for (; aFaceIt.More(); aFaceIt.Next()) |
120 | { |
121 | TopLoc_Location aLoc; |
122 | const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Value()); |
123 | Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc); |
124 | |
125 | if (aSurf->IsInstance(STANDARD_TYPE(Geom_Plane))) |
126 | continue; |
127 | |
128 | Standard_Real aF, aL; |
129 | Handle(Geom2d_Curve) aCurve2d = BRep_Tool::CurveOnSurface(theEdge, aFace, aF, aL); |
130 | if ( Abs(aF - aFirstParam) > Precision::PConfusion() || |
131 | Abs(aL - aLastParam ) > Precision::PConfusion() ) |
132 | { |
133 | continue; |
134 | } |
135 | |
136 | aNodesNb = myTool->NbPoints(); |
137 | TColStd_Array1OfReal aParamArray(1, aNodesNb); |
138 | for (Standard_Integer i = 1; i <= aNodesNb; ++i) |
139 | { |
140 | gp_Pnt2d aTmpUV; |
141 | gp_Pnt aTmpPnt; |
142 | Standard_Real aParam; |
143 | myTool->Value(i, mySurface, aParam, aTmpPnt, aTmpUV); |
144 | aParamArray.SetValue(i, aParam); |
145 | } |
146 | |
147 | for (Standard_Integer i = 1; i < aNodesNb; ++i) |
148 | splitSegment(aSurf, aCurve2d, aParamArray(i), aParamArray(i + 1), 1); |
149 | } |
150 | } |
151 | } |
152 | |
153 | //======================================================================= |
154 | //function : Value |
155 | //purpose : |
156 | //======================================================================= |
157 | void BRepMesh_EdgeTessellator::Value(const Standard_Integer theIndex, |
158 | Standard_Real& theParameter, |
159 | gp_Pnt& thePoint, |
160 | gp_Pnt2d& theUV) |
161 | { |
162 | myTool->Value(theIndex, mySurface, theParameter, thePoint, theUV); |
163 | } |
164 | |
165 | //======================================================================= |
166 | //function : splitSegment |
167 | //purpose : |
168 | //======================================================================= |
169 | void BRepMesh_EdgeTessellator::splitSegment( |
170 | const Handle(Geom_Surface)& theSurf, |
171 | const Handle(Geom2d_Curve)& theCurve2d, |
172 | const Standard_Real theFirst, |
173 | const Standard_Real theLast, |
174 | const Standard_Integer theNbIter) |
175 | { |
176 | // limit iteration depth |
177 | if(theNbIter > 10) |
178 | return; |
179 | |
180 | gp_Pnt2d uvf, uvl, uvm; |
181 | gp_Pnt P3dF, P3dL, midP3d, midP3dFromSurf; |
182 | Standard_Real midpar; |
183 | |
184 | if(Abs(theLast - theFirst) < 2 * Precision::PConfusion()) |
185 | return; |
186 | |
187 | theCurve2d->D0(theFirst, uvf); |
188 | theCurve2d->D0(theLast, uvl); |
189 | |
190 | P3dF = theSurf->Value(uvf.X(), uvf.Y()); |
191 | P3dL = theSurf->Value(uvl.X(), uvl.Y()); |
192 | |
74da0216 |
193 | if(P3dF.SquareDistance(P3dL) < mySquareMinSize) |
ceb418e1 |
194 | return; |
195 | |
196 | uvm = gp_Pnt2d((uvf.XY() + uvl.XY())*0.5); |
197 | midP3dFromSurf = theSurf->Value(uvm.X(), uvm.Y()); |
198 | |
74da0216 |
199 | gp_XYZ Vec1 = midP3dFromSurf.XYZ() - P3dF.XYZ(); |
200 | if(Vec1.SquareModulus() < mySquareMinSize) |
201 | return; |
202 | |
ceb418e1 |
203 | gp_XYZ aVec = P3dL.XYZ() - P3dF.XYZ(); |
204 | aVec.Normalize(); |
205 | |
ceb418e1 |
206 | Standard_Real aModulus = Vec1.Dot(aVec); |
207 | gp_XYZ aProj = aVec * aModulus; |
208 | gp_XYZ aDist = Vec1 - aProj; |
209 | |
210 | if(aDist.SquareModulus() < mySquareEdgeDef) |
211 | return; |
212 | |
213 | midpar = (theFirst + theLast) * 0.5; |
214 | myCOnS.D0(midpar, midP3d); |
215 | myTool->AddPoint(midP3d, midpar, Standard_False); |
216 | |
217 | splitSegment(theSurf, theCurve2d, theFirst, midpar, theNbIter + 1); |
218 | splitSegment(theSurf, theCurve2d, midpar, theLast, theNbIter + 1); |
219 | } |