0025364: BRepMesh is not able to triangulate the shape with fine deflection
[occt.git] / src / BRepMesh / BRepMesh_FastDiscret.cxx
CommitLineData
b311480e 1// Created on: 1996-02-27
2// Created by: Ekaterina SMIRNOVA
3// Copyright (c) 1996-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
fc9b36d6 17#include <BRepMesh_FastDiscret.hxx>
7fd59977 18
fc9b36d6 19#include <BRepMesh_WireChecker.hxx>
7fd59977 20#include <BRepMesh_FastDiscretFace.hxx>
21#include <BRepMesh_FaceAttribute.hxx>
22#include <BRepMesh_DataStructureOfDelaun.hxx>
7fd59977 23#include <BRepMesh_GeomTool.hxx>
24#include <BRepMesh_PairOfPolygon.hxx>
fc9b36d6 25#include <BRepMesh_Classifier.hxx>
ceb418e1 26#include <BRepMesh_EdgeParameterProvider.hxx>
27#include <BRepMesh_IEdgeTool.hxx>
28#include <BRepMesh_EdgeTessellator.hxx>
29#include <BRepMesh_EdgeTessellationExtractor.hxx>
7fd59977 30
31#include <BRepAdaptor_Curve.hxx>
32#include <BRepAdaptor_Surface.hxx>
33#include <BRepAdaptor_HSurface.hxx>
fc9b36d6 34
35#include <Bnd_Box.hxx>
7fd59977 36#include <BRepTools.hxx>
7fd59977 37#include <BRepBndLib.hxx>
fc9b36d6 38#include <BndLib_Add3dCurve.hxx>
fc9b36d6 39#include <Poly_Triangulation.hxx>
40#include <Poly_PolygonOnTriangulation.hxx>
7fd59977 41
fc9b36d6 42#include <Precision.hxx>
7fd59977 43#include <Geom2d_Curve.hxx>
7fd59977 44#include <Geom_Surface.hxx>
fc9b36d6 45#include <Geom_Plane.hxx>
46#include <GeomAbs_SurfaceType.hxx>
7fd59977 47#include <Extrema_LocateExtPC.hxx>
48
7fd59977 49#include <TColStd_Array1OfInteger.hxx>
fc9b36d6 50#include <TColStd_HArray1OfReal.hxx>
fc9b36d6 51#include <TColgp_Array1OfPnt2d.hxx>
7fd59977 52#include <TColGeom2d_SequenceOfCurve.hxx>
fc9b36d6 53#include <SortTools_ShellSortOfReal.hxx>
54#include <TCollection_CompareOfReal.hxx>
55
7fd59977 56#include <TopTools_SequenceOfShape.hxx>
fc9b36d6 57#include <TopTools_ListIteratorOfListOfShape.hxx>
fc9b36d6 58
59#include <TopAbs.hxx>
60#include <TopoDS.hxx>
61#include <TopoDS_Vertex.hxx>
62#include <TopExp.hxx>
63#include <TopExp_Explorer.hxx>
64
65#include <Standard_ErrorHandler.hxx>
66#include <Standard_Failure.hxx>
7fd59977 67#include <NCollection_IncAllocator.hxx>
68
69#include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
70#include <BRep_PointRepresentation.hxx>
7fd59977 71
72#include <vector>
73
7fd59977 74#ifdef HAVE_TBB
0b97567d
K
75 // paralleling using Intel TBB
76 #include <tbb/parallel_for_each.h>
7fd59977 77#endif
78
51c3cc5f
O
79#define UVDEFLECTION 1.e-05
80
fc9b36d6 81IMPLEMENT_STANDARD_HANDLE (BRepMesh_FastDiscret, Standard_Transient)
82IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscret, Standard_Transient)
7fd59977 83
84//=======================================================================
85//function : BRepMesh_FastDiscret
86//purpose :
87//=======================================================================
ceb418e1 88BRepMesh_FastDiscret::BRepMesh_FastDiscret(
89 const Standard_Real theDefle,
90 const Standard_Real theAngl,
91 const Bnd_Box& theBox,
92 const Standard_Boolean theWithShare,
93 const Standard_Boolean theInshape,
94 const Standard_Boolean theRelative,
95 const Standard_Boolean theShapetrigu,
96 const Standard_Boolean isInParallel)
01a6e62b 97: myAngle (theAngl),
0b97567d
K
98 myDeflection (theDefle),
99 myWithShare (theWithShare),
01a6e62b 100 myInParallel (isInParallel),
0b97567d
K
101 myRelative (theRelative),
102 myShapetrigu (theShapetrigu),
848fa7e3 103 myInshape (theInshape),
104 myBoundaryVertices(new BRepMesh::DMapOfVertexInteger),
105 myBoundaryPoints(new BRepMesh::DMapOfIntegerPnt)
7fd59977 106{
ceb418e1 107 if ( myRelative )
fc9b36d6 108 BRepMesh_ShapeTool::BoxMaxDimension(theBox, myDtotale);
7fd59977 109}
110
111//=======================================================================
112//function : BRepMesh_FastDiscret
113//purpose :
114//=======================================================================
fc9b36d6 115BRepMesh_FastDiscret::BRepMesh_FastDiscret(const TopoDS_Shape& theShape,
116 const Standard_Real theDefle,
703a6abd 117 const Standard_Real theAngl,
fc9b36d6 118 const Bnd_Box& theBox,
703a6abd
O
119 const Standard_Boolean theWithShare,
120 const Standard_Boolean theInshape,
121 const Standard_Boolean theRelative,
01a6e62b 122 const Standard_Boolean theShapetrigu,
123 const Standard_Boolean isInParallel)
124: myAngle (theAngl),
0b97567d
K
125 myDeflection (theDefle),
126 myWithShare (theWithShare),
01a6e62b 127 myInParallel (isInParallel),
0b97567d
K
128 myRelative (theRelative),
129 myShapetrigu (theShapetrigu),
848fa7e3 130 myInshape (theInshape),
131 myBoundaryVertices(new BRepMesh::DMapOfVertexInteger),
132 myBoundaryPoints(new BRepMesh::DMapOfIntegerPnt)
7fd59977 133{
ceb418e1 134 if ( myRelative )
fc9b36d6 135 BRepMesh_ShapeTool::BoxMaxDimension(theBox, myDtotale);
7fd59977 136
ceb418e1 137 Perform(theShape);
0981302b
K
138}
139
140//=======================================================================
ceb418e1 141//function : InitSharedFaces
142//purpose :
0981302b 143//=======================================================================
ceb418e1 144void BRepMesh_FastDiscret::InitSharedFaces(const TopoDS_Shape& theShape)
0981302b 145{
ceb418e1 146 TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, mySharedFaces);
0981302b
K
147}
148
0981302b 149//=======================================================================
7fd59977 150//function : Perform(shape)
151//purpose :
152//=======================================================================
703a6abd 153void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape)
7fd59977 154{
ceb418e1 155 InitSharedFaces(theShape);
156
7fd59977 157 std::vector<TopoDS_Face> aFaces;
ceb418e1 158 TopExp_Explorer anExplorer(theShape, TopAbs_FACE);
159 for (; anExplorer.More(); anExplorer.Next())
160 {
161 const TopoDS_Face& aFace = TopoDS::Face(anExplorer.Current());
162 Add(aFace);
163 aFaces.push_back(aFace);
7fd59977 164 }
0b97567d 165
fc9b36d6 166#ifdef HAVE_TBB
ceb418e1 167 if ( myInParallel )
0b97567d 168 {
ceb418e1 169 tbb::parallel_for_each(aFaces.begin(), aFaces.end(), *this);
0b97567d 170 }
7fd59977 171 else
0b97567d 172 {
fc9b36d6 173#endif
ceb418e1 174 std::vector<TopoDS_Face>::const_iterator anIt(aFaces.begin());
175 for (; anIt != aFaces.end(); anIt++)
176 Process(*anIt);
fc9b36d6 177#ifdef HAVE_TBB
0b97567d 178 }
fc9b36d6 179#endif
7fd59977 180}
181
182
183//=======================================================================
184//function : Process
185//purpose :
186//=======================================================================
7fd59977 187void BRepMesh_FastDiscret::Process(const TopoDS_Face& theFace) const
188{
ceb418e1 189 Handle(BRepMesh_FaceAttribute) anAttribute;
190 if (GetFaceAttribute(theFace, anAttribute))
7fd59977 191 {
ceb418e1 192 try
193 {
194 OCC_CATCH_SIGNALS
195
90542800 196 BRepMesh_FastDiscretFace aTool(GetAngle());
fcf15f5c 197 aTool.Perform(anAttribute);
ceb418e1 198 }
199 catch (Standard_Failure)
200 {
201 anAttribute->SetStatus(BRepMesh_Failure);
202 }
7fd59977 203 }
7fd59977 204}
205
2caff0b3 206//=======================================================================
207//function : resetDataStructure
208//purpose :
209//=======================================================================
210void BRepMesh_FastDiscret::resetDataStructure()
211{
212 Handle(NCollection_IncAllocator) aAllocator;
213 if (myAttribute->ChangeStructure().IsNull())
214 aAllocator = new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
215 else
216 aAllocator = myAttribute->ChangeStructure()->Allocator();
217
218 myAttribute->Clear();
219 aAllocator->Reset(Standard_False);
220 Handle(BRepMesh_DataStructureOfDelaun) aStructure =
221 new BRepMesh_DataStructureOfDelaun(aAllocator);
222
223 const Standard_Real aTolU = myAttribute->ToleranceU();
224 const Standard_Real aTolV = myAttribute->ToleranceV();
225 const Standard_Real uCellSize = 14.0 * aTolU;
226 const Standard_Real vCellSize = 14.0 * aTolV;
227
228 aStructure->Data()->SetCellSize ( uCellSize, vCellSize);
229 aStructure->Data()->SetTolerance( aTolU , aTolV );
230
231 myAttribute->ChangeStructure() = aStructure;
232}
233
7fd59977 234//=======================================================================
235//function : Add(face)
236//purpose :
237//=======================================================================
ceb418e1 238Standard_Integer BRepMesh_FastDiscret::Add(const TopoDS_Face& theFace)
7fd59977 239{
7fd59977 240 try
241 {
242 OCC_CATCH_SIGNALS
7fd59977 243
ceb418e1 244 // Initialize face attributes
245 myAttribute.Nullify();
246 GetFaceAttribute(theFace, myAttribute);
247 if (myAttribute.IsNull())
248 {
249 myAttribute = new BRepMesh_FaceAttribute(theFace,
250 myBoundaryVertices, myBoundaryPoints);
7fd59977 251
ceb418e1 252 myAttributes.Bind(theFace, myAttribute);
253 }
7fd59977 254
2caff0b3 255 BRepMesh::HIMapOfInteger& aVertexEdgeMap = myAttribute->ChangeVertexEdgeMap();
256 BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = myAttribute->ChangeInternalEdges();
257
258 resetDataStructure();
7fd59977 259
ceb418e1 260 if (!myWithShare)
261 {
262 myEdges.Clear();
848fa7e3 263 myBoundaryVertices->Clear();
264 myBoundaryPoints->Clear();
ceb418e1 265 }
7fd59977 266
ceb418e1 267 Standard_Real defedge;
268 Standard_Integer nbEdge = 0;
269 Standard_Real savangle = myAngle;
270 Standard_Real cdef;
271 Standard_Real maxdef = 2.* BRepMesh_ShapeTool::MaxFaceTolerance(theFace);
7fd59977 272
ceb418e1 273 Standard_Real defface = 0.;
274 if (!myRelative)
275 defface = Max(myDeflection, maxdef);
7fd59977 276
848fa7e3 277 NCollection_Sequence<EdgePCurve> aPCurves;
278 NCollection_Sequence<TopoDS_Edge> aFaceEdges;
ceb418e1 279
280 const TopoDS_Face& aFace = myAttribute->Face();
281 const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
282 TopExp_Explorer aWireIt(aFace, TopAbs_WIRE);
283 for (; aWireIt.More(); aWireIt.Next())
284 {
285 TopExp_Explorer aEdgeIt(aWireIt.Current(), TopAbs_EDGE);
286 for (; aEdgeIt.More(); aEdgeIt.Next(), ++nbEdge)
287 {
288 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
289 if (!myMapdefle.IsBound(aEdge))
290 {
291 if (myRelative)
292 {
293 if (myEdges.IsBound(aEdge))
294 {
295 const BRepMesh_PairOfPolygon& aPair = myEdges.Find(aEdge);
296 const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First();
297 defedge = aPolygon->Deflection();
298 }
299 else
300 {
301 defedge = BRepMesh_ShapeTool::RelativeEdgeDeflection(
302 aEdge, myDeflection, myDtotale, cdef);
303
304 myAngle = savangle * cdef;
305 }
306
307 defface += defedge;
308 defface = Max(maxdef, defface);
309 }
310 else
311 {
312 defedge = myDeflection;
703a6abd 313 }
fc9b36d6 314
ceb418e1 315 defedge = Max(maxdef, defedge);
316 defedge = Max(UVDEFLECTION, defedge);
317 myMapdefle.Bind(aEdge, defedge);
318 }
319 else
320 {
321 defedge = myMapdefle(aEdge);
322 if ( myRelative )
323 {
324 defface += defedge;
325 defface = Max(maxdef, defface);
7fd59977 326 }
7fd59977 327 }
ceb418e1 328
329 Standard_Real aFirstParam, aLastParam;
330 Handle(Geom2d_Curve) aCurve2d =
331 BRep_Tool::CurveOnSurface(aEdge, aFace, aFirstParam, aLastParam);
332
333 if (aCurve2d.IsNull())
334 continue;
335
336 EdgePCurve aPCurve = { aCurve2d, aFirstParam, aLastParam };
337 aPCurves.Append(aPCurve);
338 aFaceEdges.Append(aEdge);
339
340 add(aEdge, aPCurve, defedge);
341 myAngle = savangle;
7fd59977 342 }
7fd59977 343 }
7fd59977 344
2caff0b3 345 if ( nbEdge == 0 || aVertexEdgeMap->Extent() < 3 )
ceb418e1 346 {
2caff0b3 347 myAttribute->ChangeStructure().Nullify();
ceb418e1 348 myAttribute->SetStatus(BRepMesh_Failure);
349 return myAttribute->GetStatus();
350 }
7fd59977 351
ceb418e1 352 if ( myRelative )
353 {
354 defface = defface / nbEdge;
7fd59977 355 }
ceb418e1 356 else
357 {
358 defface = myDeflection;
359 }
360
361 if ( myWithShare )
362 defface = Max(maxdef, defface);
363
364 TopLoc_Location aLoc;
365 Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLoc);
366
367 if (!myShapetrigu || aTriangulation.IsNull())
7fd59977 368 {
ceb418e1 369 Standard_Real xCur, yCur;
370 Standard_Real maxX, minX, maxY, minY;
371
372 minX = minY = 1.e100;
373 maxX = maxY =-1.e100;
374
375 Standard_Integer ipn = 0;
376 Standard_Integer i1 = 1;
2caff0b3 377 for ( i1 = 1; i1 <= aVertexEdgeMap->Extent(); ++i1 )
7fd59977 378 {
2caff0b3 379 const BRepMesh_Vertex& aVertex =
380 myAttribute->ChangeStructure()->GetNode(aVertexEdgeMap->FindKey(i1));
ceb418e1 381
382 ++ipn;
383
384 xCur = aVertex.Coord().X();
385 yCur = aVertex.Coord().Y();
386
387 minX = Min(xCur, minX);
388 maxX = Max(xCur, maxX);
389 minY = Min(yCur, minY);
390 maxY = Max(yCur, maxY);
7fd59977 391 }
ceb418e1 392
393 Standard_Real myumin = minX;
394 Standard_Real myumax = maxX;
395 Standard_Real myvmin = minY;
396 Standard_Real myvmax = maxY;
397
398 const Standard_Real umin = gFace->FirstUParameter();
399 const Standard_Real umax = gFace->LastUParameter();
400 const Standard_Real vmin = gFace->FirstVParameter();
401 const Standard_Real vmax = gFace->LastVParameter();
402
403 if (myumin < umin || myumax > umax)
7fd59977 404 {
ceb418e1 405 if (gFace->IsUPeriodic())
406 {
407 if ((myumax - myumin) > (umax - umin))
408 myumax = myumin + (umax - umin);
409 }
410 else
411 {
412 if (umin > myumin)
413 myumin = umin;
414
415 if (umax < myumax)
416 myumax = umax;
417 }
7fd59977 418 }
7fd59977 419
ceb418e1 420 if (myvmin < vmin || myvmax > vmax)
7fd59977 421 {
ceb418e1 422 if (gFace->IsVPeriodic())
423 {
424 if ((myvmax - myvmin) > (vmax - vmin))
425 myvmax = myvmin + (vmax - vmin);
426 }
427 else
7fd59977 428 {
ceb418e1 429 if ( vmin > myvmin )
430 myvmin = vmin;
431
432 if (vmax < myvmax)
433 myvmax = vmax;
7fd59977 434 }
435 }
ceb418e1 436
437 GeomAbs_SurfaceType aSurfType = gFace->GetType();
438 // Fast verification of the validity of calculated limits.
439 // If wrong, sure a problem of pcurve.
440 if (aSurfType == GeomAbs_BezierSurface &&
441 (myumin < -0.5 || myumax > 1.5 || myvmin < -0.5 || myvmax > 1.5) )
7fd59977 442 {
2caff0b3 443 myAttribute->ChangeStructure().Nullify();
ceb418e1 444 myAttribute->SetStatus(BRepMesh_Failure);
445 return myAttribute->GetStatus();
7fd59977 446 }
7fd59977 447
ceb418e1 448 //define parameters for correct parametrics
449 Standard_Real deltaX = 1.0;
450 Standard_Real deltaY = 1.0;
451
7fd59977 452 {
848fa7e3 453 BRepMesh::HClassifier& aClassifier = myAttribute->ChangeClassifier();
ceb418e1 454 BRepMesh_WireChecker aDFaceChecker(aFace, Precision::PConfusion(),
2caff0b3 455 aInternalEdges, aVertexEdgeMap, myAttribute->ChangeStructure(),
ceb418e1 456 myumin, myumax, myvmin, myvmax, myInParallel );
457
458 aDFaceChecker.ReCompute(aClassifier);
459 BRepMesh_Status aCheckStatus = aDFaceChecker.Status();
460
461 if (aCheckStatus == BRepMesh_SelfIntersectingWire)
7fd59977 462 {
ceb418e1 463 Standard_Integer nbmaill = 0;
464 Standard_Real eps = Precision::Confusion();
465 while (nbmaill < 5 && aCheckStatus != BRepMesh_ReMesh)
7fd59977 466 {
ceb418e1 467 ++nbmaill;
468
2caff0b3 469 resetDataStructure();
ceb418e1 470 for (Standard_Integer j = 1; j <= aFaceEdges.Length(); ++j)
01a6e62b 471 {
ceb418e1 472 const TopoDS_Edge& anEdge = aFaceEdges(j);
473 if (myEdges.IsBound(anEdge))
474 myEdges.UnBind(anEdge);
475
476 defedge = Max(myMapdefle(anEdge) / 3.0, eps);
477 myMapdefle.Bind(anEdge, defedge);
478
479 add(anEdge, aPCurves(j), defedge);
01a6e62b 480 }
7fd59977 481
ceb418e1 482 aDFaceChecker.ReCompute(aClassifier);
483 if (aDFaceChecker.Status() == BRepMesh_NoError)
484 aCheckStatus = BRepMesh_ReMesh;
01a6e62b 485 }
703a6abd 486 }
ceb418e1 487
488 myAttribute->SetStatus(aCheckStatus);
489 if (!myAttribute->IsValid())
2caff0b3 490 {
491 myAttribute->ChangeStructure().Nullify();
ceb418e1 492 return myAttribute->GetStatus();
2caff0b3 493 }
7fd59977 494 }
7fd59977 495
ceb418e1 496 // try to find the real length:
497 // akm (bug OCC16) : We must calculate these measures in non-singular
498 // parts of face. Let's try to compute average value of three
499 // (umin, (umin+umax)/2, umax), and respectively for v.
500 // vvvvv
501 Standard_Real longu = 0.0, longv = 0.0; //, last , first;
502 gp_Pnt P11, P12, P21, P22, P31, P32;
503
504 Standard_Real du = 0.05 * ( myumax - myumin );
505 Standard_Real dv = 0.05 * ( myvmax - myvmin );
506 Standard_Real dfuave = 0.5 * ( myumin + myumax );
507 Standard_Real dfvave = 0.5 * ( myvmin + myvmax );
508 Standard_Real dfucur, dfvcur;
509
510 // U loop
511 gFace->D0(myumin, myvmin, P11);
512 gFace->D0(myumin, dfvave, P21);
513 gFace->D0(myumin, myvmax, P31);
514 for (i1=1, dfucur=myumin+du; i1 <= 20; i1++, dfucur+=du)
515 {
516 gFace->D0(dfucur, myvmin, P12);
517 gFace->D0(dfucur, dfvave, P22);
518 gFace->D0(dfucur, myvmax, P32);
519 longu += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
520 P11 = P12;
521 P21 = P22;
522 P31 = P32;
523 }
7fd59977 524
ceb418e1 525 // V loop
526 gFace->D0(myumin, myvmin, P11);
527 gFace->D0(dfuave, myvmin, P21);
528 gFace->D0(myumax, myvmin, P31);
529 for (i1=1, dfvcur=myvmin+dv; i1 <= 20; i1++, dfvcur+=dv)
530 {
531 gFace->D0(myumin, dfvcur, P12);
532 gFace->D0(dfuave, dfvcur, P22);
533 gFace->D0(myumax, dfvcur, P32);
534 longv += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
535 P11 = P12;
536 P21 = P22;
537 P31 = P32;
7fd59977 538 }
ceb418e1 539
540 longu /= 3.;
541 longv /= 3.;
542 // akm (bug OCC16) ^^^^^
543
544 if (longu <= 1.e-16 || longv <= 1.e-16)
545 {
546 //yes, it is seen!!
2caff0b3 547 myAttribute->ChangeStructure().Nullify();
ceb418e1 548 myAttribute->SetStatus(BRepMesh_Failure);
549 return myAttribute->GetStatus();
550 }
551
552
553 if (aSurfType == GeomAbs_Torus)
554 {
555 gp_Torus Tor = gFace->Torus();
556 Standard_Real r = Tor.MinorRadius(), R = Tor.MajorRadius();
557 Standard_Real Du, Dv;//, pasu, pasv;
558
559 Dv = Max(1.0e0 - (defface/r),0.0e0) ;
560 Standard_Real oldDv = 2.0 * ACos (Dv);
561 oldDv = Min(oldDv, myAngle);
562 Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
563 Dv = oldDv;
564
565 Standard_Integer nbV = Max((Standard_Integer)((myvmax-myvmin)/Dv), 2);
566 Dv = (myvmax-myvmin)/(nbV+1);
567
568 Standard_Real ru = R + r;
569 if ( ru > 1.e-16 )
570 {
571 Du = Max(1.0e0 - (defface/ru),0.0e0);
572 Du = (2.0 * ACos (Du));
573 Du = Min(Du, myAngle);
574 Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
575
576 if (aa < gp::Resolution())
2caff0b3 577 {
578 myAttribute->ChangeStructure().Nullify();
ceb418e1 579 return myAttribute->GetStatus();
2caff0b3 580 }
ceb418e1 581
582 Du = Du * Min(oldDv, Du) / aa;
583 }
584 else
585 {
586 Du = Dv;
587 }
588
589 Standard_Integer nbU = Max((Standard_Integer)((myumax-myumin)/Du), 2);
590 nbU = Max(nbU, (Standard_Integer)(nbV*(myumax-myumin)*R/((myvmax-myvmin)*r)/5.));
7fd59977 591
ceb418e1 592 Du = (myumax-myumin)/(nbU+1);
593 //-- DeltaX and DeltaY are chosen so that to avoid "jumping"
594 //-- of points on the grid
595 deltaX = Du;
596 deltaY = Dv;
597 }
598 else if (aSurfType == GeomAbs_Cylinder)
599 {
600 gp_Cylinder Cyl = gFace->Cylinder();
601 Standard_Real R = Cyl.Radius();
7fd59977 602
ceb418e1 603 // Calculate parameters for iteration in U direction
604 Standard_Real Du = 1.0 - (defface/R);
605 if (Du < 0.0)
606 Du = 0.0;
7fd59977 607
ceb418e1 608 Du = 2.0 * ACos (Du);
609 if (Du > GetAngle())
610 Du = GetAngle();
7fd59977 611
ceb418e1 612 deltaX = Du / longv;
613 deltaY = 1.;
614 }
7fd59977 615 else
ceb418e1 616 {
617 deltaX = (myumax-myumin)/longu;
618 deltaY = (myvmax-myvmin)/longv;
619 }
7fd59977 620
ceb418e1 621 // Restore face attribute
622 myAttribute->SetDefFace(defface);
623 myAttribute->SetUMax(myumax);
624 myAttribute->SetVMax(myvmax);
625 myAttribute->SetUMin(myumin);
626 myAttribute->SetVMin(myvmin);
627 myAttribute->SetDeltaX(deltaX);
628 myAttribute->SetDeltaY(deltaY);
629 }
7fd59977 630 }
631 catch(Standard_Failure)
632 {
ceb418e1 633 myAttribute->SetStatus(BRepMesh_Failure);
7fd59977 634 }
ceb418e1 635
2caff0b3 636 myAttribute->ChangeMeshNodes() =
637 myAttribute->ChangeStructure()->Data()->Vertices();
7fd59977 638
2caff0b3 639 myAttribute->ChangeStructure().Nullify();
640 return myAttribute->GetStatus();
0d36f7e4
O
641}
642
7fd59977 643//=======================================================================
ceb418e1 644//function : getEdgeAttributes
645//purpose :
7fd59977 646//=======================================================================
ceb418e1 647Standard_Boolean BRepMesh_FastDiscret::getEdgeAttributes(
648 const TopoDS_Edge& theEdge,
649 const BRepMesh_FastDiscret::EdgePCurve& thePCurve,
650 const Standard_Real theDefEdge,
651 BRepMesh_FastDiscret::EdgeAttributes& theAttributes) const
7fd59977 652{
ceb418e1 653 EdgeAttributes& aEAttr = theAttributes;
7fd59977 654
ceb418e1 655 // Get vertices
656 TopExp::Vertices(theEdge, aEAttr.FirstVertex, aEAttr.LastVertex);
657 if (aEAttr.FirstVertex.IsNull() || aEAttr.LastVertex.IsNull())
658 return Standard_False;
7fd59977 659
ceb418e1 660 // Get range on 2d curve
661 const TopoDS_Face& aFace = myAttribute->Face();
662 BRep_Tool::Range(theEdge, aFace, aEAttr.FirstParam, aEAttr.LastParam);
7fd59977 663
ceb418e1 664 // Get end points on 2d curve
665 BRep_Tool::UVPoints(theEdge, aFace, aEAttr.FirstUV, aEAttr.LastUV);
7fd59977 666
ceb418e1 667 aEAttr.IsSameUV =
668 aEAttr.FirstUV.IsEqual(aEAttr.LastUV, Precision::PConfusion());
7fd59977 669
ceb418e1 670 //Control tolerance of vertices
671 const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
672 gp_Pnt pFirst = gFace->Value(aEAttr.FirstUV.X(), aEAttr.FirstUV.Y());
673 gp_Pnt pLast = gFace->Value(aEAttr.LastUV.X(), aEAttr.LastUV.Y());
7fd59977 674
ceb418e1 675 aEAttr.MinDist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(aEAttr.FirstVertex)),
676 pLast .Distance(BRep_Tool::Pnt(aEAttr.LastVertex)));
7fd59977 677
ceb418e1 678 if (aEAttr.MinDist < BRep_Tool::Tolerance(aEAttr.FirstVertex) ||
679 aEAttr.MinDist < BRep_Tool::Tolerance(aEAttr.LastVertex))
7fd59977 680 {
ceb418e1 681 aEAttr.MinDist = theDefEdge;
7fd59977 682 }
683
ceb418e1 684 if (aEAttr.IsSameUV)
7fd59977 685 {
686 // 1. is it really sameUV without being degenerated
687 gp_Pnt2d uvF, uvL;
ceb418e1 688 thePCurve.Curve2d->D0(thePCurve.FirstParam, uvF);
689 thePCurve.Curve2d->D0(thePCurve.LastParam, uvL);
690
691 if (!aEAttr.FirstUV.IsEqual(uvF, Precision::PConfusion()))
692 aEAttr.FirstUV = uvF;
693
694 if (!aEAttr.LastUV.IsEqual(uvL, Precision::PConfusion()))
695 aEAttr.LastUV = uvL;
7fd59977 696 }
697
ceb418e1 698 return Standard_True;
699}
7fd59977 700
ceb418e1 701//=======================================================================
702//function : registerEdgeVertices
703//purpose :
704//=======================================================================
705void BRepMesh_FastDiscret::registerEdgeVertices(
706 BRepMesh_FastDiscret::EdgeAttributes& theAttributes,
707 Standard_Integer& ipf,
708 Standard_Integer& ivf,
709 Standard_Integer& isvf,
710 Standard_Integer& ipl,
711 Standard_Integer& ivl,
712 Standard_Integer& isvl)
713{
714 EdgeAttributes& aEAttr = theAttributes;
715 if (aEAttr.FirstVExtractor.IsNull())
7fd59977 716 {
ceb418e1 717 // Use edge geometry to produce tesselation.
718 aEAttr.FirstVExtractor =
719 new TopoDSVExplorer(aEAttr.FirstVertex, aEAttr.IsSameUV, aEAttr.LastVertex);
7fd59977 720 }
ceb418e1 721
722 if (aEAttr.LastVExtractor.IsNull())
7fd59977 723 {
ceb418e1 724 // Use edge geometry to produce tesselation.
725 aEAttr.LastVExtractor =
726 new TopoDSVExplorer(aEAttr.LastVertex, aEAttr.IsSameUV, aEAttr.FirstVertex);
7fd59977 727 }
b62b93ac 728
ceb418e1 729 gp_XY aTmpUV;
730 // Process first vertex
731 ipf = myAttribute->GetVertexIndex(aEAttr.FirstVExtractor, Standard_True);
732 aTmpUV = BRepMesh_ShapeTool::FindUV(ipf, aEAttr.FirstUV, aEAttr.FirstVertex,
733 aEAttr.MinDist, myAttribute);
b62b93ac 734
ceb418e1 735 myAttribute->AddNode(ipf, aTmpUV, BRepMesh_Frontier, ivf, isvf);
7fd59977 736
737 // Process last vertex
ceb418e1 738 ipl = aEAttr.LastVertex.IsSame(aEAttr.FirstVertex) ? ipf :
739 myAttribute->GetVertexIndex(aEAttr.LastVExtractor, Standard_True);
740 aTmpUV = BRepMesh_ShapeTool::FindUV(ipl, aEAttr.LastUV, aEAttr.LastVertex,
741 aEAttr.MinDist, myAttribute);
742
743 myAttribute->AddNode(ipl, aTmpUV, BRepMesh_Frontier, ivl, isvl);
744}
745
746//=======================================================================
747//function : add
748//purpose :
749//=======================================================================
750void BRepMesh_FastDiscret::add(
751 const TopoDS_Edge& theEdge,
752 const BRepMesh_FastDiscret::EdgePCurve& thePCurve,
753 const Standard_Real theDefEdge)
754{
755 const TopAbs_Orientation orEdge = theEdge.Orientation();
756 if (orEdge == TopAbs_EXTERNAL)
757 return;
758
759 EdgeAttributes aEAttr;
760 if (!getEdgeAttributes(theEdge, thePCurve, theDefEdge, aEAttr))
761 return;
762
763 if (!myEdges.IsBound(theEdge))
7fd59977 764 {
ceb418e1 765 update(theEdge, thePCurve.Curve2d, theDefEdge, aEAttr);
766 return;
7fd59977 767 }
b62b93ac 768
ceb418e1 769 Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl;
770 registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl);
b62b93ac 771
ceb418e1 772 // If this Edge has been already checked and it is not degenerated,
773 // the points of the polygon calculated at the first check are retrieved :
7fd59977 774
ceb418e1 775 // retrieve the polygone:
776 const BRepMesh_PairOfPolygon& aPair = myEdges.Find(theEdge);
777 const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First();
778 const TColStd_Array1OfInteger& aNodes = aPolygon->Nodes();
779 Handle(TColStd_HArray1OfReal) aParams = aPolygon->Parameters();
7fd59977 780
ceb418e1 781 // creation anew:
782 const Standard_Integer aNodesNb = aNodes.Length();
783 TColStd_Array1OfInteger aNewNodes (1, aNodesNb);
784 TColStd_Array1OfReal aNewParams(1, aNodesNb);
7fd59977 785
ceb418e1 786 aNewNodes (1) = isvf;
787 aNewParams(1) = aEAttr.FirstParam;
7fd59977 788
ceb418e1 789 aNewNodes (aNodesNb) = isvl;
790 aNewParams(aNodesNb) = aEAttr.LastParam;
7fd59977 791
ceb418e1 792 const TopoDS_Face& aFace = myAttribute->Face();
793 if (!BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace))
794 {
795 BRepMesh_EdgeParameterProvider aProvider(theEdge, aFace, aParams);
796 for (Standard_Integer i = 2; i < aNodesNb; ++i)
7fd59977 797 {
ceb418e1 798 const Standard_Integer aPointId = aNodes(i);
848fa7e3 799 const gp_Pnt& aPnt = myBoundaryPoints->Find(aPointId);
7fd59977 800
ceb418e1 801 const Standard_Real aParam = aProvider.Parameter(i, aPnt);
802 gp_Pnt2d aUV = thePCurve.Curve2d->Value(aParam);
32d878f5 803
ceb418e1 804 Standard_Integer iv2, isv;
805 myAttribute->AddNode(aPointId, aUV.Coord(), BRepMesh_OnCurve, iv2, isv);
32d878f5 806
ceb418e1 807 aNewNodes (i) = isv;
808 aNewParams(i) = aParam;
ceb418e1 809 }
ceb418e1 810 }
7fd59977 811
ceb418e1 812 Handle(Poly_PolygonOnTriangulation) P1 =
813 new Poly_PolygonOnTriangulation(aNewNodes, aNewParams);
7fd59977 814
ceb418e1 815 storePolygon(theEdge, P1, theDefEdge);
816}
0d36f7e4 817
ceb418e1 818//=======================================================================
819//function : update(edge)
820//purpose :
821//=======================================================================
822void BRepMesh_FastDiscret::update(
823 const TopoDS_Edge& theEdge,
824 const Handle(Geom2d_Curve)& theC2d,
825 const Standard_Real theDefEdge,
826 BRepMesh_FastDiscret::EdgeAttributes& theAttributes)
827{
828 EdgeAttributes& aEAttr = theAttributes;
7fd59977 829
ceb418e1 830 const TopoDS_Face& aFace = myAttribute->Face();
831 Handle(BRepMesh_IEdgeTool) aEdgeTool;
832 // Try to find existing tessellation.
833 for (Standard_Integer i = 1; aEdgeTool.IsNull(); ++i)
834 {
835 TopLoc_Location aLoc;
836 Handle(Poly_Triangulation) aTriangulation;
837 Handle(Poly_PolygonOnTriangulation) aPolygon;
838 BRep_Tool::PolygonOnTriangulation(theEdge, aPolygon, aTriangulation, aLoc, i);
7fd59977 839
ceb418e1 840 if (aPolygon.IsNull())
841 break;
7fd59977 842
ceb418e1 843 if (aTriangulation.IsNull() || !aPolygon->HasParameters())
844 continue;
7fd59977 845
ceb418e1 846 if (aPolygon->Deflection() > 1.1 * theDefEdge)
847 continue;
7fd59977 848
ceb418e1 849 const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
850 const TColStd_Array1OfInteger& aIndices = aPolygon->Nodes();
851 Handle(TColStd_HArray1OfReal) aParams = aPolygon->Parameters();
7fd59977 852
ceb418e1 853 aEAttr.FirstVExtractor = new PolyVExplorer(aEAttr.FirstVertex,
854 aEAttr.IsSameUV, aEAttr.LastVertex, aIndices(1), aNodes, aLoc);
7fd59977 855
ceb418e1 856 aEAttr.LastVExtractor = new PolyVExplorer(aEAttr.LastVertex,
857 aEAttr.IsSameUV, aEAttr.FirstVertex, aIndices(aIndices.Length()), aNodes, aLoc);
7fd59977 858
ceb418e1 859 aEdgeTool = new BRepMesh_EdgeTessellationExtractor(theEdge, theC2d,
860 aFace, aTriangulation, aPolygon, aLoc);
7fd59977 861 }
ceb418e1 862
863 if (aEdgeTool.IsNull())
7fd59977 864 {
ceb418e1 865 aEdgeTool = new BRepMesh_EdgeTessellator(theEdge, myAttribute,
866 mySharedFaces, theDefEdge, myAngle);
7fd59977 867 }
7fd59977 868
ceb418e1 869 Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl;
870 registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl);
7fd59977 871
ceb418e1 872 Handle(Poly_PolygonOnTriangulation) P1, P2;
873 if (BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace))
7fd59977 874 {
ceb418e1 875 const Standard_Integer aNodesNb = 2;
876 TColStd_Array1OfInteger aNewNodes (1, aNodesNb);
877 TColStd_Array1OfInteger aNewNodInStruct(1, aNodesNb);
878 TColStd_Array1OfReal aNewParams (1, aNodesNb);
7fd59977 879
ceb418e1 880 aNewNodInStruct(1) = ipf;
881 aNewNodes (1) = isvf;
882 aNewParams (1) = aEAttr.FirstParam;
7fd59977 883
ceb418e1 884 aNewNodInStruct(aNodesNb) = ipl;
885 aNewNodes (aNodesNb) = isvl;
886 aNewParams (aNodesNb) = aEAttr.LastParam;
7fd59977 887
ceb418e1 888 P1 = new Poly_PolygonOnTriangulation(aNewNodes, aNewParams);
889 P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams);
890 }
891 else
892 {
893 const Standard_Integer aNodesNb = aEdgeTool->NbPoints();
894 TColStd_Array1OfInteger aNewNodes (1, aNodesNb);
895 TColStd_Array1OfInteger aNewNodInStruct(1, aNodesNb);
896 TColStd_Array1OfReal aNewParams (1, aNodesNb);
7fd59977 897
ceb418e1 898 aNewNodInStruct(1) = ipf;
899 aNewNodes (1) = isvf;
900 aNewParams (1) = aEAttr.FirstParam;
7fd59977 901
ceb418e1 902 aNewNodInStruct(aNodesNb) = ipl;
903 aNewNodes (aNodesNb) = isvl;
904 aNewParams (aNodesNb) = aEAttr.LastParam;
7fd59977 905
ceb418e1 906 Standard_Integer aLastPointId = myAttribute->LastPointId();
907 for (Standard_Integer i = 2; i < aNodesNb; ++i)
908 {
909 gp_Pnt aPnt;
910 gp_Pnt2d aUV;
911 Standard_Real aParam;
912 aEdgeTool->Value(i, aParam, aPnt, aUV);
848fa7e3 913 myBoundaryPoints->Bind(++aLastPointId, aPnt);
7fd59977 914
ceb418e1 915 Standard_Integer iv2, isv;
916 myAttribute->AddNode(aLastPointId, aUV.Coord(), BRepMesh_Frontier, iv2, isv);
7fd59977 917
ceb418e1 918 aNewNodInStruct(i) = aLastPointId;
919 aNewNodes (i) = isv;
920 aNewParams (i) = aParam;
ceb418e1 921 }
7fd59977 922
ceb418e1 923 P1 = new Poly_PolygonOnTriangulation(aNewNodes, aNewParams);
924 P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams);
925 }
7fd59977 926
ceb418e1 927 storePolygon(theEdge, P1, theDefEdge);
928 storePolygonSharedData(theEdge, P2, theDefEdge);
7fd59977 929}
930
931//=======================================================================
ceb418e1 932//function : storeInternalPolygon
7fd59977 933//purpose :
934//=======================================================================
ceb418e1 935void BRepMesh_FastDiscret::storePolygon(
936 const TopoDS_Edge& theEdge,
937 Handle(Poly_PolygonOnTriangulation)& thePolygon,
938 const Standard_Real theDeflection)
7fd59977 939{
ceb418e1 940 thePolygon->Deflection(theDeflection);
2caff0b3 941 BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = myAttribute->ChangeInternalEdges();
942 if (aInternalEdges->IsBound(theEdge))
ceb418e1 943 {
2caff0b3 944 BRepMesh_PairOfPolygon& aPair = aInternalEdges->ChangeFind(theEdge);
ceb418e1 945 if (theEdge.Orientation() == TopAbs_REVERSED)
946 aPair.Append(thePolygon);
947 else
948 aPair.Prepend(thePolygon);
7fd59977 949
ceb418e1 950 return;
951 }
7fd59977 952
ceb418e1 953 BRepMesh_PairOfPolygon aPair;
954 aPair.Append(thePolygon);
2caff0b3 955 aInternalEdges->Bind(theEdge, aPair);
7fd59977 956}
957
958//=======================================================================
ceb418e1 959//function : storePolygonSharedData
7fd59977 960//purpose :
961//=======================================================================
ceb418e1 962void BRepMesh_FastDiscret::storePolygonSharedData(
963 const TopoDS_Edge& theEdge,
964 Handle(Poly_PolygonOnTriangulation)& thePolygon,
965 const Standard_Real theDeflection)
7fd59977 966{
ceb418e1 967 thePolygon->Deflection(theDeflection);
968 BRepMesh_PairOfPolygon aPair;
969 aPair.Append(thePolygon);
970 myEdges.Bind(theEdge, aPair);
7fd59977 971}
972
973//=======================================================================
974//function : GetFaceAttribute
975//purpose :
976//=======================================================================
ceb418e1 977Standard_Boolean BRepMesh_FastDiscret::GetFaceAttribute(
978 const TopoDS_Face& theFace,
979 Handle(BRepMesh_FaceAttribute)& theAttribute ) const
7fd59977 980{
ceb418e1 981 if (myAttributes.IsBound(theFace))
7fd59977 982 {
ceb418e1 983 theAttribute = myAttributes(theFace);
7fd59977 984 return Standard_True;
985 }
ceb418e1 986
7fd59977 987 return Standard_False;
988}
989
990//=======================================================================
991//function : RemoveFaceAttribute
992//purpose :
993//=======================================================================
7fd59977 994void BRepMesh_FastDiscret::RemoveFaceAttribute(const TopoDS_Face& theFace)
995{
ceb418e1 996 if (myAttributes.IsBound(theFace))
997 myAttributes.UnBind(theFace);
973c2be1 998}