Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2008-04-11 |
2 | // Created by: Peter KURNEV | |
973c2be1 | 3 | // Copyright (c) 2008-2014 OPEN CASCADE SAS |
b311480e | 4 | // |
973c2be1 | 5 | // This file is part of Open CASCADE Technology software library. |
b311480e | 6 | // |
d5f74e42 | 7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published | |
973c2be1 | 9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |
11 | // distribution for complete text of the license and disclaimer of any warranty. | |
b311480e | 12 | // |
973c2be1 | 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. | |
7fd59977 | 15 | |
42cf5bc1 | 16 | |
17 | #include <Bnd_Box.hxx> | |
18 | #include <BRep_Tool.hxx> | |
19 | #include <BRepGProp.hxx> | |
7fd59977 | 20 | #include <BRepMesh_DiscretFactory.hxx> |
7fd59977 | 21 | #include <BRepMesh_DiscretRoot.hxx> |
42cf5bc1 | 22 | #include <BRepMesh_Edge.hxx> |
23 | #include <BRepMesh_FactoryError.hxx> | |
0b97567d | 24 | #include <BRepMesh_IncrementalMesh.hxx> |
7fd59977 | 25 | #include <DBRep.hxx> |
42cf5bc1 | 26 | #include <Draw.hxx> |
27 | #include <Draw_Interpretor.hxx> | |
28 | #include <DrawTrSurf.hxx> | |
7fd59977 | 29 | #include <gp_Vec.hxx> |
30 | #include <GProp_GProps.hxx> | |
42cf5bc1 | 31 | #include <MeshTest.hxx> |
7fd59977 | 32 | #include <MeshTest_CheckTopology.hxx> |
42cf5bc1 | 33 | #include <NCollection_Map.hxx> |
7fd59977 | 34 | #include <Poly_Polygon2D.hxx> |
42cf5bc1 | 35 | #include <Poly_Polygon3D.hxx> |
36 | #include <Poly_PolygonOnTriangulation.hxx> | |
37 | #include <Poly_Triangulation.hxx> | |
ca0db031 | 38 | #include <Standard.hxx> |
42cf5bc1 | 39 | #include <TColgp_Array1OfPnt2d.hxx> |
40 | #include <TCollection_AsciiString.hxx> | |
2e1a4dae | 41 | #include <TColStd_Array1OfInteger.hxx> |
42cf5bc1 | 42 | #include <TColStd_MapIteratorOfMapOfAsciiString.hxx> |
43 | #include <TColStd_MapOfAsciiString.hxx> | |
44 | #include <TopExp.hxx> | |
45 | #include <TopExp_Explorer.hxx> | |
46 | #include <TopoDS.hxx> | |
2e1a4dae | 47 | #include <TopoDS_Face.hxx> |
42cf5bc1 | 48 | #include <TopTools_IndexedMapOfShape.hxx> |
7bd071ed | 49 | #include <Geom_BSplineCurve.hxx> |
50 | #include <Geom2d_BSplineCurve.hxx> | |
7fd59977 | 51 | |
52 | static Standard_Integer mpnames (Draw_Interpretor& , Standard_Integer , const char** ); | |
53 | static Standard_Integer mpsetdefaultname (Draw_Interpretor& , Standard_Integer , const char** ); | |
54 | static Standard_Integer mpgetdefaultname (Draw_Interpretor& , Standard_Integer , const char** ); | |
55 | static Standard_Integer mpsetfunctionname (Draw_Interpretor& , Standard_Integer , const char** ); | |
56 | static Standard_Integer mpgetfunctionname (Draw_Interpretor& , Standard_Integer , const char** ); | |
57 | static Standard_Integer mperror (Draw_Interpretor& , Standard_Integer , const char** ); | |
58 | static Standard_Integer mpincmesh (Draw_Interpretor& , Standard_Integer , const char** ); | |
0b97567d | 59 | static Standard_Integer mpparallel (Draw_Interpretor& , Standard_Integer , const char** ); |
7fd59977 | 60 | static Standard_Integer triarea (Draw_Interpretor& , Standard_Integer , const char** ); |
e1bcbb52 | 61 | static Standard_Integer tricheck (Draw_Interpretor& , Standard_Integer , const char** ); |
7fd59977 | 62 | |
63 | //======================================================================= | |
64 | //function : PluginCommands | |
65 | //purpose : | |
66 | //======================================================================= | |
67 | void MeshTest::PluginCommands(Draw_Interpretor& theCommands) | |
68 | { | |
69 | static Standard_Boolean done = Standard_False; | |
70 | if (done) { | |
71 | return; | |
72 | } | |
73 | done = Standard_True; | |
74 | // | |
75 | const char* g = "Mesh Commands"; | |
76 | // Commands | |
77 | theCommands.Add("mpnames" , "use mpnames" , __FILE__, mpnames , g); | |
78 | theCommands.Add("mpsetdefaultname" , "use mpsetdefaultname" , __FILE__, mpsetdefaultname , g); | |
79 | theCommands.Add("mpgetdefaultname" , "use mpgetdefaultname" , __FILE__, mpgetdefaultname , g); | |
80 | theCommands.Add("mpsetfunctionname", "use mpsetfunctionname", __FILE__, mpsetfunctionname , g); | |
81 | theCommands.Add("mpgetfunctionname", "use mpgetfunctionname", __FILE__, mpgetfunctionname , g); | |
82 | theCommands.Add("mperror" , "use mperror" , __FILE__, mperror , g); | |
83 | theCommands.Add("mpincmesh" , "use mpincmesh" , __FILE__, mpincmesh , g); | |
0b97567d K |
84 | theCommands.Add("mpparallel" , "mpparallel [toTurnOn] : show / set multi-threading flag for incremental mesh", |
85 | __FILE__, mpparallel, g); | |
7fd59977 | 86 | theCommands.Add("triarea","shape [eps] (computes triangles and surface area)",__FILE__, triarea, g); |
7bd071ed | 87 | theCommands.Add("tricheck", "shape [-small] (checks triangulation of shape);\n" |
88 | "\"-small\"-option allows finding triangles with small area", __FILE__, tricheck, g); | |
7fd59977 | 89 | } |
90 | ||
91 | //======================================================================= | |
92 | //function : mpnames | |
93 | //purpose : | |
94 | //======================================================================= | |
95 | static Standard_Integer mpnames (Draw_Interpretor& , Standard_Integer n, const char** ) | |
96 | { | |
97 | Standard_Integer aNb; | |
98 | TColStd_MapIteratorOfMapOfAsciiString aIt; | |
99 | // | |
100 | if (n!=1) { | |
101 | printf(" use mpnames\n"); | |
102 | return 0; | |
103 | } | |
104 | // | |
105 | const TColStd_MapOfAsciiString& aMN=BRepMesh_DiscretFactory::Get().Names(); | |
106 | aNb=aMN.Extent(); | |
107 | if (!aNb) { | |
108 | printf(" *no names found\n"); | |
109 | return 0; | |
110 | } | |
111 | // | |
112 | printf(" *available names:\n"); | |
113 | aIt.Initialize(aMN); | |
114 | for (; aIt.More(); aIt.Next()) { | |
115 | const TCollection_AsciiString& aName=aIt.Key(); | |
116 | printf(" %s\n", aName.ToCString()); | |
117 | } | |
118 | // | |
119 | return 0; | |
120 | } | |
121 | //======================================================================= | |
122 | //function : mpsetdefaultname | |
123 | //purpose : | |
124 | //======================================================================= | |
125 | static Standard_Integer mpsetdefaultname (Draw_Interpretor& , Standard_Integer n, const char**a ) | |
126 | { | |
127 | TCollection_AsciiString aName; | |
128 | // | |
129 | if (n!=2) { | |
130 | printf(" use mpsetdefaultname name\n"); | |
131 | return 0; | |
132 | } | |
133 | // | |
134 | aName=a[1]; | |
135 | // | |
0b97567d K |
136 | if (BRepMesh_DiscretFactory::Get().SetDefaultName (aName)) |
137 | printf(" *ready\n"); | |
138 | else | |
139 | printf(" *fault\n"); | |
7fd59977 | 140 | // |
141 | return 0; | |
142 | } | |
143 | //======================================================================= | |
144 | //function : mpgetdefaultname | |
145 | //purpose : | |
146 | //======================================================================= | |
147 | static Standard_Integer mpgetdefaultname (Draw_Interpretor& , Standard_Integer n, const char** ) | |
148 | { | |
149 | if (n!=1) { | |
150 | printf(" use mpgetdefaultname\n"); | |
151 | return 0; | |
152 | } | |
153 | // | |
154 | const TCollection_AsciiString& aName=BRepMesh_DiscretFactory::Get().DefaultName(); | |
155 | printf(" *default name: %s\n", aName.ToCString()); | |
156 | // | |
157 | return 0; | |
158 | } | |
159 | //======================================================================= | |
160 | //function : mpsetfunctionname | |
161 | //purpose : | |
162 | //======================================================================= | |
163 | static Standard_Integer mpsetfunctionname (Draw_Interpretor& , Standard_Integer n, const char**a ) | |
164 | { | |
165 | TCollection_AsciiString aName; | |
166 | // | |
167 | if (n!=2) { | |
168 | printf(" use mpsetfunctionname name\n"); | |
169 | return 0; | |
170 | } | |
171 | // | |
172 | aName=a[1]; | |
173 | // | |
0b97567d K |
174 | if (BRepMesh_DiscretFactory::Get().SetFunctionName (aName)) |
175 | printf(" *ready\n"); | |
176 | else | |
177 | printf(" *fault\n"); | |
7fd59977 | 178 | // |
179 | return 0; | |
180 | } | |
181 | //======================================================================= | |
182 | //function : mpgetdefaultname | |
183 | //purpose : | |
184 | //======================================================================= | |
185 | static Standard_Integer mpgetfunctionname (Draw_Interpretor& , Standard_Integer n, const char** ) | |
186 | { | |
187 | if (n!=1) { | |
188 | printf(" use mpgetfunctionname\n"); | |
189 | return 0; | |
190 | } | |
191 | // | |
192 | const TCollection_AsciiString& aName=BRepMesh_DiscretFactory::Get().FunctionName(); | |
193 | printf(" *function name: %s\n", aName.ToCString()); | |
194 | // | |
195 | return 0; | |
196 | } | |
197 | //======================================================================= | |
198 | //function : mperror | |
199 | //purpose : | |
200 | //======================================================================= | |
201 | static Standard_Integer mperror (Draw_Interpretor& , Standard_Integer n, const char** ) | |
202 | { | |
203 | BRepMesh_FactoryError aErr; | |
204 | // | |
205 | if (n!=1) { | |
206 | printf(" use mperror\n"); | |
207 | return 0; | |
208 | } | |
209 | // | |
210 | aErr=BRepMesh_DiscretFactory::Get().ErrorStatus(); | |
211 | printf(" *ErrorStatus: %d\n", (int)aErr); | |
212 | // | |
213 | return 0; | |
214 | } | |
215 | ||
216 | //======================================================================= | |
217 | //function :mpincmesh | |
218 | //purpose : | |
219 | //======================================================================= | |
220 | static Standard_Integer mpincmesh (Draw_Interpretor& , Standard_Integer n, const char** a) | |
221 | { | |
7fd59977 | 222 | Standard_Real aDeflection, aAngle; |
223 | TopoDS_Shape aS; | |
7fd59977 | 224 | // |
225 | if (n<3) { | |
226 | printf(" use mpincmesh s deflection [angle]\n"); | |
227 | return 0; | |
228 | } | |
229 | // | |
230 | aS=DBRep::Get(a[1]); | |
231 | if (aS.IsNull()) { | |
232 | printf(" null shapes is not allowed here\n"); | |
233 | return 0; | |
234 | } | |
235 | // | |
91322f44 | 236 | aDeflection=Draw::Atof(a[2]); |
7fd59977 | 237 | aAngle=0.5; |
238 | if (n>3) { | |
91322f44 | 239 | aAngle=Draw::Atof(a[3]); |
7fd59977 | 240 | } |
241 | // | |
0b97567d K |
242 | Handle(BRepMesh_DiscretRoot) aMeshAlgo = BRepMesh_DiscretFactory::Get().Discret (aS, |
243 | aDeflection, | |
244 | aAngle); | |
7fd59977 | 245 | // |
0b97567d K |
246 | BRepMesh_FactoryError aErr = BRepMesh_DiscretFactory::Get().ErrorStatus(); |
247 | if (aErr != BRepMesh_FE_NOERROR) | |
248 | { | |
7fd59977 | 249 | printf(" *Factory::Get().ErrorStatus()=%d\n", (int)aErr); |
250 | } | |
251 | // | |
0b97567d K |
252 | if (aMeshAlgo.IsNull()) |
253 | { | |
7fd59977 | 254 | printf(" *Can not create the algo\n"); |
255 | return 0; | |
256 | } | |
257 | // | |
0b97567d K |
258 | aMeshAlgo->Perform(); |
259 | if (!aMeshAlgo->IsDone()) | |
260 | { | |
7fd59977 | 261 | printf(" *Not done\n"); |
262 | } | |
263 | // | |
264 | return 0; | |
265 | } | |
266 | ||
267 | //####################################################################### | |
268 | static Standard_Integer triarea (Draw_Interpretor& di, int n, const char ** a) | |
269 | { | |
270 | ||
271 | if (n < 2) return 1; | |
272 | ||
273 | TopoDS_Shape shape = DBRep::Get(a[1]); | |
274 | if (shape.IsNull()) return 1; | |
275 | Standard_Real anEps = -1.; | |
276 | if (n > 2) | |
91322f44 | 277 | anEps = Draw::Atof(a[2]); |
7fd59977 | 278 | |
279 | TopTools_IndexedMapOfShape aMapF; | |
280 | TopExp::MapShapes (shape, TopAbs_FACE, aMapF); | |
281 | ||
282 | // detect if a shape has triangulation | |
283 | Standard_Boolean hasPoly = Standard_False; | |
284 | int i; | |
285 | for (i=1; i <= aMapF.Extent(); i++) { | |
286 | const TopoDS_Face& aFace = TopoDS::Face(aMapF(i)); | |
287 | TopLoc_Location aLoc; | |
288 | Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc); | |
289 | if (!aPoly.IsNull()) { | |
290 | hasPoly = Standard_True; | |
291 | break; | |
292 | } | |
293 | } | |
294 | ||
295 | // compute area by triangles | |
296 | double aTriArea=0; | |
297 | if (hasPoly) { | |
298 | for (i=1; i <= aMapF.Extent(); i++) { | |
299 | const TopoDS_Face& aFace = TopoDS::Face(aMapF(i)); | |
300 | TopLoc_Location aLoc; | |
301 | Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc); | |
302 | if (aPoly.IsNull()) { | |
04232180 | 303 | std::cout << "face "<<i<<" has no triangulation"<<std::endl; |
e1bcbb52 | 304 | continue; |
7fd59977 | 305 | } |
306 | const Poly_Array1OfTriangle& triangles = aPoly->Triangles(); | |
307 | const TColgp_Array1OfPnt& nodes = aPoly->Nodes(); | |
308 | for (int j=triangles.Lower(); j <= triangles.Upper(); j++) { | |
e1bcbb52 O |
309 | const Poly_Triangle& tri = triangles(j); |
310 | int n1, n2, n3; | |
311 | tri.Get (n1, n2, n3); | |
312 | const gp_Pnt& p1 = nodes(n1); | |
313 | const gp_Pnt& p2 = nodes(n2); | |
314 | const gp_Pnt& p3 = nodes(n3); | |
315 | gp_Vec v1(p1, p2); | |
316 | gp_Vec v2(p1, p3); | |
317 | double ar = v1.CrossMagnitude(v2); | |
318 | aTriArea += ar; | |
7fd59977 | 319 | } |
320 | } | |
321 | aTriArea /= 2; | |
322 | } | |
323 | ||
324 | // compute area by geometry | |
325 | GProp_GProps props; | |
326 | if (anEps <= 0.) | |
327 | BRepGProp::SurfaceProperties(shape, props); | |
328 | else | |
329 | BRepGProp::SurfaceProperties(shape, props, anEps); | |
330 | double aGeomArea = props.Mass(); | |
331 | ||
d2c43192 | 332 | di << aTriArea << " " << aGeomArea << "\n"; |
7fd59977 | 333 | return 0; |
334 | } | |
335 | ||
336 | //####################################################################### | |
2e1a4dae | 337 | Standard_Boolean IsEqual(const BRepMesh_Edge& theFirst, const BRepMesh_Edge& theSecond) |
338 | { | |
339 | return theFirst.IsEqual(theSecond); | |
340 | } | |
341 | ||
e1bcbb52 | 342 | static Standard_Integer tricheck (Draw_Interpretor& di, int n, const char ** a) |
7fd59977 | 343 | { |
344 | if (n < 2) return 1; | |
345 | ||
346 | TopoDS_Shape shape = DBRep::Get(a[1]); | |
347 | if (shape.IsNull()) return 1; | |
348 | ||
7bd071ed | 349 | const Standard_Boolean isToFindSmallTriangles = (n >= 3) ? (strcmp(a[2], "-small") == 0) : Standard_False; |
350 | ||
7fd59977 | 351 | TopTools_IndexedMapOfShape aMapF; |
352 | TopExp::MapShapes (shape, TopAbs_FACE, aMapF); | |
7bd071ed | 353 | const Standard_CString name = "."; |
7fd59977 | 354 | |
446e11f3 | 355 | // execute check |
7fd59977 | 356 | MeshTest_CheckTopology aCheck(shape); |
d2c43192 | 357 | aCheck.Perform(di); |
446e11f3 A |
358 | |
359 | // dump info on free links inside the triangulation | |
7fd59977 | 360 | Standard_Integer nbFree = 0; |
361 | Standard_Integer nbFac = aCheck.NbFacesWithFL(), i, k; | |
362 | if (nbFac > 0) { | |
363 | for (k=1; k <= nbFac; k++) { | |
364 | Standard_Integer nbEdge = aCheck.NbFreeLinks(k); | |
365 | Standard_Integer iF = aCheck.GetFaceNumWithFL(k); | |
366 | nbFree += nbEdge; | |
d2c43192 | 367 | di << "free links of face " << iF << "\n"; |
2e1a4dae | 368 | |
369 | const TopoDS_Shape& aShape = aMapF.FindKey(iF); | |
370 | const TopoDS_Face& aFace = TopoDS::Face(aShape); | |
7fd59977 | 371 | TopLoc_Location aLoc; |
372 | Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc); | |
373 | const TColgp_Array1OfPnt& aPoints = aT->Nodes(); | |
7fd59977 | 374 | const gp_Trsf& trsf = aLoc.Transformation(); |
2e1a4dae | 375 | |
7fd59977 | 376 | TColgp_Array1OfPnt pnts(1,2); |
377 | TColgp_Array1OfPnt2d pnts2d(1,2); | |
378 | for (i=1; i <= nbEdge; i++) { | |
e1bcbb52 O |
379 | Standard_Integer n1, n2; |
380 | aCheck.GetFreeLink(k, i, n1, n2); | |
d2c43192 | 381 | di << "{" << n1 << " " << n2 << "} "; |
e1bcbb52 O |
382 | pnts(1) = aPoints(n1).Transformed(trsf); |
383 | pnts(2) = aPoints(n2).Transformed(trsf); | |
384 | Handle(Poly_Polygon3D) poly = new Poly_Polygon3D (pnts); | |
385 | DrawTrSurf::Set (name, poly); | |
386 | DrawTrSurf::Set (name, pnts(1)); | |
387 | DrawTrSurf::Set (name, pnts(2)); | |
b508cbc5 | 388 | if (aT->HasUVNodes()) |
389 | { | |
390 | const TColgp_Array1OfPnt2d& aPoints2d = aT->UVNodes(); | |
391 | pnts2d(1) = aPoints2d(n1); | |
392 | pnts2d(2) = aPoints2d(n2); | |
393 | Handle(Poly_Polygon2D) poly2d = new Poly_Polygon2D (pnts2d); | |
394 | DrawTrSurf::Set (name, poly2d); | |
395 | DrawTrSurf::Set (name, pnts2d(1)); | |
396 | DrawTrSurf::Set (name, pnts2d(2)); | |
397 | } | |
7fd59977 | 398 | } |
d2c43192 | 399 | di << "\n"; |
7fd59977 | 400 | } |
401 | } | |
402 | ||
446e11f3 | 403 | // dump info on cross face errors |
7fd59977 | 404 | Standard_Integer nbErr = aCheck.NbCrossFaceErrors(); |
405 | if (nbErr > 0) { | |
586db386 | 406 | di << "cross face errors: {face1, node1, face2, node2, distance}\n"; |
7fd59977 | 407 | for (i=1; i <= nbErr; i++) { |
408 | Standard_Integer iF1, n1, iF2, n2; | |
409 | Standard_Real aVal; | |
410 | aCheck.GetCrossFaceError(i, iF1, n1, iF2, n2, aVal); | |
d2c43192 | 411 | di << "{" << iF1 << " " << n1 << " " << iF2 << " " << n2 << " " << aVal << "} "; |
7fd59977 | 412 | } |
d2c43192 | 413 | di << "\n"; |
7fd59977 | 414 | } |
415 | ||
446e11f3 | 416 | // dump info on edges |
7fd59977 | 417 | Standard_Integer nbAsync = aCheck.NbAsyncEdges(); |
418 | if (nbAsync > 0) { | |
586db386 | 419 | di << "async edges:\n"; |
7fd59977 | 420 | for (i=1; i <= nbAsync; i++) { |
421 | Standard_Integer ie = aCheck.GetAsyncEdgeNum(i); | |
d2c43192 | 422 | di << ie << " "; |
7fd59977 | 423 | } |
d2c43192 | 424 | di << "\n"; |
7fd59977 | 425 | } |
426 | ||
446e11f3 A |
427 | // dump info on free nodes |
428 | Standard_Integer nbFreeNodes = aCheck.NbFreeNodes(); | |
429 | if (nbFreeNodes > 0) { | |
586db386 | 430 | di << "free nodes (in pairs: face / node): \n"; |
446e11f3 A |
431 | for (i=1; i <= nbFreeNodes; i++) { |
432 | Standard_Integer iface, inode; | |
433 | aCheck.GetFreeNodeNum(i, iface, inode); | |
dc66be92 | 434 | |
435 | const TopoDS_Face& aFace = TopoDS::Face(aMapF.FindKey(iface)); | |
436 | TopLoc_Location aLoc; | |
437 | Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc); | |
438 | const TColgp_Array1OfPnt& aPoints = aT->Nodes(); | |
dc66be92 | 439 | const gp_Trsf& trsf = aLoc.Transformation(); |
440 | DrawTrSurf::Set (name, aPoints(inode).Transformed(trsf)); | |
b508cbc5 | 441 | if (aT->HasUVNodes()) |
442 | { | |
443 | DrawTrSurf::Set (name, aT->UVNodes()(inode)); | |
444 | } | |
dc66be92 | 445 | |
d2c43192 | 446 | di << "{" << iface << " " << inode << "} "; |
446e11f3 | 447 | } |
d2c43192 | 448 | di << "\n"; |
446e11f3 A |
449 | } |
450 | ||
7bd071ed | 451 | const Standard_Integer aNbSmallTriangles = isToFindSmallTriangles? aCheck.NbSmallTriangles() : 0; |
452 | if (aNbSmallTriangles > 0) | |
453 | { | |
454 | di << "triangles with null area (in pairs: face / triangle): \n"; | |
455 | for (i = 1; i <= aNbSmallTriangles; i++) | |
456 | { | |
457 | Standard_Integer aFaceId = 0, aTriID = 0; | |
458 | aCheck.GetSmallTriangle(i, aFaceId, aTriID); | |
459 | ||
460 | const TopoDS_Face& aFace = TopoDS::Face(aMapF.FindKey(aFaceId)); | |
461 | TopLoc_Location aLoc; | |
462 | const gp_Trsf& aTrsf = aLoc.Transformation(); | |
463 | const Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc); | |
464 | const Poly_Triangle &aTri = aT->Triangle(aTriID); | |
465 | Standard_Integer aN1, aN2, aN3; | |
466 | aTri.Get(aN1, aN2, aN3); | |
467 | const TColgp_Array1OfPnt& aPoints = aT->Nodes(); | |
468 | ||
469 | TColgp_Array1OfPnt aPoles(1, 4); | |
470 | aPoles(1) = aPoles(4) = aPoints(aN1).Transformed(aTrsf); | |
471 | aPoles(2) = aPoints(aN2).Transformed(aTrsf); | |
472 | aPoles(3) = aPoints(aN3).Transformed(aTrsf); | |
473 | ||
474 | TColStd_Array1OfInteger aMults(1, 4); | |
475 | aMults(1) = aMults(4) = 2; | |
476 | aMults(2) = aMults(3) = 1; | |
477 | ||
478 | TColStd_Array1OfReal aKnots(1, 4); | |
479 | aKnots(1) = 1.0; | |
480 | aKnots(2) = 2.0; | |
481 | aKnots(3) = 3.0; | |
482 | aKnots(4) = 4.0; | |
483 | ||
484 | Handle(Geom_BSplineCurve) aBS = new Geom_BSplineCurve(aPoles, aKnots, aMults, 1); | |
485 | ||
486 | DrawTrSurf::Set(name, aBS); | |
487 | ||
488 | if (aT->HasUVNodes()) | |
489 | { | |
490 | TColgp_Array1OfPnt2d aPoles2d(1, 4); | |
491 | aPoles2d(1) = aPoles2d(4) = aT->UVNodes()(aN1); | |
492 | aPoles2d(2) = aT->UVNodes()(aN2); | |
493 | aPoles2d(3) = aT->UVNodes()(aN3); | |
494 | ||
495 | Handle(Geom2d_BSplineCurve) aBS2d = new Geom2d_BSplineCurve(aPoles2d, aKnots, aMults, 1); | |
496 | ||
497 | DrawTrSurf::Set(name, aBS2d); | |
498 | } | |
499 | ||
500 | di << "{" << aFaceId << " " << aTriID << "} "; | |
501 | } | |
502 | ||
503 | di << "\n"; | |
504 | } | |
505 | ||
446e11f3 | 506 | // output errors summary to DRAW |
7bd071ed | 507 | if (nbFree > 0 || |
508 | nbErr > 0 || | |
509 | nbAsync > 0 || | |
510 | nbFreeNodes > 0 || | |
511 | (aNbSmallTriangles > 0)) | |
512 | { | |
446e11f3 | 513 | di << "Free_links " << nbFree |
7bd071ed | 514 | << " Cross_face_errors " << nbErr |
515 | << " Async_edges " << nbAsync | |
516 | << " Free_nodes " << nbFreeNodes | |
517 | << " Small triangles " << aNbSmallTriangles << "\n"; | |
518 | } | |
2e1a4dae | 519 | |
520 | Standard_Integer aFaceId = 1; | |
521 | TopExp_Explorer aFaceExp(shape, TopAbs_FACE); | |
522 | for ( ; aFaceExp.More(); aFaceExp.Next(), ++aFaceId) | |
523 | { | |
524 | const TopoDS_Shape& aShape = aFaceExp.Current(); | |
525 | const TopoDS_Face& aFace = TopoDS::Face(aShape); | |
526 | ||
527 | TopLoc_Location aLoc; | |
528 | Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc); | |
529 | ||
530 | // Iterate boundary edges | |
531 | NCollection_Map<BRepMesh_Edge> aBoundaryEdgeMap; | |
532 | TopExp_Explorer anExp(aShape, TopAbs_EDGE); | |
533 | for ( ; anExp.More(); anExp.Next() ) | |
534 | { | |
535 | TopLoc_Location anEdgeLoc; | |
536 | const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current()); | |
537 | Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(anEdge, aT, aLoc); | |
538 | if (aPoly.IsNull()) | |
539 | { | |
540 | continue; | |
541 | } | |
542 | ||
543 | const TColStd_Array1OfInteger& anIndices = aPoly->Nodes(); | |
544 | Standard_Integer aLower = anIndices.Lower(); | |
545 | Standard_Integer anUpper = anIndices.Upper(); | |
546 | ||
547 | Standard_Integer aPrevNode = -1; | |
51740958 | 548 | for (Standard_Integer j = aLower; j <= anUpper; ++j) |
2e1a4dae | 549 | { |
51740958 | 550 | Standard_Integer aNodeIdx = anIndices.Value(j); |
551 | if (j != aLower) | |
2e1a4dae | 552 | { |
553 | BRepMesh_Edge aLink(aPrevNode, aNodeIdx, BRepMesh_Frontier); | |
554 | aBoundaryEdgeMap.Add(aLink); | |
555 | } | |
556 | aPrevNode = aNodeIdx; | |
557 | } | |
558 | } | |
559 | ||
560 | if (aBoundaryEdgeMap.Size() == 0) | |
561 | { | |
562 | break; | |
563 | } | |
564 | ||
565 | const Poly_Array1OfTriangle& aTris = aT->Triangles(); | |
566 | NCollection_Map<BRepMesh_Edge> aFreeEdgeMap; | |
567 | Standard_Integer aTriNum = aTris.Length(); | |
568 | for ( Standard_Integer aTriIndx = 1; aTriIndx <= aTriNum; aTriIndx++ ) | |
569 | { | |
570 | const Poly_Triangle& aTri = aTris(aTriIndx); | |
571 | Standard_Integer aTriNodes[3] = { aTri.Value(1), aTri.Value(2), aTri.Value(3)}; | |
572 | ||
51740958 | 573 | for (Standard_Integer j = 1; j <= 3; ++j) |
2e1a4dae | 574 | { |
51740958 | 575 | Standard_Integer aLastId = aTriNodes[j % 3]; |
576 | Standard_Integer aFirstId = aTriNodes[j - 1]; | |
2e1a4dae | 577 | |
578 | BRepMesh_Edge aLink(aFirstId, aLastId, BRepMesh_Free); | |
579 | if (!aBoundaryEdgeMap.Contains(aLink)) | |
580 | { | |
581 | if (!aFreeEdgeMap.Add(aLink)) | |
582 | { | |
583 | aFreeEdgeMap.Remove(aLink); | |
584 | } | |
585 | } | |
586 | } | |
587 | } | |
588 | ||
589 | if (aFreeEdgeMap.Size() != 0) | |
590 | { | |
591 | di << "Not connected mesh inside face " << aFaceId << "\n"; | |
dc66be92 | 592 | |
593 | const TColgp_Array1OfPnt& aPoints = aT->Nodes(); | |
dc66be92 | 594 | const gp_Trsf& trsf = aLoc.Transformation(); |
595 | ||
596 | TColgp_Array1OfPnt pnts(1,2); | |
597 | TColgp_Array1OfPnt2d pnts2d(1,2); | |
598 | NCollection_Map<BRepMesh_Edge>::Iterator aMapIt(aFreeEdgeMap); | |
599 | for (; aMapIt.More(); aMapIt.Next()) | |
600 | { | |
601 | const BRepMesh_Edge& aLink = aMapIt.Key(); | |
602 | di << "{" << aLink.FirstNode() << " " << aLink.LastNode() << "} "; | |
603 | pnts(1) = aPoints(aLink.FirstNode()).Transformed(trsf); | |
604 | pnts(2) = aPoints(aLink.LastNode()).Transformed(trsf); | |
605 | Handle(Poly_Polygon3D) poly = new Poly_Polygon3D (pnts); | |
606 | DrawTrSurf::Set (name, poly); | |
607 | DrawTrSurf::Set (name, pnts(1)); | |
608 | DrawTrSurf::Set (name, pnts(2)); | |
b508cbc5 | 609 | if (aT->HasUVNodes()) |
610 | { | |
611 | const TColgp_Array1OfPnt2d& aPoints2d = aT->UVNodes(); | |
612 | pnts2d(1) = aPoints2d(aLink.FirstNode()); | |
613 | pnts2d(2) = aPoints2d(aLink.LastNode()); | |
614 | Handle(Poly_Polygon2D) poly2d = new Poly_Polygon2D (pnts2d); | |
615 | DrawTrSurf::Set (name, poly2d); | |
616 | DrawTrSurf::Set (name, pnts2d(1)); | |
617 | DrawTrSurf::Set (name, pnts2d(2)); | |
618 | } | |
dc66be92 | 619 | } |
620 | di << "\n"; | |
2e1a4dae | 621 | } |
622 | } | |
7fd59977 | 623 | return 0; |
624 | } | |
0b97567d K |
625 | |
626 | //======================================================================= | |
627 | //function : mpparallel | |
628 | //purpose : | |
629 | //======================================================================= | |
35e08fe8 | 630 | static int mpparallel (Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv) |
0b97567d K |
631 | { |
632 | if (argc == 2) | |
633 | { | |
91322f44 | 634 | Standard_Boolean isParallelOn = Draw::Atoi (argv[1]) == 1; |
0b97567d K |
635 | BRepMesh_IncrementalMesh::SetParallelDefault (isParallelOn); |
636 | } | |
637 | std::cout << "Incremental Mesh, multi-threading " | |
638 | << (BRepMesh_IncrementalMesh::IsParallelDefault() ? "ON\n" : "OFF\n"); | |
639 | return 0; | |
640 | } |