예제 #1
0
void GMSH_CutPlanePlugin::draw(void *context)
{
#if defined(HAVE_OPENGL)
  int num = (int)CutPlaneOptions_Number[7].def;
  drawContext *ctx = (drawContext *)context;
  if(num < 0) num = iview;
  if(num >= 0 && num < (int)PView::list.size()) {
    glColor4ubv((GLubyte *)&CTX::instance()->color.fg);
    glLineWidth((float)CTX::instance()->lineWidth);
    SBoundingBox3d bb = PView::list[num]->getData()->getBoundingBox();
    ctx->drawPlaneInBoundingBox(
      bb.min().x(), bb.min().y(), bb.min().z(), bb.max().x(), bb.max().y(),
      bb.max().z(), CutPlaneOptions_Number[0].def,
      CutPlaneOptions_Number[1].def, CutPlaneOptions_Number[2].def,
      CutPlaneOptions_Number[3].def);
  }
#endif
}
예제 #2
0
void GMSH_ProbePlugin::draw(void *context)
{
#if defined(HAVE_OPENGL)
  int num = (int)ProbeOptions_Number[3].def;
  if(num < 0) num = iview;
  if(num >= 0 && num < (int)PView::list.size()){
    double x = ProbeOptions_Number[0].def;
    double y = ProbeOptions_Number[1].def;
    double z = ProbeOptions_Number[2].def;
    drawContext *ctx = (drawContext*)context;
    glColor4ubv((GLubyte *) & CTX::instance()->color.fg);
    glLineWidth((float)CTX::instance()->lineWidth);
    SBoundingBox3d bb = PView::list[num]->getData()->getBoundingBox();
    if(x >= bb.min().x() && x <= bb.max().x() &&
       y >= bb.min().y() && y <= bb.max().y() &&
       z >= bb.min().z() && z <= bb.max().z()){
      // we're inside the bounding box: draw a large cross
      glBegin(GL_LINES);
      glVertex3d(bb.min().x(), y, z); glVertex3d(bb.max().x(), y, z);
      glVertex3d(x, bb.min().y(), z); glVertex3d(x, bb.max().y(), z);
      glVertex3d(x, y, bb.min().z()); glVertex3d(x, y, bb.max().z());
      glEnd();
    }
    else{
      // draw 10-pixel marker
      double d = 10 * ctx->pixel_equiv_x / ctx->s[0];
      glBegin(GL_LINES);
      glVertex3d(x - d, y, z); glVertex3d(x + d, y, z);
      glVertex3d(x, y - d, z); glVertex3d(x, y + d, z);
      glVertex3d(x, y, z - d); glVertex3d(x, y, z + d);
      glEnd();
    }
    ctx->drawSphere(CTX::instance()->pointSize, x, y, z, 1);
  }
#endif
}
예제 #3
0
int GModel::readSTL(const std::string &name, double tolerance)
{
  FILE *fp = Fopen(name.c_str(), "rb");
  if(!fp){
    Msg::Error("Unable to open file '%s'", name.c_str());
    return 0;
  }

  // store triplets of points for each solid found in the file
  std::vector<std::vector<SPoint3> > points;
  SBoundingBox3d bbox;

  // "solid", or binary data header
  char buffer[256];
  if(!fgets(buffer, sizeof(buffer), fp)){ fclose(fp); return 0; }

  bool binary = strncmp(buffer, "solid", 5) && strncmp(buffer, "SOLID", 5);

  // ASCII STL
  if(!binary){
    points.resize(1);
    while(!feof(fp)) {
      // "facet normal x y z" or "endsolid"
      if(!fgets(buffer, sizeof(buffer), fp)) break;
      if(!strncmp(buffer, "endsolid", 8) ||
         !strncmp(buffer, "ENDSOLID", 8)){
        // "solid"
        if(!fgets(buffer, sizeof(buffer), fp)) break;
        if(!strncmp(buffer, "solid", 5) ||
           !strncmp(buffer, "SOLID", 5)){
          points.resize(points.size() + 1);
          // "facet normal x y z"
          if(!fgets(buffer, sizeof(buffer), fp)) break;
        }
      }
      // "outer loop"
      if(!fgets(buffer, sizeof(buffer), fp)) break;
      // "vertex x y z"
      for(int i = 0; i < 3; i++){
        if(!fgets(buffer, sizeof(buffer), fp)) break;
        char s1[256];
        double x, y, z;
        if(sscanf(buffer, "%s %lf %lf %lf", s1, &x, &y, &z) != 4) break;
        SPoint3 p(x, y, z);
        points.back().push_back(p);
        bbox += p;
      }
      // "endloop"
      if(!fgets(buffer, sizeof(buffer), fp)) break;
      // "endfacet"
      if(!fgets(buffer, sizeof(buffer), fp)) break;
    }
   }

  // check if we could parse something
  bool empty = true;
  for(unsigned int i = 0; i < points.size(); i++){
    if(points[i].size()){
      empty = false;
      break;
    }
  }
  if(empty) points.clear();

  // binary STL (we also try to read in binary mode if the header told
  // us the format was ASCII but we could not read any vertices)
  if(binary || empty){
    if(binary)
      Msg::Info("Mesh is in binary format");
    else
      Msg::Info("Wrong ASCII header or empty file: trying binary read");
    rewind(fp);
    while(!feof(fp)) {
      char header[80];
      if(!fread(header, sizeof(char), 80, fp)) break;
      unsigned int nfacets = 0;
      size_t ret = fread(&nfacets, sizeof(unsigned int), 1, fp);
      bool swap = false;
      if(nfacets > 100000000){
        Msg::Info("Swapping bytes from binary file");
        swap = true;
        SwapBytes((char*)&nfacets, sizeof(unsigned int), 1);
      }
      if(ret && nfacets){
        points.resize(points.size() + 1);
        char *data = new char[nfacets * 50 * sizeof(char)];
        ret = fread(data, sizeof(char), nfacets * 50, fp);
        if(ret == nfacets * 50){
          for(unsigned int i = 0; i < nfacets; i++) {
            float *xyz = (float *)&data[i * 50 * sizeof(char)];
            if(swap) SwapBytes((char*)xyz, sizeof(float), 12);
            for(int j = 0; j < 3; j++){
              SPoint3 p(xyz[3 + 3 * j], xyz[3 + 3 * j + 1], xyz[3 + 3 * j + 2]);
              points.back().push_back(p);
              bbox += p;
            }
          }
        }
        delete [] data;
      }
    }
  }

  std::vector<GFace*> faces;
  for(unsigned int i = 0; i < points.size(); i++){
    if(points[i].empty()){
      Msg::Error("No facets found in STL file for solid %d", i);
      fclose(fp);
      return 0;
    }
    if(points[i].size() % 3){
      Msg::Error("Wrong number of points (%d) in STL file for solid %d",
                 points[i].size(), i);
      fclose(fp);
      return 0;
    }
    Msg::Info("%d facets in solid %d", points[i].size() / 3, i);
    // create face
    GFace *face = new discreteFace(this, getMaxElementaryNumber(2) + 1);
    faces.push_back(face);
    add(face);
  }

  // create triangles using unique vertices
  double eps = norm(SVector3(bbox.max(), bbox.min())) * tolerance;
  std::vector<MVertex*> vertices;
  for(unsigned int i = 0; i < points.size(); i++)
    for(unsigned int j = 0; j < points[i].size(); j++)
      vertices.push_back(new MVertex(points[i][j].x(), points[i][j].y(),
                                     points[i][j].z()));
  MVertexPositionSet pos(vertices);

  std::set<MFace,Less_Face> unique;
  int nbDuplic = 0;
  for(unsigned int i = 0; i < points.size(); i ++){
    for(unsigned int j = 0; j < points[i].size(); j += 3){
      MVertex *v[3];
      for(int k = 0; k < 3; k++){
        double x = points[i][j + k].x();
        double y = points[i][j + k].y();
        double z = points[i][j + k].z();
        v[k] = pos.find(x, y, z, eps);
      }
      MFace mf (v[0], v[1], v[2]);
      if (unique.find(mf) == unique.end()){
	faces[i]->triangles.push_back(new MTriangle(v[0], v[1], v[2]));
	unique.insert(mf);
      }
      else{
	nbDuplic++;
      }
    }
  }
  if (nbDuplic)
    Msg::Warning("%d duplicate triangles in STL file", nbDuplic);

  _associateEntityWithMeshVertices();
  _storeVerticesInEntities(vertices); // will delete unused vertices

  fclose(fp);
  return 1;
}
예제 #4
0
파일: Distance.cpp 프로젝트: cycheung/gmsh
PView *GMSH_DistancePlugin::execute(PView *v)
{
  int id_pt   = (int) DistanceOptions_Number[0].def;
  int id_line = (int) DistanceOptions_Number[1].def;
  int id_face = (int) DistanceOptions_Number[2].def;
  double type = (double) DistanceOptions_Number[3].def;
  int ortho   = (int) DistanceOptions_Number[6].def;

  PView *view = new PView();
  _data = getDataList(view);
#if defined(HAVE_SOLVER)
#if defined(HAVE_TAUCS)
  linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>;
#else
  linearSystemCSRGmm<double> *lsys = new linearSystemCSRGmm<double>;
  lsys->setNoisy(1);
  lsys->setGmres(1);
  lsys->setPrec(5.e-8);
#endif
  dofManager<double> * dofView = new dofManager<double>(lsys);
#endif

  std::vector<GEntity*> _entities;
  GModel::current()->getEntities(_entities);
  if (!_entities.size() || !_entities[_entities.size()-1]->getMeshElement(0)) {
    Msg::Error("This plugin needs a mesh !");
    return view;
  }

  GEntity* ge = _entities[_entities.size()-1];
  int integrationPointTetra[2] = {0,0};

  int numnodes = 0;
  for (unsigned int i = 0; i < _entities.size()-1; i++)
    numnodes += _entities[i]->mesh_vertices.size();
  int totNodes = numnodes + _entities[_entities.size()-1]->mesh_vertices.size();
  int order = ge->getMeshElement(0)->getPolynomialOrder();
  int totNumNodes = totNodes + ge->getNumMeshElements()*integrationPointTetra[order-1];

  std::vector<SPoint3> pts;
  std::vector<double> distances;
  std::vector<MVertex* > pt2Vertex;
  pts.clear();
  distances.clear();
  pt2Vertex.clear();
  pts.reserve(totNumNodes);
  distances.reserve(totNumNodes);
  pt2Vertex.reserve(totNumNodes);

  std::map<MVertex*,double> _distanceE_map;
  std::map<MVertex*,int> _isInYarn_map;
  std::vector<int> index;
  std::vector<double> distancesE;
  std::vector<double> distances2;
  std::vector<double> distancesE2;
  std::vector<int> isInYarn;
  std::vector<int> isInYarn2;
  std::vector<SPoint3> closePts;
  std::vector<SPoint3> closePts2;

  for (int i=0; i<totNumNodes; i++) {
    distances.push_back(1.e22);
  }

  int k = 0;
  for (unsigned int i=0; i<_entities.size(); i++){
    GEntity* ge = _entities[i];
    _maxDim = std::max(_maxDim, ge->dim());
    for (unsigned int j=0; j<ge->mesh_vertices.size(); j++) {
      MVertex *v = ge->mesh_vertices[j];
      pts.push_back(SPoint3(v->x(), v->y(), v->z()));
      _distance_map.insert(std::make_pair(v, 0.0));
/* TO DO (by AM)
      SPoint3 p_empty();
      _closePts_map.insert(std::make_pair(v, p_empty));
*/
      pt2Vertex[k] = v;
      k++;
    }
  }

  // Compute geometrical distance to mesh boundaries
  //------------------------------------------------------
  if (type < 0.0 ) {

    bool existEntity = false;

    for (unsigned int i=0; i<_entities.size(); i++) {
      GEntity* g2 = _entities[i];
      int gDim = g2->dim();
      std::vector<int> phys = g2->getPhysicalEntities();
      bool computeForEntity = false;
      for(unsigned int k = 0; k<phys.size(); k++) {
        int tagp = phys[k];
        if (id_pt == 0 && id_line == 0 && id_face == 0 && gDim == _maxDim - 1)
          computeForEntity = true;
        else if ((tagp == id_pt && gDim == 0) || (tagp == id_line && gDim == 1) ||
                 (tagp == id_face && gDim == 2))
          computeForEntity = true;
      }
      if (computeForEntity) {
        existEntity = true;
        for (unsigned int k = 0; k < g2->getNumMeshElements(); k++) {
          std::vector<double> iDistances;
          std::vector<SPoint3> iClosePts;
          std::vector<double> iDistancesE;
          std::vector<int> iIsInYarn;
          MElement *e = g2->getMeshElement(k);
          MVertex *v1 = e->getVertex(0);
          MVertex *v2 = e->getVertex(1);
          SPoint3 p1(v1->x(), v1->y(), v1->z());
          SPoint3 p2(v2->x(), v2->y(), v2->z());
          if ((e->getNumVertices() == 2 && order == 1) ||
              (e->getNumVertices() == 3 && order == 2)) {
            signedDistancesPointsLine(iDistances, iClosePts, pts, p1, p2);
          }
          else if ((e->getNumVertices() == 3 && order == 1) ||
                   (e->getNumVertices() == 6 && order == 2)) {
            MVertex *v3 = e->getVertex(2);
            SPoint3 p3 (v3->x(),v3->y(),v3->z());
            signedDistancesPointsTriangle(iDistances, iClosePts, pts, p1, p2, p3);
          }
          for (unsigned int kk=0; kk<pts.size(); kk++) {
            if (std::abs(iDistances[kk]) < distances[kk]) {
              distances[kk] = std::abs(iDistances[kk]);
              MVertex *v = pt2Vertex[kk];
              _distance_map[v] = distances[kk];
              /* TO DO (by AM)
              _closePts_map[v] = iClosePts[kk];
              */
            }
          }
        }
      }
    }
    if (!existEntity){
      if (id_pt != 0)   Msg::Error("The Physical Point does not exist !");
      if (id_line != 0) Msg::Error("The Physical Line does not exist !");
      if (id_face != 0) Msg::Error("The Physical Surface does not exist !");
      return view;
    }

    printView(_entities, _distance_map);

    /* TO DO (by AM)
    printView(_entities, _closePts_map);
    */
  }

  // Compute PDE for distance function
  //-----------------------------------
  else if (type > 0.0) {

#if defined(HAVE_SOLVER)

    bool existEntity = false;
    SBoundingBox3d bbox;
    for(unsigned int i = 0; i < _entities.size(); i++){
      GEntity* ge = _entities[i];
      int gDim = ge->dim();
      bool fixForEntity = false;
      std::vector<int> phys = ge->getPhysicalEntities();
      for(unsigned int k = 0; k < phys.size(); k++) {
        int tagp = phys[k];
        if (id_pt == 0 && id_line == 0 && id_face == 0 && gDim == _maxDim - 1)
          fixForEntity = true;
        else if ((tagp == id_pt && gDim == 0) || (tagp == id_line && gDim == 1) ||
                 (tagp == id_face && gDim == 2) )
          fixForEntity = true;
      }
      if (fixForEntity) {
        existEntity = true;
        for (unsigned int i = 0; i < ge->getNumMeshElements(); ++i) {
          MElement *t = ge->getMeshElement(i);
          for (int k=0; k<t->getNumVertices(); k++) {
            MVertex *v = t->getVertex(k);
            dofView->fixVertex(v, 0, 1, 0.);
            bbox += SPoint3(v->x(), v->y(), v->z());
          }
        }
      }
    }

    if (!existEntity){
      if (id_pt != 0)   Msg::Error("The Physical Point does not exist !");
      if (id_line != 0) Msg::Error("The Physical Line does not exist !");
      if (id_face != 0) Msg::Error("The Physical Surface does not exist !");
      return view;
    }

    std::vector<MElement *> allElems;
    for(unsigned int ii = 0; ii < _entities.size(); ii++){
      if(_entities[ii]->dim() == _maxDim) {
        GEntity *ge = _entities[ii];
        for(unsigned int i = 0; i < ge->getNumMeshElements(); ++i) {
          MElement *t = ge->getMeshElement(i);
          allElems.push_back(t);
          for (int k = 0; k < t->getNumVertices(); k++)
            dofView->numberVertex(t->getVertex(k), 0, 1);
        }
      }
    }

    double L = norm(SVector3(bbox.max(), bbox.min()));
    double mu = type*L;

    simpleFunction<double> DIFF(mu*mu), ONE(1.0);
    distanceTerm distance(GModel::current(), 1, &DIFF, &ONE);

    for (std::vector<MElement* >::iterator it = allElems.begin();
         it != allElems.end(); it++){
      SElement se((*it));
      distance.addToMatrix(*dofView, &se);
    }
    groupOfElements gr(allElems);
    distance.addToRightHandSide(*dofView, gr);

    Msg::Info("Distance Computation: Assembly done");
    lsys->systemSolve();
    Msg::Info("Distance Computation: System solved");

    for (std::map<MVertex*,double >::iterator itv = _distance_map.begin();
         itv != _distance_map.end() ; ++itv) {
      MVertex *v = itv->first;
      double value;
      dofView->getDofValue(v, 0, 1, value);
      value = std::min(0.9999, value);
      double dist = -mu * log(1. - value);
      itv->second = dist;
    }

    printView(_entities, _distance_map);

#endif
  }

  _data->setName("distance");
  _data->Time.push_back(0);
  _data->setFileName(_fileName.c_str());
  _data->finalize();

  // compute also orthogonal vector to distance field
  // A Uortho = -C DIST
  //------------------------------------------------
  if (ortho > 0) {
#if defined(HAVE_SOLVER)

#ifdef HAVE_TAUCS
    linearSystemCSRTaucs<double> *lsys2 = new linearSystemCSRTaucs<double>;
#else
    linearSystemCSRGmm<double> *lsys2 = new linearSystemCSRGmm<double>;
    lsys->setNoisy(1);
    lsys->setGmres(1);
    lsys->setPrec(5.e-8);
#endif
    dofManager<double> myAssembler(lsys2);
    simpleFunction<double> ONE(1.0);

    double dMax = 1.0; //EMI TO CHANGE

    std::vector<MElement *> allElems;
    for(unsigned int ii = 0; ii < _entities.size(); ii++){
      if (_entities[ii]->dim() == _maxDim) {
        GEntity *ge = _entities[ii];
        for (unsigned int i=0; i<ge->getNumMeshElements(); ++i) {
          MElement *t = ge->getMeshElement(i);
          double vMean = 0.0;
          for (int k = 0; k < t->getNumVertices(); k++) {
            std::map<MVertex*, double>::iterator it = _distance_map.find(t->getVertex(k));
            vMean += it->second;
          }
          vMean /= t->getNumVertices();
          if (vMean < dMax)
            allElems.push_back(ge->getMeshElement(i));
        }
      }
    }

    int mid = (int)floor(allElems.size() / 2.);
    MElement *e = allElems[mid];
    MVertex *vFIX = e->getVertex(0);
    myAssembler.fixVertex(vFIX, 0, 1, 0.0);

    for (std::vector<MElement* >::iterator it = allElems.begin();
         it != allElems.end(); it++){
      MElement *t = *it;
      for(int k = 0; k < t->getNumVertices(); k++)
        myAssembler.numberVertex(t->getVertex(k), 0, 1);
    }

    orthogonalTerm *ortho;
    ortho  = new orthogonalTerm(GModel::current(), 1, &ONE, &_distance_map);
    // if (type  < 0)
    //   ortho  = new orthogonalTerm(GModel::current(), 1, &ONE, view);
    // else
    //   ortho  = new orthogonalTerm(GModel::current(), 1, &ONE, dofView);

    for (std::vector<MElement* >::iterator it = allElems.begin();
         it != allElems.end(); it++){
      SElement se((*it));
      ortho->addToMatrix(myAssembler, &se);
    }
    groupOfElements gr(allElems);
    ortho->addToRightHandSide(myAssembler, gr);

    Msg::Info("Orthogonal Computation: Assembly done");
    lsys2->systemSolve();
    Msg::Info("Orthogonal Computation: System solved");

    PView *view2 = new PView();
    PViewDataList *data2 = getDataList(view2);
    data2->setName("ortogonal field");

    Msg::Info("Writing  orthogonal.pos");
    FILE * f5 = Fopen("orthogonal.pos","w");
    fprintf(f5,"View \"orthogonal\"{\n");
    for (std::vector<MElement* >::iterator it = allElems.begin();
         it != allElems.end(); it++){
      MElement *e = *it;

    int numNodes = e->getNumVertices();
    if (e->getType() == TYPE_POLYG)
      numNodes = e->getNumChildren() * e->getChild(0)->getNumVertices();
    std::vector<double> x(numNodes), y(numNodes), z(numNodes);
    std::vector<double> *out2 = data2->incrementList(1, e->getType(), numNodes);
    std::vector<MVertex*> nods;
    std::vector<double> orth;

    if(!e->getNumChildren())
      for(int i=0; i<numNodes; i++)
        nods.push_back(e->getVertex(i));
    else
      for(int i = 0; i < e->getNumChildren(); i++)
        for(int j = 0; j < e->getChild(i)->getNumVertices(); j++)
          nods.push_back(e->getChild(i)->getVertex(j));

    for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->x());
    for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->y());
    for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->z());

    if (_maxDim == 2)
      switch (numNodes) {
        case 2: fprintf(f5,"SL("); break;
        case 3: fprintf(f5,"ST("); break;
        case 4: fprintf(f5,"SQ("); break;
        default: Msg::Fatal("Error in Plugin 'Distance' (numNodes=%g).",numNodes); break;
      }
    else if (_maxDim == 3)
      switch (numNodes) {
        case 4: fprintf(f5,"SS("); break;
        case 8: fprintf(f5,"SH("); break;
        case 6: fprintf(f5,"SI("); break;
        case 5: fprintf(f5,"SY("); break;
        default: Msg::Fatal("Error in Plugin 'Distance' (numNodes=%g).",numNodes); break;
      }

    for (int j=0; j<numNodes; j++) {
      MVertex *v =  nods[j];
      if (j)
        fprintf(f5, ",%g,%g,%g", v->x(), v->y(), v->z());
      else
        fprintf(f5, "%g,%g,%g", v->x(), v->y(), v->z());
      double value;
      myAssembler.getDofValue(v, 0, 1, value);
      orth.push_back(value);
    }
    fprintf(f5,"){");
    for (unsigned int i=0; i<orth.size(); i++) {
      out2->push_back(orth[i]);
      if (i)
        fprintf(f5,",%g", orth[i]);
      else
        fprintf(f5,"%g", orth[i]);
    }
    fprintf(f5,"};\n");

  }
  fprintf(f5,"};\n");
  fclose(f5);

  lsys->clear();
  lsys2->clear();

  data2->Time.push_back(0);
  data2->setFileName("orthogonal.pos");
  data2->finalize();

#endif
  }

  return view;
}
예제 #5
0
void GMSH_SimplePartitionPlugin::run()
{
#if defined(HAVE_MESH)
  int numSlicesX = (int)SimplePartitionOptions_Number[0].def;
  int numSlicesY = (int)SimplePartitionOptions_Number[1].def;
  int numSlicesZ = (int)SimplePartitionOptions_Number[2].def;
  int createTopology = (int)SimplePartitionOptions_Number[3].def;
  std::vector<std::string> exprX(1), exprY(1), exprZ(1);
  exprX[0] = SimplePartitionOptions_String[0].def;
  exprY[0] = SimplePartitionOptions_String[1].def;
  exprZ[0] = SimplePartitionOptions_String[2].def;

  GModel *m = GModel::current();

  if(!m->getNumMeshElements()){
    Msg::Error("Plugin(SimplePartition) requires a mesh");
    return;
  }

  if(numSlicesX < 1 || numSlicesY < 1 || numSlicesZ < 1){
    Msg::Error("Number of slices should be strictly positive");
    return;
  }
  m->unpartitionMesh();

  SBoundingBox3d bbox = m->bounds();
  double pminX = bbox.min()[0], pmaxX = bbox.max()[0];
  double pminY = bbox.min()[1], pmaxY = bbox.max()[1];
  double pminZ = bbox.min()[2], pmaxZ = bbox.max()[2];
  std::vector<double> ppX(numSlicesX + 1);
  std::vector<double> ppY(numSlicesY + 1);
  std::vector<double> ppZ(numSlicesZ + 1);
  std::vector<std::string> variables(1, "t");
  std::vector<double> values(1), res(1);

  {
    mathEvaluator f(exprX, variables);
    for(int p = 0; p <= numSlicesX; p++) {
      double t = values[0] = (double)p / (double)numSlicesX;
      if(f.eval(values, res)) t = res[0];
      ppX[p] = pminX + t * (pmaxX - pminX);
    }
  }
  bool emptyX = (ppX[0] == ppX[numSlicesX]);
  {
    mathEvaluator f(exprY, variables);
    for(int p = 0; p <= numSlicesY; p++) {
      double t = values[0] = (double)p / (double)numSlicesY;
      if(f.eval(values, res)) t = res[0];
      ppY[p] = pminY + t * (pmaxY - pminY);
    }
  }
  bool emptyY = (ppY[0] == ppY[numSlicesY]);
  {
    mathEvaluator f(exprZ, variables);
    for(int p = 0; p <= numSlicesZ; p++) {
      double t = values[0] = (double)p / (double)numSlicesZ;
      if(f.eval(values, res)) t = res[0];
      ppZ[p] = pminZ + t * (pmaxZ - pminZ);
    }
  }
  bool emptyZ = (ppZ[0] == ppZ[numSlicesZ]);

  std::vector<GEntity *> entities;
  m->getEntities(entities);
  hashmap<MElement *, unsigned int> elmToPartition;
  for(std::size_t i = 0; i < entities.size(); i++) {
    GEntity *ge = entities[i];
    for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) {
      MElement *e = ge->getMeshElement(j);
      SPoint3 point = e->barycenter();
      int part = 0;
      for(int kx = 0; kx < numSlicesX; kx++) {
        if(part) break;
        for(int ky = 0; ky < numSlicesY; ky++) {
          if(part) break;
          for(int kz = 0; kz < numSlicesZ; kz++) {
            if(part) break;
            if((emptyX || (kx == 0 && ppX[0] == point[0]) ||
                (ppX[kx] < point[0] && point[0] <= ppX[kx + 1])) &&
               (emptyY || (ky == 0 && ppY[0] == point[1]) ||
                (ppY[ky] < point[1] && point[1] <= ppY[ky + 1])) &&
               (emptyZ || (kz == 0 && ppZ[0] == point[2]) ||
                (ppZ[kz] < point[2] && point[2] <= ppZ[kz + 1]))){
              part = kx * numSlicesY * numSlicesZ + ky * numSlicesZ + kz + 1;
              elmToPartition.insert(std::pair<MElement *, unsigned int>(e, part));
              e->setPartition(part); // this will be removed
            }
          }
        }
      }
    }
  }

  opt_mesh_partition_create_topology(0, GMSH_SET | GMSH_GUI, createTopology);

  int ier = PartitionUsingThisSplit(m, numSlicesX * numSlicesY * numSlicesZ,
                                    elmToPartition);
  if(!ier) {
    opt_mesh_color_carousel(0, GMSH_SET | GMSH_GUI, 3.);
    CTX::instance()->mesh.changed = ENT_ALL;
  }

#else
  Msg::Error("Gmsh must be compiled with Mesh support to partition meshes");
#endif
}
예제 #6
0
int main(int argc,char *argv[])
{
  if(argc < 6){
    printf("Usage: %s file lx ly lz rmax [levels=1] [refcs=1]\n", argv[0]);
    printf("where\n");
    printf("  'file' contains a CAD model\n");
    printf("  'lx', 'ly' and 'lz' are the sizes of the elements along the"
           " x-, y- and z-axis at the coarsest level\n");
    printf("  'rmax' is the radius of the largest sphere that can be inscribed"
           " in the structure\n");
    printf("  'levels' sets the number of levels in the grid\n");
    printf("  'refcs' selects if curved surfaces should be refined\n");
    return -1;
  }

  GmshInitialize();
  GmshSetOption("General", "Terminal", 1.);
  GmshMergeFile(argv[1]);
  double lx = atof(argv[2]), ly = atof(argv[3]), lz = atof(argv[4]);
  double rmax = atof(argv[5]);
  int levels = (argc > 6) ? atof(argv[6]) : 1;
  int refineCurvedSurfaces = (argc > 7) ? atof(argv[7]) : 1;

  // minimum distance between points in the cloud at the coarsest
  // level
  double sampling = std::min(rmax, std::min(lx, std::min(ly, lz)));

  // radius of the "tube" created around parts to refine at the
  // coarsest level
  double rtube = std::max(lx, std::max(ly, lz)) * 2.;

  GModel *gm = GModel::current();

  std::vector<SPoint3> points;
  Msg::Info("Filling coarse point cloud on surfaces");
  for (GModel::fiter fit = gm->firstFace(); fit != gm->lastFace(); fit++)
    (*fit)->fillPointCloud(sampling, &points);
  Msg::Info("  %d points in the surface cloud", (int)points.size());

  std::vector<SPoint3> refinePoints;
  if(levels > 1){
    double s = sampling / pow(2., levels - 1);
    Msg::Info("Filling refined point cloud on curves and curved surfaces");
    for (GModel::eiter eit = gm->firstEdge(); eit != gm->lastEdge(); eit++)
      fillPointCloud(*eit, s, refinePoints);

    // FIXME: refine this by computing e.g. "mean" curvature
    if(refineCurvedSurfaces){
      for (GModel::fiter fit = gm->firstFace(); fit != gm->lastFace(); fit++)
        if((*fit)->geomType() != GEntity::Plane)
          (*fit)->fillPointCloud(2 * s, &refinePoints);
    }
    Msg::Info("  %d points in the refined cloud", (int)refinePoints.size());
  }

  SBoundingBox3d bb;
  for(unsigned int i = 0; i < points.size(); i++) bb += points[i];
  for(unsigned int i = 0; i < refinePoints.size(); i++) bb += refinePoints[i];
  bb.scale(1.21, 1.21, 1.21);
  SVector3 range = bb.max() - bb.min();
  int NX = range.x() / lx;
  int NY = range.y() / ly;
  int NZ = range.z() / lz;
  if(NX < 2) NX = 2;
  if(NY < 2) NY = 2;
  if(NZ < 2) NZ = 2;

  Msg::Info("  bounding box min: %g %g %g -- max: %g %g %g",
            bb.min().x(), bb.min().y(), bb.min().z(),
            bb.max().x(), bb.max().y(), bb.max().z());
  Msg::Info("  Nx=%d Ny=%d Nz=%d", NX, NY, NZ);

  cartesianBox<double> box(bb.min().x(), bb.min().y(), bb.min().z(),
                           SVector3(range.x(), 0, 0),
                           SVector3(0, range.y(), 0),
                           SVector3(0, 0, range.z()),
                           NX, NY, NZ, levels);

  Msg::Info("Inserting active cells in the cartesian grid");
  Msg::Info("  level %d", box.getLevel());
  for (unsigned int i = 0; i < points.size(); i++)
    insertActiveCells(points[i].x(), points[i].y(), points[i].z(), rmax, box);

  cartesianBox<double> *parent = &box, *child;
  while((child = parent->getChildBox())){
    Msg::Info("  level %d", child->getLevel());
    for(unsigned int i = 0; i < refinePoints.size(); i++)
      insertActiveCells(refinePoints[i].x(), refinePoints[i].y(), refinePoints[i].z(),
                        rtube / pow(2., (levels - child->getLevel())), *child);
    parent = child;
  }

  // remove child cells that do not entirely fill parent cell or for
  // which there is no parent neighbor; then remove parent cells that
  // have children
  Msg::Info("Removing cells to match X-FEM mesh topology constraints");
  removeBadChildCells(&box);
  removeParentCellsWithChildren(&box);

  // we generate duplicate nodes at this point so we can easily access
  // cell values at each level; we will clean up by renumbering after
  // filtering
  Msg::Info("Initializing nodal values in the cartesian grid");
  box.createNodalValues();

  Msg::Info("Computing levelset on the cartesian grid");
  computeLevelset(gm, box);

  Msg::Info("Removing cells outside the structure");
  removeOutsideCells(&box);

  Msg::Info("Renumbering mesh vertices across levels");
  box.renumberNodes();

  bool decomposeInSimplex = false;
  box.writeMSH("yeah.msh", decomposeInSimplex);

  Msg::Info("Done!");
  GmshFinalize();
}
예제 #7
0
PView *GMSH_BubblesPlugin::execute(PView *v)
{
  double shrink = (double)BubblesOptions_Number[0].def;
  std::string fileName = BubblesOptions_String[0].def;

  FILE *fp = Fopen(fileName.c_str(), "w");
  if(!fp){
    Msg::Error("Could not open output file '%s'", fileName.c_str());
    return v;
  }

  GModel *m = GModel::current();

  int p = m->getMaxElementaryNumber(0) + 1;
  int l = m->getMaxElementaryNumber(1) + 1;
  int s = m->getMaxElementaryNumber(2) + 1;
  int ll = s, ps = 1;

  SBoundingBox3d bbox = m->bounds();
  double lc = norm(SVector3(bbox.max(), bbox.min())) / 100;
  fprintf(fp, "lc = %g;\n", lc);

  for(GModel::viter vit = m->firstVertex(); vit != m->lastVertex(); vit++)
    (*vit)->writeGEO(fp, "lc");

  for(GModel::eiter eit = m->firstEdge(); eit != m->lastEdge(); eit++)
    (*eit)->writeGEO(fp);

  for(GModel::fiter fit = m->firstFace(); fit != m->lastFace(); fit++){
    (*fit)->writeGEO(fp);
    fprintf(fp, "Delete { Surface {%d}; }\n", (*fit)->tag());

    int sbeg = s;
    int llbeg = ll;

    // compute vertex-to-triangle_barycenter map
    std::map<MVertex*, std::vector<SPoint3> > v2t;
    for(unsigned int i = 0; i < (*fit)->triangles.size(); i++)
      for(int j = 0; j < 3; j++)
        v2t[(*fit)->triangles[i]->getVertex(j)].push_back((*fit)->triangles[i]->barycenter());

    // add boundary vertices in map to get cells "closer" to the boundary
    for(std::map<MVertex*, std::vector<SPoint3> >::iterator it = v2t.begin();
        it != v2t.end(); it++){
      MVertex *v = it->first;
      if(v->onWhat() && v->onWhat()->dim() < 2)
        it->second.push_back(SPoint3(it->first->x(), it->first->y(), it->first->z()));
    }

    for(std::map<MVertex*, std::vector<SPoint3> >::iterator it = v2t.begin();
        it != v2t.end(); it++){
      if(it->second.size() > 2){
        // get barycenter of cell boundary points and order them
        SPoint3 bc;
        for(unsigned int i = 0; i < it->second.size(); i++)
          bc += it->second[i];
        bc *= 1. / (double)it->second.size();
        compareAngle comp(bc);
        std::sort(it->second.begin(), it->second.end(), comp);
        // shrink cells
        if(shrink){
          for(unsigned int i = 0; i < it->second.size(); i++){
            double dir[3] = {it->second[i].x() - bc.x(),
                             it->second[i].y() - bc.y(),
                             it->second[i].z() - bc.z()};
            it->second[i][0] -= shrink * dir[0];
            it->second[i][1] -= shrink * dir[1];
            it->second[i][2] -= shrink * dir[2];
          }
        }
        // create b-spline bounded surface for each cell
        int nump = it->second.size();
        for(int i = 0; i < nump; i++){
          SPoint3 &b(it->second[i]);
          fprintf(fp, "Point(%d) = {%.16g, %.16g, %.16g, lc};\n", p++, b.x(), b.y(), b.z());
        }
        fprintf(fp, "BSpline(%d) = {", l++);
        for(int i = nump - 1; i >= 0; i--)
          fprintf(fp, "%d,", p - i - 1);
        fprintf(fp, "%d};\n", p - nump);
        fprintf(fp, "Line Loop(%d) = {%d};\n", ll++, l - 1);
        fprintf(fp, "Plane Surface(%d) = {%d};\n", s++, ll - 1);
      }
    }
    fprintf(fp, "Physical Surface(%d) = {%d:%d};\n", ps++, sbeg, s - 1);

    fprintf(fp, "Plane Surface(%d) = {%d, %d:%d};\n", s++, (*fit)->tag(), llbeg, ll - 1);
    fprintf(fp, "Physical Surface(%d) = {%d};\n", ps++, s - 1);
  }

  fclose(fp);

  return v;
}
예제 #8
0
PView *GMSH_TriangulatePlugin::execute(PView *v)
{
  int iView = (int)TriangulateOptions_Number[0].def;

  PView *v1 = getView(iView, v);
  if(!v1) return v;
  PViewData *data1 = v1->getData();

  if(data1->hasMultipleMeshes()){
    Msg::Error("Triangulate plugin cannot be applied to multi-mesh views");
    return v1;
  }

  // create list of points with associated data
  std::vector<MVertex*> points;
  int numSteps = data1->getNumTimeSteps();
  for(int ent = 0; ent < data1->getNumEntities(0); ent++){
    for(int ele = 0; ele < data1->getNumElements(0, ent); ele++){
      if(data1->skipElement(0, ent, ele)) continue;
      if(data1->getNumNodes(0, ent, ele) != 1) continue;
      int numComp = data1->getNumComponents(0, ent, ele);
      double x, y, z;
      data1->getNode(0, ent, ele, 0, x, y, z);
      PointData *p = new PointData(x, y, z, numComp * numSteps);
      for(int step = 0; step < numSteps; step++)
        for(int comp = 0; comp < numComp; comp++)
          data1->getValue(step, ent, ele, 0, comp, p->v[3 + numComp * step + comp]);
      points.push_back(p);
    }
  }

  if(points.size() < 3){
    Msg::Error("Need at least 3 points to triangulate");
    for(unsigned int i = 0; i < points.size(); i++)
      delete points[i];
    return v1;
  }

  // project points onto plane
  discreteFace *s = new discreteFace
    (GModel::current(), GModel::current()->getNumFaces() + 1);
  s->computeMeanPlane(points);
  double plan[3][3];
  s->getMeanPlaneData(plan);
  for(unsigned int i = 0; i < points.size(); i++) project(points[i], plan);
  delete s;

  // get lc
  SBoundingBox3d bbox;
  for(unsigned int i = 0; i < points.size(); i++) bbox += points[i]->point();
  double lc = norm(SVector3(bbox.max(), bbox.min()));

  // build a point record structure for the divide and conquer algorithm
  DocRecord doc(points.size());
  for(unsigned int i = 0; i < points.size(); i++){
    double XX = CTX::instance()->mesh.randFactor * lc * (double)rand() / (double)RAND_MAX;
    double YY = CTX::instance()->mesh.randFactor * lc * (double)rand() / (double)RAND_MAX;
    doc.points[i].where.h = points[i]->x() + XX;
    doc.points[i].where.v = points[i]->y() + YY;
    doc.points[i].adjacent = NULL;
    doc.points[i].data = (void*)points[i];
  }

  // triangulate
  doc.MakeMeshWithPoints();

  // create output (using unperturbed data)
  PView *v2 = new PView();
  PViewDataList *data2 = getDataList(v2);
  for(int i = 0; i < doc.numTriangles; i++){
    PointData *p[3];
    p[0] = (PointData*)doc.points[doc.triangles[i].a].data;
    p[1] = (PointData*)doc.points[doc.triangles[i].b].data;
    p[2] = (PointData*)doc.points[doc.triangles[i].c].data;
    int numComp = 0;
    std::vector<double> *vec = 0;
    if((int)p[0]->v.size() == 3 + 9 * numSteps &&
       (int)p[1]->v.size() == 3 + 9 * numSteps &&
       (int)p[2]->v.size() == 3 + 9 * numSteps){
      numComp = 9; data2->NbTT++; vec = &data2->TT;
    }
    else if((int)p[0]->v.size() == 3 + 3 * numSteps &&
            (int)p[1]->v.size() == 3 + 3 * numSteps &&
            (int)p[2]->v.size() == 3 + 3 * numSteps){
      numComp = 3; data2->NbVT++; vec = &data2->VT;
    }
    else{
      numComp = 1; data2->NbST++; vec = &data2->ST;
    }
    for(int nod = 0; nod < 3; nod++) vec->push_back(p[nod]->v[0]);
    for(int nod = 0; nod < 3; nod++) vec->push_back(p[nod]->v[1]);
    for(int nod = 0; nod < 3; nod++) vec->push_back(p[nod]->v[2]);
    for(int step = 0; step < numSteps; step++)
      for(int nod = 0; nod < 3; nod++)
        for(int comp = 0; comp < numComp; comp++)
          vec->push_back(p[nod]->v[3 + numComp * step + comp]);
  }

  for(unsigned int i = 0; i < points.size(); i++)
    delete points[i];

  for(int i = 0; i < data1->getNumTimeSteps(); i++)
    data2->Time.push_back(data1->getTime(i));
  data2->setName(data1->getName() + "_Triangulate");
  data2->setFileName(data1->getName() + "_Triangulate.pos");
  data2->finalize();

  return v2;
}
예제 #9
0
static int getAspectRatio(std::vector<MElement *> &elements,
                          std::vector<std::vector<MEdge> > &boundaries)
{

  double area3D = 0.0;
  for(unsigned int i = 0; i <elements.size(); ++i){
    MElement *t = elements[i];
    std::vector<MVertex *> v(3);
    for(int k = 0; k < 3; k++) v[k] = t->getVertex(k);
    double p0[3] = {v[0]->x(), v[0]->y(), v[0]->z()};
    double p1[3] = {v[1]->x(), v[1]->y(), v[1]->z()};
    double p2[3] = {v[2]->x(), v[2]->y(), v[2]->z()};
    double a_3D = fabs(triangle_area(p0, p1, p2));
    area3D += a_3D;
  }

  double tot_length = 0.0;
  for(unsigned int i = 0; i <boundaries.size(); ++i){
    std::vector<MEdge> iBound = boundaries[i];
    double iLength = 0.0;
    for( unsigned int j = 0; j <iBound.size(); ++j){
      MVertex *v0 = iBound[j].getVertex(0);
      MVertex *v1 = iBound[j].getVertex(1);
      const double length = sqrt((v0->x() - v1->x()) * (v0->x() - v1->x()) +
                                 (v0->y() - v1->y()) * (v0->y() - v1->y()) +
                                 (v0->z() - v1->z()) * (v0->z() - v1->z()));
      iLength += length;
    }
    tot_length += iLength;
  }
  int AR = 1;
  if (boundaries.size() > 0){
    tot_length /= boundaries.size();
    AR = (int) ceil(2*3.14*area3D/(tot_length*tot_length));
  }

  //compute AR also with Bounding box
  std::set<MVertex*> vs;
  for(unsigned int i = 0; i < elements.size(); i++){
    MElement *e = elements[i];
    for(int j = 0; j < e->getNumVertices(); j++){
      vs.insert(e->getVertex(j));
    }
  }
  SBoundingBox3d bb;
  std::vector<SPoint3> vertices;
  for (std::set<MVertex* >::iterator it = vs.begin(); it != vs.end(); it++){
    SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z());
    vertices.push_back(pt);
    bb += pt;
  }
  double H = norm(SVector3(bb.max(), bb.min()));

  //SOrientedBoundingBox obbox =  SOrientedBoundingBox::buildOBB(vertices);
  //double H = obbox.getMaxSize();

  double D = H;
  if (boundaries.size()  > 0 ) D = 10e4;
  for (unsigned int i = 0; i < boundaries.size(); i++){
    std::set<MVertex*> vb;
    std::vector<MEdge> iBound = boundaries[i];
    for (unsigned int j = 0; j < iBound.size(); j++){
      MEdge e = iBound[j];
      vb.insert(e.getVertex(0));
      vb.insert(e.getVertex(1));
    }
    std::vector<SPoint3> vBounds;
    SBoundingBox3d bb;
    for (std::set<MVertex* >::iterator it = vb.begin(); it != vb.end(); it++){
      SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z());
      vBounds.push_back(pt);
      bb +=pt;
    }
    double iD = norm(SVector3(bb.max(), bb.min()));
    D = std::min(D, iD);

    //SOrientedBoundingBox obboxD = SOrientedBoundingBox::buildOBB(vBounds);
    //D = std::max(D, obboxD.getMaxSize());
  }
  int AR2 = (int)ceil(H/D);

  return std::max(AR, AR2);
}