diff --git a/Geo/GModelIO_OCC.cpp b/Geo/GModelIO_OCC.cpp index bbe066e0a2e68a68c63f40d4a735c5904f0775c9..d904e263c4b96d86ebb73e56fb4423be1e70333a 100644 --- a/Geo/GModelIO_OCC.cpp +++ b/Geo/GModelIO_OCC.cpp @@ -15,6 +15,7 @@ #include "MLine.h" #include "OpenFile.h" #include "StringUtils.h" +#include "ExtrudeParams.h" #if defined(HAVE_OCC) @@ -42,7 +43,6 @@ #include <BRepPrimAPI_MakeBox.hxx> #include <BRepPrimAPI_MakeCone.hxx> #include <BRepPrimAPI_MakeCylinder.hxx> -#include <BRepPrimAPI_MakePrism.hxx> #include <BRepPrimAPI_MakeRevol.hxx> #include <BRepPrimAPI_MakeSphere.hxx> #include <BRepPrimAPI_MakeTorus.hxx> @@ -86,7 +86,7 @@ OCC_Internals::OCC_Internals() void OCC_Internals::reset() { for(int i = 0; i < 6; i++) _maxTag[i] = 0; - for(int i = 0; i < 4; i++) _meshAttributes[i].clear(); + _meshAttr.Clear(); _somap.Clear(); _shmap.Clear(); _fmap.Clear(); _wmap.Clear(); _emap.Clear(); _vmap.Clear(); _vertexTag.Clear(); _edgeTag.Clear(); _faceTag.Clear(); _solidTag.Clear(); @@ -460,10 +460,10 @@ void OCC_Internals::addVertex(int tag, double x, double y, double z, Msg::Error("OpenCASCADE exception %s", err.GetMessageString()); return; } + if(meshSize > 0 && meshSize < MAX_LC) + _meshAttr.Bind(result, meshAttr(meshSize)); if(tag <= 0) tag = getMaxTag(0) + 1; bind(result, tag); - if(meshSize > 0 && meshSize < MAX_LC) - _meshAttributes[0][tag].size = meshSize; } void OCC_Internals::addLine(int tag, int startTag, int endTag) @@ -1341,6 +1341,144 @@ void OCC_Internals::addThickSolid(int tag, int solidTag, bind(result, true, tag, out); } +void OCC_Internals::_setMeshAttr(const TopoDS_Compound &c, BRepPrimAPI_MakePrism &p, + ExtrudeParams *e, double dx, double dy, double dz) +{ + const bool debug = false; + + BRepSweep_Prism prism = p.Prism(); + TopExp_Explorer exp0; + + int i = 0; + for(exp0.Init(c, TopAbs_FACE); exp0.More(); exp0.Next()){ + TopoDS_Face face = TopoDS::Face(exp0.Current()); + TopoDS_Shape bot = p.FirstShape(face); + TopoDS_Shape top = p.LastShape(face); + { + ExtrudeParams *ee = new ExtrudeParams(COPIED_ENTITY); + ee->fill(TRANSLATE, dx, dy, dz, 0., 0., 0., 0., 0., 0., 0.); + ee->mesh = e->mesh; + meshAttr m(ee); + m.source = bot; + _meshAttr.Bind(top, m); + } + TopoDS_Shape vol = prism.Shape(face); + { + ExtrudeParams *ee = new ExtrudeParams(EXTRUDED_ENTITY); + ee->fill(TRANSLATE, dx, dy, dz, 0., 0., 0., 0., 0., 0., 0.); + ee->mesh = e->mesh; + meshAttr m(ee); + m.source = bot; + _meshAttr.Bind(vol, m); + } + if(debug){ + char s[256]; + sprintf(s, "extrude_bot_face_%d.brep", i); BRepTools::Write(bot, s); + sprintf(s, "extrude_top_face_%d.brep", i); BRepTools::Write(top, s); + sprintf(s, "extrude_vol_%d.brep", i); BRepTools::Write(vol, s); + } + i++; + } + + i = 0; + for(exp0.Init(c, TopAbs_EDGE); exp0.More(); exp0.Next()){ + TopoDS_Edge edge = TopoDS::Edge(exp0.Current()); + TopoDS_Shape bot = p.FirstShape(edge); + TopoDS_Shape top = p.LastShape(edge); + { + ExtrudeParams *ee = new ExtrudeParams(COPIED_ENTITY); + ee->fill(TRANSLATE, dx, dy, dz, 0., 0., 0., 0., 0., 0., 0.); + ee->mesh = e->mesh; + meshAttr m(ee); + m.source = bot; + _meshAttr.Bind(top, m); + } + TopoDS_Shape sur = prism.Shape(edge); + { + ExtrudeParams *ee = new ExtrudeParams(EXTRUDED_ENTITY); + ee->fill(TRANSLATE, dx, dy, dz, 0., 0., 0., 0., 0., 0., 0.); + ee->mesh = e->mesh; + meshAttr m(ee); + m.source = bot; + _meshAttr.Bind(sur, m); + } + if(debug){ + char s[256]; + sprintf(s, "extrude_bot_edge_%d.brep", i); BRepTools::Write(bot, s); + sprintf(s, "extrude_top_edge_%d.brep", i); BRepTools::Write(top, s); + sprintf(s, "extrude_lat_face_%d.brep", i); BRepTools::Write(sur, s); + } + i++; + } + + i = 0; + for(exp0.Init(c, TopAbs_VERTEX); exp0.More(); exp0.Next()){ + TopoDS_Vertex vertex = TopoDS::Vertex(exp0.Current()); + TopoDS_Shape bot = p.FirstShape(vertex); + TopoDS_Shape top = p.LastShape(vertex); + TopoDS_Shape lin = prism.Shape(vertex); + { + ExtrudeParams *ee = new ExtrudeParams(EXTRUDED_ENTITY); + ee->fill(TRANSLATE, dx, dy, dz, 0., 0., 0., 0., 0., 0., 0.); + ee->mesh = e->mesh; + meshAttr m(ee); + m.source = bot; + _meshAttr.Bind(lin, m); + } + if(debug){ + char s[256]; + sprintf(s, "extrude_bot_vertex_%d.brep", i); BRepTools::Write(bot, s); + sprintf(s, "extrude_top_vertex_%d.brep", i); BRepTools::Write(top, s); + sprintf(s, "extrude_lat_edge_%d.brep", i); BRepTools::Write(lin, s); + } + i++; + } +} + +void OCC_Internals::_copyMeshAttr(TopoDS_Edge edge, GEdge *ge) +{ + if(!_meshAttr.IsBound(edge)) return; + meshAttr m = _meshAttr.Find(edge); + if(!m.extrude) return; + ge->meshAttributes.extrude = m.extrude; + if(ge->meshAttributes.extrude->geo.Mode == EXTRUDED_ENTITY){ + if(_vertexTag.IsBound(m.source)) + ge->meshAttributes.extrude->geo.Source = _vertexTag.Find(m.source); + } + else if(ge->meshAttributes.extrude->geo.Mode == COPIED_ENTITY){ + if(_edgeTag.IsBound(m.source)) + ge->meshAttributes.extrude->geo.Source = _edgeTag.Find(m.source); + } +} + +void OCC_Internals::_copyMeshAttr(TopoDS_Face face, GFace *gf) +{ + if(!_meshAttr.IsBound(face)) return; + meshAttr m = _meshAttr.Find(face); + if(!m.extrude) return; + gf->meshAttributes.extrude = m.extrude; + if(gf->meshAttributes.extrude->geo.Mode == EXTRUDED_ENTITY){ + if(_edgeTag.IsBound(m.source)) + gf->meshAttributes.extrude->geo.Source = _edgeTag.Find(m.source); + } + else if(gf->meshAttributes.extrude->geo.Mode == COPIED_ENTITY){ + if(_faceTag.IsBound(m.source)) + gf->meshAttributes.extrude->geo.Source = _faceTag.Find(m.source); + } +} + +void OCC_Internals::_copyMeshAttr(TopoDS_Solid solid, GRegion *gr) +{ + if(!_meshAttr.IsBound(solid)) return; + meshAttr m = _meshAttr.Find(solid); + if(!m.extrude) return; + gr->meshAttributes.extrude = m.extrude; + if(gr->meshAttributes.extrude->geo.Mode == EXTRUDED_ENTITY){ + if(_faceTag.IsBound(m.source)) + gr->meshAttributes.extrude->geo.Source = _faceTag.Find(m.source); + } +} + void OCC_Internals::_extrude(int mode, const std::vector<std::pair<int, int> > &inDimTags, double x, double y, double z, @@ -1350,9 +1488,6 @@ void OCC_Internals::_extrude(int mode, std::vector<std::pair<int, int> > &outDimTags, ExtrudeParams *e) { - if(e) - Msg::Warning("Structured meshes not yet available with OpenCASCADE extrusion"); - // build a single compound shape, so that we won't duplicate internal // boundaries BRep_Builder b; @@ -1378,6 +1513,7 @@ void OCC_Internals::_extrude(int mode, return; } result = p.Shape(); + if(e) _setMeshAttr(c, p, e, dx, dy, dz); } else if(mode == 1){ // revolve gp_Ax1 axisOfRevolution(gp_Pnt(x, y, z), gp_Dir(ax, ay, az)); @@ -1388,6 +1524,8 @@ void OCC_Internals::_extrude(int mode, return; } result = r.Shape(); + if(e) + Msg::Warning("Structured meshes not yet available with OpenCASCADE revolution"); } else if(mode == 2){ // pipe if(!_tagWire.IsBound(wireTag)){ @@ -1402,6 +1540,8 @@ void OCC_Internals::_extrude(int mode, return; } result = p.Shape(); + if(e) + Msg::Warning("Structured meshes not yet available with OpenCASCADE pipe"); } } catch(Standard_Failure &err){ @@ -1887,8 +2027,10 @@ void OCC_Internals::exportShapes(const std::string &fileName, void OCC_Internals::setMeshSize(int dim, int tag, double size) { - if(dim < 0 || dim > 3) return; - _meshAttributes[dim][tag].size = size; + if(dim != 0) return; + if(_tagVertex.IsBound(tag)){ + _meshAttr.Bind(_tagVertex.Find(tag), meshAttr(size)); + } } void OCC_Internals::synchronize(GModel *model) @@ -1965,10 +2107,13 @@ void OCC_Internals::synchronize(GModel *model) tag = _vertexTag.Find(vertex); else tag = ++vTagMax; - std::map<int, meshAttribute>::iterator it = - _meshAttributes[0].find(tag); - double lc = (it == _meshAttributes[0].end()) ? MAX_LC : it->second.size; - model->add(new OCCVertex(model, tag, vertex, lc)); + double lc = MAX_LC; + if(_meshAttr.IsBound(vertex)){ + meshAttr m = _meshAttr.Find(vertex); + lc = m.size; + } + OCCVertex *occv = new OCCVertex(model, tag, vertex, lc); + model->add(occv); } } for(int i = 1; i <= _emap.Extent(); i++){ @@ -1981,7 +2126,9 @@ void OCC_Internals::synchronize(GModel *model) tag = _edgeTag.Find(edge); else tag = ++eTagMax; - model->add(new OCCEdge(model, edge, tag, v1, v2)); + OCCEdge *occe = new OCCEdge(model, edge, tag, v1, v2); + model->add(occe); + _copyMeshAttr(edge, occe); } } for(int i = 1; i <= _fmap.Extent(); i++){ @@ -1992,7 +2139,9 @@ void OCC_Internals::synchronize(GModel *model) tag = _faceTag.Find(face); else tag = ++fTagMax; - model->add(new OCCFace(model, face, tag)); + OCCFace *occf = new OCCFace(model, face, tag); + model->add(occf); + _copyMeshAttr(face, occf); } } for(int i = 1; i <= _somap.Extent(); i++){ @@ -2003,7 +2152,9 @@ void OCC_Internals::synchronize(GModel *model) tag = _solidTag(region); else tag = ++rTagMax; - model->add(new OCCRegion(model, region, tag)); + OCCRegion *occr = new OCCRegion(model, region, tag); + model->add(occr); + _copyMeshAttr(region, occr); } } diff --git a/Geo/GModelIO_OCC.h b/Geo/GModelIO_OCC.h index 578b68abb866e1c1cbb5cf8c9f8e44dde25bf405..7c5242b66fbd93b328c103b6897c235eae6b16c6 100644 --- a/Geo/GModelIO_OCC.h +++ b/Geo/GModelIO_OCC.h @@ -23,10 +23,14 @@ class ExtrudeParams; #include <TopoDS_Face.hxx> #include <TopoDS_Shell.hxx> #include <TopoDS_Solid.hxx> +#include <TopoDS_Compound.hxx> #include <TopTools_IndexedMapOfShape.hxx> #include <TopTools_DataMapOfShapeInteger.hxx> #include <TopTools_DataMapOfIntegerShape.hxx> +#include <TopTools_ShapeMapHasher.hxx> #include <BRepBuilderAPI_Transform.hxx> +#include <BRepPrimAPI_MakePrism.hxx> +#include <NCollection_DataMap.hxx> class OCC_Internals { public: @@ -52,14 +56,17 @@ class OCC_Internals { TopTools_DataMapOfShapeInteger _wireTag, _shellTag; TopTools_DataMapOfIntegerShape _tagWire, _tagShell; - // internal mesh attributes, linked to tags - class meshAttribute { + // internal mesh attributes + class meshAttr { public: - meshAttribute() : size(MAX_LC), extrude(0) {} + meshAttr() : size(MAX_LC), extrude(0) {} + meshAttr(double s) : size(s), extrude(0) {} + meshAttr(ExtrudeParams *e) : size(MAX_LC), extrude(e) {} double size; ExtrudeParams *extrude; + TopoDS_Shape source; }; - std::map<int, meshAttribute> _meshAttributes[4]; + NCollection_DataMap<TopoDS_Shape, meshAttr, TopTools_ShapeMapHasher> _meshAttr; // iterate on all bound entities and recompute the maximum tag void _recomputeMaxTag(int dim); @@ -89,6 +96,13 @@ class OCC_Internals { std::vector<std::pair<int, int> > &outDimTags, ExtrudeParams *e=0); + // set mesh attributes for extruded meshes + void _setMeshAttr(const TopoDS_Compound &c, BRepPrimAPI_MakePrism &p, + ExtrudeParams *e, double dx, double dy, double dz); + void _copyMeshAttr(TopoDS_Edge edge, GEdge *ge); + void _copyMeshAttr(TopoDS_Face face, GFace *gf); + void _copyMeshAttr(TopoDS_Solid solid, GRegion *gr); + public: OCC_Internals();