Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created by: Ekaterina SMIRNOVA |
973c2be1 | 2 | // Copyright (c) 2008-2014 OPEN CASCADE SAS |
b311480e | 3 | // |
973c2be1 | 4 | // This file is part of Open CASCADE Technology software library. |
b311480e | 5 | // |
d5f74e42 | 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 | |
973c2be1 | 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. | |
b311480e | 11 | // |
973c2be1 | 12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. | |
7fd59977 | 14 | |
fc9b36d6 | 15 | #include <BRepMesh_FastDiscretFace.hxx> |
7fd59977 | 16 | |
7fd59977 | 17 | #include <BRepMesh_PairOfPolygon.hxx> |
fc9b36d6 | 18 | #include <BRepMesh_ShapeTool.hxx> |
19 | #include <Poly_PolygonOnTriangulation.hxx> | |
20 | #include <Poly_Triangulation.hxx> | |
21 | ||
22 | #include <BRepAdaptor_Surface.hxx> | |
23 | #include <BRepAdaptor_HSurface.hxx> | |
24 | #include <BRepAdaptor_Curve.hxx> | |
25 | #include <Adaptor3d_IsoCurve.hxx> | |
26 | ||
27 | #include <BRep_ListIteratorOfListOfPointRepresentation.hxx> | |
7fd59977 | 28 | #include <BRep_PointRepresentation.hxx> |
29 | #include <BRep_TVertex.hxx> | |
30 | #include <BRep_Tool.hxx> | |
fc9b36d6 | 31 | |
fc9b36d6 | 32 | #include <GeomLib.hxx> |
33 | #include <Geom_Surface.hxx> | |
34 | #include <Geom_BSplineSurface.hxx> | |
c04c30b3 | 35 | #include <Geom_BezierSurface.hxx> |
fc9b36d6 | 36 | #include <GCPnts_TangentialDeflection.hxx> |
74da0216 | 37 | #include <GCPnts_AbscissaPoint.hxx> |
fc9b36d6 | 38 | |
7fd59977 | 39 | #include <Standard_ErrorHandler.hxx> |
40 | #include <Standard_Failure.hxx> | |
7fd59977 | 41 | #include <TColStd_Array1OfReal.hxx> |
fc9b36d6 | 42 | #include <TColStd_ListOfInteger.hxx> |
7fd59977 | 43 | #include <TColStd_SequenceOfReal.hxx> |
44 | #include <TColStd_Array1OfInteger.hxx> | |
7fd59977 | 45 | #include <TColStd_HArray1OfReal.hxx> |
fc9b36d6 | 46 | #include <TColgp_Array1OfPnt2d.hxx> |
47 | #include <TopTools_DataMapOfShapeReal.hxx> | |
48 | ||
7fd59977 | 49 | #include <TopExp_Explorer.hxx> |
7fd59977 | 50 | #include <TopoDS.hxx> |
fc9b36d6 | 51 | #include <TopoDS_Vertex.hxx> |
7fd59977 | 52 | #include <TopExp.hxx> |
fc9b36d6 | 53 | |
7fd59977 | 54 | #include <NCollection_Map.hxx> |
7fd59977 | 55 | #include <Bnd_Box2d.hxx> |
56 | ||
ceb418e1 | 57 | #include <algorithm> |
51c3cc5f | 58 | |
fc9b36d6 | 59 | |
92efcf78 | 60 | IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscretFace,Standard_Transient) |
61 | ||
7fd59977 | 62 | static Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_Integer PLen) |
63 | { | |
64 | Standard_Integer i, j, n = 0; | |
65 | Standard_Real p, result = 0.; | |
66 | ||
67 | for(i = 1; i <= PLen; i++) | |
68 | { | |
69 | // Sort | |
70 | for(j = i + 1; j <= PLen; j++) | |
71 | { | |
72 | if(P(i) > P(j)) | |
73 | { | |
74 | p = P(i); | |
75 | P(i) = P(j); | |
76 | P(j) = p; | |
77 | } | |
78 | } | |
79 | // Accumulate | |
80 | if (i != 1) | |
81 | { | |
82 | p = Abs(P(i) - P(i-1)); | |
83 | if(p > 1.e-7) | |
84 | { | |
85 | result += p; | |
86 | n++; | |
87 | } | |
88 | } | |
89 | } | |
90 | return (n? (result / (Standard_Real) n) : -1.); | |
91 | } | |
92 | ||
90542800 | 93 | namespace |
94 | { | |
ceb418e1 | 95 | |
96 | //! Auxiliary class used to extract geometrical parameters of fixed TopoDS_Vertex. | |
97 | class FixedVExplorer | |
98 | { | |
99 | public: | |
100 | ||
101 | DEFINE_STANDARD_ALLOC | |
102 | ||
103 | FixedVExplorer(const TopoDS_Vertex& theVertex) | |
104 | : myVertex(theVertex) | |
105 | { | |
106 | } | |
107 | ||
108 | const TopoDS_Vertex& Vertex() const | |
109 | { | |
110 | return myVertex; | |
111 | } | |
112 | ||
113 | Standard_Boolean IsSameUV() const | |
114 | { | |
115 | return Standard_False; | |
116 | } | |
117 | ||
118 | TopoDS_Vertex SameVertex() const | |
119 | { | |
120 | return TopoDS_Vertex(); | |
121 | } | |
122 | ||
90542800 | 123 | gp_Pnt Point() const |
ceb418e1 | 124 | { |
125 | return BRep_Tool::Pnt(myVertex); | |
126 | } | |
127 | ||
128 | private: | |
129 | ||
130 | void operator =(const FixedVExplorer& /*theOther*/) | |
131 | { | |
132 | } | |
133 | ||
134 | private: | |
135 | const TopoDS_Vertex& myVertex; | |
136 | }; | |
137 | } | |
138 | ||
139 | ||
7fd59977 | 140 | //======================================================================= |
141 | //function : BRepMesh_FastDiscretFace | |
90542800 | 142 | //purpose : |
7fd59977 | 143 | //======================================================================= |
a319f03f | 144 | BRepMesh_FastDiscretFace::BRepMesh_FastDiscretFace( |
145 | const Standard_Real theAngle, | |
74da0216 | 146 | const Standard_Real theMinSize, |
f43eff9f | 147 | const Standard_Boolean isInternalVerticesMode, |
148 | const Standard_Boolean isControlSurfaceDeflection) | |
90542800 | 149 | : myAngle(theAngle), |
74da0216 | 150 | myInternalVerticesMode(isInternalVerticesMode), |
f43eff9f | 151 | myMinSize(theMinSize), |
152 | myIsControlSurfaceDeflection(isControlSurfaceDeflection) | |
7fd59977 | 153 | { |
7fd59977 | 154 | } |
155 | ||
156 | //======================================================================= | |
fcf15f5c | 157 | //function : Perform |
158 | //purpose : | |
159 | //======================================================================= | |
160 | void BRepMesh_FastDiscretFace::Perform(const Handle(BRepMesh_FaceAttribute)& theAttribute) | |
161 | { | |
2caff0b3 | 162 | add(theAttribute); |
fcf15f5c | 163 | commitSurfaceTriangulation(); |
164 | } | |
165 | ||
166 | //======================================================================= | |
2caff0b3 | 167 | //function : initDataStructure |
7fd59977 | 168 | //purpose : |
169 | //======================================================================= | |
2caff0b3 | 170 | void BRepMesh_FastDiscretFace::initDataStructure() |
7fd59977 | 171 | { |
2caff0b3 | 172 | const Standard_Real aTolU = myAttribute->ToleranceU(); |
173 | const Standard_Real aTolV = myAttribute->ToleranceV(); | |
174 | const Standard_Real uCellSize = 14.0 * aTolU; | |
175 | const Standard_Real vCellSize = 14.0 * aTolV; | |
176 | ||
177 | const Standard_Real deltaX = myAttribute->GetDeltaX(); | |
178 | const Standard_Real deltaY = myAttribute->GetDeltaY(); | |
c80dc6c3 | 179 | |
74da0216 | 180 | Handle(NCollection_IncAllocator) aAllocator = |
181 | new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE); | |
182 | myStructure = new BRepMesh_DataStructureOfDelaun(aAllocator); | |
2caff0b3 | 183 | myStructure->Data()->SetCellSize ( uCellSize / deltaX, vCellSize / deltaY); |
184 | myStructure->Data()->SetTolerance( aTolU / deltaX, aTolV / deltaY); | |
51c3cc5f | 185 | |
2caff0b3 | 186 | myAttribute->ChangeStructure() = myStructure; |
187 | myAttribute->ChangeSurfacePoints() = new BRepMesh::DMapOfIntegerPnt; | |
188 | myAttribute->ChangeSurfaceVertices()= new BRepMesh::DMapOfVertexInteger; | |
51c3cc5f | 189 | |
2caff0b3 | 190 | // Check the necessity to fill the map of parameters |
ceb418e1 | 191 | const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); |
192 | GeomAbs_SurfaceType thetype = gFace->GetType(); | |
13cd069d | 193 | const Standard_Boolean isBSpline = (thetype == GeomAbs_BezierSurface || |
194 | thetype == GeomAbs_BSplineSurface); | |
195 | const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus ||isBSpline); | |
196 | ||
2caff0b3 | 197 | myUParam.Clear(); |
198 | myVParam.Clear(); | |
51c3cc5f | 199 | |
2caff0b3 | 200 | // essai de determination de la longueur vraie: |
201 | // akm (bug OCC16) : We must calculate these measures in non-singular | |
202 | // parts of face. Let`s try to compute average value of three | |
203 | // (umin, (umin+umax)/2, umax), and respectively for v. | |
204 | // vvvvv | |
205 | //Standard_Real longu = 0.0, longv = 0.0; //, last , first; | |
206 | //gp_Pnt P11, P12, P21, P22, P31, P32; | |
207 | BRepMesh::HVectorOfVertex& aBoundaryNodes = myAttribute->ChangeMeshNodes(); | |
208 | BRepMesh::VectorOfVertex::Iterator aNodesIt(*aBoundaryNodes); | |
209 | for (; aNodesIt.More(); aNodesIt.Next()) | |
210 | { | |
211 | BRepMesh_Vertex& aNode = aNodesIt.ChangeValue(); | |
212 | gp_XY aPnt2d = aNode.Coord(); | |
213 | ||
214 | if (useUVParam) | |
215 | { | |
216 | myUParam.Add(aPnt2d.X()); | |
217 | myVParam.Add(aPnt2d.Y()); | |
218 | } | |
219 | ||
220 | aNode.ChangeCoord() = myAttribute->Scale(aPnt2d, Standard_True); | |
221 | myStructure->AddNode(aNode, Standard_True); | |
222 | } | |
223 | aBoundaryNodes.Nullify(); | |
51c3cc5f | 224 | |
13cd069d | 225 | if (isBSpline) |
226 | { | |
227 | const Standard_Real aRange[2][2] = { | |
228 | {myAttribute->GetUMin(), myAttribute->GetUMax()}, | |
229 | {myAttribute->GetVMin(), myAttribute->GetVMax()} | |
230 | }; | |
231 | ||
232 | const GeomAbs_Shape aContinuity = GeomAbs_CN; | |
233 | for (Standard_Integer i = 0; i < 2; ++i) | |
234 | { | |
235 | const Standard_Boolean isU = (i == 0); | |
236 | const Standard_Integer aIntervalsNb = isU ? | |
237 | gFace->NbUIntervals(aContinuity) : | |
238 | gFace->NbVIntervals(aContinuity); | |
239 | ||
240 | BRepMesh::IMapOfReal& aParams = isU ? myUParam : myVParam; | |
241 | if (aIntervalsNb < aParams.Size()) | |
242 | continue; | |
243 | ||
244 | TColStd_Array1OfReal aIntervals(1, aIntervalsNb + 1); | |
245 | if (isU) | |
246 | gFace->UIntervals(aIntervals, aContinuity); | |
247 | else | |
248 | gFace->VIntervals(aIntervals, aContinuity); | |
249 | ||
250 | for (Standard_Integer j = 1; j <= aIntervals.Upper(); ++j) | |
251 | { | |
252 | const Standard_Real aParam = aIntervals(j); | |
253 | if (aParam > aRange[i][0] && aParam < aRange[i][1]) | |
254 | aParams.Add(aParam); | |
255 | } | |
256 | } | |
257 | } | |
258 | ||
ceb418e1 | 259 | //////////////////////////////////////////////////////////// |
260 | //add internal vertices after self-intersection check | |
ceb418e1 | 261 | if ( myInternalVerticesMode ) |
262 | { | |
263 | TopExp_Explorer anExplorer(myAttribute->Face(), TopAbs_VERTEX, TopAbs_EDGE); | |
264 | for ( ; anExplorer.More(); anExplorer.Next() ) | |
265 | add(TopoDS::Vertex(anExplorer.Current())); | |
ceb418e1 | 266 | } |
51c3cc5f | 267 | |
2caff0b3 | 268 | const BRepMesh::HDMapOfShapePairOfPolygon& aEdges = myAttribute->ChangeInternalEdges(); |
269 | TopExp_Explorer aWireIt(myAttribute->Face(), TopAbs_WIRE); | |
270 | for (; aWireIt.More(); aWireIt.Next()) | |
271 | { | |
272 | TopExp_Explorer aEdgeIt(aWireIt.Current(), TopAbs_EDGE); | |
273 | for (; aEdgeIt.More(); aEdgeIt.Next()) | |
274 | { | |
275 | const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current()); | |
276 | BRepMesh_PairOfPolygon aPair; | |
277 | if (!aEdges->Find(aEdge, aPair)) | |
278 | continue; | |
7fd59977 | 279 | |
2caff0b3 | 280 | TopAbs_Orientation aOri = aEdge.Orientation(); |
281 | const Handle(Poly_PolygonOnTriangulation)& aPolygon = | |
282 | aOri == TopAbs_REVERSED ? aPair.Last() : aPair.First(); | |
304c45c8 | 283 | |
2caff0b3 | 284 | const TColStd_Array1OfInteger& aIndices = aPolygon->Nodes(); |
285 | const Standard_Integer aNodesNb = aPolygon->NbNodes(); | |
7fd59977 | 286 | |
2caff0b3 | 287 | Standard_Integer aPrevId = aIndices(1); |
288 | for (Standard_Integer i = 2; i <= aNodesNb; ++i) | |
289 | { | |
290 | const Standard_Integer aCurId = aIndices(i); | |
291 | addLinkToMesh(aPrevId, aCurId, aOri); | |
292 | aPrevId = aCurId; | |
293 | } | |
294 | } | |
295 | } | |
296 | } | |
7fd59977 | 297 | |
2caff0b3 | 298 | //======================================================================= |
299 | //function : addLinkToMesh | |
300 | //purpose : | |
301 | //======================================================================= | |
302 | void BRepMesh_FastDiscretFace::addLinkToMesh( | |
303 | const Standard_Integer theFirstNodeId, | |
304 | const Standard_Integer theLastNodeId, | |
305 | const TopAbs_Orientation theOrientation) | |
306 | { | |
307 | if (theOrientation == TopAbs_FORWARD) | |
308 | myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Frontier)); | |
309 | else if (theOrientation == TopAbs_REVERSED) | |
310 | myStructure->AddLink(BRepMesh_Edge(theLastNodeId, theFirstNodeId, BRepMesh_Frontier)); | |
311 | else if (theOrientation == TopAbs_INTERNAL) | |
312 | myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Fixed)); | |
313 | } | |
7fd59977 | 314 | |
2caff0b3 | 315 | //======================================================================= |
316 | //function : Add | |
317 | //purpose : | |
318 | //======================================================================= | |
319 | void BRepMesh_FastDiscretFace::add(const Handle(BRepMesh_FaceAttribute)& theAttribute) | |
320 | { | |
321 | if (!theAttribute->IsValid() || theAttribute->ChangeMeshNodes()->IsEmpty()) | |
322 | return; | |
7fd59977 | 323 | |
2caff0b3 | 324 | myAttribute = theAttribute; |
325 | initDataStructure(); | |
ceb418e1 | 326 | |
2caff0b3 | 327 | BRepMesh::HIMapOfInteger& aVertexEdgeMap = myAttribute->ChangeVertexEdgeMap(); |
328 | Standard_Integer nbVertices = aVertexEdgeMap->Extent(); | |
329 | BRepMesh::Array1OfInteger tabvert_corr(1, nbVertices); | |
330 | for ( Standard_Integer i = 1; i <= nbVertices; ++i ) | |
ceb418e1 | 331 | tabvert_corr(i) = i; |
7fd59977 | 332 | |
ceb418e1 | 333 | BRepMesh_Delaun trigu(myStructure, tabvert_corr); |
f67d0512 | 334 | |
ceb418e1 | 335 | //removed all free edges from triangulation |
336 | const Standard_Integer nbLinks = myStructure->NbLinks(); | |
2caff0b3 | 337 | for( Standard_Integer i = 1; i <= nbLinks; i++ ) |
ceb418e1 | 338 | { |
339 | if( myStructure->ElementsConnectedTo(i).Extent() < 1 ) | |
340 | { | |
341 | BRepMesh_Edge& anEdge = (BRepMesh_Edge&)trigu.GetEdge(i); | |
342 | if ( anEdge.Movability() == BRepMesh_Deleted ) | |
343 | continue; | |
f67d0512 | 344 | |
ceb418e1 | 345 | anEdge.SetMovability(BRepMesh_Free); |
346 | myStructure->RemoveLink(i); | |
347 | } | |
c80dc6c3 | 348 | } |
7fd59977 | 349 | |
2caff0b3 | 350 | const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); |
351 | GeomAbs_SurfaceType thetype = gFace->GetType(); | |
352 | ||
353 | Standard_Boolean rajout = | |
354 | (thetype == GeomAbs_Sphere || thetype == GeomAbs_Torus); | |
355 | ||
356 | // Check the necessity to fill the map of parameters | |
357 | const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus || | |
358 | thetype == GeomAbs_BezierSurface || | |
359 | thetype == GeomAbs_BSplineSurface); | |
360 | ||
ceb418e1 | 361 | const Standard_Real umax = myAttribute->GetUMax(); |
362 | const Standard_Real umin = myAttribute->GetUMin(); | |
363 | const Standard_Real vmax = myAttribute->GetVMax(); | |
364 | const Standard_Real vmin = myAttribute->GetVMin(); | |
b0cf1019 | 365 | |
ceb418e1 | 366 | Standard_Boolean isaline = |
367 | ((umax - umin) < Precision::PConfusion() || | |
368 | (vmax - vmin) < Precision::PConfusion()); | |
b0cf1019 | 369 | |
ceb418e1 | 370 | Standard_Real aDef = -1; |
371 | if ( !isaline && myStructure->ElementsOfDomain().Extent() > 0 ) | |
c80dc6c3 | 372 | { |
848fa7e3 | 373 | BRepMesh::ListOfVertex aNewVertices; |
74da0216 | 374 | if (!rajout) |
c80dc6c3 | 375 | { |
ceb418e1 | 376 | aDef = control(aNewVertices, trigu, Standard_True); |
74da0216 | 377 | rajout = (aDef > myAttribute->GetDefFace() || aDef < 0.); |
c80dc6c3 | 378 | } |
ceb418e1 | 379 | |
74da0216 | 380 | if (!rajout && useUVParam) |
c80dc6c3 | 381 | { |
74da0216 | 382 | rajout = (myVParam.Extent() > 2 && |
383 | (gFace->IsUClosed() || gFace->IsVClosed())); | |
7fd59977 | 384 | } |
7fd59977 | 385 | |
74da0216 | 386 | if (rajout) |
ceb418e1 | 387 | { |
388 | insertInternalVertices(aNewVertices, trigu); | |
fc9b36d6 | 389 | |
ceb418e1 | 390 | //control internal points |
f43eff9f | 391 | if (myIsControlSurfaceDeflection) |
392 | aDef = control(aNewVertices, trigu, Standard_False); | |
ceb418e1 | 393 | } |
c80dc6c3 | 394 | } |
ceb418e1 | 395 | |
396 | //modify myStructure back | |
2caff0b3 | 397 | BRepMesh::HVectorOfVertex& aMeshNodes = myStructure->Data()->ChangeVertices(); |
398 | for ( Standard_Integer i = 1; i <= myStructure->NbNodes(); ++i ) | |
c80dc6c3 | 399 | { |
2caff0b3 | 400 | BRepMesh_Vertex& aNode = aMeshNodes->ChangeValue(i - 1); |
401 | aNode.ChangeCoord() = myAttribute->Scale(aNode.Coord(), Standard_False); | |
ceb418e1 | 402 | |
2caff0b3 | 403 | const BRepMesh::ListOfInteger& alist = myStructure->LinksConnectedTo(i); |
ceb418e1 | 404 | // Register internal nodes used in triangulation |
2caff0b3 | 405 | if (!alist.IsEmpty() && aVertexEdgeMap->FindIndex(i) == 0) |
406 | aVertexEdgeMap->Add(i); | |
c80dc6c3 | 407 | } |
b0cf1019 | 408 | |
ceb418e1 | 409 | if (!(aDef < 0.)) |
410 | myAttribute->SetDefFace(aDef); | |
c80dc6c3 | 411 | } |
b0cf1019 P |
412 | |
413 | //======================================================================= | |
ceb418e1 | 414 | //function : addVerticesToMesh |
b0cf1019 P |
415 | //purpose : |
416 | //======================================================================= | |
ceb418e1 | 417 | Standard_Boolean BRepMesh_FastDiscretFace::addVerticesToMesh( |
848fa7e3 | 418 | const BRepMesh::ListOfVertex& theVertices, |
419 | BRepMesh_Delaun& theMeshBuilder) | |
ceb418e1 | 420 | { |
421 | if (theVertices.IsEmpty()) | |
422 | return Standard_False; | |
423 | ||
848fa7e3 | 424 | BRepMesh::Array1OfVertexOfDelaun aArrayOfNewVertices(1, theVertices.Extent()); |
425 | BRepMesh::ListOfVertex::Iterator aVertexIt(theVertices); | |
ceb418e1 | 426 | for (Standard_Integer aVertexId = 0; aVertexIt.More(); aVertexIt.Next()) |
427 | aArrayOfNewVertices(++aVertexId) = aVertexIt.Value(); | |
428 | ||
429 | theMeshBuilder.AddVertices(aArrayOfNewVertices); | |
430 | return Standard_True; | |
431 | } | |
b0cf1019 | 432 | |
ceb418e1 | 433 | //======================================================================= |
434 | //function : insertInternalVertices | |
435 | //purpose : | |
436 | //======================================================================= | |
848fa7e3 | 437 | static void filterParameters(const BRepMesh::IMapOfReal& theParams, |
438 | const Standard_Real theMinDist, | |
439 | const Standard_Real theFilterDist, | |
440 | BRepMesh::SequenceOfReal& theResult) | |
b0cf1019 P |
441 | { |
442 | // Sort sequence of parameters | |
848fa7e3 | 443 | BRepMesh::SequenceOfReal aParamTmp; |
b0cf1019 P |
444 | Standard_Integer aParamLength = 1; |
445 | const Standard_Integer anInitLen = theParams.Extent(); | |
703a6abd | 446 | |
b0cf1019 P |
447 | TColStd_Array1OfReal aParamArray(1, anInitLen); |
448 | Standard_Integer j; | |
449 | for (j = 1; j <= anInitLen; j++) | |
450 | aParamArray(j) = theParams(j); | |
451 | ||
e35db416 | 452 | std::sort (aParamArray.begin(), aParamArray.end()); |
b0cf1019 | 453 | |
e35db416 | 454 | // mandatory pre-filtering using the first (minimal) filter value |
b0cf1019 P |
455 | Standard_Real aP1, aP2; |
456 | aP1 = aParamArray(1); | |
457 | aParamTmp.Append(aP1); | |
458 | for (j = 2; j <= anInitLen; j++) | |
459 | { | |
460 | aP2 = aParamArray(j); | |
461 | if ((aP2-aP1) > theMinDist) | |
462 | { | |
463 | aParamTmp.Append(aP2); | |
464 | aP1 = aP2; | |
465 | aParamLength++; | |
466 | } | |
703a6abd | 467 | } |
b0cf1019 P |
468 | |
469 | //add last point if required | |
470 | if(aParamArray(anInitLen)-theParams(aParamLength) > theMinDist) | |
703a6abd | 471 | { |
ceb418e1 | 472 | aParamTmp.Append(aParamArray(anInitLen)); |
b0cf1019 | 473 | aParamLength++; |
703a6abd | 474 | } |
b0cf1019 P |
475 | |
476 | //perform filtering on series | |
477 | Standard_Real aLastAdded, aLastCandidate; | |
478 | Standard_Boolean isCandidateDefined = Standard_False; | |
479 | aLastAdded = aParamTmp.First(); | |
480 | aLastCandidate = aLastAdded; | |
481 | theResult.Append(aParamTmp.First()); | |
482 | ||
483 | for(j=2;j<aParamTmp.Length();j++) | |
703a6abd | 484 | { |
b0cf1019 P |
485 | Standard_Real aVal = aParamTmp.Value(j); |
486 | if(aVal-aLastAdded > theFilterDist) | |
487 | { | |
488 | //adds the parameter | |
489 | if(isCandidateDefined) { | |
490 | aLastAdded = aLastCandidate; | |
491 | isCandidateDefined = Standard_False; | |
492 | j--; | |
493 | } | |
494 | else | |
495 | { | |
496 | aLastAdded = aVal; | |
497 | } | |
498 | theResult.Append(aLastAdded); | |
499 | continue; | |
500 | } | |
501 | ||
502 | aLastCandidate = aVal; | |
503 | isCandidateDefined = Standard_True; | |
703a6abd | 504 | } |
b0cf1019 | 505 | theResult.Append(aParamTmp.Last()); |
4071d9e6 O |
506 | |
507 | if( theResult.Length() == 2 ) | |
508 | { | |
509 | Standard_Real dist = theResult.Last() - theResult.First(); | |
510 | Standard_Integer nbint = (Standard_Integer)((dist / theFilterDist) + 0.5); | |
511 | ||
512 | if( nbint > 1 ) | |
513 | { | |
514 | //Five points more is maximum | |
515 | if( nbint > 5 ) | |
516 | { | |
517 | nbint = 5; | |
518 | } | |
519 | ||
520 | Standard_Integer i; | |
521 | Standard_Real dU = dist / nbint; | |
522 | for( i = 1; i < nbint; i++ ) | |
523 | { | |
524 | theResult.InsertAfter(i, theResult.First()+i*dU); | |
525 | } | |
526 | } | |
527 | } | |
703a6abd | 528 | } |
7fd59977 | 529 | |
ceb418e1 | 530 | void BRepMesh_FastDiscretFace::insertInternalVertices( |
848fa7e3 | 531 | BRepMesh::ListOfVertex& theNewVertices, |
532 | BRepMesh_Delaun& theMeshBuilder) | |
7fd59977 | 533 | { |
ceb418e1 | 534 | const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); |
535 | switch (gFace->GetType()) | |
536 | { | |
537 | case GeomAbs_Sphere: | |
538 | insertInternalVerticesSphere(theNewVertices); | |
539 | break; | |
540 | ||
541 | case GeomAbs_Cylinder: | |
542 | insertInternalVerticesCylinder(theNewVertices); | |
543 | break; | |
544 | ||
545 | case GeomAbs_Cone: | |
546 | insertInternalVerticesCone(theNewVertices); | |
547 | break; | |
548 | ||
549 | case GeomAbs_Torus: | |
550 | insertInternalVerticesTorus(theNewVertices); | |
551 | break; | |
552 | ||
553 | case GeomAbs_BezierSurface: | |
554 | case GeomAbs_BSplineSurface: | |
555 | insertInternalVerticesBSpline(theNewVertices); | |
556 | break; | |
557 | ||
558 | default: | |
559 | insertInternalVerticesOther(theNewVertices); | |
560 | break; | |
561 | } | |
7fd59977 | 562 | |
ceb418e1 | 563 | addVerticesToMesh(theNewVertices, theMeshBuilder); |
564 | } | |
565 | ||
566 | //======================================================================= | |
567 | //function : insertInternalVerticesSphere | |
568 | //purpose : | |
569 | //======================================================================= | |
570 | void BRepMesh_FastDiscretFace::insertInternalVerticesSphere( | |
848fa7e3 | 571 | BRepMesh::ListOfVertex& theNewVertices) |
ceb418e1 | 572 | { |
74da0216 | 573 | Standard_Real aRange[] = { |
574 | myAttribute->GetVMin(), myAttribute->GetVMax(), | |
575 | myAttribute->GetUMin(), myAttribute->GetUMax() | |
576 | }; | |
ceb418e1 | 577 | |
74da0216 | 578 | gp_Sphere aSphere = myAttribute->Surface()->Sphere(); |
ceb418e1 | 579 | |
580 | // Calculate parameters for iteration in V direction | |
74da0216 | 581 | Standard_Real aStep = 0.7 * GCPnts_TangentialDeflection::ArcAngularStep( |
582 | aSphere.Radius(), myAttribute->GetDefFace(), myAngle, myMinSize); | |
ceb418e1 | 583 | |
74da0216 | 584 | Standard_Real aDd[2] = {aStep, aStep}; |
585 | Standard_Real aPasMax[2] = {0., 0.}; | |
586 | for (Standard_Integer i = 0; i < 2; ++i) | |
587 | { | |
588 | const Standard_Real aMax = aRange[2 * i + 1]; | |
589 | const Standard_Real aDiff = aMax - aRange[2 * i + 0]; | |
590 | aDd[i] = aDiff / ((Standard_Integer)(aDiff / aDd[i]) + 1); | |
591 | aPasMax[i] = aMax - Precision::PConfusion(); | |
592 | } | |
ceb418e1 | 593 | |
74da0216 | 594 | const Standard_Real aHalfDu = aDd[1] * 0.5; |
ceb418e1 | 595 | Standard_Boolean Shift = Standard_False; |
74da0216 | 596 | Standard_Real aPasV = aRange[0] + aDd[0]; |
597 | for (; aPasV < aPasMax[0]; aPasV += aDd[0]) | |
ceb418e1 | 598 | { |
ceb418e1 | 599 | Shift = !Shift; |
74da0216 | 600 | const Standard_Real d = (Shift) ? aHalfDu : 0.; |
601 | Standard_Real aPasU = aRange[2] + d; | |
602 | for (; aPasU < aPasMax[1]; aPasU += aDd[1]) | |
7fd59977 | 603 | { |
74da0216 | 604 | tryToInsertAnalyticVertex(gp_Pnt2d(aPasU, aPasV), aSphere, theNewVertices); |
7fd59977 | 605 | } |
606 | } | |
ceb418e1 | 607 | } |
7fd59977 | 608 | |
ceb418e1 | 609 | //======================================================================= |
610 | //function : insertInternalVerticesCylinder | |
611 | //purpose : | |
612 | //======================================================================= | |
613 | void BRepMesh_FastDiscretFace::insertInternalVerticesCylinder( | |
848fa7e3 | 614 | BRepMesh::ListOfVertex& theNewVertices) |
ceb418e1 | 615 | { |
616 | const Standard_Real umax = myAttribute->GetUMax(); | |
617 | const Standard_Real umin = myAttribute->GetUMin(); | |
618 | const Standard_Real vmax = myAttribute->GetVMax(); | |
619 | const Standard_Real vmin = myAttribute->GetVMin(); | |
620 | ||
74da0216 | 621 | gp_Cylinder aCylinder = myAttribute->Surface()->Cylinder(); |
622 | const Standard_Real aRadius = aCylinder.Radius(); | |
ceb418e1 | 623 | |
624 | // Calculate parameters for iteration in U direction | |
74da0216 | 625 | Standard_Real Du = GCPnts_TangentialDeflection::ArcAngularStep( |
626 | aRadius, myAttribute->GetDefFace(), myAngle, myMinSize); | |
627 | ||
ceb418e1 | 628 | const Standard_Real su = umax - umin; |
629 | const Standard_Integer nbU = (Standard_Integer)(su / Du); | |
630 | Du = su / (nbU + 1); | |
631 | ||
632 | // Calculate parameters for iteration in V direction | |
633 | const Standard_Real sv = vmax - vmin; | |
74da0216 | 634 | Standard_Integer nbV = (Standard_Integer)(nbU*sv / (su*aRadius)); |
ceb418e1 | 635 | nbV = Min(nbV, 100 * nbU); |
636 | Standard_Real Dv = sv / (nbV + 1); | |
637 | ||
638 | Standard_Real pasu, pasv, pasvmax = vmax - Dv*0.5, pasumax = umax - Du*0.5; | |
639 | for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) | |
640 | { | |
641 | for (pasu = umin + Du; pasu < pasumax; pasu += Du) | |
642 | { | |
74da0216 | 643 | tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), aCylinder, theNewVertices); |
7fd59977 | 644 | } |
645 | } | |
ceb418e1 | 646 | } |
647 | ||
648 | //======================================================================= | |
649 | //function : insertInternalVerticesCone | |
650 | //purpose : | |
651 | //======================================================================= | |
652 | void BRepMesh_FastDiscretFace::insertInternalVerticesCone( | |
848fa7e3 | 653 | BRepMesh::ListOfVertex& theNewVertices) |
ceb418e1 | 654 | { |
655 | const Standard_Real umax = myAttribute->GetUMax(); | |
656 | const Standard_Real umin = myAttribute->GetUMin(); | |
657 | const Standard_Real vmax = myAttribute->GetVMax(); | |
658 | const Standard_Real vmin = myAttribute->GetVMin(); | |
659 | ||
74da0216 | 660 | gp_Cone aCone = myAttribute->Surface()->Cone(); |
661 | Standard_Real RefR = aCone.RefRadius(); | |
662 | Standard_Real SAng = aCone.SemiAngle(); | |
663 | Standard_Real aRadius = Max(Abs(RefR + vmin*Sin(SAng)), Abs(RefR + vmax*Sin(SAng))); | |
664 | ||
665 | Standard_Real Du = GCPnts_TangentialDeflection::ArcAngularStep( | |
666 | aRadius, myAttribute->GetDefFace(), myAngle, myMinSize); | |
667 | ||
668 | Standard_Real Dv, pasu, pasv; | |
ceb418e1 | 669 | Standard_Integer nbU = (Standard_Integer)((umax - umin) / Du); |
74da0216 | 670 | Standard_Integer nbV = (Standard_Integer)(nbU*(vmax - vmin) / ((umax - umin)*aRadius)); |
ceb418e1 | 671 | Du = (umax - umin) / (nbU + 1); |
672 | Dv = (vmax - vmin) / (nbV + 1); | |
673 | ||
674 | Standard_Real pasvmax = vmax - Dv*0.5, pasumax = umax - Du*0.5; | |
675 | for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) | |
7fd59977 | 676 | { |
ceb418e1 | 677 | for (pasu = umin + Du; pasu < pasumax; pasu += Du) |
678 | { | |
74da0216 | 679 | tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), aCone, theNewVertices); |
7fd59977 | 680 | } |
681 | } | |
ceb418e1 | 682 | } |
683 | ||
684 | //======================================================================= | |
685 | //function : insertInternalVerticesTorus | |
686 | //purpose : | |
687 | //======================================================================= | |
688 | void BRepMesh_FastDiscretFace::insertInternalVerticesTorus( | |
848fa7e3 | 689 | BRepMesh::ListOfVertex& theNewVertices) |
ceb418e1 | 690 | { |
691 | const Standard_Real umax = myAttribute->GetUMax(); | |
692 | const Standard_Real umin = myAttribute->GetUMin(); | |
693 | const Standard_Real vmax = myAttribute->GetVMax(); | |
694 | const Standard_Real vmin = myAttribute->GetVMin(); | |
695 | const Standard_Real deltaX = myAttribute->GetDeltaX(); | |
696 | const Standard_Real deltaY = myAttribute->GetDeltaY(); | |
697 | const Standard_Real aDefFace = myAttribute->GetDefFace(); | |
698 | ||
699 | gp_Torus T = myAttribute->Surface()->Torus(); | |
700 | ||
701 | Standard_Boolean insert; | |
702 | Standard_Integer i, j, ParamULength, ParamVLength; | |
703 | Standard_Real pp, pasu, pasv; | |
704 | Standard_Real r = T.MinorRadius(), R = T.MajorRadius(); | |
705 | ||
848fa7e3 | 706 | BRepMesh::SequenceOfReal ParamU, ParamV; |
ceb418e1 | 707 | |
74da0216 | 708 | Standard_Real oldDv = GCPnts_TangentialDeflection::ArcAngularStep( |
709 | r, aDefFace, myAngle, myMinSize); | |
710 | ||
711 | Standard_Real Dv = 0.9*oldDv; //TWOTHIRD * oldDv; | |
ceb418e1 | 712 | Dv = oldDv; |
713 | ||
74da0216 | 714 | Standard_Real Du; |
ceb418e1 | 715 | Standard_Integer nbV = Max((Standard_Integer)((vmax - vmin) / Dv), 2); |
716 | Dv = (vmax - vmin) / (nbV + 1); | |
717 | Standard_Real ru = R + r; | |
718 | if (ru > 1.e-16) | |
7fd59977 | 719 | { |
74da0216 | 720 | Du = GCPnts_TangentialDeflection::ArcAngularStep( |
721 | ru, aDefFace, myAngle, myMinSize); | |
722 | ||
ceb418e1 | 723 | Standard_Real aa = sqrt(Du*Du + oldDv*oldDv); |
724 | if (aa < gp::Resolution()) | |
725 | return; | |
726 | Du *= Min(oldDv, Du) / aa; | |
727 | } | |
728 | else Du = Dv; | |
7fd59977 | 729 | |
ceb418e1 | 730 | Standard_Integer nbU = Max((Standard_Integer)((umax - umin) / Du), 2); |
731 | nbU = Max(nbU, (int)(nbV*(umax - umin)*R / ((vmax - vmin)*r) / 5.)); | |
732 | Du = (umax - umin) / (nbU + 1); | |
7fd59977 | 733 | |
ceb418e1 | 734 | if (R < r) |
735 | { | |
736 | // As the points of edges are returned. | |
737 | // in this case, the points are not representative. | |
7fd59977 | 738 | |
ceb418e1 | 739 | //-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid |
740 | for (i = 0; i <= nbU; i++) ParamU.Append(umin + i* Du); | |
741 | }//R<r | |
742 | else //U if R > r | |
743 | { | |
744 | //--ofv: U | |
745 | // Number of mapped U parameters | |
746 | const Standard_Integer LenU = myUParam.Extent(); | |
747 | // Fill array of U parameters | |
748 | TColStd_Array1OfReal Up(1, LenU); | |
749 | for (j = 1; j <= LenU; j++) Up(j) = myUParam(j); | |
750 | ||
751 | // Calculate DU, leave array of parameters | |
752 | Standard_Real aDU = FUN_CalcAverageDUV(Up, LenU); | |
753 | aDU = Max(aDU, Abs(umax - umin) / (Standard_Real)nbU / 2.); | |
754 | Standard_Real dUstd = Abs(umax - umin) / (Standard_Real)LenU; | |
755 | if (aDU > dUstd) dUstd = aDU; | |
756 | // Add U parameters | |
757 | for (j = 1; j <= LenU; j++) | |
7fd59977 | 758 | { |
ceb418e1 | 759 | pp = Up(j); |
7fd59977 | 760 | insert = Standard_True; |
ceb418e1 | 761 | ParamULength = ParamU.Length(); |
762 | for (i = 1; i <= ParamULength && insert; i++) | |
7fd59977 | 763 | { |
ceb418e1 | 764 | insert = (Abs(ParamU.Value(i) - pp) > (0.5*dUstd)); |
7fd59977 | 765 | } |
ceb418e1 | 766 | if (insert) ParamU.Append(pp); |
7fd59977 | 767 | } |
ceb418e1 | 768 | } |
7fd59977 | 769 | |
ceb418e1 | 770 | //--ofv: V |
771 | // Number of mapped V parameters | |
772 | const Standard_Integer LenV = myVParam.Extent(); | |
773 | // Fill array of V parameters | |
774 | TColStd_Array1OfReal Vp(1, LenV); | |
775 | for (j = 1; j <= LenV; j++) Vp(j) = myVParam(j); | |
776 | // Calculate DV, sort array of parameters | |
777 | Standard_Real aDV = FUN_CalcAverageDUV(Vp, LenV); | |
778 | aDV = Max(aDV, Abs(vmax - vmin) / (Standard_Real)nbV / 2.); | |
779 | ||
780 | Standard_Real dVstd = Abs(vmax - vmin) / (Standard_Real)LenV; | |
781 | if (aDV > dVstd) dVstd = aDV; | |
782 | // Add V parameters | |
783 | for (j = 1; j <= LenV; j++) | |
784 | { | |
785 | pp = Vp(j); | |
7fd59977 | 786 | |
ceb418e1 | 787 | insert = Standard_True; |
788 | ParamVLength = ParamV.Length(); | |
789 | for (i = 1; i <= ParamVLength && insert; i++) | |
7fd59977 | 790 | { |
ceb418e1 | 791 | insert = (Abs(ParamV.Value(i) - pp) > (dVstd*2. / 3.)); |
792 | } | |
793 | if (insert) ParamV.Append(pp); | |
794 | } | |
795 | ||
796 | Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length(); | |
797 | Standard_Real uminnew = umin + deltaY*0.1; | |
798 | Standard_Real vminnew = vmin + deltaX*0.1; | |
799 | Standard_Real umaxnew = umax - deltaY*0.1; | |
800 | Standard_Real vmaxnew = vmax - deltaX*0.1; | |
801 | ||
802 | for (i = 1; i <= Lu; i++) | |
803 | { | |
804 | pasu = ParamU.Value(i); | |
805 | if (pasu >= uminnew && pasu < umaxnew) | |
806 | { | |
807 | for (j = 1; j <= Lv; j++) | |
7fd59977 | 808 | { |
ceb418e1 | 809 | pasv = ParamV.Value(j); |
810 | if (pasv >= vminnew && pasv < vmaxnew) | |
7fd59977 | 811 | { |
ceb418e1 | 812 | tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), T, theNewVertices); |
c80dc6c3 | 813 | } |
7fd59977 | 814 | } |
815 | } | |
816 | } | |
ceb418e1 | 817 | } |
818 | ||
819 | //======================================================================= | |
820 | //function : insertInternalVerticesBSpline | |
821 | //purpose : | |
822 | //======================================================================= | |
823 | void BRepMesh_FastDiscretFace::insertInternalVerticesBSpline( | |
848fa7e3 | 824 | BRepMesh::ListOfVertex& theNewVertices) |
ceb418e1 | 825 | { |
826 | const Standard_Real aRange[2][2] = { | |
827 | { myAttribute->GetUMax(), myAttribute->GetUMin() }, | |
828 | { myAttribute->GetVMax(), myAttribute->GetVMin() } | |
829 | }; | |
830 | ||
831 | const Standard_Real aDelta[2] = { | |
832 | myAttribute->GetDeltaX(), | |
833 | myAttribute->GetDeltaY() | |
834 | }; | |
835 | ||
836 | const Standard_Real aDefFace = myAttribute->GetDefFace(); | |
837 | const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); | |
838 | ||
848fa7e3 | 839 | BRepMesh::SequenceOfReal aParams[2]; |
ceb418e1 | 840 | for (Standard_Integer i = 0; i < 2; ++i) |
7fd59977 | 841 | { |
ceb418e1 | 842 | Standard_Boolean isU = (i == 0); |
843 | Standard_Real aRes = isU ? | |
844 | gFace->UResolution(aDefFace) : | |
845 | gFace->VResolution(aDefFace); | |
b0cf1019 P |
846 | |
847 | // Sort and filter sequence of parameters | |
ceb418e1 | 848 | Standard_Real aMinDiff = Precision::PConfusion(); |
849 | if (aDelta[i] < 1.) | |
850 | aMinDiff /= aDelta[i]; | |
851 | ||
74da0216 | 852 | aMinDiff = Max(myMinSize, aMinDiff); |
853 | ||
ceb418e1 | 854 | Standard_Real aRangeDiff = aRange[i][0] - aRange[i][1]; |
855 | Standard_Real aDiffMaxLim = 0.1 * aRangeDiff; | |
74da0216 | 856 | Standard_Real aDiffMinLim = Max(0.005 * aRangeDiff, 2. * aRes); |
857 | Standard_Real aDiff = Max(myMinSize, Min(aDiffMaxLim, aDiffMinLim)); | |
ceb418e1 | 858 | filterParameters(isU ? myUParam : myVParam, aMinDiff, aDiff, aParams[i]); |
859 | } | |
860 | ||
861 | // check intermediate isolines | |
862 | Handle(Geom_Surface) aBSpline; | |
863 | GeomAbs_SurfaceType aSurfType = gFace->GetType(); | |
864 | if (aSurfType == GeomAbs_BezierSurface) | |
865 | aBSpline = gFace->Bezier(); | |
866 | else if (aSurfType == GeomAbs_BSplineSurface) | |
867 | aBSpline = gFace->BSpline(); | |
868 | ||
2caff0b3 | 869 | const BRepMesh::HClassifier& aClassifier = myAttribute->ChangeClassifier(); |
870 | ||
ceb418e1 | 871 | // precision for compare square distances |
872 | const Standard_Real aPrecision = Precision::Confusion(); | |
873 | const Standard_Real aSqPrecision = aPrecision * aPrecision; | |
874 | for (Standard_Integer k = 0; k < 2; ++k) | |
875 | { | |
848fa7e3 | 876 | BRepMesh::SequenceOfReal& aParams1 = aParams[k]; |
877 | BRepMesh::SequenceOfReal& aParams2 = aParams[(k + 1) % 2]; | |
ceb418e1 | 878 | const Standard_Boolean isU = (k == 0); |
879 | Standard_Integer aStartIndex, aEndIndex; | |
880 | if (isU) | |
881 | { | |
882 | aStartIndex = 1; | |
883 | aEndIndex = aParams1.Length(); | |
7fd59977 | 884 | } |
ceb418e1 | 885 | else |
886 | { | |
887 | aStartIndex = 2; | |
888 | aEndIndex = aParams1.Length() - 1; | |
7fd59977 | 889 | } |
7fd59977 | 890 | |
ceb418e1 | 891 | for (Standard_Integer i = aStartIndex; i <= aEndIndex; ++i) |
892 | { | |
893 | const Standard_Real aParam1 = aParams1(i); | |
74da0216 | 894 | GeomAdaptor_Curve aIso(isU ? |
895 | aBSpline->UIso(aParam1) : aBSpline->VIso(aParam1)); | |
ceb418e1 | 896 | |
897 | Standard_Real aPrevParam2 = aParams2(1); | |
74da0216 | 898 | gp_Pnt aPrevPnt2 = aIso.Value(aPrevParam2); |
ceb418e1 | 899 | for (Standard_Integer j = 2; j <= aParams2.Length();) |
900 | { | |
901 | Standard_Real aParam2 = aParams2(j); | |
74da0216 | 902 | gp_Pnt aPnt2 = aIso.Value(aParam2); |
ceb418e1 | 903 | Standard_Real aMidParam = 0.5 * (aPrevParam2 + aParam2); |
74da0216 | 904 | gp_Pnt aMidPnt = aIso.Value(aMidParam); |
ceb418e1 | 905 | |
7fd59977 | 906 | // 23.03.2010 skl for OCC21645 - change precision for comparison |
ceb418e1 | 907 | Standard_Real aDist; |
908 | if (aPrevPnt2.SquareDistance(aPnt2) > aSqPrecision) | |
909 | { | |
910 | gp_Lin aLin(aPrevPnt2, gp_Dir(gp_Vec(aPrevPnt2, aPnt2))); | |
911 | aDist = aLin.Distance(aMidPnt); | |
7fd59977 | 912 | } |
ceb418e1 | 913 | else |
914 | aDist = aPrevPnt2.Distance(aMidPnt); | |
915 | ||
74da0216 | 916 | if (aDist > aDefFace && aDist > myMinSize) |
ceb418e1 | 917 | { |
7fd59977 | 918 | // insertion |
ceb418e1 | 919 | aParams2.InsertBefore(j, aMidParam); |
7fd59977 | 920 | } |
ceb418e1 | 921 | else |
922 | { | |
b0cf1019 | 923 | //put regular grig for normals |
ceb418e1 | 924 | gp_Pnt2d aStPnt1, aStPnt2; |
925 | if (isU) | |
926 | { | |
927 | aStPnt1 = gp_Pnt2d(aParam1, aPrevParam2); | |
928 | aStPnt2 = gp_Pnt2d(aParam1, aMidParam); | |
b0cf1019 | 929 | } |
ceb418e1 | 930 | else |
931 | { | |
932 | aStPnt1 = gp_Pnt2d(aPrevParam2, aParam1); | |
933 | aStPnt2 = gp_Pnt2d(aMidParam, aParam1); | |
b0cf1019 | 934 | } |
7fd59977 | 935 | |
ceb418e1 | 936 | gp_Dir N1(0, 0, 1), N2(0, 0, 1); |
937 | Standard_Boolean aSt1 = GeomLib::NormEstim(aBSpline, aStPnt1, aPrecision, N1); | |
938 | Standard_Boolean aSt2 = GeomLib::NormEstim(aBSpline, aStPnt2, aPrecision, N2); | |
939 | ||
940 | Standard_Real aAngle = N2.Angle(N1); | |
941 | if (aSt1 < 1 && aSt2 < 1 && aAngle > myAngle) | |
942 | { | |
74da0216 | 943 | Standard_Real aLen = GCPnts_AbscissaPoint::Length(aIso, |
944 | aPrevParam2, aMidParam, aDefFace); | |
945 | ||
946 | if (aLen > myMinSize) | |
947 | { | |
948 | // insertion | |
949 | aParams2.InsertBefore(j, aMidParam); | |
950 | continue; | |
951 | } | |
b0cf1019 | 952 | } |
74da0216 | 953 | |
954 | aPrevParam2 = aParam2; | |
955 | aPrevPnt2 = aPnt2; | |
956 | ||
edf3cf25 | 957 | ++j; |
c80dc6c3 | 958 | } |
7fd59977 | 959 | } |
960 | } | |
961 | } | |
13cd069d | 962 | |
963 | // insert nodes of the regular grid | |
964 | for (Standard_Integer i = 1; i <= aParams[0].Length(); ++i) | |
965 | { | |
966 | const Standard_Real aParam1 = aParams[0].Value(i); | |
967 | for (Standard_Integer j = 1; j <= aParams[1].Length(); ++j) | |
968 | { | |
969 | gp_Pnt2d aPnt2d(aParam1, aParams[1].Value(j)); | |
970 | ||
971 | // Classify intersection point | |
972 | if (aClassifier->Perform(aPnt2d) == TopAbs_IN) | |
973 | { | |
974 | gp_Pnt aPnt; | |
975 | gFace->D0(aPnt2d.X(), aPnt2d.Y(), aPnt); | |
976 | insertVertex(aPnt, aPnt2d.Coord(), theNewVertices); | |
977 | } | |
978 | } | |
979 | } | |
ceb418e1 | 980 | } |
7fd59977 | 981 | |
ceb418e1 | 982 | //======================================================================= |
983 | //function : insertInternalVerticesOther | |
984 | //purpose : | |
985 | //======================================================================= | |
986 | void BRepMesh_FastDiscretFace::insertInternalVerticesOther( | |
848fa7e3 | 987 | BRepMesh::ListOfVertex& theNewVertices) |
ceb418e1 | 988 | { |
74da0216 | 989 | const Standard_Real aAngle = myAngle;//0.35; |
ceb418e1 | 990 | const Standard_Real aRange[2][2] = { |
991 | { myAttribute->GetUMax(), myAttribute->GetUMin() }, | |
992 | { myAttribute->GetVMax(), myAttribute->GetVMin() } | |
993 | }; | |
994 | ||
995 | const Standard_Real aDefFace = myAttribute->GetDefFace(); | |
996 | const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); | |
997 | ||
848fa7e3 | 998 | BRepMesh::SequenceOfReal aParams[2]; |
ceb418e1 | 999 | const Standard_Integer aIsoPointsNb = 11; |
1000 | for (Standard_Integer k = 0; k < 2; ++k) | |
1001 | { | |
1002 | const Standard_Boolean isU = (k == 0); | |
1003 | const GeomAbs_IsoType aIsoType = isU ? GeomAbs_IsoU : GeomAbs_IsoV; | |
1004 | const Standard_Integer aOtherParamsIndex = (k + 1) % 2; | |
1005 | const Standard_Real (&aRange1)[2] = aRange[k]; | |
1006 | const Standard_Real (&aRange2)[2] = aRange[aOtherParamsIndex]; | |
1007 | ||
1008 | GCPnts_TangentialDeflection aDiscretIso[aIsoPointsNb]; | |
1009 | const Standard_Real aStepWidth = (aRange1[0] - aRange1[1]) / aIsoPointsNb; | |
1010 | ||
1011 | // Find the most curved Iso. | |
1012 | Standard_Integer aMaxIndex = 1, aMaxPointsNb = 0; | |
1013 | for (Standard_Integer aIsoIt = 0; aIsoIt < aIsoPointsNb; ++aIsoIt) | |
1014 | { | |
1015 | Standard_Real aParam = aRange1[1] + aIsoIt * aStepWidth; | |
1016 | Adaptor3d_IsoCurve aIso(gFace, aIsoType, aParam); | |
7fd59977 | 1017 | |
ceb418e1 | 1018 | Standard_Real aFirstParam = Max(aRange2[1], aIso.FirstParameter()); |
1019 | Standard_Real aLastParam = Min(aRange2[0], aIso.LastParameter()); | |
7fd59977 | 1020 | |
ceb418e1 | 1021 | aDiscretIso[aIsoIt].Initialize(aIso, aFirstParam, aLastParam, |
74da0216 | 1022 | aAngle, 0.7 * aDefFace, 2, Precision::PConfusion(), myMinSize); |
7fd59977 | 1023 | |
ceb418e1 | 1024 | const Standard_Integer aPointsNb = aDiscretIso[aIsoIt].NbPoints(); |
1025 | if (aPointsNb > aMaxPointsNb) | |
1026 | { | |
1027 | aMaxPointsNb = aPointsNb; | |
1028 | aMaxIndex = aIsoIt; | |
7fd59977 | 1029 | } |
1030 | } | |
7fd59977 | 1031 | |
848fa7e3 | 1032 | BRepMesh::SequenceOfReal& aParams2 = aParams[aOtherParamsIndex]; |
1033 | GCPnts_TangentialDeflection& aDIso = aDiscretIso[aMaxIndex]; | |
ceb418e1 | 1034 | for (Standard_Integer i = 1; i <= aMaxPointsNb; ++i) |
1035 | aParams2.Append(aDIso.Parameter(i)); | |
7fd59977 | 1036 | |
ceb418e1 | 1037 | if (aParams2.Length() == 2) |
1038 | aParams2.InsertAfter(1, 0.5 * (aRange2[1] + aRange2[0])); | |
7fd59977 | 1039 | } |
7fd59977 | 1040 | |
ceb418e1 | 1041 | Adaptor3d_IsoCurve aIsoV; |
1042 | aIsoV.Load(gFace); | |
7fd59977 | 1043 | |
2caff0b3 | 1044 | const BRepMesh::HClassifier& aClassifier = myAttribute->ChangeClassifier(); |
ceb418e1 | 1045 | const Standard_Integer aUPointsNb = aParams[0].Length(); |
1046 | const Standard_Integer aVPointsNb = aParams[1].Length(); | |
1047 | for (Standard_Integer i = 2; i < aVPointsNb; ++i) | |
1048 | { | |
1049 | const Standard_Real aV = aParams[1].Value(i); | |
1050 | aIsoV.Load(GeomAbs_IsoV, aV); | |
7fd59977 | 1051 | |
ceb418e1 | 1052 | for (Standard_Integer j = 2; j < aUPointsNb; ++j) |
1053 | { | |
1054 | const Standard_Real aU = aParams[0].Value(j); | |
7fd59977 | 1055 | |
ceb418e1 | 1056 | const gp_Pnt2d aNewPoint(aU, aV); |
2caff0b3 | 1057 | if (aClassifier->Perform(aNewPoint) == TopAbs_IN) |
ceb418e1 | 1058 | insertVertex(aIsoV.Value(aU), aNewPoint.Coord(), theNewVertices); |
1059 | } | |
1060 | } | |
1061 | } | |
7fd59977 | 1062 | |
74da0216 | 1063 | //======================================================================= |
1064 | //function : checkDeflectionAndInsert | |
1065 | //purpose : | |
1066 | //======================================================================= | |
1067 | Standard_Boolean BRepMesh_FastDiscretFace::checkDeflectionAndInsert( | |
1068 | const gp_Pnt& thePnt3d, | |
1069 | const gp_XY& theUV, | |
1070 | const Standard_Boolean isDeflectionCheckOnly, | |
1071 | const Standard_Real theTriangleDeflection, | |
1072 | const Standard_Real theFaceDeflection, | |
1073 | const BRepMesh_CircleTool& theCircleTool, | |
1074 | BRepMesh::ListOfVertex& theVertices, | |
1075 | Standard_Real& theMaxTriangleDeflection) | |
1076 | { | |
1077 | if (theTriangleDeflection > theMaxTriangleDeflection) | |
1078 | theMaxTriangleDeflection = theTriangleDeflection; | |
1079 | ||
1080 | if (theTriangleDeflection < theFaceDeflection) | |
1081 | return Standard_True; | |
1082 | ||
1083 | if (myMinSize > Precision::Confusion()) | |
1084 | { | |
1085 | // Iterator in the list of indexes of circles containing the node | |
1086 | BRepMesh::ListOfInteger& aCirclesList = | |
1087 | const_cast<BRepMesh_CircleTool&>(theCircleTool).Select( | |
1088 | myAttribute->Scale(theUV, Standard_True)); | |
1089 | ||
1090 | Handle(NCollection_IncAllocator) aAllocator = | |
1091 | new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE); | |
1092 | BRepMesh::MapOfInteger aUsedNodes(10, aAllocator); | |
1093 | BRepMesh::ListOfInteger::Iterator aCircleIt(aCirclesList); | |
1094 | for (; aCircleIt.More(); aCircleIt.Next()) | |
1095 | { | |
1096 | const BRepMesh_Triangle& aTriangle = | |
1097 | myStructure->GetElement(aCircleIt.Value()); | |
1098 | ||
1099 | Standard_Integer aNodes[3]; | |
1100 | myStructure->ElementNodes(aTriangle, aNodes); | |
1101 | ||
1102 | for (Standard_Integer i = 0; i < 3; ++i) | |
1103 | { | |
1104 | const Standard_Integer aNodeId = aNodes[i]; | |
1105 | if (aUsedNodes.Contains(aNodeId)) | |
1106 | continue; | |
1107 | ||
1108 | aUsedNodes.Add(aNodeId); | |
1109 | const BRepMesh_Vertex& aNode = myStructure->GetNode(aNodeId); | |
1110 | const gp_Pnt& aPoint = myAttribute->GetPoint(aNode); | |
1111 | ||
1112 | if (thePnt3d.SquareDistance(aPoint) < myMinSize * myMinSize) | |
1113 | return Standard_True; | |
1114 | } | |
1115 | } | |
1116 | } | |
1117 | ||
1118 | if (isDeflectionCheckOnly) | |
1119 | return Standard_False; | |
1120 | ||
1121 | insertVertex(thePnt3d, theUV, theVertices); | |
1122 | return Standard_True; | |
1123 | } | |
1124 | ||
7fd59977 | 1125 | //======================================================================= |
ceb418e1 | 1126 | //function : control |
7fd59977 | 1127 | //purpose : |
1128 | //======================================================================= | |
ceb418e1 | 1129 | Standard_Real BRepMesh_FastDiscretFace::control( |
848fa7e3 | 1130 | BRepMesh::ListOfVertex& theNewVertices, |
1131 | BRepMesh_Delaun& theTrigu, | |
1132 | const Standard_Boolean theIsFirst) | |
7fd59977 | 1133 | { |
ceb418e1 | 1134 | Standard_Integer aTrianglesNb = myStructure->ElementsOfDomain().Extent(); |
1135 | if (aTrianglesNb < 1) | |
1136 | return -1.0; | |
1137 | ||
7fd59977 | 1138 | //IMPORTANT: Constants used in calculations |
ceb418e1 | 1139 | const Standard_Real MinimalArea2d = 1.e-9; |
7fd59977 | 1140 | const Standard_Real MinimalSqLength3d = 1.e-12; |
ceb418e1 | 1141 | const Standard_Real aSqDefFace = myAttribute->GetDefFace() * myAttribute->GetDefFace(); |
7fd59977 | 1142 | |
ceb418e1 | 1143 | const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); |
7fd59977 | 1144 | |
ceb418e1 | 1145 | Handle(Geom_Surface) aBSpline; |
1146 | GeomAbs_SurfaceType aSurfType = gFace->GetType(); | |
1147 | if (aSurfType == GeomAbs_BezierSurface) | |
1148 | aBSpline = gFace->Bezier(); | |
1149 | else if (aSurfType == GeomAbs_BSplineSurface) | |
1150 | aBSpline = gFace->BSpline(); | |
c80dc6c3 | 1151 | |
ceb418e1 | 1152 | NCollection_DataMap<Standard_Integer, gp_Dir> aNorMap; |
848fa7e3 | 1153 | BRepMesh::MapOfIntegerInteger aStatMap; |
ceb418e1 | 1154 | NCollection_Map<BRepMesh_OrientedEdge> aCouples(3 * aTrianglesNb); |
74da0216 | 1155 | const BRepMesh_CircleTool& aCircles = theTrigu.Circles(); |
7fd59977 | 1156 | |
1157 | // Perform refinement passes | |
ceb418e1 | 1158 | // Define the number of iterations |
1159 | Standard_Integer aIterationsNb = 11; | |
1160 | const Standard_Integer aPassesNb = (theIsFirst ? 1 : aIterationsNb); | |
1161 | // Initialize stop condition | |
1162 | Standard_Real aMaxSqDef = -1.; | |
1163 | Standard_Integer aPass = 1, aInsertedNb = 1; | |
1164 | Standard_Boolean isAllDegenerated = Standard_False; | |
1165 | for (; aPass <= aPassesNb && aInsertedNb && !isAllDegenerated; ++aPass) | |
7fd59977 | 1166 | { |
ceb418e1 | 1167 | theNewVertices.Clear(); |
7fd59977 | 1168 | |
ceb418e1 | 1169 | // Reset stop condition |
1170 | aInsertedNb = 0; | |
1171 | aMaxSqDef = -1.; | |
1172 | isAllDegenerated = Standard_True; | |
7fd59977 | 1173 | |
ceb418e1 | 1174 | aTrianglesNb = myStructure->ElementsOfDomain().Extent(); |
1175 | if (aTrianglesNb < 1) | |
1176 | break; | |
7fd59977 | 1177 | |
1178 | // Iterate on current triangles | |
848fa7e3 | 1179 | const BRepMesh::MapOfInteger& aTriangles = myStructure->ElementsOfDomain(); |
1180 | BRepMesh::MapOfInteger::Iterator aTriangleIt(aTriangles); | |
ceb418e1 | 1181 | for (; aTriangleIt.More(); aTriangleIt.Next()) |
7fd59977 | 1182 | { |
ceb418e1 | 1183 | const Standard_Integer aTriangleId = aTriangleIt.Key(); |
1184 | const BRepMesh_Triangle& aCurrentTriangle = myStructure->GetElement(aTriangleId); | |
1185 | ||
1186 | if (aCurrentTriangle.Movability() == BRepMesh_Deleted) | |
1187 | continue; | |
1188 | ||
fc9b36d6 | 1189 | Standard_Integer v[3]; |
ceb418e1 | 1190 | myStructure->ElementNodes(aCurrentTriangle, v); |
fc9b36d6 | 1191 | |
1192 | Standard_Integer e[3]; | |
1193 | Standard_Boolean o[3]; | |
ceb418e1 | 1194 | aCurrentTriangle.Edges(e, o); |
1195 | ||
1196 | gp_XY xy[3]; | |
1197 | gp_XYZ p[3]; | |
1198 | Standard_Boolean m[3]; | |
1199 | for (Standard_Integer i = 0; i < 3; ++i) | |
7fd59977 | 1200 | { |
ceb418e1 | 1201 | m[i] = (myStructure->GetLink(e[i]).Movability() == BRepMesh_Frontier); |
1202 | ||
1203 | const BRepMesh_Vertex& aVertex = myStructure->GetNode(v[i]); | |
1204 | xy[i] = myAttribute->Scale(aVertex.Coord(), Standard_False); | |
1205 | p [i] = myAttribute->GetPoint(aVertex).Coord(); | |
7fd59977 | 1206 | } |
1207 | ||
ceb418e1 | 1208 | gp_XYZ aLinkVec[3]; |
1209 | Standard_Boolean isDegeneratedTri = Standard_False; | |
1210 | for (Standard_Integer i = 0; i < 3 && !isDegeneratedTri; ++i) | |
1211 | { | |
1212 | aLinkVec[i] = p[(i + 1) % 3] - p[i]; | |
1213 | isDegeneratedTri = (aLinkVec[i].SquareModulus() < MinimalSqLength3d); | |
1214 | } | |
1215 | ||
1216 | if (isDegeneratedTri) | |
1217 | continue; | |
7fd59977 | 1218 | |
ceb418e1 | 1219 | isAllDegenerated = Standard_False; |
7fd59977 | 1220 | |
1221 | // Check triangle area in 2d | |
ceb418e1 | 1222 | if (Abs((xy[1]-xy[0])^(xy[2]-xy[1])) < MinimalArea2d) |
7fd59977 | 1223 | continue; |
7fd59977 | 1224 | |
1225 | // Check triangle normal | |
ceb418e1 | 1226 | gp_Pnt pDef; |
1227 | Standard_Real aSqDef = -1.; | |
1228 | Standard_Boolean isSkipped = Standard_False; | |
1229 | gp_XYZ normal(aLinkVec[0] ^ aLinkVec[1]); | |
99c008e9 | 1230 | if (normal.SquareModulus () < gp::Resolution()) |
1231 | continue; | |
ceb418e1 | 1232 | |
99c008e9 | 1233 | normal.Normalize(); |
ceb418e1 | 1234 | |
99c008e9 | 1235 | // Check deflection at triangle centroid |
1236 | gp_XY aCenter2d = (xy[0] + xy[1] + xy[2]) / 3.0; | |
1237 | gFace->D0(aCenter2d.X(), aCenter2d.Y(), pDef); | |
1238 | aSqDef = Abs(normal * (pDef.XYZ() - p[0])); | |
1239 | aSqDef *= aSqDef; | |
ceb418e1 | 1240 | |
99c008e9 | 1241 | isSkipped = !checkDeflectionAndInsert(pDef, aCenter2d, theIsFirst, |
1242 | aSqDef, aSqDefFace, aCircles, theNewVertices, aMaxSqDef); | |
74da0216 | 1243 | |
99c008e9 | 1244 | if (isSkipped) |
1245 | break; | |
ceb418e1 | 1246 | |
99c008e9 | 1247 | // Check deflection at triangle links |
ceb418e1 | 1248 | for (Standard_Integer i = 0; i < 3 && !isSkipped; ++i) |
7fd59977 | 1249 | { |
ceb418e1 | 1250 | if (m[i]) // is a boundary |
1251 | continue; | |
1252 | ||
1253 | Standard_Integer j = (i + 1) % 3; | |
7fd59977 | 1254 | // Check if this link was already processed |
ceb418e1 | 1255 | Standard_Integer aFirstVertex, aLastVertex; |
1256 | if (v[i] < v[j]) | |
1257 | { | |
1258 | aFirstVertex = v[i]; | |
1259 | aLastVertex = v[j]; | |
1260 | } | |
1261 | else | |
7fd59977 | 1262 | { |
ceb418e1 | 1263 | aFirstVertex = v[j]; |
1264 | aLastVertex = v[i]; | |
7fd59977 | 1265 | } |
7fd59977 | 1266 | |
ceb418e1 | 1267 | if (aCouples.Add(BRepMesh_OrientedEdge(aFirstVertex, aLastVertex))) |
7fd59977 | 1268 | { |
ceb418e1 | 1269 | // Check deflection on edge 1 |
1270 | gp_XY mi2d = (xy[i] + xy[j]) * 0.5; | |
1271 | gFace->D0(mi2d.X(), mi2d.Y(), pDef); | |
1272 | gp_Lin aLin(p[i], gp_Vec(p[i], p[j])); | |
1273 | aSqDef = aLin.SquareDistance(pDef); | |
1274 | ||
74da0216 | 1275 | isSkipped = !checkDeflectionAndInsert(pDef, mi2d, theIsFirst, |
1276 | aSqDef, aSqDefFace, aCircles, theNewVertices, aMaxSqDef); | |
7fd59977 | 1277 | } |
1278 | } | |
1279 | ||
ceb418e1 | 1280 | if (isSkipped) |
1281 | break; | |
1282 | ||
1283 | //check normal on bsplines | |
1284 | if (theIsFirst && !aBSpline.IsNull()) | |
7fd59977 | 1285 | { |
ceb418e1 | 1286 | gp_Dir N[3] = { gp::DZ(), gp::DZ(), gp::DZ() }; |
1287 | Standard_Integer aSt[3]; | |
1288 | ||
1289 | for (Standard_Integer i = 0; i < 3; ++i) | |
7fd59977 | 1290 | { |
ceb418e1 | 1291 | if (aNorMap.IsBound(v[i])) |
7fd59977 | 1292 | { |
ceb418e1 | 1293 | aSt[i] = aStatMap.Find(v[i]); |
1294 | N[i] = aNorMap.Find(v[i]); | |
1295 | } | |
1296 | else | |
1297 | { | |
1298 | aSt[i] = GeomLib::NormEstim(aBSpline, gp_Pnt2d(xy[i]), Precision::Confusion(), N[i]); | |
1299 | aStatMap.Bind(v[i], aSt[i]); | |
1300 | aNorMap.Bind(v[i], N[i]); | |
7fd59977 | 1301 | } |
7fd59977 | 1302 | } |
1303 | ||
ceb418e1 | 1304 | Standard_Real aAngle[3]; |
1305 | for (Standard_Integer i = 0; i < 3; ++i) | |
1306 | aAngle[i] = N[(i + 1) % 3].Angle(N[i]); | |
7fd59977 | 1307 | |
ceb418e1 | 1308 | if (aSt[0] < 1 && aSt[1] < 1 && aSt[2] < 1) |
1309 | { | |
1310 | if (aAngle[0] > myAngle || aAngle[1] > myAngle || aAngle[2] > myAngle) | |
1311 | { | |
1312 | aMaxSqDef = -1.; | |
7fd59977 | 1313 | break; |
ceb418e1 | 1314 | } |
7fd59977 | 1315 | } |
1316 | } | |
1317 | } | |
d00cba63 | 1318 | |
ceb418e1 | 1319 | if (theIsFirst) |
1320 | continue; | |
d00cba63 | 1321 | |
ceb418e1 | 1322 | if (addVerticesToMesh(theNewVertices, theTrigu)) |
1323 | ++aInsertedNb; | |
7fd59977 | 1324 | } |
7fd59977 | 1325 | |
ceb418e1 | 1326 | return (aMaxSqDef < 0) ? aMaxSqDef : Sqrt(aMaxSqDef); |
7fd59977 | 1327 | } |
1328 | ||
1329 | //======================================================================= | |
ceb418e1 | 1330 | //function : add |
7fd59977 | 1331 | //purpose : |
1332 | //======================================================================= | |
ceb418e1 | 1333 | void BRepMesh_FastDiscretFace::add(const TopoDS_Vertex& theVertex) |
7fd59977 | 1334 | { |
ceb418e1 | 1335 | if (theVertex.Orientation() != TopAbs_INTERNAL) |
1336 | return; | |
7fd59977 | 1337 | |
ceb418e1 | 1338 | try |
1339 | { | |
1340 | OCC_CATCH_SIGNALS | |
7fd59977 | 1341 | |
ceb418e1 | 1342 | gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, myAttribute->Face()); |
a319f03f | 1343 | // check UV values for internal vertices |
1344 | if (myAttribute->ChangeClassifier()->Perform(aPnt2d) != TopAbs_IN) | |
1345 | return; | |
7fd59977 | 1346 | |
848fa7e3 | 1347 | NCollection_Handle<FixedVExplorer> aFixedVExplorer = new FixedVExplorer(theVertex); |
ceb418e1 | 1348 | Standard_Integer aIndex = myAttribute->GetVertexIndex(aFixedVExplorer); |
1349 | gp_XY anUV = BRepMesh_ShapeTool::FindUV(aIndex, aPnt2d, | |
1350 | theVertex, BRep_Tool::Tolerance(theVertex), myAttribute); | |
7fd59977 | 1351 | |
ceb418e1 | 1352 | Standard_Integer aTmpId1, aTmpId2; |
2caff0b3 | 1353 | anUV = myAttribute->Scale(anUV, Standard_True); |
ceb418e1 | 1354 | myAttribute->AddNode(aIndex, anUV, BRepMesh_Fixed, aTmpId1, aTmpId2); |
1355 | } | |
1356 | catch (Standard_Failure) | |
1357 | { | |
1358 | } | |
7fd59977 | 1359 | } |
1360 | ||
1361 | //======================================================================= | |
ceb418e1 | 1362 | //function : insertVertex |
7fd59977 | 1363 | //purpose : |
1364 | //======================================================================= | |
ceb418e1 | 1365 | void BRepMesh_FastDiscretFace::insertVertex( |
848fa7e3 | 1366 | const gp_Pnt& thePnt3d, |
1367 | const gp_XY& theUV, | |
1368 | BRepMesh::ListOfVertex& theVertices) | |
7fd59977 | 1369 | { |
ceb418e1 | 1370 | Standard_Integer aNbLocat = myAttribute->LastPointId(); |
2caff0b3 | 1371 | myAttribute->ChangeSurfacePoints()->Bind(++aNbLocat, thePnt3d); |
7fd59977 | 1372 | |
ceb418e1 | 1373 | gp_XY aPnt2d = myAttribute->Scale(theUV, Standard_True); |
1374 | BRepMesh_Vertex aVertex(aPnt2d, aNbLocat, BRepMesh_Free); | |
1375 | theVertices.Append(aVertex); | |
fcf15f5c | 1376 | } |
1377 | ||
1378 | //======================================================================= | |
1379 | //function : commitSurfaceTriangulation | |
1380 | //purpose : | |
1381 | //======================================================================= | |
1382 | void BRepMesh_FastDiscretFace::commitSurfaceTriangulation() | |
1383 | { | |
1384 | if (myAttribute.IsNull() || !myAttribute->IsValid()) | |
1385 | return; | |
1386 | ||
2caff0b3 | 1387 | const TopoDS_Face& aFace = myAttribute->Face(); |
fcf15f5c | 1388 | BRepMesh_ShapeTool::NullifyFace(aFace); |
1389 | ||
1390 | Handle(BRepMesh_DataStructureOfDelaun)& aStructure = myAttribute->ChangeStructure(); | |
1391 | const BRepMesh::MapOfInteger& aTriangles = aStructure->ElementsOfDomain(); | |
1392 | ||
1393 | if (aTriangles.IsEmpty()) | |
2caff0b3 | 1394 | { |
1395 | myAttribute->SetStatus(BRepMesh_Failure); | |
fcf15f5c | 1396 | return; |
2caff0b3 | 1397 | } |
fcf15f5c | 1398 | |
1399 | BRepMesh::HIMapOfInteger& aVetrexEdgeMap = myAttribute->ChangeVertexEdgeMap(); | |
1400 | ||
1401 | // Store triangles | |
1402 | Standard_Integer aVerticesNb = aVetrexEdgeMap->Extent(); | |
1403 | Standard_Integer aTrianglesNb = aTriangles.Extent(); | |
1404 | Handle(Poly_Triangulation) aNewTriangulation = | |
1405 | new Poly_Triangulation(aVerticesNb, aTrianglesNb, Standard_True); | |
1406 | ||
1407 | Poly_Array1OfTriangle& aPolyTrianges = aNewTriangulation->ChangeTriangles(); | |
1408 | ||
1409 | Standard_Integer aTriangeId = 1; | |
1410 | BRepMesh::MapOfInteger::Iterator aTriIt(aTriangles); | |
1411 | for (; aTriIt.More(); aTriIt.Next()) | |
1412 | { | |
1413 | const BRepMesh_Triangle& aCurElem = aStructure->GetElement(aTriIt.Key()); | |
1414 | ||
1415 | Standard_Integer aNode[3]; | |
1416 | aStructure->ElementNodes(aCurElem, aNode); | |
1417 | ||
1418 | Standard_Integer aNodeId[3]; | |
1419 | for (Standard_Integer i = 0; i < 3; ++i) | |
1420 | aNodeId[i] = aVetrexEdgeMap->FindIndex(aNode[i]); | |
1421 | ||
1422 | aPolyTrianges(aTriangeId++).Set(aNodeId[0], aNodeId[1], aNodeId[2]); | |
1423 | } | |
1424 | ||
1425 | // Store mesh nodes | |
1426 | TColgp_Array1OfPnt& aNodes = aNewTriangulation->ChangeNodes(); | |
1427 | TColgp_Array1OfPnt2d& aNodes2d = aNewTriangulation->ChangeUVNodes(); | |
1428 | ||
1429 | for (Standard_Integer i = 1; i <= aVerticesNb; ++i) | |
1430 | { | |
1431 | Standard_Integer aVertexId = aVetrexEdgeMap->FindKey(i); | |
1432 | const BRepMesh_Vertex& aVertex = aStructure->GetNode(aVertexId); | |
1433 | const gp_Pnt& aPoint = myAttribute->GetPoint(aVertex); | |
1434 | ||
1435 | aNodes(i) = aPoint; | |
1436 | aNodes2d(i) = aVertex.Coord(); | |
1437 | } | |
1438 | ||
1439 | aNewTriangulation->Deflection(myAttribute->GetDefFace()); | |
1440 | BRepMesh_ShapeTool::AddInFace(aFace, aNewTriangulation); | |
1441 | ||
1442 | // Delete unused data | |
2caff0b3 | 1443 | myAttribute->ChangeStructure().Nullify(); |
1444 | myAttribute->ChangeSurfacePoints().Nullify(); | |
1445 | myAttribute->ChangeSurfaceVertices().Nullify(); | |
1446 | ||
1447 | myAttribute->ChangeClassifier().Nullify(); | |
1448 | myAttribute->ChangeLocation2D().Nullify(); | |
1449 | myAttribute->ChangeVertexEdgeMap().Nullify(); | |
fcf15f5c | 1450 | } |