8 #include "GmshConfig.h"
24 #include <BRepAlgoAPI_Common.hxx>
25 #include <BRepAlgoAPI_Cut.hxx>
26 #include <BRepAlgoAPI_Fuse.hxx>
27 #include <BRepAlgoAPI_Section.hxx>
28 #include <BRepBndLib.hxx>
29 #include <BRepBuilderAPI_Copy.hxx>
30 #include <BRepBuilderAPI_GTransform.hxx>
31 #include <BRepBuilderAPI_MakeEdge.hxx>
32 #include <BRepBuilderAPI_MakeFace.hxx>
33 #include <BRepBuilderAPI_MakeShell.hxx>
34 #include <BRepBuilderAPI_MakeSolid.hxx>
35 #include <BRepBuilderAPI_MakeVertex.hxx>
36 #include <BRepBuilderAPI_MakeWire.hxx>
37 #include <BRepBuilderAPI_NurbsConvert.hxx>
38 #include <BRepBuilderAPI_Transform.hxx>
39 #include <BRepCheck_Analyzer.hxx>
40 #include <BRepExtrema_DistShapeShape.hxx>
41 #include <BRepFill_CurveConstraint.hxx>
42 #include <BRepFilletAPI_MakeChamfer.hxx>
43 #include <BRepFilletAPI_MakeFillet.hxx>
44 #include <BRepGProp.hxx>
45 #include <BRepLib.hxx>
46 #include <BRepOffsetAPI_MakeFilling.hxx>
47 #include <BRepOffsetAPI_MakePipe.hxx>
48 #include <BRepOffsetAPI_MakeThickSolid.hxx>
49 #include <BRepOffsetAPI_Sewing.hxx>
50 #include <BRepOffsetAPI_ThruSections.hxx>
51 #include <BRepPrimAPI_MakeBox.hxx>
52 #include <BRepPrimAPI_MakeCone.hxx>
53 #include <BRepPrimAPI_MakeCylinder.hxx>
54 #include <BRepPrimAPI_MakePrism.hxx>
55 #include <BRepPrimAPI_MakeRevol.hxx>
56 #include <BRepPrimAPI_MakeSphere.hxx>
57 #include <BRepPrimAPI_MakeTorus.hxx>
58 #include <BRepPrimAPI_MakeWedge.hxx>
59 #include <BRepTools.hxx>
60 #include <BRepTools_WireExplorer.hxx>
61 #include <BRep_Tool.hxx>
62 #include <Bnd_Box.hxx>
64 #include <GProp_GProps.hxx>
65 #include <Geom2d_Curve.hxx>
66 #include <GeomAPI_Interpolate.hxx>
67 #include <GeomConvert.hxx>
68 #include <GeomFill_BSplineCurves.hxx>
69 #include <GeomFill_BezierCurves.hxx>
70 #include <GeomProjLib.hxx>
71 #include <Geom_BSplineCurve.hxx>
72 #include <Geom_BSplineSurface.hxx>
73 #include <Geom_BezierCurve.hxx>
74 #include <Geom_BezierSurface.hxx>
75 #include <Geom_Circle.hxx>
76 #include <Geom_Ellipse.hxx>
77 #include <Geom_Plane.hxx>
78 #include <Geom_Surface.hxx>
79 #include <Geom_TrimmedCurve.hxx>
80 #include <IGESControl_Reader.hxx>
81 #include <IGESControl_Writer.hxx>
82 #include <Interface_Static.hxx>
83 #include <Poly_PolygonOnTriangulation.hxx>
84 #include <Poly_Triangle.hxx>
85 #include <Poly_Triangulation.hxx>
86 #include <ProjLib_ProjectedCurve.hxx>
87 #include <STEPControl_Reader.hxx>
88 #include <STEPControl_Writer.hxx>
89 #include <ShapeBuild_ReShape.hxx>
90 #include <ShapeFix_FixSmallFace.hxx>
91 #include <ShapeFix_Shape.hxx>
92 #include <ShapeFix_Wireframe.hxx>
93 #include <Standard_Version.hxx>
94 #include <TColStd_Array1OfInteger.hxx>
95 #include <TColStd_Array1OfReal.hxx>
96 #include <TColStd_Array2OfReal.hxx>
97 #include <TColgp_Array1OfPnt.hxx>
98 #include <TColgp_Array1OfPnt2d.hxx>
99 #include <TColgp_Array2OfPnt.hxx>
100 #include <TColgp_HArray1OfPnt.hxx>
101 #include <TopExp.hxx>
102 #include <TopExp_Explorer.hxx>
103 #include <TopTools_DataMapIteratorOfDataMapOfIntegerShape.hxx>
104 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
105 #include <TopTools_ListIteratorOfListOfShape.hxx>
106 #include <TopoDS.hxx>
107 #include <gce_MakeCirc.hxx>
108 #include <gce_MakeElips.hxx>
109 #include <gce_MakePln.hxx>
113 #if OCC_VERSION_HEX < 0x060900
114 #error "Gmsh requires OpenCASCADE >= 6.9"
117 #if OCC_VERSION_HEX > 0x070100
118 #include <BOPAlgo_Alerts.hxx>
121 #if OCC_VERSION_HEX > 0x070300
122 #include <BRepMesh_IncrementalMesh.hxx>
124 #include <BRepMesh_FastDiscret.hxx>
127 #if OCC_VERSION_HEX < 0x070400
128 #include <ShapeUpgrade_UnifySameDomain.hxx>
131 #if defined(HAVE_OCC_CAF)
132 #include <IGESCAFControl_Reader.hxx>
133 #include <Quantity_Color.hxx>
134 #include <STEPCAFControl_Reader.hxx>
135 #include <TDF_ChildIterator.hxx>
136 #include <TDF_Tool.hxx>
137 #include <TDataStd_Name.hxx>
138 #include <TDocStd_Document.hxx>
139 #include <XCAFApp_Application.hxx>
140 #include <XCAFDoc_Color.hxx>
141 #include <XCAFDoc_ColorTool.hxx>
142 #include <XCAFDoc_DocumentTool.hxx>
143 #include <XCAFDoc_Location.hxx>
144 #include <XCAFDoc_MaterialTool.hxx>
145 #include <XCAFDoc_ShapeTool.hxx>
150 void writeBrep(
const T &shapes,
const std::string &fileName =
"debug.brep")
155 for(
auto s : shapes) b.Add(
c, s);
156 BRepTools::Write(
c, fileName.c_str());
161 for(
int i = 0; i < 6; i++) _maxTag[i] = 0;
163 _attributes =
new OCCAttributesRTree(
CTX::instance()->geom.tolerance);
166 OCC_Internals::~OCC_Internals() {
delete _attributes; }
170 _attributes->clear();
182 if(dim < -2 || dim > 3)
return;
183 _maxTag[dim + 2] = std::max(_maxTag[dim + 2], val);
188 if(dim < -2 || dim > 3)
return 0;
189 return _maxTag[dim + 2];
192 void OCC_Internals::_recomputeMaxTag(
int dim)
194 if(dim < -2 || dim > 3)
return;
195 _maxTag[dim + 2] = 0;
196 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp;
198 case 0: exp.Initialize(_tagVertex);
break;
199 case 1: exp.Initialize(_tagEdge);
break;
200 case 2: exp.Initialize(_tagFace);
break;
201 case 3: exp.Initialize(_tagSolid);
break;
202 case -1: exp.Initialize(_tagWire);
break;
203 case -2: exp.Initialize(_tagShell);
break;
205 for(; exp.More(); exp.Next())
206 _maxTag[dim + 2] = std::max(_maxTag[dim + 2], exp.Key());
209 void OCC_Internals::_bind(
const TopoDS_Vertex &vertex,
int tag,
bool recursive)
211 if(vertex.IsNull())
return;
212 if(_vertexTag.IsBound(vertex)) {
213 if(_vertexTag.Find(vertex) != tag) {
214 Msg::Info(
"Cannot bind existing OpenCASCADE point %d to second tag %d",
215 _vertexTag.Find(vertex), tag);
219 if(_tagVertex.IsBound(tag)) {
221 Msg::Info(
"Rebinding OpenCASCADE point %d", tag);
223 _vertexTag.Bind(vertex, tag);
224 _tagVertex.Bind(tag, vertex);
227 _attributes->insert(
new OCCAttributes(0, vertex));
231 void OCC_Internals::_bind(
const TopoDS_Edge &edge,
int tag,
bool recursive)
233 if(edge.IsNull())
return;
234 if(_edgeTag.IsBound(edge)) {
235 if(_edgeTag.Find(edge) != tag) {
236 Msg::Info(
"Cannot bind existing OpenCASCADE curve %d to second tag %d",
237 _edgeTag.Find(edge), tag);
241 if(_tagEdge.IsBound(tag)) {
243 Msg::Info(
"Rebinding OpenCASCADE curve %d", tag);
245 _edgeTag.Bind(edge, tag);
246 _tagEdge.Bind(tag, edge);
249 _attributes->insert(
new OCCAttributes(1, edge));
252 TopExp_Explorer exp0;
253 for(exp0.Init(edge, TopAbs_VERTEX); exp0.More(); exp0.Next()) {
254 TopoDS_Vertex vertex = TopoDS::Vertex(exp0.Current());
255 if(!_vertexTag.IsBound(vertex)) {
257 _bind(vertex, t, recursive);
263 void OCC_Internals::_bind(
const TopoDS_Wire &wire,
int tag,
bool recursive)
265 if(wire.IsNull())
return;
266 if(_wireTag.IsBound(wire)) {
267 if(_wireTag.Find(wire) != tag) {
268 Msg::Info(
"Cannot bind existing OpenCASCADE wire %d to second tag %d",
269 _wireTag.Find(wire), tag);
273 if(_tagWire.IsBound(tag)) {
275 Msg::Info(
"Rebinding OpenCASCADE wire %d", tag);
277 _wireTag.Bind(wire, tag);
278 _tagWire.Bind(tag, wire);
283 TopExp_Explorer exp0;
284 for(exp0.Init(wire, TopAbs_EDGE); exp0.More(); exp0.Next()) {
285 TopoDS_Edge edge = TopoDS::Edge(exp0.Current());
286 if(!_edgeTag.IsBound(edge)) {
288 _bind(edge, t, recursive);
294 void OCC_Internals::_bind(
const TopoDS_Face &face,
int tag,
bool recursive)
296 if(face.IsNull())
return;
297 if(_faceTag.IsBound(face)) {
298 if(_faceTag.Find(face) != tag) {
299 Msg::Info(
"Cannot bind existing OpenCASCADE surface %d to second tag %d",
300 _faceTag.Find(face), tag);
304 if(_tagFace.IsBound(tag)) {
306 Msg::Info(
"Rebinding OpenCASCADE surface %d", tag);
308 _faceTag.Bind(face, tag);
309 _tagFace.Bind(tag, face);
312 _attributes->insert(
new OCCAttributes(2, face));
315 TopExp_Explorer exp0;
316 for(exp0.Init(face, TopAbs_WIRE); exp0.More(); exp0.Next()) {
317 TopoDS_Wire wire = TopoDS::Wire(exp0.Current());
318 if(!_wireTag.IsBound(wire)) {
320 _bind(wire, t, recursive);
323 for(exp0.Init(face, TopAbs_EDGE); exp0.More(); exp0.Next()) {
324 TopoDS_Edge edge = TopoDS::Edge(exp0.Current());
325 if(!_edgeTag.IsBound(edge)) {
327 _bind(edge, t, recursive);
333 void OCC_Internals::_bind(
const TopoDS_Shell &shell,
int tag,
bool recursive)
335 if(shell.IsNull())
return;
336 if(_shellTag.IsBound(shell)) {
337 if(_shellTag.Find(shell) != tag) {
338 Msg::Info(
"Cannot bind existing OpenCASCADE shell %d to second tag %d",
339 _shellTag.Find(shell), tag);
343 if(_tagShell.IsBound(tag)) {
345 Msg::Info(
"Rebinding OpenCASCADE shell %d", tag);
347 _shellTag.Bind(shell, tag);
348 _tagShell.Bind(tag, shell);
353 TopExp_Explorer exp0;
354 for(exp0.Init(shell, TopAbs_FACE); exp0.More(); exp0.Next()) {
355 TopoDS_Face face = TopoDS::Face(exp0.Current());
356 if(!_faceTag.IsBound(face)) {
358 _bind(face, t, recursive);
364 void OCC_Internals::_bind(
const TopoDS_Solid &solid,
int tag,
bool recursive)
366 if(solid.IsNull())
return;
367 if(_solidTag.IsBound(solid)) {
368 if(_solidTag.Find(solid) != tag) {
369 Msg::Info(
"Cannot bind existing OpenCASCADE volume %d to second tag %d",
370 _solidTag.Find(solid), tag);
374 if(_tagSolid.IsBound(tag)) {
376 Msg::Info(
"Rebinding OpenCASCADE volume %d", tag);
378 _solidTag.Bind(solid, tag);
379 _tagSolid.Bind(tag, solid);
382 _attributes->insert(
new OCCAttributes(3, solid));
385 TopExp_Explorer exp0;
386 for(exp0.Init(solid, TopAbs_SHELL); exp0.More(); exp0.Next()) {
387 TopoDS_Shell shell = TopoDS::Shell(exp0.Current());
388 if(!_shellTag.IsBound(shell)) {
390 _bind(shell, t, recursive);
393 for(exp0.Init(solid, TopAbs_FACE); exp0.More(); exp0.Next()) {
394 TopoDS_Face face = TopoDS::Face(exp0.Current());
395 if(!_faceTag.IsBound(face)) {
397 _bind(face, t, recursive);
403 void OCC_Internals::_bind(TopoDS_Shape shape,
int dim,
int tag,
bool recursive)
406 case 0: _bind(TopoDS::Vertex(shape), tag, recursive);
break;
407 case 1: _bind(TopoDS::Edge(shape), tag, recursive);
break;
408 case 2: _bind(TopoDS::Face(shape), tag, recursive);
break;
409 case 3: _bind(TopoDS::Solid(shape), tag, recursive);
break;
410 case -1: _bind(TopoDS::Wire(shape), tag, recursive);
break;
411 case -2: _bind(TopoDS::Shell(shape), tag, recursive);
break;
416 void OCC_Internals::_unbind(
const TopoDS_Vertex &vertex,
int tag,
bool recursive)
418 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp0(_tagEdge);
419 for(; exp0.More(); exp0.Next()) {
420 TopoDS_Edge edge = TopoDS::Edge(exp0.Value());
421 TopExp_Explorer exp1;
422 for(exp1.Init(edge, TopAbs_VERTEX); exp1.More(); exp1.Next()) {
423 if(exp1.Current().IsSame(vertex))
return;
426 std::pair<int, int> dimTag(0, tag);
427 if(_toPreserve.find(dimTag) != _toPreserve.end())
return;
428 _vertexTag.UnBind(vertex);
429 _tagVertex.UnBind(tag);
430 _toRemove.insert(dimTag);
435 void OCC_Internals::_unbind(
const TopoDS_Edge &edge,
int tag,
bool recursive)
437 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp2(_tagFace);
438 for(; exp2.More(); exp2.Next()) {
439 TopoDS_Face face = TopoDS::Face(exp2.Value());
440 TopExp_Explorer exp1;
441 for(exp1.Init(face, TopAbs_EDGE); exp1.More(); exp1.Next()) {
442 if(exp1.Current().IsSame(edge))
return;
445 std::pair<int, int> dimTag(1, tag);
446 if(_toPreserve.find(dimTag) != _toPreserve.end())
return;
447 _edgeTag.UnBind(edge);
448 _tagEdge.UnBind(tag);
449 _toRemove.insert(dimTag);
452 TopExp_Explorer exp0;
453 for(exp0.Init(edge, TopAbs_VERTEX); exp0.More(); exp0.Next()) {
454 TopoDS_Vertex vertex = TopoDS::Vertex(exp0.Current());
455 if(_vertexTag.IsBound(vertex)) {
456 int t = _vertexTag.Find(vertex);
457 _unbind(vertex, t, recursive);
464 void OCC_Internals::_unbind(
const TopoDS_Wire &wire,
int tag,
bool recursive)
466 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp0(_tagFace);
467 for(; exp0.More(); exp0.Next()) {
468 TopoDS_Face face = TopoDS::Face(exp0.Value());
469 TopExp_Explorer exp1;
470 for(exp1.Init(face, TopAbs_WIRE); exp1.More(); exp1.Next()) {
471 if(exp1.Current().IsSame(wire))
return;
474 std::pair<int, int> dimTag(-1, tag);
475 if(_toPreserve.find(dimTag) != _toPreserve.end())
return;
476 _wireTag.UnBind(wire);
477 _tagWire.UnBind(tag);
478 _toRemove.insert(dimTag);
479 _recomputeMaxTag(-1);
481 TopExp_Explorer exp0;
482 for(exp0.Init(wire, TopAbs_EDGE); exp0.More(); exp0.Next()) {
483 TopoDS_Edge edge = TopoDS::Edge(exp0.Current());
484 if(_edgeTag.IsBound(edge)) {
485 int t = _edgeTag.Find(edge);
486 _unbind(edge, t, recursive);
493 void OCC_Internals::_unbind(
const TopoDS_Face &face,
int tag,
bool recursive)
495 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp2(_tagSolid);
496 for(; exp2.More(); exp2.Next()) {
497 TopoDS_Solid solid = TopoDS::Solid(exp2.Value());
498 TopExp_Explorer exp1;
499 for(exp1.Init(solid, TopAbs_FACE); exp1.More(); exp1.Next()) {
500 if(exp1.Current().IsSame(face))
return;
503 std::pair<int, int> dimTag(2, tag);
504 if(_toPreserve.find(dimTag) != _toPreserve.end())
return;
505 _faceTag.UnBind(face);
506 _tagFace.UnBind(tag);
507 _toRemove.insert(dimTag);
510 TopExp_Explorer exp0;
511 for(exp0.Init(face, TopAbs_WIRE); exp0.More(); exp0.Next()) {
512 TopoDS_Wire wire = TopoDS::Wire(exp0.Current());
513 if(_wireTag.IsBound(wire)) {
514 int t = _wireTag.Find(wire);
515 _unbind(wire, t, recursive);
518 for(exp0.Init(face, TopAbs_EDGE); exp0.More(); exp0.Next()) {
519 TopoDS_Edge edge = TopoDS::Edge(exp0.Current());
520 if(_edgeTag.IsBound(edge)) {
521 int t = _edgeTag.Find(edge);
522 _unbind(edge, t, recursive);
529 void OCC_Internals::_unbind(
const TopoDS_Shell &shell,
int tag,
bool recursive)
531 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp0(_tagSolid);
532 for(; exp0.More(); exp0.Next()) {
533 TopoDS_Solid solid = TopoDS::Solid(exp0.Value());
534 TopExp_Explorer exp1;
535 for(exp1.Init(solid, TopAbs_SHELL); exp1.More(); exp1.Next()) {
536 if(exp1.Current().IsSame(shell))
return;
539 std::pair<int, int> dimTag(-2, tag);
540 if(_toPreserve.find(dimTag) != _toPreserve.end())
return;
541 _shellTag.UnBind(shell);
542 _tagShell.UnBind(tag);
543 _toRemove.insert(dimTag);
544 _recomputeMaxTag(-2);
546 TopExp_Explorer exp0;
547 for(exp0.Init(shell, TopAbs_FACE); exp0.More(); exp0.Next()) {
548 TopoDS_Face face = TopoDS::Face(exp0.Current());
549 if(_faceTag.IsBound(face)) {
550 int t = _faceTag.Find(face);
551 _unbind(face, t, recursive);
558 void OCC_Internals::_unbind(
const TopoDS_Solid &solid,
int tag,
bool recursive)
560 std::pair<int, int> dimTag(3, tag);
561 if(_toPreserve.find(dimTag) != _toPreserve.end())
return;
562 _solidTag.UnBind(solid);
563 _tagSolid.UnBind(tag);
564 _toRemove.insert(dimTag);
567 TopExp_Explorer exp0;
568 for(exp0.Init(solid, TopAbs_SHELL); exp0.More(); exp0.Next()) {
569 TopoDS_Shell shell = TopoDS::Shell(exp0.Current());
570 if(_shellTag.IsBound(shell)) {
571 int t = _shellTag.Find(shell);
572 _unbind(shell, t, recursive);
575 for(exp0.Init(solid, TopAbs_FACE); exp0.More(); exp0.Next()) {
576 TopoDS_Face face = TopoDS::Face(exp0.Current());
577 if(_faceTag.IsBound(face)) {
578 int t = _faceTag.Find(face);
579 _unbind(face, t, recursive);
586 void OCC_Internals::_unbind(TopoDS_Shape shape,
int dim,
int tag,
bool recursive)
589 case 0: _unbind(TopoDS::Vertex(shape), tag, recursive);
break;
590 case 1: _unbind(TopoDS::Edge(shape), tag, recursive);
break;
591 case 2: _unbind(TopoDS::Face(shape), tag, recursive);
break;
592 case 3: _unbind(TopoDS::Solid(shape), tag, recursive);
break;
593 case -1: _unbind(TopoDS::Wire(shape), tag, recursive);
break;
594 case -2: _unbind(TopoDS::Shell(shape), tag, recursive);
break;
599 void OCC_Internals::_unbindWithoutChecks(TopoDS_Shape shape)
601 TopExp_Explorer exp0;
602 for(exp0.Init(shape, TopAbs_SOLID); exp0.More(); exp0.Next()) {
603 TopoDS_Solid solid = TopoDS::Solid(exp0.Current());
604 if(_solidTag.IsBound(solid)) {
605 int tag = _solidTag.Find(solid);
606 _solidTag.UnBind(solid);
607 _tagSolid.UnBind(tag);
608 _toRemove.insert(std::make_pair(3, tag));
612 for(exp0.Init(shape, TopAbs_SHELL); exp0.More(); exp0.Next()) {
613 TopoDS_Shell shell = TopoDS::Shell(exp0.Current());
614 if(_shellTag.IsBound(shell)) {
615 int tag = _shellTag.Find(shell);
616 _shellTag.UnBind(shell);
617 _tagShell.UnBind(tag);
618 _toRemove.insert(std::make_pair(-2, tag));
622 for(exp0.Init(shape, TopAbs_FACE); exp0.More(); exp0.Next()) {
623 TopoDS_Face face = TopoDS::Face(exp0.Current());
624 if(_faceTag.IsBound(face)) {
625 int tag = _faceTag.Find(face);
626 _faceTag.UnBind(face);
627 _tagFace.UnBind(tag);
628 _toRemove.insert(std::make_pair(2, tag));
632 for(exp0.Init(shape, TopAbs_WIRE); exp0.More(); exp0.Next()) {
633 TopoDS_Wire wire = TopoDS::Wire(exp0.Current());
634 if(_wireTag.IsBound(wire)) {
635 int tag = _wireTag.Find(wire);
636 _wireTag.UnBind(wire);
637 _tagWire.UnBind(tag);
638 _toRemove.insert(std::make_pair(-1, tag));
642 for(exp0.Init(shape, TopAbs_EDGE); exp0.More(); exp0.Next()) {
643 TopoDS_Edge edge = TopoDS::Edge(exp0.Current());
644 if(_edgeTag.IsBound(edge)) {
645 int tag = _edgeTag.Find(edge);
646 _edgeTag.UnBind(edge);
647 _tagEdge.UnBind(tag);
648 _toRemove.insert(std::make_pair(1, tag));
652 for(exp0.Init(shape, TopAbs_VERTEX); exp0.More(); exp0.Next()) {
653 TopoDS_Vertex vertex = TopoDS::Vertex(exp0.Current());
654 if(_vertexTag.IsBound(vertex)) {
655 int tag = _vertexTag.Find(vertex);
656 _vertexTag.UnBind(vertex);
657 _tagVertex.UnBind(tag);
658 _toRemove.insert(std::make_pair(0, tag));
662 for(
int d = -2; d <= 3; d++) _recomputeMaxTag(d);
665 void OCC_Internals::_unbind()
667 for(
int i = 0; i < 6; i++) _maxTag[i] = 0;
669 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp;
670 exp.Initialize(_tagVertex);
671 for(; exp.More(); exp.Next())
672 _toRemove.insert(std::make_pair(0, exp.Key()));
673 exp.Initialize(_tagEdge);
674 for(; exp.More(); exp.Next())
675 _toRemove.insert(std::make_pair(1, exp.Key()));
676 exp.Initialize(_tagFace);
677 for(; exp.More(); exp.Next())
678 _toRemove.insert(std::make_pair(2, exp.Key()));
679 exp.Initialize(_tagSolid);
680 for(; exp.More(); exp.Next())
681 _toRemove.insert(std::make_pair(3, exp.Key()));
682 exp.Initialize(_tagWire);
683 for(; exp.More(); exp.Next())
684 _toRemove.insert(std::make_pair(-1, exp.Key()));
685 exp.Initialize(_tagShell);
686 for(; exp.More(); exp.Next())
687 _toRemove.insert(std::make_pair(-2, exp.Key()));
706 void OCC_Internals::_multiBind(
const TopoDS_Shape &shape,
int tag,
707 std::vector<std::pair<int, int> > &outDimTags,
708 bool highestDimOnly,
bool recursive,
711 TopExp_Explorer exp0;
713 for(exp0.Init(shape, TopAbs_SOLID); exp0.More(); exp0.Next()) {
714 TopoDS_Solid solid = TopoDS::Solid(exp0.Current());
718 if(_solidTag.IsBound(solid)) {
719 t = _solidTag.Find(solid);
726 Msg::Error(
"Cannot bind multiple volumes to single tag %d", t);
729 if(!exists) _bind(solid, t, recursive);
730 if(!exists || !returnNewOnly)
731 outDimTags.push_back(std::make_pair(3, t));
734 if(highestDimOnly && count)
return;
735 for(exp0.Init(shape, TopAbs_FACE); exp0.More(); exp0.Next()) {
736 TopoDS_Face face = TopoDS::Face(exp0.Current());
740 if(_faceTag.IsBound(face)) {
741 t = _faceTag.Find(face);
748 Msg::Error(
"Cannot bind multiple surfaces to single tag %d", t);
751 if(!exists) _bind(face, t, recursive);
752 if(!exists || !returnNewOnly)
753 outDimTags.push_back(std::make_pair(2, t));
756 if(highestDimOnly && count)
return;
757 for(exp0.Init(shape, TopAbs_EDGE); exp0.More(); exp0.Next()) {
758 TopoDS_Edge edge = TopoDS::Edge(exp0.Current());
762 if(_edgeTag.IsBound(edge)) {
763 t = _edgeTag.Find(edge);
770 Msg::Error(
"Cannot bind multiple curves to single tag %d", t);
773 if(!exists) _bind(edge, t, recursive);
774 if(!exists || !returnNewOnly)
775 outDimTags.push_back(std::make_pair(1, t));
778 if(highestDimOnly && count)
return;
779 for(exp0.Init(shape, TopAbs_VERTEX); exp0.More(); exp0.Next()) {
780 TopoDS_Vertex vertex = TopoDS::Vertex(exp0.Current());
784 if(_vertexTag.IsBound(vertex)) {
785 t = _vertexTag.Find(vertex);
792 Msg::Error(
"Cannot bind multiple points to single tag %d", t);
795 if(!exists) _bind(vertex, t, recursive);
796 if(!exists || !returnNewOnly)
797 outDimTags.push_back(std::make_pair(0, t));
802 bool OCC_Internals::_isBound(
int dim,
int tag)
805 case 0:
return _tagVertex.IsBound(tag);
806 case 1:
return _tagEdge.IsBound(tag);
807 case 2:
return _tagFace.IsBound(tag);
808 case 3:
return _tagSolid.IsBound(tag);
809 case -1:
return _tagWire.IsBound(tag);
810 case -2:
return _tagShell.IsBound(tag);
811 default:
return false;
815 bool OCC_Internals::_isBound(
int dim,
const TopoDS_Shape &shape)
818 case 0:
return _vertexTag.IsBound(shape);
819 case 1:
return _edgeTag.IsBound(shape);
820 case 2:
return _faceTag.IsBound(shape);
821 case 3:
return _solidTag.IsBound(shape);
822 case -1:
return _wireTag.IsBound(shape);
823 case -2:
return _shellTag.IsBound(shape);
824 default:
return false;
828 TopoDS_Shape OCC_Internals::_find(
int dim,
int tag)
831 case 0:
return _tagVertex.Find(tag);
832 case 1:
return _tagEdge.Find(tag);
833 case 2:
return _tagFace.Find(tag);
834 case 3:
return _tagSolid.Find(tag);
835 case -1:
return _tagWire.Find(tag);
836 case -2:
return _tagShell.Find(tag);
837 default:
return TopoDS_Shape();
841 int OCC_Internals::_find(
int dim,
const TopoDS_Shape &shape)
844 case 0:
return _vertexTag.Find(shape);
845 case 1:
return _edgeTag.Find(shape);
846 case 2:
return _faceTag.Find(shape);
847 case 3:
return _solidTag.Find(shape);
848 case -1:
return _wireTag.Find(shape);
849 case -2:
return _shellTag.Find(shape);
857 if(tag >= 0 && _tagVertex.IsBound(tag)) {
858 Msg::Error(
"OpenCASCADE point with tag %d already exists", tag);
861 TopoDS_Vertex result;
863 gp_Pnt aPnt(x, y,
z);
864 BRepBuilderAPI_MakeVertex v(aPnt);
871 }
catch(Standard_Failure &err) {
872 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
875 if(meshSize > 0 && meshSize <
MAX_LC)
876 _attributes->insert(
new OCCAttributes(0, result, meshSize));
878 _bind(result, tag,
true);
884 if(tag >= 0 && _tagEdge.IsBound(tag)) {
885 Msg::Error(
"OpenCASCADE curve with tag %d already exists", tag);
888 if(!_tagVertex.IsBound(startTag)) {
889 Msg::Error(
"Unknown OpenCASCADE point with tag %d", startTag);
892 if(!_tagVertex.IsBound(endTag)) {
893 Msg::Error(
"Unknown OpenCASCADE point with tag %d", endTag);
896 if(startTag == endTag) {
897 Msg::Error(
"Start and end points of line should be different");
902 TopoDS_Vertex start = TopoDS::Vertex(_tagVertex.Find(startTag));
903 TopoDS_Vertex end = TopoDS::Vertex(_tagVertex.Find(endTag));
904 BRepBuilderAPI_MakeEdge e(start, end);
911 }
catch(Standard_Failure &err) {
912 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
916 _bind(result, tag,
true);
922 if(pointTags.size() == 2)
return addLine(tag, pointTags[0], pointTags[1]);
925 Msg::Error(
"OpenCASCADE polyline currently not supported");
932 if(tag >= 0 && _tagEdge.IsBound(tag)) {
933 Msg::Error(
"OpenCASCADE curve with tag %d already exists", tag);
936 if(!_tagVertex.IsBound(startTag)) {
937 Msg::Error(
"Unknown OpenCASCADE point with tag %d", startTag);
940 if(!_tagVertex.IsBound(centerTag)) {
941 Msg::Error(
"Unknown OpenCASCADE point with tag %d", centerTag);
944 if(!_tagVertex.IsBound(endTag)) {
945 Msg::Error(
"Unknown OpenCASCADE point with tag %d", endTag);
950 TopoDS_Vertex start = TopoDS::Vertex(_tagVertex.Find(startTag));
951 TopoDS_Vertex center = TopoDS::Vertex(_tagVertex.Find(centerTag));
952 TopoDS_Vertex end = TopoDS::Vertex(_tagVertex.Find(endTag));
953 gp_Pnt aP1 = BRep_Tool::Pnt(start);
954 gp_Pnt aP2 = BRep_Tool::Pnt(center);
955 gp_Pnt aP3 = BRep_Tool::Pnt(end);
956 Standard_Real Radius = aP1.Distance(aP2);
960 p = gce_MakePln(aP1, aP2, aP3).Value();
963 Msg::Info(
"Could not make plane from 3 points - assuming z=%g", aP2.Z());
964 gp_Dir N_dir(0., 0., 1.);
965 p = gce_MakePln(aP2, N_dir).Value();
969 gce_MakeCirc MC(aP2, p, Radius);
974 const gp_Circ &Circ = MC.Value();
975 Standard_Real Alpha1 = ElCLib::Parameter(Circ, aP1);
976 Standard_Real Alpha2 = ElCLib::Parameter(Circ, aP3);
977 Handle(Geom_Circle) C =
new Geom_Circle(Circ);
978 Handle(Geom_TrimmedCurve) arc =
979 new Geom_TrimmedCurve(C, Alpha1, Alpha2,
false);
980 BRepBuilderAPI_MakeEdge e(arc, start, end);
987 }
catch(Standard_Failure &err) {
988 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
992 _bind(result, tag,
true);
997 int majorTag,
int endTag)
999 if(tag >= 0 && _tagEdge.IsBound(tag)) {
1000 Msg::Error(
"OpenCASCADE curve with tag %d already exists", tag);
1003 if(!_tagVertex.IsBound(startTag)) {
1004 Msg::Error(
"Unknown OpenCASCADE point with tag %d", startTag);
1007 if(!_tagVertex.IsBound(centerTag)) {
1008 Msg::Error(
"Unknown OpenCASCADE point with tag %d", centerTag);
1011 if(!_tagVertex.IsBound(majorTag)) {
1012 Msg::Error(
"Unknown OpenCASCADE point with tag %d", majorTag);
1015 if(!_tagVertex.IsBound(endTag)) {
1016 Msg::Error(
"Unknown OpenCASCADE point with tag %d", endTag);
1022 TopoDS_Vertex start = TopoDS::Vertex(_tagVertex.Find(startTag));
1023 TopoDS_Vertex center = TopoDS::Vertex(_tagVertex.Find(centerTag));
1024 TopoDS_Vertex major = TopoDS::Vertex(_tagVertex.Find(majorTag));
1025 TopoDS_Vertex end = TopoDS::Vertex(_tagVertex.Find(endTag));
1026 gp_Pnt startPnt = BRep_Tool::Pnt(start);
1027 gp_Pnt centerPnt = BRep_Tool::Pnt(center);
1028 gp_Pnt majorPnt = BRep_Tool::Pnt(major);
1029 gp_Pnt endPnt = BRep_Tool::Pnt(end);
1030 gp_XYZ x1 = startPnt.XYZ() - centerPnt.XYZ();
1031 gp_XYZ x2 = endPnt.XYZ() - centerPnt.XYZ();
1032 gp_Dir u = majorPnt.XYZ() - centerPnt.XYZ();
1034 if(!u.IsParallel(x1, 1e-6))
1035 v = x1 - x1.Dot(u.XYZ()) * u.XYZ();
1036 else if(!u.IsParallel(x2, 1e-6))
1037 v = x2 - x2.Dot(u.XYZ()) * u.XYZ();
1039 Msg::Error(
"The points do not define an ellipse");
1042 Standard_Real x1u =
Square(x1.Dot(u.XYZ()));
1043 Standard_Real x1v =
Square(x1.Dot(v.XYZ()));
1044 Standard_Real x2u =
Square(x2.Dot(u.XYZ()));
1045 Standard_Real x2v =
Square(x2.Dot(v.XYZ()));
1046 if(IsEqual(x1u, x2u) || IsEqual(x1v, x2v)) {
1047 Msg::Error(
"The points do not define an ellipse");
1050 Standard_Real
a2 = (x1v * x2u - x1u * x2v) / (x1v - x2v);
1051 Standard_Real b2 = (x1u * x2v - x1v * x2u) / (x1u - x2u);
1052 if(
a2 <= 0.0 || b2 <= 0.0) {
1053 Msg::Error(
"The points do not define an ellipse");
1062 Axes = gp_Ax2(centerPnt, u ^ v, u);
1065 Msg::Warning(
"Major radius smaller than minor radius");
1068 Axes = gp_Ax2(centerPnt, v ^ u, v);
1070 gce_MakeElips ME(Axes, a, b);
1075 const gp_Elips &Elips = ME.Value();
1076 Standard_Real Alpha1 = ElCLib::Parameter(Elips, startPnt);
1077 Standard_Real Alpha2 = ElCLib::Parameter(Elips, endPnt);
1078 Handle(Geom_Ellipse) E =
new Geom_Ellipse(Elips);
1079 Handle(Geom_TrimmedCurve) arc;
1080 if((Alpha2 > Alpha1 && Alpha2 - Alpha1 < M_PI) || Alpha1 - Alpha2 > M_PI)
1081 arc =
new Geom_TrimmedCurve(E, Alpha1, Alpha2,
true);
1083 arc =
new Geom_TrimmedCurve(E, Alpha2, Alpha1,
false);
1084 BRepBuilderAPI_MakeEdge e(arc, start, end);
1091 }
catch(Standard_Failure &err) {
1092 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
1096 _bind(result, tag,
true);
1101 double angle1,
double angle2,
1102 const std::vector<double> &N,
1103 const std::vector<double> &V)
1105 if(tag >= 0 && _tagEdge.IsBound(tag)) {
1106 Msg::Error(
"OpenCASCADE curve with tag %d already exists", tag);
1110 Msg::Error(
"Circle radius should be positive");
1117 gp_Pnt center(x, y,
z);
1118 if(N.size() == 3 && V.size() == 3) {
1119 gp_Dir N_dir(N[0], N[1], N[2]);
1120 gp_Dir x_dir(V[0], V[1], V[2]);
1121 gp_Ax2 axis(center, N_dir, x_dir);
1122 circ.SetPosition(axis);
1124 else if(N.size() == 3) {
1125 gp_Dir N_dir(N[0], N[1], N[2]);
1126 gp_Ax2 axis(center, N_dir);
1127 circ.SetPosition(axis);
1130 gp_Dir N_dir(0., 0., 1.);
1131 gp_Dir x_dir(1., 0., 0.);
1132 gp_Ax2 axis(center, N_dir, x_dir);
1133 circ.SetPosition(axis);
1136 if(angle1 == 0. && angle2 == 2 * M_PI) {
1137 result = BRepBuilderAPI_MakeEdge(circ);
1140 Handle(Geom_Circle) C =
new Geom_Circle(circ);
1141 Handle(Geom_TrimmedCurve) arc =
1142 new Geom_TrimmedCurve(C, angle1, angle2,
true);
1143 BRepBuilderAPI_MakeEdge e(arc);
1150 }
catch(Standard_Failure &err) {
1151 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
1155 _bind(result, tag,
true);
1160 double rx,
double ry,
double angle1,
1161 double angle2,
const std::vector<double> &N,
1162 const std::vector<double> &V)
1164 if(tag >= 0 && _tagEdge.IsBound(tag)) {
1165 Msg::Error(
"OpenCASCADE curve with tag %d already exists", tag);
1169 Msg::Error(
"Major radius rx should be larger than minor radius ry");
1172 if(ry <= 0 || rx <= 0) {
1173 Msg::Error(
"Ellipse radii should be positive");
1180 gp_Pnt center(x, y,
z);
1181 if(N.size() == 3 && V.size() == 3) {
1182 gp_Dir N_dir(N[0], N[1], N[2]);
1183 gp_Dir x_dir(V[0], V[1], V[2]);
1184 gp_Ax2 axis(center, N_dir, x_dir);
1185 el.SetPosition(axis);
1187 else if(N.size() == 3) {
1188 gp_Dir N_dir(N[0], N[1], N[2]);
1189 gp_Ax2 axis(center, N_dir);
1190 el.SetPosition(axis);
1193 gp_Dir N_dir(0., 0., 1.);
1194 gp_Dir x_dir(1., 0., 0.);
1195 gp_Ax2 axis(center, N_dir, x_dir);
1196 el.SetPosition(axis);
1198 el.SetMajorRadius(rx);
1199 el.SetMinorRadius(ry);
1200 if(angle1 == 0 && angle2 == 2 * M_PI) {
1201 result = BRepBuilderAPI_MakeEdge(el);
1204 Handle(Geom_Ellipse) E =
new Geom_Ellipse(el);
1205 Handle(Geom_TrimmedCurve) arc =
1206 new Geom_TrimmedCurve(E, angle1, angle2,
true);
1207 BRepBuilderAPI_MakeEdge e(arc);
1214 }
catch(Standard_Failure &err) {
1215 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
1219 _bind(result, tag,
true);
1223 void debugBSpline(
const Handle(Geom_BSplineCurve) & curve)
1225 int degree = curve->Degree();
1226 bool periodic = curve->IsPeriodic();
1227 bool rational = curve->IsRational();
1229 int npoles = curve->NbPoles();
1230 TColgp_Array1OfPnt poles(1, npoles);
1231 curve->Poles(poles);
1233 TColStd_Array1OfReal weights(1, npoles);
1234 curve->Weights(weights);
1236 int nknots = curve->NbKnots();
1237 TColStd_Array1OfReal knots(1, nknots);
1238 curve->Knots(knots);
1240 TColStd_Array1OfInteger mults(1, nknots);
1241 curve->Multiplicities(mults);
1243 printf(
"BSpline: degree %d, periodic %d, rational %d\n", degree, periodic,
1246 for(
int i = 1; i <= npoles; i++)
1247 printf(
" %d (%g, %g, %g) weight %g\n", i, poles(i).X(), poles(i).Y(),
1248 poles(i).Z(), weights(i));
1250 for(
int i = 1; i <= nknots; i++)
1251 printf(
" %d (%g) mult %d\n", i, knots(i), mults(i));
1254 bool OCC_Internals::_addBSpline(
int &tag,
const std::vector<int> &pointTags,
1255 int mode,
const int degree,
1256 const std::vector<double> &weights,
1257 const std::vector<double> &knots,
1258 const std::vector<int> &multiplicities,
1259 const std::vector<SVector3> &tangents)
1261 if(tag >= 0 && _tagEdge.IsBound(tag)) {
1262 Msg::Error(
"OpenCASCADE curve with tag %d already exists", tag);
1265 if(pointTags.size() < 2) {
1266 Msg::Error(
"Number of control points should be at least 2");
1272 TColgp_Array1OfPnt ctrlPoints(1, pointTags.size());
1273 TopoDS_Vertex start, end;
1274 for(std::size_t i = 0; i < pointTags.size(); i++) {
1275 if(!_tagVertex.IsBound(pointTags[i])) {
1276 Msg::Error(
"Unknown OpenCASCADE point with tag %d", pointTags[i]);
1279 TopoDS_Vertex vertex = TopoDS::Vertex(_tagVertex.Find(pointTags[i]));
1280 ctrlPoints.SetValue(i + 1, BRep_Tool::Pnt(vertex));
1281 if(i == 0) start = vertex;
1282 if(i == pointTags.size() - 1) end = vertex;
1284 bool periodic = (pointTags.front() == pointTags.back());
1288 int np = periodic ? ctrlPoints.Length() - 1 : ctrlPoints.Length();
1289 Handle(TColgp_HArray1OfPnt) p =
new TColgp_HArray1OfPnt(1, np);
1290 for(
int i = 1; i <= np; i++) p->SetValue(i, ctrlPoints(i));
1291 GeomAPI_Interpolate intp(p, periodic,
CTX::instance()->geom.tolerance);
1292 if(tangents.size() == 2) {
1293 gp_Vec t1(tangents[0].x(), tangents[0].y(), tangents[0].
z());
1294 gp_Vec tN(tangents[1].x(), tangents[1].y(), tangents[1].
z());
1297 else if(tangents.size() == pointTags.size()) {
1298 TColgp_Array1OfVec Tangents(1, tangents.size());
1299 Handle(TColStd_HArray1OfBoolean) TangentFlags =
1300 new TColStd_HArray1OfBoolean(1, tangents.size());
1301 for(std::size_t i = 1; i <= tangents.size(); i++) {
1302 gp_Vec t(tangents[i - 1].x(), tangents[i - 1].y(), tangents[i - 1].
z());
1303 Tangents.SetValue(i, t);
1304 if(tangents[i - 1].
normSq() < 1e-12) {
1305 TangentFlags->SetValue(i, Standard_False);
1308 TangentFlags->SetValue(i, Standard_True);
1311 intp.Load(Tangents, TangentFlags);
1313 else if(!tangents.empty()) {
1314 Msg::Warning(
"Wrong number of tangent constraints for spline (%lu != %lu)",
1315 tangents.size(), pointTags.size());
1318 if(!intp.IsDone()) {
1322 Handle(Geom_BSplineCurve) curve = intp.Curve();
1323 BRepBuilderAPI_MakeEdge e(curve, start, end);
1330 else if(mode == 1) {
1332 Handle(Geom_BezierCurve) curve =
new Geom_BezierCurve(ctrlPoints);
1333 BRepBuilderAPI_MakeEdge e(curve, start, end);
1340 else if(mode == 2) {
1344 Msg::Error(
"BSpline degree (%d) should be >= 0", degree);
1347 if(weights.size() != pointTags.size()) {
1348 Msg::Error(
"Number of BSpline weights (%d) and control points (%d) "
1350 weights.size(), pointTags.size());
1353 if(knots.size() != multiplicities.size()) {
1355 "Number of BSpline knots (%d) and multiplicities (%d) should be "
1357 knots.size(), multiplicities.size());
1360 if(knots.size() < 2) {
1361 Msg::Error(
"Number of BSpline knots (%d) should be >= 2", knots.size());
1364 for(std::size_t i = 0; i < knots.size() - 1; i++) {
1365 if(knots[i] >= knots[i + 1]) {
1366 Msg::Error(
"BSpline knots should be increasing: knot %d (%g) > "
1368 i, knots[i], i + 1, knots[i + 1]);
1372 for(std::size_t i = 0; i < multiplicities.size(); i++) {
1373 if(multiplicities[i] < 1) {
1374 Msg::Error(
"BSpline multiplicities should be >= 1");
1377 if(i != 0 && i != multiplicities.size() - 1 &&
1378 multiplicities[i] > degree) {
1380 "BSpline interior knot multiplicities should be <= degree");
1383 if((i == 0 || i == multiplicities.size() - 1) &&
1384 multiplicities[i] > degree + 1) {
1385 Msg::Error(
"BSpline end knot multiplicities should be <= degree + 1");
1390 if(multiplicities.front() != multiplicities.back()) {
1392 "Periodic BSpline end knot multiplicies (%d and %d) should "
1394 multiplicities.front(), multiplicities.back());
1397 const auto sum = std::accumulate(
1398 begin(multiplicities), std::prev(std::end(multiplicities)),
1400 [](std::size_t
const partial_sum,
int const multiplicity) {
1401 return partial_sum + multiplicity;
1403 if(pointTags.size() - 1 != sum) {
1404 Msg::Error(
"Number of control points - 1 for periodic BSpline should "
1405 "be equal to the sum of multiplicities for all knots "
1406 "except the first (or last)");
1411 const auto sum = std::accumulate(
1412 begin(multiplicities), std::end(multiplicities), std::size_t(0),
1413 [](std::size_t
const partial_sum,
int const multiplicity) {
1414 return partial_sum + multiplicity;
1416 if(pointTags.size() != sum - degree - 1) {
1417 Msg::Error(
"Number of control points for non-periodic BSpline should "
1418 "be equal to the sum of multiplicities - degree - 1");
1422 int np = (periodic ? ctrlPoints.Length() - 1 : ctrlPoints.Length());
1423 TColgp_Array1OfPnt p(1, np);
1424 TColStd_Array1OfReal w(1, np);
1425 for(
int i = 1; i <= np; i++) {
1426 p.SetValue(i, ctrlPoints(i));
1427 w.SetValue(i, weights[i - 1]);
1429 TColStd_Array1OfReal k(1, knots.size());
1430 for(std::size_t i = 0; i < knots.size(); i++) k.SetValue(i + 1, knots[i]);
1431 TColStd_Array1OfInteger m(1, multiplicities.size());
1432 for(std::size_t i = 0; i < multiplicities.size(); i++)
1433 m.SetValue(i + 1, multiplicities[i]);
1434 Handle(Geom_BSplineCurve) curve =
1435 new Geom_BSplineCurve(p, w, k, m, degree, periodic);
1436 if(curve->StartPoint().IsEqual(BRep_Tool::Pnt(start),
1438 curve->EndPoint().IsEqual(BRep_Tool::Pnt(end),
1440 !curve->StartPoint().IsEqual(curve->EndPoint(),
1442 BRepBuilderAPI_MakeEdge e(curve, start, end);
1444 Msg::Error(
"Could not create BSpline curve (with end points)");
1450 BRepBuilderAPI_MakeEdge e(curve);
1452 Msg::Error(
"Could not create BSpline curve (without end points)");
1459 double lc = _attributes->getMeshSize(0, start);
1460 if(lc > 0 && lc <
MAX_LC) {
1461 TopExp_Explorer exp0;
1462 for(exp0.Init(result, TopAbs_VERTEX); exp0.More(); exp0.Next()) {
1463 TopoDS_Vertex vertex = TopoDS::Vertex(exp0.Current());
1464 _attributes->insert(
new OCCAttributes(0, vertex, lc));
1469 }
catch(Standard_Failure &err) {
1470 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
1474 _bind(result, tag,
true);
1479 const std::vector<SVector3> &tangents)
1481 std::vector<double> weights;
1482 std::vector<double> knots;
1483 std::vector<int> multiplicities;
1484 return _addBSpline(tag, pointTags, 0, -1, weights, knots, multiplicities,
1490 return _addBSpline(tag, pointTags, 1);
1495 const std::vector<double> &weights,
1496 const std::vector<double> &knots,
1497 const std::vector<int> &multiplicities)
1499 int np = pointTags.size();
1501 Msg::Error(
"BSpline curve requires at least 2 control points");
1505 std::vector<double> w(weights), k(knots);
1506 std::vector<int> m(multiplicities);
1510 if(d > np - 1) d = np - 1;
1512 if(w.empty()) w.resize(np, 1);
1515 bool periodic = (pointTags.front() == pointTags.back());
1517 int sumOfAllMult = np + d + 1;
1518 int numKnots = sumOfAllMult - 2 * d;
1520 Msg::Error(
"Not enough control points for building BSpline of "
1526 for(std::size_t i = 0; i < k.size(); i++) k[i] = i;
1527 m.resize(numKnots, 1);
1533 for(std::size_t i = 0; i < k.size(); i++) k[i] = i;
1534 m.resize(k.size(), 1);
1537 return _addBSpline(tag, pointTags, 2, d, w, k, m);
1543 if(tag >= 0 && _tagWire.IsBound(tag)) {
1544 Msg::Error(
"OpenCASCADE wire or curve loop with tag %d already exists", tag);
1553 BRepBuilderAPI_MakeWire w;
1555 for(std::size_t i = 0; i < curveTags.size(); i++) {
1559 int t = std::abs(curveTags[i]);
1560 if(!_tagEdge.IsBound(t)) {
1561 Msg::Error(
"Unknown OpenCASCADE curve with tag %d", t);
1564 TopoDS_Edge edge = TopoDS::Edge(_tagEdge.Find(t));
1573 if(checkClosed && !wire.Closed()) {
1578 _bind(wire, tag,
true);
1579 }
catch(Standard_Failure &err) {
1580 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
1588 return addWire(tag, curveTags,
true);
1591 static bool makeRectangle(TopoDS_Face &result,
double x,
double y,
double z,
1592 double dx,
double dy,
double roundedRadius)
1595 Msg::Error(
"Rectangle with zero width or height");
1600 if(roundedRadius <= 0.) {
1601 double x1 = x, y1 = y, z1 =
z, x2 = x1 + dx, y2 = y1 + dy;
1602 TopoDS_Vertex v1 = BRepBuilderAPI_MakeVertex(gp_Pnt(x1, y1, z1));
1603 TopoDS_Vertex v2 = BRepBuilderAPI_MakeVertex(gp_Pnt(x2, y1, z1));
1604 TopoDS_Vertex v3 = BRepBuilderAPI_MakeVertex(gp_Pnt(x2, y2, z1));
1605 TopoDS_Vertex v4 = BRepBuilderAPI_MakeVertex(gp_Pnt(x1, y2, z1));
1606 TopoDS_Edge e1 = BRepBuilderAPI_MakeEdge(v1, v2);
1607 TopoDS_Edge e2 = BRepBuilderAPI_MakeEdge(v2, v3);
1608 TopoDS_Edge e3 = BRepBuilderAPI_MakeEdge(v3, v4);
1609 TopoDS_Edge e4 = BRepBuilderAPI_MakeEdge(v4, v1);
1610 wire = BRepBuilderAPI_MakeWire(e1, e2, e3, e4);
1613 double x1, y1, z1 =
z, x2, y2;
1614 double r = roundedRadius;
1631 TopoDS_Vertex v1 = BRepBuilderAPI_MakeVertex(gp_Pnt(x1 + r, y1, z1));
1632 TopoDS_Vertex v2 = BRepBuilderAPI_MakeVertex(gp_Pnt(x2 - r, y1, z1));
1633 TopoDS_Vertex v3 = BRepBuilderAPI_MakeVertex(gp_Pnt(x2, y1 + r, z1));
1634 TopoDS_Vertex v4 = BRepBuilderAPI_MakeVertex(gp_Pnt(x2, y2 - r, z1));
1635 TopoDS_Vertex v5 = BRepBuilderAPI_MakeVertex(gp_Pnt(x2 - r, y2, z1));
1636 TopoDS_Vertex v6 = BRepBuilderAPI_MakeVertex(gp_Pnt(x1 + r, y2, z1));
1637 TopoDS_Vertex v7 = BRepBuilderAPI_MakeVertex(gp_Pnt(x1, y2 - r, z1));
1638 TopoDS_Vertex v8 = BRepBuilderAPI_MakeVertex(gp_Pnt(x1, y1 + r, z1));
1639 TopoDS_Edge e1 = BRepBuilderAPI_MakeEdge(v1, v2);
1640 TopoDS_Edge e2 = BRepBuilderAPI_MakeEdge(v3, v4);
1641 TopoDS_Edge e3 = BRepBuilderAPI_MakeEdge(v5, v6);
1642 TopoDS_Edge e4 = BRepBuilderAPI_MakeEdge(v7, v8);
1643 gp_Pnt
c1(x1 + r, y1 + r, z1);
1644 gp_Pnt c2(x2 - r, y1 + r, z1);
1645 gp_Pnt c3(x2 - r, y2 - r, z1);
1646 gp_Pnt c4(x1 + r, y2 - r, z1);
1647 gp_Pln plane = gce_MakePln(
c1, c2, c3).Value();
1648 gp_Circ circ1 = gce_MakeCirc(
c1, plane, r).Value();
1649 gp_Circ circ2 = gce_MakeCirc(c2, plane, r).Value();
1650 gp_Circ circ3 = gce_MakeCirc(c3, plane, r).Value();
1651 gp_Circ circ4 = gce_MakeCirc(c4, plane, r).Value();
1652 Handle(Geom_Circle) circle1 =
new Geom_Circle(circ1);
1653 Handle(Geom_Circle) circle2 =
new Geom_Circle(circ2);
1654 Handle(Geom_Circle) circle3 =
new Geom_Circle(circ3);
1655 Handle(Geom_Circle) circle4 =
new Geom_Circle(circ4);
1656 Handle(Geom_TrimmedCurve) arc1 =
1657 new Geom_TrimmedCurve(circle1, -M_PI, -M_PI / 2.,
true);
1658 Handle(Geom_TrimmedCurve) arc2 =
1659 new Geom_TrimmedCurve(circle2, -M_PI / 2, 0,
true);
1660 Handle(Geom_TrimmedCurve) arc3 =
1661 new Geom_TrimmedCurve(circle3, 0, M_PI / 2,
true);
1662 Handle(Geom_TrimmedCurve) arc4 =
1663 new Geom_TrimmedCurve(circle4, M_PI / 2, M_PI,
true);
1664 TopoDS_Edge ce1 = BRepBuilderAPI_MakeEdge(arc1, v8, v1);
1665 TopoDS_Edge ce2 = BRepBuilderAPI_MakeEdge(arc2, v2, v3);
1666 TopoDS_Edge ce3 = BRepBuilderAPI_MakeEdge(arc3, v4, v5);
1667 TopoDS_Edge ce4 = BRepBuilderAPI_MakeEdge(arc4, v6, v7);
1668 BRepBuilderAPI_MakeWire w;
1679 result = BRepBuilderAPI_MakeFace(wire);
1680 }
catch(Standard_Failure &err) {
1681 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
1688 double dx,
double dy,
double roundedRadius)
1690 if(tag >= 0 && _tagFace.IsBound(tag)) {
1691 Msg::Error(
"OpenCASCADE surface with tag %d already exists", tag);
1695 if(!makeRectangle(result, x, y,
z, dx, dy, roundedRadius))
return false;
1697 _bind(result, tag,
true);
1701 static bool makeDisk(TopoDS_Face &result,
double xc,
double yc,
double zc,
1702 double rx,
double ry,
1703 const std::vector<double> &N = std::vector<double>(),
1704 const std::vector<double> &V = std::vector<double>())
1707 Msg::Error(
"Major radius rx should be larger than minor radius ry");
1710 if(ry <= 0 || rx <= 0) {
1711 Msg::Error(
"Disk radius should be positive");
1716 gp_Pnt center(xc, yc, zc);
1717 if(N.size() == 3 && V.size() == 3) {
1718 gp_Dir N_dir(N[0], N[1], N[2]);
1719 gp_Dir x_dir(V[0], V[1], V[2]);
1720 gp_Ax2 axis(center, N_dir, x_dir);
1721 el.SetPosition(axis);
1723 else if(N.size() == 3) {
1724 gp_Dir N_dir(N[0], N[1], N[2]);
1725 gp_Ax2 axis(center, N_dir);
1726 el.SetPosition(axis);
1729 gp_Dir N_dir(0., 0., 1.);
1730 gp_Dir x_dir(1., 0., 0.);
1731 gp_Ax2 axis(center, N_dir, x_dir);
1732 el.SetPosition(axis);
1734 el.SetMajorRadius(rx);
1735 el.SetMinorRadius(ry);
1736 TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(el);
1737 TopoDS_Wire wire = BRepBuilderAPI_MakeWire(edge);
1738 result = BRepBuilderAPI_MakeFace(wire);
1739 }
catch(Standard_Failure &err) {
1740 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
1747 double rx,
double ry,
const std::vector<double> &N,
1748 const std::vector<double> &V)
1750 if(tag >= 0 && _tagFace.IsBound(tag)) {
1751 Msg::Error(
"OpenCASCADE surface with tag %d already exists", tag);
1755 if(!makeDisk(result, xc, yc, zc, rx, ry, N, V))
return false;
1757 _bind(result, tag,
true);
1763 if(tag >= 0 && _tagFace.IsBound(tag)) {
1764 Msg::Error(
"OpenCASCADE surface with tag %d already exists", tag);
1768 std::vector<TopoDS_Wire> wires;
1769 for(std::size_t i = 0; i < wireTags.size(); i++) {
1772 int wireTag = std::abs(wireTags[i]);
1773 if(!_tagWire.IsBound(wireTag)) {
1774 Msg::Error(
"Unknown OpenCASCADE curve loop with tag %d", wireTag);
1777 TopoDS_Wire wire = TopoDS::Wire(_tagWire.Find(wireTag));
1778 wires.push_back(wire);
1782 if(wires.size() == 0) {
1783 Msg::Error(
"Plane surface requires at least one curve loop");
1788 BRepBuilderAPI_MakeFace
f(wires[0]);
1789 for(std::size_t i = 1; i < wires.size(); i++) {
1791 TopoDS_Wire w = wires[i];
1792 w.Orientation(TopAbs_REVERSED);
1803 ShapeFix_Face fix(result);
1805 result = fix.Face();
1807 }
catch(Standard_Failure &err) {
1808 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
1813 _bind(result, tag,
true);
1818 const std::vector<int> &pointTags,
1819 const std::vector<int> &surfaceTags,
1820 const std::vector<int> &surfaceContinuity,
1822 const int numPointsOnCurves,
1824 const bool anisotropic,
1827 const double tolAng,
1828 const double tolCurv,
1829 const int maxDegree,
1830 const int maxSegments)
1832 if(tag >= 0 && _tagFace.IsBound(tag)) {
1833 Msg::Error(
"OpenCASCADE surface with tag %d already exists", tag);
1839 BRepOffsetAPI_MakeFilling
f(degree, numPointsOnCurves, numIter, anisotropic,
1840 tol2d, tol3d, tolAng, tolCurv, maxDegree,
1843 if(!_tagWire.IsBound(wireTag)) {
1844 Msg::Error(
"Unknown OpenCASCADE curve loop with tag %d", wireTag);
1847 TopoDS_Wire wire = TopoDS::Wire(_tagWire.Find(wireTag));
1848 BRepTools_WireExplorer exp0;
1850 for(exp0.Init(wire); exp0.More(); exp0.Next()) {
1851 TopoDS_Edge edge = exp0.Current();
1852 if(i < surfaceTags.size()) {
1854 if(!_tagFace.IsBound(surfaceTags[i])) {
1855 Msg::Error(
"Unknown OpenCASCADE surface with tag %d", surfaceTags[i]);
1858 TopoDS_Face face = TopoDS::Face(_tagFace.Find(surfaceTags[i]));
1859 if(i < surfaceContinuity.size() && surfaceContinuity[i] == 2)
1860 f.Add(edge, face, GeomAbs_G2);
1862 f.Add(edge, face, GeomAbs_G1);
1865 f.Add(edge, GeomAbs_C0);
1870 for(std::size_t i = 0; i < pointTags.size(); i++) {
1871 if(!_tagVertex.IsBound(pointTags[i])) {
1872 Msg::Error(
"Unknown OpenCASCADE point with tag %d", pointTags[i]);
1875 TopoDS_Vertex vertex = TopoDS::Vertex(_tagVertex.Find(pointTags[i]));
1876 f.Add(BRep_Tool::Pnt(vertex));
1880 Msg::Error(
"Could not build surface filling");
1885 TopoDS_Face tmp = TopoDS::Face(
f.Shape());
1886 Handle(Geom_Surface) s = BRep_Tool::Surface(tmp);
1891 bool reverse = sff.FixOrientation();
1892 result = sff.Face();
1893 if(reverse) result.Orientation(TopAbs_REVERSED);
1894 }
catch(Standard_Failure &err) {
1895 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
1900 _bind(result, tag,
true);
1905 const std::string &type)
1907 if(tag >= 0 && _tagFace.IsBound(tag)) {
1908 Msg::Error(
"OpenCASCADE surface with tag %d already exists", tag);
1918 GeomFill_BSplineCurves
f;
1919 if(!_tagWire.IsBound(wireTag)) {
1920 Msg::Error(
"Unknown OpenCASCADE curve loop with tag %d", wireTag);
1923 TopoDS_Wire wire = TopoDS::Wire(_tagWire.Find(wireTag));
1924 std::vector<Handle(Geom_BSplineCurve)> bsplines;
1925 BRepTools_WireExplorer exp0;
1926 for(exp0.Init(wire); exp0.More(); exp0.Next()) {
1927 TopoDS_Edge edge = exp0.Current();
1929 Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, s0, s1);
1930 Handle(Geom_BSplineCurve) bspline;
1931 bool approx =
false;
1932 if(curve->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve)) {
1933 bspline = Handle(Geom_BSplineCurve)::DownCast(curve);
1934 if(bspline->Degree() < degree) approx =
true;
1942 BRepBuilderAPI_NurbsConvert nurbs(edge);
1943 TopoDS_Edge edge2 = TopoDS::Edge(nurbs.ModifiedShape(edge));
1944 curve = BRep_Tool::Curve(edge2, s0, s1);
1945 if(curve->DynamicType() != STANDARD_TYPE(Geom_BSplineCurve)) {
1946 Msg::Error(
"Could not convert bounding curve for BSpline filling to "
1950 bspline = Handle(Geom_BSplineCurve)::DownCast(curve);
1951 if(bspline->Degree() < degree)
1952 bspline->IncreaseDegree(degree);
1955 TopoDS_Vertex v0 = TopExp::FirstVertex(edge);
1956 TopoDS_Vertex v1 = TopExp::LastVertex(edge);
1957 if(!bspline->StartPoint().IsEqual(BRep_Tool::Pnt(v0), tol) ||
1958 !bspline->EndPoint().IsEqual(BRep_Tool::Pnt(v1), tol)) {
1959 bspline = GeomConvert::SplitBSplineCurve(bspline, s0, s1, 1e-6);
1961 bsplines.push_back(bspline);
1964 GeomFill_FillingStyle t;
1965 if(type ==
"Stretch")
1966 t = GeomFill_StretchStyle;
1967 else if(type ==
"Coons")
1968 t = GeomFill_CoonsStyle;
1970 t = GeomFill_CurvedStyle;
1972 if(bsplines.size() == 4) {
1973 f.Init(bsplines[0], bsplines[1], bsplines[2], bsplines[3], t);
1975 else if(bsplines.size() == 3) {
1978 if(!bsplines[0]->EndPoint().IsEqual(bsplines[1]->StartPoint(), tol) &&
1979 !bsplines[0]->EndPoint().IsEqual(bsplines[1]->EndPoint(), tol)) {
1980 f.Init(bsplines[0], bsplines[2], bsplines[1], t);
1983 f.Init(bsplines[0], bsplines[1], bsplines[2], t);
1986 else if(bsplines.size() == 2) {
1987 f.Init(bsplines[0], bsplines[1], t);
1991 "BSpline filling requires between 2 and 4 boundary BSpline curves");
1995 sff.Init(
f.Surface(), tol);
1998 bool reverse = sff.FixOrientation();
1999 result = sff.Face();
2000 if(reverse) result.Orientation(TopAbs_REVERSED);
2001 }
catch(Standard_Failure &err) {
2002 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2007 _bind(result, tag,
true);
2012 const std::string &type)
2014 if(tag >= 0 && _tagFace.IsBound(tag)) {
2015 Msg::Error(
"OpenCASCADE surface with tag %d already exists", tag);
2021 GeomFill_BezierCurves
f;
2022 if(!_tagWire.IsBound(wireTag)) {
2023 Msg::Error(
"Unknown OpenCASCADE curve loop with tag %d", wireTag);
2026 TopoDS_Wire wire = TopoDS::Wire(_tagWire.Find(wireTag));
2027 BRepTools_WireExplorer exp0;
2028 std::vector<Handle(Geom_BezierCurve)> beziers;
2029 for(exp0.Init(wire); exp0.More(); exp0.Next()) {
2030 TopoDS_Edge edge = exp0.Current();
2032 Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, s0, s1);
2033 if(curve->DynamicType() == STANDARD_TYPE(Geom_BezierCurve)) {
2034 beziers.push_back(Handle(Geom_BezierCurve)::DownCast(curve));
2038 "Bounding curve for Bezier filling should be a Bezier curve");
2042 GeomFill_FillingStyle t;
2043 if(type ==
"Stretch")
2044 t = GeomFill_StretchStyle;
2045 else if(type ==
"Coons")
2046 t = GeomFill_CoonsStyle;
2048 t = GeomFill_CurvedStyle;
2050 if(beziers.size() == 4) {
2051 f.Init(beziers[0], beziers[1], beziers[2], beziers[3], t);
2053 else if(beziers.size() == 3) {
2054 f.Init(beziers[0], beziers[1], beziers[2], t);
2056 else if(beziers.size() == 2) {
2057 f.Init(beziers[0], beziers[1], t);
2061 "Bezier filling requires between 2 and 4 boundary Bezier curves");
2068 bool reverse = sff.FixOrientation();
2069 result = sff.Face();
2070 if(reverse) result.Orientation(TopAbs_REVERSED);
2071 }
catch(Standard_Failure &err) {
2072 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2077 _bind(result, tag,
true);
2081 static bool makeEdgeOnSurface(
const TopoDS_Edge &edge,
2082 const Handle(Geom_Surface) &surf,
2083 bool curve3D, TopoDS_Edge &edgeOnSurf)
2086 Standard_Real first, last;
2087 Handle(Geom_Curve)
c = BRep_Tool::Curve(edge, first, last);
2090 Handle(Geom_Curve) cProj = GeomProjLib::Project
2091 (
new Geom_TrimmedCurve(
c, first, last, Standard_True, Standard_False),
2093 edgeOnSurf = BRepBuilderAPI_MakeEdge
2094 (cProj, cProj->FirstParameter(), cProj->LastParameter());
2099 Handle(Geom_Plane) p =
new Geom_Plane(0, 0, 1, 0);
2100 TopLoc_Location loc;
2101 Handle(Geom2d_Curve) c2d =
2102 BRep_Tool::CurveOnSurface(edge, p, loc, first, last);
2104 edgeOnSurf = BRepBuilderAPI_MakeEdge(c2d, surf, first, last);
2107 catch(Standard_Failure &err) {
2108 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2114 static bool makeTrimmedSurface(
const Handle(Geom_Surface) &surf,
2115 const std::vector<TopoDS_Wire> &wires,
2116 bool wire3D, TopoDS_Face &result)
2119 result = BRepBuilderAPI_MakeFace(surf,
CTX::instance()->geom.tolerance);
2126 ShapeBuild_ReShape rebuild;
2127 TopExp_Explorer exp0;
2128 for(exp0.Init(result, TopAbs_EDGE); exp0.More(); exp0.Next()) {
2129 TopoDS_Edge e = TopoDS::Edge(exp0.Current());
2130 TopoDS_Vertex v1 = TopExp::FirstVertex(e);
2131 TopoDS_Vertex v2 = TopExp::LastVertex(e);
2133 Handle(Geom_Curve) curve = BRep_Tool::Curve(e, s0, s1);
2134 if(curve->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve)){
2135 Handle(Geom_BSplineCurve) bs = Handle(Geom_BSplineCurve)::DownCast(curve);
2136 for(std::size_t i = 0; i < corners.size(); i++) {
2137 if(bs->StartPoint().IsEqual(BRep_Tool::Pnt(corners[i]),
2141 if(bs->EndPoint().IsEqual(BRep_Tool::Pnt(corners[i]),
2147 BRepBuilderAPI_MakeEdge newe(curve, v1, v2);
2148 rebuild.Replace(e, newe);
2150 result = TopoDS::Face(rebuild.Apply(result));
2151 ShapeFix_Face fix(result);
2154 fix.FixOrientation();
2155 result = fix.Face();
2159 std::vector<TopoDS_Wire> wiresProj;
2160 for(std::size_t i = 0; i < wires.size(); i++) {
2161 BRepBuilderAPI_MakeWire w;
2162 BRepTools_WireExplorer exp0;
2163 for(exp0.Init(wires[i]); exp0.More(); exp0.Next()) {
2164 TopoDS_Edge edge = exp0.Current(), edgeOnSurf;
2165 if(makeEdgeOnSurface(edge, surf, wire3D, edgeOnSurf)) {
2174 TopoDS_Wire wire = w.Wire();
2175 wiresProj.push_back(wire);
2177 BRepBuilderAPI_MakeFace
f(surf, wiresProj[0]);
2178 for(std::size_t i = 1; i < wiresProj.size(); i++)
f.Add(wiresProj[i]);
2186 ShapeFix_Face fix(result);
2188 result = fix.Face();
2194 int &tag,
const std::vector<int> &pointTags,
const int numPointsU,
2195 const int degreeU,
const int degreeV,
const std::vector<double> &weights,
2196 const std::vector<double> &knotsU,
const std::vector<double> &knotsV,
2197 const std::vector<int> &multiplicitiesU,
2198 const std::vector<int> &multiplicitiesV,
const std::vector<int> &wireTags,
2201 if(tag >= 0 && _tagFace.IsBound(tag)) {
2202 Msg::Error(
"OpenCASCADE surface with tag %d already exists", tag);
2207 if(numPointsU < 1) {
2208 Msg::Error(
"Wrong number of control points along U for BSpline surface");
2211 int numPointsV = pointTags.size() / numPointsU;
2212 if(numPointsU * numPointsV != (
int)pointTags.size()) {
2213 Msg::Error(
"Wrong number of control points for BSpline surface");
2216 int dU = degreeU, dV = degreeV;
2217 std::vector<double> w(weights), kU(knotsU), kV(knotsV);
2218 std::vector<int> mU(multiplicitiesU), mV(multiplicitiesV);
2223 if(dU > numPointsU - 1) dU = numPointsU - 1;
2224 if(dV > numPointsV - 1) dV = numPointsV - 1;
2226 if(w.empty()) w.resize(pointTags.size(), 1);
2227 if(w.size() != pointTags.size()) {
2228 Msg::Error(
"Wrong number of weights for BSpline surface");
2231 bool periodicU =
true;
2232 for(
int i = 0; i < numPointsV; i++) {
2233 if(pointTags[i * numPointsU] != pointTags[(i + 1) * numPointsU - 1]) {
2238 bool periodicV =
true;
2239 for(
int i = 0; i < numPointsU; i++) {
2240 if(pointTags[i * numPointsV] != pointTags[(i + 1) * numPointsV - 1]) {
2248 int sumOfAllMultU = numPointsU + dU + 1;
2249 int numKnotsU = sumOfAllMultU - 2 * dU;
2251 Msg::Error(
"Not enough control points along U for building BSpline of "
2256 kU.resize(numKnotsU);
2257 for(std::size_t i = 0; i < kU.size(); i++) kU[i] = i;
2258 mU.resize(numKnotsU, 1);
2259 mU.front() = dU + 1;
2263 kU.resize(numPointsU - dU + 2);
2264 for(std::size_t i = 0; i < kU.size(); i++) kU[i] = i;
2265 mU.resize(kU.size(), 1);
2266 mU.front() = dU - 1;
2270 if(kU.size() != mU.size()) {
2271 Msg::Error(
"Number of BSpline knots and multiplicities should be equal");
2277 int sumOfAllMultV = numPointsV + dV + 1;
2278 int numKnotsV = sumOfAllMultV - 2 * dV;
2280 Msg::Error(
"Not enough control points along V for building BSpline of "
2285 kV.resize(numKnotsV);
2286 for(std::size_t i = 0; i < kV.size(); i++) kV[i] = i;
2287 mV.resize(numKnotsV, 1);
2288 mV.front() = dV + 1;
2292 kV.resize(numPointsV - dV + 2);
2293 for(std::size_t i = 0; i < kV.size(); i++) kV[i] = i;
2294 mV.resize(kV.size(), 1);
2295 mV.front() = dV - 1;
2299 if(kV.size() != mV.size()) {
2300 Msg::Error(
"Number of BSpline knots and multiplicities should be equal");
2304 std::vector<TopoDS_Wire> wires;
2305 for(std::size_t i = 0; i < wireTags.size(); i++) {
2306 int wireTag = std::abs(wireTags[i]);
2307 if(!_tagWire.IsBound(wireTag)) {
2308 Msg::Error(
"Unknown OpenCASCADE curve loop with tag %d", wireTag);
2311 TopoDS_Wire wire = TopoDS::Wire(_tagWire.Find(wireTag));
2312 wires.push_back(wire);
2317 std::vector<TopoDS_Vertex> corners;
2318 int npU = (periodicU ? numPointsU - 1 : numPointsU);
2319 int npV = (periodicV ? numPointsV - 1 : numPointsV);
2320 TColgp_Array2OfPnt pp(1, npU, 1, npV);
2321 for(
int i = 1; i <= npU; i++) {
2322 for(
int j = 1; j <= npV; j++) {
2323 int k = (j - 1) * numPointsU + (i - 1);
2324 if(!_tagVertex.IsBound(pointTags[k])) {
2325 Msg::Error(
"Unknown OpenCASCADE point with tag %d", pointTags[k]);
2328 TopoDS_Vertex vertex = TopoDS::Vertex(_tagVertex.Find(pointTags[k]));
2329 if((i == 1 && j == 1) || (i == 1 && j == npV) || (i == npU && j == 1) ||
2330 (i == npU && j == npV))
2331 corners.push_back(vertex);
2332 pp.SetValue(i, j, BRep_Tool::Pnt(vertex));
2335 TColStd_Array2OfReal ww(1, npU, 1, npV);
2336 for(
int i = 1; i <= npU; i++) {
2337 for(
int j = 1; j <= npV; j++) {
2338 int k = (j - 1) * numPointsU + (i - 1);
2339 ww.SetValue(i, j, w[k]);
2342 TColStd_Array1OfReal kkU(1, kU.size());
2343 for(std::size_t i = 1; i <= kU.size(); i++) kkU.SetValue(i, kU[i - 1]);
2344 TColStd_Array1OfReal kkV(1, kV.size());
2345 for(std::size_t i = 1; i <= kV.size(); i++) kkV.SetValue(i, kV[i - 1]);
2346 TColStd_Array1OfInteger mmU(1, mU.size());
2347 for(std::size_t i = 1; i <= mU.size(); i++) mmU.SetValue(i, mU[i - 1]);
2348 TColStd_Array1OfInteger mmV(1, mV.size());
2349 for(std::size_t i = 1; i <= mV.size(); i++) mmV.SetValue(i, mV[i - 1]);
2350 Handle(Geom_BSplineSurface) surf =
new Geom_BSplineSurface(
2351 pp, ww, kkU, kkV, mmU, mmV, dU, dV, periodicU, periodicV);
2352 makeTrimmedSurface(surf, wires, wire3D, result);
2353 }
catch(Standard_Failure &err) {
2354 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2359 _bind(result, tag,
true);
2364 const std::vector<int> &pointTags,
2365 const int numPointsU,
2366 const std::vector<int> &wireTags,
2369 if(tag >= 0 && _tagFace.IsBound(tag)) {
2370 Msg::Error(
"OpenCASCADE surface with tag %d already exists", tag);
2375 if(numPointsU < 1) {
2376 Msg::Error(
"Wrong number of control points along U for Bezier surface");
2379 int numPointsV = pointTags.size() / numPointsU;
2380 if(numPointsU * numPointsV != (
int)pointTags.size()) {
2381 Msg::Error(
"Wrong number of control points for Bezier surface");
2385 std::vector<TopoDS_Wire> wires;
2386 for(std::size_t i = 0; i < wireTags.size(); i++) {
2387 int wireTag = std::abs(wireTags[i]);
2388 if(!_tagWire.IsBound(wireTag)) {
2389 Msg::Error(
"Unknown OpenCASCADE curve loop with tag %d", wireTag);
2392 TopoDS_Wire wire = TopoDS::Wire(_tagWire.Find(wireTag));
2393 wires.push_back(wire);
2398 TColgp_Array2OfPnt pp(1, numPointsU, 1, numPointsV);
2399 for(
int i = 1; i <= numPointsU; i++) {
2400 for(
int j = 1; j <= numPointsV; j++) {
2401 int k = (j - 1) * numPointsU + (i - 1);
2402 if(!_tagVertex.IsBound(pointTags[k])) {
2403 Msg::Error(
"Unknown OpenCASCADE point with tag %d", pointTags[k]);
2406 TopoDS_Vertex vertex = TopoDS::Vertex(_tagVertex.Find(pointTags[k]));
2407 pp.SetValue(i, j, BRep_Tool::Pnt(vertex));
2410 Handle(Geom_BezierSurface) surf =
new Geom_BezierSurface(pp);
2411 makeTrimmedSurface(surf, wires, wire3D, result);
2412 }
catch(Standard_Failure &err) {
2413 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2418 _bind(result, tag,
true);
2423 const std::vector<int> &wireTags,
2426 if(tag >= 0 && _tagFace.IsBound(tag)) {
2427 Msg::Error(
"OpenCASCADE surface with tag %d already exists", tag);
2431 if(!_tagFace.IsBound(surfaceTag)) {
2432 Msg::Error(
"Unknown OpenCASCADE surface with tag %d", surfaceTag);
2435 TopoDS_Face face = TopoDS::Face(_tagFace.Find(surfaceTag));
2437 std::vector<TopoDS_Wire> wires;
2438 for(std::size_t i = 0; i < wireTags.size(); i++) {
2439 int wireTag = std::abs(wireTags[i]);
2440 if(!_tagWire.IsBound(wireTag)) {
2441 Msg::Error(
"Unknown OpenCASCADE curve loop with tag %d", wireTag);
2444 TopoDS_Wire wire = TopoDS::Wire(_tagWire.Find(wireTag));
2445 wires.push_back(wire);
2450 Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
2451 makeTrimmedSurface(surf, wires, wire3D, result);
2452 }
catch(Standard_Failure &err) {
2453 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2458 _bind(result, tag,
true);
2463 const std::vector<int> &surfaceTags,
2466 if(tag >= 0 && _tagShell.IsBound(tag)) {
2467 Msg::Error(
"OpenCASCADE surface loop with tag %d already exists", tag);
2474 TopoDS_Shape result;
2476 BRepBuilderAPI_Sewing s;
2477 for(std::size_t i = 0; i < surfaceTags.size(); i++) {
2478 if(!_tagFace.IsBound(surfaceTags[i])) {
2479 Msg::Error(
"Unknown OpenCASCADE surface with tag %d", surfaceTags[i]);
2482 TopoDS_Face face = TopoDS::Face(_tagFace.Find(surfaceTags[i]));
2486 result = s.SewedShape();
2487 }
catch(Standard_Failure &err) {
2488 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2492 TopExp_Explorer exp0;
2493 for(exp0.Init(result, TopAbs_SHELL); exp0.More(); exp0.Next()) {
2494 TopoDS_Shell shell = TopoDS::Shell(exp0.Current());
2497 ShapeFix_Shell fix(shell);
2499 shell = fix.Shell();
2501 if(first) { first =
false; }
2504 Msg::Warning(
"Creating additional surface loop %d", tag);
2507 _bind(shell, tag,
true);
2513 BRep_Builder builder;
2514 BRepPrim_Builder b(builder);
2517 for(std::size_t i = 0; i < surfaceTags.size(); i++) {
2518 if(!_tagFace.IsBound(surfaceTags[i])) {
2519 Msg::Error(
"Unknown OpenCASCADE surface with tag %d", surfaceTags[i]);
2522 TopoDS_Face face = TopoDS::Face(_tagFace.Find(surfaceTags[i]));
2523 b.AddShellFace(shell, face);
2527 ShapeFix_Shell fix(shell);
2529 shell = fix.Shell();
2532 _bind(shell, tag,
true);
2534 }
catch(Standard_Failure &err) {
2535 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2542 if(tag >= 0 && _tagSolid.IsBound(tag)) {
2543 Msg::Error(
"OpenCASCADE volume with tag %d already exists", tag);
2547 TopoDS_Solid result;
2549 BRepBuilderAPI_MakeSolid s;
2550 for(std::size_t i = 0; i < shellTags.size(); i++) {
2551 if(!_tagShell.IsBound(shellTags[i])) {
2552 Msg::Error(
"Unknown OpenCASCADE surface loop with tag %d",
2556 TopoDS_Shell shell = TopoDS::Shell(_tagShell.Find(shellTags[i]));
2562 ShapeFix_Solid fix(result);
2564 result = TopoDS::Solid(fix.Solid());
2566 }
catch(Standard_Failure &err) {
2567 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2571 _bind(result, tag,
true);
2575 static bool makeSphere(TopoDS_Solid &result,
double xc,
double yc,
double zc,
2576 double radius,
double angle1,
double angle2,
2580 Msg::Error(
"Sphere radius should be positive");
2583 if(angle3 <= 0 || angle3 > 2 * M_PI) {
2584 Msg::Error(
"Cannot build sphere with angle <= 0 or angle > 2*Pi");
2588 gp_Pnt p(xc, yc, zc);
2589 BRepPrimAPI_MakeSphere s(p, radius, angle1, angle2, angle3);
2595 result = TopoDS::Solid(s.Shape());
2596 }
catch(Standard_Failure &err) {
2597 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2604 double radius,
double angle1,
double angle2,
2607 if(tag >= 0 && _tagSolid.IsBound(tag)) {
2608 Msg::Error(
"OpenCASCADE volume with tag %d already exists", tag);
2611 TopoDS_Solid result;
2612 if(!makeSphere(result, xc, yc, zc, radius, angle1, angle2, angle3))
2615 _bind(result, tag,
true);
2619 static bool makeBox(TopoDS_Solid &result,
double x,
double y,
double z,
2620 double dx,
double dy,
double dz)
2622 if(!dx || !dy || !dz) {
2628 gp_Pnt P2(x + dx, y + dy,
z + dz);
2629 BRepPrimAPI_MakeBox b(P1, P2);
2635 result = TopoDS::Solid(b.Shape());
2636 }
catch(Standard_Failure &err) {
2637 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2644 double dy,
double dz)
2646 if(tag >= 0 && _tagSolid.IsBound(tag)) {
2647 Msg::Error(
"OpenCASCADE volume with tag %d already exists", tag);
2650 TopoDS_Solid result;
2651 if(!makeBox(result, x, y,
z, dx, dy, dz))
return false;
2653 _bind(result, tag,
true);
2657 static bool makeCylinder(TopoDS_Solid &result,
double x,
double y,
double z,
2658 double dx,
double dy,
double dz,
double r,
2661 const double H = sqrt(dx * dx + dy * dy + dz * dz);
2663 Msg::Error(
"Cannot build cylinder of zero height");
2666 if(angle <= 0 || angle > 2 * M_PI) {
2667 Msg::Error(
"Cannot build cylinder with angle <= 0 or angle > 2*Pi");
2672 gp_Vec v(dx / H, dy / H, dz / H);
2674 BRepPrimAPI_MakeCylinder
c(axis, r, H,
angle);
2680 result = TopoDS::Solid(
c.Shape());
2681 }
catch(Standard_Failure &err) {
2682 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2689 double dx,
double dy,
double dz,
double r,
2692 if(tag >= 0 && _tagSolid.IsBound(tag)) {
2693 Msg::Error(
"OpenCASCADE volume with tag %d already exists", tag);
2696 TopoDS_Solid result;
2697 if(!makeCylinder(result, x, y,
z, dx, dy, dz, r,
angle))
return false;
2699 _bind(result, tag,
true);
2703 static bool makeTorus(TopoDS_Solid &result,
double x,
double y,
double z,
2704 double r1,
double r2,
double angle,
2705 const std::vector<double> &N = std::vector<double>())
2707 if(r1 <= 0 || r2 <= 0) {
2708 Msg::Error(
"Torus radii should be positive");
2713 std::vector<double> NN(N);
2714 if(NN.size() != 3) {
2720 gp_Vec v(NN[0], NN[1], NN[2]);
2722 BRepPrimAPI_MakeTorus t(axis, r1, r2,
angle);
2728 result = TopoDS::Solid(t.Shape());
2729 }
catch(Standard_Failure &err) {
2730 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2737 double r2,
double angle,
2738 const std::vector<double> &N)
2740 if(tag >= 0 && _tagSolid.IsBound(tag)) {
2741 Msg::Error(
"OpenCASCADE volume with tag %d already exists", tag);
2744 TopoDS_Solid result;
2745 if(!makeTorus(result, x, y,
z, r1, r2,
angle, N))
return false;
2747 _bind(result, tag,
true);
2751 static bool makeCone(TopoDS_Solid &result,
double x,
double y,
double z,
2752 double dx,
double dy,
double dz,
double r1,
double r2,
2755 const double H = sqrt(dx * dx + dy * dy + dz * dz);
2757 Msg::Error(
"Cannot build cone of zero height");
2766 gp_Vec aV(dx / H, dy / H, dz / H);
2767 gp_Ax2 anAxes(aP, aV);
2768 BRepPrimAPI_MakeCone
c(anAxes, r1, r2, H,
angle);
2774 result = TopoDS::Solid(
c.Shape());
2775 }
catch(Standard_Failure &err) {
2776 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2783 double dy,
double dz,
double r1,
double r2,
2786 if(tag >= 0 && _tagSolid.IsBound(tag)) {
2787 Msg::Error(
"OpenCASCADE volume with tag %d already exists", tag);
2790 TopoDS_Solid result;
2791 if(!makeCone(result, x, y,
z, dx, dy, dz, r1, r2,
angle))
return false;
2793 _bind(result, tag,
true);
2797 static bool makeWedge(TopoDS_Solid &result,
double x,
double y,
double z,
2798 double dx,
double dy,
double dz,
double ltx,
2799 const std::vector<double> &N = std::vector<double>())
2803 std::vector<double> NN(N);
2804 if(NN.size() != 3) {
2810 gp_Vec v(NN[0], NN[1], NN[2]);
2812 BRepPrimAPI_MakeWedge w(axis, dx, dy, dz, ltx);
2818 result = TopoDS::Solid(w.Shape());
2819 }
catch(Standard_Failure &err) {
2820 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2827 double dy,
double dz,
double ltx,
2828 const std::vector<double> &N)
2830 if(tag >= 0 && _tagSolid.IsBound(tag)) {
2831 Msg::Error(
"OpenCASCADE volume with tag %d already exists", tag);
2834 TopoDS_Solid result;
2835 if(!makeWedge(result, x, y,
z, dx, dy, dz, ltx, N))
return false;
2837 _bind(result, tag,
true);
2842 int tag,
const std::vector<int> &wireTags,
bool makeSolid,
bool makeRuled,
2843 std::vector<std::pair<int, int> > &outDimTags,
int maxDegree,
2844 const std::string &continuity,
const std::string ¶metrization,
2847 int dim = makeSolid ? 3 : 2;
2848 if(tag >= 0 && _isBound(dim, tag)) {
2849 Msg::Error(
"OpenCASCADE entity of dimension %d with tag %d already exists",
2853 if(wireTags.size() < 2) {
2854 Msg::Error(
"ThruSections require at least 2 wires");
2857 TopoDS_Shape result;
2859 BRepOffsetAPI_ThruSections ts(makeSolid, makeRuled);
2860 if(continuity ==
"C0")
2861 ts.SetContinuity(GeomAbs_C0);
2862 else if(continuity ==
"G1")
2863 ts.SetContinuity(GeomAbs_G1);
2864 else if(continuity ==
"C1")
2865 ts.SetContinuity(GeomAbs_C1);
2866 else if(continuity ==
"G2")
2867 ts.SetContinuity(GeomAbs_G2);
2868 else if(continuity ==
"C2")
2869 ts.SetContinuity(GeomAbs_C2);
2870 else if(continuity ==
"C3")
2871 ts.SetContinuity(GeomAbs_C3);
2872 else if(continuity ==
"CN")
2873 ts.SetContinuity(GeomAbs_CN);
2878 ts.SetMaxDegree(maxDegree);
2880 ts.SetMaxDegree(
CTX::instance()->geom.occThruSectionsDegree);
2882 if(parametrization ==
"ChordLength")
2883 ts.SetParType(Approx_ChordLength);
2884 else if(parametrization ==
"Centripetal")
2885 ts.SetParType(Approx_Centripetal);
2886 else if(parametrization ==
"IsoParametric")
2887 ts.SetParType(Approx_IsoParametric);
2889 ts.SetSmoothing(smoothing ? Standard_True : Standard_False);
2891 for(std::size_t i = 0; i < wireTags.size(); i++) {
2892 if(!_tagWire.IsBound(wireTags[i])) {
2893 Msg::Error(
"Unknown OpenCASCADE wire or curve loop with tag %d",
2897 TopoDS_Wire wire = TopoDS::Wire(_tagWire.Find(wireTags[i]));
2898 if(makeSolid && !wire.Closed()) {
2899 Msg::Error(
"Making solid requires closed wires");
2904 ts.CheckCompatibility(Standard_False);
2910 result = ts.Shape();
2911 }
catch(Standard_Failure &err) {
2912 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2915 _multiBind(result, tag, outDimTags,
true,
true);
2920 const std::vector<int> &excludeFaceTags,
2922 std::vector<std::pair<int, int> > &outDimTags)
2924 if(tag >= 0 && _isBound(3, tag)) {
2925 Msg::Error(
"OpenCASCADE volume with tag %d already exists", tag);
2928 if(!_isBound(3, solidTag)) {
2929 Msg::Error(
"Unknown OpenCASCADE volume with tag %d", solidTag);
2932 TopoDS_Shape result;
2934 TopoDS_Shape shape = _find(3, solidTag);
2935 TopTools_ListOfShape exclude;
2936 for(std::size_t i = 0; i < excludeFaceTags.size(); i++) {
2937 if(!_tagFace.IsBound(excludeFaceTags[i])) {
2938 Msg::Error(
"Unknown OpenCASCADE surface with tag %d",
2939 excludeFaceTags[i]);
2942 exclude.Append(_tagFace.Find(excludeFaceTags[i]));
2944 #if OCC_VERSION_HEX > 0x070400
2945 BRepOffsetAPI_MakeThickSolid ts;
2946 ts.MakeThickSolidByJoin(shape, exclude, offset,
2949 BRepOffsetAPI_MakeThickSolid ts(shape, exclude, offset,
2957 result = ts.Shape();
2958 }
catch(Standard_Failure &err) {
2959 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
2962 _multiBind(result, tag, outDimTags,
true,
true);
2966 void OCC_Internals::_setExtrudedAttributes(
2967 const TopoDS_Compound &
c, BRepSweep_Prism *p, BRepSweep_Revol *r,
2968 ExtrudeParams *e,
double x,
double y,
double z,
double dx,
double dy,
2969 double dz,
double ax,
double ay,
double az,
double angle)
2971 if(!p && !r)
return;
2973 bool extrude_attributes = (e ? true :
false);
2975 if(extrude_attributes && r &&
angle >= 2 * M_PI) {
2978 Msg::Warning(
"Extruded meshes by revolution only for angle < 2*Pi");
2979 extrude_attributes =
false;
2982 TopExp_Explorer exp0;
2984 for(exp0.Init(
c, TopAbs_FACE); exp0.More(); exp0.Next()) {
2985 TopoDS_Face face = TopoDS::Face(exp0.Current());
2986 TopoDS_Shape bot = p ? p->FirstShape(face) : r->FirstShape(face);
2987 TopoDS_Shape top = p ? p->LastShape(face) : r->LastShape(face);
2988 if(extrude_attributes) {
2990 ee->
fill(p ?
TRANSLATE :
ROTATE, dx, dy, dz, ax, ay, az, x, y,
z,
angle);
2992 _attributes->insert(
new OCCAttributes(2, top, ee, 2, bot));
2994 TopoDS_Shape vol = p ? p->Shape(face) : r->Shape(face);
2995 if(extrude_attributes) {
2997 ee->
fill(p ?
TRANSLATE :
ROTATE, dx, dy, dz, ax, ay, az, x, y,
z,
angle);
2999 _attributes->insert(
new OCCAttributes(3, vol, ee, 2, bot));
3003 for(exp0.Init(
c, TopAbs_EDGE); exp0.More(); exp0.Next()) {
3004 TopoDS_Edge edge = TopoDS::Edge(exp0.Current());
3005 TopoDS_Shape bot = p ? p->FirstShape(edge) : r->FirstShape(edge);
3006 TopoDS_Shape top = p ? p->LastShape(edge) : r->LastShape(edge);
3007 if(extrude_attributes) {
3009 ee->
fill(p ?
TRANSLATE :
ROTATE, dx, dy, dz, ax, ay, az, x, y,
z,
angle);
3011 _attributes->insert(
new OCCAttributes(1, top, ee, 1, bot));
3013 TopoDS_Shape sur = p ? p->Shape(edge) : r->Shape(edge);
3014 if(extrude_attributes) {
3016 ee->
fill(p ?
TRANSLATE :
ROTATE, dx, dy, dz, ax, ay, az, x, y,
z,
angle);
3018 _attributes->insert(
new OCCAttributes(2, sur, ee, 1, bot));
3022 for(exp0.Init(
c, TopAbs_VERTEX); exp0.More(); exp0.Next()) {
3023 TopoDS_Vertex vertex = TopoDS::Vertex(exp0.Current());
3024 TopoDS_Shape bot = p ? p->FirstShape(vertex) : r->FirstShape(vertex);
3025 TopoDS_Shape top = p ? p->LastShape(vertex) : r->LastShape(vertex);
3026 TopoDS_Shape lin = p ? p->Shape(vertex) : r->Shape(vertex);
3027 if(extrude_attributes) {
3029 ee->
fill(p ?
TRANSLATE :
ROTATE, dx, dy, dz, ax, ay, az, x, y,
z,
angle);
3031 _attributes->insert(
new OCCAttributes(1, lin, ee, 0, bot));
3034 double lc = _attributes->getMeshSize(0, bot);
3035 if(lc > 0 && lc <
MAX_LC)
3036 _attributes->insert(
new OCCAttributes(0, top, lc));
3041 int OCC_Internals::_getFuzzyTag(
int dim,
const TopoDS_Shape &s)
3043 if(_isBound(dim, s))
return _find(dim, s);
3045 std::vector<TopoDS_Shape> candidates;
3046 _attributes->getSimilarShapes(dim, s, candidates);
3049 for(std::size_t i = 0; i < candidates.size(); i++) {
3050 if(_isBound(dim, candidates[i])) { num++; }
3052 Msg::Debug(
"Extruded mesh constraint fuzzy search: found %d candidates "
3053 "(dim=%d, %d bound)",
3054 (
int)candidates.size(), dim, num);
3055 for(std::size_t i = 0; i < candidates.size(); i++) {
3056 if(_isBound(dim, candidates[i])) {
return _find(dim, candidates[i]); }
3061 void OCC_Internals::_copyExtrudedAttributes(TopoDS_Edge edge,
GEdge *ge)
3064 TopoDS_Shape sourceShape;
3066 _attributes->getExtrudeParams(1, edge, sourceDim, sourceShape);
3069 e->
geo.
Source = _getFuzzyTag(0, sourceShape);
3072 e->
geo.
Source = _getFuzzyTag(1, sourceShape);
3078 Msg::Info(
"Extrusion layer cycle detected for curve %d", ge->
tag());
3095 void OCC_Internals::_copyExtrudedAttributes(TopoDS_Face face,
GFace *gf)
3098 TopoDS_Shape sourceShape;
3100 _attributes->getExtrudeParams(2, face, sourceDim, sourceShape);
3103 e->
geo.
Source = _getFuzzyTag(1, sourceShape);
3106 e->
geo.
Source = _getFuzzyTag(2, sourceShape);
3112 Msg::Info(
"Extrusion layer cycle detected for surface %d", gf->
tag());
3129 void OCC_Internals::_copyExtrudedAttributes(TopoDS_Solid solid,
GRegion *gr)
3132 TopoDS_Shape sourceShape;
3134 _attributes->getExtrudeParams(3, solid, sourceDim, sourceShape);
3137 e->
geo.
Source = _getFuzzyTag(2, sourceShape);
3143 static int getReturnedShapes(
const TopoDS_Compound &
c, T *sweep,
3144 std::vector<TopoDS_Shape> &top,
3145 std::vector<TopoDS_Shape> &body,
3146 std::vector<std::vector<TopoDS_Shape> > &lateral)
3148 TopExp_Explorer exp0, exp1;
3149 for(exp0.Init(
c, TopAbs_FACE); exp0.More(); exp0.Next()) {
3150 TopoDS_Face face = TopoDS::Face(exp0.Current());
3151 top.push_back(sweep->LastShape(face));
3152 body.push_back(sweep->Shape(face));
3153 lateral.push_back(std::vector<TopoDS_Shape>());
3154 for(exp1.Init(face, TopAbs_EDGE); exp1.More(); exp1.Next()) {
3155 TopoDS_Edge edge = TopoDS::Edge(exp1.Current());
3156 lateral.back().push_back(sweep->Shape(edge));
3159 if(top.size())
return 3;
3160 for(exp0.Init(
c, TopAbs_EDGE); exp0.More(); exp0.Next()) {
3161 TopoDS_Edge edge = TopoDS::Edge(exp0.Current());
3162 top.push_back(sweep->LastShape(edge));
3163 body.push_back(sweep->Shape(edge));
3164 lateral.push_back(std::vector<TopoDS_Shape>());
3165 for(exp1.Init(edge, TopAbs_VERTEX); exp1.More(); exp1.Next()) {
3166 TopoDS_Vertex vertex = TopoDS::Vertex(exp1.Current());
3167 lateral.back().push_back(sweep->Shape(vertex));
3170 if(top.size())
return 2;
3171 for(exp0.Init(
c, TopAbs_VERTEX); exp0.More(); exp0.Next()) {
3172 TopoDS_Vertex vertex = TopoDS::Vertex(exp0.Current());
3173 top.push_back(sweep->LastShape(vertex));
3174 body.push_back(sweep->Shape(vertex));
3176 if(top.size())
return 1;
3180 bool OCC_Internals::_extrudePerDim(
3181 int mode,
int inDim,
const std::vector<int> &inTags,
double x,
double y,
3182 double z,
double dx,
double dy,
double dz,
double ax,
double ay,
double az,
3183 double angle,
int wireTag, std::vector<std::pair<int, int> > &outDimTags,
3191 for(std::size_t i = 0; i < inTags.size(); i++) {
3192 if(!_isBound(inDim, inTags[i])) {
3193 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d",
3197 TopoDS_Shape shape = _find(inDim, inTags[i]);
3200 TopoDS_Shape result;
3201 std::vector<TopoDS_Shape> top, body;
3202 std::vector<std::vector<TopoDS_Shape> > lateral;
3206 BRepPrimAPI_MakePrism p(
c, gp_Vec(dx, dy, dz), Standard_False);
3213 const BRepSweep_Prism &
prism(p.Prism());
3214 _setExtrudedAttributes(
c, (BRepSweep_Prism *)&
prism,
nullptr, e, 0., 0.,
3215 0., dx, dy, dz, 0., 0., 0., 0.);
3216 dim = getReturnedShapes(
c, (BRepSweep_Prism *)&
prism, top, body, lateral);
3218 else if(mode == 1) {
3219 gp_Ax1 axisOfRevolution(gp_Pnt(x, y,
z), gp_Dir(ax, ay, az));
3220 BRepPrimAPI_MakeRevol r(
c, axisOfRevolution,
angle, Standard_False);
3227 const BRepSweep_Revol &revol(r.Revol());
3228 _setExtrudedAttributes(
c,
nullptr, (BRepSweep_Revol *)&revol, e, x, y,
z,
3229 0., 0., 0., ax, ay, az,
angle);
3230 dim = getReturnedShapes(
c, (BRepSweep_Revol *)&revol, top, body, lateral);
3232 else if(mode == 2) {
3233 if(!_tagWire.IsBound(wireTag)) {
3234 Msg::Error(
"Unknown OpenCASCADE wire with tag %d", wireTag);
3237 TopoDS_Wire wire = TopoDS::Wire(_tagWire.Find(wireTag));
3240 GeomFill_Trihedron mode = GeomFill_IsDiscreteTrihedron;
3241 if(trihedron ==
"DiscreteTrihedron")
3242 mode = GeomFill_IsDiscreteTrihedron;
3243 else if(trihedron ==
"CorrectedFrenet")
3244 mode = GeomFill_IsCorrectedFrenet;
3245 else if(trihedron ==
"Fixed")
3246 mode = GeomFill_IsFixed;
3247 else if(trihedron ==
"Frenet")
3248 mode = GeomFill_IsFrenet;
3249 else if(trihedron ==
"ConstantNormal")
3250 mode = GeomFill_IsConstantNormal;
3251 else if(trihedron ==
"Darboux")
3252 mode = GeomFill_IsDarboux;
3253 else if(trihedron ==
"GuideAC")
3254 mode = GeomFill_IsGuideAC;
3255 else if(trihedron ==
"GuidePlan")
3256 mode = GeomFill_IsGuidePlan;
3257 else if(trihedron ==
"GuideACWithContact")
3258 mode = GeomFill_IsGuideACWithContact;
3259 else if(trihedron ==
"GuidePlanWithContact")
3260 mode = GeomFill_IsGuidePlanWithContact;
3263 "Unknown trihedron mode for pipe: using 'DiscreteTrihedron'");
3264 BRepOffsetAPI_MakePipe p(wire,
c, mode);
3274 "Structured meshes not yet available with OpenCASCADE pipe");
3283 }
catch(Standard_Failure &err) {
3284 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
3288 _multiBind(result, -1, outDimTags,
true,
true);
3291 if(dim >= 1 && dim <= 3 && top.size() == inTags.size() &&
3292 top.size() == body.size()) {
3294 for(std::size_t i = 0; i < top.size(); i++) {
3295 if(_isBound(dim - 1, top[i]))
3296 outDimTags.push_back(
3297 std::make_pair(dim - 1, _find(dim - 1, top[i])));
3298 if(_isBound(dim, body[i]))
3299 outDimTags.push_back(std::make_pair(dim, _find(dim, body[i])));
3301 top.size() == lateral.size()) {
3302 for(std::size_t j = 0; j < lateral[i].size(); j++) {
3303 if(_isBound(dim - 1, lateral[i][j]))
3304 outDimTags.push_back(
3305 std::make_pair(dim - 1, _find(dim - 1, lateral[i][j])));
3313 bool OCC_Internals::_extrude(
int mode,
3314 const std::vector<std::pair<int, int> > &inDimTags,
3315 double x,
double y,
double z,
double dx,
double dy,
3316 double dz,
double ax,
double ay,
double az,
3317 double angle,
int wireTag,
3318 std::vector<std::pair<int, int> > &outDimTags,
3321 std::vector<int> inTags[4];
3322 for(std::size_t i = 0; i < inDimTags.size(); i++) {
3323 int dim = inDimTags[i].first;
3324 if(dim < 0 || dim > 3) {
3325 Msg::Error(
"Wrong input dimension in extrusion");
3328 inTags[dim].push_back(inDimTags[i].second);
3330 for(
int dim = 0; dim < 4; dim++) {
3331 if(!inTags[dim].empty()) {
3332 std::vector<std::pair<int, int> > out;
3333 if(_extrudePerDim(mode, dim, inTags[dim], x, y,
z, dx, dy, dz, ax, ay, az,
3334 angle, wireTag, out, e, trihedron)) {
3335 outDimTags.insert(outDimTags.end(), out.begin(), out.end());
3343 double dx,
double dy,
double dz,
3344 std::vector<std::pair<int, int> > &outDimTags,
3347 return _extrude(0, inDimTags, 0., 0., 0., dx, dy, dz, 0., 0., 0., 0., 0,
3352 double x,
double y,
double z,
double ax,
double ay,
3353 double az,
double angle,
3354 std::vector<std::pair<int, int> > &outDimTags,
3357 return _extrude(1, inDimTags, x, y,
z, 0., 0., 0., ax, ay, az,
angle, 0,
3363 std::vector<std::pair<int, int> > &outDimTags,
3364 const std::string &trihedron)
3366 std::string t = trihedron;
3368 return _extrude(2, inDimTags, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., wireTag,
3369 outDimTags,
nullptr, t);
3372 bool OCC_Internals::_fillet(
int mode,
const std::vector<int> &volumeTags,
3373 const std::vector<int> &curveTags,
3374 const std::vector<int> &surfaceTags,
3375 const std::vector<double> ¶m,
3376 std::vector<std::pair<int, int> > &outDimTags,
3379 std::vector<TopoDS_Edge>
edges;
3380 for(std::size_t i = 0; i < curveTags.size(); i++) {
3381 if(!_tagEdge.IsBound(curveTags[i])) {
3382 Msg::Error(
"Unknown OpenCASCADE curve with tag %d", curveTags[i]);
3385 edges.push_back(TopoDS::Edge(_tagEdge.Find(curveTags[i])));
3388 std::vector<TopoDS_Face>
faces;
3389 for(std::size_t i = 0; i < surfaceTags.size(); i++) {
3390 if(!_tagFace.IsBound(surfaceTags[i])) {
3391 Msg::Error(
"Unknown OpenCASCADE surface with tag %d", surfaceTags[i]);
3394 faces.push_back(TopoDS::Face(_tagFace.Find(surfaceTags[i])));
3397 Msg::Error(
"Different number of curves and surfaces for chamfer");
3405 for(std::size_t i = 0; i < volumeTags.size(); i++) {
3406 if(!_isBound(3, volumeTags[i])) {
3407 Msg::Error(
"Unknown OpenCASCADE volume with tag %d", volumeTags[i]);
3410 TopoDS_Shape shape = _find(3, volumeTags[i]);
3411 if(removeVolume) _unbind(shape, 3, volumeTags[i],
true);
3414 ShapeFix_Solid fix(TopoDS::Solid(shape));
3416 shape = fix.Solid();
3420 TopoDS_Shape result;
3423 BRepFilletAPI_MakeFillet
f(
c);
3424 for(std::size_t i = 0; i <
edges.size(); i++) {
3425 if(param.size() == 1)
3426 f.Add(param[0],
edges[i]);
3427 else if(param.size() ==
edges.size())
3428 f.Add(param[i],
edges[i]);
3429 else if(param.size() == 2 *
edges.size())
3430 f.Add(param[2 * i], param[2 * i + 1],
edges[i]);
3440 BRepFilletAPI_MakeChamfer
f(
c);
3441 for(std::size_t i = 0; i <
edges.size(); i++) {
3442 if(param.size() == 1)
3444 else if(param.size() ==
edges.size())
3446 else if(param.size() == 2 *
edges.size())
3447 f.Add(param[2 * i], param[2 * i + 1],
edges[i],
faces[i]);
3456 }
catch(Standard_Failure &err) {
3457 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
3461 if(result.IsNull()) {
3462 Msg::Error(
"%s produces empty shape", mode ?
"Chamfer" :
"Fillet");
3470 _multiBind(result, -1, outDimTags,
true,
true);
3475 const std::vector<int> &curveTags,
3476 const std::vector<double> &radii,
3477 std::vector<std::pair<int, int> > &outDimTags,
3480 std::vector<int> dummy;
3481 return _fillet(0, volumeTags, curveTags, dummy, radii, outDimTags,
3486 const std::vector<int> &curveTags,
3487 const std::vector<int> &surfaceTags,
3488 const std::vector<double> &distances,
3489 std::vector<std::pair<int, int> > &outDimTags,
3492 return _fillet(1, volumeTags, curveTags, surfaceTags, distances, outDimTags,
3496 static void _filterTags(std::vector<std::pair<int, int> > &outDimTags,
3499 std::vector<std::pair<int, int> > tmp(outDimTags);
3501 for(std::size_t i = 0; i < tmp.size(); i++) {
3502 if(tmp[i].first >= minDim) outDimTags.push_back(tmp[i]);
3507 int tag, BooleanOperator op,
3508 const std::vector<std::pair<int, int> > &objectDimTags,
3509 const std::vector<std::pair<int, int> > &toolDimTags,
3510 std::vector<std::pair<int, int> > &outDimTags,
3511 std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap,
3512 bool removeObject,
bool removeTool)
3518 if(objectDimTags.empty())
return true;
3520 if(tag >= 0 && _isBound(objectDimTags[0].first, tag)) {
3521 Msg::Error(
"OpenCASCADE entity with tag %d already exists", tag);
3526 TopTools_ListOfShape objectShapes, toolShapes;
3527 for(std::size_t i = 0; i < objectDimTags.size(); i++) {
3528 int dim = objectDimTags[i].first;
3529 int t = objectDimTags[i].second;
3530 if(!_isBound(dim, t)) {
3531 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d", dim,
3536 TopoDS_Shape
object = _find(dim, t);
3537 objectShapes.Append(
object);
3539 minDim = std::min(minDim, dim);
3541 for(std::size_t i = 0; i < toolDimTags.size(); i++) {
3542 int dim = toolDimTags[i].first;
3543 int t = toolDimTags[i].second;
3544 if(!_isBound(dim, t)) {
3545 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d", dim,
3550 TopoDS_Shape tool = _find(dim, t);
3551 toolShapes.Append(tool);
3553 minDim = std::min(minDim, dim);
3556 TopoDS_Shape result;
3557 std::vector<TopoDS_Shape> mapOriginal;
3558 std::vector<TopTools_ListOfShape> mapModified, mapGenerated;
3559 std::vector<bool> mapDeleted;
3563 BRepAlgoAPI_Fuse fuse;
3564 fuse.SetRunParallel(parallel);
3565 fuse.SetArguments(objectShapes);
3566 fuse.SetTools(toolShapes);
3583 if(!fuse.IsDone()) {
3584 Msg::Error(
"Fuse operation cannot be performed");
3590 #if OCC_VERSION_HEX < 0x070400
3591 result = fuse.Shape();
3592 ShapeUpgrade_UnifySameDomain unify(result);
3594 result = unify.Shape();
3598 fuse.SimplifyResult();
3599 result = fuse.Shape();
3603 result = fuse.Shape();
3605 TopTools_ListIteratorOfListOfShape it(objectShapes);
3606 for(; it.More(); it.Next()) {
3607 mapOriginal.push_back(it.Value());
3608 mapModified.push_back(fuse.Modified(it.Value()));
3609 mapDeleted.push_back(fuse.IsDeleted(it.Value()));
3610 mapGenerated.push_back(fuse.Generated(it.Value()));
3612 TopTools_ListIteratorOfListOfShape it2(toolShapes);
3613 for(; it2.More(); it2.Next()) {
3614 mapOriginal.push_back(it2.Value());
3615 mapModified.push_back(fuse.Modified(it2.Value()));
3616 mapDeleted.push_back(fuse.IsDeleted(it2.Value()));
3617 mapGenerated.push_back(fuse.Generated(it2.Value()));
3621 BRepAlgoAPI_Common common;
3622 common.SetRunParallel(parallel);
3623 common.SetArguments(objectShapes);
3624 common.SetTools(toolShapes);
3627 if(!common.IsDone()) {
3628 Msg::Error(
"Intersection operation cannot be performed");
3631 result = common.Shape();
3632 TopTools_ListIteratorOfListOfShape it(objectShapes);
3633 for(; it.More(); it.Next()) {
3634 mapOriginal.push_back(it.Value());
3635 mapModified.push_back(common.Modified(it.Value()));
3636 mapDeleted.push_back(common.IsDeleted(it.Value()));
3637 mapGenerated.push_back(common.Generated(it.Value()));
3639 TopTools_ListIteratorOfListOfShape it2(toolShapes);
3640 for(; it2.More(); it2.Next()) {
3641 mapOriginal.push_back(it2.Value());
3642 mapModified.push_back(common.Modified(it2.Value()));
3643 mapDeleted.push_back(common.IsDeleted(it2.Value()));
3644 mapGenerated.push_back(common.Generated(it2.Value()));
3649 BRepAlgoAPI_Cut cut;
3650 cut.SetRunParallel(parallel);
3651 cut.SetArguments(objectShapes);
3652 cut.SetTools(toolShapes);
3656 Msg::Error(
"Intersection operation cannot be performed");
3659 result = cut.Shape();
3660 TopTools_ListIteratorOfListOfShape it(objectShapes);
3661 for(; it.More(); it.Next()) {
3662 mapOriginal.push_back(it.Value());
3663 mapModified.push_back(cut.Modified(it.Value()));
3664 mapDeleted.push_back(cut.IsDeleted(it.Value()));
3665 mapGenerated.push_back(cut.Generated(it.Value()));
3667 TopTools_ListIteratorOfListOfShape it2(toolShapes);
3668 for(; it2.More(); it2.Next()) {
3669 mapOriginal.push_back(it2.Value());
3670 mapModified.push_back(cut.Modified(it2.Value()));
3671 mapDeleted.push_back(cut.IsDeleted(it2.Value()));
3672 mapGenerated.push_back(cut.Generated(it2.Value()));
3678 BRepAlgoAPI_BuilderAlgo fragments;
3679 fragments.SetRunParallel(parallel);
3680 objectShapes.Append(toolShapes);
3682 fragments.SetArguments(objectShapes);
3685 #if OCC_VERSION_HEX > 0x070100
3686 if(fragments.HasErrors() &&
3687 fragments.HasError(STANDARD_TYPE(BOPAlgo_AlertTooFewArguments))) {
3688 Msg::Warning(
"Boolean fragments skipped - too few arguments");
3692 if(!fragments.IsDone()) {
3696 result = fragments.Shape();
3697 TopTools_ListIteratorOfListOfShape it(objectShapes);
3698 for(; it.More(); it.Next()) {
3699 mapOriginal.push_back(it.Value());
3700 mapModified.push_back(fragments.Modified(it.Value()));
3701 mapDeleted.push_back(fragments.IsDeleted(it.Value()));
3702 mapGenerated.push_back(fragments.Generated(it.Value()));
3706 }
catch(Standard_Failure &err) {
3707 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
3711 std::vector<std::pair<int, int> > inDimTags;
3712 inDimTags.insert(inDimTags.end(), objectDimTags.begin(), objectDimTags.end());
3713 inDimTags.insert(inDimTags.end(), toolDimTags.begin(), toolDimTags.end());
3714 std::size_t numObjects = objectDimTags.size();
3716 if(tag >= 0 || !preserveNumbering) {
3719 for(std::size_t i = 0; i < inDimTags.size(); i++) {
3720 bool remove = (i < numObjects) ? removeObject : removeTool;
3722 int d = inDimTags[i].first;
3723 int t = inDimTags[i].second;
3724 if(_isBound(d, t)) {
3726 _unbind(_find(d, t), d, t,
true);
3728 _unbindWithoutChecks(_find(d, t));
3732 _multiBind(result, tag, outDimTags, (tag >= 0) ?
true :
false,
true,
3733 (tag >= 0) ?
false :
true);
3734 _filterTags(outDimTags, minDim);
3741 _toPreserve.clear();
3742 for(std::size_t i = 0; i < inDimTags.size(); i++) {
3743 int dim = inDimTags[i].first;
3744 int tag = inDimTags[i].second;
3745 bool remove = (i < numObjects) ? removeObject : removeTool;
3749 _unbind(mapOriginal[i], dim, tag,
true);
3751 _unbindWithoutChecks(mapOriginal[i]);
3753 Msg::Debug(
"BOOL (%d,%d) deleted", dim, tag);
3755 else if(mapModified[i].Extent() == 0) {
3756 auto ins = _toPreserve.insert(std::make_pair(dim, tag));
3758 outDimTags.push_back(std::make_pair(dim, tag));
3759 Msg::Debug(
"BOOL (%d,%d) not modified", dim, tag);
3761 else if(mapModified[i].Extent() == 1) {
3763 _unbind(mapOriginal[i], dim, tag,
true);
3764 _bind(mapModified[i].First(), dim, tag,
false);
3765 int t = _find(dim, mapModified[i].First());
3767 Msg::Info(
"Could not preserve tag of %dD object %d (->%d)", dim,
3769 auto ins = _toPreserve.insert(std::make_pair(dim, t));
3771 outDimTags.push_back(std::make_pair(dim, t));
3773 Msg::Debug(
"BOOL (%d,%d) replaced by 1", dim, tag);
3776 if(
remove) _unbind(mapOriginal[i], dim, tag,
true);
3780 for(
int d = -2; d <= 3; d++) _recomputeMaxTag(d);
3782 _multiBind(result, -1, outDimTags,
false,
true,
true);
3783 _filterTags(outDimTags, minDim);
3784 _toPreserve.clear();
3788 for(std::size_t i = 0; i < inDimTags.size(); i++) {
3789 int dim = inDimTags[i].first;
3790 int tag = inDimTags[i].second;
3791 std::pair<int, int> dimTag(dim, tag);
3792 std::vector<std::pair<int, int> > dimTags;
3795 else if(mapModified[i].Extent() == 0) {
3796 if(_isBound(dim, tag)) dimTags.push_back(dimTag);
3799 TopTools_ListIteratorOfListOfShape it(mapModified[i]);
3800 for(; it.More(); it.Next()) {
3801 if(_isBound(dim, it.Value())) {
3802 int t = _find(dim, it.Value());
3803 dimTags.push_back(std::make_pair(dim, t));
3806 TopTools_ListIteratorOfListOfShape it2(mapGenerated[i]);
3807 for(; it2.More(); it2.Next()) {
3808 if(_isBound(dim, it2.Value())) {
3809 int t = _find(dim, it2.Value());
3810 dimTags.push_back(std::make_pair(dim, t));
3814 std::ostringstream sstream;
3815 sstream <<
"BOOL in (" << dim <<
"," << tag <<
") -> out";
3816 for(std::size_t j = 0; j < dimTags.size(); j++)
3817 sstream <<
" (" << dimTags[j].first <<
"," << dimTags[j].second <<
")";
3819 outDimTagsMap.push_back(dimTags);
3826 int tag,
const std::vector<std::pair<int, int> > &objectDimTags,
3827 const std::vector<std::pair<int, int> > &toolDimTags,
3828 std::vector<std::pair<int, int> > &outDimTags,
3829 std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap,
3830 bool removeObject,
bool removeTool)
3833 outDimTags, outDimTagsMap, removeObject, removeTool);
3837 int tag,
const std::vector<std::pair<int, int> > &objectDimTags,
3838 const std::vector<std::pair<int, int> > &toolDimTags,
3839 std::vector<std::pair<int, int> > &outDimTags,
3840 std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap,
3841 bool removeObject,
bool removeTool)
3844 toolDimTags, outDimTags, outDimTagsMap, removeObject,
3849 int tag,
const std::vector<std::pair<int, int> > &objectDimTags,
3850 const std::vector<std::pair<int, int> > &toolDimTags,
3851 std::vector<std::pair<int, int> > &outDimTags,
3852 std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap,
3853 bool removeObject,
bool removeTool)
3856 toolDimTags, outDimTags, outDimTagsMap, removeObject,
3861 int tag,
const std::vector<std::pair<int, int> > &objectDimTags,
3862 const std::vector<std::pair<int, int> > &toolDimTags,
3863 std::vector<std::pair<int, int> > &outDimTags,
3864 std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap,
3865 bool removeObject,
bool removeTool)
3868 toolDimTags, outDimTags, outDimTagsMap, removeObject,
3872 int OCC_Internals::_getMaxDim()
3874 if(_tagSolid.Extent())
return 3;
3875 if(_tagFace.Extent())
return 2;
3876 if(_tagEdge.Extent())
return 1;
3880 void OCC_Internals::_getAllDimTags(std::vector<std::pair<int, int> > &dimTags,
3883 for(
int d = -2; d < 4; d++) {
3884 if(dim != 99 && dim != d)
continue;
3885 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp;
3887 case 0: exp.Initialize(_tagVertex);
break;
3888 case 1: exp.Initialize(_tagEdge);
break;
3889 case 2: exp.Initialize(_tagFace);
break;
3890 case 3: exp.Initialize(_tagSolid);
break;
3891 case -1: exp.Initialize(_tagWire);
break;
3892 case -2: exp.Initialize(_tagShell);
break;
3894 for(; exp.More(); exp.Next())
3895 dimTags.push_back(std::pair<int, int>(d, exp.Key()));
3901 std::vector<std::pair<int, int> > objectDimTags, toolDimTags, outDimTags;
3902 std::vector<std::vector<std::pair<int, int> > > outDimTagsMap;
3903 _getAllDimTags(objectDimTags, _getMaxDim());
3904 booleanFragments(-1, objectDimTags, toolDimTags, outDimTags, outDimTagsMap,
3910 std::vector<std::pair<int, int> > objectDimTags, toolDimTags, outDimTags;
3911 std::vector<std::vector<std::pair<int, int> > > outDimTagsMap;
3912 for(std::size_t i = 0; i <
tags.size(); i++)
3913 objectDimTags.push_back(std::pair<int, int>(0,
tags[i]));
3915 outDimTagsMap,
true,
true);
3918 void _addSimpleShapes(
const TopoDS_Shape &shape,
3919 std::vector<TopoDS_Shape> &simple)
3921 if(shape.ShapeType() != TopAbs_COMPOUND &&
3922 shape.ShapeType() != TopAbs_COMPSOLID) {
3923 simple.push_back(shape);
3927 TopTools_MapOfShape mapShape;
3928 TopoDS_Iterator It(shape, Standard_True, Standard_True);
3930 for(; It.More(); It.Next()) {
3931 const TopoDS_Shape &s = It.Value();
3932 if(mapShape.Add(s)) {
3933 if(s.ShapeType() == TopAbs_COMPOUND ||
3934 s.ShapeType() == TopAbs_COMPSOLID) {
3935 _addSimpleShapes(s, simple);
3938 simple.push_back(s);
3944 bool OCC_Internals::_transform(
3945 const std::vector<std::pair<int, int> > &inDimTags,
3946 BRepBuilderAPI_Transform *tfo, BRepBuilderAPI_GTransform *gtfo)
3953 for(std::size_t i = 0; i < inDimTags.size(); i++) {
3954 int dim = inDimTags[i].first;
3955 int tag = inDimTags[i].second;
3956 if(!_isBound(dim, tag)) {
3957 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d", dim,
3961 TopoDS_Shape shape = _find(dim, tag);
3965 std::vector<TopoDS_Shape> inShapes;
3966 _addSimpleShapes(
c, inShapes);
3968 TopoDS_Shape result;
3970 tfo->Perform(
c, Standard_False);
3971 if(!tfo->IsDone()) {
3972 Msg::Error(
"Could not apply transformation");
3975 result = tfo->Shape();
3978 gtfo->Perform(
c, Standard_False);
3979 if(!gtfo->IsDone()) {
3980 Msg::Error(
"Could not apply transformation");
3983 result = gtfo->Shape();
3987 TopExp_Explorer exp0;
3988 for(exp0.Init(
c, TopAbs_VERTEX); exp0.More(); exp0.Next()) {
3989 TopoDS_Vertex vertex = TopoDS::Vertex(exp0.Current());
3990 TopoDS_Shape transformed;
3992 transformed = tfo->ModifiedShape(vertex);
3994 transformed = gtfo->ModifiedShape(vertex);
3995 if(!transformed.IsNull()) {
3996 double lc = _attributes->getMeshSize(0, vertex);
3997 if(lc > 0 && lc <
MAX_LC)
3998 _attributes->insert(
new OCCAttributes(0, transformed, lc));
4003 std::vector<TopoDS_Shape> outShapes;
4004 _addSimpleShapes(result, outShapes);
4006 if(inShapes.size() != inDimTags.size() ||
4007 inShapes.size() != outShapes.size()) {
4008 Msg::Error(
"OpenCASCADE transform changed the number of shapes");
4011 for(std::size_t i = 0; i < inDimTags.size(); i++) {
4012 int dim = inDimTags[i].first;
4013 int tag = inDimTags[i].second;
4019 _unbind(inShapes[i], dim, tag,
true);
4027 _unbindWithoutChecks(inShapes[i]);
4031 _bind(outShapes[i], dim, tag,
true);
4038 const std::vector<std::pair<int, int> > &inDimTags,
double dx,
double dy,
4043 t.SetTranslation(gp_Pnt(0, 0, 0), gp_Pnt(dx, dy, dz));
4044 BRepBuilderAPI_Transform tfo(t);
4045 return _transform(inDimTags, &tfo,
nullptr);
4046 }
catch(Standard_Failure &err) {
4047 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
4053 double x,
double y,
double z,
double ax,
double ay,
4054 double az,
double angle)
4058 gp_Ax1 axisOfRevolution(gp_Pnt(x, y,
z), gp_Dir(ax, ay, az));
4059 t.SetRotation(axisOfRevolution,
angle);
4060 BRepBuilderAPI_Transform tfo(t);
4061 return _transform(inDimTags, &tfo,
nullptr);
4062 }
catch(Standard_Failure &err) {
4063 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
4069 double x,
double y,
double z,
double a,
double b,
4074 gt.SetVectorialPart(gp_Mat(a, 0, 0, 0, b, 0, 0, 0,
c));
4075 gt.SetTranslationPart(gp_XYZ(x * (1 - a), y * (1 - b),
z * (1 -
c)));
4076 BRepBuilderAPI_GTransform gtfo(gt);
4077 return _transform(inDimTags,
nullptr, >fo);
4078 }
catch(Standard_Failure &err) {
4079 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
4085 double a,
double b,
double c,
double d)
4089 double p = (a * a + b * b +
c *
c);
4091 double f = -2.0 / p;
4092 gt.SetVectorialPart(gp_Mat(1 + a * a *
f, a * b *
f, a *
c *
f, a * b *
f,
4093 1. + b * b *
f, b *
c *
f, a *
c *
f, b *
c *
f,
4095 gt.SetTranslationPart(gp_XYZ(a * d *
f, b * d *
f,
c * d *
f));
4096 BRepBuilderAPI_GTransform gtfo(gt);
4097 return _transform(inDimTags,
nullptr, >fo);
4098 }
catch(Standard_Failure &err) {
4099 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
4105 const std::vector<double> &mat)
4108 std::vector<double> a(mat);
4110 Msg::Warning(
"%d < 12 entries in affine transform matrix", (
int)a.size());
4114 gt.SetVectorialPart(
4115 gp_Mat(a[0], a[1], a[2], a[4], a[5], a[6], a[8], a[9], a[10]));
4116 gt.SetTranslationPart(gp_XYZ(a[3], a[7], a[11]));
4117 BRepBuilderAPI_GTransform gtfo(gt);
4118 return _transform(inDimTags,
nullptr, >fo);
4119 }
catch(Standard_Failure &err) {
4120 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
4126 std::vector<std::pair<int, int> > &outDimTags)
4133 for(std::size_t i = 0; i < inDimTags.size(); i++) {
4134 int dim = inDimTags[i].first;
4135 int tag = inDimTags[i].second;
4136 if(!_isBound(dim, tag)) {
4137 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d", dim,
4141 TopoDS_Shape shape = _find(dim, tag);
4145 TopoDS_Shape result = BRepBuilderAPI_Copy(
c).Shape();
4146 _multiBind(result, -1, outDimTags,
true,
true);
4152 if(!_isBound(dim, tag)) {
4153 Msg::Warning(
"Unknown OpenCASCADE entity of dimension %d with tag %d", dim,
4157 _unbind(_find(dim, tag), dim, tag, recursive);
4165 for(std::size_t i = 0; i < dimTags.size(); i++) {
4166 if(!
remove(dimTags[i].first, dimTags[i].second, recursive)) ret =
false;
4171 static void setTargetUnit(
const std::string &unit)
4173 if(unit.empty())
return;
4174 if(!Interface_Static::SetCVal(
"xstep.cascade.unit", unit.c_str()))
4175 Msg::Error(
"Could not set OpenCASCADE target unit '%s'", unit.c_str());
4178 #if defined(HAVE_OCC_CAF)
4180 static void getColorRGB(
const Quantity_Color &col,
double &r,
double &g,
double &b)
4182 #if OCC_VERSION_HEX >= 0x070500
4185 col.Values(r, g, b, Quantity_TOC_sRGB);
4193 static void setShapeAttributes(OCCAttributesRTree *attributes,
4194 const Handle_XCAFDoc_ShapeTool &shapeTool,
4195 const Handle_XCAFDoc_ColorTool &colorTool,
4196 const Handle_XCAFDoc_MaterialTool &materialTool,
4197 const TDF_Label &label,
4198 const TopLoc_Location &loc,
4199 const std::string &pathName,
bool isRef)
4201 std::string phys = pathName;
4202 Handle(TDataStd_Name) n;
4203 if(label.FindAttribute(TDataStd_Name::GetID(), n)) {
4204 TCollection_ExtendedString name = n->Get();
4205 if(!phys.empty()) phys +=
"/";
4206 phys += TCollection_AsciiString(name).ToCString();
4209 TopLoc_Location partLoc = loc;
4210 Handle(XCAFDoc_Location) l;
4211 if(label.FindAttribute(XCAFDoc_Location::GetID(), l)) {
4213 partLoc = partLoc * l->Get();
4219 if(shapeTool->IsReference(label) && shapeTool->GetReferredShape(label, ref)) {
4220 setShapeAttributes(attributes, shapeTool, colorTool, materialTool, ref,
4221 partLoc, phys,
true);
4224 if(shapeTool->IsSimpleShape(label) && (isRef || shapeTool->IsFree(label))) {
4225 TopoDS_Shape shape = shapeTool->GetShape(label);
4226 shape.Location(isRef ? loc : partLoc);
4228 (shape.ShapeType() == TopAbs_VERTEX) ? 0 :
4229 (shape.ShapeType() == TopAbs_EDGE || shape.ShapeType() == TopAbs_WIRE) ?
4231 (shape.ShapeType() == TopAbs_FACE || shape.ShapeType() == TopAbs_SHELL) ?
4235 Handle(TCollection_HAsciiString) matName;
4236 Handle(TCollection_HAsciiString) matDescription;
4237 Standard_Real matDensity;
4238 Handle(TCollection_HAsciiString) matDensName;
4239 Handle(TCollection_HAsciiString) matDensValType;
4240 if(materialTool->GetMaterial(label, matName, matDescription, matDensity,
4241 matDensName, matDensValType)) {
4242 if(!phys.empty()) phys +=
" & ";
4243 phys += matName->ToCString();
4244 Msg::Info(
" - Label & material '%s' (%dD)", phys.c_str());
4246 else if(phys.size()) {
4247 Msg::Info(
" - Label '%s' (%dD)", phys.c_str(), dim);
4249 if(phys.size()) { attributes->insert(
new OCCAttributes(dim, shape, phys)); }
4252 if(colorTool->GetColor(label, XCAFDoc_ColorGen, col)) {
4254 getColorRGB(col, r, g, b);
4255 Msg::Info(
" - Color (%g, %g, %g) (%dD)", r, g, b, dim);
4256 attributes->insert(
new OCCAttributes(dim, shape, r, g, b, 1.));
4258 else if(colorTool->GetColor(label, XCAFDoc_ColorSurf, col)) {
4260 getColorRGB(col, r, g, b);
4261 Msg::Info(
" - Color (%g, %g, %g) (%dD & Surfaces)", r, g, b, dim);
4262 attributes->insert(
new OCCAttributes(dim, shape, r, g, b, 1., 1));
4264 else if(colorTool->GetColor(label, XCAFDoc_ColorCurv, col)) {
4266 getColorRGB(col, r, g, b);
4267 Msg::Info(
" - Color (%g, %g, %g) (%dD & Curves)", r, g, b, dim);
4268 attributes->insert(
new OCCAttributes(dim, shape, r, g, b, 1., 2));
4272 TopExp_Explorer xp2(shape, TopAbs_FACE);
4274 if(colorTool->GetColor(xp2.Current(), XCAFDoc_ColorGen, col) ||
4275 colorTool->GetColor(xp2.Current(), XCAFDoc_ColorSurf, col) ||
4276 colorTool->GetColor(xp2.Current(), XCAFDoc_ColorCurv, col)) {
4278 getColorRGB(col, r, g, b);
4279 Msg::Info(
" - Color (%g, %g, %g) (Surface)", r, g, b);
4280 TopoDS_Face face = TopoDS::Face(xp2.Current());
4281 attributes->insert(
new OCCAttributes(2, face, r, g, b, 1.));
4287 TopExp_Explorer xp1(shape, TopAbs_EDGE);
4289 if(colorTool->GetColor(xp1.Current(), XCAFDoc_ColorGen, col) ||
4290 colorTool->GetColor(xp1.Current(), XCAFDoc_ColorSurf, col) ||
4291 colorTool->GetColor(xp1.Current(), XCAFDoc_ColorCurv, col)) {
4293 getColorRGB(col, r, g, b);
4294 Msg::Info(
" - Color (%g, %g, %g) (Curve)", r, g, b);
4295 TopoDS_Edge edge = TopoDS::Edge(xp1.Current());
4296 attributes->insert(
new OCCAttributes(1, edge, r, g, b, 1.));
4303 for(TDF_ChildIterator it(label); it.More(); it.Next()) {
4304 setShapeAttributes(attributes, shapeTool, colorTool, materialTool,
4305 it.Value(), partLoc, phys, isRef);
4311 void readAttributes(OCCAttributesRTree *attributes, T &reader,
4312 const std::string &format)
4315 static Handle_XCAFApp_Application dummy_app =
4316 XCAFApp_Application::GetApplication();
4318 Handle_TDocStd_Document doc;
4321 if(dummy_app->NbDocuments() > 0) {
4322 dummy_app->GetDocument(1, doc);
4323 dummy_app->Close(doc);
4325 dummy_app->NewDocument(format.c_str(), doc);
4327 reader.Transfer(doc);
4328 TDF_Label mainLabel = doc->Main();
4329 Handle_XCAFDoc_ShapeTool shapeTool =
4330 XCAFDoc_DocumentTool::ShapeTool(mainLabel);
4331 Handle_XCAFDoc_ColorTool colorTool =
4332 XCAFDoc_DocumentTool::ColorTool(mainLabel);
4333 Handle_XCAFDoc_MaterialTool materialTool =
4334 XCAFDoc_DocumentTool::MaterialTool(mainLabel);
4336 setShapeAttributes(attributes, shapeTool, colorTool, materialTool, mainLabel,
4337 TopLoc_Location(),
"",
false);
4343 bool highestDimOnly,
4344 std::vector<std::pair<int, int> > &outDimTags,
4345 const std::string &format)
4349 TCollection_AsciiString occfile(fileName.c_str());
4351 TopoDS_Shape result;
4353 if(format ==
"brep" || split[2] ==
".brep" || split[2] ==
".BREP") {
4354 BRep_Builder aBuilder;
4355 BRepTools::Read(result, occfile.ToCString(), aBuilder);
4357 else if(format ==
"step" || split[2] ==
".step" || split[2] ==
".stp" ||
4358 split[2] ==
".STEP" || split[2] ==
".STP") {
4359 STEPControl_Reader reader;
4361 Interface_Static::SetIVal(
"read.step.ideas", 1);
4362 Interface_Static::SetIVal(
"read.step.nonmanifold", 1);
4363 #if defined(HAVE_OCC_CAF)
4365 STEPCAFControl_Reader cafreader;
4366 if(cafreader.ReadFile(occfile.ToCString()) != IFSelect_RetDone) {
4367 Msg::Error(
"Could not read file '%s'", fileName.c_str());
4371 readAttributes(_attributes, cafreader,
"STEP-XCAF");
4372 reader = cafreader.ChangeReader();
4374 if(reader.ReadFile(occfile.ToCString()) != IFSelect_RetDone) {
4375 Msg::Error(
"Could not read file '%s'", fileName.c_str());
4379 reader.NbRootsForTransfer();
4380 reader.TransferRoots();
4381 result = reader.OneShape();
4383 else if(format ==
"iges" || split[2] ==
".iges" || split[2] ==
".igs" ||
4384 split[2] ==
".IGES" || split[2] ==
".IGS") {
4386 #if defined(HAVE_OCC_CAF)
4387 IGESCAFControl_Reader reader;
4388 if(reader.ReadFile(occfile.ToCString()) != IFSelect_RetDone) {
4389 Msg::Error(
"Could not read file '%s'", fileName.c_str());
4393 readAttributes(_attributes, reader,
"IGES-XCAF");
4395 IGESControl_Reader reader;
4396 if(reader.ReadFile(occfile.ToCString()) != IFSelect_RetDone) {
4397 Msg::Error(
"Could not read file '%s'", fileName.c_str());
4401 reader.NbRootsForTransfer();
4402 reader.TransferRoots();
4403 result = reader.OneShape();
4406 Msg::Error(
"Unknown file type '%s'", fileName.c_str());
4409 }
catch(Standard_Failure &err) {
4410 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
4414 BRepTools::Clean(result);
4423 _multiBind(result, -1, outDimTags, highestDimOnly,
true);
4428 std::vector<std::pair<int, int> > &outDimTags)
4430 if(!shape)
return false;
4431 _multiBind(*shape, -1, outDimTags, highestDimOnly,
true);
4436 const std::string &format,
bool onlyVisible)
4450 Msg::Debug(
"Adding volume %d to exported compound", gr->
tag());
4460 for(
auto gr : regions) {
4469 Msg::Debug(
"Adding surface %d to exported compound", gf->
tag());
4479 for(
auto gf :
faces) {
4488 Msg::Debug(
"Adding curve %d to exported compound", ge->
tag());
4498 for(
auto ge :
edges) {
4507 Msg::Debug(
"Adding point %d to exported compound", gv->
tag());
4514 TCollection_AsciiString occfile(fileName.c_str());
4517 if(format ==
"brep" || split[2] ==
".brep" || split[2] ==
".BREP") {
4518 BRepTools::Write(
c, occfile.ToCString());
4520 else if(format ==
"step" || split[2] ==
".step" || split[2] ==
".stp" ||
4521 split[2] ==
".STEP" || split[2] ==
".STP") {
4522 STEPControl_Writer writer;
4527 Interface_Static::SetIVal(
"write.step.nonmanifold", 1);
4529 if(writer.Transfer(
c, STEPControl_AsIs) == IFSelect_RetDone) {
4530 if(writer.Write(occfile.ToCString()) != IFSelect_RetDone) {
4531 Msg::Error(
"Could not create file '%s'", fileName.c_str());
4540 }
catch(Standard_Failure &err) {
4541 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
4549 if(dim != 0)
return;
4550 if(_tagVertex.IsBound(tag)) {
4551 OCCAttributes *a =
new OCCAttributes(0, _tagVertex.Find(tag), size);
4553 _attributes->remove(a);
4554 _attributes->insert(a);
4561 for(
int d = 0; d < 4; d++) {
4562 if(dim != -1 && dim != d)
continue;
4563 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp;
4565 case 0: exp.Initialize(_tagVertex);
break;
4566 case 1: exp.Initialize(_tagEdge);
break;
4567 case 2: exp.Initialize(_tagFace);
break;
4568 case 3: exp.Initialize(_tagSolid);
break;
4570 for(; exp.More(); exp.Next())
4571 dimTags.push_back(std::make_pair(d, exp.Key()));
4578 if(_tagVertex.IsBound(tag)) {
4579 gp_Pnt pnt = BRep_Tool::Pnt(TopoDS::Vertex(_tagVertex.Find(tag)));
4588 bool OCC_Internals::_getBoundingBox(
const TopoDS_Shape &shape,
double &xmin,
4589 double &ymin,
double &zmin,
double &xmax,
4590 double &ymax,
double &zmax)
4593 std::vector<SPoint3> vertices;
4594 std::vector<SVector3> normals;
4595 std::vector<int> triangles;
4596 _makeSTL(shape, vertices, normals, triangles);
4605 if(vertices.size()) {
4607 for(std::size_t i = 0; i < vertices.size(); i++)
4608 bbox += vertices[i];
4609 xmin = bbox.
min().
x();
4610 ymin = bbox.
min().
y();
4611 zmin = bbox.
min().
z();
4612 xmax = bbox.
max().
x();
4613 ymax = bbox.
max().
y();
4614 zmax = bbox.
max().
z();
4620 BRepBndLib::Add(shape, b);
4621 }
catch(Standard_Failure &err) {
4622 Msg::Error(
"OpenCASCADE exception %s", err.GetMessageString());
4625 b.Get(xmin, ymin, zmin, xmax, ymax, zmax);
4630 double &zmin,
double &xmax,
double &ymax,
4633 if(!_isBound(dim, tag)) {
4634 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d", dim,
4638 TopoDS_Shape shape = _find(dim, tag);
4639 return _getBoundingBox(shape, xmin, ymin, zmin, xmax, ymax, zmax);
4643 double xmin,
double ymin,
double zmin,
double xmax,
double ymax,
double zmax,
4644 std::vector<std::pair<int, int> > &dimTags,
int dim)
4647 for(
int d = 0; d < 4; d++) {
4648 if(dim != -1 && dim != d)
continue;
4649 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp;
4651 case 0: exp.Initialize(_tagVertex);
break;
4652 case 1: exp.Initialize(_tagEdge);
break;
4653 case 2: exp.Initialize(_tagFace);
break;
4654 case 3: exp.Initialize(_tagSolid);
break;
4656 for(; exp.More(); exp.Next()) {
4657 double xmin2 = 0, ymin2 = 0, zmin2 = 0, xmax2 = 0, ymax2 = 0, zmax2 = 0;
4658 _getBoundingBox(exp.Value(), xmin2, ymin2, zmin2, xmax2, ymax2, zmax2);
4659 if(xmin2 >= xmin && xmax2 <= xmax && ymin2 >= ymin && ymax2 <= ymax &&
4660 zmin2 >= zmin && zmax2 <= zmax)
4661 dimTags.push_back(std::make_pair(d, exp.Key()));
4668 std::vector<std::vector<int> > &curveTags)
4670 if(!_tagFace.IsBound(surfaceTag)) {
4671 Msg::Error(
"Unknown OpenCASCADE surface with tag %d", surfaceTag);
4674 curveLoopTags.clear();
4676 TopoDS_Face face = TopoDS::Face(_tagFace.Find(surfaceTag));
4677 TopExp_Explorer exp0;
4678 for(exp0.Init(face, TopAbs_WIRE); exp0.More(); exp0.Next()) {
4679 TopoDS_Wire wire = TopoDS::Wire(exp0.Current());
4680 if(_wireTag.IsBound(wire)) {
4681 curveLoopTags.push_back(_wireTag.Find(wire));
4686 curveLoopTags.push_back(t);
4688 curveTags.push_back(std::vector<int>());
4689 BRepTools_WireExplorer exp1;
4690 for(exp1.Init(wire); exp1.More(); exp1.Next()) {
4691 TopoDS_Edge edge = exp1.Current();
4692 if(_edgeTag.IsBound(edge)) {
4693 curveTags.back().push_back(_edgeTag.Find(edge));
4698 curveTags.back().push_back(t);
4706 std::vector<std::vector<int> > &surfaceTags)
4708 if(!_tagSolid.IsBound(volumeTag)) {
4709 Msg::Error(
"Unknown OpenCASCADE volume with tag %d", volumeTag);
4712 surfaceLoopTags.clear();
4713 surfaceTags.clear();
4714 TopoDS_Solid solid = TopoDS::Solid(_tagSolid.Find(volumeTag));
4715 TopExp_Explorer exp0;
4716 for(exp0.Init(solid, TopAbs_SHELL); exp0.More(); exp0.Next()) {
4717 TopoDS_Shell shell = TopoDS::Shell(exp0.Current());
4718 if(_shellTag.IsBound(shell)) {
4719 surfaceLoopTags.push_back(_shellTag.Find(shell));
4724 surfaceLoopTags.push_back(t);
4726 surfaceTags.push_back(std::vector<int>());
4727 TopExp_Explorer exp1;
4728 for(exp1.Init(shell, TopAbs_FACE); exp1.More(); exp1.Next()) {
4729 TopoDS_Face face = TopoDS::Face(exp1.Current());
4730 if(_faceTag.IsBound(face)) {
4731 surfaceTags.back().push_back(_faceTag.Find(face));
4736 surfaceTags.back().push_back(t);
4745 if(!_isBound(dim, tag)) {
4746 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d", dim,
4750 TopoDS_Shape shape = _find(dim, tag);
4751 GProp_GProps System;
4753 case 1: BRepGProp::LinearProperties(shape, System);
break;
4754 case 2: BRepGProp::SurfaceProperties(shape, System);
break;
4755 case 3: BRepGProp::VolumeProperties(shape, System);
break;
4757 mass = System.Mass();
4764 if(!_isBound(dim, tag)) {
4765 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d", dim,
4769 TopoDS_Shape shape = _find(dim, tag);
4770 GProp_GProps System;
4772 case 1: BRepGProp::LinearProperties(shape, System);
break;
4773 case 2: BRepGProp::SurfaceProperties(shape, System);
break;
4774 case 3: BRepGProp::VolumeProperties(shape, System);
break;
4776 gp_Pnt
c = System.CentreOfMass();
4784 std::vector<double> &mat)
4786 if(!_isBound(dim, tag)) {
4787 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d", dim,
4791 TopoDS_Shape shape = _find(dim, tag);
4792 GProp_GProps System;
4794 case 1: BRepGProp::LinearProperties(shape, System);
break;
4795 case 2: BRepGProp::SurfaceProperties(shape, System);
break;
4796 case 3: BRepGProp::VolumeProperties(shape, System);
break;
4798 gp_Mat m = System.MatrixOfInertia();
4800 for(
int i = 1; i <= 3; i++)
4801 for(
int j = 1; j <= 3; j++) mat.push_back(m.Value(i, j));
4807 double &x1,
double &y1,
double &z1,
4808 double &x2,
double &y2,
double &z2)
4810 if(!_isBound(dim1, tag1)) {
4811 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d",
4815 TopoDS_Shape shape1 = _find(dim1, tag1);
4817 if(!_isBound(dim2, tag2)) {
4818 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d",
4822 TopoDS_Shape shape2 = _find(dim2, tag2);
4824 BRepExtrema_DistShapeShape dist(shape1, shape2);
4826 double dmin = 1.e200;
4827 gp_Pnt pmin1, pmin2;
4828 for(
int i = 1; i <= dist.NbSolution(); i++) {
4829 gp_Pnt p1 = dist.PointOnShape1(i);
4830 gp_Pnt p2 = dist.PointOnShape2(i);
4831 double d = p1.Distance(p2);
4850 bool const sortByInvDim(std::pair<int, int>
const &lhs,
4851 std::pair<int, int>
const &rhs)
4853 return lhs.first > rhs.first;
4858 Msg::Debug(
"Syncing OCC_Internals with GModel");
4862 std::vector<std::pair<int, int> > toRemove;
4863 toRemove.insert(toRemove.end(), _toRemove.begin(), _toRemove.end());
4864 Msg::Debug(
"Sync is removing %d model entities", toRemove.size());
4867 std::sort(toRemove.begin(), toRemove.end(), sortByInvDim);
4868 std::vector<GEntity*> removed;
4869 model->
remove(toRemove, removed);
4870 Msg::Debug(
"Destroying %lu entities in model", removed.size());
4871 for(std::size_t i = 0; i < removed.size(); i++)
delete removed[i];
4882 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp0(_tagVertex);
4883 for(; exp0.More(); exp0.Next()) _addShapeToMaps(exp0.Value());
4884 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp1(_tagEdge);
4885 for(; exp1.More(); exp1.Next()) _addShapeToMaps(exp1.Value());
4886 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp2(_tagFace);
4887 for(; exp2.More(); exp2.Next()) _addShapeToMaps(exp2.Value());
4888 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp3(_tagSolid);
4889 for(; exp3.More(); exp3.Next()) _addShapeToMaps(exp3.Value());
4896 for(
int i = 1; i <= _vmap.Extent(); i++) {
4897 TopoDS_Vertex vertex = TopoDS::Vertex(_vmap(i));
4898 GVertex *occv = getVertexForOCCShape(model, vertex);
4901 if(_vertexTag.IsBound(vertex))
4902 tag = _vertexTag.Find(vertex);
4905 Msg::Debug(
"Binding unbound OpenCASCADE point to tag %d", tag);
4908 occv =
new OCCVertex(model, vertex, tag);
4911 double lc = _attributes->getMeshSize(0, vertex);
4913 std::vector<std::string> labels;
4914 _attributes->getLabels(0, vertex, labels);
4916 unsigned int col = 0, boundary = 0;
4917 if(!occv->
useColor() && _attributes->getColor(0, vertex, col, boundary)) {
4921 for(
int i = 1; i <= _emap.Extent(); i++) {
4922 TopoDS_Edge edge = TopoDS::Edge(_emap(i));
4923 GEdge *occe = getEdgeForOCCShape(model, edge);
4925 GVertex *v1 = getVertexForOCCShape(model, TopExp::FirstVertex(edge));
4926 GVertex *v2 = getVertexForOCCShape(model, TopExp::LastVertex(edge));
4928 if(_edgeTag.IsBound(edge))
4929 tag = _edgeTag.Find(edge);
4932 Msg::Debug(
"Binding unbound OpenCASCADE curve to tag %d", tag);
4935 occe =
new OCCEdge(model, edge, tag, v1, v2);
4938 _copyExtrudedAttributes(edge, occe);
4939 std::vector<std::string> labels;
4940 _attributes->getLabels(1, edge, labels);
4942 unsigned int col = 0, boundary = 0;
4943 if(!occe->
useColor() && _attributes->getColor(1, edge, col, boundary)) {
4947 for(
int i = 1; i <= _fmap.Extent(); i++) {
4948 TopoDS_Face face = TopoDS::Face(_fmap(i));
4949 GFace *occf = getFaceForOCCShape(model, face);
4952 if(_faceTag.IsBound(face))
4953 tag = _faceTag.Find(face);
4956 Msg::Debug(
"Binding unbound OpenCASCADE surface to tag %d", tag);
4959 occf =
new OCCFace(model, face, tag);
4962 _copyExtrudedAttributes(face, occf);
4963 std::vector<std::string> labels;
4964 _attributes->getLabels(2, face, labels);
4966 unsigned int col = 0, boundary = 0;
4967 if(!occf->
useColor() && _attributes->getColor(2, face, col, boundary)) {
4971 for(std::size_t j = 0; j <
edges.size(); j++) {
4972 if(!
edges[j]->useColor())
edges[j]->setColor(col);
4977 for(
int i = 1; i <= _somap.Extent(); i++) {
4978 TopoDS_Solid region = TopoDS::Solid(_somap(i));
4979 GRegion *occr = getRegionForOCCShape(model, region);
4982 if(_solidTag.IsBound(region))
4983 tag = _solidTag(region);
4986 Msg::Debug(
"Binding unbound OpenCASCADE volume to tag %d", tag);
4989 occr =
new OCCRegion(model, region, tag);
4992 _copyExtrudedAttributes(region, occr);
4993 std::vector<std::string> labels;
4994 _attributes->getLabels(3, region, labels);
4996 unsigned int col = 0, boundary = 0;
4997 if(!occr->
useColor() && _attributes->getColor(3, region, col, boundary)) {
5001 for(std::size_t j = 0; j <
faces.size(); j++) {
5002 if(!
faces[j]->useColor())
faces[j]->setColor(col);
5005 else if(boundary == 2) {
5007 for(std::size_t j = 0; j <
edges.size(); j++) {
5008 if(!
edges[j]->useColor())
edges[j]->setColor(col);
5030 const TopoDS_Vertex &toFind)
5032 if(_vertexTag.IsBound(toFind))
5037 GEdge *OCC_Internals::getEdgeForOCCShape(
GModel *model,
5038 const TopoDS_Edge &toFind)
5040 if(_edgeTag.IsBound(toFind))
5045 GFace *OCC_Internals::getFaceForOCCShape(
GModel *model,
5046 const TopoDS_Face &toFind)
5048 if(_faceTag.IsBound(toFind))
5054 const TopoDS_Solid &toFind)
5056 if(_solidTag.IsBound(toFind))
5061 void OCC_Internals::_addShapeToMaps(
const TopoDS_Shape &shape)
5064 TopExp_Explorer exp0, exp1, exp2, exp3, exp4, exp5;
5065 for(exp0.Init(shape, TopAbs_SOLID); exp0.More(); exp0.Next()) {
5066 TopoDS_Solid solid = TopoDS::Solid(exp0.Current());
5067 if(_somap.FindIndex(solid) < 1) {
5069 for(exp1.Init(solid, TopAbs_SHELL); exp1.More(); exp1.Next()) {
5070 TopoDS_Shell shell = TopoDS::Shell(exp1.Current());
5071 if(_shmap.FindIndex(shell) < 1) {
5074 for(exp2.Init(shell, TopAbs_FACE); exp2.More(); exp2.Next()) {
5075 TopoDS_Face face = TopoDS::Face(exp2.Current());
5076 if(_fmap.FindIndex(face) < 1) {
5079 for(exp3.Init(face.Oriented(TopAbs_FORWARD), TopAbs_WIRE);
5080 exp3.More(); exp3.Next()) {
5082 TopoDS_Wire wire = TopoDS::Wire(exp3.Current());
5083 if(_wmap.FindIndex(wire) < 1) {
5086 for(exp4.Init(wire, TopAbs_EDGE); exp4.More(); exp4.Next()) {
5087 TopoDS_Edge edge = TopoDS::Edge(exp4.Current());
5088 if(_emap.FindIndex(edge) < 1) {
5091 for(exp5.Init(edge, TopAbs_VERTEX); exp5.More();
5093 TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current());
5094 if(_vmap.FindIndex(vertex) < 1) _vmap.Add(vertex);
5108 for(exp1.Init(shape, TopAbs_SHELL, TopAbs_SOLID); exp1.More(); exp1.Next()) {
5109 const TopoDS_Shape &shell = exp1.Current();
5110 if(_shmap.FindIndex(shell) < 1) {
5113 for(exp2.Init(shell, TopAbs_FACE); exp2.More(); exp2.Next()) {
5114 TopoDS_Face face = TopoDS::Face(exp2.Current());
5115 if(_fmap.FindIndex(face) < 1) {
5118 for(exp3.Init(face, TopAbs_WIRE); exp3.More(); exp3.Next()) {
5119 TopoDS_Wire wire = TopoDS::Wire(exp3.Current());
5120 if(_wmap.FindIndex(wire) < 1) {
5123 for(exp4.Init(wire, TopAbs_EDGE); exp4.More(); exp4.Next()) {
5124 TopoDS_Edge edge = TopoDS::Edge(exp4.Current());
5125 if(_emap.FindIndex(edge) < 1) {
5128 for(exp5.Init(edge, TopAbs_VERTEX); exp5.More();
5130 TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current());
5131 if(_vmap.FindIndex(vertex) < 1) _vmap.Add(vertex);
5143 for(exp2.Init(shape, TopAbs_FACE, TopAbs_SHELL); exp2.More(); exp2.Next()) {
5144 TopoDS_Face face = TopoDS::Face(exp2.Current());
5145 if(_fmap.FindIndex(face) < 1) {
5148 for(exp3.Init(face, TopAbs_WIRE); exp3.More(); exp3.Next()) {
5149 TopoDS_Wire wire = TopoDS::Wire(exp3.Current());
5150 if(_wmap.FindIndex(wire) < 1) {
5153 for(exp4.Init(wire, TopAbs_EDGE); exp4.More(); exp4.Next()) {
5154 TopoDS_Edge edge = TopoDS::Edge(exp4.Current());
5155 if(_emap.FindIndex(edge) < 1) {
5158 for(exp5.Init(edge, TopAbs_VERTEX); exp5.More(); exp5.Next()) {
5159 TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current());
5160 if(_vmap.FindIndex(vertex) < 1) _vmap.Add(vertex);
5170 for(exp3.Init(shape, TopAbs_WIRE, TopAbs_FACE); exp3.More(); exp3.Next()) {
5171 TopoDS_Wire wire = TopoDS::Wire(exp3.Current());
5172 if(_wmap.FindIndex(wire) < 1) {
5175 for(exp4.Init(wire, TopAbs_EDGE); exp4.More(); exp4.Next()) {
5176 TopoDS_Edge edge = TopoDS::Edge(exp4.Current());
5177 if(_emap.FindIndex(edge) < 1) {
5180 for(exp5.Init(edge, TopAbs_VERTEX); exp5.More(); exp5.Next()) {
5181 TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current());
5182 if(_vmap.FindIndex(vertex) < 1) _vmap.Add(vertex);
5190 for(exp4.Init(shape, TopAbs_EDGE, TopAbs_WIRE); exp4.More(); exp4.Next()) {
5191 TopoDS_Edge edge = TopoDS::Edge(exp4.Current());
5192 if(_emap.FindIndex(edge) < 1) {
5195 for(exp5.Init(edge, TopAbs_VERTEX); exp5.More(); exp5.Next()) {
5196 TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current());
5197 if(_vmap.FindIndex(vertex) < 1) _vmap.Add(vertex);
5203 for(exp5.Init(shape, TopAbs_VERTEX, TopAbs_EDGE); exp5.More(); exp5.Next()) {
5204 TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current());
5205 if(_vmap.FindIndex(vertex) < 1) { _vmap.Add(vertex); }
5209 void OCC_Internals::_healShape(TopoDS_Shape &myshape,
double tolerance,
5210 bool fixDegenerated,
bool fixSmallEdges,
5211 bool fixSmallFaces,
bool sewFaces,
5212 bool makeSolids,
double scaling)
5214 if(scaling != 1.0) {
5215 Msg::Info(
"Scaling geometry (factor: %g)", scaling);
5217 t.SetScaleFactor(scaling);
5218 BRepBuilderAPI_Transform trsf(myshape, t);
5219 myshape = trsf.Shape();
5222 if(!fixDegenerated && !fixSmallEdges && !fixSmallFaces && !sewFaces &&
5235 _addShapeToMaps(myshape);
5237 TopExp_Explorer exp0, exp1;
5238 int nrc = 0, nrcs = 0;
5239 int nrso = _somap.Extent(), nrsh = _shmap.Extent(), nrf = _fmap.Extent();
5240 int nrw = _wmap.Extent(), nre = _emap.Extent(), nrv = _vmap.Extent();
5241 for(exp0.Init(myshape, TopAbs_COMPOUND); exp0.More(); exp0.Next()) nrc++;
5242 for(exp0.Init(myshape, TopAbs_COMPSOLID); exp0.More(); exp0.Next()) nrcs++;
5244 double surfacecont = 0;
5245 for(exp0.Init(myshape, TopAbs_FACE); exp0.More(); exp0.Next()) {
5246 TopoDS_Face face = TopoDS::Face(exp0.Current());
5247 GProp_GProps system;
5248 BRepGProp::SurfaceProperties(face, system);
5249 surfacecont += system.Mass();
5252 if(fixDegenerated) {
5253 Msg::Info(
" - Fixing degenerated edges and faces");
5256 ShapeBuild_ReShape rebuild;
5257 for(exp1.Init(myshape, TopAbs_EDGE); exp1.More(); exp1.Next()) {
5258 TopoDS_Edge edge = TopoDS::Edge(exp1.Current());
5259 if(BRep_Tool::Degenerated(edge)) rebuild.Remove(edge);
5261 myshape = rebuild.Apply(myshape);
5265 ShapeBuild_ReShape rebuild;
5266 for(exp0.Init(myshape, TopAbs_FACE); exp0.More(); exp0.Next()) {
5267 TopoDS_Face face = TopoDS::Face(exp0.Current());
5269 ShapeFix_Face sff(face);
5270 sff.FixAddNaturalBoundMode() = Standard_True;
5271 sff.FixSmallAreaWireMode() = Standard_True;
5274 if(sff.Status(ShapeExtend_DONE1) || sff.Status(ShapeExtend_DONE2) ||
5275 sff.Status(ShapeExtend_DONE3) || sff.Status(ShapeExtend_DONE4) ||
5276 sff.Status(ShapeExtend_DONE5)) {
5278 if(sff.Status(ShapeExtend_DONE1))
5280 else if(sff.Status(ShapeExtend_DONE2))
5281 Msg::Info(
" . Orientation of wires fixed");
5282 else if(sff.Status(ShapeExtend_DONE3))
5284 else if(sff.Status(ShapeExtend_DONE4))
5285 Msg::Info(
" . Small area wire removed");
5286 else if(sff.Status(ShapeExtend_DONE5))
5289 TopoDS_Face newface = sff.Face();
5290 rebuild.Replace(face, newface);
5293 myshape = rebuild.Apply(myshape);
5297 ShapeBuild_ReShape rebuild;
5298 for(exp1.Init(myshape, TopAbs_EDGE); exp1.More(); exp1.Next()) {
5299 TopoDS_Edge edge = TopoDS::Edge(exp1.Current());
5300 if(BRep_Tool::Degenerated(edge)) rebuild.Remove(edge);
5302 myshape = rebuild.Apply(myshape);
5310 ShapeBuild_ReShape rebuild;
5312 for(exp0.Init(myshape, TopAbs_FACE); exp0.More(); exp0.Next()) {
5313 TopoDS_Face face = TopoDS::Face(exp0.Current());
5315 for(exp1.Init(face, TopAbs_WIRE); exp1.More(); exp1.Next()) {
5316 TopoDS_Wire oldwire = TopoDS::Wire(exp1.Current());
5317 ShapeFix_Wire sfw(oldwire, face,
tolerance);
5318 sfw.ModifyTopologyMode() = Standard_True;
5319 sfw.ClosedWireMode() = Standard_True;
5320 bool replace =
false;
5321 replace = sfw.FixReorder() || replace;
5322 replace = sfw.FixConnected() || replace;
5324 if(sfw.FixSmall(Standard_False,
tolerance) &&
5325 !(sfw.StatusSmall(ShapeExtend_FAIL1) ||
5326 sfw.StatusSmall(ShapeExtend_FAIL2) ||
5327 sfw.StatusSmall(ShapeExtend_FAIL3))) {
5328 Msg::Info(
" . Fixed small edge in wire");
5331 else if(sfw.StatusSmall(ShapeExtend_FAIL1))
5332 Msg::Warning(
"Failed to fix small edge in wire, edge cannot be "
5333 "checked (no 3d curve and no pcurve)");
5334 else if(sfw.StatusSmall(ShapeExtend_FAIL2))
5335 Msg::Warning(
"Failed to fix small edge in wire, edge is null-"
5336 "length and has different vertives at begin and end, "
5337 "and lockvtx is True or ModifiyTopologyMode is False");
5338 else if(sfw.StatusSmall(ShapeExtend_FAIL3))
5339 Msg::Warning(
"Failed to fix small edge in wire, CheckConnected has "
5342 replace = sfw.FixEdgeCurves() || replace;
5343 replace = sfw.FixDegenerated() || replace;
5344 replace = sfw.FixSelfIntersection() || replace;
5345 replace = sfw.FixLacking(Standard_True) || replace;
5347 TopoDS_Wire newwire = sfw.Wire();
5348 rebuild.Replace(oldwire, newwire);
5352 myshape = rebuild.Apply(myshape);
5356 ShapeBuild_ReShape rebuild;
5358 for(exp1.Init(myshape, TopAbs_EDGE); exp1.More(); exp1.Next()) {
5359 TopoDS_Edge edge = TopoDS::Edge(exp1.Current());
5360 GProp_GProps system;
5361 BRepGProp::LinearProperties(edge, system);
5363 Msg::Info(
" - Removing degenerated edge");
5364 rebuild.Remove(edge);
5367 myshape = rebuild.Apply(myshape);
5371 ShapeBuild_ReShape rebuild;
5372 for(exp1.Init(myshape, TopAbs_EDGE); exp1.More(); exp1.Next()) {
5373 TopoDS_Edge edge = TopoDS::Edge(exp1.Current());
5374 if(BRep_Tool::Degenerated(edge)) rebuild.Remove(edge);
5376 myshape = rebuild.Apply(myshape);
5379 ShapeFix_Wireframe sfwf;
5382 sfwf.ModeDropSmallEdges() = Standard_True;
5384 if(sfwf.FixWireGaps()) {
5386 if(sfwf.StatusWireGaps(ShapeExtend_OK))
Msg::Info(
" no gaps found");
5387 if(sfwf.StatusWireGaps(ShapeExtend_DONE1))
5389 if(sfwf.StatusWireGaps(ShapeExtend_DONE2))
5391 if(sfwf.StatusWireGaps(ShapeExtend_FAIL1))
5392 Msg::Info(
" . Failed to fix some 2D gaps");
5393 if(sfwf.StatusWireGaps(ShapeExtend_FAIL2))
5394 Msg::Info(
" . Failed to fix some 3D gaps");
5399 if(sfwf.FixSmallEdges()) {
5401 if(sfwf.StatusSmallEdges(ShapeExtend_OK))
5403 if(sfwf.StatusSmallEdges(ShapeExtend_DONE1))
5405 if(sfwf.StatusSmallEdges(ShapeExtend_FAIL1))
5406 Msg::Info(
" . Failed to fix some small edges");
5409 myshape = sfwf.Shape();
5413 Msg::Info(
" - Fixing spot and strip faces");
5414 ShapeFix_FixSmallFace sffsm;
5415 sffsm.Init(myshape);
5418 myshape = sffsm.FixShape();
5424 BRepOffsetAPI_Sewing sewedObj(
tolerance);
5426 for(exp0.Init(myshape, TopAbs_FACE); exp0.More(); exp0.Next()) {
5427 TopoDS_Face face = TopoDS::Face(exp0.Current());
5433 if(!sewedObj.SewedShape().IsNull())
5434 myshape = sewedObj.SewedShape();
5440 ShapeBuild_ReShape rebuild;
5441 for(exp1.Init(myshape, TopAbs_EDGE); exp1.More(); exp1.Next()) {
5442 TopoDS_Edge edge = TopoDS::Edge(exp1.Current());
5443 if(BRep_Tool::Degenerated(edge)) rebuild.Remove(edge);
5445 myshape = rebuild.Apply(myshape);
5451 BRepBuilderAPI_MakeSolid ms;
5453 for(exp0.Init(myshape, TopAbs_SHELL); exp0.More(); exp0.Next()) {
5455 ms.Add(TopoDS::Shell(exp0.Current()));
5458 if(!count) {
Msg::Info(
" . Could not make solid (no shells)"); }
5460 BRepCheck_Analyzer ba(ms);
5467 myshape = sfs.Shape();
5468 for(exp0.Init(myshape, TopAbs_SOLID); exp0.More(); exp0.Next()) {
5469 TopoDS_Solid solid = TopoDS::Solid(exp0.Current());
5470 TopoDS_Solid newsolid = solid;
5471 BRepLib::OrientClosedSolid(newsolid);
5472 ShapeBuild_ReShape rebuild;
5473 rebuild.Replace(solid, newsolid);
5474 myshape = rebuild.Apply(myshape, TopAbs_COMPSOLID);
5482 double newsurfacecont = 0;
5483 for(exp0.Init(myshape, TopAbs_FACE); exp0.More(); exp0.Next()) {
5484 TopoDS_Face face = TopoDS::Face(exp0.Current());
5485 GProp_GProps system;
5486 BRepGProp::SurfaceProperties(face, system);
5487 newsurfacecont += system.Mass();
5496 _addShapeToMaps(myshape);
5497 int nnrc = 0, nnrcs = 0;
5498 int nnrso = _somap.Extent(), nnrsh = _shmap.Extent(), nnrf = _fmap.Extent();
5499 int nnrw = _wmap.Extent(), nnre = _emap.Extent(), nnrv = _vmap.Extent();
5500 for(exp0.Init(myshape, TopAbs_COMPOUND); exp0.More(); exp0.Next()) nnrc++;
5501 for(exp0.Init(myshape, TopAbs_COMPSOLID); exp0.More(); exp0.Next()) nnrcs++;
5504 Msg::Info(
"Done healing shapes (Wall %gs, CPU %gs):", w2 -
w1, t2 - t1);
5505 Msg::Info(
" - Compounds : %d (%d)", nnrc, nrc);
5506 Msg::Info(
" - Composite solids : %d (%d)", nnrcs, nrcs);
5507 Msg::Info(
" - Solids : %d (%d)", nnrso, nrso);
5508 Msg::Info(
" - Shells : %d (%d)", nnrsh, nrsh);
5509 Msg::Info(
" - Wires : %d (%d)", nnrw, nrw);
5510 Msg::Info(
" - Faces : %d (%d)", nnrf, nrf);
5511 Msg::Info(
" - Edges : %d (%d)", nnre, nre);
5512 Msg::Info(
" - Vertices : %d (%d)", nnrv, nrv);
5513 Msg::Info(
" - Total surface area : %g (%g)", newsurfacecont, surfacecont);
5517 const std::vector<std::pair<int, int> > &inDimTags,
5518 std::vector<std::pair<int, int> > &outDimTags,
double tolerance,
5519 bool fixDegenerated,
bool fixSmallEdges,
bool fixSmallFaces,
bool sewFaces,
5533 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp0(_tagVertex);
5534 for(; exp0.More(); exp0.Next()) _addShapeToMaps(exp0.Value());
5535 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp1(_tagEdge);
5536 for(; exp1.More(); exp1.Next()) _addShapeToMaps(exp1.Value());
5537 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp2(_tagFace);
5538 for(; exp2.More(); exp2.Next()) _addShapeToMaps(exp2.Value());
5539 TopTools_DataMapIteratorOfDataMapOfIntegerShape exp3(_tagSolid);
5540 for(; exp3.More(); exp3.Next()) _addShapeToMaps(exp3.Value());
5541 for(
int i = 1; i <= _vmap.Extent(); i++) b.Add(
c, _vmap(i));
5542 for(
int i = 1; i <= _emap.Extent(); i++) b.Add(
c, _emap(i));
5543 for(
int i = 1; i <= _wmap.Extent(); i++) b.Add(
c, _wmap(i));
5544 for(
int i = 1; i <= _fmap.Extent(); i++) b.Add(
c, _fmap(i));
5545 for(
int i = 1; i <= _shmap.Extent(); i++) b.Add(
c, _shmap(i));
5546 for(
int i = 1; i <= _somap.Extent(); i++) b.Add(
c, _somap(i));
5548 std::vector<TopoDS_Shape> toHeal;
5549 for(std::size_t i = 0; i < inDimTags.size(); i++) {
5550 int dim = inDimTags[i].first;
5551 int tag = inDimTags[i].second;
5552 if(!_isBound(dim, tag)) {
5553 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d",
5557 toHeal.push_back(_find(dim, tag));
5563 if(toHeal.empty()) {
5564 _healShape(
c,
tolerance, fixDegenerated, fixSmallEdges, fixSmallFaces,
5565 sewFaces, makeSolids, 1.0);
5568 for(std::size_t i = 0; i < toHeal.size(); i++) {
5569 TopoDS_Shape olds = toHeal[i];
5570 TopoDS_Shape news = olds;
5571 _healShape(news,
tolerance, fixDegenerated, fixSmallEdges, fixSmallFaces,
5572 sewFaces, makeSolids, 1.0);
5573 ShapeBuild_ReShape rebuild;
5574 rebuild.Replace(olds, news);
5575 c = TopoDS::Compound(rebuild.Apply(
c));
5580 _multiBind(
c, -1, outDimTags,
false,
true);
5586 const std::vector<std::pair<int, int> > &inDimTags)
5588 for(std::size_t i = 0; i < inDimTags.size(); i++) {
5589 int dim = inDimTags[i].first;
5590 int tag = inDimTags[i].second;
5591 if(!_isBound(dim, tag)) {
5592 Msg::Error(
"Unknown OpenCASCADE entity of dimension %d with tag %d", dim,
5596 TopoDS_Shape shape = _find(dim, tag);
5597 BRepBuilderAPI_NurbsConvert nurbs(shape);
5598 TopoDS_Shape res = nurbs.ModifiedShape(shape);
5599 _unbindWithoutChecks(shape);
5600 _bind(res, dim, tag,
true);
5606 static bool makeSTL(
const TopoDS_Face &s, std::vector<SPoint2> *verticesUV,
5607 std::vector<SPoint3> *verticesXYZ,
5608 std::vector<SVector3> *normals, std::vector<int> &triangles)
5616 #if OCC_VERSION_HEX > 0x070300
5617 BRepMesh_IncrementalMesh aMesher(s, lin, rel, ang, Standard_True);
5618 #elif OCC_VERSION_HEX > 0x070000
5620 BRepBndLib::Add(s, aBox);
5621 BRepMesh_FastDiscret::Parameters parameters;
5622 parameters.Deflection = lin;
5623 parameters.Relative = rel;
5624 parameters.Angle = ang;
5625 BRepMesh_FastDiscret aMesher(aBox, parameters);
5629 BRepBndLib::Add(s, aBox);
5630 BRepMesh_FastDiscret aMesher(lin, ang, aBox, Standard_False, Standard_False,
5631 Standard_True, Standard_True);
5635 TopLoc_Location loc;
5636 Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation(s, loc);
5638 if(triangulation.IsNull())
return false;
5640 if(verticesUV && !triangulation->HasUVNodes())
return false;
5642 if(normals && !triangulation->HasUVNodes())
return false;
5645 if(verticesUV) start = verticesUV->size();
5646 if(verticesXYZ) start = verticesXYZ->size();
5647 for(
int i = 1; i <= triangulation->NbNodes(); i++) {
5649 #if OCC_VERSION_HEX >= 0x070600
5650 gp_Pnt2d p = triangulation->UVNode(i);
5652 gp_Pnt2d p = (triangulation->UVNodes())(i);
5654 verticesUV->push_back(
SPoint2(p.X(), p.Y()));
5657 #if OCC_VERSION_HEX >= 0x070600
5658 gp_Pnt pp = triangulation->Node(i);
5660 gp_Pnt pp = (triangulation->Nodes())(i);
5662 double x = pp.X(), y = pp.Y(),
z = pp.Z();
5663 loc.Transformation().Transforms(x, y,
z);
5664 verticesXYZ->push_back(
SPoint3(x, y,
z));
5667 #if OCC_VERSION_HEX >= 0x070600
5668 gp_Pnt2d p = triangulation->UVNode(i);
5670 gp_Pnt2d p = (triangulation->UVNodes())(i);
5672 Handle(Geom_Surface) sur = BRep_Tool::Surface(s);
5675 sur->D1(p.X(), p.Y(), pnt, du, dv);
5676 SVector3 t1(du.X(), du.Y(), du.Z());
5677 SVector3 t2(dv.X(), dv.Y(), dv.Z());
5680 if(s.Orientation() == TopAbs_REVERSED) n *= -1.;
5681 normals->push_back(n);
5684 for(
int i = 1; i <= triangulation->NbTriangles(); i++) {
5685 #if OCC_VERSION_HEX >= 0x070600
5686 Poly_Triangle
triangle = triangulation->Triangle(i);
5688 Poly_Triangle
triangle = (triangulation->Triangles())(i);
5692 triangles.push_back(start + p1 - 1);
5693 if(s.Orientation() == TopAbs_REVERSED) {
5694 triangles.push_back(start + p3 - 1);
5695 triangles.push_back(start + p2 - 1);
5698 triangles.push_back(start + p2 - 1);
5699 triangles.push_back(start + p3 - 1);
5705 bool OCC_Internals::makeEdgeSTLFromFace(
const TopoDS_Edge &
c,
5706 const TopoDS_Face &s,
5707 std::vector<SPoint3> *verticesXYZ)
5709 TopLoc_Location transf;
5710 Handle(Poly_Triangulation) trian = BRep_Tool::Triangulation(s, transf);
5711 if(trian.IsNull())
return false;
5713 Handle(Poly_PolygonOnTriangulation) edgepoly =
5714 BRep_Tool::PolygonOnTriangulation(
c, trian, transf);
5715 if(edgepoly.IsNull())
return false;
5716 if(edgepoly->NbNodes() < 2)
return false;
5718 for(
int i = 1; i <= edgepoly->NbNodes(); i++) {
5719 #if OCC_VERSION_HEX > 0x070600
5720 int j = edgepoly->Node(i);
5722 int j = (edgepoly->Nodes())(i);
5724 #if OCC_VERSION_HEX >= 0x070600
5725 gp_Pnt pp = trian->Node(j);
5727 gp_Pnt pp = (trian->Nodes())(j);
5729 if(!transf.IsIdentity()) { pp.Transform(transf); }
5730 verticesXYZ->push_back(
SPoint3(pp.X(), pp.Y(), pp.Z()));
5735 bool OCC_Internals::makeFaceSTL(
const TopoDS_Face &s,
5736 std::vector<SPoint2> &vertices_uv,
5737 std::vector<int> &triangles)
5739 return makeSTL(s, &vertices_uv,
nullptr,
nullptr, triangles);
5742 bool OCC_Internals::makeFaceSTL(
const TopoDS_Face &s,
5743 std::vector<SPoint2> &vertices_uv,
5744 std::vector<SPoint3> &vertices,
5745 std::vector<SVector3> &normals,
5746 std::vector<int> &triangles)
5748 return makeSTL(s, &vertices_uv, &vertices, &normals, triangles);
5751 bool OCC_Internals::makeFaceSTL(
const TopoDS_Face &s,
5752 std::vector<SPoint3> &vertices,
5753 std::vector<SVector3> &normals,
5754 std::vector<int> &triangles)
5756 return makeSTL(s,
nullptr, &vertices, &normals, triangles);
5759 bool OCC_Internals::_makeSTL(
const TopoDS_Shape &s,
5760 std::vector<SPoint3> &vertices,
5761 std::vector<SVector3> &normals,
5762 std::vector<int> &triangles)
5765 TopExp_Explorer exp0;
5766 for(exp0.Init(s, TopAbs_FACE); exp0.More(); exp0.Next()) {
5767 TopoDS_Face face = TopoDS::Face(exp0.Current());
5768 bool tmp = makeSTL(TopoDS::Face(face.Oriented(TopAbs_FORWARD)),
nullptr,
5769 &vertices, &normals, triangles);
5770 if(!tmp) ret =
false;
5776 double dy,
double roundedRadius,
5777 std::vector<SPoint3> &vertices,
5778 std::vector<SVector3> &normals,
5779 std::vector<int> &triangles)
5782 if(!makeRectangle(result, x, y,
z, dx, dy, roundedRadius))
return false;
5783 if(!makeFaceSTL(result, vertices, normals, triangles))
return false;
5788 double ry, std::vector<SPoint3> &vertices,
5789 std::vector<SVector3> &normals,
5790 std::vector<int> &triangles)
5793 if(!makeDisk(result, xc, yc, zc, rx, ry))
return false;
5794 if(!makeFaceSTL(result, vertices, normals, triangles))
return false;
5799 double radius,
double angle1,
double angle2,
5800 double angle3, std::vector<SPoint3> &vertices,
5801 std::vector<SVector3> &normals,
5802 std::vector<int> &triangles)
5804 TopoDS_Solid result;
5805 if(!makeSphere(result, xc, yc, zc, radius, angle1, angle2, angle3))
5807 if(!_makeSTL(result, vertices, normals, triangles))
return false;
5812 double dy,
double dz,
5813 std::vector<SPoint3> &vertices,
5814 std::vector<SVector3> &normals,
5815 std::vector<int> &triangles)
5817 TopoDS_Solid result;
5818 if(!makeBox(result, x, y,
z, dx, dy, dz))
return false;
5819 if(!_makeSTL(result, vertices, normals, triangles))
return false;
5824 double dy,
double dz,
double r,
5826 std::vector<SPoint3> &vertices,
5827 std::vector<SVector3> &normals,
5828 std::vector<int> &triangles)
5830 TopoDS_Solid result;
5831 if(!makeCylinder(result, x, y,
z, dx, dy, dz, r,
angle))
return false;
5832 if(!_makeSTL(result, vertices, normals, triangles))
return false;
5837 double dy,
double dz,
double r1,
double r2,
5838 double angle, std::vector<SPoint3> &vertices,
5839 std::vector<SVector3> &normals,
5840 std::vector<int> &triangles)
5842 TopoDS_Solid result;
5843 if(!makeCone(result, x, y,
z, dx, dy, dz, r1, r2,
angle))
return false;
5844 if(!_makeSTL(result, vertices, normals, triangles))
return false;
5849 double dy,
double dz,
double ltx,
5850 std::vector<SPoint3> &vertices,
5851 std::vector<SVector3> &normals,
5852 std::vector<int> &triangles)
5854 TopoDS_Solid result;
5855 if(!makeWedge(result, x, y,
z, dx, dy, dz, ltx))
return false;
5856 if(!_makeSTL(result, vertices, normals, triangles))
return false;
5861 double r2,
double angle,
5862 std::vector<SPoint3> &vertices,
5863 std::vector<SVector3> &normals,
5864 std::vector<int> &triangles)
5866 TopoDS_Solid result;
5867 if(!makeTorus(result, x, y,
z, r1, r2,
angle))
return false;
5868 if(!_makeSTL(result, vertices, normals, triangles))
return false;
5895 std::vector<std::pair<int, int> > outDimTags;
5905 std::vector<std::pair<int, int> > outDimTags;
5914 std::vector<std::pair<int, int> > outDimTags;
5945 #if defined(HAVE_OCC)
5946 std::vector<std::pair<int, int> > outDimTags;
5949 Msg::Error(
"Gmsh requires OpenCASCADE to import TopoDS_Shape");
5959 #if defined(HAVE_OCC)
5960 return _occ_internals->getVertexForOCCShape(
this, *(TopoDS_Vertex *)shape);
5969 #if defined(HAVE_OCC)
5970 return _occ_internals->getEdgeForOCCShape(
this, *(TopoDS_Edge *)shape);
5979 #if defined(HAVE_OCC)
5980 return _occ_internals->getFaceForOCCShape(
this, *(TopoDS_Face *)shape);
5989 #if defined(HAVE_OCC)
5990 return _occ_internals->getRegionForOCCShape(
this, *(TopoDS_Solid *)shape);