1 // Created on: 2008-04-11
2 // Created by: Peter KURNEV
3 // Copyright (c) 2008-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16
17 #include <Bnd_Box.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepGProp.hxx>
20 #include <BRepMesh_DiscretFactory.hxx>
21 #include <BRepMesh_DiscretRoot.hxx>
22 #include <BRepMesh_Edge.hxx>
23 #include <BRepMesh_FactoryError.hxx>
24 #include <BRepMesh_IncrementalMesh.hxx>
25 #include <DBRep.hxx>
26 #include <Draw.hxx>
27 #include <Draw_Interpretor.hxx>
28 #include <DrawTrSurf.hxx>
29 #include <gp_Vec.hxx>
30 #include <GProp_GProps.hxx>
31 #include <MeshTest.hxx>
32 #include <MeshTest_CheckTopology.hxx>
33 #include <NCollection_Map.hxx>
34 #include <Poly_Polygon2D.hxx>
35 #include <Poly_Polygon3D.hxx>
36 #include <Poly_PolygonOnTriangulation.hxx>
37 #include <Poly_Triangulation.hxx>
38 #include <Standard.hxx>
39 #include <TColgp_Array1OfPnt2d.hxx>
40 #include <TCollection_AsciiString.hxx>
41 #include <TColStd_Array1OfInteger.hxx>
42 #include <TColStd_MapIteratorOfMapOfAsciiString.hxx>
43 #include <TColStd_MapOfAsciiString.hxx>
44 #include <TopExp.hxx>
45 #include <TopExp_Explorer.hxx>
46 #include <TopoDS.hxx>
47 #include <TopoDS_Face.hxx>
48 #include <TopTools_IndexedMapOfShape.hxx>
49 #include <Geom_BSplineCurve.hxx>
50 #include <Geom2d_BSplineCurve.hxx>
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** );
59 static Standard_Integer mpparallel (Draw_Interpretor& , Standard_Integer , const char** );
60 static Standard_Integer triarea (Draw_Interpretor& , Standard_Integer , const char** );
61 static Standard_Integer tricheck (Draw_Interpretor& , Standard_Integer , const char** );
62
63 //=======================================================================
64 //function : PluginCommands
65 //purpose :
66 //=======================================================================
PluginCommands(Draw_Interpretor & theCommands)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);
84 theCommands.Add("mpparallel" , "mpparallel [toTurnOn] : show / set multi-threading flag for incremental mesh",
85 __FILE__, mpparallel, g);
86 theCommands.Add("triarea","shape [eps] (computes triangles and surface area)",__FILE__, triarea, g);
87 theCommands.Add("tricheck", "shape [-small] (checks triangulation of shape);\n"
88 "\"-small\"-option allows finding triangles with small area", __FILE__, tricheck, g);
89 }
90
91 //=======================================================================
92 //function : mpnames
93 //purpose :
94 //=======================================================================
mpnames(Draw_Interpretor &,Standard_Integer n,const char **)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 //=======================================================================
mpsetdefaultname(Draw_Interpretor &,Standard_Integer n,const char ** a)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 //
136 if (BRepMesh_DiscretFactory::Get().SetDefaultName (aName))
137 printf(" *ready\n");
138 else
139 printf(" *fault\n");
140 //
141 return 0;
142 }
143 //=======================================================================
144 //function : mpgetdefaultname
145 //purpose :
146 //=======================================================================
mpgetdefaultname(Draw_Interpretor &,Standard_Integer n,const char **)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 //=======================================================================
mpsetfunctionname(Draw_Interpretor &,Standard_Integer n,const char ** a)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 //
174 if (BRepMesh_DiscretFactory::Get().SetFunctionName (aName))
175 printf(" *ready\n");
176 else
177 printf(" *fault\n");
178 //
179 return 0;
180 }
181 //=======================================================================
182 //function : mpgetdefaultname
183 //purpose :
184 //=======================================================================
mpgetfunctionname(Draw_Interpretor &,Standard_Integer n,const char **)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 //=======================================================================
mperror(Draw_Interpretor &,Standard_Integer n,const char **)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 //=======================================================================
mpincmesh(Draw_Interpretor &,Standard_Integer n,const char ** a)220 static Standard_Integer mpincmesh (Draw_Interpretor& , Standard_Integer n, const char** a)
221 {
222 Standard_Real aDeflection, aAngle;
223 TopoDS_Shape aS;
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 //
236 aDeflection=Draw::Atof(a[2]);
237 aAngle=0.5;
238 if (n>3) {
239 aAngle=Draw::Atof(a[3]);
240 }
241 //
242 Handle(BRepMesh_DiscretRoot) aMeshAlgo = BRepMesh_DiscretFactory::Get().Discret (aS,
243 aDeflection,
244 aAngle);
245 //
246 BRepMesh_FactoryError aErr = BRepMesh_DiscretFactory::Get().ErrorStatus();
247 if (aErr != BRepMesh_FE_NOERROR)
248 {
249 printf(" *Factory::Get().ErrorStatus()=%d\n", (int)aErr);
250 }
251 //
252 if (aMeshAlgo.IsNull())
253 {
254 printf(" *Can not create the algo\n");
255 return 0;
256 }
257 //
258 aMeshAlgo->Perform();
259 if (!aMeshAlgo->IsDone())
260 {
261 printf(" *Not done\n");
262 }
263 //
264 return 0;
265 }
266
267 //#######################################################################
triarea(Draw_Interpretor & di,int n,const char ** a)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)
277 anEps = Draw::Atof(a[2]);
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()) {
303 std::cout << "face "<<i<<" has no triangulation"<<std::endl;
304 continue;
305 }
306 for (int j = 1; j <= aPoly->NbTriangles(); j++)
307 {
308 const Poly_Triangle tri = aPoly->Triangle (j);
309 int n1, n2, n3;
310 tri.Get (n1, n2, n3);
311 const gp_Pnt p1 = aPoly->Node (n1);
312 const gp_Pnt p2 = aPoly->Node (n2);
313 const gp_Pnt p3 = aPoly->Node (n3);
314 gp_Vec v1(p1, p2);
315 gp_Vec v2(p1, p3);
316 double ar = v1.CrossMagnitude(v2);
317 aTriArea += ar;
318 }
319 }
320 aTriArea /= 2;
321 }
322
323 // compute area by geometry
324 GProp_GProps props;
325 if (anEps <= 0.)
326 BRepGProp::SurfaceProperties(shape, props);
327 else
328 BRepGProp::SurfaceProperties(shape, props, anEps);
329 double aGeomArea = props.Mass();
330
331 di << aTriArea << " " << aGeomArea << "\n";
332 return 0;
333 }
334
335 //#######################################################################
IsEqual(const BRepMesh_Edge & theFirst,const BRepMesh_Edge & theSecond)336 Standard_Boolean IsEqual(const BRepMesh_Edge& theFirst, const BRepMesh_Edge& theSecond)
337 {
338 return theFirst.IsEqual(theSecond);
339 }
340
tricheck(Draw_Interpretor & di,int n,const char ** a)341 static Standard_Integer tricheck (Draw_Interpretor& di, int n, const char ** a)
342 {
343 if (n < 2) return 1;
344
345 TopoDS_Shape shape = DBRep::Get(a[1]);
346 if (shape.IsNull()) return 1;
347
348 const Standard_Boolean isToFindSmallTriangles = (n >= 3) ? (strcmp(a[2], "-small") == 0) : Standard_False;
349
350 TopTools_IndexedMapOfShape aMapF;
351 TopExp::MapShapes (shape, TopAbs_FACE, aMapF);
352 const Standard_CString name = ".";
353
354 // execute check
355 MeshTest_CheckTopology aCheck(shape);
356 aCheck.Perform(di);
357
358 // dump info on free links inside the triangulation
359 Standard_Integer nbFree = 0;
360 Standard_Integer nbFac = aCheck.NbFacesWithFL(), i, k;
361 if (nbFac > 0) {
362 for (k=1; k <= nbFac; k++) {
363 Standard_Integer nbEdge = aCheck.NbFreeLinks(k);
364 Standard_Integer iF = aCheck.GetFaceNumWithFL(k);
365 nbFree += nbEdge;
366 di << "free links of face " << iF << "\n";
367
368 const TopoDS_Shape& aShape = aMapF.FindKey(iF);
369 const TopoDS_Face& aFace = TopoDS::Face(aShape);
370 TopLoc_Location aLoc;
371 Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
372 const gp_Trsf& trsf = aLoc.Transformation();
373
374 TColgp_Array1OfPnt pnts(1,2);
375 TColgp_Array1OfPnt2d pnts2d(1,2);
376 for (i=1; i <= nbEdge; i++) {
377 Standard_Integer n1, n2;
378 aCheck.GetFreeLink(k, i, n1, n2);
379 di << "{" << n1 << " " << n2 << "} ";
380 pnts (1) = aT->Node (n1).Transformed (trsf);
381 pnts (2) = aT->Node (n2).Transformed (trsf);
382 Handle(Poly_Polygon3D) poly = new Poly_Polygon3D (pnts);
383 DrawTrSurf::Set (name, poly);
384 DrawTrSurf::Set (name, pnts(1));
385 DrawTrSurf::Set (name, pnts(2));
386 if (aT->HasUVNodes())
387 {
388 pnts2d (1) = aT->UVNode (n1);
389 pnts2d (2) = aT->UVNode (n2);
390 Handle(Poly_Polygon2D) poly2d = new Poly_Polygon2D (pnts2d);
391 DrawTrSurf::Set (name, poly2d);
392 DrawTrSurf::Set (name, pnts2d(1));
393 DrawTrSurf::Set (name, pnts2d(2));
394 }
395 }
396 di << "\n";
397 }
398 }
399
400 // dump info on cross face errors
401 Standard_Integer nbErr = aCheck.NbCrossFaceErrors();
402 if (nbErr > 0) {
403 di << "cross face errors: {face1, node1, face2, node2, distance}\n";
404 for (i=1; i <= nbErr; i++) {
405 Standard_Integer iF1, n1, iF2, n2;
406 Standard_Real aVal;
407 aCheck.GetCrossFaceError(i, iF1, n1, iF2, n2, aVal);
408 di << "{" << iF1 << " " << n1 << " " << iF2 << " " << n2 << " " << aVal << "} ";
409 }
410 di << "\n";
411 }
412
413 // dump info on edges
414 Standard_Integer nbAsync = aCheck.NbAsyncEdges();
415 if (nbAsync > 0) {
416 di << "async edges:\n";
417 for (i=1; i <= nbAsync; i++) {
418 Standard_Integer ie = aCheck.GetAsyncEdgeNum(i);
419 di << ie << " ";
420 }
421 di << "\n";
422 }
423
424 // dump info on free nodes
425 Standard_Integer nbFreeNodes = aCheck.NbFreeNodes();
426 if (nbFreeNodes > 0) {
427 di << "free nodes (in pairs: face / node): \n";
428 for (i=1; i <= nbFreeNodes; i++) {
429 Standard_Integer iface, inode;
430 aCheck.GetFreeNodeNum(i, iface, inode);
431
432 const TopoDS_Face& aFace = TopoDS::Face(aMapF.FindKey(iface));
433 TopLoc_Location aLoc;
434 Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
435 const gp_Trsf& trsf = aLoc.Transformation();
436 DrawTrSurf::Set (name, aT->Node (inode).Transformed (trsf));
437 if (aT->HasUVNodes())
438 {
439 DrawTrSurf::Set (name, aT->UVNode (inode));
440 }
441
442 di << "{" << iface << " " << inode << "} ";
443 }
444 di << "\n";
445 }
446
447 const Standard_Integer aNbSmallTriangles = isToFindSmallTriangles? aCheck.NbSmallTriangles() : 0;
448 if (aNbSmallTriangles > 0)
449 {
450 di << "triangles with null area (in pairs: face / triangle): \n";
451 for (i = 1; i <= aNbSmallTriangles; i++)
452 {
453 Standard_Integer aFaceId = 0, aTriID = 0;
454 aCheck.GetSmallTriangle(i, aFaceId, aTriID);
455
456 const TopoDS_Face& aFace = TopoDS::Face(aMapF.FindKey(aFaceId));
457 TopLoc_Location aLoc;
458 const gp_Trsf& aTrsf = aLoc.Transformation();
459 const Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
460 const Poly_Triangle &aTri = aT->Triangle(aTriID);
461 Standard_Integer aN1, aN2, aN3;
462 aTri.Get(aN1, aN2, aN3);
463
464 TColgp_Array1OfPnt aPoles(1, 4);
465 aPoles (1) = aPoles (4) = aT->Node (aN1).Transformed (aTrsf);
466 aPoles (2) = aT->Node (aN2).Transformed (aTrsf);
467 aPoles (3) = aT->Node (aN3).Transformed (aTrsf);
468
469 TColStd_Array1OfInteger aMults(1, 4);
470 aMults(1) = aMults(4) = 2;
471 aMults(2) = aMults(3) = 1;
472
473 TColStd_Array1OfReal aKnots(1, 4);
474 aKnots(1) = 1.0;
475 aKnots(2) = 2.0;
476 aKnots(3) = 3.0;
477 aKnots(4) = 4.0;
478
479 Handle(Geom_BSplineCurve) aBS = new Geom_BSplineCurve(aPoles, aKnots, aMults, 1);
480
481 DrawTrSurf::Set(name, aBS);
482
483 if (aT->HasUVNodes())
484 {
485 TColgp_Array1OfPnt2d aPoles2d(1, 4);
486 aPoles2d (1) = aPoles2d (4) = aT->UVNode (aN1);
487 aPoles2d (2) = aT->UVNode (aN2);
488 aPoles2d (3) = aT->UVNode (aN3);
489
490 Handle(Geom2d_BSplineCurve) aBS2d = new Geom2d_BSplineCurve(aPoles2d, aKnots, aMults, 1);
491
492 DrawTrSurf::Set(name, aBS2d);
493 }
494
495 di << "{" << aFaceId << " " << aTriID << "} ";
496 }
497
498 di << "\n";
499 }
500
501 // output errors summary to DRAW
502 if (nbFree > 0 ||
503 nbErr > 0 ||
504 nbAsync > 0 ||
505 nbFreeNodes > 0 ||
506 (aNbSmallTriangles > 0))
507 {
508 di << "Free_links " << nbFree
509 << " Cross_face_errors " << nbErr
510 << " Async_edges " << nbAsync
511 << " Free_nodes " << nbFreeNodes
512 << " Small triangles " << aNbSmallTriangles << "\n";
513 }
514
515 Standard_Integer aFaceId = 1;
516 TopExp_Explorer aFaceExp(shape, TopAbs_FACE);
517 for ( ; aFaceExp.More(); aFaceExp.Next(), ++aFaceId)
518 {
519 const TopoDS_Shape& aShape = aFaceExp.Current();
520 const TopoDS_Face& aFace = TopoDS::Face(aShape);
521
522 TopLoc_Location aLoc;
523 Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
524
525 // Iterate boundary edges
526 NCollection_Map<BRepMesh_Edge> aBoundaryEdgeMap;
527 TopExp_Explorer anExp(aShape, TopAbs_EDGE);
528 for ( ; anExp.More(); anExp.Next() )
529 {
530 TopLoc_Location anEdgeLoc;
531 const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
532 Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(anEdge, aT, aLoc);
533 if (aPoly.IsNull())
534 {
535 continue;
536 }
537
538 const TColStd_Array1OfInteger& anIndices = aPoly->Nodes();
539 Standard_Integer aLower = anIndices.Lower();
540 Standard_Integer anUpper = anIndices.Upper();
541
542 Standard_Integer aPrevNode = -1;
543 for (Standard_Integer j = aLower; j <= anUpper; ++j)
544 {
545 Standard_Integer aNodeIdx = anIndices.Value(j);
546 if (j != aLower)
547 {
548 BRepMesh_Edge aLink(aPrevNode, aNodeIdx, BRepMesh_Frontier);
549 aBoundaryEdgeMap.Add(aLink);
550 }
551 aPrevNode = aNodeIdx;
552 }
553 }
554
555 if (aBoundaryEdgeMap.Size() == 0)
556 {
557 break;
558 }
559
560 NCollection_Map<BRepMesh_Edge> aFreeEdgeMap;
561 const Standard_Integer aTriNum = aT->NbTriangles();
562 for ( Standard_Integer aTriIndx = 1; aTriIndx <= aTriNum; aTriIndx++ )
563 {
564 const Poly_Triangle aTri = aT->Triangle (aTriIndx);
565 Standard_Integer aTriNodes[3] = { aTri.Value(1), aTri.Value(2), aTri.Value(3)};
566
567 for (Standard_Integer j = 1; j <= 3; ++j)
568 {
569 Standard_Integer aLastId = aTriNodes[j % 3];
570 Standard_Integer aFirstId = aTriNodes[j - 1];
571
572 BRepMesh_Edge aLink(aFirstId, aLastId, BRepMesh_Free);
573 if (!aBoundaryEdgeMap.Contains(aLink))
574 {
575 if (!aFreeEdgeMap.Add(aLink))
576 {
577 aFreeEdgeMap.Remove(aLink);
578 }
579 }
580 }
581 }
582
583 if (aFreeEdgeMap.Size() != 0)
584 {
585 di << "Not connected mesh inside face " << aFaceId << "\n";
586
587 const gp_Trsf& trsf = aLoc.Transformation();
588
589 TColgp_Array1OfPnt pnts(1,2);
590 TColgp_Array1OfPnt2d pnts2d(1,2);
591 NCollection_Map<BRepMesh_Edge>::Iterator aMapIt(aFreeEdgeMap);
592 for (; aMapIt.More(); aMapIt.Next())
593 {
594 const BRepMesh_Edge& aLink = aMapIt.Key();
595 di << "{" << aLink.FirstNode() << " " << aLink.LastNode() << "} ";
596 pnts (1) = aT->Node (aLink.FirstNode()).Transformed (trsf);
597 pnts (2) = aT->Node (aLink.LastNode()).Transformed (trsf);
598 Handle(Poly_Polygon3D) poly = new Poly_Polygon3D (pnts);
599 DrawTrSurf::Set (name, poly);
600 DrawTrSurf::Set (name, pnts(1));
601 DrawTrSurf::Set (name, pnts(2));
602 if (aT->HasUVNodes())
603 {
604 pnts2d (1) = aT->UVNode (aLink.FirstNode());
605 pnts2d (2) = aT->UVNode (aLink.LastNode());
606 Handle(Poly_Polygon2D) poly2d = new Poly_Polygon2D (pnts2d);
607 DrawTrSurf::Set (name, poly2d);
608 DrawTrSurf::Set (name, pnts2d(1));
609 DrawTrSurf::Set (name, pnts2d(2));
610 }
611 }
612 di << "\n";
613 }
614 }
615 return 0;
616 }
617
618 //=======================================================================
619 //function : mpparallel
620 //purpose :
621 //=======================================================================
mpparallel(Draw_Interpretor &,Standard_Integer argc,const char ** argv)622 static int mpparallel (Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
623 {
624 if (argc == 2)
625 {
626 Standard_Boolean isParallelOn = Draw::Atoi (argv[1]) == 1;
627 BRepMesh_IncrementalMesh::SetParallelDefault (isParallelOn);
628 }
629 std::cout << "Incremental Mesh, multi-threading "
630 << (BRepMesh_IncrementalMesh::IsParallelDefault() ? "ON\n" : "OFF\n");
631 return 0;
632 }
633