예제 #1
0
파일: tesselate.cpp 프로젝트: jzrake/luview
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());
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #4
0
void TetGenWrapper::run_tetgen()
{
  // Call tetrahedralize from the TetGen library.
  tetrahedralize(&tetgen_be, &tetgen_data, tetgen_output);
}
예제 #5
0
파일: 52-GEL-duck.cpp 프로젝트: jateeq/FYDP
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);
}
예제 #6
0
파일: 52-GEL-duck.cpp 프로젝트: jateeq/FYDP
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);
}
예제 #7
0
	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();
	}
예제 #8
0
파일: GemMesh.C 프로젝트: mcellteam/gamer
/*
 * ***************************************************************************
 * 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);

}
예제 #9
0
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;
}
예제 #12
0
// 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);
}
예제 #13
0
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());
}