void MSubLine::getGradShapeFunctions(double u, double v, double w, double s[][3], int order) const { if(!_orig) return; if (_orig->getDim()==getDim()) return _orig->getGradShapeFunctions(u, v, w, s, order); int nsf = _orig->getNumShapeFunctions(); double gradsuvw[1256][3]; _orig->getGradShapeFunctions(u, v, w, gradsuvw, order); double jac[3][3]; double invjac[3][3]; _orig->getJacobian(u, v, w, jac); inv3x3(jac, invjac); MEdge edge = getBaseElement()->getEdge(0); SVector3 tang = edge.tangent(); double gradxyz[3]; double projgradxyz[3]; for (int i=0; i<nsf; ++i) { // (i) get the cartesian coordinates of the gradient gradxyz[0] = invjac[0][0] * gradsuvw[i][0] + invjac[0][1] * gradsuvw[i][1] + invjac[0][2] * gradsuvw[i][2]; gradxyz[1] = invjac[1][0] * gradsuvw[i][0] + invjac[1][1] * gradsuvw[i][1] + invjac[1][2] * gradsuvw[i][2]; gradxyz[2] = invjac[2][0] * gradsuvw[i][0] + invjac[2][1] * gradsuvw[i][1] + invjac[2][2] * gradsuvw[i][2]; // (ii) projection of the gradient on edges in the cartesian space SVector3 grad(&gradxyz[0]); double prodscal = dot(tang,grad); projgradxyz[0] = prodscal * tang.x(); projgradxyz[1] = prodscal * tang.y(); projgradxyz[2] = prodscal * tang.z(); // (iii) get the parametric coordinates of the projection in the parametric space of the parent element s[i][0] = jac[0][0] * projgradxyz[0] + jac[0][1] * projgradxyz[1] + jac[0][2] * projgradxyz[2]; s[i][1] = jac[1][0] * projgradxyz[0] + jac[1][1] * projgradxyz[1] + jac[1][2] * projgradxyz[2]; s[i][2] = jac[2][0] * projgradxyz[0] + jac[2][1] * projgradxyz[1] + jac[2][2] * projgradxyz[2]; } }
static void drawBarycentricDual(std::vector<T*> &elements) { glColor4ubv((GLubyte *) & CTX::instance()->color.fg); glEnable(GL_LINE_STIPPLE); glLineStipple(1, 0x0F0F); gl2psEnable(GL2PS_LINE_STIPPLE); glBegin(GL_LINES); for(unsigned int i = 0; i < elements.size(); i++){ MElement *ele = elements[i]; if(!isElementVisible(ele)) continue; SPoint3 pc = ele->barycenter(); if(ele->getDim() == 2){ for(int j = 0; j < ele->getNumEdges(); j++){ MEdge e = ele->getEdge(j); SPoint3 p = e.barycenter(); glVertex3d(pc.x(), pc.y(), pc.z()); glVertex3d(p.x(), p.y(), p.z()); } } else if(ele->getDim() == 3){ for(int j = 0; j < ele->getNumFaces(); j++){ MFace f = ele->getFace(j); SPoint3 p = f.barycenter(); glVertex3d(pc.x(), pc.y(), pc.z()); glVertex3d(p.x(), p.y(), p.z()); for(int k = 0; k < f.getNumVertices(); k++){ MEdge e(f.getVertex(k), (k == f.getNumVertices() - 1) ? f.getVertex(0) : f.getVertex(k + 1)); SPoint3 pe = e.barycenter(); glVertex3d(p.x(), p.y(), p.z()); glVertex3d(pe.x(), pe.y(), pe.z()); } } } } glEnd(); glDisable(GL_LINE_STIPPLE); gl2psDisable(GL2PS_LINE_STIPPLE); }
void updateBoVec<2, MEdge>( const int normalSource, const MVertex *const vertex, const int zoneIndex, const int vertIndex, const CCon::FaceVector<MZoneBoundary<2>::GlobalVertexData<MEdge>::FaceDataB> &faces, ZoneBoVec &zoneBoVec, BCPatchIndex &patch, bool &warnNormFromElem) { GEntity *ent; if(normalSource == NormalSourceElement) goto getNormalFromElements; ent = vertex->onWhat(); if(ent == 0) { goto getNormalFromElements; // No entity: try to find a normal from the faces } else { switch(ent->dim()) { case 0: /*--------------------------------------------------------------------* * In this case, there are possibly two GEdges from this zone * connected to the vertex. If the angle between the two edges is * significant, the BC patch will be split and this vertex will be * written in both patches with different normals. If the angle is * small, or only one GEdge belongs to this zone, then the vertex will * only be written to one patch. *--------------------------------------------------------------------*/ { // Find edge entities that are connected to elements in the zone std::vector<std::pair<GEdge *, int> > useGEdge; const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(zoneIndex == faces[iFace].zoneIndex) { MEdge mEdge = faces[iFace].parentElement->getEdge(faces[iFace].parentFace); // Get the other vertex on the mesh edge. MVertex *vertex2 = mEdge.getMinVertex(); if(vertex2 == vertex) vertex2 = mEdge.getMaxVertex(); // Check if the entity associated with vertex2 is a line and // is also connected to vertex. If so, add it to the container of // edge entities that will be used to determine the normal GEntity *const ent2 = vertex2->onWhat(); if(ent2->dim() == 1) { useGEdge.push_back( std::pair<GEdge *, int>(static_cast<GEdge *>(ent2), iFace)); } } } //--'useGEdge' now contains the edge entities that will be used to // determine //--the normals switch(useGEdge.size()) { case 0: // goto getNormalFromElements; // We probably don't want BC data if none of the faces attatched to // this vertex and in this zone are on the boundary. break; case 1: { const GEdge *const gEdge = static_cast<const GEdge *>(useGEdge[0].first); SVector3 boNormal; if(edge_normal(vertex, zoneIndex, gEdge, faces, boNormal)) goto getNormalFromElements; zoneBoVec.push_back(VertexBoundary(zoneIndex, gEdge->tag(), boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add(gEdge->tag()); } break; case 2: { // Get the first normal const GEdge *const gEdge1 = static_cast<const GEdge *>(useGEdge[0].first); SVector3 boNormal1; if(edge_normal(vertex, zoneIndex, gEdge1, faces, boNormal1, useGEdge[0].second)) goto getNormalFromElements; // Get the second normal const GEdge *const gEdge2 = static_cast<const GEdge *>(useGEdge[1].first); SVector3 boNormal2; if(edge_normal(vertex, zoneIndex, gEdge2, faces, boNormal2, useGEdge[1].second)) goto getNormalFromElements; if(dot(boNormal1, boNormal2) < 0.98) { //--Write 2 separate patches zoneBoVec.push_back( VertexBoundary(zoneIndex, gEdge1->tag(), boNormal1, const_cast<MVertex *>(vertex), vertIndex)); patch.add(gEdge1->tag()); zoneBoVec.push_back( VertexBoundary(zoneIndex, gEdge2->tag(), boNormal2, const_cast<MVertex *>(vertex), vertIndex)); patch.add(gEdge2->tag()); } else { //--Write one patch boNormal1 += boNormal2; boNormal1 *= 0.5; zoneBoVec.push_back( VertexBoundary(zoneIndex, gEdge1->tag(), boNormal1, const_cast<MVertex *>(vertex), vertIndex)); patch.addPair(gEdge1->tag(), gEdge2->tag()); } } break; default: Msg::Error("Internal error based on 2-D boundary assumptions (file " "\'MZoneBoundary.cpp'). Boundary vertices may be " "incorrect"); break; } } break; case 1: /*--------------------------------------------------------------------* * The vertex exists on an edge and belongs to only 1 BC patch. *--------------------------------------------------------------------*/ { SVector3 boNormal; if(edge_normal(vertex, zoneIndex, static_cast<const GEdge *>(ent), faces, boNormal)) goto getNormalFromElements; zoneBoVec.push_back(VertexBoundary(zoneIndex, ent->tag(), boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add(ent->tag()); } break; default: goto getNormalFromElements; } } return; getNormalFromElements:; /*--------------------------------------------------------------------* * Geometry information cannot be used - generate normals from the * elements *--------------------------------------------------------------------*/ { if(warnNormFromElem && normalSource == 1) { Msg::Warning("Some or all boundary normals were determined from mesh " "elements instead of from the geometry"); warnNormFromElem = false; } // The mesh plane normal is computed from all elements attached to the // vertex SVector3 meshPlaneNormal(0.); // This normal is perpendicular to the // plane of the mesh const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { // Make sure all the planes go in the same direction //**Required? SVector3 mpnt = faces[iFace].parentElement->getFace(0).normal(); if(dot(mpnt, meshPlaneNormal) < 0.) mpnt.negate(); meshPlaneNormal += mpnt; } } // Sum the normals from each element. The tangent is computed from all // faces in the zone attached to the vertex and is weighted by the length of // the edge. Each tangent has to be converted independently into an // inwards-pointing normal. SVector3 boNormal(0.); for(int iFace = 0; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { const SVector3 tangent = faces[iFace] .parentElement->getEdge(faces[iFace].parentFace) .tangent(); // Normal to the boundary (unknown direction) SVector3 bnt = crossprod(tangent, meshPlaneNormal); // Inwards normal const SVector3 inwards(vertex->point(), faces[iFace].parentElement->barycenter()); if(dot(bnt, inwards) < 0.) bnt.negate(); boNormal += bnt; } } boNormal.normalize(); zoneBoVec.push_back(VertexBoundary( zoneIndex, 0, boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add(0); } }
bool Centerline::cutByDisk(SVector3 &PT, SVector3 &NORM, double &maxRad) { double a = NORM.x(); double b = NORM.y(); double c = NORM.z(); double d = -a * PT.x() - b * PT.y() - c * PT.z(); int maxStep = 20; const double EPS = 0.007; //std::set<MEdge,Less_Edge> allEdges; std::vector<MEdge> allEdges; for(unsigned int i = 0; i < triangles.size(); i++){ for ( unsigned int j= 0; j < 3; j++){ allEdges.push_back(triangles[i]->getEdge(j)); //allEdges.insert(triangles[i]->getEdge(j)); } } std::unique(allEdges.begin(), allEdges.end()); bool closedCut = false; int step = 0; while (!closedCut && step < maxStep){ double rad = 1.1*maxRad+0.05*step*maxRad; std::map<MEdge,MVertex*,Less_Edge> cutEdges; std::vector<MVertex*> cutVertices; std::vector<MTriangle*> newTris; std::set<MEdge,Less_Edge> newCut; cutEdges.clear(); cutVertices.clear(); newTris.clear(); newCut.clear(); // for (std::set<MEdge,Less_Edge>::iterator it = allEdges.begin(); // it != allEdges.end() ; ++it){ // MEdge me = *it; for (unsigned int j = 0; j < allEdges.size(); j++){ MEdge me = allEdges[j]; SVector3 P1(me.getVertex(0)->x(),me.getVertex(0)->y(), me.getVertex(0)->z()); SVector3 P2(me.getVertex(1)->x(),me.getVertex(1)->y(), me.getVertex(1)->z()); double V1 = a * P1.x() + b * P1.y() + c * P1.z() + d; double V2 = a * P2.x() + b * P2.y() + c * P2.z() + d; bool inters = (V1*V2<=0.0) ? true: false; bool inDisk = ((norm(P1-PT) < rad ) || (norm(P2-PT) < rad)) ? true : false; double rdist = -V1/(V2-V1); if (inters && rdist > EPS && rdist < 1.-EPS){ SVector3 PZ = P1+rdist*(P2-P1); if (inDisk){ MVertex *newv = new MVertex (PZ.x(), PZ.y(), PZ.z()); cutEdges.insert(std::make_pair(me,newv)); } } else if (inters && rdist <= EPS && inDisk ) cutVertices.push_back(me.getVertex(0)); else if (inters && rdist >= 1.-EPS && inDisk) cutVertices.push_back(me.getVertex(1)); } for(unsigned int i = 0; i < triangles.size(); i++){ cutTriangle(triangles[i], cutEdges,cutVertices, newTris, newCut); } if (isClosed(newCut)) { triangles.clear(); triangles = newTris; theCut.insert(newCut.begin(),newCut.end()); break; } else { step++; //if (step == maxStep) {printf("no closed cut %d \n", (int)newCut.size()); }; // // triangles = newTris; // // theCut.insert(newCut.begin(),newCut.end()); // char name[256]; // sprintf(name, "myCUT-%d.pos", step); // FILE * f2 = Fopen(name,"w"); // fprintf(f2, "View \"\"{\n"); // std::set<MEdge,Less_Edge>::iterator itp = newCut.begin(); // while (itp != newCut.end()){ // MEdge l = *itp; // fprintf(f2, "SL(%g,%g,%g,%g,%g,%g){%g,%g};\n", // l.getVertex(0)->x(), l.getVertex(0)->y(), l.getVertex(0)->z(), // l.getVertex(1)->x(), l.getVertex(1)->y(), l.getVertex(1)->z(), // 1.0,1.0); // itp++; // } // fprintf(f2,"};\n"); // fclose(f2); } } if (step < maxStep){ //printf("cutByDisk OK step =%d \n", step); return true; } else { //printf("cutByDisk not succeeded \n"); return false; } }
static int getAspectRatio(std::vector<MElement *> &elements, std::vector<std::vector<MEdge> > &boundaries) { double area3D = 0.0; for(unsigned int i = 0; i <elements.size(); ++i){ MElement *t = elements[i]; std::vector<MVertex *> v(3); for(int k = 0; k < 3; k++) v[k] = t->getVertex(k); double p0[3] = {v[0]->x(), v[0]->y(), v[0]->z()}; double p1[3] = {v[1]->x(), v[1]->y(), v[1]->z()}; double p2[3] = {v[2]->x(), v[2]->y(), v[2]->z()}; double a_3D = fabs(triangle_area(p0, p1, p2)); area3D += a_3D; } double tot_length = 0.0; for(unsigned int i = 0; i <boundaries.size(); ++i){ std::vector<MEdge> iBound = boundaries[i]; double iLength = 0.0; for( unsigned int j = 0; j <iBound.size(); ++j){ MVertex *v0 = iBound[j].getVertex(0); MVertex *v1 = iBound[j].getVertex(1); const double length = sqrt((v0->x() - v1->x()) * (v0->x() - v1->x()) + (v0->y() - v1->y()) * (v0->y() - v1->y()) + (v0->z() - v1->z()) * (v0->z() - v1->z())); iLength += length; } tot_length += iLength; } int AR = 1; if (boundaries.size() > 0){ tot_length /= boundaries.size(); AR = (int) ceil(2*3.14*area3D/(tot_length*tot_length)); } //compute AR also with Bounding box std::set<MVertex*> vs; for(unsigned int i = 0; i < elements.size(); i++){ MElement *e = elements[i]; for(int j = 0; j < e->getNumVertices(); j++){ vs.insert(e->getVertex(j)); } } SBoundingBox3d bb; std::vector<SPoint3> vertices; for (std::set<MVertex* >::iterator it = vs.begin(); it != vs.end(); it++){ SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z()); vertices.push_back(pt); bb += pt; } double H = norm(SVector3(bb.max(), bb.min())); //SOrientedBoundingBox obbox = SOrientedBoundingBox::buildOBB(vertices); //double H = obbox.getMaxSize(); double D = H; if (boundaries.size() > 0 ) D = 10e4; for (unsigned int i = 0; i < boundaries.size(); i++){ std::set<MVertex*> vb; std::vector<MEdge> iBound = boundaries[i]; for (unsigned int j = 0; j < iBound.size(); j++){ MEdge e = iBound[j]; vb.insert(e.getVertex(0)); vb.insert(e.getVertex(1)); } std::vector<SPoint3> vBounds; SBoundingBox3d bb; for (std::set<MVertex* >::iterator it = vb.begin(); it != vb.end(); it++){ SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z()); vBounds.push_back(pt); bb +=pt; } double iD = norm(SVector3(bb.max(), bb.min())); D = std::min(D, iD); //SOrientedBoundingBox obboxD = SOrientedBoundingBox::buildOBB(vBounds); //D = std::max(D, obboxD.getMaxSize()); } int AR2 = (int)ceil(H/D); return std::max(AR, AR2); }