void Tesselation3D::__refresh_cpu() { // z: number indices from zero // v: generate voronoi // Q: quiet // ee: generate edges (NOTE: e -> subedges breaks) // nn: neighbor list (needed for adjtetlist) // f: write faces (also needed for nn to work) out->deinitialize(); out->initialize(); try { tetrahedralize("nnfzee", inp, out); } catch (int) { luaL_error(__lua_state, "need to load some data before tesselating"); } // --------------------------------------------------------------------------- // Refresh the output data sources // --------------------------------------------------------------------------- std::vector<GLfloat> verts; std::vector<GLuint> indtri; std::vector<GLuint> indseg; int leftout=0; for (int n=0; n<3*out->numberofpoints; ++n) { verts.push_back(out->pointlist[n]); } for (int n=0; n<out->numberoftrifaces; ++n) { // if (out->adjtetlist[2*n] != -1 && out->adjtetlist[2*n+1] != -1) { // if ((double)rand() / RAND_MAX < 0.01) { if (1) { indtri.push_back(out->trifacelist[3*n+0]); indtri.push_back(out->trifacelist[3*n+1]); indtri.push_back(out->trifacelist[3*n+2]); } else { ++leftout; } } for (int n=0; n<2*out->numberofedges; ++n) { indseg.push_back(out->edgelist[n]); } printf("leftout=%d\n", leftout); int N[2] = { verts.size()/3, 3 }; __output_ds["triangles"]->set_data(&verts[0], N, 2); __output_ds["triangles"]->set_indices(&indtri[0], indtri.size()); __output_ds["segments"]->set_data(&verts[0], N, 2); __output_ds["segments"]->set_indices(&indseg[0], indseg.size()); }
MeshData *TetGenCaller::Execute() { STATUS("\n== Create tet-mesh with TetGen ===================================\n", 0); tetgenio in, out; CopyMeshFromSelf(&in); tetrahedralize((char *) "pq2/10AV", &in, &out, NULL); //pq1.414a0.1 //tetrahedralize( ( char * ) "AVq1.5/15CC", & in, & out, NULL ); //pq1.414a0.1 STATUS("==================================================================\n\n", 0); return CopyTetMesh(&out); }
void TetGenCaller::TestMesh() { STATUS("\n== Test mesh with TetGen =========================================\n", 0); tetgenio in, out; CopyMeshFromSelf(&in); tetrahedralize((char *) "pd", &in, &out); if (out.numberoftrifaces > 0) { STATUS("Check failed\n", 0); for (int i = 0; i < out.numberoftrifaces; i++) { int marker = out.trifacemarkerlist[i]; STATUS ("\t%u\n", marker); } throw (0); } STATUS("==================================================================\n\n", 0); }
void TetGenWrapper::run_tetgen() { // Call tetrahedralize from the TetGen library. tetrahedralize(&tetgen_be, &tetgen_data, tetgen_output); }
bool createSkeletonMesh(cGELMesh *a_object, char *a_filename, char *a_filenameHighRes) { a_object->m_useSkeletonModel = true; a_object->m_useMassParticleModel = false; a_object->loadFromFile(a_filenameHighRes); cGELMesh* model = new cGELMesh(world); tetgenio input; if (input.load_off(a_filename)) { // use TetGen to tetrahedralize our mesh tetgenio output; tetrahedralize(TETGEN_SWITCHES, &input, &output); // create a vertex in the object for each point of the result for (int p = 0, pi = 0; p < output.numberofpoints; ++p, pi += 3) { cVector3d point; point.x = output.pointlist[pi+0]; point.y = output.pointlist[pi+1]; point.z = output.pointlist[pi+2]; model->newVertex(point); } // create a triangle for each face on the surface for (int t = 0, ti = 0; t < output.numberoftrifaces; ++t, ti += 3) { cVector3d p[3]; int vi[3]; for (int i = 0; i < 3; ++i) { int tc = output.trifacelist[ti+i]; vi[i] = tc; int pi = tc*3; p[i].x = output.pointlist[pi+0]; p[i].y = output.pointlist[pi+1]; p[i].z = output.pointlist[pi+2]; } //unsigned int index = a_object->newTriangle(p[1], p[0], p[2]); model->newTriangle(vi[1], vi[0], vi[2]); } // find out exactly which vertices are on the inside and outside set<int> inside, outside; for (int t = 0; t < output.numberoftrifaces * 3; ++t) { outside.insert(output.trifacelist[t]); } for (int p = 0; p < output.numberofpoints; ++p) { if (outside.find(p) == outside.end()) inside.insert(p); } model->computeAllNormals(); // compute a boundary box model->computeBoundaryBox(true); // get dimensions of object double size = cSub(model->getBoundaryMax(), model->getBoundaryMin()).length(); // resize object to screen if (size > 0) { model->scale( 1.5 / size); a_object->scale( 1.5 / size); } // setup default values for nodes cGELSkeletonNode::default_radius = 0.05; cGELSkeletonNode::default_kDampingPos = 0.3; cGELSkeletonNode::default_kDampingRot = 0.1; cGELSkeletonNode::default_mass = 0.002; // [kg] cGELSkeletonNode::default_showFrame = false; cGELSkeletonNode::default_color.set(1.0, 0.6, 0.6); cGELSkeletonNode::default_useGravity = true; cGELSkeletonNode::default_gravity.set(0.00, 0.00, -3.45); radius = cGELSkeletonNode::default_radius; a_object->buildVertices(); model->buildVertices(); vector<cGELSkeletonNode*> nodes; int i=0; for (set<int>::iterator it = inside.begin(); it != inside.end(); ++it) { cGELSkeletonNode* newNode = new cGELSkeletonNode(); a_object->m_nodes.push_front(newNode); cVertex* vertex = model->getVertex(*it); newNode->m_pos = vertex->getPos(); newNode->m_rot.identity(); newNode->m_radius = 0.1; newNode->m_fixed = false; vertex->m_tag = i; i++; nodes.push_back(newNode); } // get all the edges of our tetrahedra set< pair<int,int> > springs; for (int t = 0, ti = 0; t < output.numberoftetrahedra; ++t, ti += 4) { // store each edge of the tetrahedron as a pair of indices for (int i = 0; i < 4; ++i) { int v0 = output.tetrahedronlist[ti+i]; for (int j = i+1; j < 4; ++j) { int v1 = output.tetrahedronlist[ti+j]; // connect only if both points are inside if (inside.find(v0) != inside.end() && inside.find(v1) != inside.end()) springs.insert(pair<int,int>(min(v0,v1), max(v0,v1))); } } } // setup default values for links cGELSkeletonLink::default_kSpringElongation = 100.0; // [N/m] cGELSkeletonLink::default_kSpringFlexion = 0.1; // [Nm/RAD] cGELSkeletonLink::default_kSpringTorsion = 0.1; // [Nm/RAD] cGELSkeletonLink::default_color.set(0.2, 0.2, 1.0); for (set< pair<int,int> >::iterator it = springs.begin(); it != springs.end(); ++it) { cVertex* v0 = model->getVertex(it->first); cVertex* v1 = model->getVertex(it->second); cGELSkeletonNode* n0 = nodes[v0->m_tag]; cGELSkeletonNode* n1 = nodes[v1->m_tag]; cGELSkeletonLink* newLink = new cGELSkeletonLink(n0, n1); a_object->m_links.push_front(newLink); } a_object->connectVerticesToSkeleton(false); cMaterial mat; mat.m_ambient.set(0.7, 0.7, 0.7); mat.m_diffuse.set(0.8, 0.8, 0.8); mat.m_specular.set(0.0, 0.0, 0.0); a_object->setMaterial(mat, true); return (true); } return (false); }
bool createTetGenMesh(cGELMesh *a_object, char *a_filename, char *a_filenameHighRes) { a_object->m_useSkeletonModel = false; a_object->m_useMassParticleModel = true; cGELMesh* model = new cGELMesh(world); model->loadFromFile(a_filenameHighRes); tetgenio input; if (input.load_off(a_filename)) { // use TetGen to tetrahedralize our mesh tetgenio output; tetrahedralize(TETGEN_SWITCHES0, &input, &output); // create a vertex in the object for each point of the result for (int p = 0, pi = 0; p < output.numberofpoints; ++p, pi += 3) { cVector3d point; point.x = output.pointlist[pi+0]; point.y = output.pointlist[pi+1]; point.z = output.pointlist[pi+2]; a_object->newVertex(point); } // create a triangle for each face on the surface set<int> outside; for (int t = 0, ti = 0; t < output.numberoftrifaces; ++t, ti += 3) { cVector3d p[3]; int vi[3]; for (int i = 0; i < 3; ++i) { int tc = output.trifacelist[ti+i]; outside.insert(tc); vi[i] = tc; int pi = tc*3; p[i].x = output.pointlist[pi+0]; p[i].y = output.pointlist[pi+1]; p[i].z = output.pointlist[pi+2]; } //unsigned int index = a_object->newTriangle(p[1], p[0], p[2]); a_object->newTriangle(vi[1], vi[0], vi[2]); } a_object->computeAllNormals(); // compute a boundary box a_object->computeBoundaryBox(true); // get dimensions of object double size = cSub(a_object->getBoundaryMax(), a_object->getBoundaryMin()).length(); // resize object to screen if (size > 0) { model->scale(1.5 / size); a_object->scale(1.5 / size); } // build dynamic vertices cGELMassParticle::default_mass = 0.002; cGELMassParticle::default_kDampingPos = 4.0; cGELMassParticle::default_gravity.set(0,0,-0.1); a_object->buildVertices(); // get all the edges of our tetrahedra set< pair<int,int> > springs; for (int t = 0, ti = 0; t < output.numberoftetrahedra; ++t, ti += 4) { // store each edge of the tetrahedron as a pair of indices for (int i = 0; i < 4; ++i) { int v0 = output.tetrahedronlist[ti+i]; for (int j = i+1; j < 4; ++j) { int v1 = output.tetrahedronlist[ti+j]; springs.insert(pair<int,int>(min(v0,v1), max(v0,v1))); } } } // create a spring on each tetrahedral edge we found in the output cGELLinearSpring::default_kSpringElongation = 40.0; // 0.55; for (set< pair<int,int> >::iterator it = springs.begin(); it != springs.end(); ++it) { cVertex* v0 = a_object->getVertex(it->first); cVertex* v1 = a_object->getVertex(it->second); cGELMassParticle* m0 = a_object->m_gelVertices[v0->m_tag].m_massParticle; cGELMassParticle* m1 = a_object->m_gelVertices[v1->m_tag].m_massParticle; cGELLinearSpring* spring = new cGELLinearSpring(m0, m1); a_object->m_linearSprings.push_back(spring); } // extract texture int numModelV = model->getNumVertices(true); for (set<int>::iterator it = outside.begin(); it != outside.end(); ++it) { cVertex *v = a_object->getVertex(*it); cVertex *t = 0; double closest = 1e10; for (int j = 0; j < numModelV; ++j) { cVertex *test = model->getVertex(j, true); double d = cDistanceSq(v->getPos(), test->getPos()); if (d < closest) { closest = d; t = test; } } v->setTexCoord(t->getTexCoord()); } cMesh* mesh = (cMesh*)model->getChild(0); mesh->m_texture->setWrapMode(GL_CLAMP, GL_CLAMP); a_object->setTexture(mesh->m_texture, true); a_object->setUseTexture(true, true); cMaterial mat; mat.m_ambient.set(0.7, 0.7, 0.7); mat.m_diffuse.set(0.8, 0.8, 0.8); mat.m_specular.set(0.0, 0.0, 0.0); a_object->setMaterial(mat, true); return (true); } return (false); }
Polyhedron_triangulation::Polyhedron_triangulation(const std::vector<Packing_polyhedron>& objects, const Packing_polyhedron& container) : nb_groups(0) { typedef Packing_polyhedron::Point_3 Point_3; typedef Packing_polyhedron::Vertex_const_iterator Vertex_const_iterator; typedef Packing_polyhedron::Facet_const_iterator Facet_const_iterator; tetgenio bndmesh; bndmesh.firstnumber = 0; bndmesh.numberofpoints = 0; bndmesh.numberoffacets = 0; for (size_t i = 0; i < objects.size(); i++) { bndmesh.numberofpoints += objects[i].size_of_vertices(); bndmesh.numberoffacets += objects[i].size_of_facets(); } bndmesh.numberofpoints += container.size_of_vertices(); bndmesh.numberoffacets += container.size_of_facets(); bndmesh.pointlist = new REAL[bndmesh.numberofpoints * 3]; bndmesh.pointmarkerlist = new int[bndmesh.numberofpoints]; int *marker_ptr = bndmesh.pointmarkerlist; REAL *pnt_ptr = bndmesh.pointlist; // construct point list for (size_t i = 0; i < objects.size(); i++) { for (Vertex_const_iterator vit = objects[i].vertices_begin(); vit != objects[i].vertices_end(); ++vit) { Point_3 v = vit->point(); *pnt_ptr++ = v.x(); *pnt_ptr++ = v.y(); *pnt_ptr++ = v.z(); *marker_ptr++ = i; } nb_groups++; } for (Vertex_const_iterator vit = container.vertices_begin(); vit != container.vertices_end(); ++vit) { Point_3 v = vit->point(); *pnt_ptr++ = v.x(); *pnt_ptr++ = v.y(); *pnt_ptr++ = v.z(); *marker_ptr++ = -1; } // construct facets bndmesh.facetlist = new tetgenio::facet[bndmesh.numberoffacets]; //bndmesh.facetmarkerlist = new int[bndmesh.numberoffacets]; bndmesh.facetmarkerlist = NULL; tetgenio::facet *fct_ptr = bndmesh.facetlist; for (size_t i = 0; i < objects.size(); i++) { for (Facet_const_iterator fit = objects[i].facets_begin(); fit != objects[i].facets_end(); ++fit) { fct_ptr->numberofpolygons = 1; fct_ptr->polygonlist = new tetgenio::polygon[fct_ptr->numberofpolygons]; fct_ptr->numberofholes = 0; fct_ptr->holelist = NULL; tetgenio::polygon *p = fct_ptr->polygonlist; p->numberofvertices = 3; // assume triangle polyhedra p->vertexlist = new int[3]; Packing_polyhedron::Halfedge_const_handle hh = fit->halfedge(); p->vertexlist[0] = hh->vertex()->idx; hh = hh->next(); p->vertexlist[1] = hh->vertex()->idx; hh = hh->next(); p->vertexlist[2] = hh->vertex()->idx; ++fct_ptr; } } for (Facet_const_iterator fit = container.facets_begin(); fit != container.facets_end(); ++fit) { fct_ptr->numberofpolygons = 1; fct_ptr->polygonlist = new tetgenio::polygon[fct_ptr->numberofpolygons]; fct_ptr->numberofholes = 0; fct_ptr->holelist = NULL; tetgenio::polygon *p = fct_ptr->polygonlist; std::list<Packing_polyhedron::Vertex_const_handle> verts; p->numberofvertices = 0; // assume triangle polyhedra Packing_polyhedron::Halfedge_const_handle hh = fit->halfedge(), hs; hs = hh; do { p->numberofvertices++; verts.push_back(hh->vertex()); hh = hh->next(); } while (hh != hs); p->vertexlist = new int[p->numberofvertices]; int *vl_ptr = p->vertexlist; for (std::list<Packing_polyhedron::Vertex_const_handle>::const_iterator it = verts.begin(); it != verts.end(); ++it) *vl_ptr++ = (*it)->idx; ++fct_ptr; } //std::fill(bndmesh.facetmarkerlist, bndmesh.facetmarkerlist + bndmesh.numberoffacets, 0); tetrahedralize("pnY", &bndmesh, &tetra_mesh); //std::cout<<"Number of tetrahedra in tetrahedron mesh: " <<tetra_mesh.numberoftetrahedra<<std::endl; // debug //for (int i = 0; i < bndmesh.numberofpoints; i++) // assert(bndmesh.pointmarkerlist[i] == tetra_mesh.pointmarkerlist[i]); //vtx_groups.resize(nb_group); //for (int i = 0; i < tetra_mesh.numberofpoints; i++) // vtx_groups[tetra cat_cells.resize(nb_groups); extract_CAT(); }
/* * *************************************************************************** * Routine: GemMesh_fromSurfaceMeshes * * Author: Johan Hake ([email protected]) * * Purpose: Use tetgen to generate a GemMesh from a surface mesh * *************************************************************************** */ GemMesh* GemMesh_fromSurfaceMeshes(SurfaceMesh** surfmeshes, int num_surface_meshes, char* tetgen_params) { unsigned int j, sm_index, num_vertices = 0, num_faces = 0; unsigned int num_regions = 0, num_holes = 0; SurfaceMesh* surfmesh; FLTVECT normal, midpoint; INT3VECT face0; tetgenio in, out; tetgenio::facet *f; tetgenio::polygon *p; in.firstnumber = 1; // Collect info from the surface meshes for (sm_index=0; sm_index<num_surface_meshes; sm_index++) { // Get the surface mesh surfmesh = surfmeshes[sm_index]; // Check if neighborlist is created if (surfmesh->neighbor_list == NULL) SurfaceMesh_createNeighborlist(surfmesh); if (surfmesh->num_vertices == 0 || surfmesh->num_faces == 0) { printf("The %d:th surface mesh is empty. Abandoning "\ "tetrahedralization.\n", sm_index); return GemMesh_ctor(0, 0, false); } if (!surfmesh->closed) { printf("The %d:th surface mesh is not closed. Abandoning "\ "tetrahedralization.\n", sm_index); return GemMesh_ctor(0, 0, false); } // Bump counters if (!surfmesh->as_hole) num_regions += 1; else num_holes += 1; num_vertices += surfmesh->num_vertices; num_faces += surfmesh->num_faces; } // We need at least one region if (num_regions < 1) { printf("Expected at least one surface mesh which is not a hole.\n"); return GemMesh_ctor(0, 0, false); } // Assign memory printf("num vertices: %d\n", num_vertices); printf("num faces: %d\n", num_faces); in.numberofpoints = num_vertices; in.pointlist = new REAL[in.numberofpoints * 3]; in.numberoffacets = num_faces; in.facetlist = new tetgenio::facet[in.numberoffacets]; in.facetmarkerlist = new int[in.numberoffacets]; printf("num regions: %d\n", num_regions); in.numberofregions = num_regions; in.regionlist = new REAL[num_regions*5]; if (num_holes > 0) { printf("num holes: %d\n", num_holes); in.numberofholes = num_holes; in.holelist = new REAL[num_holes*3]; } // Reset counters num_vertices = num_faces = num_regions = num_holes = 0; // Iterate over the surface meshes and assign info for (sm_index=0; sm_index<num_surface_meshes; sm_index++) { // Get the surface mesh surfmesh = surfmeshes[sm_index]; // Assign vertex information for (j = 0; j < surfmesh->num_vertices; j++) { in.pointlist[j*3 + 0 + num_vertices*3] = surfmesh->vertex[j].x; in.pointlist[j*3 + 1 + num_vertices*3] = surfmesh->vertex[j].y; in.pointlist[j*3 + 2 + num_vertices*3] = surfmesh->vertex[j].z; } // Assign face information for (j = 0; j < surfmesh->num_faces; j++) { f = &in.facetlist[j+num_faces]; f->holelist = (REAL *) NULL; f->numberofholes = 0; f->numberofpolygons = 1; f->polygonlist = new tetgenio::polygon[f->numberofpolygons]; p = &f->polygonlist[0]; p->numberofvertices = 3; p->vertexlist = new int[p->numberofvertices]; p->vertexlist[0] = surfmesh->face[j].a + in.firstnumber + num_vertices; p->vertexlist[1] = surfmesh->face[j].b + in.firstnumber + num_vertices; p->vertexlist[2] = surfmesh->face[j].c + in.firstnumber + num_vertices; in.facetmarkerlist[j+num_faces] = surfmesh->face[j].m == -1 ? 0 : surfmesh->face[j].m; } // Get region or hole coordinate by using a face face0 = surfmesh->face[0]; // Face normal normal = GetCrossProduct(surfmesh, face0.a, face0.b, face0.c); // Midpoint of face midpoint.x = surfmesh->vertex[face0.a].x/3; midpoint.y = surfmesh->vertex[face0.a].y/3; midpoint.z = surfmesh->vertex[face0.a].z/3; midpoint.x += surfmesh->vertex[face0.b].x/3; midpoint.y += surfmesh->vertex[face0.b].y/3; midpoint.z += surfmesh->vertex[face0.b].z/3; midpoint.x += surfmesh->vertex[face0.c].x/3; midpoint.y += surfmesh->vertex[face0.c].y/3; midpoint.z += surfmesh->vertex[face0.c].z/3; // Weight based on length double weight = sqrt(pow(surfmesh->vertex[face0.a].x-\ surfmesh->vertex[face0.b].x, 2) + \ pow(surfmesh->vertex[face0.a].y-\ surfmesh->vertex[face0.b].y, 2) + \ pow(surfmesh->vertex[face0.a].z-\ surfmesh->vertex[face0.b].z, 2)); // Add region information if (!surfmesh->as_hole) { // Calculate region info using face information // FIXME: Why should we add the normal values? // FIXME: If normal is pointing outwards we should substract to // FIXME: get a point inside the surface mesh.... in.regionlist[num_regions*5 + 0] = midpoint.x + normal.x*weight; in.regionlist[num_regions*5 + 1] = midpoint.y + normal.y*weight; in.regionlist[num_regions*5 + 2] = midpoint.z + normal.z*weight; // Set region marker (attribute) in.regionlist[num_regions*5 + 3] = surfmesh->marker; // If volume constraints if (surfmesh->use_volume_constraint) { printf("Volume constraint: %.5f\n", surfmesh->volume_constraint); in.regionlist[num_regions*5 + 4] = surfmesh->volume_constraint; } else in.regionlist[num_regions*5 + 4] = -1; // Bump counter num_regions += 1; } else { // Calculate hole info using face information in.holelist[num_holes*3 + 0] = midpoint.x + normal.x*weight; in.holelist[num_holes*3 + 1] = midpoint.y + normal.y*weight; in.holelist[num_holes*3 + 2] = midpoint.z + normal.z*weight; // Bump counter num_holes += 1; } // Bump face and vertex counters num_vertices += surfmesh->num_vertices; num_faces += surfmesh->num_faces; } // Add boundary marker on each node // FIXME: Why? Aren't the markers set on the generatedmesh? in.pointmarkerlist = new int[in.numberofpoints]; for (j = 0; j < in.numberofpoints; j++) in.pointmarkerlist[j] = 1; // Debug in.save_nodes("plc"); in.save_poly("plc"); // Call TetGen tetrahedralize(tetgen_params, &in, &out, NULL); // Debug out.save_nodes("result"); out.save_elements("result"); out.save_faces("result"); // Convert to a generalized tetrahedral mesh structure return GemMesh_fromTetgen(out); }
void GUICutRenderWindow::renderImage(wxImage* image) { //Speichern der Zeit für die Laufzeitmessung timeval tm1; gettimeofday(&tm1, NULL); int width = imgWidthEdit->GetValue(); int height = imgHeightEdit->GetValue(); //aktualisieren der Skala canvas->getScalePanel()->refresh(width, height); //die Anzahl der zur Berechnung zu verwendenden Kerne core_count = threadcountedit->GetValue(); /* * Versuchen, die Interpolation durch vorgezogenes Testen des zuletzt verwendeten Tetraeders zu beschleunigen. * Diese Option ist verursacht Ungenauigkeiten und bietet zumeist wenig Performancegewinn. * Sie ist deshalb standardmäßig deaktiviert und nicht über die Programmoberfläche aktivierbar. */ bool use_last_tet = false; //zurücksetzen der Grafik delete image; image = new wxImage(width, height, true); image->InitAlpha(); //Punkt als Dezimaltrennzeichen setlocale(LC_NUMERIC, "C"); //Eigenschaften der Temperaturverteilung CutRender_info* info = getCutRenderProperties(); Triangle* tri = info->tri; //X-Achse der Ebene im 3D-Raum Vector3D* xvec = tri->getV2()->copy(); xvec->sub(tri->getV1()); //Normale der Ebene Vector3D* tri_nor = tri->getNormal(); //Y-Achse der Ebene im 3D-Raum Vector3D* yvec = xvec->crossProduct(tri_nor); delete tri_nor; xvec->normalize(); yvec->normalize(); //Das aktive Objekt ObjectData* obj = wxGetApp().getActiveObject(); //Erstellen möglichst einfacher Geometrien für die Materialien vector<tetgenio*> bases(obj->getMaterials()->size()); for (unsigned int i = 0; i < obj->getMaterials()->size(); i++) { tetgenio* tri_io = new tetgenio(); string args = "Q"; tetrahedralize(const_cast<char*>(args.c_str()), obj->getMaterials()->at(i).tetgeninput, tri_io, NULL, NULL); bases.at(i) = tri_io; } //Zurücksetzen des Datenarrays für die Temperaturverteilung if (value_img != NULL) { delete[] value_img; } value_img = new float[width * height]; //Verknüpfen der Ausgabe mit den Temperaturverteilungsdaten und der Grafik canvas->setImage(image); canvas->setValueImg(value_img); //Erstellen des Statusregisters für die Berechnungsthreads bool thread_running[core_count]; for (int i = 0; i < core_count; i++) { thread_running[i] = 1; } //Array für die Thread-Objekts vector<thread*> threads = vector<thread*>(0); //Array für die Kopierten Sensordaten. Das Kopieren ist erforderlich, da die Threads die Daten verändern (sortieren). vector<vector<SensorPoint>> copied_sensor_data = vector<vector<SensorPoint>>(core_count); //Höhe für die Streifen, die die einzelnen Threads berechnen int delta_h = height / core_count; //Für alle Threads... for (int i = 0; i < core_count; i++) { //Die Starthöhe des Threads in der Temperaturverteilung int startheight = delta_h * i; //eventuelle Korrektur der Streifenhöhe für den letzten Thread if (i == core_count - 1) { if (startheight + delta_h < height) { delta_h = height - startheight; } } //Aktueller Sensordatensatz SensorData* dataset = &obj->getSensorDataList()->at( obj->getCurrentSensorIndex()); vector<SensorPoint>* original_sd = &dataset->data.at( dataset->current_time_index); copied_sensor_data.at(i).resize(original_sd->size()); //Kopieren der Sensordaten den Thread for (int p = 0; p < int(original_sd->size()); p++) { copySensorPoint(&original_sd->at(p), &copied_sensor_data.at(i).at(p)); } //Starten des Threads threads.resize(threads.size() + 1, new thread(render_thread, &thread_running[i], value_img, image, width, height, startheight, delta_h, info, xvec, yvec, tri->getV1(), &bases, obj, &copied_sensor_data.at(i), use_last_tet)); } //Pfüfzahl, ob noch Threads laufen unsigned int running = 0; //Solange threads laufen... do { //Ausgabe aktualisieren canvas->Update(); canvas->Refresh(); //ermitteln der Pfüfzahl, ob noch Threads laufen. Wenn diese 0 bleibt, sind alle Threads fertig. running = 0; for (int i = 0; i < core_count; i++) { running = running << 1; running += thread_running[i]; }; } while (running); //Threads zusammenführen for (int i = 0; i < core_count; i++) { threads.at(i)->join(); delete threads.at(i); } //Freigeben des Ebenendreiecks for (int i = 0; i < 3; i++) { delete tri->getVert(i); } delete tri; //Zeitmessung beenden timeval tm2; gettimeofday(&tm2, NULL); unsigned long long t = 1000 * (tm2.tv_sec - tm1.tv_sec) + (tm2.tv_usec - tm1.tv_usec) / 1000; //Ausgeben der Berechnungsdauer auf SetTitle( wxT( "Berechnung abgeschlossen. ( ") + floattowxstr(t / 1000.)+wxT( "s )")); //Freigeben der Ressourcen delete xvec; delete yvec; for (unsigned int i = 0; i < obj->getMaterials()->size(); i++) { delete bases.at(i); } delete info; }
//弾性体用 メッシュ生成 void tetgen_function::TetGen_elastic(mpsconfig &CON, vector<mpselastic> &PART, int fluid_number, int particle_number, vector<tetgen_node> &NODEall, vector<tetgen_facet> &FACEall, vector<tetgen_element> &ELEMall, vector<int> &TRANS) { //tetgenioクラス宣言と初期化 tetgenio in, out; in.initialize(); out.initialize(); //TetGen設定クラス tetgen_config TET; //全体配列初期化 NODEall.clear(); FACEall.clear(); //各部品用配列(使い回し) vector<tetgen_node> NODE; vector<tetgen_facet> FACE; ////////////エラストマー領域//////////// NODE.clear(); FACE.clear(); SetElastBoundary(CON, PART, TET, NODE, FACE); SetTRANS(NODE, TRANS); //粒子が節点に対応する時に実行??? AddBoundaryData(CON, NODEall, FACEall, NODE, FACE, MAGELAST);//* //////////////電磁石領域///////////// NODE.clear(); FACE.clear(); SetMagnetBoundary(CON, TET, NODE, FACE); AddBoundaryData(CON, NODEall, FACEall, NODE, FACE, MAGNET);//*/ /////////////コイル領域////////////// /*NODE.clear(); FACE.clear(); SetCOILBoundary(CON, TET, NODE, FACE); AddBoundaryData(CON, NODEall, FACEall, NODE, FACE, COIL);*/ ////////////鉄心領域///////////////////* /*NODE.clear(); FACE.clear(); SetIRONBoundary(CON, TET, NODE, FACE); AddBoundaryData(CON, NODEall, FACEall, NODE, FACE, IRON);*/ ////////////空気領域//////////// NODE.clear(); FACE.clear(); SetAirBoundary(CON, TET, NODE, FACE); AddBoundaryData(CON, NODEall, FACEall, NODE, FACE, AIR); /* //////////////空気領域追加節点//////////// NODE.clear(); FACE.clear(); SetAirFineBoundary(CON, PART, TET, NODE, FACE); AddBoundaryData(CON, NODEall, FACEall, NODE, FACE, AIR); //*/ //.nodeファイル作成 MakeNodeFile(CON, NODEall, "all_boundary.node"); //.polyファイルの出力 MakePolyFile(CON, TET, NODEall, FACEall, "all_boundary.poly"); cout<<"polyファイル読み込み"<<endl; in.load_poly("all_boundary"); //.polyを読み込んだら自動的に.nodeも読み込むらしい cout<<"自動分割開始"<<endl; tetrahedralize("pq1.1a1.0e-4AYYn", &in, &out); //1.1未満では切れない デフォルトはrqa1.1AYYn pq1.3a1.67e-7AYYn out.save_nodes("output"); out.save_elements("output"); //out.save_faces("output"); //out.save_neighbors("output"); //*/ cout<<"材質の修正開始\n"; //cout<<"材質修正"<<endl; //ModifyAttribute(CON, TET, NODEall, ELEMall, in, out); ModifyAttribute_tetgenio(CON, TET, NODEall, ELEMall, in, out); //tetgenioを直接編集 //出力 cout<<"TetView用ファイル出力"<<endl; //MakeNodeFile(CON, NODEall, "output_final.node"); //MakeElemFile(CON, ELEMall, "output_final.ele"); out.save_nodes("output_final"); out.save_elements("output_final"); //節点・要素データ取得 cout<<"TetGenより節点・要素データ取得"<<endl; GetPointList(NODEall, in, out); GetTetrahedronList_full(ELEMall, in, out); }
FTendrModelData UTendrModelTetraGeneratorComponent::Build( const FTendrVertexArray& InputVertices, const FTendrIndexArray& InputIndices, bool bSilent ) { FTendrModelData OutputModelData; if(InputVertices.Num() > 0 && InputIndices.Num() > 0) { if(!bSilent) { GWarn->BeginSlowTask( FText::FromString( TEXT( "Building Tendr model" ) ), true ); } // Generate model { // Debug statistics const uint32 NumSurfaceVerts = InputVertices.Num(); // 1. Tetrahedralization bool ValidModel = false; tetgenio out; // deinitialize (deallocator) is automatically called when these go out of scope { // Tetrahedral model generation { tetgenio in; // deinitialize (deallocator) is automatically called when these go out of scope in.firstnumber = 0; in.numberofpoints = NumSurfaceVerts; in.pointlist = new REAL[ in.numberofpoints * 3 ]; in.pointparamlist = new tetgenio::pointparam[ in.numberofpoints ]; for(int i = 0; i < in.numberofpoints; ++i) { // Store vertices in.pointlist[ i * 3 + 0 ] = InputVertices[ i ].X; in.pointlist[ i * 3 + 1 ] = InputVertices[ i ].Y; in.pointlist[ i * 3 + 2 ] = InputVertices[ i ].Z; // Store UVs (currently not used) tetgenio::pointparam param; param.tag = 0; param.type = 0; for(uint32 t = 0; t < MAX_TEXCOORDS; ++t) { param.uv[ t * 2 + 0 ] = 1; param.uv[ t * 2 + 1 ] = 1; } // Store other per-vertex data (currently not used) param.uv[ 8 + 0 ] = 0; param.uv[ 8 + 1 ] = 0; param.uv[ 8 + 2 ] = 0; param.uv[ 8 + 3 ] = 0; param.uv[ 8 + 4 ] = 0; param.uv[ 8 + 5 ] = 0; in.pointparamlist[ i ] = param; #ifdef TETRA_DEBUG UE_LOG( TendrModelTetraLog, Log, TEXT( "Vertex %u: %.3f, %.3f, %.3f" ), i, InputVertices[ i ].X, InputVertices[ i ].Y, InputVertices[ i ].Z ); #endif } in.numberoffacets = InputIndices.Num() / 3; in.facetlist = new tetgenio::facet[ in.numberoffacets ]; in.facetmarkerlist = new int[ in.numberoffacets ]; for(int i = 0; i < in.numberoffacets; ++i) { in.facetmarkerlist[ i ] = 1; tetgenio::facet& f = in.facetlist[ i ]; f.holelist = NULL; f.numberofholes = 0; f.numberofpolygons = 1; f.polygonlist = new tetgenio::polygon[ f.numberofpolygons ]; tetgenio::polygon& p = f.polygonlist[ 0 ]; p.numberofvertices = 3; p.vertexlist = new int[ p.numberofvertices ]; p.vertexlist[ 0 ] = InputIndices[ i * 3 + 0 ]; p.vertexlist[ 1 ] = InputIndices[ i * 3 + 1 ]; p.vertexlist[ 2 ] = InputIndices[ i * 3 + 2 ]; } in.facetmarkerlist = NULL; UE_LOG( TendrModelTetraLog, Log, TEXT( "Tetrahedralizing mesh (input vertices: %u, triangles: %u)" ), in.numberofpoints, in.numberoffacets ); tetgenbehavior b; { b.zeroindex = 1; b.docheck = 1; b.verbose = 1; b.diagnose = 0; b.facesout = 1; b.edgesout = 1; b.neighout = 1; b.object = tetgenbehavior::POLY; b.plc = 1; b.quality = 1; //b.weighted = 1; //b.no_sort = 1; //b.optscheme = 0; //b.optlevel = 0; // Disable removal of duplicate vertices and faces b.nomergefacet = 1; b.nomergevertex = 1; b.nojettison = 1; // Prevent insertion of vertices on boundary, only interior b.nobisect = 1; b.nobisect_nomerge = 1; //b.supsteiner_level = 0; // UV support b.psc = 1; // Constrain maximum volume of tetras //b.metric = 1; //b.minratio = 10; if(MaximumTetraVolume > 0) { b.maxvolume = MaximumTetraVolume; b.fixedvolume = 1; } } try { // Invoke tetgen { tetrahedralize( &b, &in, &out ); UE_LOG( TendrModelTetraLog, Log, TEXT( "Output mesh done, points: %u, tetras: %u, triangles: %u, edges: %u" ), out.numberofpoints, out.numberoftetrahedra, out.numberoftrifaces, out.numberofedges ); } // Conversion to compatible structures { // // Temporary coarse to sparse map // // Coarse: duplicated vertices, for use in UE4 graphics rendering // Sparse: non-duplicated vertices, for use in physics engine // // This distinction is necessary because UE4 graphics rendering requires the use of duplicated vertices // for vertex data blending, while our physics engine needs to be as sparse as possible for performnace reasons. // TMap<FVector, uint32> TempMapCoarseToSparse; // Iterate over generated points of model for(int i = 0; i < out.numberofpoints; ++i) { // Retrieve vertex FVector Vertex( out.pointlist[ i * 3 + 0 ], out.pointlist[ i * 3 + 1 ], out.pointlist[ i * 3 + 2 ] ); // Store vertex OutputModelData.Vertices.Add( FVector4( Vertex, 0 ) ); // Coarse to sparse mapping algorithm { uint32 IndexSparse = OutputModelData.VerticesPhysics.Num(); // Check if duplicate vertex exists and insert if it doesn't uint32 * pKey = TempMapCoarseToSparse.Find( Vertex ); if(pKey == NULL) { // No duplicate vertex exists // Add to map TempMapCoarseToSparse.Add( Vertex, IndexSparse ); // Initialize dummy connectivity to InvalidIndex FTendrVertexConnectivityData Dummy; memset( Dummy.NeighbourIndices, 0xFF, sizeof( Dummy.NeighbourIndices ) ); OutputModelData.Connectivity.Add( Dummy ); #ifdef TETRA_DEBUG UE_LOG( TendrModelTetraLog, Log, TEXT( "Vertex %u (%.3f, %.3f, %.3f) ++ physics vertex %u" ), i, Vertex.X, Vertex.Y, Vertex.Z, IndexSparse ); #endif // Add vertex to sparse data structure OutputModelData.VerticesPhysics.Add( FVector4( Vertex, 0 ) ); } else { #ifdef TETRA_DEBUG UE_LOG( TendrModelTetraLog, Log, TEXT( "Vertex %u (%.3f, %.3f, %.3f) == physics vertex %u" ), i, Vertex.X, Vertex.Y, Vertex.Z, *pKey ); #endif } // In any case, add mapping OutputModelData.MappingCoarseToSparse.Add( ( pKey == NULL ) ? IndexSparse : (*pKey) ); } } // Iterate over generated triangles of model for(int i = 0; i < out.numberoftrifaces; ++i) { int A = out.trifacelist[ i * 3 + 0 ]; int B = out.trifacelist[ i * 3 + 1 ]; int C = out.trifacelist[ i * 3 + 2 ]; OutputModelData.Indices.Add( A ); OutputModelData.Indices.Add( B ); OutputModelData.Indices.Add( C ); #ifdef TETRA_DEBUG UE_LOG( TendrModelTetraLog, Log, TEXT( "Index %u: %u %u %u" ), i, A, B, C ); #endif } // Output some statistics UE_LOG( TendrModelTetraLog, Log, TEXT( "Input = Indices [%u], Vertices [%u]" ), InputIndices.Num(), NumSurfaceVerts ); UE_LOG( TendrModelTetraLog, Log, TEXT( "Output = Indices [%u], Vertices [%u surface, %u internal, %u physics]" ), OutputModelData.Indices.Num(), NumSurfaceVerts, OutputModelData.Vertices.Num(), OutputModelData.VerticesPhysics.Num() ); // Add connectivity based on edges uint32 MaxNeighbours = 0; for(int i = 0; i < out.numberofedges; ++i) { int a, b; { // Retrieve edge indices (coarse) int coarseA = out.edgelist[ i * 2 + 0 ]; int coarseB = out.edgelist[ i * 2 + 1 ]; // Get corresponding sparse index a = OutputModelData.MappingCoarseToSparse[ coarseA ]; b = OutputModelData.MappingCoarseToSparse[ coarseB ]; // Check for consistency check( a != InvalidIndex ); check( b != InvalidIndex ); // Add to sparse connectivity data structure ConnectivityAddNeighbour( OutputModelData, a, b, MaxNeighbours ); ConnectivityAddNeighbour( OutputModelData, b, a, MaxNeighbours ); } } UE_LOG( TendrModelTetraLog, Log, TEXT( "Maximum neighbours in model: %u" ), MaxNeighbours ); // Mark as valid OutputModelData.Valid = true; } } catch(int error) { switch(error) { case 1: SetError( TEXT( "Not enough memory available or model excessively large" ) ); break; case 3: SetError( TEXT( "Input contains self-intersecting triangles" ) ); break; case 4: case 5: SetError( TEXT( "Input contains triangles that are too small" ) ); break; default: SetError( FString::Printf( TEXT( "Input could not be processed (tetgen error %u)" ), error ) ); break; } } } } } if(!bSilent) { GWarn->EndSlowTask(); } } return OutputModelData; }
// assumes interface will not evolve beyond [-10, 10]^3 and encloses the point (0, 0, 0) TetMesh * TetMeshFactory::from_indexed_face_set(IndexedFaceSet & ifs) { tetgenio * inner_input = IndexedFaceSet::to_tetgenio(ifs); tetgenio * outer_input = IndexedFaceSet::to_tetgenio(ifs); //add outer cube vertices int orig_num_v = outer_input->numberofpoints; outer_input->numberofpoints += 8; REAL * new_vertices = new REAL[outer_input->numberofpoints * 3]; for (int i = 0; i < orig_num_v * 3; i++) { new_vertices[i] = outer_input->pointlist[i]; } // TODO: for robustness, generate size based on bounding sphere static const REAL cube_corners[] = { 10, 10, 10, 10, 10, -10, 10, -10, 10, 10, -10, -10, -10, 10, 10, -10, 10, -10, -10, -10, 10, -10, -10, -10 }; for (int i = 0; i < 8 * 3; i++) { new_vertices[orig_num_v * 3 + i] = cube_corners[i]; } delete[] outer_input->pointlist; outer_input->pointlist = new_vertices; //add outer cube faces int orig_num_f = outer_input->numberoffacets; outer_input->numberoffacets += 6; tetgenio::facet * new_facets = new tetgenio::facet[outer_input->numberoffacets]; delete[] outer_input->facetmarkerlist; outer_input->facetmarkerlist = new int[outer_input->numberoffacets]; for (int i = 0; i < orig_num_f; i++) { new_facets[i] = outer_input->facetlist[i]; } static const int cube_faces[] = { 0, 1, 3, 2, 4, 5, 7, 6, 0, 1, 5, 4, 2, 3, 7, 6, 0, 2, 6, 4, 1, 3, 7, 5 }; for (int i = 0; i < 6; i++) { new_facets[orig_num_f + i].numberofholes = 0; new_facets[orig_num_f + i].holelist = NULL; new_facets[orig_num_f + i].numberofpolygons = 1; new_facets[orig_num_f + i].polygonlist = new tetgenio::polygon[1]; new_facets[orig_num_f + i].polygonlist[0].numberofvertices = 4; new_facets[orig_num_f + i].polygonlist[0].vertexlist = new int[4]; new_facets[orig_num_f + i].polygonlist[0].vertexlist[0] = orig_num_v + cube_faces[i * 4]; new_facets[orig_num_f + i].polygonlist[0].vertexlist[1] = orig_num_v + cube_faces[i * 4 + 1]; new_facets[orig_num_f + i].polygonlist[0].vertexlist[2] = orig_num_v + cube_faces[i * 4 + 2]; new_facets[orig_num_f + i].polygonlist[0].vertexlist[3] = orig_num_v + cube_faces[i * 4 + 3]; } delete[] outer_input->facetlist; outer_input->facetlist = new_facets; // add hole at (0, 0, 0) outer_input->numberofholes = 1; outer_input->holelist = new REAL[3]; outer_input->holelist[0] = 0; outer_input->holelist[1] = 0; outer_input->holelist[2] = 0; tetgenio inner_output; tetgenio outer_output; tetgenbehavior switches; switches.parse_commandline("pYqQ"); tetrahedralize(&switches, inner_input, &inner_output); tetrahedralize(&switches, outer_input, &outer_output); int outer_num_v = outer_output.numberofpoints - orig_num_v; int inner_num_v = inner_output.numberofpoints - orig_num_v; int num_v = orig_num_v + outer_num_v + inner_num_v; std::vector<REAL> vertices; std::vector<REAL> targets; vertices.resize(num_v * 3); targets.resize(num_v * 3); for (int i = 0; i < orig_num_v + inner_num_v; i++) { vec_copy(&vertices[i * 3], &inner_output.pointlist[i * 3]); } for (int i = orig_num_v; i < orig_num_v + outer_num_v; i++) { vec_copy(&vertices[(i + inner_num_v) * 3], &outer_output.pointlist[i * 3]); } for (int i = 0; i < num_v * 3; i++) { targets[i] = vertices[i]; } int inner_num_t = inner_output.numberoftetrahedra; int num_t = outer_output.numberoftetrahedra + inner_num_t; std::vector<unsigned int> tetrahedra; std::vector<status_t> statuses; tetrahedra.resize(num_t * 4); statuses.resize(num_t); for (int i = 0; i < inner_num_t; i++) { for (int j = 0; j < 4; j++) { tetrahedra[i * 4 + j] = inner_output.tetrahedronlist[i * 4 + j]; } statuses[i] = INSIDE; } for (int i = 0; i < outer_output.numberoftetrahedra; i++) { for (int j = 0; j < 4; j++) { tetrahedra[(i + inner_num_t) * 4 + j] = outer_output.tetrahedronlist[i * 4 + j]; if (outer_output.tetrahedronlist[i * 4 + j] >= orig_num_v) { tetrahedra[(i + inner_num_t) * 4 + j] += inner_num_v; } } statuses[i + inner_num_t] = OUTSIDE; } delete inner_input; delete outer_input; std::vector<GeometrySet<unsigned int>> vertex_to_tet(num_v); for (int i = 0; i < num_t; i++) { for (int j = 0; j < 4; j++) { vertex_to_tet[tetrahedra[i * 4 + j]].insert(i); } } return new TetMesh(vertices, targets, tetrahedra, statuses, vertex_to_tet); }
static void to_tcf(const std::string& output_filename, const mqo_reader::document_type& doc, const std::string& physical_name) { std::vector<Primitive> primitives; create_triangle_list(primitives, doc); //////////////////////////////////////////////////////////////// // make tetgenio in tetgenio in, out; in.firstnumber = 0; // vertex count in.numberofpoints = 0; in.numberoffacets = 0; for (const auto& p: primitives) { in.numberofpoints += p.vertices.size(); in.numberoffacets += p.indices.size() / 3; } // store vertices in.pointlist = new REAL[in.numberofpoints * 3]; // 3 = vector x, y, z REAL* vp = in.pointlist; for (const auto& prim: primitives) { for (const auto& vertex: prim.vertices) { *vp++ = vertex.x; *vp++ = vertex.y; *vp++ = vertex.z; } } // store indices in.facetlist = new tetgenio::facet[in.numberoffacets]; int facet_index = 0; for (const auto& prim: primitives) { for (size_t j = 0 ; j < prim.indices.size() ; j += 3) { tetgenio::facet* f = &in.facetlist[facet_index++]; f->numberofpolygons = 1; f->polygonlist = new tetgenio::polygon[1]; f->numberofholes = 0; f->holelist = NULL; tetgenio::polygon* p = &f->polygonlist[0]; p->numberofvertices = 3; p->vertexlist = new int[3]; p->vertexlist[0] = prim.indices[j+0]; p->vertexlist[1] = prim.indices[j+1]; p->vertexlist[2] = prim.indices[j+2]; } } // store facet markers in.facetmarkerlist = new int[in.numberoffacets]; memset(in.facetmarkerlist, 0, sizeof(int)*in.numberoffacets); // Tetrahedralize the PLC. Switches are chosen to read a PLC(p), // do quality mesh generation(q)with a specified quality bound // (1.414), and apply a maximum volume constraint(a0.1). //////////////////////////////////////////////////////////////// // write tetrahedralize("pqi", &in, &out); // Output mesh to files 'barout.node', 'barout.ele' and 'barout.face'. out.save_nodes(const_cast<char*>(output_filename.c_str())); out.save_elements(const_cast<char*>(output_filename.c_str())); out.save_faces(const_cast<char*>(output_filename.c_str())); std::string os = output_filename; std::ofstream ofs(os.c_str()); cat(ofs, os + ".node"); cat(ofs, os + ".ele"); cat(ofs, os + ".face"); _unlink((os + ".node").c_str()); _unlink((os + ".ele").c_str()); _unlink((os + ".face").c_str()); }