void BGMBase::export_tensor_as_vectors( const std::string &filename, const TensorStorageType &_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"); TensorStorageType::const_iterator it = _whatToPrint.begin(); const char *s = "VP"; for(; it != _whatToPrint.end(); it++) { // for all vertices GPoint p = get_GPoint_from_MVertex(it->first); for(int i = 0; i < 3; i++) { fprintf(f, "%s(%g,%g,%g){%g,%g,%g};\n", s, p.x(), p.y(), p.z(), (it->second)(0, i), (it->second)(1, i), (it->second)(2, i)); fprintf(f, "%s(%g,%g,%g){%g,%g,%g};\n", s, p.x(), p.y(), p.z(), -(it->second)(0, i), -(it->second)(1, i), -(it->second)(2, i)); } } fprintf(f, "};\n"); fclose(f); }
inline double computeEdgeLinearLength(BDS_Point *p1, BDS_Point *p2, GFace *f, double SCALINGU, double SCALINGV) { // FIXME SUPER HACK // if (CTX::instance()->mesh.recombineAll || f->meshAttributes.recombine || 1){ // double quadAngle = backgroundMesh::current()->getAngle (0.5 * (p1->u + p2->u) * SCALINGU, 0.5 * (p1->v + p2->v) * SCALINGV,0); // const double a [2] = {p1->u,p1->v}; // const double b [2] = {p2->u,p2->v}; // return lengthInfniteNorm(a,b, quadAngle); // } GPoint GP = f->point(SPoint2(0.5 * (p1->u + p2->u) * SCALINGU, 0.5 * (p1->v + p2->v) * SCALINGV)); if (!GP.succeeded()) return computeEdgeLinearLength(p1,p2); 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); return l1 + l2; }
SOrientedBoundingBox GRegion::getOBB() { if (!_obb) { std::vector<SPoint3> vertices; std::list<GFace*> b_faces = faces(); for (std::list<GFace*>::iterator b_face = b_faces.begin(); b_face != b_faces.end(); b_face++) { if((*b_face)->getNumMeshVertices() > 0) { int N = (*b_face)->getNumMeshVertices(); for (int i = 0; i < N; i++) { MVertex* mv = (*b_face)->getMeshVertex(i); vertices.push_back(mv->point()); } std::list<GEdge*> eds = (*b_face)->edges(); for(std::list<GEdge*>::iterator ed = eds.begin(); ed != eds.end(); ed++) { int N2 = (*ed)->getNumMeshVertices(); for (int i = 0; i < N2; i++) { MVertex* mv = (*ed)->getMeshVertex(i); vertices.push_back(mv->point()); } // Don't forget to add the first and last vertices... SPoint3 pt1((*ed)->getBeginVertex()->x(), (*ed)->getBeginVertex()->y(), (*ed)->getBeginVertex()->z()); SPoint3 pt2((*ed)->getEndVertex()->x(), (*ed)->getEndVertex()->y(), (*ed)->getEndVertex()->z()); vertices.push_back(pt1); vertices.push_back(pt2); } } else if ((*b_face)->buildSTLTriangulation()) { for (unsigned int i = 0; i < (*b_face)->stl_vertices.size(); i++){ GPoint p = (*b_face)->point((*b_face)->stl_vertices[i]); vertices.push_back(SPoint3(p.x(), p.y(), p.z())); } } else { int N = 10; std::list<GEdge*> b_edges = (*b_face)->edges(); for (std::list<GEdge*>::iterator b_edge = b_edges.begin(); b_edge != b_edges.end(); b_edge++) { Range<double> tr = (*b_edge)->parBounds(0); for (int j = 0; j < N; j++) { double t = tr.low() + (double)j / (double)(N - 1) * (tr.high() - tr.low()); GPoint p = (*b_edge)->point(t); SPoint3 pt(p.x(), p.y(), p.z()); vertices.push_back(pt); } } } } _obb = SOrientedBoundingBox::buildOBB(vertices); } return SOrientedBoundingBox(_obb); }
void gmshVertex::setPosition(GPoint &p) { v->Pos.X = p.x(); v->Pos.Y = p.y(); v->Pos.Z = p.z(); if(mesh_vertices.size()){ mesh_vertices[0]->x() = p.x(); mesh_vertices[0]->y() = p.y(); mesh_vertices[0]->z() = p.z(); } }
void GenericVertex::setPosition(GPoint &p) { _x = p.x(); _y = p.y(); _z = p.z(); if(mesh_vertices.size()){ mesh_vertices[0]->x() = p.x(); mesh_vertices[0]->y() = p.y(); mesh_vertices[0]->z() = p.z(); } }
SPoint2 OCCEdge::reparamOnFace(const GFace *face, double epar, int dir) const { if (face->getNativeType() != GEntity::OpenCascadeModel){ const GPoint pt = point(epar); SPoint3 sp(pt.x(), pt.y(), pt.z()); return face->parFromPoint(sp); } else{ const TopoDS_Face *s = (TopoDS_Face*) face->getNativePtr(); double t0, t1; Handle(Geom2d_Curve) c2d; if(dir == 1){ c2d = BRep_Tool::CurveOnSurface(c, *s, t0, t1); } else{ c2d = BRep_Tool::CurveOnSurface(c_rev, *s, t0, t1); } if(c2d.IsNull()){ Msg::Error("Reparam on face failed: curve %d is not on surface %d", tag(), face->tag()); const GPoint pt = point(epar); SPoint3 sp(pt.x(), pt.y(), pt.z()); return face->parFromPoint(sp); } double u, v; gp_Pnt2d pnt = c2d->Value(epar); pnt.Coord(u, v); // sometimes OCC miserably fails ... if (0){ GPoint p1 = point(epar); GPoint p2 = face->point(u, v); const double dx = p1.x()-p2.x(); const double dy = p1.y()-p2.y(); const double dz = p1.z()-p2.z(); if(sqrt(dx * dx + dy * dy + dz * dz) > 1.e-2 * CTX::instance()->lc){ Msg::Warning("Reparam on face was inaccurate for curve %d on surface %d at point %g", tag(), face->tag(), epar); Msg::Warning("On the face %d local (%g %g) global (%g %g %g)", face->tag(), u, v, p2.x(), p2.y(), p2.z()); Msg::Warning("On the edge %d local (%g) global (%g %g %g)", tag(), epar, p1.x(), p1.y(), p1.z()); } } return SPoint2(u, v); } }
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); }
// use real space + projection at the end static double _relocateVertex2(GFace *gf, MVertex *ver, const std::vector<MElement *> <, 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; }
static double objective_function(double const xi, MVertex *const ver, GFace *const gf, SPoint3 &p1, SPoint3 &p2, const std::vector<MElement *> <) { 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; }
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); }
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)); } }
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); }
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); }
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); }
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(); }
SVector3 gmshFace::normal(const SPoint2 ¶m) 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]); } } }
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; }
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; }
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++; } } } }
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(); } } }
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())); } }
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); }
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; }
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; }
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()); }
static double _relocateVertex(GFace *gf, MVertex *ver, const std::vector<MElement *> <, 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; }
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()); } }
static double objective_function(double xi, MVertex *ver, GFace *gf, SPoint2 &p1, SPoint2 &p2, const std::vector<MElement *> <) { 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; }
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 ; }
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; }