0022337: V3d_View::Print crashes in OCCT 6.5.0
[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),
d51c7072
O
55 myModified(Standard_False),
56 myStatus(0)
7fd59977 57{
58 mymapedge.Clear();
59 myancestors.Clear();
60}
61
62//=======================================================================
63//function : BRepMesh_IncrementalMesh
64//purpose :
65//=======================================================================
66
67BRepMesh_IncrementalMesh::
68BRepMesh_IncrementalMesh(const TopoDS_Shape& S,
69 const Standard_Real D,
70 const Standard_Boolean Rel,
71 const Standard_Real Ang) :
72 myRelative(Rel),
d51c7072
O
73 myModified(Standard_False),
74 myStatus(0)
7fd59977 75{
76 mymapedge.Clear();
77 myancestors.Clear();
78 myDeflection = D;
79 myAngle = Ang;
80 myShape = S;
81
82 //
83 Perform();
84}
85
86//=======================================================================
87//function : ~
88//purpose :
89//=======================================================================
90BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh()
91{
92}
93
94//=======================================================================
95//function : Init
96//purpose :
97//=======================================================================
98void BRepMesh_IncrementalMesh::Init()
99{
100 myModified=Standard_False;
101 mymapedge.Clear();
102 myancestors.Clear();
103}
104
105//=======================================================================
106//function : SetRelative
107//purpose :
108//=======================================================================
109void BRepMesh_IncrementalMesh::SetRelative(const Standard_Boolean theFlag)
110{
111 myRelative=theFlag;
112}
113
114//=======================================================================
115//function : Relative
116//purpose :
117//=======================================================================
118Standard_Boolean BRepMesh_IncrementalMesh::Relative()const
119{
120 return myRelative;
121}
122
123//=======================================================================
124//function : IsModified
125//purpose :
126//=======================================================================
127Standard_Boolean BRepMesh_IncrementalMesh::IsModified() const
128{
129 return myModified;
130}
131
132//=======================================================================
133//function : Perform
134//purpose :
135//=======================================================================
136void BRepMesh_IncrementalMesh::Perform()
137{
138 Bnd_Box aBox;
139 //
140 SetDone();
141 //
142 Init();
143 //
144 BRepBndLib::Add(myShape, aBox);
8e3006e4 145 myBox = aBox;
7fd59977 146 //
8e3006e4
O
147 if (!myMesh.IsNull()) {
148 myMesh.Nullify();
149 }
7fd59977 150 //
8e3006e4
O
151 myMesh = new BRepMesh_FastDiscret(myDeflection,
152 myAngle,
153 aBox,
154 Standard_True,
155 Standard_True,
156 myRelative,
157 Standard_True);
7fd59977 158 //
8e3006e4 159 Update(myShape);
7fd59977 160}
161
8e3006e4 162//=======================================================================
d51c7072 163//function : GetStatus
8e3006e4
O
164//purpose :
165//=======================================================================
d51c7072 166Standard_Integer BRepMesh_IncrementalMesh::GetStatusFlags() const
8e3006e4 167{
d51c7072 168 return myStatus;
8e3006e4 169}
7fd59977 170
171//=======================================================================
172//function : Update(shape)
173//purpose : Builds the incremental mesh of the shape
174//=======================================================================
175void BRepMesh_IncrementalMesh::Update(const TopoDS_Shape& S)
176
177{
178 myModified = Standard_False;
179 TopExp_Explorer ex;
180
7fd59977 181 //AGV 080407: Since version 6.2.0 there would be exception without this check
182 if (myBox.IsVoid())
183 return;
184
2b59653e 185 BRepMesh_FastDiscret::BoxMaxDimension(myBox, mydtotale);
7fd59977 186
187 for (ex.Init(S, TopAbs_EDGE); ex.More(); ex.Next()) {
188 if(BRep_Tool::IsGeometric(TopoDS::Edge(ex.Current()))) {
189 Update(TopoDS::Edge(ex.Current()));
190 }
191 }
192
193 // get list of faces
194 TopTools_ListOfShape LF;
195 BRepLib::ReverseSortFaces(S,LF);
196
197 // make array of faces suitable for processing (excluding faces without surface)
198 std::vector<TopoDS_Face> aFaces;
199 for (TopTools_ListIteratorOfListOfShape it(LF); it.More(); it.Next())
200 {
201 TopoDS_Face F = TopoDS::Face(it.Value());
202
203 TopLoc_Location L1;
204 const Handle(Geom_Surface)& Surf = BRep_Tool::Surface(F, L1);
205 if(Surf.IsNull())
206 continue;
207
208 Update (F);
209 aFaces.push_back (F);
210 }
211
212 // mesh faces in parallel threads using TBB
213#ifdef HAVE_TBB
214 if (Standard::IsReentrant())
215 tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *myMesh.operator->());
216 else
217#endif
218 for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
219 myMesh->Process (*it);
220
221 // maillage des edges non contenues dans les faces :
222 Standard_Real f, l, defedge;
223 Standard_Integer i, nbNodes;
224 TopLoc_Location L;
2b59653e 225 Standard_Real cdef = 1.;
7fd59977 226 ex.Init(S ,TopAbs_EDGE, TopAbs_FACE);
227
228 while (ex.More()) {
229 const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
230
231 if(!BRep_Tool::IsGeometric(E)) {
232 ex.Next();
233 continue;
234 }
235
2b59653e
E
236 if (myRelative)
237 defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection,
238 mydtotale, cdef);
239 else
240 defedge = myDeflection;
7fd59977 241
242 Handle(Poly_Polygon3D) P3D = BRep_Tool::Polygon3D(E, L);
243 Standard_Boolean maill = Standard_False;
244 if (P3D.IsNull()) {
245 maill = Standard_True;
246 }
247 else if (P3D->Deflection() > 1.1*defedge) {
248 maill = Standard_True;
249 }
250 if (maill) {
251 BRepAdaptor_Curve C(E);
252 f = C.FirstParameter();
253 l = C.LastParameter();
254
255 GCPnts_TangentialDeflection TD(C, f, l, myAngle, defedge, 2);
256 nbNodes = TD.NbPoints();
257
258 TColgp_Array1OfPnt Nodes(1, nbNodes);
259 TColStd_Array1OfReal UVNodes(1, nbNodes);
260 for ( i = 1; i <= nbNodes; i++) {
2b59653e
E
261 Nodes(i) = TD.Value(i);
262 UVNodes(i) = TD.Parameter(i);
7fd59977 263 }
264
265 BRep_Builder B;
266 Handle(Poly_Polygon3D) P = new Poly_Polygon3D(Nodes, UVNodes);
267 P->Deflection(myDeflection);
268 B.UpdateEdge(E, P);
269 }
270
271 ex.Next();
272 }
273}
274//=======================================================================
275//function : Update(edge)
276//purpose : Locate a correct discretisation if it exists
277// Set no one otherwise
278//=======================================================================
279void BRepMesh_IncrementalMesh::Update(const TopoDS_Edge& E)
280{
281 TopLoc_Location l;
282 Standard_Integer i = 1;
283 Handle(Poly_Triangulation) T, TNull;
284 Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
285 Standard_Boolean found = Standard_False;
286 Standard_Real defedge;
2b59653e 287 Standard_Real cdef = 1.;
7fd59977 288 BRep_Builder B;
289 Standard_Boolean defined = Standard_False;
290
291 do {
292 BRep_Tool::PolygonOnTriangulation(E, Poly, T, l, i);
293 i++;
294 if (!T.IsNull() && !Poly.IsNull()) {
295 if (!defined) {
2b59653e
E
296 if (myRelative)
297 defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection,
298 mydtotale, cdef);
299 else
300 defedge = myDeflection;
301 mymapedge.Bind(E, defedge);
302 defined = Standard_True;
7fd59977 303 }
304 if ((!myRelative && Poly->Deflection() <= 1.1*defedge) ||
2b59653e
E
305 (myRelative && Poly->Deflection() <= 1.1*defedge))
306 found = Standard_True;
7fd59977 307 else {
2b59653e
E
308 myModified = Standard_True;
309 B.UpdateEdge(E, NullPoly, T, l);
7fd59977 310 }
311 }
312 } while (!Poly.IsNull());
313
314 if (!found) myMap.Add(E);
315}
316
317
318//=======================================================================
319//function : Update(face)
320//purpose : If the face is not correctly triangulated, or if one of its
321// edges is to be discretisated correctly, the triangulation
322// of this face is built.
323//=======================================================================
324void BRepMesh_IncrementalMesh::Update(const TopoDS_Face& F)
325{
326 TopLoc_Location l;
327 Handle(Geom_Surface) SS = BRep_Tool::Surface(F, l);
328 if (SS.IsNull()) return;
329
330 //Standard_Integer i;
331 Standard_Boolean WillBeTriangulated = Standard_False;
332 Handle(Poly_Triangulation) T, TNull;
333 T = BRep_Tool::Triangulation(F, l);
334 Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
335
336 BRep_Builder B;
337 TopExp_Explorer ex;
338
2b59653e 339 Standard_Real defedge, defface, cdef = 1.;
7fd59977 340 Standard_Integer nbEdge = 0;
341 if (myRelative) {
342 defface = 0.;
343
344 for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
345 const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
346 nbEdge++;
347 if (mymapedge.IsBound(edge)) {
2b59653e 348 defedge = mymapedge(edge);
7fd59977 349 }
2b59653e
E
350 else
351 defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(edge, myDeflection, mydtotale, cdef);
7fd59977 352 defface = defface + defedge;
353 }
354 if (nbEdge != 0) defface = defface / nbEdge;
355 else defface = myDeflection;
356 }
357 else
358 defface = myDeflection;
359
360 if (!T.IsNull()) {
361 if ((!myRelative && T->Deflection() <= 1.1*defface) ||
2b59653e
E
362 (myRelative && T->Deflection() <= 1.1*defface)) {
363 for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
364 const TopoDS_Shape& E = ex.Current();
365 Poly = BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(E), T, l);
366 if (Poly.IsNull() || myMap.Contains(E)) {
367 WillBeTriangulated = Standard_True;
368 // cas un peu special. la triangulation est bonne, mais
369 // l'edge n'a pas de representation polygonalisee sur celle-ci.
370 break;
371 }
7fd59977 372 }
373 }
374 else WillBeTriangulated = Standard_True;
375 }
376
377 if (WillBeTriangulated || T.IsNull()) {
378 myModified = Standard_True;
379 if (!T.IsNull()) {
380 for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
2b59653e
E
381 B.UpdateEdge(TopoDS::Edge(ex.Current()), NullPoly, T, l);
382 myMap.Remove(ex.Current());
7fd59977 383 }
384 B.UpdateFace(F, TNull);
385 }
386 myMesh->Add(F);
d51c7072 387 myStatus |= (Standard_Integer)(myMesh->CurrentFaceStatus());
7fd59977 388 if (myMesh->CurrentFaceStatus() == BRepMesh_ReMesh) {
389#ifdef DEB_MESH
390 cout << " face remaillee + finement que prevu."<< endl;
391#endif
392
393 Standard_Integer index;
394 if( myancestors.Extent() < 1 )
395 TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,myancestors);
396
397 TopTools_MapOfShape MShape;
398 MShape.Add(F);
399
400 TopoDS_Iterator ex(F),ex2;
401 for (; ex.More(); ex.Next()) {
402 const TopoDS_Shape& aWire = ex.Value();
403 if (aWire.ShapeType() != TopAbs_WIRE)
404 continue;
405 TopoDS_Iterator exW(aWire);
406 for(; exW.More(); exW.Next()) {
407 const TopoDS_Edge& edge = TopoDS::Edge(exW.Value());
408 index = myancestors.FindIndex(edge);
409 if (index != 0) {
410 const TopTools_ListOfShape& L = myancestors.FindFromKey(edge);
411
412 TopTools_ListIteratorOfListOfShape it(L);
413
414 for (; it.More(); it.Next()) {
415 TopoDS_Face F2 = TopoDS::Face(it.Value());
416 if (!MShape.Contains(F2)) {
417 MShape.Add(F2);
418 T = BRep_Tool::Triangulation(F2, l);
419 if (!T.IsNull()) {
420#ifdef DEB_MESH
421 cout <<"triangulation a refaire" <<endl;
422#endif
423 for (ex2.Initialize(F2); ex2.More(); ex2.Next()) {
424 const TopoDS_Shape& aWire2 = ex2.Value();
425 if (aWire2.ShapeType() != TopAbs_WIRE)
426 continue;
427 TopoDS_Iterator exW2(aWire2);
428 for(; exW2.More(); exW2.Next()) {
429 TopoDS_Edge E2 = TopoDS::Edge(exW2.Value());
430 B.UpdateEdge(E2, NullPoly, T, l);
431 }
432 }
433 B.UpdateFace(F2, TNull);
434 myMesh->Add(F2);
435 }
436 }
437 }
438 }
439 }
440 }
441 }
442 }
443}