Ejemplo n.º 1
0
// use real space + projection at the end
static double _relocateVertex2(GFace *gf, MVertex *ver,
                               const std::vector<MElement *> &lt, double tol)
{
  SPoint3 p1(0, 0, 0);
  std::size_t counter = 0;
  for(std::size_t i = 0; i < lt.size(); i++) {
    for(std::size_t j = 0; j < lt[i]->getNumVertices(); j++) {
      MVertex *v = lt[i]->getVertex(j);
      p1 += SPoint3(v->x(), v->y(), v->z());
      counter++;
    }
  }
  p1 *= 1.0 / (double)counter;
  SPoint3 p2(ver->x(), ver->y(), ver->z());
  double worst;
  double xi = Maximize_Quality_Golden_Section(ver, gf, p1, p2, lt, tol, worst);

  SPoint3 p = p1 * (1 - xi) + p2 * xi;
  double initialGuess[2] = {0, 0};
  GPoint pp = gf->closestPoint(p, initialGuess);
  if(!pp.succeeded()) return 2.0;
  ver->x() = pp.x();
  ver->y() = pp.y();
  ver->z() = pp.z();
  return worst;
}
Ejemplo n.º 2
0
void frameFieldBackgroundMesh2D::exportCrossField(const std::string &filename)
{
    FILE *f = Fopen(filename.c_str(), "w");
    if(!f) {
        Msg::Error("Could not open file '%s'", filename.c_str());
        return;
    }
    fprintf(f,"View \"Cross Field\"{\n");
    std::vector<double> deltas(2);
    deltas[0] = 0.;
    deltas[1] = M_PI;

    for (std::vector<MVertex*>::iterator it = beginvertices(); it!=endvertices(); it++) {
        MVertex *v = *it;
        double angle_current = angle(v);
        GPoint p = get_GPoint_from_MVertex(v);
        for (int i=0; i<2; i++) {
            Pair<SVector3, SVector3> dirs = compute_crossfield_directions(v->x(),v->y(),angle_current+deltas[i]);
            fprintf(f,"VP(%g,%g,%g) {%g,%g,%g};\n",p.x(),p.y(),p.z(),dirs.first()[0], dirs.first()[1], dirs.first()[2]);
            fprintf(f,"VP(%g,%g,%g) {%g,%g,%g};\n",p.x(),p.y(),p.z(),dirs.second()[0], dirs.second()[1], dirs.second()[2]);
        }
    }
    fprintf(f,"};\n");
    fclose(f);
}
Ejemplo n.º 3
0
static double objective_function(double const xi, MVertex *const ver,
                                 GFace *const gf, SPoint3 &p1, SPoint3 &p2,
                                 const std::vector<MElement *> &lt)
{
  double const x = ver->x();
  double const y = ver->y();
  double const z = ver->z();
  SPoint3 p = p1 * (1. - xi) + p2 * xi;

  double initialGuess[2] = {0, 0};

  GPoint pp = gf->closestPoint(p, initialGuess);
  ver->x() = pp.x();
  ver->y() = pp.y();
  ver->z() = pp.z();
  double minQual = 1.0;
  for(std::size_t i = 0; i < lt.size(); i++) {
    if(lt[i]->getNumVertices() == 4)
      minQual = std::min(lt[i]->etaShapeMeasure(), minQual);
    else
      minQual = std::min(std::abs(lt[i]->gammaShapeMeasure()), minQual);
  }
  ver->x() = x;
  ver->y() = y;
  ver->z() = z;
  return minQual;
}
Ejemplo n.º 4
0
SOrientedBoundingBox GEdge::getOBB()
{
  if (!_obb) {
    std::vector<SPoint3> vertices;
    if(getNumMeshVertices() > 0) {
      int N = getNumMeshVertices();
      for (int i = 0; i < N; i++) {
        MVertex* mv = getMeshVertex(i);
        vertices.push_back(mv->point());
      }
      // Don't forget to add the first and last vertices...
      SPoint3 pt1(getBeginVertex()->x(), getBeginVertex()->y(), getBeginVertex()->z());
      SPoint3 pt2(getEndVertex()->x(), getEndVertex()->y(), getEndVertex()->z());
      vertices.push_back(pt1);
      vertices.push_back(pt2);
    }
    else if(geomType() != DiscreteCurve && geomType() != BoundaryLayerCurve){
      Range<double> tr = this->parBounds(0);
      // N can be choosen arbitrarily, but 10 points seems reasonable
      int N = 10;
      for (int i = 0; i < N; i++) {
        double t = tr.low() + (double)i / (double)(N - 1) * (tr.high() - tr.low());
        GPoint p = point(t);
        SPoint3 pt(p.x(), p.y(), p.z());
        vertices.push_back(pt);
      }
    }
    else {
      SPoint3 dummy(0, 0, 0);
      vertices.push_back(dummy);
    }
    _obb = SOrientedBoundingBox::buildOBB(vertices);
  }
  return SOrientedBoundingBox(_obb);
}
Ejemplo n.º 5
0
SPoint2 GEdge::reparamOnFace(const GFace *face, double epar,int dir) const
{
  // reparametrize the point onto the given face.
  const GPoint p3 = point(epar);
  SPoint3 sp3(p3.x(), p3.y(), p3.z());
  return face->parFromPoint(sp3);
}
Ejemplo n.º 6
0
void copyMesh(GEdge *from, GEdge *to, int direction)
{  
  Range<double> u_bounds = from->parBounds(0);
  double u_min = u_bounds.low();
  double u_max = u_bounds.high();

  Range<double> to_u_bounds = to->parBounds(0);
  double to_u_min = to_u_bounds.low();
  double to_u_max = to_u_bounds.high();

  for(unsigned int i = 0; i < from->mesh_vertices.size(); i++){
    int index = (direction < 0) ? (from->mesh_vertices.size() - 1 - i) : i;
    MVertex *v = from->mesh_vertices[index];
    double u; v->getParameter(0, u);
    double newu = (direction > 0) ? (u-u_min+to_u_min) : (u_max-u+to_u_min);
    GPoint gp = to->point(newu);
    MEdgeVertex *vv = new MEdgeVertex(gp.x(), gp.y(), gp.z(), to, newu);
    to->mesh_vertices.push_back(vv);
    to->correspondingVertices[vv] = v;
  }
  for(unsigned int i = 0; i < to->mesh_vertices.size() + 1; i++){
    MVertex *v0 = (i == 0) ?
      to->getBeginVertex()->mesh_vertices[0] : to->mesh_vertices[i - 1];
    MVertex *v1 = (i == to->mesh_vertices.size()) ?
      to->getEndVertex()->mesh_vertices[0] : to->mesh_vertices[i];
    to->lines.push_back(new MLine(v0, v1));
  }
}
Ejemplo n.º 7
0
void BGMBase::export_vector(const std::string &filename,
                            const VectorStorageType &_whatToPrint) const
{
  FILE *f = Fopen(filename.c_str(), "w");
  if(!f) {
    Msg::Error("Could not open file '%s'", filename.c_str());
    return;
  }

  fprintf(f, "View \"Background Mesh\"{\n");

  const MElement *elem;
  int nvertex;
  int type;

  for(unsigned int i = 0; i < getNumMeshElements(); i++) {
    elem = getElement(i);
    nvertex = elem->getNumVertices();
    type = elem->getType();
    const char *s = 0;
    switch(type) {
    case TYPE_PNT: s = "VP"; break;
    case TYPE_LIN: s = "VL"; break;
    case TYPE_TRI: s = "VT"; break;
    case TYPE_QUA: s = "VQ"; break;
    case TYPE_TET: s = "VS"; break;
    case TYPE_HEX: s = "VH"; break;
    case TYPE_PRI: s = "VI"; break;
    case TYPE_PYR: s = "VY"; break;
    default: throw;
    }

    fprintf(f, "%s(", s);
    const MVertex *v;
    std::vector<double> values(nvertex * 3);
    for(int iv = 0; iv < nvertex; iv++) {
      v = elem->getVertex(iv);
      std::vector<double> temp = get_nodal_value(v, _whatToPrint);
      for(int j = 0; j < 3; j++) values[iv * 3 + j] = temp[j];
      GPoint p = get_GPoint_from_MVertex(v);
      fprintf(f, "%g,%g,%g", p.x(), p.y(), p.z());
      if(iv != nvertex - 1)
        fprintf(f, ",");
      else
        fprintf(f, "){");
    }
    for(int iv = 0; iv < nvertex; iv++) {
      for(int j = 0; j < 3; j++) {
        fprintf(f, "%g", values[iv * 3 + j]);
        if(!((iv == nvertex - 1) && (j == 2)))
          fprintf(f, ",");
        else
          fprintf(f, "};\n");
      }
    }
  }
  fprintf(f, "};\n");
  fclose(f);
}
Ejemplo n.º 8
0
void BGMBase::export_scalar(const std::string &filename,
                            const DoubleStorageType &_whatToPrint) const
{
  FILE *f = Fopen(filename.c_str(), "w");
  if(!f) {
    Msg::Error("Could not open file '%s'", filename.c_str());
    return;
  }

  fprintf(f, "View \"Background Mesh\"{\n");

  const MElement *elem;
  int nvertex;
  int type;

  for(unsigned int i = 0; i < getNumMeshElements(); i++) {
    elem = getElement(i);
    nvertex = elem->getNumVertices();
    type = elem->getType();
    const char *s = 0;
    switch(type) {
    case TYPE_PNT: s = "SP"; break;
    case TYPE_LIN: s = "SL"; break;
    case TYPE_TRI: s = "ST"; break;
    case TYPE_QUA: s = "SQ"; break;
    case TYPE_TET: s = "SS"; break;
    case TYPE_HEX: s = "SH"; break;
    case TYPE_PRI: s = "SI"; break;
    case TYPE_PYR: s = "SY"; break;
    default: throw;
    }

    fprintf(f, "%s(", s);
    const MVertex *v;
    std::vector<double> values(nvertex);
    for(int iv = 0; iv < nvertex; iv++) {
      v = elem->getVertex(iv);
      values[iv] = get_nodal_value(v, _whatToPrint);
      // GPoint p = gf->point(SPoint2(v->x(),v->y()));
      GPoint p = get_GPoint_from_MVertex(v);
      fprintf(f, "%g,%g,%g", p.x(), p.y(), p.z());
      if(iv != nvertex - 1)
        fprintf(f, ",");
      else
        fprintf(f, "){");
    }
    for(int iv = 0; iv < nvertex; iv++) {
      fprintf(f, "%g", values[iv]);
      if(iv != nvertex - 1)
        fprintf(f, ",");
      else
        fprintf(f, "};\n");
    }
  }
  fprintf(f, "};\n");
  fclose(f);
}
Ejemplo n.º 9
0
SVector3 gmshFace::normal(const SPoint2 &param) const
{
  if(s->Typ != MSH_SURF_PLAN){
    Vertex vu = InterpolateSurface(s, param[0], param[1], 1, 1);
    Vertex vv = InterpolateSurface(s, param[0], param[1], 1, 2);
    Vertex n = vu % vv;
    n.norme();
    return SVector3(n.Pos.X, n.Pos.Y, n.Pos.Z);
  }
  else{
    // We cannot use InterpolateSurface() for plane surfaces since it
    // relies on the mean plane, which does not respect the
    // orientation

    // FIXME: move this test at the end of the MeanPlane computation
    // routine--and store the correct normal, damn it!

    double n[3] = {meanPlane.a, meanPlane.b, meanPlane.c};
    norme(n);
    GPoint pt = point(param.x(), param.y());
    double v[3] = {pt.x(), pt.y(), pt.z()};
    int NP = 10, tries = 0;
    while(1){
      tries++;
      double angle = 0.;
      for(int i = 0; i < List_Nbr(s->Generatrices); i++) {
        Curve *c;
        List_Read(s->Generatrices, i, &c);
        int N = (c->Typ == MSH_SEGM_LINE) ? 1 : NP;
        for(int j = 0; j < N; j++) {
          double u1 = (double)j / (double)N;
          double u2 = (double)(j + 1) / (double)N;
          Vertex p1 = InterpolateCurve(c, u1, 0);
          Vertex p2 = InterpolateCurve(c, u2, 0);
          double v1[3] = {p1.Pos.X, p1.Pos.Y, p1.Pos.Z};
          double v2[3] = {p2.Pos.X, p2.Pos.Y, p2.Pos.Z};
          angle += angle_plan(v, v1, v2, n);
        }
      }
      if(fabs(angle) < 0.5){ // we're outside
        NP *= 2;
        Msg::Debug("Could not compute normal of surface %d - retrying with %d points",
                   tag(), NP);
        if(tries > 10){
          Msg::Warning("Could not orient normal of surface %d", tag());
          return SVector3(n[0], n[1], n[2]);
        }
      }
      else if(angle > 0)
        return SVector3(n[0], n[1], n[2]);
      else
        return SVector3(-n[0], -n[1], -n[2]);
    }
  }
}
Ejemplo n.º 10
0
bool GEdge::computeDistanceFromMeshToGeometry (double &d2, double &dmax)
{
  d2 = 0.0; dmax = 0.0;
  if (geomType() == Line) return true;
  if (!lines.size())return false;
  IntPt *pts;
  int npts;
  lines[0]->getIntegrationPoints(2*lines[0]->getPolynomialOrder(), &npts, &pts);

  for (unsigned int i = 0; i < lines.size(); i++){
    MLine *l = lines[i];
    double t[256];

    for (int j=0; j< l->getNumVertices();j++){
      MVertex *v = l->getVertex(j);
      if (v->onWhat() == getBeginVertex()){
	t[j] = getLowerBound();
      }
      else if (v->onWhat() == getEndVertex()){
	t[j] = getUpperBound();
      }
      else {
	v->getParameter(0,t[j]);
      }
    }
    for (int j=0;j<npts;j++){
      SPoint3 p;
      l->pnt(pts[j].pt[0],0,0,p);
      double tinit = l->interpolate(t,pts[j].pt[0],0,0);
      GPoint pc = closestPoint(p, tinit);
      if (!pc.succeeded())continue;
      double dsq =
	(pc.x()-p.x())*(pc.x()-p.x()) +
	(pc.y()-p.y())*(pc.y()-p.y()) +
	(pc.z()-p.z())*(pc.z()-p.z());
      d2 += pts[i].weight * fabs(l->getJacobianDeterminant(pts[j].pt[0],0,0)) * dsq;
      dmax = std::max(dmax,sqrt(dsq));
    }
  }
  d2 = sqrt(d2);
  return true;
}
Ejemplo n.º 11
0
static double F_Lc(GEdge *ge, double t)
{
  GPoint p = ge->point(t);
  double lc_here;

  Range<double> bounds = ge->parBounds(0);
  double t_begin = bounds.low();
  double t_end = bounds.high();

  if(t == t_begin)
    lc_here = BGM_MeshSize(ge->getBeginVertex(), t, 0, p.x(), p.y(), p.z());
  else if(t == t_end)
    lc_here = BGM_MeshSize(ge->getEndVertex(), t, 0, p.x(), p.y(), p.z());
  else
    lc_here = BGM_MeshSize(ge, t, 0, p.x(), p.y(), p.z());

  SVector3 der = ge->firstDer(t);
  const double d = norm(der);

  return d / lc_here;
}
Ejemplo n.º 12
0
void splitEdgePass(GFace *gf, BDS_Mesh &m, double MAXE_, int &nb_split)
{
  std::list<BDS_Edge*>::iterator it = m.edges.begin();
  std::vector<std::pair<double, BDS_Edge*> > edges;

  while (it != m.edges.end()){
    if(!(*it)->deleted && (*it)->numfaces() == 2){
      double lone = NewGetLc(*it, gf, m.scalingU, m.scalingV);
      if(lone > MAXE_){
        edges.push_back(std::make_pair(-lone, *it));
      }
    }
    ++it;
  }

  std::sort(edges.begin(), edges.end());

  for (unsigned int i = 0; i < edges.size(); ++i){
    BDS_Edge *e = edges[i].second;
    if (!e->deleted){
      const double coord = 0.5;
      BDS_Point *mid ;
      double U, V;
      U = coord * e->p1->u + (1 - coord) * e->p2->u;
      V = coord * e->p1->v + (1 - coord) * e->p2->v;

      GPoint gpp = gf->point(m.scalingU*U,m.scalingV*V);
      if (gpp.succeeded()){
        mid  = m.add_point(++m.MAXPOINTNUMBER, gpp.x(),gpp.y(),gpp.z());
        mid->u = U;
        mid->v = V;
        if (backgroundMesh::current() && 0){
          mid->lc() = mid->lcBGM() =
            backgroundMesh::current()->operator()
            ((coord * e->p1->u + (1 - coord) * e->p2->u)*m.scalingU,
             (coord * e->p1->v + (1 - coord) * e->p2->v)*m.scalingV,
             0.0);
        }
        else {
          mid->lcBGM() = BGM_MeshSize
            (gf,
             (coord * e->p1->u + (1 - coord) * e->p2->u)*m.scalingU,
             (coord * e->p1->v + (1 - coord) * e->p2->v)*m.scalingV,
             mid->X,mid->Y,mid->Z);
	  mid->lc() = 0.5 * (e->p1->lc() +  e->p2->lc());
        }
        if(!m.split_edge(e, mid)) m.del_point(mid);
        else nb_split++;
      }
    }
  }
}
Ejemplo n.º 13
0
void GEdge::relocateMeshVertices()
{
  for(unsigned int i = 0; i < mesh_vertices.size(); i++){
    MVertex *v = mesh_vertices[i];
    double u0 = 0;
    if(v->getParameter(0, u0)){
      GPoint p = point(u0);
      v->x() = p.x();
      v->y() = p.y();
      v->z() = p.z();
    }
  }
}
Ejemplo n.º 14
0
static void fillPointCloud(GEdge *ge, double sampling, std::vector<SPoint3> &points)
{
  Range<double> t_bounds = ge->parBounds(0);
  double t_min = t_bounds.low();
  double t_max = t_bounds.high();
  double length = ge->length(t_min, t_max, 20);
  int N = length / sampling;
  for(int i = 0; i < N; i++) {
    double t = t_min + (double)i / (double)(N - 1) * (t_max - t_min);
    GPoint p = ge->point(t);
    points.push_back(SPoint3(p.x(), p.y(), p.z()));
  }
}
Ejemplo n.º 15
0
static double F_Lc_aniso(GEdge *ge, double t)
{
#if defined(HAVE_ANN)
  FieldManager *fields = ge->model()->getFields();
  BoundaryLayerField *blf = 0;
  Field *bl_field = fields->get(fields->getBoundaryLayerField());
  blf = dynamic_cast<BoundaryLayerField*> (bl_field);
#else
  bool blf = false;
#endif


  GPoint p = ge->point(t);
  SMetric3 lc_here;

  Range<double> bounds = ge->parBounds(0);
  double t_begin = bounds.low();
  double t_end = bounds.high();

  if(t == t_begin)
    lc_here = BGM_MeshMetric(ge->getBeginVertex(), t, 0, p.x(), p.y(), p.z());
  else if(t == t_end)
    lc_here = BGM_MeshMetric(ge->getEndVertex(), t, 0, p.x(), p.y(), p.z());
  else
    lc_here = BGM_MeshMetric(ge, t, 0, p.x(), p.y(), p.z());

#if defined(HAVE_ANN)
  if (blf && !blf->isEdgeBL(ge->tag())){
    SMetric3 lc_bgm;
    blf->computeFor1dMesh ( p.x(), p.y(), p.z() , lc_bgm );
    lc_here = intersection_conserveM1 (lc_here, lc_bgm );
  }
#endif

  SVector3 der = ge->firstDer(t);
  double lSquared = dot(der, lc_here, der);
  return sqrt(lSquared);
}
Ejemplo n.º 16
0
inline double computeEdgeMiddleCoord(BDS_Point *p1, BDS_Point *p2, GFace *f,
                                     double SCALINGU, double SCALINGV)
{
  if (f->geomType() == GEntity::Plane)
    return 0.5;

  GPoint GP = f->point(SPoint2(0.5 * (p1->u + p2->u) * SCALINGU,
                               0.5 * (p1->v + p2->v) * SCALINGV));

  const double dx1 = p1->X - GP.x();
  const double dy1 = p1->Y - GP.y();
  const double dz1 = p1->Z - GP.z();
  const double l1 = sqrt(dx1 * dx1 + dy1 * dy1 + dz1 * dz1);
  const double dx2 = p2->X - GP.x();
  const double dy2 = p2->Y - GP.y();
  const double dz2 = p2->Z - GP.z();
  const double l2 = sqrt(dx2 * dx2 + dy2 * dy2 + dz2 * dz2);

  if (l1 > l2)
    return 0.25 * (l1 + l2) / l1;
  else
    return 0.25 * (3 * l2 - l1) / l2;
}
Ejemplo n.º 17
0
SBoundingBox3d GEdge::bounds() const
{
  SBoundingBox3d bbox;
  if(geomType() != DiscreteCurve && geomType() != BoundaryLayerCurve){
    Range<double> tr = parBounds(0);
    const int N = 10;
    for(int i = 0; i < N; i++){
      double t = tr.low() + (double)i / (double)(N - 1) * (tr.high() - tr.low());
      GPoint p = point(t);
      bbox += SPoint3(p.x(), p.y(), p.z());
    }
  }
  else{
    for(unsigned int i = 0; i < mesh_vertices.size(); i++)
      bbox += mesh_vertices[i]->point();
  }
  return bbox;
}
Ejemplo n.º 18
0
void GEdge::writeGEO(FILE *fp)
{
  if(!getBeginVertex() || !getEndVertex() || geomType() == DiscreteCurve) return;

  if(geomType() == Line){
    fprintf(fp, "Line(%d) = {%d, %d};\n",
            tag(), getBeginVertex()->tag(), getEndVertex()->tag());
  }
  else{
    // approximate other curves by splines
    Range<double> bounds = parBounds(0);
    double umin = bounds.low();
    double umax = bounds.high();
    fprintf(fp, "p%d = newp;\n", tag());
    int N = minimumDrawSegments();
    for(int i = 1; i < N; i++){
      double u = umin + (double)i / N * (umax - umin);
      GPoint p = point(u);
      fprintf(fp, "Point(p%d + %d) = {%.16g, %.16g, %.16g};\n",
              tag(), i, p.x(), p.y(), p.z());
    }
    fprintf(fp, "Spline(%d) = {%d", tag(), getBeginVertex()->tag());
    for(int i = 1; i < N; i++)
      fprintf(fp, ", p%d + %d", tag(), i);
    fprintf(fp, ", %d};\n", getEndVertex()->tag());
  }

  if(meshAttributes.method == MESH_TRANSFINITE){
    fprintf(fp, "Transfinite Line {%d} = %d",
            tag() * (meshAttributes.typeTransfinite > 0 ? 1 : -1),
            meshAttributes.nbPointsTransfinite);
    if(meshAttributes.typeTransfinite){
      if(std::abs(meshAttributes.typeTransfinite) == 1)
        fprintf(fp, " Using Progression ");
      else
        fprintf(fp, " Using Bump ");
      fprintf(fp, "%g", meshAttributes.coeffTransfinite);
    }
    fprintf(fp, ";\n");
  }

  if(meshAttributes.reverseMesh)
    fprintf(fp, "Reverse Line {%d};\n", tag());
}
Ejemplo n.º 19
0
static double _relocateVertex(GFace *gf, MVertex *ver,
                              const std::vector<MElement *> &lt, double tol)
{
  if(ver->onWhat()->dim() != 2) return 2.0;

  SPoint2 p1(0, 0);
  SPoint2 p2;
  if(ver->getParameter(0, p2[0])) {
    ver->getParameter(1, p2[1]);
  }
  else {
    return _relocateVertex2(gf, ver, lt, tol);
  }

  std::size_t counter = 0;
  for(std::size_t i = 0; i < lt.size(); i++) {
    for(std::size_t j = 0; j < lt[i]->getNumVertices(); j++) {
      MVertex *v = lt[i]->getVertex(j);
      SPoint2 pp;
      reparamMeshVertexOnFace(v, gf, pp);
      counter++;
      if(v->onWhat()->dim() == 1) {
        GEdge *ge = dynamic_cast<GEdge *>(v->onWhat());
        // do not take any chance
        if(ge->isSeam(gf)) return 2.0;
      }
      p1 += pp;
    }
  }
  p1 *= 1. / (double)counter;
  double worst;
  double xi = Maximize_Quality_Golden_Section(ver, gf, p1, p2, lt, tol, worst);
  // if (xi != 0) printf("xi = %g\n",xi);
  SPoint2 p = p1 * (1 - xi) + p2 * xi;
  GPoint pp = gf->point(p);
  if(!pp.succeeded()) return 2.0;
  ver->x() = pp.x();
  ver->y() = pp.y();
  ver->z() = pp.z();
  ver->setParameter(0, pp.u());
  ver->setParameter(1, pp.v());
  return worst;
}
Ejemplo n.º 20
0
 virtual void onHandleClick(GClick* click) {
     if (click->isName("move")) {
         const GPoint curr = click->curr();
         const GPoint prev = click->prev();
         fShape->setRect(offset(fShape->getRect(), curr.x() - prev.x(), curr.y() - prev.y()));
     } else if (click->isName("resize")) {
         fShape->setRect(((ResizeClick*)click)->makeRect());
     } else {
         fShape->setRect(make_from_pts(click->orig(), click->curr()));
     }
     if (NULL != fShape && GClick::kUp_State == click->state()) {
         if (fShape->getRect().isEmpty()) {
             this->removeShape(fShape);
             fShape = NULL;
         }
     }
     this->updateTitle();
     this->requestDraw();
 }
Ejemplo n.º 21
0
void highOrderTools::computeMetricInfo(GFace *gf,
                                       MElement *e,
                                       fullMatrix<double> &J,
                                       fullMatrix<double> &JT,
                                       fullVector<double> &D)
{
  int nbNodes = e->getNumVertices();
  //  printf("ELEMENT --\n");
  for (int j = 0; j < nbNodes; j++){
    SPoint2 param;
    reparamMeshVertexOnFace(e->getVertex(j), gf, param);
    //    printf("%g %g vs %g %g %g\n",param.x(),param.y(),
    //	   e->getVertex(j)->x(),e->getVertex(j)->y(),e->getVertex(j)->z());

    Pair<SVector3,SVector3> der = gf->firstDer(param);

    int XJ = j;
    int YJ = j + nbNodes;
    int ZJ = j + 2 * nbNodes;
    int UJ = j;
    int VJ = j + nbNodes;
    J(XJ,UJ) = der.first().x();
    J(YJ,UJ) = der.first().y();
    J(ZJ,UJ) = der.first().z();
    J(XJ,VJ) = der.second().x();
    J(YJ,VJ) = der.second().y();
    J(ZJ,VJ) = der.second().z();

    JT(UJ,XJ) = der.first().x();
    JT(UJ,YJ) = der.first().y();
    JT(UJ,ZJ) = der.first().z();
    JT(VJ,XJ) = der.second().x();
    JT(VJ,YJ) = der.second().y();
    JT(VJ,ZJ) = der.second().z();

    SVector3 ss = getSSL(e->getVertex(j));
    GPoint gp = gf->point(param);
    D(XJ) = (gp.x() - ss.x());
    D(YJ) = (gp.y() - ss.y());
    D(ZJ) = (gp.z() - ss.z());
  }
}
Ejemplo n.º 22
0
static double objective_function(double xi, MVertex *ver, GFace *gf,
                                 SPoint2 &p1, SPoint2 &p2,
                                 const std::vector<MElement *> &lt)
{
  double x = ver->x();
  double y = ver->y();
  double z = ver->z();
  SPoint2 p = p1 * (1. - xi) + p2 * xi;
  GPoint pp = gf->point(p);
  ver->x() = pp.x();
  ver->y() = pp.y();
  ver->z() = pp.z();
  double minQual = 1.0;
  for(std::size_t i = 0; i < lt.size(); i++) {
    if(lt[i]->getNumVertices() == 4)
      minQual = std::min((lt[i]->etaShapeMeasure()), minQual);
    else
      minQual = std::min(std::abs(lt[i]->gammaShapeMeasure()), minQual);
  }
  ver->x() = x;
  ver->y() = y;
  ver->z() = z;
  return minQual;
}
Ejemplo n.º 23
0
static void Subdivide(GFace *gf, bool splitIntoQuads, bool splitIntoHexas,
                      faceContainer &faceVertices)
{

  if(!splitIntoQuads && !splitIntoHexas){
    std::vector<MTriangle*> triangles2;
    for(unsigned int i = 0; i < gf->triangles.size(); i++){
      MTriangle *t = gf->triangles[i];
      if(t->getNumVertices() == 6){
        triangles2.push_back
          (new MTriangle(t->getVertex(0), t->getVertex(3), t->getVertex(5)));
        triangles2.push_back
          (new MTriangle(t->getVertex(3), t->getVertex(4), t->getVertex(5)));
        triangles2.push_back
          (new MTriangle(t->getVertex(3), t->getVertex(1), t->getVertex(4)));
        triangles2.push_back
          (new MTriangle(t->getVertex(5), t->getVertex(4), t->getVertex(2)));
      }
      delete t;
    }
    gf->triangles = triangles2;
  }

  std::vector<MQuadrangle*> quadrangles2;
  for(unsigned int i = 0; i < gf->quadrangles.size(); i++){
    MQuadrangle *q = gf->quadrangles[i];
    if(q->getNumVertices() == 9){
      quadrangles2.push_back
        (new MQuadrangle(q->getVertex(0), q->getVertex(4), q->getVertex(8), q->getVertex(7)));
      quadrangles2.push_back
        (new MQuadrangle(q->getVertex(4), q->getVertex(1), q->getVertex(5), q->getVertex(8)));
      quadrangles2.push_back
        (new MQuadrangle(q->getVertex(8), q->getVertex(5), q->getVertex(2), q->getVertex(6)));
      quadrangles2.push_back
        (new MQuadrangle(q->getVertex(7), q->getVertex(8), q->getVertex(6), q->getVertex(3)));
    }
    delete q;
  }
  if(splitIntoQuads || splitIntoHexas){
    for(unsigned int i = 0; i < gf->triangles.size(); i++){
      MTriangle *t = gf->triangles[i];
      if(t->getNumVertices() == 6){
        SPoint2 pt;
        SPoint3 ptx; t->pnt(0.5, 0.5, 0, ptx);
        bool reparamOK = true;
        for(int k = 0; k < 6; k++){
          SPoint2 temp;
          reparamOK &= reparamMeshVertexOnFace(t->getVertex(k), gf, temp);
          pt[0] += temp[0] / 6.;
          pt[1] += temp[1] / 6.;
        }
        MVertex *newv;
        if (reparamOK){
          GPoint gp = gf->point(pt);
          newv = new MFaceVertex(gp.x(), gp.y(), gp.z(), gf, pt[0], pt[1]);
        }
        else {
          newv = new MVertex(ptx.x(), ptx.y(), ptx.z(), gf);
        }
        gf->mesh_vertices.push_back(newv);
        if(splitIntoHexas) faceVertices[t->getFace(0)].push_back(newv);
        quadrangles2.push_back
          (new MQuadrangle(t->getVertex(0), t->getVertex(3), newv, t->getVertex(5)));
        quadrangles2.push_back
          (new MQuadrangle(t->getVertex(3), t->getVertex(1), t->getVertex(4), newv));
        quadrangles2.push_back
          (new MQuadrangle(t->getVertex(5), newv,t->getVertex(4), t->getVertex(2)));
        delete t;
      }
    }
    gf->triangles.clear();
  }
  gf->quadrangles = quadrangles2;

  for(unsigned int i = 0; i < gf->mesh_vertices.size(); i++)
    gf->mesh_vertices[i]->setPolynomialOrder(1);
  gf->deleteVertexArrays();
}
Ejemplo n.º 24
0
bool OptHOM::addBndObjGrad(double factor, double &Obj, alglib::real_1d_array &gradObj)
{
  // set the mesh to its present position
  std::vector<SPoint3> xyz,uvw;
  mesh.getGEntityPositions(xyz,uvw);
  mesh.updateGEntityPositions();

  //could be better (e.g. store the model in the Mesh:: datastrucure)

  GModel *gm = GModel::current();

  // for all model edges, compute the error between the geometry and the mesh

  maxDistCAD = 0.0;
  double distCAD = 0.0;

  for (GModel::eiter it = gm->firstEdge(); it != gm->lastEdge(); ++it){
    // do not do straight lines
    if ((*it)->geomType() == GEntity::Line)continue;
    // look at all mesh lines

    std::vector<bool> doWeCompute((*it)->lines.size());
    for (unsigned int i=0;i<(*it)->lines.size(); i++){
      doWeCompute[i] = false;
      for (unsigned int j=0;j<(*it)->lines[i]->getNumVertices(); j++){
        int index = mesh.getFreeVertexStartIndex((*it)->lines[i]->getVertex(j));
        if (index >=0){
          doWeCompute[i] = true;
          continue;
        }
      }
    }

    std::vector<double> dist((*it)->lines.size());
    for (unsigned int i=0;i<(*it)->lines.size(); i++){
      if (doWeCompute[i]){
        // compute the distance from the geometry to the mesh
        dist[i] = MLineGEdgeDistance ( (*it)->lines[i] , *it );
        maxDistCAD = std::max(maxDistCAD,dist[i]);
        distCAD += dist [i] * factor;
      }
    }
    // be clever to compute the derivative : iterate on all
    // Distance = \sum_{lines} Distance (line, GEdge)
    // For a high order vertex, we compute the derivative only by
    // recomputing the distance to one only line
    const double eps = 1.e-6;
    for (unsigned int i=0;i<(*it)->lines.size(); i++){
      if (doWeCompute[i]){
        for (int j=2 ; j<(*it)->lines[i]->getNumVertices()  ; j++){
          MVertex *v = (*it)->lines[i]->getVertex(j);
          int index = mesh.getFreeVertexStartIndex(v);
          //	printf("%d %d (%d %d)\n",v->getNum(),index,v->onWhat()->tag(),v->onWhat()->dim());
          if (index >= 0){
            double t;
            v->getParameter(0,t);
            SPoint3 pp (v->x(),v->y(),v->z());
            GPoint gp = (*it)->point(t+eps);
            v->setParameter(0,t+eps);
            v->setXYZ(gp.x(),gp.y(),gp.z());
            double dist2 = MLineGEdgeDistance ( (*it)->lines[i] , *it );
            double deriv = (dist2 - dist[i])/eps;
            v->setXYZ(pp.x(),pp.y(),pp.z());
            v->setParameter(0,t);
            //	  printf("%g %g %g\n",dist[i],dist2, MLineGEdgeDistance ( (*it)->lines[i] , *it ));
            // get the index of the vertex
            gradObj[index] += deriv * factor;
          }
        }
      }
      //    printf("done\n");
      // For a low order vertex classified on the GEdge, we recompute
    // two distances for the two MLines connected to the vertex
      for (unsigned int i=0;i<(*it)->lines.size()-1; i++){
        MVertex *v =  (*it)->lines[i]->getVertex(1);
        int index = mesh.getFreeVertexStartIndex(v);
        if (index >= 0){
          double t;
          v->getParameter(0,t);
          SPoint3 pp (v->x(),v->y(),v->z());
          GPoint gp = (*it)->point(t+eps);
          v->setParameter(0,t+eps);
          v->setXYZ(gp.x(),gp.y(),gp.z());
          MLine *l1 = (*it)->lines[i];
          MLine *l2 = (*it)->lines[i+1];
          //	printf("%d %d -- %d %d\n",l1->getVertex(0)->getNum(),l1->getVertex(1)->getNum(),l2->getVertex(0)->getNum(),l2->getVertex(1)->getNum());
          double deriv =
            (MLineGEdgeDistance ( l1 , *it ) - dist[i])  /eps +
            (MLineGEdgeDistance ( l2 , *it ) - dist[i+1])/eps;
          v->setXYZ(pp.x(),pp.y(),pp.z());
          v->setParameter(0,t);
          gradObj[index] += deriv * factor;
        }
      }
    }
  }
  //  printf("computing distance : 1D part %12.5E\n",distCAD);

  // now the 3D part !

  std::vector<std::vector<SVector3> > gsfT;
  computeGradSFAtNodes ( (*gm->firstFace())->triangles[0],gsfT);

  std::map<MVertex*,SVector3> normalsToCAD;


  for(GModel::fiter it = gm->firstFace(); it != gm->lastFace(); ++it){
    // do not do plane surfaces
    if ((*it)->geomType() == GEntity::Plane)continue;
    std::map<MTriangle*,double> dist;

    std::vector<bool> doWeCompute((*it)->triangles.size());
    for (unsigned int i=0;i<(*it)->triangles.size(); i++){
      doWeCompute[i] = false;
      for (unsigned int j=0;j<(*it)->triangles[i]->getNumVertices(); j++){
        int index = mesh.getFreeVertexStartIndex((*it)->triangles[i]->getVertex(j));
        if (index >=0){
          doWeCompute[i] = true;
        }
      }
      if (doWeCompute[i]){
        for (unsigned int j=0;j<(*it)->triangles[i]->getNumVertices(); j++){
          MVertex *v = (*it)->triangles[i]->getVertex(j);
          if (normalsToCAD.find(v) == normalsToCAD.end()){
            SPoint2 p_cad;
            reparamMeshVertexOnFace(v, *it, p_cad);
            SVector3 tg_cad = (*it)->normal(p_cad);
            tg_cad.normalize();
            normalsToCAD[v] = tg_cad;
          }
        }
      }
    }

    for (unsigned int i=0;i<(*it)->triangles.size(); i++){
      // compute the distance from the geometry to the mesh
      if(doWeCompute[i]){
        const double d = MFaceGFaceDistanceOld((*it)->triangles[i], *it, &gsfT, &normalsToCAD);
        dist[(*it)->triangles[i]] = d;
        maxDistCAD = std::max(maxDistCAD,d);
        distCAD += d * factor;
      }
    }

    // be clever again to compute the derivatives
    const double eps = 1.e-6;
    for (unsigned int i=0;i<(*it)->triangles.size(); i++){
      if(doWeCompute[i]){
        for (unsigned int j=0;j<(*it)->triangles[i]->getNumVertices(); j++){
          //    for (; itm !=v2t.end(); ++itm){
          MVertex   *v = (*it)->triangles[i]->getVertex(j);
          if(v->onWhat()->dim() == 1){
            int index = mesh.getFreeVertexStartIndex(v);
            if (index >= 0){
              MTriangle *t = (*it)->triangles[i];
              GEdge *ge = v->onWhat()->cast2Edge();
              double t_;
              v->getParameter(0,t_);
              SPoint3 pp (v->x(),v->y(),v->z());
              GPoint gp = ge->point(t_+eps);
              v->setParameter(0,t_+eps);
              v->setXYZ(gp.x(),gp.y(),gp.z());
              const double distT = dist[t];
              double deriv =  (MFaceGFaceDistanceOld(t, *it, &gsfT, &normalsToCAD) - distT) /eps;
              v->setXYZ(pp.x(),pp.y(),pp.z());
              v->setParameter(0,t_);
              gradObj[index] += deriv * factor;
            }
          }

          if(v->onWhat() == *it){
            int index = mesh.getFreeVertexStartIndex(v);
            if (index >= 0){
              MTriangle *t = (*it)->triangles[i];
              double uu,vv;
              v->getParameter(0,uu);
              v->getParameter(1,vv);
              SPoint3 pp (v->x(),v->y(),v->z());

              const double distT = dist[t];

              GPoint gp = (*it)->point(uu+eps,vv);
              v->setParameter(0,uu+eps);
              v->setXYZ(gp.x(),gp.y(),gp.z());
              double deriv = (MFaceGFaceDistanceOld(t, *it, &gsfT, &normalsToCAD) - distT) /eps;
              v->setXYZ(pp.x(),pp.y(),pp.z());
              v->setParameter(0,uu);
              gradObj[index] += deriv * factor;

              gp = (*it)->point(uu,vv+eps);
              v->setParameter(1,vv+eps);
              v->setXYZ(gp.x(),gp.y(),gp.z());
              deriv = (MFaceGFaceDistanceOld(t, *it, &gsfT, &normalsToCAD) - distT) /eps;
              v->setXYZ(pp.x(),pp.y(),pp.z());
              v->setParameter(1,vv);
              gradObj[index+1] += deriv * factor;
            }
          }
        }
      }
    }
  }
  mesh.updateGEntityPositions(xyz,uvw);
  Obj +=distCAD;
  //  printf("computing distance : 2D part %12.5E\n",distCAD);
  //  printf("%22.15E\n",distCAD);
  return true;
}
Ejemplo n.º 25
0
bool computeFourNeighbors (frameFieldBackgroundMesh2D *bgm,
                           MVertex *v_center, // the vertex for which we want to
                                              // generate 4 neighbors (real
                                              // vertex (xyz), not parametric!)
                           SPoint2 &midpoint,
                           bool goNonLinear, // do we compute the position in
                                             // the real surface which is
                                             // nonlinear
                           SPoint2 newP[4][NUMDIR], // look into other directions
                           SMetric3 &metricField) // the mesh metric
{
  // we assume that v is on surface gf, and backgroundMesh2D has been created based on gf

  // get BGM and GFace
  GFace *gf = dynamic_cast<GFace*>(bgm->getBackgroundGEntity());

  // get the parametric coordinates of the point on the surface
  reparamMeshVertexOnFace(v_center, gf, midpoint);

  // get RK info on midpoint (infos in two directions...)
  RK_form infos;
  bgm->compute_RK_infos(midpoint[0],midpoint[1],v_center->x(), v_center->y(),
                        v_center->z(), infos);
  metricField = infos.metricField;

  // shoot in four directions
  SPoint2 param_vec;
  double h;
  for (int i=0;i<4;i++){// in four directions
    switch (i){
    case 0:
      param_vec = infos.paramt1;
      h = infos.paramh.first;
      break;
    case 1:
      param_vec = infos.paramt2;
      h = infos.paramh.second;
      break;
    case 2:
      param_vec = infos.paramt1 * -1.;
      h = infos.paramh.first;
      break;
    case 3:
      param_vec = infos.paramt2 * -1.;
      h = infos.paramh.second;
      break;
    }
    shoot(midpoint,param_vec,h,newP[i][0]);
    //    cout << "(" << midpoint[0] << "," <<midpoint[1] << ") -> (" <<
    //    newP[i][0][0] << "," << newP[i][0][1] << ") " << endl;
  }

  // the following comes from surfaceFiller.cpp...
  const double EPS = 1.e-7;
  for (int j=0;j<2;j++){
    for (int i=0;i<4;i++){
      newP[i][0][j] += (EPS* (double)rand() / RAND_MAX);
    }
  }

  // We could stop here. Yet, if the metric varies a lot, we can solve a
  // nonlinear problem in order to find a better approximation in the real
  // surface
  if (1 && goNonLinear){
    double L = infos.localsize;
    double newPoint[4][2];
    for (int j=0;j<2;j++){
      for (int i=0;i<4;i++){
        newPoint[i][j] = newP[i][0][j];
      }
    }
    double ERR[4];
    for (int i=0;i<4;i++){                                              //
      //      if (newPoint[i][0] < rangeU.low())newPoint[i][0] = rangeU.low();
      //      if (newPoint[i][0] > rangeU.high())newPoint[i][0] = rangeU.high();
      //      if (newPoint[i][1] < rangeV.low())newPoint[i][1] = rangeV.low();
      //      if (newPoint[i][1] > rangeV.high())newPoint[i][1] = rangeV.high();
      GPoint pp = gf->point(newP[i][0]);
      double D = sqrt ((pp.x() - v_center->x())*(pp.x() - v_center->x()) +
                       (pp.y() - v_center->y())*(pp.y() - v_center->y()) +
                       (pp.z() - v_center->z())*(pp.z() - v_center->z()) );
      ERR[i] = 100*fabs(D-L)/(D+L);
      //      printf("L = %12.5E D = %12.5E ERR = %12.5E\n",L,D,100*fabs(D-L)/(D+L));
    }

    surfaceFunctorGFace ss (gf);
    SVector3 dirs[4] = {infos.t1*(-1.0),infos.t2*(-1.0),infos.t1*(1.0),infos.t2*(1.0)};
    for (int i=0;i<4;i++){
      if (ERR[i] > 12){
        double uvt[3] = {newPoint[i][0],newPoint[i][1],0.0};
        // printf("Intersecting with circle N = %g %g %g dir = %g %g %g R
        //	  = %g p = %g %g
        //	  %g\n",n.x(),n.y(),n.z(),dirs[i].x(),dirs[i].y(),dirs[i].z(),L,
        //        v_center->x(),v_center->y(),v_center->z());
        curveFunctorCircle cf (dirs[i],infos.normal,
                               SVector3(v_center->x(),v_center->y(),v_center->z()), L);
        if (intersectCurveSurface (cf,ss,uvt,infos.paramh.first*1.e-3)){
          GPoint pp = gf->point(SPoint2(uvt[0],uvt[1]));
          double D = sqrt ((pp.x() - v_center->x())*(pp.x() - v_center->x()) +
                           (pp.y() - v_center->y())*(pp.y() - v_center->y()) +
                           (pp.z() - v_center->z())*(pp.z() - v_center->z()) );
          double DP = sqrt ((newPoint[i][0]-uvt[0])*(newPoint[i][0]-uvt[0]) +
                            (newPoint[i][1]-uvt[1])*(newPoint[i][1]-uvt[1]));
          double newErr = 100*fabs(D-L)/(D+L);
          //	    if (v_center->onWhat() != gf && gf->tag() == 3){
          //	      crossField2d::normalizeAngle (uvt[2]);
          //	      printf("INTERSECT angle = %g DP %g\n",uvt[2],DP);
          //	    }
          if (newErr < 1 && DP < .1){
            //	      printf("%12.5E vs %12.5E : %12.5E %12.5E vs %12.5E %12.5E
            //	      \n",ERR[i],newErr,newPoint[i][0],newPoint[i][1],uvt[0],uvt[1]);
            newPoint[i][0] = uvt[0];
            newPoint[i][1] = uvt[1];
          }
          //	    printf("OK\n");
        }
        else{
          Msg::Debug("Cannot put a new point on Surface %d",gf->tag());
          // printf("NOT OK\n");
        }
      }
    }

    // return the four new vertices
    for (int i=0;i<4;i++){
      newP[i][0] = SPoint2(newPoint[i][0],newPoint[i][1]);
    }
  }

  return true;
}
Ejemplo n.º 26
0
void Filler2D::pointInsertion2D(GFace* gf,  vector<MVertex*> &packed,
                                vector<SMetric3> &metrics)
{
  // NB/ do not use the mesh in GFace, use the one in backgroundMesh2D!

  //  if(debug) cout << " ------------------   OLD -------------------" << endl;
  //  stringstream ssa;
  ////  ssa << "oldbgm_angles_" << gf->tag() << ".pos";
  ////  backgroundMesh::current()->print(ssa.str(),gf,1);
  //  ssa << "oldbgm_sizes_" << gf->tag() << ".pos";
  //  backgroundMesh::current()->print(ssa.str(),gf,0);
  //
  //
  //
  //
  //  if(debug) cout << " ------------------   NEW -------------------" << endl;
  //  backgroundMesh2D *bgm2 = dynamic_cast<backgroundMesh2D*>(BGMManager::get(gf));
  //  stringstream ss2;
  //  ss2 << "basebg_sizefield_" << gf->tag() << ".pos";
  //  bgm2->exportSizeField(ss2.str());
  //
  //
  //
  //  return;
  //

  BGMManager::set_use_cross_field(true);

  const bool goNonLinear = true;
  const bool debug=false;
  const bool export_stuff=true;

  if (debug) cout << "ENTERING POINTINSERTION2D" << endl;

  double a;

  // acquire background mesh
  if(debug) cout << "pointInsertion2D: recover BGM" << endl;
  a=Cpu();
  frameFieldBackgroundMesh2D *bgm =
    dynamic_cast<frameFieldBackgroundMesh2D*>(BGMManager::get(gf));
  time_bgm_and_smoothing += (Cpu() - a);

  if (!bgm){
    Msg::Error("BGM dynamic cast failed in filler2D::pointInsertion2D");
    return;
  }

  // export BGM size field
  if(export_stuff){
    cout << "pointInsertion2D: export size field " << endl;
    stringstream ss;
    ss << "bg2D_sizefield_" << gf->tag() << ".pos";
    bgm->exportSizeField(ss.str());

    cout << "pointInsertion2D : export crossfield " << endl;
    stringstream sscf;
    sscf << "bg2D_crossfield_" << gf->tag() << ".pos";
    bgm->exportCrossField(sscf.str());

    cout << "pointInsertion2D : export smoothness " << endl;
    stringstream sss;
    sss << "bg2D_smoothness_" << gf->tag() << ".pos";
    bgm->exportSmoothness(sss.str());
  }



  // point insertion algorithm:
  a=Cpu();

  // for debug check...
  int priority_counter=0;
  map<MVertex*,int> vert_priority;

  // get all the boundary vertices
  if(debug) cout << "pointInsertion2D : get bnd vertices " << endl;
  set<MVertex*> bnd_vertices = bgm->get_vertices_of_maximum_dim(1);

  // put boundary vertices in a fifo queue
  set<smoothness_point_pair, compareSurfacePointWithExclusionRegionPtr_Smoothness> fifo;
  vector<surfacePointWithExclusionRegion*> vertices;

  // initiate the rtree
  if(debug) cout << "pointInsertion2D : initiate RTree " << endl;
  RTree<surfacePointWithExclusionRegion*,double,2,double> rtree;
  SMetric3 metricField(1.0);
  SPoint2 newp[4][NUMDIR];
  set<MVertex*>::iterator it = bnd_vertices.begin() ;

  for (; it !=  bnd_vertices.end() ; ++it){
    SPoint2 midpoint;
    computeFourNeighbors(bgm,*it, midpoint, goNonLinear, newp, metricField);
    surfacePointWithExclusionRegion *sp = new surfacePointWithExclusionRegion
      (*it, newp, midpoint,metricField);

    smoothness_point_pair mp;
    mp.ptr = sp;
    mp.rank=(1.-bgm->get_smoothness(midpoint[0],midpoint[1]));
    fifo.insert(mp);

    vertices.push_back(sp);
    double _min[2],_max[2];
    sp->minmax(_min,_max);
    rtree.Insert(_min,_max,sp);
  }

  // ---------- main loop -----------------
  while(!fifo.empty()){
    if(debug) cout << " -------- fifo.size() = " << fifo.size() << endl;
    int count_nbaddedpt = 0;

    surfacePointWithExclusionRegion * parent = (*fifo.begin()).ptr;
    fifo.erase(fifo.begin());

    for (int dir=0;dir<NUMDIR;dir++){
      for (int i=0;i<4;i++){
        if (!inExclusionZone (parent->_p[i][dir], rtree, vertices) ){

          GPoint gp = gf->point(parent->_p[i][dir]);
          MFaceVertex *v = new MFaceVertex(gp.x(),gp.y(),gp.z(),gf,gp.u(),gp.v());
          SPoint2 midpoint;
          computeFourNeighbors(bgm,v, midpoint, goNonLinear, newp, metricField);
          surfacePointWithExclusionRegion *sp = new surfacePointWithExclusionRegion
            (v, newp, midpoint, metricField, parent);
          smoothness_point_pair mp;mp.ptr = sp;mp.rank=(1.-bgm->get_smoothness(gp.u(),gp.v()));

          if (debug) vert_priority[v] = priority_counter++;

          fifo.insert(mp);
          vertices.push_back(sp);
          double _min[2],_max[2];
          sp->minmax(_min,_max);
          rtree.Insert(_min,_max,sp);

          if (debug){
            cout << "  adding node (" << sp->_v->x() << "," << sp->_v->y()
                 << "," << sp->_v->z() << ")" << endl;
            cout << "    ----------------------------- sub --- fifo.size() = "
                 << fifo.size() << endl;
          }
          count_nbaddedpt++;
        }
      }
    }
    if(debug) cout << "////////// nbre of added point: " << count_nbaddedpt << endl;
  }
  time_insertion += (Cpu() - a);

  if (debug){
    stringstream ss;
    ss << "priority_" << gf->tag() << ".pos";
    print_nodal_info(ss.str().c_str(),vert_priority);
    ss.clear();
  }

  // add the vertices as additional vertices in the
  // surface mesh
  char ccc[256]; sprintf(ccc,"points%d.pos",gf->tag());
  FILE *f = Fopen(ccc,"w");
  if(f){
    fprintf(f,"View \"\"{\n");
    for (unsigned int i=0;i<vertices.size();i++){
      vertices[i]->print(f,i);
      if(vertices[i]->_v->onWhat() == gf) {
        packed.push_back(vertices[i]->_v);
        metrics.push_back(vertices[i]->_meshMetric);
        SPoint2 midpoint;
        reparamMeshVertexOnFace(vertices[i]->_v, gf, midpoint);
      }
      delete  vertices[i];
    }
    fprintf(f,"};");
    fclose(f);
  }
}
Ejemplo n.º 27
0
void highOrderTools::applySmoothingTo(std::vector<MElement*> &all, GFace *gf)
{
#ifdef HAVE_TAUCS
  linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>;
#else
  linearSystemPETSc<double> *lsys = new  linearSystemPETSc<double>;
#endif
  // compute the straight sided positions of high order nodes that are
  // on the edges of the face in the UV plane
  dofManager<double> myAssembler(lsys);
  elasticityTerm El(0, 1.0, CTX::instance()->mesh.hoPoissonRatio, _tag);
  std::vector<MElement*> layer, v;
  double minD;
  getDistordedElements(all, CTX::instance()->mesh.hoThresholdMin, v, minD);
  int numBad = v.size();
  const int nbLayers = CTX::instance()->mesh.hoNLayers;
  for (int i = 0; i < nbLayers; i++){
    addOneLayer(all, v, layer);
    v.insert(v.end(), layer.begin(), layer.end());
  }

  if (!v.size()) return;
  Msg::Info("Smoothing high order mesh : model face %d (%d elements considered in "
            "the elastic analogy, worst mapping %12.5E, %3d bad elements)", gf->tag(),
            v.size(),minD,numBad);

  addOneLayer(all, v, layer);
  std::set<MVertex*>::iterator it;
  std::set<MVertex*> verticesToMove;

  // on the last layer, fix displacement to 0
  for (unsigned int i = 0; i < layer.size(); i++){
    for (int j = 0; j < layer[i]->getNumVertices(); j++){
      MVertex *vert = layer[i]->getVertex(j);
      myAssembler.fixVertex(vert, 0, _tag, 0);
      myAssembler.fixVertex(vert, 1, _tag, 0);
    }
  }

  // fix all vertices that cannot move
  for (unsigned int i = 0; i < v.size(); i++){
    moveToStraightSidedLocation(v[i]);
    for (int j = 0; j < v[i]->getNumVertices(); j++){
      MVertex *vert = v[i]->getVertex(j);
      if (vert->onWhat()->dim() < 2){
	double du = 0, dv = 0;
        myAssembler.fixVertex(vert, 0, _tag, du);
        myAssembler.fixVertex(vert, 1, _tag, dv);
      }
    }
  }

  // number the other DOFs
  for (unsigned int i = 0; i < v.size(); i++){
    for (int j = 0; j < v[i]->getNumVertices(); j++){
      MVertex *vert = v[i]->getVertex(j);
      myAssembler.numberVertex(vert, 0, _tag);
      myAssembler.numberVertex(vert, 1, _tag);
      verticesToMove.insert(vert);
    }
  }

  double dx0 = smooth_metric_(v, gf, myAssembler, verticesToMove, El);
  double dx = dx0;
  Msg::Debug(" dx0 = %12.5E", dx0);
  int iter = 0;
  while(0){
    double dx2 = smooth_metric_(v, gf, myAssembler, verticesToMove, El);
    Msg::Debug(" dx2  = %12.5E", dx2);
    if (fabs(dx2 - dx) < 1.e-4 * dx0)break;
    if (iter++ > 2)break;
    dx = dx2;
  }

  for (it = verticesToMove.begin(); it != verticesToMove.end(); ++it){
    SPoint2 param;
    if ((*it)->onWhat()->dim() == 2){
      reparamMeshVertexOnFace(*it, gf, param);
      GPoint gp = gf->point(param);
      (*it)->x() = gp.x();
      (*it)->y() = gp.y();
      (*it)->z() = gp.z();
      _targetLocation[*it] = SVector3(gp.x(), gp.y(), gp.z());
    }
    else{
      SVector3 p =  getTL(*it);
      (*it)->x() = p.x();
      (*it)->y() = p.y();
      (*it)->z() = p.z();
    }
  }
  delete lsys;
}
Ejemplo n.º 28
0
void meshGEdge::operator() (GEdge *ge)
{
#if defined(HAVE_ANN)
  FieldManager *fields = ge->model()->getFields();
  BoundaryLayerField *blf = 0;
  Field *bl_field = fields->get(fields->getBoundaryLayerField());
  blf = dynamic_cast<BoundaryLayerField*> (bl_field);
#else
  bool blf = false;
#endif

  ge->model()->setCurrentMeshEntity(ge);

  if(ge->geomType() == GEntity::DiscreteCurve) return;
  if(ge->geomType() == GEntity::BoundaryLayerCurve) return;
  if(ge->meshAttributes.method == MESH_NONE) return;
  if(CTX::instance()->mesh.meshOnlyVisible && !ge->getVisibility()) return;

  // look if we are doing the STL triangulation
  std::vector<MVertex*> &mesh_vertices = ge->mesh_vertices ;
  std::vector<MLine*> &lines = ge->lines ;

  deMeshGEdge dem;
  dem(ge);

  if(MeshExtrudedCurve(ge)) return;

  if (ge->meshMaster() != ge){
    GEdge *gef = dynamic_cast<GEdge*> (ge->meshMaster());
    if (gef->meshStatistics.status == GEdge::PENDING) return;
    Msg::Info("Meshing curve %d (%s) as a copy of %d", ge->tag(),
              ge->getTypeString().c_str(), ge->meshMaster()->tag());
    copyMesh(gef, ge, ge->masterOrientation);
    ge->meshStatistics.status = GEdge::DONE;
    return;
  }

  Msg::Info("Meshing curve %d (%s)", ge->tag(), ge->getTypeString().c_str());

  // compute bounds
  Range<double> bounds = ge->parBounds(0);
  double t_begin = bounds.low();
  double t_end = bounds.high();

  // first compute the length of the curve by integrating one
  double length;
  std::vector<IntPoint> Points;
  if(ge->geomType() == GEntity::Line &&
      ge->getBeginVertex() == ge->getEndVertex() &&
      //do not consider closed lines as degenerated
      (ge->position(0.5) - ge->getBeginVertex()->xyz()).norm() < CTX::instance()->geom.tolerance)
    length = 0.; // special case t avoid infinite loop in integration
  else
    length = Integration(ge, t_begin, t_end, F_One, Points, 1.e-8 * CTX::instance()->lc);
  ge->setLength(length);
  Points.clear();

  if(length < CTX::instance()->mesh.toleranceEdgeLength){
    ge->setTooSmall(true);
  }

  // Integrate detJ/lc du
  double a;
  int N;
  if(length == 0. && CTX::instance()->mesh.toleranceEdgeLength == 0.){
    Msg::Warning("Curve %d has a zero length", ge->tag());
    a = 0.;
    N = 1;
  }
  else if(ge->degenerate(0)){
    a = 0.;
    N = 1;
  }
  else if(ge->meshAttributes.method == MESH_TRANSFINITE){
    a = Integration(ge, t_begin, t_end, F_Transfinite, Points,
                    CTX::instance()->mesh.lcIntegrationPrecision);
    N = ge->meshAttributes.nbPointsTransfinite;
    if(CTX::instance()->mesh.flexibleTransfinite && CTX::instance()->mesh.lcFactor)
      N /= CTX::instance()->mesh.lcFactor;
  }
  else{
    if (CTX::instance()->mesh.algo2d == ALGO_2D_BAMG || blf){
      a = Integration(ge, t_begin, t_end, F_Lc_aniso, Points,
                      CTX::instance()->mesh.lcIntegrationPrecision);
    }
    else{
       a = Integration(ge, t_begin, t_end, F_Lc, Points,
                      CTX::instance()->mesh.lcIntegrationPrecision);
    }

    // we should maybe provide an option to disable the smoothing
    for (unsigned int i = 0; i < Points.size(); i++){
      IntPoint &pt = Points[i];
      SVector3 der = ge->firstDer(pt.t);
      pt.xp = der.norm();
    }
    a = smoothPrimitive(ge, sqrt(CTX::instance()->mesh.smoothRatio), Points);
    N = std::max(ge->minimumMeshSegments() + 1, (int)(a + 1.99));
  }

  // force odd number of points if blossom is used for recombination
  if((ge->meshAttributes.method != MESH_TRANSFINITE ||
      CTX::instance()->mesh.flexibleTransfinite) &&
     CTX::instance()->mesh.algoRecombine != 0){
    if(CTX::instance()->mesh.recombineAll){
      if (N % 2 == 0) N++;
      if (CTX::instance()->mesh.algoRecombine == 2)
	N = increaseN(N);
    }
    else{
      std::list<GFace*> faces = ge->faces();
      for(std::list<GFace*>::iterator it = faces.begin(); it != faces.end(); it++){
        if((*it)->meshAttributes.recombine){
	  if (N % 2 == 0) N ++;
	  if (CTX::instance()->mesh.algoRecombine == 2)
	    N = increaseN(N);
          break;
        }
      }
    }
  }

  // printFandPrimitive(ge->tag(),Points);

  // if the curve is periodic and if the begin vertex is identical to
  // the end vertex and if this vertex has only one model curve
  // adjacent to it, then the vertex is not connecting any other
  // curve. So, the mesh vertex and its associated geom vertex are not
  // necessary at the same location
  GPoint beg_p, end_p;
  if(ge->getBeginVertex() == ge->getEndVertex() &&
     ge->getBeginVertex()->edges().size() == 1){
    end_p = beg_p = ge->point(t_begin);
    Msg::Debug("Meshing periodic closed curve");
  }
  else{
    MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0];
    MVertex *v1 = ge->getEndVertex()->mesh_vertices[0];
    beg_p = GPoint(v0->x(), v0->y(), v0->z());
    end_p = GPoint(v1->x(), v1->y(), v1->z());
  }

  // do not consider the first and the last vertex (those are not
  // classified on this mesh edge)
  if(N > 1){
    const double b = a / (double)(N - 1);
    int count = 1, NUMP = 1;
    IntPoint P1, P2;
    mesh_vertices.resize(N - 2);
    while(NUMP < N - 1) {
      P1 = Points[count - 1];
      P2 = Points[count];
      const double d = (double)NUMP * b;
      if((fabs(P2.p) >= fabs(d)) && (fabs(P1.p) < fabs(d))) {
        double dt = P2.t - P1.t;
        double dlc = P2.lc - P1.lc;
        double dp = P2.p - P1.p;
        double t   = P1.t + dt / dp * (d - P1.p);
        SVector3 der = ge->firstDer(t);
        const double d = norm(der);
        double lc  = d/(P1.lc + dlc / dp * (d - P1.p));
        GPoint V = ge->point(t);
        mesh_vertices[NUMP - 1] = new MEdgeVertex(V.x(), V.y(), V.z(), ge, t, lc);
        NUMP++;
      }
      else {
        count++;
      }
    }
    mesh_vertices.resize(NUMP - 1);
  }

  for(unsigned int i = 0; i < mesh_vertices.size() + 1; i++){
    MVertex *v0 = (i == 0) ?
      ge->getBeginVertex()->mesh_vertices[0] : mesh_vertices[i - 1];
    MVertex *v1 = (i == mesh_vertices.size()) ?
      ge->getEndVertex()->mesh_vertices[0] : mesh_vertices[i];
    lines.push_back(new MLine(v0, v1));
  }

  if(ge->getBeginVertex() == ge->getEndVertex() &&
     ge->getBeginVertex()->edges().size() == 1){
    MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0];
    v0->x() = beg_p.x();
    v0->y() = beg_p.y();
    v0->z() = beg_p.z();
  }

  ge->meshStatistics.status = GEdge::DONE;
}
Ejemplo n.º 29
0
PView *GMSH_CVTRemeshPlugin::execute(PView *v)
{
  //TODO normalization

  GModel* m = GModel::current() ;

  std::vector<double> vertices ;
  std::vector<unsigned int> faces ;

  unsigned int offset = 0 ;
  for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it) {
    (*it)->buildSTLTriangulation() ;
    for(unsigned int i = 0; i < (*it)->stl_vertices.size(); ++i) {
      GPoint p = (*it)->point((*it)->stl_vertices[i]) ;
      vertices.push_back(p.x()) ;
      vertices.push_back(p.y()) ;
      vertices.push_back(p.z()) ;
    }
    for(unsigned int i = 0; i < (*it)->stl_triangles.size(); ++i) {
      faces.push_back((*it)->stl_triangles[i]+offset) ;
    }
    offset += (*it)->stl_vertices.size() ;
  }

  Revoropt::MeshBuilder<3> mesh ;
  mesh.swap_vertices(vertices) ;
  mesh.swap_faces(faces) ;

  double mesh_center[3] ;
  double mesh_scale ;
  Revoropt::normalize_mesh(&mesh, mesh_center, &mesh_scale) ;

  double nradius = (double)CVTRemeshOptions_Number[5].def ;

  //normals
  std::vector<double> normals(3*mesh.vertices_size()) ;
  Revoropt::full_robust_vertex_normals(&mesh,nradius,normals.data()) ;

  //lifted vertices
  std::vector<double> lifted_vertices(6*mesh.vertices_size(), 0) ;
  for(unsigned int vertex = 0; vertex < mesh.vertices_size(); ++vertex) {
    std::copy( mesh.vertex(vertex),
               mesh.vertex(vertex)+3,
               lifted_vertices.data()+6*vertex
             ) ;
    std::copy( normals.data()+3*vertex,
               normals.data()+3*vertex+3,
               lifted_vertices.data()+6*vertex+3
             ) ;
  }

  //setup lifted mesh
  Revoropt::ROMeshWrapper<3,6> lifted_mesh(
    lifted_vertices.data(),
    lifted_vertices.size()/6,
    &mesh
  ) ;

  //triangle weight factor
  double twfactor = (double)CVTRemeshOptions_Number[3].def ;

  //face ratios
  std::vector<double> triangle_weights(lifted_mesh.faces_size()) ;
  if(twfactor > 0) {
    for(unsigned int f = 0; f < lifted_mesh.faces_size(); ++f) {
      //vertices of the initial triangle
      const unsigned int* fverts = mesh.face(f) ;

      //positions
      const double* x[3] ;
      for(int i=0; i<3; ++i) {
        x[i] = lifted_mesh.vertex(fverts[i]) ;
      }

      //ratio
      double ratio = 1 ;

      //vectors
      typedef Eigen::Matrix<double,3,1> Vector3 ;

      Eigen::Map<const Vector3> v0(x[0]) ;
      Eigen::Map<const Vector3> v1(x[1]) ;
      Eigen::Map<const Vector3> v2(x[2]) ;

      //triangle frame
      Vector3 U = (v1-v0) ;
      const double U_len = U.norm() ;
      if(U_len > 0) {
        U /= U_len ;
        Vector3 H = (v2-v0) ;
        H = H - H.dot(U)*U ;
        const double H_len = H.norm() ;
        if(H_len > 0) {
          //we know that the triangle is not flat
          H /= H_len ;

          //gradient of the barycentric weights in the triangle
          Eigen::Matrix<double,3,2> bar_grads ;
          bar_grads(2,0) = 0 ;
          bar_grads(2,1) = 1/H_len ;

          //gradient norms of every normal component
          for(int i = 0; i < 2; ++i) {
            //reference frame for the vertex
            Eigen::Map<const Vector3> vi0(x[(i+1)%3]) ;
            Eigen::Map<const Vector3> vi1(x[(i+2)%3]) ;
            Eigen::Map<const Vector3> vi2(x[ i     ]) ;

            Vector3 Ui = (vi1-vi0) ;
            Ui /= Ui.norm() ;
            Vector3 Hi = (vi2-vi0) ;
            Hi = Hi - Hi.dot(Ui)*Ui ;
            const double Hi_invlen = 1/Hi.norm() ;
            Hi *= Hi_invlen ;
            bar_grads(i,0) = Hi.dot(U)*Hi_invlen ;
            bar_grads(i,1) = Hi.dot(H)*Hi_invlen ;
          }

          //gradient of each component of the normal
          Eigen::Map<const Vector3> n0(x[0]+3) ;
          Eigen::Map<const Vector3> n1(x[1]+3) ;
          Eigen::Map<const Vector3> n2(x[2]+3) ;

          Eigen::Matrix<double,3,2> n_grads = Eigen::Matrix<double,3,2>::Zero() ;

          n_grads = n0*bar_grads.row(0) ;
          n_grads += n1*bar_grads.row(1) ;
          n_grads += n2*bar_grads.row(2) ;

          //maximal gradient norm
          double g_max = n_grads.row(0).dot(n_grads.row(0)) ;
          double g_other = n_grads.row(1).dot(n_grads.row(1)) ;
          g_max = g_max > g_other ? g_max : g_other ;
          g_other = n_grads.row(2).dot(n_grads.row(2)) ;
          g_max = g_max > g_other ? g_max : g_other ;

          if(g_max == g_max) { //prevent nan
            ratio += g_max ;
          }
        }
      }
      triangle_weights[f] = pow(ratio,twfactor) ;
    }
  }

  //normal factor
  double nfactor = (double)CVTRemeshOptions_Number[2].def ; ;

  //weight the normal component by the provided factor
  for(unsigned int i = 0; i<lifted_mesh.vertices_size(); ++i) {
    double* v = lifted_vertices.data() + 6*i ;
    v[3]*= nfactor ;
    v[4]*= nfactor ;
    v[5]*= nfactor ;
  }

  //number of sites
  unsigned int nsites = (unsigned int)CVTRemeshOptions_Number[0].def ;

  //lifted sites
  std::vector<double> lifted_sites(6*nsites) ;
  if(twfactor > 0) {
    Revoropt::generate_random_sites< Revoropt::ROMesh<3,6> >(
      &lifted_mesh, nsites, lifted_sites.data(), triangle_weights.data()
    ) ;
  } else {
    Revoropt::generate_random_sites< Revoropt::ROMesh<3,6> >(
      &lifted_mesh, nsites, lifted_sites.data()
    ) ;
  }

  //setup the cvt minimizer
  Revoropt::CVT::DirectMinimizer< Revoropt::ROMesh<3,6> > cvt ;
  cvt.set_sites(lifted_sites.data(), nsites) ;
  cvt.set_mesh(&lifted_mesh) ;
  if(twfactor > 0) {
    cvt.set_triangle_weights(triangle_weights.data()) ;
  }

  //setup the callback
  SolverCallback callback ;

  //number of iterations
  unsigned int niter = (unsigned int)CVTRemeshOptions_Number[1].def ; ;
  unsigned int aniso_niter = std::min<unsigned int>(10,niter) ;

  //solver status
  int status = 0 ;

  //isotropic iterations
  if(niter > 10) {
    aniso_niter = std::max(aniso_niter,niter*10/100) ;
    cvt.set_anisotropy(1) ;
    status = cvt.minimize<Revoropt::Solver::AlgLBFGS>(niter-aniso_niter, &callback) ;
  }

  //anisotropic iterations
  if(niter > 0) {
    //tangent space anisotropy
    double tanisotropy = (double)CVTRemeshOptions_Number[4].def ; ;

    //anisotropic iterations
    cvt.set_anisotropy(tanisotropy) ;
    status = cvt.minimize<Revoropt::Solver::AlgLBFGS>(aniso_niter, &callback) ;
  }

  //rdt
  std::vector<unsigned int> rdt_triangles ;
  Revoropt::RDTBuilder< Revoropt::ROMesh<3,6> > build_rdt(rdt_triangles) ;
  Revoropt::RVD< Revoropt::ROMesh<3,6> > rvd ;
  rvd.set_sites(lifted_sites.data(), nsites) ;
  rvd.set_mesh(&lifted_mesh) ;
  rvd.compute(build_rdt) ;

  GFace* res_face = new discreteFace(m, m->getMaxElementaryNumber(2)+1) ;
  m->add(res_face) ;

  //scale back and transfer to gmsh
  std::vector<MVertex*> m_verts(nsites) ;
  for(unsigned int i = 0; i < nsites; ++i) {
    m_verts[i] = new MVertex(
        lifted_sites[6*i  ]*mesh_scale + mesh_center[0],
        lifted_sites[6*i+1]*mesh_scale + mesh_center[1],
        lifted_sites[6*i+2]*mesh_scale + mesh_center[2]
        ) ;
    res_face->addMeshVertex(m_verts[i]) ;
  }
  for(unsigned int i = 0; i < rdt_triangles.size()/3; ++i) {
    res_face->addTriangle(
      new MTriangle(
        m_verts[rdt_triangles[3*i  ]],
        m_verts[rdt_triangles[3*i+1]],
        m_verts[rdt_triangles[3*i+2]]
        )
    ) ;
  }

  res_face->setAllElementsVisible(true) ;

  return v ;
}
Ejemplo n.º 30
0
void Mesh::approximationErrorAndGradients(int iEl, double &f, std::vector<double> &gradF, double eps,
					  simpleFunction<double> &fct)
{
  std::vector<SPoint3> _xyz_temp;
  for (int iV = 0; iV < nVert(); iV++){
    _xyz_temp.push_back(SPoint3( _vert[iV]->x(), _vert[iV]->y(), _vert[iV]->z()));
    _vert[iV]->setXYZ(_xyz[iV].x(),_xyz[iV].y(),_xyz[iV].z());
  }

  MElement *element = _el[iEl];

  f = approximationError (fct, element);
  // FIME
  //  if (iEl < 1)printf("approx error elem %d = %g\n",iEl,f);
  int currentId = 0;
  // compute the size of the gradient
  // depends on how many dofs exist per vertex (0,1,2 or 3)
  for (size_t i = 0; i < element->getNumVertices(); ++i) {
    if (_el2FV[iEl][i] >= 0) {// some free coordinates
      currentId += _nPCFV[_el2FV[iEl][i]];
    }
  }
  gradF.clear();
  gradF.resize(currentId, 0.);
  currentId = 0;
  for (size_t i = 0; i < element->getNumVertices(); ++i) {
    if (_el2FV[iEl][i] >= 0) {// some free coordinates
      MVertex *v =  element->getVertex(i);
      // vertex classified on a model edge
      if (_nPCFV[_el2FV[iEl][i]] == 1){
	double t = _uvw[_el2FV[iEl][i]].x();
	GEdge *ge = (GEdge*)v->onWhat();
	SPoint3 p (v->x(),v->y(),v->z());
	GPoint d = ge->point(t+eps);
	v->setXYZ(d.x(),d.y(),d.z());
	double f_d = approximationError (fct, element);
	gradF[currentId++] = (f_d-f)/eps;
	if (iEl < 1)printf("df = %g\n",(f_d-f)/eps);
	v->setXYZ(p.x(),p.y(),p.z());
      }
      else if (_nPCFV[_el2FV[iEl][i]] == 2){
	double uu = _uvw[_el2FV[iEl][i]].x();
	double vv = _uvw[_el2FV[iEl][i]].y();
	GFace *gf = (GFace*)v->onWhat();
	SPoint3 p (v->x(),v->y(),v->z());
	GPoint  d = gf->point(uu+eps,vv);
	v->setXYZ(d.x(),d.y(),d.z());
	double f_u = approximationError (fct, element);
	gradF[currentId++] = (f_u-f)/eps;
	d = gf->point(uu,vv+eps);
	v->setXYZ(d.x(),d.y(),d.z());
	double f_v = approximationError (fct, element);
	gradF[currentId++] = (f_v-f)/eps;
	v->setXYZ(p.x(),p.y(),p.z());
	//	if (iEl < 1)printf("df = %g %g\n",(f_u-f)/eps,(f_v-f)/eps);
      }
    }
  }
  for (int iV = 0; iV < nVert(); iV++)
    _vert[iV]->setXYZ(_xyz_temp[iV].x(),_xyz_temp[iV].y(),_xyz_temp[iV].z());

}