Update for OCCT 6.5.1
[occt.git] / src / BRepMesh / BRepMesh_IncrementalMesh.cxx
CommitLineData
7fd59977 1// File: BRepMesh_IncrementalMesh.cxx
2// Created: Tue Jun 20 10:34:51 1995
3// Author: Stagiaire Alain JOURDAIN
4// <ajo@phobox>
5
6
7#include <BRepMesh_IncrementalMesh.ixx>
8
9#include <BRepMesh.hxx>
10#include <BRepMesh_Edge.hxx>
11#include <BRepMesh_Triangle.hxx>
12#include <BRepMesh_FastDiscretFace.hxx>
13
14#include <Bnd_Box.hxx>
15#include <BRep_Builder.hxx>
16#include <BRep_Tool.hxx>
17#include <BRepLib.hxx>
18#include <BRepBndLib.hxx>
19#include <BRepAdaptor_Curve.hxx>
20#include <GCPnts_TangentialDeflection.hxx>
21#include <Precision.hxx>
22#include <TopExp.hxx>
23#include <TopExp_Explorer.hxx>
24#include <TopAbs.hxx>
25#include <TopTools_ListIteratorOfListOfShape.hxx>
26#include <TColgp_Array1OfPnt.hxx>
27#include <TColStd_Array1OfReal.hxx>
28#include <TopoDS_Shape.hxx>
29#include <TopoDS_Face.hxx>
30#include <TopoDS_Edge.hxx>
31#include <TopoDS.hxx>
32#include <TopTools_HArray1OfShape.hxx>
33#include <Poly_Triangulation.hxx>
34#include <Poly_Polygon3D.hxx>
35#include <Poly_PolygonOnTriangulation.hxx>
36
37#include <vector>
38
39// NOTE: to be replaced by more correct check
40// #if defined(WNT) || defined(LIN)
41// #define HAVE_TBB 1
42// #endif
43
44// paralleling with Intel TBB
45#ifdef HAVE_TBB
46#include <tbb/parallel_for_each.h>
47#endif
48
49//=======================================================================
50//function : BRepMesh_IncrementalMesh
51//purpose :
52//=======================================================================
53BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh()
54: myRelative(Standard_False),
55 myModified(Standard_False)
56{
57 mymapedge.Clear();
58 myancestors.Clear();
59}
60
61//=======================================================================
62//function : BRepMesh_IncrementalMesh
63//purpose :
64//=======================================================================
65
66BRepMesh_IncrementalMesh::
67BRepMesh_IncrementalMesh(const TopoDS_Shape& S,
68 const Standard_Real D,
69 const Standard_Boolean Rel,
70 const Standard_Real Ang) :
71 myRelative(Rel),
72 myModified(Standard_False)
73{
74 mymapedge.Clear();
75 myancestors.Clear();
76 myDeflection = D;
77 myAngle = Ang;
78 myShape = S;
79
80 //
81 Perform();
82}
83
84//=======================================================================
85//function : ~
86//purpose :
87//=======================================================================
88BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh()
89{
90}
91
92//=======================================================================
93//function : Init
94//purpose :
95//=======================================================================
96void BRepMesh_IncrementalMesh::Init()
97{
98 myModified=Standard_False;
99 mymapedge.Clear();
100 myancestors.Clear();
101}
102
103//=======================================================================
104//function : SetRelative
105//purpose :
106//=======================================================================
107void BRepMesh_IncrementalMesh::SetRelative(const Standard_Boolean theFlag)
108{
109 myRelative=theFlag;
110}
111
112//=======================================================================
113//function : Relative
114//purpose :
115//=======================================================================
116Standard_Boolean BRepMesh_IncrementalMesh::Relative()const
117{
118 return myRelative;
119}
120
121//=======================================================================
122//function : IsModified
123//purpose :
124//=======================================================================
125Standard_Boolean BRepMesh_IncrementalMesh::IsModified() const
126{
127 return myModified;
128}
129
130//=======================================================================
131//function : Perform
132//purpose :
133//=======================================================================
134void BRepMesh_IncrementalMesh::Perform()
135{
136 Bnd_Box aBox;
137 //
138 SetDone();
139 //
140 Init();
141 //
142 BRepBndLib::Add(myShape, aBox);
8e3006e4 143 myBox = aBox;
7fd59977 144 //
8e3006e4
O
145 if (!myMesh.IsNull()) {
146 myMesh.Nullify();
147 }
7fd59977 148 //
8e3006e4
O
149 myMesh = new BRepMesh_FastDiscret(myDeflection,
150 myAngle,
151 aBox,
152 Standard_True,
153 Standard_True,
154 myRelative,
155 Standard_True);
7fd59977 156 //
8e3006e4
O
157 Update(myShape);
158#ifdef DEB
159 EchoStatus();
160#endif
7fd59977 161}
162
8e3006e4
O
163//=======================================================================
164//function : EchoStatus
165//purpose :
166//=======================================================================
167void BRepMesh_IncrementalMesh::EchoStatus() const
168{
169 cout << "BRepMesh_FastDiscret::Meshing status: ";
170 switch(myMesh->CurrentFaceStatus())
171 {
172 case BRepMesh_NoError:
173 cout << "NoError" << endl;
174 break;
175 case BRepMesh_OpenWire:
176 cout << "OpenWire" << endl;
177 break;
178 case BRepMesh_SelfIntersectingWire:
179 cout << "SelfIntersectingWire" << endl;
180 break;
181 case BRepMesh_Failure:
182 cout << "Failure" << endl;
183 break;
184 case BRepMesh_ReMesh:
185 cout << "ReMesh" << endl;
186 break;
187 default: cout << "UnsupportedStatus" << endl;
188 }
189}
7fd59977 190
191//=======================================================================
192//function : Update(shape)
193//purpose : Builds the incremental mesh of the shape
194//=======================================================================
195void BRepMesh_IncrementalMesh::Update(const TopoDS_Shape& S)
196
197{
198 myModified = Standard_False;
199 TopExp_Explorer ex;
200
201 Standard_Real TXmin, TYmin, TZmin, TXmax, TYmax, TZmax;
202 Standard_Real dx, dy, dz;
203
204 //AGV 080407: Since version 6.2.0 there would be exception without this check
205 if (myBox.IsVoid())
206 return;
207
208 myBox.Get(TXmin, TYmin, TZmin, TXmax, TYmax, TZmax);
209 dx = TXmax-TXmin;
210 dy = TYmax-TYmin;
211 dz = TZmax-TZmin;
212 mydtotale = dx;
213 if (dy > mydtotale) mydtotale = dy;
214 if (dz > mydtotale) mydtotale = dz;
215
216 for (ex.Init(S, TopAbs_EDGE); ex.More(); ex.Next()) {
217 if(BRep_Tool::IsGeometric(TopoDS::Edge(ex.Current()))) {
218 Update(TopoDS::Edge(ex.Current()));
219 }
220 }
221
222 // get list of faces
223 TopTools_ListOfShape LF;
224 BRepLib::ReverseSortFaces(S,LF);
225
226 // make array of faces suitable for processing (excluding faces without surface)
227 std::vector<TopoDS_Face> aFaces;
228 for (TopTools_ListIteratorOfListOfShape it(LF); it.More(); it.Next())
229 {
230 TopoDS_Face F = TopoDS::Face(it.Value());
231
232 TopLoc_Location L1;
233 const Handle(Geom_Surface)& Surf = BRep_Tool::Surface(F, L1);
234 if(Surf.IsNull())
235 continue;
236
237 Update (F);
238 aFaces.push_back (F);
239 }
240
241 // mesh faces in parallel threads using TBB
242#ifdef HAVE_TBB
243 if (Standard::IsReentrant())
244 tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *myMesh.operator->());
245 else
246#endif
247 for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
248 myMesh->Process (*it);
249
250 // maillage des edges non contenues dans les faces :
251 Standard_Real f, l, defedge;
252 Standard_Integer i, nbNodes;
253 TopLoc_Location L;
254 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
255 ex.Init(S ,TopAbs_EDGE, TopAbs_FACE);
256
257 while (ex.More()) {
258 const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
259
260 if(!BRep_Tool::IsGeometric(E)) {
261 ex.Next();
262 continue;
263 }
264
265 if (myRelative) {
266 Bnd_Box B;
267 BRepBndLib::Add(E, B);
268 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
269 dx = aXmax-aXmin;
270 dy = aYmax-aYmin;
271 dz = aZmax-aZmin;
272 defedge = dx;
273 if (defedge < dy) defedge = dy;
274 if (defedge < dz) defedge = dz;
275 // ajustement par rapport a la taille totale:
276 Standard_Real cdef = mydtotale/(2*defedge);
277 if (cdef < 0.5) cdef = 0.5;
278 if (cdef > 2.) cdef = 2.;
279 defedge = cdef * defedge * myDeflection;
280 }
281 else defedge = myDeflection;
282
283 Handle(Poly_Polygon3D) P3D = BRep_Tool::Polygon3D(E, L);
284 Standard_Boolean maill = Standard_False;
285 if (P3D.IsNull()) {
286 maill = Standard_True;
287 }
288 else if (P3D->Deflection() > 1.1*defedge) {
289 maill = Standard_True;
290 }
291 if (maill) {
292 BRepAdaptor_Curve C(E);
293 f = C.FirstParameter();
294 l = C.LastParameter();
295
296 GCPnts_TangentialDeflection TD(C, f, l, myAngle, defedge, 2);
297 nbNodes = TD.NbPoints();
298
299 TColgp_Array1OfPnt Nodes(1, nbNodes);
300 TColStd_Array1OfReal UVNodes(1, nbNodes);
301 for ( i = 1; i <= nbNodes; i++) {
302 Nodes(i) = TD.Value(i);
303 UVNodes(i) = TD.Parameter(i);
304 }
305
306 BRep_Builder B;
307 Handle(Poly_Polygon3D) P = new Poly_Polygon3D(Nodes, UVNodes);
308 P->Deflection(myDeflection);
309 B.UpdateEdge(E, P);
310 }
311
312 ex.Next();
313 }
314}
315//=======================================================================
316//function : Update(edge)
317//purpose : Locate a correct discretisation if it exists
318// Set no one otherwise
319//=======================================================================
320void BRepMesh_IncrementalMesh::Update(const TopoDS_Edge& E)
321{
322 TopLoc_Location l;
323 Standard_Integer i = 1;
324 Handle(Poly_Triangulation) T, TNull;
325 Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
326 Standard_Boolean found = Standard_False;
327 Standard_Real defedge;
328 BRep_Builder B;
329 Standard_Boolean defined = Standard_False;
330
331 do {
332 BRep_Tool::PolygonOnTriangulation(E, Poly, T, l, i);
333 i++;
334 if (!T.IsNull() && !Poly.IsNull()) {
335 if (!defined) {
336 if (myRelative) {
337 Bnd_Box aBox;
338 BRepBndLib::Add(E, aBox);
339 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dx, dy, dz;
340 aBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
341 dx = aXmax-aXmin;
342 dy = aYmax-aYmin;
343 dz = aZmax-aZmin;
344 defedge = dx;
345 if (defedge < dy) defedge = dy;
346 if (defedge < dz) defedge = dz;
347 // ajustement par rapport a la taille totale:
348 Standard_Real cdef = mydtotale/(2*defedge);
349 if (cdef < 0.5) cdef = 0.5;
350 if (cdef > 2.) cdef = 2.;
351 defedge = cdef * defedge * myDeflection;
352 }
353 else defedge = myDeflection;
354 mymapedge.Bind(E, defedge);
355 defined = Standard_True;
356 }
357 if ((!myRelative && Poly->Deflection() <= 1.1*defedge) ||
358 (myRelative && Poly->Deflection() <= 1.1*defedge))
359 found = Standard_True;
360 else {
361 myModified = Standard_True;
362 B.UpdateEdge(E, NullPoly, T, l);
363 }
364 }
365 } while (!Poly.IsNull());
366
367 if (!found) myMap.Add(E);
368}
369
370
371//=======================================================================
372//function : Update(face)
373//purpose : If the face is not correctly triangulated, or if one of its
374// edges is to be discretisated correctly, the triangulation
375// of this face is built.
376//=======================================================================
377void BRepMesh_IncrementalMesh::Update(const TopoDS_Face& F)
378{
379 TopLoc_Location l;
380 Handle(Geom_Surface) SS = BRep_Tool::Surface(F, l);
381 if (SS.IsNull()) return;
382
383 //Standard_Integer i;
384 Standard_Boolean WillBeTriangulated = Standard_False;
385 Handle(Poly_Triangulation) T, TNull;
386 T = BRep_Tool::Triangulation(F, l);
387 Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
388
389 BRep_Builder B;
390 TopExp_Explorer ex;
391
392 Standard_Real defedge, defface;
393 Standard_Integer nbEdge = 0;
394 if (myRelative) {
395 defface = 0.;
396
397 for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
398 const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
399 nbEdge++;
400 if (mymapedge.IsBound(edge)) {
401 defedge = mymapedge(edge);
402 }
403 else {
404 Bnd_Box aBox;
405 BRepBndLib::Add(edge, aBox);
406 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dx, dy, dz;
407 aBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
408 dx = aXmax-aXmin;
409 dy = aYmax-aYmin;
410 dz = aZmax-aZmin;
411 defedge = dx;
412 if (defedge < dy) defedge = dy;
413 if (defedge < dz) defedge = dz;
414 // ajustement par rapport a la taille totale:
415 Standard_Real cdef = mydtotale/(2*defedge);
416 if (cdef < 0.5) cdef = 0.5;
417 if (cdef > 2.) cdef = 2.;
418 defedge = cdef * defedge * myDeflection;
419 }
420 defface = defface + defedge;
421 }
422 if (nbEdge != 0) defface = defface / nbEdge;
423 else defface = myDeflection;
424 }
425 else
426 defface = myDeflection;
427
428 if (!T.IsNull()) {
429 if ((!myRelative && T->Deflection() <= 1.1*defface) ||
430 (myRelative && T->Deflection() <= 1.1*defface)) {
431 for (ex.Init(F, TopAbs_EDGE);
432 ex.More();
433 ex.Next()) {
434 const TopoDS_Shape& E = ex.Current();
435 Poly = BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(E), T, l);
436 if (Poly.IsNull() || myMap.Contains(E)) {
437 WillBeTriangulated = Standard_True;
438 // cas un peu special. la triangulation est bonne, mais
439 // l'edge n'a pas de representation polygonalisee sur celle-ci.
440 break;
441 }
442 }
443 }
444 else WillBeTriangulated = Standard_True;
445 }
446
447 if (WillBeTriangulated || T.IsNull()) {
448 myModified = Standard_True;
449 if (!T.IsNull()) {
450 for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
451 B.UpdateEdge(TopoDS::Edge(ex.Current()), NullPoly, T, l);
452 myMap.Remove(ex.Current());
453 }
454 B.UpdateFace(F, TNull);
455 }
456 myMesh->Add(F);
457 if (myMesh->CurrentFaceStatus() == BRepMesh_ReMesh) {
458#ifdef DEB_MESH
459 cout << " face remaillee + finement que prevu."<< endl;
460#endif
461
462 Standard_Integer index;
463 if( myancestors.Extent() < 1 )
464 TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,myancestors);
465
466 TopTools_MapOfShape MShape;
467 MShape.Add(F);
468
469 TopoDS_Iterator ex(F),ex2;
470 for (; ex.More(); ex.Next()) {
471 const TopoDS_Shape& aWire = ex.Value();
472 if (aWire.ShapeType() != TopAbs_WIRE)
473 continue;
474 TopoDS_Iterator exW(aWire);
475 for(; exW.More(); exW.Next()) {
476 const TopoDS_Edge& edge = TopoDS::Edge(exW.Value());
477 index = myancestors.FindIndex(edge);
478 if (index != 0) {
479 const TopTools_ListOfShape& L = myancestors.FindFromKey(edge);
480
481 TopTools_ListIteratorOfListOfShape it(L);
482
483 for (; it.More(); it.Next()) {
484 TopoDS_Face F2 = TopoDS::Face(it.Value());
485 if (!MShape.Contains(F2)) {
486 MShape.Add(F2);
487 T = BRep_Tool::Triangulation(F2, l);
488 if (!T.IsNull()) {
489#ifdef DEB_MESH
490 cout <<"triangulation a refaire" <<endl;
491#endif
492 for (ex2.Initialize(F2); ex2.More(); ex2.Next()) {
493 const TopoDS_Shape& aWire2 = ex2.Value();
494 if (aWire2.ShapeType() != TopAbs_WIRE)
495 continue;
496 TopoDS_Iterator exW2(aWire2);
497 for(; exW2.More(); exW2.Next()) {
498 TopoDS_Edge E2 = TopoDS::Edge(exW2.Value());
499 B.UpdateEdge(E2, NullPoly, T, l);
500 }
501 }
502 B.UpdateFace(F2, TNull);
503 myMesh->Add(F2);
504 }
505 }
506 }
507 }
508 }
509 }
510 }
511 }
512}