void GMSH_CutPlanePlugin::draw(void *context) { #if defined(HAVE_OPENGL) int num = (int)CutPlaneOptions_Number[7].def; drawContext *ctx = (drawContext *)context; if(num < 0) num = iview; if(num >= 0 && num < (int)PView::list.size()) { glColor4ubv((GLubyte *)&CTX::instance()->color.fg); glLineWidth((float)CTX::instance()->lineWidth); SBoundingBox3d bb = PView::list[num]->getData()->getBoundingBox(); ctx->drawPlaneInBoundingBox( bb.min().x(), bb.min().y(), bb.min().z(), bb.max().x(), bb.max().y(), bb.max().z(), CutPlaneOptions_Number[0].def, CutPlaneOptions_Number[1].def, CutPlaneOptions_Number[2].def, CutPlaneOptions_Number[3].def); } #endif }
int GModel::readSTL(const std::string &name, double tolerance) { FILE *fp = Fopen(name.c_str(), "rb"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } // store triplets of points for each solid found in the file std::vector<std::vector<SPoint3> > points; SBoundingBox3d bbox; // "solid", or binary data header char buffer[256]; if(!fgets(buffer, sizeof(buffer), fp)){ fclose(fp); return 0; } bool binary = strncmp(buffer, "solid", 5) && strncmp(buffer, "SOLID", 5); // ASCII STL if(!binary){ points.resize(1); while(!feof(fp)) { // "facet normal x y z" or "endsolid" if(!fgets(buffer, sizeof(buffer), fp)) break; if(!strncmp(buffer, "endsolid", 8) || !strncmp(buffer, "ENDSOLID", 8)){ // "solid" if(!fgets(buffer, sizeof(buffer), fp)) break; if(!strncmp(buffer, "solid", 5) || !strncmp(buffer, "SOLID", 5)){ points.resize(points.size() + 1); // "facet normal x y z" if(!fgets(buffer, sizeof(buffer), fp)) break; } } // "outer loop" if(!fgets(buffer, sizeof(buffer), fp)) break; // "vertex x y z" for(int i = 0; i < 3; i++){ if(!fgets(buffer, sizeof(buffer), fp)) break; char s1[256]; double x, y, z; if(sscanf(buffer, "%s %lf %lf %lf", s1, &x, &y, &z) != 4) break; SPoint3 p(x, y, z); points.back().push_back(p); bbox += p; } // "endloop" if(!fgets(buffer, sizeof(buffer), fp)) break; // "endfacet" if(!fgets(buffer, sizeof(buffer), fp)) break; } } // check if we could parse something bool empty = true; for(unsigned int i = 0; i < points.size(); i++){ if(points[i].size()){ empty = false; break; } } if(empty) points.clear(); // binary STL (we also try to read in binary mode if the header told // us the format was ASCII but we could not read any vertices) if(binary || empty){ if(binary) Msg::Info("Mesh is in binary format"); else Msg::Info("Wrong ASCII header or empty file: trying binary read"); rewind(fp); while(!feof(fp)) { char header[80]; if(!fread(header, sizeof(char), 80, fp)) break; unsigned int nfacets = 0; size_t ret = fread(&nfacets, sizeof(unsigned int), 1, fp); bool swap = false; if(nfacets > 100000000){ Msg::Info("Swapping bytes from binary file"); swap = true; SwapBytes((char*)&nfacets, sizeof(unsigned int), 1); } if(ret && nfacets){ points.resize(points.size() + 1); char *data = new char[nfacets * 50 * sizeof(char)]; ret = fread(data, sizeof(char), nfacets * 50, fp); if(ret == nfacets * 50){ for(unsigned int i = 0; i < nfacets; i++) { float *xyz = (float *)&data[i * 50 * sizeof(char)]; if(swap) SwapBytes((char*)xyz, sizeof(float), 12); for(int j = 0; j < 3; j++){ SPoint3 p(xyz[3 + 3 * j], xyz[3 + 3 * j + 1], xyz[3 + 3 * j + 2]); points.back().push_back(p); bbox += p; } } } delete [] data; } } } std::vector<GFace*> faces; for(unsigned int i = 0; i < points.size(); i++){ if(points[i].empty()){ Msg::Error("No facets found in STL file for solid %d", i); fclose(fp); return 0; } if(points[i].size() % 3){ Msg::Error("Wrong number of points (%d) in STL file for solid %d", points[i].size(), i); fclose(fp); return 0; } Msg::Info("%d facets in solid %d", points[i].size() / 3, i); // create face GFace *face = new discreteFace(this, getMaxElementaryNumber(2) + 1); faces.push_back(face); add(face); } // create triangles using unique vertices double eps = norm(SVector3(bbox.max(), bbox.min())) * tolerance; std::vector<MVertex*> vertices; for(unsigned int i = 0; i < points.size(); i++) for(unsigned int j = 0; j < points[i].size(); j++) vertices.push_back(new MVertex(points[i][j].x(), points[i][j].y(), points[i][j].z())); MVertexPositionSet pos(vertices); std::set<MFace,Less_Face> unique; int nbDuplic = 0; for(unsigned int i = 0; i < points.size(); i ++){ for(unsigned int j = 0; j < points[i].size(); j += 3){ MVertex *v[3]; for(int k = 0; k < 3; k++){ double x = points[i][j + k].x(); double y = points[i][j + k].y(); double z = points[i][j + k].z(); v[k] = pos.find(x, y, z, eps); } MFace mf (v[0], v[1], v[2]); if (unique.find(mf) == unique.end()){ faces[i]->triangles.push_back(new MTriangle(v[0], v[1], v[2])); unique.insert(mf); } else{ nbDuplic++; } } } if (nbDuplic) Msg::Warning("%d duplicate triangles in STL file", nbDuplic); _associateEntityWithMeshVertices(); _storeVerticesInEntities(vertices); // will delete unused vertices fclose(fp); return 1; }
void GMSH_SimplePartitionPlugin::run() { #if defined(HAVE_MESH) int numSlicesX = (int)SimplePartitionOptions_Number[0].def; int numSlicesY = (int)SimplePartitionOptions_Number[1].def; int numSlicesZ = (int)SimplePartitionOptions_Number[2].def; int createTopology = (int)SimplePartitionOptions_Number[3].def; std::vector<std::string> exprX(1), exprY(1), exprZ(1); exprX[0] = SimplePartitionOptions_String[0].def; exprY[0] = SimplePartitionOptions_String[1].def; exprZ[0] = SimplePartitionOptions_String[2].def; GModel *m = GModel::current(); if(!m->getNumMeshElements()){ Msg::Error("Plugin(SimplePartition) requires a mesh"); return; } if(numSlicesX < 1 || numSlicesY < 1 || numSlicesZ < 1){ Msg::Error("Number of slices should be strictly positive"); return; } m->unpartitionMesh(); SBoundingBox3d bbox = m->bounds(); double pminX = bbox.min()[0], pmaxX = bbox.max()[0]; double pminY = bbox.min()[1], pmaxY = bbox.max()[1]; double pminZ = bbox.min()[2], pmaxZ = bbox.max()[2]; std::vector<double> ppX(numSlicesX + 1); std::vector<double> ppY(numSlicesY + 1); std::vector<double> ppZ(numSlicesZ + 1); std::vector<std::string> variables(1, "t"); std::vector<double> values(1), res(1); { mathEvaluator f(exprX, variables); for(int p = 0; p <= numSlicesX; p++) { double t = values[0] = (double)p / (double)numSlicesX; if(f.eval(values, res)) t = res[0]; ppX[p] = pminX + t * (pmaxX - pminX); } } bool emptyX = (ppX[0] == ppX[numSlicesX]); { mathEvaluator f(exprY, variables); for(int p = 0; p <= numSlicesY; p++) { double t = values[0] = (double)p / (double)numSlicesY; if(f.eval(values, res)) t = res[0]; ppY[p] = pminY + t * (pmaxY - pminY); } } bool emptyY = (ppY[0] == ppY[numSlicesY]); { mathEvaluator f(exprZ, variables); for(int p = 0; p <= numSlicesZ; p++) { double t = values[0] = (double)p / (double)numSlicesZ; if(f.eval(values, res)) t = res[0]; ppZ[p] = pminZ + t * (pmaxZ - pminZ); } } bool emptyZ = (ppZ[0] == ppZ[numSlicesZ]); std::vector<GEntity *> entities; m->getEntities(entities); hashmap<MElement *, unsigned int> elmToPartition; for(std::size_t i = 0; i < entities.size(); i++) { GEntity *ge = entities[i]; for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) { MElement *e = ge->getMeshElement(j); SPoint3 point = e->barycenter(); int part = 0; for(int kx = 0; kx < numSlicesX; kx++) { if(part) break; for(int ky = 0; ky < numSlicesY; ky++) { if(part) break; for(int kz = 0; kz < numSlicesZ; kz++) { if(part) break; if((emptyX || (kx == 0 && ppX[0] == point[0]) || (ppX[kx] < point[0] && point[0] <= ppX[kx + 1])) && (emptyY || (ky == 0 && ppY[0] == point[1]) || (ppY[ky] < point[1] && point[1] <= ppY[ky + 1])) && (emptyZ || (kz == 0 && ppZ[0] == point[2]) || (ppZ[kz] < point[2] && point[2] <= ppZ[kz + 1]))){ part = kx * numSlicesY * numSlicesZ + ky * numSlicesZ + kz + 1; elmToPartition.insert(std::pair<MElement *, unsigned int>(e, part)); e->setPartition(part); // this will be removed } } } } } } opt_mesh_partition_create_topology(0, GMSH_SET | GMSH_GUI, createTopology); int ier = PartitionUsingThisSplit(m, numSlicesX * numSlicesY * numSlicesZ, elmToPartition); if(!ier) { opt_mesh_color_carousel(0, GMSH_SET | GMSH_GUI, 3.); CTX::instance()->mesh.changed = ENT_ALL; } #else Msg::Error("Gmsh must be compiled with Mesh support to partition meshes"); #endif }
PView *GMSH_DistancePlugin::execute(PView *v) { int id_pt = (int) DistanceOptions_Number[0].def; int id_line = (int) DistanceOptions_Number[1].def; int id_face = (int) DistanceOptions_Number[2].def; double type = (double) DistanceOptions_Number[3].def; int ortho = (int) DistanceOptions_Number[6].def; PView *view = new PView(); _data = getDataList(view); #if defined(HAVE_SOLVER) #if defined(HAVE_TAUCS) linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>; #else linearSystemCSRGmm<double> *lsys = new linearSystemCSRGmm<double>; lsys->setNoisy(1); lsys->setGmres(1); lsys->setPrec(5.e-8); #endif dofManager<double> * dofView = new dofManager<double>(lsys); #endif std::vector<GEntity*> _entities; GModel::current()->getEntities(_entities); if (!_entities.size() || !_entities[_entities.size()-1]->getMeshElement(0)) { Msg::Error("This plugin needs a mesh !"); return view; } GEntity* ge = _entities[_entities.size()-1]; int integrationPointTetra[2] = {0,0}; int numnodes = 0; for (unsigned int i = 0; i < _entities.size()-1; i++) numnodes += _entities[i]->mesh_vertices.size(); int totNodes = numnodes + _entities[_entities.size()-1]->mesh_vertices.size(); int order = ge->getMeshElement(0)->getPolynomialOrder(); int totNumNodes = totNodes + ge->getNumMeshElements()*integrationPointTetra[order-1]; std::vector<SPoint3> pts; std::vector<double> distances; std::vector<MVertex* > pt2Vertex; pts.clear(); distances.clear(); pt2Vertex.clear(); pts.reserve(totNumNodes); distances.reserve(totNumNodes); pt2Vertex.reserve(totNumNodes); std::map<MVertex*,double> _distanceE_map; std::map<MVertex*,int> _isInYarn_map; std::vector<int> index; std::vector<double> distancesE; std::vector<double> distances2; std::vector<double> distancesE2; std::vector<int> isInYarn; std::vector<int> isInYarn2; std::vector<SPoint3> closePts; std::vector<SPoint3> closePts2; for (int i=0; i<totNumNodes; i++) { distances.push_back(1.e22); } int k = 0; for (unsigned int i=0; i<_entities.size(); i++){ GEntity* ge = _entities[i]; _maxDim = std::max(_maxDim, ge->dim()); for (unsigned int j=0; j<ge->mesh_vertices.size(); j++) { MVertex *v = ge->mesh_vertices[j]; pts.push_back(SPoint3(v->x(), v->y(), v->z())); _distance_map.insert(std::make_pair(v, 0.0)); /* TO DO (by AM) SPoint3 p_empty(); _closePts_map.insert(std::make_pair(v, p_empty)); */ pt2Vertex[k] = v; k++; } } // Compute geometrical distance to mesh boundaries //------------------------------------------------------ if (type < 0.0 ) { bool existEntity = false; for (unsigned int i=0; i<_entities.size(); i++) { GEntity* g2 = _entities[i]; int gDim = g2->dim(); std::vector<int> phys = g2->getPhysicalEntities(); bool computeForEntity = false; for(unsigned int k = 0; k<phys.size(); k++) { int tagp = phys[k]; if (id_pt == 0 && id_line == 0 && id_face == 0 && gDim == _maxDim - 1) computeForEntity = true; else if ((tagp == id_pt && gDim == 0) || (tagp == id_line && gDim == 1) || (tagp == id_face && gDim == 2)) computeForEntity = true; } if (computeForEntity) { existEntity = true; for (unsigned int k = 0; k < g2->getNumMeshElements(); k++) { std::vector<double> iDistances; std::vector<SPoint3> iClosePts; std::vector<double> iDistancesE; std::vector<int> iIsInYarn; MElement *e = g2->getMeshElement(k); MVertex *v1 = e->getVertex(0); MVertex *v2 = e->getVertex(1); SPoint3 p1(v1->x(), v1->y(), v1->z()); SPoint3 p2(v2->x(), v2->y(), v2->z()); if ((e->getNumVertices() == 2 && order == 1) || (e->getNumVertices() == 3 && order == 2)) { signedDistancesPointsLine(iDistances, iClosePts, pts, p1, p2); } else if ((e->getNumVertices() == 3 && order == 1) || (e->getNumVertices() == 6 && order == 2)) { MVertex *v3 = e->getVertex(2); SPoint3 p3 (v3->x(),v3->y(),v3->z()); signedDistancesPointsTriangle(iDistances, iClosePts, pts, p1, p2, p3); } for (unsigned int kk=0; kk<pts.size(); kk++) { if (std::abs(iDistances[kk]) < distances[kk]) { distances[kk] = std::abs(iDistances[kk]); MVertex *v = pt2Vertex[kk]; _distance_map[v] = distances[kk]; /* TO DO (by AM) _closePts_map[v] = iClosePts[kk]; */ } } } } } if (!existEntity){ if (id_pt != 0) Msg::Error("The Physical Point does not exist !"); if (id_line != 0) Msg::Error("The Physical Line does not exist !"); if (id_face != 0) Msg::Error("The Physical Surface does not exist !"); return view; } printView(_entities, _distance_map); /* TO DO (by AM) printView(_entities, _closePts_map); */ } // Compute PDE for distance function //----------------------------------- else if (type > 0.0) { #if defined(HAVE_SOLVER) bool existEntity = false; SBoundingBox3d bbox; for(unsigned int i = 0; i < _entities.size(); i++){ GEntity* ge = _entities[i]; int gDim = ge->dim(); bool fixForEntity = false; std::vector<int> phys = ge->getPhysicalEntities(); for(unsigned int k = 0; k < phys.size(); k++) { int tagp = phys[k]; if (id_pt == 0 && id_line == 0 && id_face == 0 && gDim == _maxDim - 1) fixForEntity = true; else if ((tagp == id_pt && gDim == 0) || (tagp == id_line && gDim == 1) || (tagp == id_face && gDim == 2) ) fixForEntity = true; } if (fixForEntity) { existEntity = true; for (unsigned int i = 0; i < ge->getNumMeshElements(); ++i) { MElement *t = ge->getMeshElement(i); for (int k=0; k<t->getNumVertices(); k++) { MVertex *v = t->getVertex(k); dofView->fixVertex(v, 0, 1, 0.); bbox += SPoint3(v->x(), v->y(), v->z()); } } } } if (!existEntity){ if (id_pt != 0) Msg::Error("The Physical Point does not exist !"); if (id_line != 0) Msg::Error("The Physical Line does not exist !"); if (id_face != 0) Msg::Error("The Physical Surface does not exist !"); return view; } std::vector<MElement *> allElems; for(unsigned int ii = 0; ii < _entities.size(); ii++){ if(_entities[ii]->dim() == _maxDim) { GEntity *ge = _entities[ii]; for(unsigned int i = 0; i < ge->getNumMeshElements(); ++i) { MElement *t = ge->getMeshElement(i); allElems.push_back(t); for (int k = 0; k < t->getNumVertices(); k++) dofView->numberVertex(t->getVertex(k), 0, 1); } } } double L = norm(SVector3(bbox.max(), bbox.min())); double mu = type*L; simpleFunction<double> DIFF(mu*mu), ONE(1.0); distanceTerm distance(GModel::current(), 1, &DIFF, &ONE); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ SElement se((*it)); distance.addToMatrix(*dofView, &se); } groupOfElements gr(allElems); distance.addToRightHandSide(*dofView, gr); Msg::Info("Distance Computation: Assembly done"); lsys->systemSolve(); Msg::Info("Distance Computation: System solved"); for (std::map<MVertex*,double >::iterator itv = _distance_map.begin(); itv != _distance_map.end() ; ++itv) { MVertex *v = itv->first; double value; dofView->getDofValue(v, 0, 1, value); value = std::min(0.9999, value); double dist = -mu * log(1. - value); itv->second = dist; } printView(_entities, _distance_map); #endif } _data->setName("distance"); _data->Time.push_back(0); _data->setFileName(_fileName.c_str()); _data->finalize(); // compute also orthogonal vector to distance field // A Uortho = -C DIST //------------------------------------------------ if (ortho > 0) { #if defined(HAVE_SOLVER) #ifdef HAVE_TAUCS linearSystemCSRTaucs<double> *lsys2 = new linearSystemCSRTaucs<double>; #else linearSystemCSRGmm<double> *lsys2 = new linearSystemCSRGmm<double>; lsys->setNoisy(1); lsys->setGmres(1); lsys->setPrec(5.e-8); #endif dofManager<double> myAssembler(lsys2); simpleFunction<double> ONE(1.0); double dMax = 1.0; //EMI TO CHANGE std::vector<MElement *> allElems; for(unsigned int ii = 0; ii < _entities.size(); ii++){ if (_entities[ii]->dim() == _maxDim) { GEntity *ge = _entities[ii]; for (unsigned int i=0; i<ge->getNumMeshElements(); ++i) { MElement *t = ge->getMeshElement(i); double vMean = 0.0; for (int k = 0; k < t->getNumVertices(); k++) { std::map<MVertex*, double>::iterator it = _distance_map.find(t->getVertex(k)); vMean += it->second; } vMean /= t->getNumVertices(); if (vMean < dMax) allElems.push_back(ge->getMeshElement(i)); } } } int mid = (int)floor(allElems.size() / 2.); MElement *e = allElems[mid]; MVertex *vFIX = e->getVertex(0); myAssembler.fixVertex(vFIX, 0, 1, 0.0); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ MElement *t = *it; for(int k = 0; k < t->getNumVertices(); k++) myAssembler.numberVertex(t->getVertex(k), 0, 1); } orthogonalTerm *ortho; ortho = new orthogonalTerm(GModel::current(), 1, &ONE, &_distance_map); // if (type < 0) // ortho = new orthogonalTerm(GModel::current(), 1, &ONE, view); // else // ortho = new orthogonalTerm(GModel::current(), 1, &ONE, dofView); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ SElement se((*it)); ortho->addToMatrix(myAssembler, &se); } groupOfElements gr(allElems); ortho->addToRightHandSide(myAssembler, gr); Msg::Info("Orthogonal Computation: Assembly done"); lsys2->systemSolve(); Msg::Info("Orthogonal Computation: System solved"); PView *view2 = new PView(); PViewDataList *data2 = getDataList(view2); data2->setName("ortogonal field"); Msg::Info("Writing orthogonal.pos"); FILE * f5 = Fopen("orthogonal.pos","w"); fprintf(f5,"View \"orthogonal\"{\n"); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ MElement *e = *it; int numNodes = e->getNumVertices(); if (e->getType() == TYPE_POLYG) numNodes = e->getNumChildren() * e->getChild(0)->getNumVertices(); std::vector<double> x(numNodes), y(numNodes), z(numNodes); std::vector<double> *out2 = data2->incrementList(1, e->getType(), numNodes); std::vector<MVertex*> nods; std::vector<double> orth; if(!e->getNumChildren()) for(int i=0; i<numNodes; i++) nods.push_back(e->getVertex(i)); else for(int i = 0; i < e->getNumChildren(); i++) for(int j = 0; j < e->getChild(i)->getNumVertices(); j++) nods.push_back(e->getChild(i)->getVertex(j)); for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->x()); for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->y()); for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->z()); if (_maxDim == 2) switch (numNodes) { case 2: fprintf(f5,"SL("); break; case 3: fprintf(f5,"ST("); break; case 4: fprintf(f5,"SQ("); break; default: Msg::Fatal("Error in Plugin 'Distance' (numNodes=%g).",numNodes); break; } else if (_maxDim == 3) switch (numNodes) { case 4: fprintf(f5,"SS("); break; case 8: fprintf(f5,"SH("); break; case 6: fprintf(f5,"SI("); break; case 5: fprintf(f5,"SY("); break; default: Msg::Fatal("Error in Plugin 'Distance' (numNodes=%g).",numNodes); break; } for (int j=0; j<numNodes; j++) { MVertex *v = nods[j]; if (j) fprintf(f5, ",%g,%g,%g", v->x(), v->y(), v->z()); else fprintf(f5, "%g,%g,%g", v->x(), v->y(), v->z()); double value; myAssembler.getDofValue(v, 0, 1, value); orth.push_back(value); } fprintf(f5,"){"); for (unsigned int i=0; i<orth.size(); i++) { out2->push_back(orth[i]); if (i) fprintf(f5,",%g", orth[i]); else fprintf(f5,"%g", orth[i]); } fprintf(f5,"};\n"); } fprintf(f5,"};\n"); fclose(f5); lsys->clear(); lsys2->clear(); data2->Time.push_back(0); data2->setFileName("orthogonal.pos"); data2->finalize(); #endif } return view; }
int main(int argc,char *argv[]) { if(argc < 6){ printf("Usage: %s file lx ly lz rmax [levels=1] [refcs=1]\n", argv[0]); printf("where\n"); printf(" 'file' contains a CAD model\n"); printf(" 'lx', 'ly' and 'lz' are the sizes of the elements along the" " x-, y- and z-axis at the coarsest level\n"); printf(" 'rmax' is the radius of the largest sphere that can be inscribed" " in the structure\n"); printf(" 'levels' sets the number of levels in the grid\n"); printf(" 'refcs' selects if curved surfaces should be refined\n"); return -1; } GmshInitialize(); GmshSetOption("General", "Terminal", 1.); GmshMergeFile(argv[1]); double lx = atof(argv[2]), ly = atof(argv[3]), lz = atof(argv[4]); double rmax = atof(argv[5]); int levels = (argc > 6) ? atof(argv[6]) : 1; int refineCurvedSurfaces = (argc > 7) ? atof(argv[7]) : 1; // minimum distance between points in the cloud at the coarsest // level double sampling = std::min(rmax, std::min(lx, std::min(ly, lz))); // radius of the "tube" created around parts to refine at the // coarsest level double rtube = std::max(lx, std::max(ly, lz)) * 2.; GModel *gm = GModel::current(); std::vector<SPoint3> points; Msg::Info("Filling coarse point cloud on surfaces"); for (GModel::fiter fit = gm->firstFace(); fit != gm->lastFace(); fit++) (*fit)->fillPointCloud(sampling, &points); Msg::Info(" %d points in the surface cloud", (int)points.size()); std::vector<SPoint3> refinePoints; if(levels > 1){ double s = sampling / pow(2., levels - 1); Msg::Info("Filling refined point cloud on curves and curved surfaces"); for (GModel::eiter eit = gm->firstEdge(); eit != gm->lastEdge(); eit++) fillPointCloud(*eit, s, refinePoints); // FIXME: refine this by computing e.g. "mean" curvature if(refineCurvedSurfaces){ for (GModel::fiter fit = gm->firstFace(); fit != gm->lastFace(); fit++) if((*fit)->geomType() != GEntity::Plane) (*fit)->fillPointCloud(2 * s, &refinePoints); } Msg::Info(" %d points in the refined cloud", (int)refinePoints.size()); } SBoundingBox3d bb; for(unsigned int i = 0; i < points.size(); i++) bb += points[i]; for(unsigned int i = 0; i < refinePoints.size(); i++) bb += refinePoints[i]; bb.scale(1.21, 1.21, 1.21); SVector3 range = bb.max() - bb.min(); int NX = range.x() / lx; int NY = range.y() / ly; int NZ = range.z() / lz; if(NX < 2) NX = 2; if(NY < 2) NY = 2; if(NZ < 2) NZ = 2; Msg::Info(" bounding box min: %g %g %g -- max: %g %g %g", bb.min().x(), bb.min().y(), bb.min().z(), bb.max().x(), bb.max().y(), bb.max().z()); Msg::Info(" Nx=%d Ny=%d Nz=%d", NX, NY, NZ); cartesianBox<double> box(bb.min().x(), bb.min().y(), bb.min().z(), SVector3(range.x(), 0, 0), SVector3(0, range.y(), 0), SVector3(0, 0, range.z()), NX, NY, NZ, levels); Msg::Info("Inserting active cells in the cartesian grid"); Msg::Info(" level %d", box.getLevel()); for (unsigned int i = 0; i < points.size(); i++) insertActiveCells(points[i].x(), points[i].y(), points[i].z(), rmax, box); cartesianBox<double> *parent = &box, *child; while((child = parent->getChildBox())){ Msg::Info(" level %d", child->getLevel()); for(unsigned int i = 0; i < refinePoints.size(); i++) insertActiveCells(refinePoints[i].x(), refinePoints[i].y(), refinePoints[i].z(), rtube / pow(2., (levels - child->getLevel())), *child); parent = child; } // remove child cells that do not entirely fill parent cell or for // which there is no parent neighbor; then remove parent cells that // have children Msg::Info("Removing cells to match X-FEM mesh topology constraints"); removeBadChildCells(&box); removeParentCellsWithChildren(&box); // we generate duplicate nodes at this point so we can easily access // cell values at each level; we will clean up by renumbering after // filtering Msg::Info("Initializing nodal values in the cartesian grid"); box.createNodalValues(); Msg::Info("Computing levelset on the cartesian grid"); computeLevelset(gm, box); Msg::Info("Removing cells outside the structure"); removeOutsideCells(&box); Msg::Info("Renumbering mesh vertices across levels"); box.renumberNodes(); bool decomposeInSimplex = false; box.writeMSH("yeah.msh", decomposeInSimplex); Msg::Info("Done!"); GmshFinalize(); }
PView *GMSH_BubblesPlugin::execute(PView *v) { double shrink = (double)BubblesOptions_Number[0].def; std::string fileName = BubblesOptions_String[0].def; FILE *fp = Fopen(fileName.c_str(), "w"); if(!fp){ Msg::Error("Could not open output file '%s'", fileName.c_str()); return v; } GModel *m = GModel::current(); int p = m->getMaxElementaryNumber(0) + 1; int l = m->getMaxElementaryNumber(1) + 1; int s = m->getMaxElementaryNumber(2) + 1; int ll = s, ps = 1; SBoundingBox3d bbox = m->bounds(); double lc = norm(SVector3(bbox.max(), bbox.min())) / 100; fprintf(fp, "lc = %g;\n", lc); for(GModel::viter vit = m->firstVertex(); vit != m->lastVertex(); vit++) (*vit)->writeGEO(fp, "lc"); for(GModel::eiter eit = m->firstEdge(); eit != m->lastEdge(); eit++) (*eit)->writeGEO(fp); for(GModel::fiter fit = m->firstFace(); fit != m->lastFace(); fit++){ (*fit)->writeGEO(fp); fprintf(fp, "Delete { Surface {%d}; }\n", (*fit)->tag()); int sbeg = s; int llbeg = ll; // compute vertex-to-triangle_barycenter map std::map<MVertex*, std::vector<SPoint3> > v2t; for(unsigned int i = 0; i < (*fit)->triangles.size(); i++) for(int j = 0; j < 3; j++) v2t[(*fit)->triangles[i]->getVertex(j)].push_back((*fit)->triangles[i]->barycenter()); // add boundary vertices in map to get cells "closer" to the boundary for(std::map<MVertex*, std::vector<SPoint3> >::iterator it = v2t.begin(); it != v2t.end(); it++){ MVertex *v = it->first; if(v->onWhat() && v->onWhat()->dim() < 2) it->second.push_back(SPoint3(it->first->x(), it->first->y(), it->first->z())); } for(std::map<MVertex*, std::vector<SPoint3> >::iterator it = v2t.begin(); it != v2t.end(); it++){ if(it->second.size() > 2){ // get barycenter of cell boundary points and order them SPoint3 bc; for(unsigned int i = 0; i < it->second.size(); i++) bc += it->second[i]; bc *= 1. / (double)it->second.size(); compareAngle comp(bc); std::sort(it->second.begin(), it->second.end(), comp); // shrink cells if(shrink){ for(unsigned int i = 0; i < it->second.size(); i++){ double dir[3] = {it->second[i].x() - bc.x(), it->second[i].y() - bc.y(), it->second[i].z() - bc.z()}; it->second[i][0] -= shrink * dir[0]; it->second[i][1] -= shrink * dir[1]; it->second[i][2] -= shrink * dir[2]; } } // create b-spline bounded surface for each cell int nump = it->second.size(); for(int i = 0; i < nump; i++){ SPoint3 &b(it->second[i]); fprintf(fp, "Point(%d) = {%.16g, %.16g, %.16g, lc};\n", p++, b.x(), b.y(), b.z()); } fprintf(fp, "BSpline(%d) = {", l++); for(int i = nump - 1; i >= 0; i--) fprintf(fp, "%d,", p - i - 1); fprintf(fp, "%d};\n", p - nump); fprintf(fp, "Line Loop(%d) = {%d};\n", ll++, l - 1); fprintf(fp, "Plane Surface(%d) = {%d};\n", s++, ll - 1); } } fprintf(fp, "Physical Surface(%d) = {%d:%d};\n", ps++, sbeg, s - 1); fprintf(fp, "Plane Surface(%d) = {%d, %d:%d};\n", s++, (*fit)->tag(), llbeg, ll - 1); fprintf(fp, "Physical Surface(%d) = {%d};\n", ps++, s - 1); } fclose(fp); return v; }
void GMSH_ProbePlugin::draw(void *context) { #if defined(HAVE_OPENGL) int num = (int)ProbeOptions_Number[3].def; if(num < 0) num = iview; if(num >= 0 && num < (int)PView::list.size()){ double x = ProbeOptions_Number[0].def; double y = ProbeOptions_Number[1].def; double z = ProbeOptions_Number[2].def; drawContext *ctx = (drawContext*)context; glColor4ubv((GLubyte *) & CTX::instance()->color.fg); glLineWidth((float)CTX::instance()->lineWidth); SBoundingBox3d bb = PView::list[num]->getData()->getBoundingBox(); if(x >= bb.min().x() && x <= bb.max().x() && y >= bb.min().y() && y <= bb.max().y() && z >= bb.min().z() && z <= bb.max().z()){ // we're inside the bounding box: draw a large cross glBegin(GL_LINES); glVertex3d(bb.min().x(), y, z); glVertex3d(bb.max().x(), y, z); glVertex3d(x, bb.min().y(), z); glVertex3d(x, bb.max().y(), z); glVertex3d(x, y, bb.min().z()); glVertex3d(x, y, bb.max().z()); glEnd(); } else{ // draw 10-pixel marker double d = 10 * ctx->pixel_equiv_x / ctx->s[0]; glBegin(GL_LINES); glVertex3d(x - d, y, z); glVertex3d(x + d, y, z); glVertex3d(x, y - d, z); glVertex3d(x, y + d, z); glVertex3d(x, y, z - d); glVertex3d(x, y, z + d); glEnd(); } ctx->drawSphere(CTX::instance()->pointSize, x, y, z, 1); } #endif }
PView *GMSH_TriangulatePlugin::execute(PView *v) { int iView = (int)TriangulateOptions_Number[0].def; PView *v1 = getView(iView, v); if(!v1) return v; PViewData *data1 = v1->getData(); if(data1->hasMultipleMeshes()){ Msg::Error("Triangulate plugin cannot be applied to multi-mesh views"); return v1; } // create list of points with associated data std::vector<MVertex*> points; int numSteps = data1->getNumTimeSteps(); for(int ent = 0; ent < data1->getNumEntities(0); ent++){ for(int ele = 0; ele < data1->getNumElements(0, ent); ele++){ if(data1->skipElement(0, ent, ele)) continue; if(data1->getNumNodes(0, ent, ele) != 1) continue; int numComp = data1->getNumComponents(0, ent, ele); double x, y, z; data1->getNode(0, ent, ele, 0, x, y, z); PointData *p = new PointData(x, y, z, numComp * numSteps); for(int step = 0; step < numSteps; step++) for(int comp = 0; comp < numComp; comp++) data1->getValue(step, ent, ele, 0, comp, p->v[3 + numComp * step + comp]); points.push_back(p); } } if(points.size() < 3){ Msg::Error("Need at least 3 points to triangulate"); for(unsigned int i = 0; i < points.size(); i++) delete points[i]; return v1; } // project points onto plane discreteFace *s = new discreteFace (GModel::current(), GModel::current()->getNumFaces() + 1); s->computeMeanPlane(points); double plan[3][3]; s->getMeanPlaneData(plan); for(unsigned int i = 0; i < points.size(); i++) project(points[i], plan); delete s; // get lc SBoundingBox3d bbox; for(unsigned int i = 0; i < points.size(); i++) bbox += points[i]->point(); double lc = norm(SVector3(bbox.max(), bbox.min())); // build a point record structure for the divide and conquer algorithm DocRecord doc(points.size()); for(unsigned int i = 0; i < points.size(); i++){ double XX = CTX::instance()->mesh.randFactor * lc * (double)rand() / (double)RAND_MAX; double YY = CTX::instance()->mesh.randFactor * lc * (double)rand() / (double)RAND_MAX; doc.points[i].where.h = points[i]->x() + XX; doc.points[i].where.v = points[i]->y() + YY; doc.points[i].adjacent = NULL; doc.points[i].data = (void*)points[i]; } // triangulate doc.MakeMeshWithPoints(); // create output (using unperturbed data) PView *v2 = new PView(); PViewDataList *data2 = getDataList(v2); for(int i = 0; i < doc.numTriangles; i++){ PointData *p[3]; p[0] = (PointData*)doc.points[doc.triangles[i].a].data; p[1] = (PointData*)doc.points[doc.triangles[i].b].data; p[2] = (PointData*)doc.points[doc.triangles[i].c].data; int numComp = 0; std::vector<double> *vec = 0; if((int)p[0]->v.size() == 3 + 9 * numSteps && (int)p[1]->v.size() == 3 + 9 * numSteps && (int)p[2]->v.size() == 3 + 9 * numSteps){ numComp = 9; data2->NbTT++; vec = &data2->TT; } else if((int)p[0]->v.size() == 3 + 3 * numSteps && (int)p[1]->v.size() == 3 + 3 * numSteps && (int)p[2]->v.size() == 3 + 3 * numSteps){ numComp = 3; data2->NbVT++; vec = &data2->VT; } else{ numComp = 1; data2->NbST++; vec = &data2->ST; } for(int nod = 0; nod < 3; nod++) vec->push_back(p[nod]->v[0]); for(int nod = 0; nod < 3; nod++) vec->push_back(p[nod]->v[1]); for(int nod = 0; nod < 3; nod++) vec->push_back(p[nod]->v[2]); for(int step = 0; step < numSteps; step++) for(int nod = 0; nod < 3; nod++) for(int comp = 0; comp < numComp; comp++) vec->push_back(p[nod]->v[3 + numComp * step + comp]); } for(unsigned int i = 0; i < points.size(); i++) delete points[i]; for(int i = 0; i < data1->getNumTimeSteps(); i++) data2->Time.push_back(data1->getTime(i)); data2->setName(data1->getName() + "_Triangulate"); data2->setFileName(data1->getName() + "_Triangulate.pos"); data2->finalize(); return v2; }
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); }