Skip to content
Snippets Groups Projects
Select Git revision
  • 4608e03c213fb6d19fb9561dfe47d7261c20e872
  • master default protected
  • patches-4.14
  • steplayer
  • bl
  • pluginMeshQuality
  • fixBugsAmaury
  • hierarchical-basis
  • alphashapes
  • relaying
  • new_export_boris
  • oras_vs_osm
  • reassign_partitions
  • distributed_fwi
  • rename-classes
  • fix/fortran-api-example-t4
  • robust_partitions
  • reducing_files
  • fix_overlaps
  • 3115-issue-fix
  • 3023-Fillet2D-Update
  • gmsh_4_14_0
  • gmsh_4_13_1
  • gmsh_4_13_0
  • gmsh_4_12_2
  • gmsh_4_12_1
  • gmsh_4_12_0
  • gmsh_4_11_1
  • gmsh_4_11_0
  • gmsh_4_10_5
  • gmsh_4_10_4
  • gmsh_4_10_3
  • gmsh_4_10_2
  • gmsh_4_10_1
  • gmsh_4_10_0
  • gmsh_4_9_5
  • gmsh_4_9_4
  • gmsh_4_9_3
  • gmsh_4_9_2
  • gmsh_4_9_1
  • gmsh_4_9_0
41 results

t4.geo

Blame
  • OCCAttributes.h 10.51 KiB
    // Gmsh - Copyright (C) 1997-2019 C. Geuzaine, J.-F. Remacle
    //
    // See the LICENSE.txt file for license information. Please report all
    // issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
    
    #ifndef OCC_ATTRIBUTES_H
    #define OCC_ATTRIBUTES_H
    
    #include <vector>
    #include <string>
    #include "GmshConfig.h"
    #include "GmshMessage.h"
    #include "OS.h"
    #include "Context.h"
    #include "rtree.h"
    
    #if defined(HAVE_OCC)
    
    #include <Bnd_Box.hxx>
    #include <BRepBndLib.hxx>
    #include <TopoDS_Shape.hxx>
    #include <BRepTools.hxx>
    
    class OCCAttributes {
    private:
      int _dim;
      TopoDS_Shape _shape;
      double _meshSize;
      ExtrudeParams *_extrude;
      int _sourceDim;
      TopoDS_Shape _sourceShape;
      std::string _label;
      std::vector<double> _color;
    public:
      OCCAttributes()
        : _dim(-1), _meshSize(MAX_LC), _extrude(0), _sourceDim(-1)
      {
      }
      OCCAttributes(int dim, TopoDS_Shape shape)
        : _dim(dim), _shape(shape), _meshSize(MAX_LC), _extrude(0), _sourceDim(-1)
      {
      }
      OCCAttributes(int dim, TopoDS_Shape shape, double size)
        : _dim(dim), _shape(shape), _meshSize(size), _extrude(0), _sourceDim(-1)
      {
      }
      OCCAttributes(int dim, TopoDS_Shape shape, ExtrudeParams *e,
                        int sourceDim, TopoDS_Shape sourceShape)
        : _dim(dim), _shape(shape), _meshSize(MAX_LC), _extrude(e),
          _sourceDim(sourceDim), _sourceShape(sourceShape)
      {
      }
      OCCAttributes(int dim, TopoDS_Shape shape, const std::string &label)
        : _dim(dim), _shape(shape), _meshSize(MAX_LC), _extrude(0), _sourceDim(-1),
          _label(label)
      {
      }
      OCCAttributes(int dim, TopoDS_Shape shape, double r, double g, double b,
                    double a = 1., int boundary = 0)
        : _dim(dim), _shape(shape), _meshSize(MAX_LC), _extrude(0), _sourceDim(-1)
      {
        _color.resize(boundary ? 5 : 4);
        _color[0] = r;
        _color[1] = g;
        _color[2] = b;
        _color[3] = a;
        if(boundary) _color[4] = boundary;
      }
      ~OCCAttributes() {}
      int getDim() { return _dim; }
      TopoDS_Shape getShape() { return _shape; }
      double getMeshSize() { return _meshSize; }
      ExtrudeParams *getExtrudeParams() { return _extrude; }
      int getSourceDim() { return _sourceDim; }
      TopoDS_Shape getSourceShape() { return _sourceShape; }
      const std::string &getLabel() { return _label; }
      const std::vector<double> &getColor() { return _color; }
    };
    
    // attributes are stored according to the center of their associated shape
    // bounding box; this allows to efficiently search for potential matches, even
    // if the actual underlying shape has been modified (typically through boolean
    // fragments)
    class OCCAttributesRTree {
    private:
      RTree<OCCAttributes *, double, 3, double> *_rtree[4];
      std::vector<OCCAttributes *> _all;
      double _tol;
      static bool rtree_callback(OCCAttributes *v, void *ctx)
      {
        std::vector<OCCAttributes *> *out =
          static_cast<std::vector<OCCAttributes *> *>(ctx);
        out->push_back(v);
        return true;
      }
      void _find(int dim, const TopoDS_Shape &shape,
                 std::vector<OCCAttributes *> &attr,
                 bool requireMeshSize, bool requireExtrudeParams, bool requireLabel,
                 bool requireColor, bool excludeSame)
      {
        attr.clear();
        if(dim < 0 || dim > 3) return;
        Bnd_Box box;
        try {
          BRepBndLib::Add(shape, box);
          if(box.IsVoid()) {
            Msg::Debug(
              "Searching for (null or degenerate) shape with void bounding box");
            return;
          }
        } catch(Standard_Failure &err) {
          Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
          return;
        }
        double xmin, ymin, zmin, xmax, ymax, zmax;
        box.Get(xmin, ymin, zmin, xmax, ymax, zmax);
        double x = 0.5 * (xmin + xmax);
        double y = 0.5 * (ymin + ymax);
        double z = 0.5 * (zmin + zmax);
        double bmin[3] = {x - _tol, y - _tol, z - _tol};
        double bmax[3] = {x + _tol, y + _tol, z + _tol};
        std::vector<OCCAttributes *> tmp;
        _rtree[dim]->Search(bmin, bmax, rtree_callback, &tmp);
        Msg::Debug("OCCRTree found %d matches at (%g,%g,%g) in tree of size %d",
                   (int)tmp.size(), x, y, z, (int)_all.size());
        if(tmp.empty()) { // no match
          return;
        }
        if(!excludeSame) {
          for(std::size_t i = 0; i < tmp.size(); i++) {
            if(requireMeshSize && tmp[i]->getMeshSize() == MAX_LC) continue;
            if(requireExtrudeParams && !tmp[i]->getExtrudeParams()) continue;
            if(requireLabel && tmp[i]->getLabel().empty()) continue;
            if(requireColor && tmp[i]->getColor().empty()) continue;
            if(shape.IsSame(tmp[i]->getShape())) { // exact match: same shape
              attr.push_back(tmp[i]);
              Msg::Debug("OCCRTree exact match");
              return;
            }
          }
        }
        // potential matches based on bounding box
        for(std::size_t i = 0; i < tmp.size(); i++) {
          if(requireMeshSize && tmp[i]->getMeshSize() == MAX_LC) continue;
          if(requireExtrudeParams && !tmp[i]->getExtrudeParams()) continue;
          if(requireLabel && tmp[i]->getLabel().empty()) continue;
          if(requireColor && tmp[i]->getColor().empty()) continue;
          Bnd_Box box2;
          BRepBndLib::Add(tmp[i]->getShape(), box2);
          if(box.Distance(box2) < _tol) {
            attr.push_back(tmp[i]);
          }
        }
        Msg::Debug("OCCRtree %d matches after bounding box filtering",
                   (int)attr.size());
      }
    
    public:
      OCCAttributesRTree(double tolerance = 1.e-8)
      {
        for(int dim = 0; dim < 4; dim++)
          _rtree[dim] = new RTree<OCCAttributes *, double, 3, double>();
        _tol = tolerance;
      }
      ~OCCAttributesRTree()
      {
        clear();
        for(int dim = 0; dim < 4; dim++) delete _rtree[dim];
      }
      void clear()
      {
        for(int dim = 0; dim < 4; dim++) _rtree[dim]->RemoveAll();
        for(std::size_t i = 0; i < _all.size(); i++) delete _all[i];
        _all.clear();
      }
      void print(const std::string &fileName = "")
      {
        FILE *fp = stdout;
        if(fileName.size()) {
          fp = Fopen(fileName.c_str(), "w");
          if(!fp) {
            Msg::Error("Could not open file '%s'", fileName.c_str());
            return;
          }
        }
        fprintf(fp, "View(\"rtree mesh sizes\"){\n");
        for(std::size_t i = 0; i < _all.size(); i++) {
          if(_all[i]->getDim() != 0) continue;
          if(_all[i]->getMeshSize() == MAX_LC) continue;
          gp_Pnt pnt = BRep_Tool::Pnt(TopoDS::Vertex(_all[i]->getShape()));
          fprintf(fp, "SP(%g,%g,%g){%g};\n", pnt.X(), pnt.Y(), pnt.Z(),
                  _all[i]->getMeshSize());
        }
        fprintf(fp, "};\n");
        if(fileName.size()) fclose(fp);
      }
      void insert(OCCAttributes *v)
      {
        _all.push_back(v);
        if(v->getDim() < 0 || v->getDim() > 3) return;
        Bnd_Box box;
        try {
          BRepBndLib::Add(v->getShape(), box);
          if(box.IsVoid()) {
            Msg::Debug("Inserting (null or degenerate) shape with void bounding box");
            // BRepTools::Dump(v->getShape(), std::cout);
            return;
          }
        } catch(Standard_Failure &err) {
          Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
          return;
        }
        double xmin, ymin, zmin, xmax, ymax, zmax;
        box.Get(xmin, ymin, zmin, xmax, ymax, zmax);
        double x = 0.5 * (xmin + xmax);
        double y = 0.5 * (ymin + ymax);
        double z = 0.5 * (zmin + zmax);
        double bmin[3] = {x - _tol, y - _tol, z - _tol};
        double bmax[3] = {x + _tol, y + _tol, z + _tol};
        _rtree[v->getDim()]->Insert(bmin, bmax, v);
      }
      void remove(OCCAttributes *v)
      {
        if(v->getDim() < 0 || v->getDim() > 3) return;
        Bnd_Box box;
        try {
          BRepBndLib::Add(v->getShape(), box);
          if(box.IsVoid()) {
            Msg::Debug("Removing (null or degenerate) shape with void bounding box");
            // BRepTools::Dump(v->getShape(), std::cout);
            return;
          }
        } catch(Standard_Failure &err) {
          Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
          return;
        }
        double xmin, ymin, zmin, xmax, ymax, zmax;
        box.Get(xmin, ymin, zmin, xmax, ymax, zmax);
        double x = 0.5 * (xmin + xmax);
        double y = 0.5 * (ymin + ymax);
        double z = 0.5 * (zmin + zmax);
        double bmin[3] = {x - _tol, y - _tol, z - _tol};
        double bmax[3] = {x + _tol, y + _tol, z + _tol};
        std::vector<OCCAttributes *> tmp;
        _rtree[v->getDim()]->Search(bmin, bmax, rtree_callback, &tmp);
        for(std::size_t i = 0; i < tmp.size(); i++)
          _rtree[v->getDim()]->Remove(bmin, bmax, tmp[i]);
      }
      double getMeshSize(int dim, TopoDS_Shape shape)
      {
        std::vector<OCCAttributes *> attr;
        _find(dim, shape, attr, true, false, false, false, false);
        for(std::size_t i = 0; i < attr.size(); i++) {
          if(attr[i]->getMeshSize() < MAX_LC) return attr[i]->getMeshSize();
        }
        return MAX_LC;
      }
      ExtrudeParams *getExtrudeParams(int dim, TopoDS_Shape shape, int &sourceDim,
                                      TopoDS_Shape &sourceShape)
      {
        std::vector<OCCAttributes *> attr;
        _find(dim, shape, attr, false, true, false, false, false);
        for(std::size_t i = 0; i < attr.size(); i++) {
          if(attr[i]->getExtrudeParams()) {
            sourceDim = attr[i]->getSourceDim();
            sourceShape = attr[i]->getSourceShape();
            return attr[i]->getExtrudeParams();
          }
        }
        return 0;
      }
      void getLabels(int dim, TopoDS_Shape shape, std::vector<std::string> &labels)
      {
        labels.clear();
        std::vector<OCCAttributes *> attr;
        _find(dim, shape, attr, false, false, true, false, false);
        for(std::size_t i = 0; i < attr.size(); i++) {
          if(!attr[i]->getLabel().empty())
            labels.push_back(attr[i]->getLabel());
        }
      }
      bool getColor(int dim, TopoDS_Shape shape, unsigned int &color,
                    unsigned int &boundary)
      {
        std::vector<OCCAttributes *> attr;
        _find(dim, shape, attr, false, false, false, true, false);
        for(std::size_t i = 0; i < attr.size(); i++) {
          const std::vector<double> &col = attr[i]->getColor();
          if(col.size() >= 3){
            int r = (int)(col[0] * 255);
            r = (r < 0) ? 0 : (r > 255) ? 255 : r;
            int g = (int)(col[1] * 255);
            g = (g < 0) ? 0 : (g > 255) ? 255 : g;
            int b = (int)(col[2] * 255);
            b = (b < 0) ? 0 : (b > 255) ? 255 : b;
            int a = 255;
            if(col.size() >= 4){
              int a = (int)(col[3] * 255);
              a = (a < 0) ? 0 : (a > 255) ? 255 : a;
            }
            color = CTX::instance()->packColor(r, g, b, a);
            boundary = (col.size() == 5) ? col[4] : 0;
            return true;
          }
        }
        return false;
      }
      void getSimilarShapes(int dim, TopoDS_Shape shape,
                            std::vector<TopoDS_Shape> &other)
      {
        std::vector<OCCAttributes *> attr;
        _find(dim, shape, attr, false, false, false, false, true);
        for(std::size_t i = 0; i < attr.size(); i++) {
          TopoDS_Shape s = attr[i]->getShape();
          if(!s.IsNull()) other.push_back(s);
        }
      }
    };
    
    #endif
    #endif