0027232: Configuration - fix mblen missing building issue on Android
[occt.git] / src / BRepMesh / BRepMesh_FastDiscretFace.cxx
CommitLineData
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 60IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscretFace,Standard_Transient)
61
7fd59977 62static 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 93namespace
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 144BRepMesh_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//=======================================================================
160void 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 170void 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//=======================================================================
302void 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//=======================================================================
319void 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 417Standard_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 437static 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 530void 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//=======================================================================
570void 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//=======================================================================
613void 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//=======================================================================
652void 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//=======================================================================
688void 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//=======================================================================
823void 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//=======================================================================
986void 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//=======================================================================
1067Standard_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 1129Standard_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 1333void 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 1365void 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//=======================================================================
1382void 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}