// 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; }
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); }
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; }
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); }
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 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); }
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; }
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(); }
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; }
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(); }
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; }
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; }
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); } }
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; }
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; }
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 ; }
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()); }