static double LC_MVertex_CURV(GEntity *ge, double U, double V) { double Crv = 0; switch(ge->dim()){ case 0: Crv = max_edge_curvature((const GVertex *)ge); //Crv = std::max(max_surf_curvature_vertex((const GVertex *)ge), Crv); // Crv = max_surf_curvature((const GVertex *)ge); break; case 1: { GEdge *ged = (GEdge *)ge; Crv = ged->curvature(U); Crv = std::max(Crv, max_surf_curvature(ged, U)); // Crv = max_surf_curvature(ged, U); } break; case 2: { GFace *gf = (GFace *)ge; Crv = gf->curvature(SPoint2(U, V)); } break; } double lc = Crv > 0 ? 2 * M_PI / Crv / CTX::instance()->mesh.minCircPoints : MAX_LC; return lc; }
SMetric3 metric_based_on_surface_curvature(const GFace *gf, double u, double v, bool surface_isotropic, double d_normal , double d_tangent_max) { if (gf->geomType() == GEntity::Plane)return SMetric3(1.e-12); double cmax, cmin; SVector3 dirMax,dirMin; cmax = gf->curvatures(SPoint2(u, v),&dirMax, &dirMin, &cmax,&cmin); if (cmin == 0)cmin =1.e-12; if (cmax == 0)cmax =1.e-12; double lambda1 = ((2 * M_PI) /( fabs(cmin) * CTX::instance()->mesh.minCircPoints ) ); double lambda2 = ((2 * M_PI) /( fabs(cmax) * CTX::instance()->mesh.minCircPoints ) ); SVector3 Z = crossprod(dirMax,dirMin); if (surface_isotropic) lambda2 = lambda1 = std::min(lambda2,lambda1); dirMin.normalize(); dirMax.normalize(); Z.normalize(); lambda1 = std::max(lambda1, CTX::instance()->mesh.lcMin); lambda2 = std::max(lambda2, CTX::instance()->mesh.lcMin); lambda1 = std::min(lambda1, CTX::instance()->mesh.lcMax); lambda2 = std::min(lambda2, CTX::instance()->mesh.lcMax); double lambda3 = std::min(d_normal, CTX::instance()->mesh.lcMax); lambda3 = std::max(lambda3, CTX::instance()->mesh.lcMin); lambda1 = std::min(lambda1, d_tangent_max); lambda2 = std::min(lambda2, d_tangent_max); SMetric3 curvMetric (1./(lambda1*lambda1),1./(lambda2*lambda2), 1./(lambda3*lambda3), dirMin, dirMax, Z ); return curvMetric; }
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; }
// returns the cross field as a pair of othogonal vectors (NOT in parametric coordinates, but real 3D coordinates) Pair<SVector3, SVector3> frameFieldBackgroundMesh2D::compute_crossfield_directions(double u, double v, double angle_current) { // get the unit normal at that point GFace *face = dynamic_cast<GFace*>(gf); if(!face) { Msg::Error("Entity is not a face in background mesh"); return Pair<SVector3,SVector3>(SVector3(), SVector3()); } Pair<SVector3, SVector3> der = face->firstDer(SPoint2(u,v)); SVector3 s1 = der.first(); SVector3 s2 = der.second(); SVector3 n = crossprod(s1,s2); n.normalize(); SVector3 basis_u = s1; basis_u.normalize(); SVector3 basis_v = crossprod(n,basis_u); // normalize vector t1 that is tangent to gf at uv SVector3 t1 = basis_u * cos(angle_current) + basis_v * sin(angle_current) ; t1.normalize(); // compute the second direction t2 and normalize (t1,t2,n) is the tangent frame SVector3 t2 = crossprod(n,t1); t2.normalize(); return Pair<SVector3,SVector3>(SVector3(t1[0],t1[1],t1[2]), SVector3(t2[0],t2[1],t2[2])); }
SPoint2 fourierFace::parFromPoint(const SPoint3 &p, bool onSurface) const { double u, v, x, y, z; x = p.x(); y = p.y(); z = p.z(); face->Inverse(x,y,z,u,v); return SPoint2(u, v); }
GPoint backgroundMesh2D::get_GPoint_from_MVertex(const MVertex *v)const { GFace *face = dynamic_cast<GFace*>(gf); if(!face) { Msg::Error("Entity is not a face in background mesh"); return GPoint(); } return face->point(SPoint2(v->x(),v->y())); }
bool reparamMeshVertexOnFace(MVertex *v, const GFace *gf, SPoint2 ¶m, bool onSurface) { if (gf->geomType() == GEntity::CompoundSurface ){ GFaceCompound *gfc = (GFaceCompound*) gf; param = gfc->parFromVertex(v); return true; } if(v->onWhat()->geomType() == GEntity::DiscreteCurve || v->onWhat()->geomType() == GEntity::BoundaryLayerCurve){ param = gf->parFromPoint(SPoint3(v->x(), v->y(), v->z()), onSurface); return true; } if(v->onWhat()->dim() == 0){ GVertex *gv = (GVertex*)v->onWhat(); // hack for bug in periodic curves if (gv->getNativeType() == GEntity::GmshModel && gf->geomType() == GEntity::Plane) param = gf->parFromPoint(SPoint3(v->x(), v->y(), v->z()), onSurface); else param = gv->reparamOnFace(gf, 1); // shout, we could be on a seam std::list<GEdge*> ed = gv->edges(); for(std::list<GEdge*>::iterator it = ed.begin(); it != ed.end(); it++) if((*it)->isSeam(gf)) return false; } else if(v->onWhat()->dim() == 1){ GEdge *ge = (GEdge*)v->onWhat(); double t; v->getParameter(0, t); param = ge->reparamOnFace(gf, t, 1); if(!v->getParameter(0,t)) { Msg::Error("Vertex %p not MEdgeVertex", v); return false; //param = gf->parFromPoint(SPoint3(v->x(), v->y(), v->z()), onSurface); } // shout, we are on a seam if(ge->isSeam(gf)) return false; } else{ double uu, vv; if(v->onWhat() == gf && v->getParameter(0, uu) && v->getParameter(1, vv)){ param = SPoint2(uu, vv); } else { // brute force! param = gf->parFromPoint(SPoint3(v->x(), v->y(), v->z()), onSurface); } } return true; }
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); } }
static void getAllParameters(MVertex *v, GFace *gf, std::vector<SPoint2> ¶ms) { params.clear(); if (gf->geomType() == GEntity::CompoundSurface ){ GFaceCompound *gfc = (GFaceCompound*) gf; params.push_back(gfc->parFromVertex(v)); return; } if(v->onWhat()->dim() == 0){ GVertex *gv = (GVertex*)v->onWhat(); std::list<GEdge*> ed = gv->edges(); bool seam = false; for(std::list<GEdge*>::iterator it = ed.begin(); it != ed.end(); it++){ if((*it)->isSeam(gf)) { Range<double> range = (*it)->parBounds(0); if (gv == (*it)->getBeginVertex()){ params.push_back((*it)->reparamOnFace(gf, range.low(),-1)); params.push_back((*it)->reparamOnFace(gf, range.low(), 1)); } if (gv == (*it)->getEndVertex()){ params.push_back((*it)->reparamOnFace(gf, range.high(),-1)); params.push_back((*it)->reparamOnFace(gf, range.high(), 1)); } if (gv != (*it)->getBeginVertex() && gv != (*it)->getEndVertex()){ Msg::Warning("Strange!"); } seam = true; } } if (!seam) params.push_back(gv->reparamOnFace(gf, 1)); } else if(v->onWhat()->dim() == 1){ GEdge *ge = (GEdge*)v->onWhat(); if(!ge->haveParametrization()) return; double UU; v->getParameter(0, UU); if (UU == 0.0) UU = ge->parFromPoint(v->point()); params.push_back(ge->reparamOnFace(gf, UU, 1)); if(ge->isSeam(gf)) params.push_back(ge->reparamOnFace(gf, UU, -1)); } else{ double UU, VV; if(v->onWhat() == gf && v->getParameter(0, UU) && v->getParameter(1, VV)) params.push_back(SPoint2(UU, VV)); } }
SPoint2 gmshFace::parFromPoint(const SPoint3 &qp, bool onSurface) const { if(s->Typ == MSH_SURF_PLAN){ double x, y, z, VX[3], VY[3]; getMeanPlaneData(VX, VY, x, y, z); double u, v, vec[3] = {qp.x() - x, qp.y() - y, qp.z() - z}; prosca(vec, VX, &u); prosca(vec, VY, &v); return SPoint2(u, v); } else{ return GFace::parFromPoint(qp, onSurface); } }
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; }
void Mesh::calcScaledNormalEl2D(const std::map<MElement*,GEntity*> &element2entity, int iEl) { const JacobianBasis *jac = _el[iEl]->getJacobianFuncSpace(); fullMatrix<double> primNodesXYZ(jac->getNumPrimMapNodes(),3); SVector3 geoNorm(0.,0.,0.); std::map<MElement*,GEntity*>::const_iterator itEl2ent = element2entity.find(_el[iEl]); GEntity *ge = (itEl2ent == element2entity.end()) ? 0 : itEl2ent->second; const bool hasGeoNorm = ge && (ge->dim() == 2) && ge->haveParametrization(); for (int i=0; i<jac->getNumPrimMapNodes(); i++) { const int &iV = _el2V[iEl][i]; primNodesXYZ(i,0) = _xyz[iV].x(); primNodesXYZ(i,1) = _xyz[iV].y(); primNodesXYZ(i,2) = _xyz[iV].z(); if (hasGeoNorm && (_vert[iV]->onWhat() == ge)) { double u, v; _vert[iV]->getParameter(0,u); _vert[iV]->getParameter(1,v); geoNorm += ((GFace*)ge)->normal(SPoint2(u,v)); } } if (hasGeoNorm && (geoNorm.normSq() == 0.)) { SPoint2 param = ((GFace*)ge)->parFromPoint(_el[iEl]->barycenter(true),false); geoNorm = ((GFace*)ge)->normal(param); } fullMatrix<double> &elNorm = _scaledNormEl[iEl]; elNorm.resize(1,3); const double norm = jac->getPrimNormal2D(primNodesXYZ,elNorm); double factor = 1./norm; if (hasGeoNorm) { const double scal = geoNorm(0)*elNorm(0,0)+geoNorm(1)*elNorm(0,1)+geoNorm(2)*elNorm(0,2); if (scal < 0.) factor = -factor; } elNorm.scale(factor); // Re-scaling normal here is faster than an extra scaling operation on the Jacobian }
inline double computeEdgeLinearLength_new(BDS_Point *p1, BDS_Point *p2, GFace *f, double SCALINGU, double SCALINGV) { const int nbSb = 10; GPoint GP[nbSb]; for (int i = 1; i < nbSb; i++){ double xi = (double)i / nbSb; GP[i-1] = f->point(SPoint2(((1-xi) * p1->u + xi * p2->u) * SCALINGU, ((1-xi) * p1->v + xi * p2->v) * SCALINGV)); if (!GP[i-1].succeeded()) return computeEdgeLinearLength(p1,p2); } double l = 0; for (int i = 0; i < nbSb; i++){ if (i == 0){ const double dx1 = p1->X - GP[0].x(); const double dy1 = p1->Y - GP[0].y(); const double dz1 = p1->Z - GP[0].z(); l+= sqrt(dx1 * dx1 + dy1 * dy1 + dz1 * dz1); } else if (i == nbSb-1){ const double dx1 = p2->X - GP[nbSb-1].x(); const double dy1 = p2->Y - GP[nbSb-1].y(); const double dz1 = p2->Z - GP[nbSb-1].z(); l+= sqrt(dx1 * dx1 + dy1 * dy1 + dz1 * dz1); } else{ const double dx1 = GP[i].x() - GP[i-1].x(); const double dy1 = GP[i].y() - GP[i-1].y(); const double dz1 = GP[i].z() - GP[i-1].z(); l+= sqrt(dx1 * dx1 + dy1 * dy1 + dz1 * dz1); } } return l; }
SPoint2 gmshSurface::parFromPoint(double x, double y, double z) { Msg::Error("Parametric coordinate computation not implemented for this type of surface"); return SPoint2(); }
bool frameFieldBackgroundMesh2D::compute_RK_infos(double u,double v, double x, double y, double z, RK_form &infos) { // check if point is in domain if (!inDomain(u,v)) return false; // get stored angle double angle_current = angle(u,v); // compute t1,t2: cross field directions // get the unit normal at that point GFace *face = dynamic_cast<GFace*>(gf); if(!face) { Msg::Error("Entity is not a face in background mesh"); return false; } Pair<SVector3, SVector3> der = face->firstDer(SPoint2(u,v)); SVector3 s1 = der.first(); SVector3 s2 = der.second(); SVector3 n = crossprod(s1,s2); n.normalize(); SVector3 basis_u = s1; basis_u.normalize(); SVector3 basis_v = crossprod(n,basis_u); // normalize vector t1 that is tangent to gf at uv SVector3 t1 = basis_u * cos(angle_current) + basis_v * sin(angle_current) ; t1.normalize(); // compute the second direction t2 and normalize (t1,t2,n) is the tangent frame SVector3 t2 = crossprod(n,t1); t2.normalize(); // get metric double L = size(u,v); infos.metricField = SMetric3(1./(L*L)); FieldManager *fields = gf->model()->getFields(); if(fields->getBackgroundField() > 0) { Field *f = fields->get(fields->getBackgroundField()); if (!f->isotropic()) { (*f)(x,y,z, infos.metricField,gf); } else { L = (*f)(x,y,z,gf); infos.metricField = SMetric3(1./(L*L)); } } double M = dot(s1,s1); double N = dot(s2,s2); double E = dot(s1,s2); // compute the first fundamental form i.e. the metric tensor at the point // M_{ij} = s_i \cdot s_j double metric[2][2] = {{M,E},{E,N}}; // get sizes double size_1 = sqrt(1. / dot(t1,infos.metricField,t1)); double size_2 = sqrt(1. / dot(t2,infos.metricField,t2)); // compute covariant coordinates of t1 and t2 - cross field directions in parametric domain double covar1[2],covar2[2]; // t1 = a s1 + b s2 --> // t1 . s1 = a M + b E // t1 . s2 = a E + b N --> solve the 2 x 2 system // and get covariant coordinates a and b double rhs1[2] = {dot(t1,s1),dot(t1,s2)}; bool singular = false; if (!sys2x2(metric,rhs1,covar1)) { Msg::Info("Argh surface %d %g %g %g -- %g %g %g -- %g %g",gf->tag(),s1.x(),s1.y(),s1.z(),s2.x(),s2.y(),s2.z(),size_1,size_2); covar1[1] = 1.0; covar1[0] = 0.0; singular = true; } double rhs2[2] = {dot(t2,s1),dot(t2,s2)}; if (!sys2x2(metric,rhs2,covar2)) { Msg::Info("Argh surface %d %g %g %g -- %g %g %g",gf->tag(),s1.x(),s1.y(),s1.z(),s2.x(),s2.y(),s2.z()); covar2[0] = 1.0; covar2[1] = 0.0; singular = true; } // transform the sizes with respect to the metric // consider a vector v of size 1 in the parameter plane // its length is sqrt (v^T M v) --> if I want a real size // of size1 in direction v, it should be sqrt(v^T M v) * size1 double l1 = sqrt(covar1[0]*covar1[0]+covar1[1]*covar1[1]); double l2 = sqrt(covar2[0]*covar2[0]+covar2[1]*covar2[1]); covar1[0] /= l1; covar1[1] /= l1; covar2[0] /= l2; covar2[1] /= l2; double size_param_1 = size_1 / sqrt ( M*covar1[0]*covar1[0]+ 2*E*covar1[1]*covar1[0]+ N*covar1[1]*covar1[1]); double size_param_2 = size_2 / sqrt ( M*covar2[0]*covar2[0]+ 2*E*covar2[1]*covar2[0]+ N*covar2[1]*covar2[1]); if (singular) { size_param_1 = size_param_2 = std::min (size_param_1,size_param_2); } // filling form... infos.t1 = t1; infos.h.first = size_1; infos.h.second = size_2; infos.paramh.first = size_param_1; infos.paramh.second = size_param_2; infos.paramt1 = SPoint2(covar1[0],covar1[1]); infos.paramt2 = SPoint2(covar2[0],covar2[1]); infos.angle = angle_current; infos.localsize = L; infos.normal = n; return true; }
SPoint2 gmshVertex::reparamOnFace(const GFace *face, int dir) const { Surface *s = (Surface*)face->getNativePtr(); if(s->geometry){ // It is not always right if it is periodic. if(l_edges.size() == 1 && (*l_edges.begin())->getBeginVertex() == (*l_edges.begin())->getEndVertex()){ Range<double> bb = (*l_edges.begin())->parBounds(0); return (*l_edges.begin())->reparamOnFace(face, bb.low(), dir); } return v->pntOnGeometry; } if(s->Typ == MSH_SURF_REGL){ Curve *C[4]; for(int i = 0; i < 4; i++) List_Read(s->Generatrices, i, &C[i]); double U, V; if ((C[0]->beg == v && C[3]->beg == v) || (C[0]->end == v && C[3]->beg == v) || (C[0]->beg == v && C[3]->end == v) || (C[0]->end == v && C[3]->end == v)){ U = V = 0; } else if ((C[0]->beg == v && C[1]->beg == v) || (C[0]->end == v && C[1]->beg == v) || (C[0]->beg == v && C[1]->end == v) || (C[0]->end == v && C[1]->end == v)){ U = 1; V = 0; } else if ((C[2]->beg == v && C[1]->beg == v) || (C[2]->end == v && C[1]->beg == v) || (C[2]->beg == v && C[1]->end == v) || (C[2]->end == v && C[1]->end == v)){ U = 1; V = 1; } else if ((C[2]->beg == v && C[3]->beg == v) || (C[2]->end == v && C[3]->beg == v) || (C[2]->beg == v && C[3]->end == v) || (C[2]->end == v && C[3]->end == v)){ U = 0; V = 1; } else{ Msg::Info("Reparameterizing point %d on face %d", v->Num, s->Num); return GVertex::reparamOnFace(face, dir); } return SPoint2(U, V); } else if(s->Typ == MSH_SURF_TRIC){ Curve *C[3]; for(int i = 0; i < 3; i++) List_Read(s->Generatrices, i, &C[i]); double U, V; if ((C[0]->beg == v && C[2]->beg == v) || (C[0]->end == v && C[2]->beg == v) || (C[0]->beg == v && C[2]->end == v) || (C[0]->end == v && C[2]->end == v)){ U = V = 0; } else if ((C[0]->beg == v && C[1]->beg == v) || (C[0]->end == v && C[1]->beg == v) || (C[0]->beg == v && C[1]->end == v) || (C[0]->end == v && C[1]->end == v)){ U = 1; V = 0; } else if ((C[2]->beg == v && C[1]->beg == v) || (C[2]->end == v && C[1]->beg == v) || (C[2]->beg == v && C[1]->end == v) || (C[2]->end == v && C[1]->end == v)){ U = 1; V = 1; } else{ Msg::Info("Reparameterizing point %d on face %d", v->Num, s->Num); return GVertex::reparamOnFace(face, dir); } return SPoint2(U, V); } else{ return GVertex::reparamOnFace(face, dir); } }
SPoint2 gmshEdge::reparamOnFace(const GFace *face, double epar,int dir) const { Surface *s = (Surface*) face->getNativePtr(); bool periodic = (c->end == c->beg); if(s->geometry){ switch (c->Typ) { case MSH_SEGM_LINE: { Vertex *v[3]; List_Read(c->Control_Points, 0, &v[1]); List_Read(c->Control_Points, 1, &v[2]); SPoint2 p = v[1]->pntOnGeometry + (v[2]->pntOnGeometry - v[1]->pntOnGeometry) * epar; return p; } case MSH_SEGM_BSPLN: case MSH_SEGM_BEZIER: { int NbControlPoints = List_Nbr(c->Control_Points); int NbCurves = NbControlPoints + (periodic ? -1 : 1); int iCurve = (int)floor(epar * (double)NbCurves); if(iCurve >= NbCurves) iCurve = NbCurves - 1; else if (iCurve < 0) // ? does it happen ? iCurve = 0; double t1 = (double)(iCurve) / (double)(NbCurves); double t2 = (double)(iCurve+1) / (double)(NbCurves); double t = (epar - t1) / (t2 - t1); Vertex *v[4]; for(int j = 0; j < 4; j ++ ){ int k = iCurve - (periodic ? 1 : 2) + j; if(k < 0) k = periodic ? k + NbControlPoints - 1 : 0; if(k >= NbControlPoints) k = periodic ? k - NbControlPoints + 1: NbControlPoints - 1; List_Read(c->Control_Points, k, &v[j]); } return InterpolateCubicSpline(v, t, c->mat, t1, t2, c->geometry,0); } case MSH_SEGM_SPLN : { Vertex temp1, temp2; int N = List_Nbr(c->Control_Points); int i = (int)((double)(N - 1) * epar); if(i < 0) i = 0; if(i >= N - 1) i = N - 2; double t1 = (double)(i) / (double)(N - 1); double t2 = (double)(i + 1) / (double)(N - 1); double t = (epar - t1) / (t2 - t1); Vertex *v[4]; List_Read(c->Control_Points, i, &v[1]); List_Read(c->Control_Points, i + 1, &v[2]); if(!i) { if(c->beg == c->end){ List_Read(c->Control_Points,N-2,&v[0]); } else{ v[0] = &temp1; v[0]->pntOnGeometry = v[1]->pntOnGeometry * 2. - v[2]->pntOnGeometry; } } else{ List_Read(c->Control_Points, i - 1, &v[0]); } if(i == N - 2) { if(c->beg == c->end){ List_Read(c->Control_Points,1,&v[3]); } else{ v[3] = &temp2; v[3]->pntOnGeometry = v[2]->pntOnGeometry * 2. - v[1]->pntOnGeometry; } } else{ List_Read(c->Control_Points, i + 2, &v[3]); } return InterpolateCubicSpline(v, t, c->mat, t1, t2, c->geometry,0); } default: Msg::Error("Unknown edge type in reparamOnFace"); return SPoint2(); } } if(s->Typ == MSH_SURF_REGL){ Curve *C[4]; for(int i = 0; i < 4; i++) List_Read(s->Generatrices, i, &C[i]); double U, V; if (C[0]->Num == c->Num) { U = (epar - C[0]->ubeg) / (C[0]->uend - C[0]->ubeg) ; V = 0; } else if (C[0]->Num == -c->Num) { U = (C[0]->uend - epar - C[0]->ubeg) / (C[0]->uend - C[0]->ubeg) ; V = 0; } else if (C[1]->Num == c->Num) { V = (epar - C[1]->ubeg) / (C[1]->uend - C[1]->ubeg) ; U = 1; } else if (C[1]->Num == -c->Num) { V = (C[1]->uend - epar - C[1]->ubeg) / (C[1]->uend - C[1]->ubeg) ; U = 1; } else if (C[2]->Num == c->Num) { U = 1 - (epar - C[2]->ubeg) / (C[2]->uend - C[2]->ubeg) ; V = 1; } else if (C[2]->Num == -c->Num) { U = 1 - ( C[2]->uend -epar - C[2]->ubeg) / (C[2]->uend - C[2]->ubeg) ; V = 1; } else if (C[3]->Num == c->Num) { V = 1-(epar - C[3]->ubeg) / (C[3]->uend - C[3]->ubeg) ; U = 0; } else if (C[3]->Num == -c->Num) { V = 1-(C[3]->uend - epar - C[3]->ubeg) / (C[3]->uend - C[3]->ubeg) ; U = 0; } else{ Msg::Info("Reparameterizing edge %d on face %d", c->Num, s->Num); return GEdge::reparamOnFace(face, epar, dir); } return SPoint2(U, V); } else if (s->Typ == MSH_SURF_TRIC){ Curve *C[3]; for(int i = 0; i < 3; i++) List_Read(s->Generatrices, i, &C[i]); double U, V; if(CTX::instance()->geom.oldRuledSurface){ if (C[0]->Num == c->Num) { U = (epar - C[0]->ubeg) / (C[0]->uend - C[0]->ubeg) ; V = 0; } else if (C[0]->Num == -c->Num) { U = (C[0]->uend - epar - C[0]->ubeg) / (C[0]->uend - C[0]->ubeg) ; V = 0; } else if (C[1]->Num == c->Num) { V = (epar - C[1]->ubeg) / (C[1]->uend - C[1]->ubeg) ; U = 1; } else if (C[1]->Num == -c->Num) { V = (C[1]->uend - epar - C[1]->ubeg) / (C[1]->uend - C[1]->ubeg) ; U = 1; } else if (C[2]->Num == c->Num) { U = 1-(epar - C[2]->ubeg) / (C[2]->uend - C[2]->ubeg) ; V = 1; } else if (C[2]->Num == -c->Num) { U = 1-(C[2]->uend - epar - C[2]->ubeg) / (C[2]->uend - C[2]->ubeg) ; V = 1; } else{ Msg::Info("Reparameterizing edge %d on face %d", c->Num, s->Num); return GEdge::reparamOnFace(face, epar, dir); } } else{ // FIXME: workaround for exact extrusions bool hack = false; if(CTX::instance()->geom.exactExtrusion && s->Extrude && s->Extrude->geo.Mode == EXTRUDED_ENTITY && s->Typ != MSH_SURF_PLAN) hack = true; if (C[0]->Num == c->Num) { U = (epar - C[0]->ubeg) / (C[0]->uend - C[0]->ubeg) ; V = 0; } else if (C[0]->Num == -c->Num) { U = (C[0]->uend - epar - C[0]->ubeg) / (C[0]->uend - C[0]->ubeg) ; V = 0; } else if (C[1]->Num == c->Num) { V = (epar - C[1]->ubeg) / (C[1]->uend - C[1]->ubeg) ; U = 1; } else if (C[1]->Num == -c->Num) { V = (C[1]->uend - epar - C[1]->ubeg) / (C[1]->uend - C[1]->ubeg) ; U = 1; } else if (C[2]->Num == c->Num) { U = 1-(epar - C[2]->ubeg) / (C[2]->uend - C[2]->ubeg) ; V = hack ? 1 : U; } else if (C[2]->Num == -c->Num) { U = 1-(C[2]->uend - epar - C[2]->ubeg) / (C[2]->uend - C[2]->ubeg) ; V = hack ? 1 : U; } else{ Msg::Info("Reparameterizing edge %d on face %d", c->Num, s->Num); return GEdge::reparamOnFace(face, epar, dir); } } return SPoint2(U, V); } else{ return GEdge::reparamOnFace(face, epar, dir); } }
SPoint2 fourierProjectionFace::parFromPoint(const SPoint3 &p, bool onSurface) const { double u,v; ps_->Inverse(p[0], p[1], p[2], u, v); return SPoint2(u, v); }
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]); // std::cout << "(" << midpoint[0] << "," <<midpoint[1] << ") -> (" << // newP[i][0][0] << "," << newP[i][0][1] << ") " << std::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; }