0025364: BRepMesh is not able to triangulate the shape with fine deflection
[occt.git] / src / BRepMesh / BRepMesh_DataStructureOfDelaun.cxx
CommitLineData
b311480e 1// Created on: 1993-05-11
2// Created by: Didier PIFFAULT
3// Copyright (c) 1993-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
0d88155b 16
fc9b36d6 17#include <BRepMesh_DataStructureOfDelaun.hxx>
18#include <BRepMesh_PairOfIndex.hxx>
19#include <BRepBuilderAPI_MakeEdge.hxx>
2caff0b3 20#include <BRepBuilderAPI_MakeVertex.hxx>
fc9b36d6 21
22#include <TopoDS_Compound.hxx>
23#include <BRep_Builder.hxx>
24#include <BRepTools.hxx>
25#include <Standard_ErrorHandler.hxx>
26
27IMPLEMENT_STANDARD_HANDLE (BRepMesh_DataStructureOfDelaun, Standard_Transient)
28IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_DataStructureOfDelaun, Standard_Transient)
0d88155b
O
29
30//=======================================================================
31//function : BRepMesh_DataStructureOfDelaun
32//purpose :
33//=======================================================================
fc9b36d6 34BRepMesh_DataStructureOfDelaun::BRepMesh_DataStructureOfDelaun(
848fa7e3 35 const Handle(NCollection_IncAllocator)& theAllocator,
36 const Standard_Integer theReservedNodeSize)
2caff0b3 37 : myAllocator (theAllocator),
38 myNodes (new BRepMesh_VertexTool(theReservedNodeSize, myAllocator)),
39 myLinks (theReservedNodeSize * 3, myAllocator),
40 myDelLinks (myAllocator),
41 myElements (theReservedNodeSize * 2, myAllocator),
42 myElementsOfDomain(theReservedNodeSize * 2, myAllocator),
43 myLinksOfDomain (theReservedNodeSize * 2, myAllocator)
0d88155b 44{
0d88155b
O
45}
46
2caff0b3 47//=======================================================================
48//function : SubstituteNode
49//purpose :
50//=======================================================================
51Standard_Integer BRepMesh_DataStructureOfDelaun::AddNode(
52 const BRepMesh_Vertex& theNode,
53 const Standard_Boolean isForceAdd)
54{
55 const Standard_Integer aNodeId = myNodes->Add(theNode, isForceAdd);
56 if (!myNodeLinks.IsBound(aNodeId))
57 myNodeLinks.Bind(aNodeId, BRepMesh::ListOfInteger(myAllocator));
58
59 return aNodeId;
60}
61
0d88155b 62//=======================================================================
fc9b36d6 63//function : SubstituteNode
0d88155b
O
64//purpose :
65//=======================================================================
fc9b36d6 66Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteNode(
67 const Standard_Integer theIndex,
68 const BRepMesh_Vertex& theNewNode)
0d88155b 69{
2caff0b3 70 if (myNodes->FindIndex(theNewNode) != 0)
fc9b36d6 71 return Standard_False;
0d88155b 72
2caff0b3 73 myNodes->Substitute(theIndex, theNewNode);
fc9b36d6 74 return Standard_True;
0d88155b
O
75}
76
77//=======================================================================
fc9b36d6 78//function : AddLink
0d88155b
O
79//purpose :
80//=======================================================================
fc9b36d6 81Standard_Integer BRepMesh_DataStructureOfDelaun::AddLink(
82 const BRepMesh_Edge& theLink)
0d88155b 83{
fc9b36d6 84 Standard_Integer aLinkIndex = IndexOf(theLink);
85 if (aLinkIndex > 0)
86 {
87 return theLink.IsSameOrientation(GetLink(aLinkIndex)) ?
88 aLinkIndex : -aLinkIndex;
89 }
0d88155b 90
fc9b36d6 91 BRepMesh_PairOfIndex aPair;
92 if (!myDelLinks.IsEmpty())
93 {
94 aLinkIndex = myDelLinks.First();
95 myLinks.Substitute(aLinkIndex, theLink, aPair);
96 myDelLinks.RemoveFirst();
0d88155b 97 }
fc9b36d6 98 else
99 aLinkIndex = myLinks.Add(theLink, aPair);
0d88155b 100
fc9b36d6 101 const Standard_Integer aLinkId = Abs(aLinkIndex);
2caff0b3 102 linksConnectedTo(theLink.FirstNode()).Append(aLinkId);
103 linksConnectedTo(theLink.LastNode() ).Append(aLinkId);
fc9b36d6 104 myLinksOfDomain.Add(aLinkIndex);
0d88155b 105
fc9b36d6 106 return aLinkIndex;
0d88155b
O
107}
108
109//=======================================================================
fc9b36d6 110//function : SubstituteLink
0d88155b
O
111//purpose :
112//=======================================================================
fc9b36d6 113Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteLink(
114 const Standard_Integer theIndex,
115 const BRepMesh_Edge& theNewLink)
0d88155b 116{
fc9b36d6 117 BRepMesh_PairOfIndex aPair;
118 BRepMesh_Edge aLink = GetLink(theIndex);
119 if (aLink.Movability() == BRepMesh_Deleted)
120 {
121 myLinks.Substitute(theIndex, theNewLink, aPair);
122 return Standard_True;
0d88155b 123 }
0d88155b 124
fc9b36d6 125 if (IndexOf(theNewLink) != 0)
126 return Standard_False;
0d88155b 127
fc9b36d6 128 aLink.SetMovability(BRepMesh_Deleted);
129 myLinks.Substitute(theIndex, aLink, aPair);
130 cleanLink(theIndex, aLink);
0d88155b 131
fc9b36d6 132 const Standard_Integer aLinkId = Abs(theIndex);
2caff0b3 133 linksConnectedTo(theNewLink.FirstNode()).Append(aLinkId);
134 linksConnectedTo(theNewLink.LastNode() ).Append(aLinkId);
fc9b36d6 135 myLinks.Substitute(theIndex, theNewLink, aPair);
136
137 return Standard_True;
0d88155b
O
138}
139
140//=======================================================================
fc9b36d6 141//function : ForceRemoveLink
0d88155b
O
142//purpose :
143//=======================================================================
fc9b36d6 144void BRepMesh_DataStructureOfDelaun::RemoveLink(
145 const Standard_Integer theIndex,
146 const Standard_Boolean isForce)
0d88155b 147{
fc9b36d6 148 BRepMesh_Edge& aLink = (BRepMesh_Edge&)GetLink(theIndex);
149 if (aLink.Movability() == BRepMesh_Deleted ||
150 (!isForce && aLink.Movability() != BRepMesh_Free) ||
151 ElementsConnectedTo(theIndex).Extent() != 0)
152 {
153 return;
0d88155b 154 }
0d88155b 155
fc9b36d6 156 cleanLink(theIndex, aLink);
157 aLink.SetMovability(BRepMesh_Deleted);
0d88155b 158
fc9b36d6 159 myLinksOfDomain.Remove(theIndex);
160 myDelLinks.Append (theIndex);
0d88155b
O
161}
162
163//=======================================================================
fc9b36d6 164//function : cleanLink
0d88155b
O
165//purpose :
166//=======================================================================
fc9b36d6 167void BRepMesh_DataStructureOfDelaun::cleanLink(
168 const Standard_Integer theIndex,
169 const BRepMesh_Edge& theLink)
0d88155b 170{
fc9b36d6 171 for (Standard_Integer i = 0; i < 2; ++i)
172 {
173 const Standard_Integer aNodeId = (i == 0) ?
174 theLink.FirstNode() : theLink.LastNode();
0d88155b 175
2caff0b3 176 BRepMesh::ListOfInteger& aLinkList = linksConnectedTo(aNodeId);
848fa7e3 177 BRepMesh::ListOfInteger::Iterator aLinkIt(aLinkList);
fc9b36d6 178 for(; aLinkIt.More(); aLinkIt.Next())
179 {
180 if (aLinkIt.Value() == theIndex)
181 {
182 aLinkList.Remove(aLinkIt);
0d88155b
O
183 break;
184 }
185 }
0d88155b 186 }
0d88155b
O
187}
188
189//=======================================================================
190//function : AddElement
191//purpose :
192//=======================================================================
fc9b36d6 193Standard_Integer BRepMesh_DataStructureOfDelaun::AddElement(
194 const BRepMesh_Triangle& theElement)
0d88155b 195{
fc9b36d6 196 Standard_Integer aElementIndex = IndexOf(theElement);
197 if (aElementIndex > 0)
198 return aElementIndex;
0d88155b 199
fc9b36d6 200 aElementIndex = myElements.Add(theElement);
201 myElementsOfDomain.Add(aElementIndex);
0d88155b 202
fc9b36d6 203 Standard_Integer e[3];
204 Standard_Boolean o[3];
205 theElement.Edges(e, o);
206 for (Standard_Integer i = 0; i < 3; ++i)
207 myLinks(e[i]).Append(aElementIndex);
0d88155b 208
fc9b36d6 209 return aElementIndex;
0d88155b
O
210}
211
212//=======================================================================
fc9b36d6 213//function : RemoveElement
0d88155b
O
214//purpose :
215//=======================================================================
fc9b36d6 216void BRepMesh_DataStructureOfDelaun::RemoveElement(
217 const Standard_Integer theIndex)
0d88155b 218{
fc9b36d6 219 BRepMesh_Triangle& aElement = (BRepMesh_Triangle&)GetElement(theIndex);
220 if (aElement.Movability() == BRepMesh_Deleted)
221 return;
222
223 cleanElement(theIndex, aElement);
224 aElement.SetMovability(BRepMesh_Deleted);
225 myElementsOfDomain.Remove(theIndex);
0d88155b
O
226}
227
228//=======================================================================
fc9b36d6 229//function : cleanElement
0d88155b
O
230//purpose :
231//=======================================================================
fc9b36d6 232void BRepMesh_DataStructureOfDelaun::cleanElement(
233 const Standard_Integer theIndex,
234 const BRepMesh_Triangle& theElement)
0d88155b 235{
fc9b36d6 236 if (theElement.Movability() != BRepMesh_Free)
237 return;
0d88155b 238
fc9b36d6 239 Standard_Integer e[3];
240 Standard_Boolean o[3];
241 theElement.Edges(e, o);
0d88155b 242
fc9b36d6 243 for (Standard_Integer i = 0; i < 3; ++i)
244 removeElementIndex(theIndex, myLinks(e[i]));
0d88155b
O
245}
246
247//=======================================================================
fc9b36d6 248//function : removeElementIndex
0d88155b
O
249//purpose :
250//=======================================================================
fc9b36d6 251void BRepMesh_DataStructureOfDelaun::removeElementIndex(
252 const Standard_Integer theIndex,
253 BRepMesh_PairOfIndex& thePair)
0d88155b 254{
fc9b36d6 255 for (Standard_Integer i = 1, n = thePair.Extent(); i <= n; ++i)
256 {
257 if (thePair.Index(i) == theIndex)
258 {
259 thePair.RemoveIndex(i);
260 return;
0d88155b 261 }
0d88155b 262 }
0d88155b
O
263}
264
265//=======================================================================
fc9b36d6 266//function : SubstituteElement
0d88155b
O
267//purpose :
268//=======================================================================
fc9b36d6 269Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteElement(
270 const Standard_Integer theIndex,
271 const BRepMesh_Triangle& theNewElement)
0d88155b 272{
fc9b36d6 273 const BRepMesh_Triangle& aElement = GetElement(theIndex);
274 if (aElement.Movability() == BRepMesh_Deleted)
275 {
276 myElements.Substitute(theIndex, theNewElement);
277 return Standard_True;
0d88155b 278 }
0d88155b 279
fc9b36d6 280 if (IndexOf(theNewElement) != 0)
281 return Standard_False;
0d88155b 282
fc9b36d6 283 cleanElement(theIndex, aElement);
284 // Warning: here new element and old element should have different Hash code
285 myElements.Substitute(theIndex, theNewElement);
0d88155b 286
fc9b36d6 287 Standard_Integer e[3];
288 Standard_Boolean o[3];
289 theNewElement.Edges(e, o);
290 for (Standard_Integer i = 0; i < 3; ++i)
291 myLinks(e[i]).Append(theIndex);
0d88155b 292
fc9b36d6 293 return Standard_True;
0d88155b
O
294}
295
296//=======================================================================
fc9b36d6 297//function : ElementNodes
298//purpose :
0d88155b 299//=======================================================================
fc9b36d6 300void BRepMesh_DataStructureOfDelaun::ElementNodes(
301 const BRepMesh_Triangle& theElement,
302 Standard_Integer (&theNodes)[3])
0d88155b 303{
fc9b36d6 304 Standard_Integer e[3];
305 Standard_Boolean o[3];
306 theElement.Edges(e, o);
0d88155b 307
fc9b36d6 308 const BRepMesh_Edge& aLink1 = GetLink(e[0]);
309 if (o[0])
310 {
311 theNodes[0] = aLink1.FirstNode();
312 theNodes[1] = aLink1.LastNode();
313 }
314 else
315 {
316 theNodes[1] = aLink1.FirstNode();
317 theNodes[0] = aLink1.LastNode();
318 }
319
320 const BRepMesh_Edge& aLink2 = GetLink(e[2]);
321 if (o[2])
322 theNodes[2] = aLink2.FirstNode();
323 else
324 theNodes[2] = aLink2.LastNode();
0d88155b
O
325}
326
327//=======================================================================
fc9b36d6 328//function : ClearDomain
0d88155b
O
329//purpose :
330//=======================================================================
fc9b36d6 331void BRepMesh_DataStructureOfDelaun::ClearDomain()
0d88155b 332{
848fa7e3 333 BRepMesh::MapOfInteger aFreeEdges;
334 BRepMesh::MapOfInteger::Iterator aElementIt(myElementsOfDomain);
fc9b36d6 335 for (; aElementIt.More(); aElementIt.Next())
336 {
337 const Standard_Integer aElementId = aElementIt.Key();
338 BRepMesh_Triangle& aElement = (BRepMesh_Triangle&)GetElement(aElementId);
0d88155b 339
fc9b36d6 340 Standard_Integer e[3];
341 Standard_Boolean o[3];
342 aElement.Edges(e, o);
343
344 for (Standard_Integer i = 0; i < 3; ++i)
345 aFreeEdges.Add(e[i]);
346
347 cleanElement(aElementId, aElement);
348 aElement.SetMovability(BRepMesh_Deleted);
349 }
350 myElementsOfDomain.Clear();
351
848fa7e3 352 BRepMesh::MapOfInteger::Iterator aEdgeIt(aFreeEdges);
fc9b36d6 353 for (; aEdgeIt.More(); aEdgeIt.Next())
354 RemoveLink(aEdgeIt.Key());
0d88155b
O
355}
356
357//=======================================================================
fc9b36d6 358//function : clearDeletedLinks
0d88155b
O
359//purpose :
360//=======================================================================
fc9b36d6 361void BRepMesh_DataStructureOfDelaun::clearDeletedLinks()
0d88155b 362{
fc9b36d6 363 Standard_Integer aLastLiveItem = NbLinks();
364 while (!myDelLinks.IsEmpty())
365 {
366 while (aLastLiveItem > 0)
367 {
368 if (GetLink(aLastLiveItem).Movability() != BRepMesh_Deleted)
0d88155b 369 break;
fc9b36d6 370
0d88155b 371 myLinks.RemoveLast();
fc9b36d6 372 --aLastLiveItem;
0d88155b
O
373 }
374
fc9b36d6 375 Standard_Integer aDelItem = myDelLinks.First();
0d88155b
O
376 myDelLinks.RemoveFirst();
377
fc9b36d6 378 if (aDelItem > aLastLiveItem)
379 continue;
380
381 BRepMesh_Edge aLink = GetLink(aLastLiveItem);
382 BRepMesh_PairOfIndex& aPair = myLinks(aLastLiveItem);
383
384 myLinks.RemoveLast();
385 myLinks.Substitute(aDelItem, aLink, aPair);
386
387 myLinksOfDomain.Remove(aLastLiveItem);
388 myLinksOfDomain.Add(aDelItem);
389 --aLastLiveItem;
390
391 const Standard_Integer aLastLiveItemId = aLastLiveItem + 1;
848fa7e3 392 BRepMesh::ListOfInteger::Iterator aLinkIt;
fc9b36d6 393 // update link references
394 for (Standard_Integer i = 0; i < 2; ++i)
395 {
396 const Standard_Integer aCurNodeId = (i == 0) ?
397 aLink.FirstNode() : aLink.LastNode();
398
2caff0b3 399 for (aLinkIt.Init(linksConnectedTo(aCurNodeId)); aLinkIt.More(); aLinkIt.Next())
fc9b36d6 400 {
401 Standard_Integer& aLinkId = aLinkIt.ChangeValue();
402 if (aLinkId == aLastLiveItemId)
403 {
404 aLinkId = aDelItem;
405 break;
0d88155b
O
406 }
407 }
fc9b36d6 408 }
409
410 // update elements references
411 for(Standard_Integer j = 1, jn = aPair.Extent(); j <= jn; ++j)
412 {
413 const BRepMesh_Triangle& aElement = GetElement(aPair.Index(j));
414
415 Standard_Integer e[3];
416 Standard_Boolean o[3];
417 aElement.Edges(e, o);
418 for (Standard_Integer i = 0; i < 3; ++i)
419 {
420 if (e[i] == aLastLiveItemId)
421 {
422 e[i] = aDelItem;
423 break;
0d88155b 424 }
0d88155b 425 }
fc9b36d6 426
427 myElements.Substitute(aLinkIt.Value(),
428 BRepMesh_Triangle(e, o, aElement.Movability()));
0d88155b
O
429 }
430 }
fc9b36d6 431}
0d88155b 432
fc9b36d6 433//=======================================================================
434//function : clearDeletedNodes
435//purpose :
436//=======================================================================
437void BRepMesh_DataStructureOfDelaun::clearDeletedNodes()
438{
848fa7e3 439 BRepMesh::ListOfInteger& aDelNodes =
2caff0b3 440 (BRepMesh::ListOfInteger&)myNodes->GetListOfDelNodes();
0d88155b 441
fc9b36d6 442 Standard_Integer aLastLiveItem = NbNodes();
443 while (!aDelNodes.IsEmpty())
444 {
445 while (aLastLiveItem > 0)
446 {
447 if (GetNode(aLastLiveItem).Movability() != BRepMesh_Deleted)
0d88155b 448 break;
fc9b36d6 449
2caff0b3 450 myNodes->RemoveLast();
fc9b36d6 451 --aLastLiveItem;
0d88155b 452 }
fc9b36d6 453
454 Standard_Integer aDelItem = aDelNodes.First();
51c3cc5f 455 aDelNodes.RemoveFirst();
0d88155b 456
fc9b36d6 457 if (aDelItem > aLastLiveItem)
458 continue;
459
460 BRepMesh_Vertex aNode = GetNode(aLastLiveItem);
2caff0b3 461 BRepMesh::ListOfInteger& aLinkList = linksConnectedTo(aLastLiveItem);
fc9b36d6 462
2caff0b3 463 myNodes->RemoveLast();
fc9b36d6 464 --aLastLiveItem;
465
2caff0b3 466 myNodes->Substitute(aDelItem, aNode);
467 myNodeLinks.ChangeFind(aDelItem) = aLinkList;
fc9b36d6 468
469 const Standard_Integer aLastLiveItemId = aLastLiveItem + 1;
848fa7e3 470 BRepMesh::ListOfInteger::Iterator aLinkIt(aLinkList);
fc9b36d6 471 for (; aLinkIt.More(); aLinkIt.Next())
472 {
473 const Standard_Integer aLinkId = aLinkIt.Value();
474 const BRepMesh_Edge& aLink = GetLink(aLinkId);
475 BRepMesh_PairOfIndex& aPair = myLinks(aLinkId);
476
477 Standard_Integer v[2] = { aLink.FirstNode(), aLink.LastNode() };
478 if (v[0] == aLastLiveItemId)
479 v[0] = aDelItem;
480 else if (v[1] == aLastLiveItemId)
481 v[1] = aDelItem;
482
483 myLinks.Substitute(aLinkId,
484 BRepMesh_Edge(v[0], v[1], aLink.Movability()), aPair);
0d88155b
O
485 }
486 }
487}
488
489//=======================================================================
490//function : Statistics
491//purpose :
492//=======================================================================
fc9b36d6 493void BRepMesh_DataStructureOfDelaun::Statistics(Standard_OStream& theStream) const
0d88155b 494{
fc9b36d6 495 theStream << " Map of nodes : \n";
2caff0b3 496 myNodes->Statistics(theStream);
497 theStream << "\n Deleted nodes : " << myNodes->GetListOfDelNodes().Extent() << endl;
0d88155b 498
fc9b36d6 499 theStream << "\n\n Map of Links : \n";
500 myLinks.Statistics(theStream);
501 theStream << "\n Deleted links : " << myDelLinks.Extent() << endl;
0d88155b 502
fc9b36d6 503 theStream << "\n\n Map of elements : \n";
504 myElements.Statistics(theStream);
0d88155b
O
505}
506
507//=======================================================================
fc9b36d6 508//function : BRepMesh_Write
0d88155b 509//purpose :
fc9b36d6 510// Global function not declared in any public header, intended for use
511// from debugger prompt (Command Window in Visual Studio).
512//
513// Stores the mesh data structure to BRep file with the given name.
0d88155b 514//=======================================================================
fc9b36d6 515Standard_CString BRepMesh_Dump(void* theMeshHandlePtr,
516 Standard_CString theFileNameStr)
0d88155b 517{
fc9b36d6 518 if (theMeshHandlePtr == 0 || theFileNameStr == 0)
519 {
520 return "Error: file name or mesh data is null";
521 }
51c3cc5f 522
fc9b36d6 523 Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
524 *(Handle(BRepMesh_DataStructureOfDelaun)*)theMeshHandlePtr;
525
526 if (aMeshData.IsNull())
527 return "Error: mesh data is empty";
528
529 TopoDS_Compound aMesh;
530 BRep_Builder aBuilder;
531 aBuilder.MakeCompound(aMesh);
532
533 try
534 {
535 OCC_CATCH_SIGNALS
536
2caff0b3 537 if (aMeshData->LinksOfDomain().IsEmpty())
fc9b36d6 538 {
2caff0b3 539 const Standard_Integer aNodesNb = aMeshData->NbNodes();
540 for (Standard_Integer i = 1; i <= aNodesNb; ++i)
fc9b36d6 541 {
2caff0b3 542 const gp_XY& aNode = aMeshData->GetNode(i).Coord();
543 gp_Pnt aPnt(aNode.X(), aNode.Y(), 0.);
544 aBuilder.Add(aMesh, BRepBuilderAPI_MakeVertex(aPnt));
fc9b36d6 545 }
2caff0b3 546 }
547 else
548 {
549 BRepMesh::MapOfInteger::Iterator aLinksIt(aMeshData->LinksOfDomain());
550 for (; aLinksIt.More(); aLinksIt.Next())
551 {
552 const BRepMesh_Edge& aLink = aMeshData->GetLink(aLinksIt.Value());
553 gp_Pnt aPnt[2];
554 for (Standard_Integer i = 0; i < 2; ++i)
555 {
556 const Standard_Integer aNodeId =
557 (i == 0) ? aLink.FirstNode() : aLink.LastNode();
558
559 const gp_XY& aNode = aMeshData->GetNode(aNodeId).Coord();
560 aPnt[i] = gp_Pnt(aNode.X(), aNode.Y(), 0.);
561 }
fc9b36d6 562
2caff0b3 563 if (aPnt[0].SquareDistance(aPnt[1]) < Precision::SquareConfusion())
564 continue;
fc9b36d6 565
2caff0b3 566 aBuilder.Add(aMesh, BRepBuilderAPI_MakeEdge(aPnt[0], aPnt[1]));
567 }
fc9b36d6 568 }
569
570 if (!BRepTools::Write(aMesh, theFileNameStr))
571 return "Error: write failed";
572 }
573 catch (Standard_Failure)
574 {
575 return Standard_Failure::Caught()->GetMessageString();
576 }
577
578 return theFileNameStr;
51c3cc5f 579}