Integration of OCCT 6.5.0 from SVN
[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);
143 if (aBox.IsVoid() == Standard_False)
144 {
145 myBox = aBox;
146 //
147 if (!myMesh.IsNull()) {
148 myMesh.Nullify();
149 }
150 //
151 myMesh = new BRepMesh_FastDiscret(myDeflection,
152 myAngle,
153 aBox,
154 Standard_True,
155 Standard_True,
156 myRelative,
157 Standard_True);
158 //
159 Update(myShape);
160 }
161}
162
163
164//=======================================================================
165//function : Update(shape)
166//purpose : Builds the incremental mesh of the shape
167//=======================================================================
168void BRepMesh_IncrementalMesh::Update(const TopoDS_Shape& S)
169
170{
171 myModified = Standard_False;
172 TopExp_Explorer ex;
173
174 Standard_Real TXmin, TYmin, TZmin, TXmax, TYmax, TZmax;
175 Standard_Real dx, dy, dz;
176
177 //AGV 080407: Since version 6.2.0 there would be exception without this check
178 if (myBox.IsVoid())
179 return;
180
181 myBox.Get(TXmin, TYmin, TZmin, TXmax, TYmax, TZmax);
182 dx = TXmax-TXmin;
183 dy = TYmax-TYmin;
184 dz = TZmax-TZmin;
185 mydtotale = dx;
186 if (dy > mydtotale) mydtotale = dy;
187 if (dz > mydtotale) mydtotale = dz;
188
189 for (ex.Init(S, TopAbs_EDGE); ex.More(); ex.Next()) {
190 if(BRep_Tool::IsGeometric(TopoDS::Edge(ex.Current()))) {
191 Update(TopoDS::Edge(ex.Current()));
192 }
193 }
194
195 // get list of faces
196 TopTools_ListOfShape LF;
197 BRepLib::ReverseSortFaces(S,LF);
198
199 // make array of faces suitable for processing (excluding faces without surface)
200 std::vector<TopoDS_Face> aFaces;
201 for (TopTools_ListIteratorOfListOfShape it(LF); it.More(); it.Next())
202 {
203 TopoDS_Face F = TopoDS::Face(it.Value());
204
205 TopLoc_Location L1;
206 const Handle(Geom_Surface)& Surf = BRep_Tool::Surface(F, L1);
207 if(Surf.IsNull())
208 continue;
209
210 Update (F);
211 aFaces.push_back (F);
212 }
213
214 // mesh faces in parallel threads using TBB
215#ifdef HAVE_TBB
216 if (Standard::IsReentrant())
217 tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *myMesh.operator->());
218 else
219#endif
220 for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
221 myMesh->Process (*it);
222
223 // maillage des edges non contenues dans les faces :
224 Standard_Real f, l, defedge;
225 Standard_Integer i, nbNodes;
226 TopLoc_Location L;
227 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
228 ex.Init(S ,TopAbs_EDGE, TopAbs_FACE);
229
230 while (ex.More()) {
231 const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
232
233 if(!BRep_Tool::IsGeometric(E)) {
234 ex.Next();
235 continue;
236 }
237
238 if (myRelative) {
239 Bnd_Box B;
240 BRepBndLib::Add(E, B);
241 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
242 dx = aXmax-aXmin;
243 dy = aYmax-aYmin;
244 dz = aZmax-aZmin;
245 defedge = dx;
246 if (defedge < dy) defedge = dy;
247 if (defedge < dz) defedge = dz;
248 // ajustement par rapport a la taille totale:
249 Standard_Real cdef = mydtotale/(2*defedge);
250 if (cdef < 0.5) cdef = 0.5;
251 if (cdef > 2.) cdef = 2.;
252 defedge = cdef * defedge * myDeflection;
253 }
254 else defedge = myDeflection;
255
256 Handle(Poly_Polygon3D) P3D = BRep_Tool::Polygon3D(E, L);
257 Standard_Boolean maill = Standard_False;
258 if (P3D.IsNull()) {
259 maill = Standard_True;
260 }
261 else if (P3D->Deflection() > 1.1*defedge) {
262 maill = Standard_True;
263 }
264 if (maill) {
265 BRepAdaptor_Curve C(E);
266 f = C.FirstParameter();
267 l = C.LastParameter();
268
269 GCPnts_TangentialDeflection TD(C, f, l, myAngle, defedge, 2);
270 nbNodes = TD.NbPoints();
271
272 TColgp_Array1OfPnt Nodes(1, nbNodes);
273 TColStd_Array1OfReal UVNodes(1, nbNodes);
274 for ( i = 1; i <= nbNodes; i++) {
275 Nodes(i) = TD.Value(i);
276 UVNodes(i) = TD.Parameter(i);
277 }
278
279 BRep_Builder B;
280 Handle(Poly_Polygon3D) P = new Poly_Polygon3D(Nodes, UVNodes);
281 P->Deflection(myDeflection);
282 B.UpdateEdge(E, P);
283 }
284
285 ex.Next();
286 }
287}
288//=======================================================================
289//function : Update(edge)
290//purpose : Locate a correct discretisation if it exists
291// Set no one otherwise
292//=======================================================================
293void BRepMesh_IncrementalMesh::Update(const TopoDS_Edge& E)
294{
295 TopLoc_Location l;
296 Standard_Integer i = 1;
297 Handle(Poly_Triangulation) T, TNull;
298 Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
299 Standard_Boolean found = Standard_False;
300 Standard_Real defedge;
301 BRep_Builder B;
302 Standard_Boolean defined = Standard_False;
303
304 do {
305 BRep_Tool::PolygonOnTriangulation(E, Poly, T, l, i);
306 i++;
307 if (!T.IsNull() && !Poly.IsNull()) {
308 if (!defined) {
309 if (myRelative) {
310 Bnd_Box aBox;
311 BRepBndLib::Add(E, aBox);
312 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dx, dy, dz;
313 aBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
314 dx = aXmax-aXmin;
315 dy = aYmax-aYmin;
316 dz = aZmax-aZmin;
317 defedge = dx;
318 if (defedge < dy) defedge = dy;
319 if (defedge < dz) defedge = dz;
320 // ajustement par rapport a la taille totale:
321 Standard_Real cdef = mydtotale/(2*defedge);
322 if (cdef < 0.5) cdef = 0.5;
323 if (cdef > 2.) cdef = 2.;
324 defedge = cdef * defedge * myDeflection;
325 }
326 else defedge = myDeflection;
327 mymapedge.Bind(E, defedge);
328 defined = Standard_True;
329 }
330 if ((!myRelative && Poly->Deflection() <= 1.1*defedge) ||
331 (myRelative && Poly->Deflection() <= 1.1*defedge))
332 found = Standard_True;
333 else {
334 myModified = Standard_True;
335 B.UpdateEdge(E, NullPoly, T, l);
336 }
337 }
338 } while (!Poly.IsNull());
339
340 if (!found) myMap.Add(E);
341}
342
343
344//=======================================================================
345//function : Update(face)
346//purpose : If the face is not correctly triangulated, or if one of its
347// edges is to be discretisated correctly, the triangulation
348// of this face is built.
349//=======================================================================
350void BRepMesh_IncrementalMesh::Update(const TopoDS_Face& F)
351{
352 TopLoc_Location l;
353 Handle(Geom_Surface) SS = BRep_Tool::Surface(F, l);
354 if (SS.IsNull()) return;
355
356 //Standard_Integer i;
357 Standard_Boolean WillBeTriangulated = Standard_False;
358 Handle(Poly_Triangulation) T, TNull;
359 T = BRep_Tool::Triangulation(F, l);
360 Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
361
362 BRep_Builder B;
363 TopExp_Explorer ex;
364
365 Standard_Real defedge, defface;
366 Standard_Integer nbEdge = 0;
367 if (myRelative) {
368 defface = 0.;
369
370 for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
371 const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
372 nbEdge++;
373 if (mymapedge.IsBound(edge)) {
374 defedge = mymapedge(edge);
375 }
376 else {
377 Bnd_Box aBox;
378 BRepBndLib::Add(edge, aBox);
379 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dx, dy, dz;
380 aBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
381 dx = aXmax-aXmin;
382 dy = aYmax-aYmin;
383 dz = aZmax-aZmin;
384 defedge = dx;
385 if (defedge < dy) defedge = dy;
386 if (defedge < dz) defedge = dz;
387 // ajustement par rapport a la taille totale:
388 Standard_Real cdef = mydtotale/(2*defedge);
389 if (cdef < 0.5) cdef = 0.5;
390 if (cdef > 2.) cdef = 2.;
391 defedge = cdef * defedge * myDeflection;
392 }
393 defface = defface + defedge;
394 }
395 if (nbEdge != 0) defface = defface / nbEdge;
396 else defface = myDeflection;
397 }
398 else
399 defface = myDeflection;
400
401 if (!T.IsNull()) {
402 if ((!myRelative && T->Deflection() <= 1.1*defface) ||
403 (myRelative && T->Deflection() <= 1.1*defface)) {
404 for (ex.Init(F, TopAbs_EDGE);
405 ex.More();
406 ex.Next()) {
407 const TopoDS_Shape& E = ex.Current();
408 Poly = BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(E), T, l);
409 if (Poly.IsNull() || myMap.Contains(E)) {
410 WillBeTriangulated = Standard_True;
411 // cas un peu special. la triangulation est bonne, mais
412 // l'edge n'a pas de representation polygonalisee sur celle-ci.
413 break;
414 }
415 }
416 }
417 else WillBeTriangulated = Standard_True;
418 }
419
420 if (WillBeTriangulated || T.IsNull()) {
421 myModified = Standard_True;
422 if (!T.IsNull()) {
423 for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
424 B.UpdateEdge(TopoDS::Edge(ex.Current()), NullPoly, T, l);
425 myMap.Remove(ex.Current());
426 }
427 B.UpdateFace(F, TNull);
428 }
429 myMesh->Add(F);
430 if (myMesh->CurrentFaceStatus() == BRepMesh_ReMesh) {
431#ifdef DEB_MESH
432 cout << " face remaillee + finement que prevu."<< endl;
433#endif
434
435 Standard_Integer index;
436 if( myancestors.Extent() < 1 )
437 TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,myancestors);
438
439 TopTools_MapOfShape MShape;
440 MShape.Add(F);
441
442 TopoDS_Iterator ex(F),ex2;
443 for (; ex.More(); ex.Next()) {
444 const TopoDS_Shape& aWire = ex.Value();
445 if (aWire.ShapeType() != TopAbs_WIRE)
446 continue;
447 TopoDS_Iterator exW(aWire);
448 for(; exW.More(); exW.Next()) {
449 const TopoDS_Edge& edge = TopoDS::Edge(exW.Value());
450 index = myancestors.FindIndex(edge);
451 if (index != 0) {
452 const TopTools_ListOfShape& L = myancestors.FindFromKey(edge);
453
454 TopTools_ListIteratorOfListOfShape it(L);
455
456 for (; it.More(); it.Next()) {
457 TopoDS_Face F2 = TopoDS::Face(it.Value());
458 if (!MShape.Contains(F2)) {
459 MShape.Add(F2);
460 T = BRep_Tool::Triangulation(F2, l);
461 if (!T.IsNull()) {
462#ifdef DEB_MESH
463 cout <<"triangulation a refaire" <<endl;
464#endif
465 for (ex2.Initialize(F2); ex2.More(); ex2.Next()) {
466 const TopoDS_Shape& aWire2 = ex2.Value();
467 if (aWire2.ShapeType() != TopAbs_WIRE)
468 continue;
469 TopoDS_Iterator exW2(aWire2);
470 for(; exW2.More(); exW2.Next()) {
471 TopoDS_Edge E2 = TopoDS::Edge(exW2.Value());
472 B.UpdateEdge(E2, NullPoly, T, l);
473 }
474 }
475 B.UpdateFace(F2, TNull);
476 myMesh->Add(F2);
477 }
478 }
479 }
480 }
481 }
482 }
483 }
484 }
485}