コード例 #1
0
ファイル: tetmesh_fem.C プロジェクト: davidheryanto/sc14
// Read this mesh from the FEM framework's mesh m
void readFEM(int m,TetMesh &t) {
  int nNode=FEM_Mesh_get_length(m,FEM_NODE);
  int nTet=FEM_Mesh_get_length(m,FEM_ELEM+0);
  t.allocate(nTet, nNode);
  FEM_Mesh_data(m,FEM_NODE,FEM_COORD,t.getPointArray(),0,nNode,FEM_DOUBLE,3);
  FEM_Mesh_data(m,FEM_ELEM+0,FEM_CONN,t.getTetConn(),0,nTet,FEM_INDEX_0,4);
}
コード例 #2
0
ファイル: ComputeMassMat.cpp プロジェクト: Tonsty/Utility
void ComputeMassMat::computeCompactM(SXMatrix &M,const TetMesh& mesh)const{

  const int n = (int)mesh.nodes().size();
  M.resize(n,n);
  for(int i=0;i<(int)mesh.tets().size();i++)
	assembleMass(mesh,mesh.tets()[i],_density[i],M);
}
コード例 #3
0
float
max_dihedral_angle(const TetMesh& mesh)
{
	// Measure maximum dihedral angle of tet mesh.
	float maxAngle = 0.0f;
	for (size_t t = 0; t < mesh.tSize(); ++t) {
        std::vector<float> angles;
        mesh.getTet(t).dihedralAngles(angles);
        for (size_t i = 0; i < angles.size(); ++i) {
		    if (angles[i] > maxAngle) {
			    maxAngle = angles[i];
		    }
        }
	}
	return maxAngle * 180.0f / M_PI;
}
コード例 #4
0
// cut a chunk of the lattice out to roughly match the shape
static void
cut_lattice(const SDF& sdf,
            TetMesh& mesh,
            std::vector<float>& vphi) // phi evaluated at vertices
{
    std::map<Vec3i,int> lattice_map;
    // loop over tiles that overlap bounding box
    int i, j, k;
    for (k=0; k<sdf.phi.nk; k+=4) for (j=0; j<sdf.phi.nj; j+=4) 
      for (i=0; i<sdf.phi.ni; i+=4) {
        for (int t=0; t<num_lattice_tets; ++t) {
            // check this tet is entirely inside the grid & has a negative phi
            bool good_tet = true;
            bool negative_phi = false;
            for (int u=0; u<4; ++u) {
                int a = lattice_node[lattice_tet[t][u]][0]+i;
                if (a >= sdf.phi.ni) { good_tet=false; break; }
                int b = lattice_node[lattice_tet[t][u]][1]+j;
                if (b >= sdf.phi.nj) { good_tet=false; break; }
                int c = lattice_node[lattice_tet[t][u]][2]+k;
                if (c >= sdf.phi.nk) { good_tet=false; break; }
                if (sdf.phi(a,b,c) < 0)
                    negative_phi = true;
            }
            if (good_tet && negative_phi) {
                // add vertices if they don't exist yet, find actual tet to add
                Vec4i actual_tet(-1,-1,-1,-1);
                for (int u=0; u<4; ++u) {
                    Vec3i vertex=lattice_node[lattice_tet[t][u]]+Vec3i(i,j,k);
                    std::map<Vec3i,int>::iterator p = lattice_map.find(vertex);
                    if (p == lattice_map.end()) {
                        actual_tet[u] = mesh.vSize();
                        lattice_map[vertex] = actual_tet[u];
                        mesh.verts().push_back(sdf.origin+sdf.dx*Vec3f(vertex));
                        vphi.push_back(sdf.phi(vertex[0],vertex[1],vertex[2]));
                    } else {
                        actual_tet[u]=p->second;
                    }
                }
                mesh.tets().push_back(actual_tet);
            }
        }
    }
}
コード例 #5
0
ファイル: ComputeMassMat.cpp プロジェクト: Tonsty/Utility
void ComputeMassMat::assembleMass(const TetMesh& mesh,const Vector4i& tet,const SX& density,SXMatrix &M)const{

  SX influence=tetrahedron(mesh.nodes()[tet[0]],mesh.nodes()[tet[1]],
						   mesh.nodes()[tet[2]],mesh.nodes()[tet[3]]).volume()/20.0f;
  influence*=density;

  ADD_INFLUENCE_AD(0,0,M);
  ADD_INFLUENCE_AD(1,1,M);
  ADD_INFLUENCE_AD(2,2,M);
  ADD_INFLUENCE_AD(3,3,M);

  ADD_INFLUENCE_AD(1,0,M);
  ADD_INFLUENCE_AD(2,0,M);
  ADD_INFLUENCE_AD(3,0,M);

  ADD_INFLUENCE_AD(1,2,M);
  ADD_INFLUENCE_AD(2,3,M);
  ADD_INFLUENCE_AD(3,1,M);
}
コード例 #6
0
// assuming vphi[i] and vphi[j] have different signs, find or create a new
// vertex on the edge between them where phi interpolates to zero.
static int
cut_edge(int i, int j,
         TetMesh& mesh,
         std::vector<float> &vphi,
         std::map<Vec2i,int> &cut_map)
{
    assert((vphi[i]<0 && vphi[j]>0) || (vphi[i]>0 && vphi[j]<0));
    Vec2i edge(min(i,j), max(i,j));
    std::map<Vec2i,int>::iterator p = cut_map.find(edge);
    if (p == cut_map.end()) { // this edge hasn't been cut yet?
        int v = (int)mesh.vSize();
        float alpha = vphi[i]/(vphi[i]-vphi[j]);
        mesh.verts().push_back((1-alpha)*mesh.V(i) + alpha*mesh.V(j));
        vphi.push_back(0);
        cut_map[edge] = v;
        return v;
    } else { // already done this edge
        return p->second;
    }
}
コード例 #7
0
// remove tets with corners where phi=0 but are outside the volume
static void
remove_exterior_tets(TetMesh& mesh,
                     const std::vector<float> &vphi,
                     const SDF& sdf)
{
    for (size_t t=0; t<mesh.tSize(); ) {
        int i, j, k, l; assign(mesh.T(t), i, j, k, l);
        assert(vphi[i]<=0 && vphi[j]<=0 && vphi[k]<=0 && vphi[l]<=0);
        if (vphi[i]==0 && vphi[j]==0 && vphi[k]==0 && vphi[l]==0
            && sdf((mesh.V(i)+mesh.V(j)+mesh.V(k)+mesh.V(l))/4)>0) {
            mesh.T(t) = mesh.tets().back();
            mesh.tets().pop_back();
        } else {
            ++t;
        }
    }
}
コード例 #8
0
ファイル: tetmesh_fem.C プロジェクト: davidheryanto/sc14
// Read this mesh from the FEM framework's mesh m and include ghosts
void readGhostFEM(int m,TetMesh &t) {
  int nNode=FEM_Mesh_get_length(m,FEM_NODE);
  int ngNode=FEM_Mesh_get_length(m,FEM_NODE+FEM_GHOST);
  int nTet=FEM_Mesh_get_length(m,FEM_ELEM+0);
  int ngTet=FEM_Mesh_get_length(m,FEM_ELEM+0+FEM_GHOST);
  t.allocate(nTet+ngTet, nNode+ngNode);
  FEM_Mesh_data(m,FEM_NODE,FEM_COORD,t.getPointArray(),0,nNode,FEM_DOUBLE,3);
  FEM_Mesh_data(m,FEM_ELEM+0,FEM_CONN,t.getTetConn(),0,nTet,FEM_INDEX_0,4);
  // add ghost data if it exists
  if (ngTet > 0) {
    FEM_Mesh_data(m,FEM_ELEM+0+FEM_GHOST,FEM_CONN,t.getTet(nTet),0,ngTet, 
		  FEM_INDEX_0,4);
    if (ngNode > 0)
      FEM_Mesh_data(m,FEM_NODE+FEM_GHOST,FEM_COORD,t.getPoint(nNode),0,ngNode,
		    FEM_DOUBLE,3);
  }
  t.nonGhostPt = nNode;
  t.nonGhostTet = nTet;
  // convert ghost node indices from negative to positive
  //printf("nNode=%d ngNode=%d nTet=%d ngTet=%d\n", nNode, ngNode, nTet, ngTet);
  if (ngTet > 0) {
    int *tconn;
    for (int i=nTet; i<ngTet+nTet; i++) {
      tconn = t.getTet(i);
      for (int j=0; j<4; j++) {
	//printf("Tet=%d conn[%d]=%d before conversion.\n", i, j, tconn[j]);
	if (tconn[j] < -1) tconn[j] = (tconn[j]*-1)-2+nNode;
	//printf("Tet=%d conn[%d]=%d after conversion.\n", i, j, tconn[j]);
	assert(tconn[j] < nNode+ngNode);
	assert(!(tconn[j] < -1));
      }
    }
  }
}
コード例 #9
0
int main(int argc, char** argv)
{
  po::variables_map var_map = read_command_line(argc,argv);

  TetMesh mesh;
  string mesh_file = var_map["mesh"].as<string>();
  cout << "Reading in mesh from [" << mesh_file << "]..." << endl;
  mesh.read_cgal(mesh_file);
  mesh.freeze();
  
  cout << "Mesh stats:" << endl;
  cout << "\tNumber of vertices: " << mesh.number_of_vertices() << endl;
  cout << "\tNumber of tetrahedra: " << mesh.number_of_cells() << endl;
  mat bounds = mesh.find_bounding_box();
  vec lb = bounds.col(0);
  vec ub = bounds.col(1);
  cout << "\tLower bound:" << lb.t();
  cout << "\tUpper bound:" << ub.t();


  RoundaboutDubinsCarSimulator dubins = RoundaboutDubinsCarSimulator(DUBINS_ACTIONS);
  bool include_oob = true;
  LCP L = build_lcp(&dubins,
                    &mesh,
                    DUBINS_GAMMA,
                    include_oob);
  //string filename = var_map["lcp"].as<string>();
  //L.write(filename);

  string filename = "/home/epz/data/dubins.lcp";
  L.write(filename);
}
コード例 #10
0
ファイル: ComputeMassMat.cpp プロジェクト: Tonsty/Utility
void ComputeMassMat::compute(SXMatrix &M,const TetMesh&mesh, const vector<SX> &density){
  
  assert_eq(density.size(),mesh.tets().size());
  this->_density = density;

  _M.setZero();
  computeCompactM(_M,mesh);

  const int n = mesh.nodes().size();
  M.resize(n*3,n*3);
  M.setZero();

  for (int i = 0; i < _M.size1(); ++i){
	for (int j = 0; j < _M.size2(); ++j){
	  if( _M.hasNZ(i,j) ){
		M.elem(i*3+0,j*3+0) = _M.elem(i,j);
		M.elem(i*3+1,j*3+1) = _M.elem(i,j);
		M.elem(i*3+2,j*3+2) = _M.elem(i,j);
	  }
	}
  }
}
コード例 #11
0
ファイル: TetMesh.cpp プロジェクト: fmckenna/OpenSees
int OPS_TetMesh()
{
    if (OPS_GetNumRemainingInputArgs() < 6) {
        opserr<<"WARNING: want tag? nummesh? mtags? id? ndf? size? eleType? eleArgs?\n";
        return -1;
    }

    // get tag and number mesh
    int num = 2;
    int idata[2];
    if (OPS_GetIntInput(&num,idata) < 0) {
        opserr<<"WARNING: failed to read mesh tag and number of 2D boundary mesh\n";
        return -1;
    }

    if (OPS_GetNumRemainingInputArgs() < idata[1]+3) {
        opserr<<"WARNING: want mtags? id? ndf? size? <eleType? eleArgs?>\n";
        return -1;
    }

    // create mesh
    TetMesh* mesh = new TetMesh(idata[0]);
    if(OPS_addMesh(mesh) == false) {
        opserr<<"WARNING: failed to add mesh\n";
        return -1;
    }

    // get mesh tags
    num = idata[1];
    ID mtags(num);
    if (OPS_GetIntInput(&num,&mtags(0)) < 0) {
        opserr<<"WARNING: failed to read boundary mesh tags\n";
        return -1;
    }
    mesh->setMeshTags(mtags);

    // get id and ndf
    num = 2;
    int data[2];
    if (OPS_GetIntInput(&num,data) < 0) {
        opserr<<"WARNING: failed to read id and ndf\n";
        return -1;
    }
    mesh->setID(data[0]);
    mesh->setNdf(data[1]);

    // get size
    num = 1;
    double size;
    if (OPS_GetDoubleInput(&num,&size) < 0) {
        opserr<<"WARNING: failed to read mesh size\n";
        return -1;
    }
    mesh->setMeshsize(size);

    // set eleArgs
    if (mesh->setEleArgs() < 0) {
        opserr << "WARNING: failed to set element arguments\n";
        return -1;
    }

    // mesh
    if (mesh->mesh() < 0) {
        opserr<<"WARNING: failed to do triangular mesh\n";
        return -1;
    }

    return 0;
}
コード例 #12
0
void
make_tet_mesh(TetMesh& mesh,
              const SDF& sdf,
              FeatureSet& featureSet,
              bool optimize,
              bool intermediate,
              bool unsafe)
{
    // Initialize exact arithmetic
    initialize_exact();

    // Initialize mesh from acute lattice.
    std::vector<float> vphi; // SDF value at each lattice vertex.
    mesh.verts().resize(0);
    mesh.tets().resize(0);

    std::cout<<"  cutting from lattice"<<std::endl;
    cut_lattice(sdf, mesh, vphi);

    if (intermediate) {
        static const char* cutLatticeFile = "1_cut_lattice.tet";
        static const char* cutLatticeInfo = "1_cut_lattice.info";
        mesh.writeToFile(cutLatticeFile);
        mesh.writeInfoToFile(cutLatticeInfo);
        std::cout << "Mesh written to " << cutLatticeFile << std::endl;
    }

    // Warp any vertices close enough to phi=0 to fix sign crossings.
    static const float WARP_THRESHOLD = 0.3;
    std::cout<<"  warping vertices"<<std::endl;
    warp_vertices(WARP_THRESHOLD, mesh, vphi);

    if (intermediate) {
        static const char* warpVerticesFile = "2_warp_vertices.tet";
        static const char* warpVerticesInfo = "2_warp_vertices.info";
        mesh.writeToFile(warpVerticesFile);
        mesh.writeInfoToFile(warpVerticesInfo);
        std::cout << "Mesh written to " << warpVerticesFile << std::endl;
    }

    // Cut through tets that still poke out of the level set
    std::cout<<"  trimming spikes"<<std::endl;
    trim_spikes(mesh, vphi);

    if (intermediate) {
        static const char* trimSpikesFile = "3_trim_spikes.tet";
        static const char* trimSpikesInfo = "3_trim_spikes.info";
        mesh.writeToFile(trimSpikesFile);
        mesh.writeInfoToFile(trimSpikesInfo);
        std::cout << "Mesh written to " << trimSpikesFile << std::endl;
    }

    // At this point, there could be some bad tets with all four vertices on
    // the surface but which lie outside the level set.  Get rid of them.
    std::cout<<"  removing exterior tets"<<std::endl;
    remove_exterior_tets(mesh, vphi, sdf);

    // Compact mesh and clear away unused vertices.
    std::cout<<"  compacting mesh"<<std::endl;
    mesh.compactMesh();

    if (intermediate) {
        static const char* removeExtFile = "4_remove_exterior.tet";
        static const char* removeExtInfo = "4_remove_exterior.info";
        static const char* removeExtObj = "4_remove_exterior.obj";
        mesh.writeToFile(removeExtFile);
        mesh.writeInfoToFile(removeExtInfo);
        std::vector<Vec3f> objVerts;
        std::vector<Vec3i> objTris;
        mesh.getBoundary(objVerts, objTris);
        write_objfile(objVerts, objTris, removeExtObj);
        std::cout << "Mesh written to " << removeExtFile << std::endl;
    }

    // Compute maximum dihedral angle of mesh (unoptimized, no features).
    std::cout << "  Maximum dihedral angle = " << max_dihedral_angle(mesh) 
        << std::endl;

    if (featureSet.numFeatures() > 0 || optimize)
    {
        // Identify boundary vertices
        std::vector<int> boundary_verts;
        std::vector<Vec3i> boundary_tris;
        std::cout << "  identifying boundary" << std::endl;
        mesh.getBoundary(boundary_verts, boundary_tris);
        assert(!boundary_verts.empty());
        
        // Snap vertices to given features
        std::vector<int> feature_endpoints;
        std::map<int, int> vertex_feature_map;
        if (featureSet.numFeatures() > 0)
        {
            // Move vertices to match desired features
            std::cout << "  matching features" << std::endl;
            clock_t featureTime = clock();

            match_features(mesh, featureSet, sdf.dx,
                           boundary_verts, boundary_tris,
                           feature_endpoints, vertex_feature_map,
                           unsafe);

            featureTime = clock() - featureTime;
        
            std::cout << "  features matched in " 
                      << ((float)featureTime)/CLOCKS_PER_SEC 
                      << " seconds." << std::endl;
            std::cout << "  Maximum dihedral angle = "
                      << max_dihedral_angle(mesh) << std::endl;

            if (optimize && intermediate)
            {
                static const char* matchFeaturesFile = "5_match_features.tet";
                static const char* matchFeaturesInfo = "5_match_features.info";
                mesh.writeToFile(matchFeaturesFile);
                mesh.writeInfoToFile(matchFeaturesInfo);
                std::cout << "Mesh written to " << matchFeaturesFile 
                          << std::endl;
            }
        } 

        // Finish by optimizing the tetmesh, if desired.
        if (optimize) 
        {
            std::cout << "  optimizing mesh" << std::endl;
            clock_t optTime = clock();

            optimize_tet_mesh(mesh, sdf, 
                              boundary_verts, 
                              featureSet,
                              feature_endpoints,
                              vertex_feature_map);

            optTime = clock() - optTime;
            std::cout << "  Mesh optimization completed in " 
                      << ((float)optTime)/CLOCKS_PER_SEC
                      << " seconds." << std::endl;
            std::cout<< "  Maximum dihedral angle = "
                     << max_dihedral_angle(mesh) << std::endl;
        }

        // DEBUGGING
        // Check for inverted tets
        for (size_t t = 0; t < mesh.tSize(); ++t)
        {
            Tet tet = mesh.getTet(t);
            float signedVolume = tet.volume();
            if (signedVolume <= 0.0)
            {
                std::cerr << "Tet #" << t << " is inverted! " <<
                    "Volume = " << signedVolume << "; " <<
                    "Aspect = " << tet.aspectRatio() << std::endl <<
                    "{" << tet[0] << "} {" << tet[1] << "} {" << tet[2] <<
                    "} {" << tet[3] << "}" << std::endl;
            }
        }
    }
}
コード例 #13
0
// Find all tets with vertices where a corner has vphi>0 and trim them back.
static void
trim_spikes(TetMesh& mesh,
            std::vector<float> &vphi)
{
    // keep track of edges we cut - store the index of the new vertex
    std::map<Vec2i,int> cut_map;
    // we have a separate list for the results of trimming tets
    std::vector<Vec4i> new_tets;
    // go through the existing tets to see what we have to trim
    for (int t=0; t<(int)mesh.tSize(); ++t) {
        int p, q, r, s; assign(mesh.T(t), p, q, r, s);
        if (vphi[p]<=0 && vphi[q]<=0 && vphi[r]<=0 && vphi[s]<=0)
            continue; // this tet doesn't stick out

        // We have a plethora of cases to deal with. Let's sort the vertices
        // by their phi values and break ties with index, remembering if we
        // have switched orientation or not, to cut down on the number of
        // cases to handle. Use a sorting network to do the job.
        bool flipped=false;
        if (vphi[p]<vphi[q] || (vphi[p]==vphi[q] && p<q)) {
            std::swap(p, q);
            flipped = !flipped;
        }
        if (vphi[r]<vphi[s] || (vphi[r]==vphi[s] && r<s)) {
            std::swap(r, s);
            flipped = !flipped;
        }
        if (vphi[p]<vphi[r] || (vphi[p]==vphi[r] && p<r)) {
            std::swap(p, r);
            flipped = !flipped;
        }
        if (vphi[q]<vphi[s] || (vphi[q]==vphi[s] && q<s)) {
            std::swap(q, s);
            flipped = !flipped;
        }
        if (vphi[q]<vphi[r] || (vphi[q]==vphi[r] && q<r)) {
            std::swap(q, r);
            flipped = !flipped;
        }

        // sanity checks
        assert(vphi[p]>=vphi[q] && vphi[q]>=vphi[r] && vphi[r]>=vphi[s]); //sort
        assert(vphi[p]>0); // we already skipped interior tets
        assert(vphi[s]<=0); // we never generate tets with all positive phi

        // now do the actual trimming
        if (vphi[s]==0) { // +++0 entirely outside
            mesh.T(t)=mesh.tets().back(); // overwrite with last tet
            mesh.tets().pop_back(); // get rid of the last one
            --t; // decrement to cancel the next for-loop increment

        } else if (vphi[r]>0) { // +++- just one vertex inside, three out
            // replace this tet with one clipped back to the isosurface
            int ps = cut_edge(p, s, mesh, vphi, cut_map),
                qs = cut_edge(q, s, mesh, vphi, cut_map),
                rs = cut_edge(r, s, mesh, vphi, cut_map);
            if (flipped)
                mesh.T(t) = Vec4i(qs, ps, rs, s);
            else
                mesh.T(t) = Vec4i(ps, qs, rs, s);

        } else if(vphi[q]<0) { // +--- just one vertex outside, three in
            // Have to tetrahedralize the resulting triangular prism.
            // Note that the quad faces have to be split in a way that will
            // be consistent with face-adjacent tets: our sort of pqrs with
            // consistently broken ties makes this work. We cut the quad to the
            // deepest vertex (phi as negative as possible).
            int pq = cut_edge(p, q, mesh, vphi, cut_map),
                pr = cut_edge(p, r, mesh, vphi, cut_map),
                ps = cut_edge(p, s, mesh, vphi, cut_map);
            if (flipped) {
                mesh.T(t) = Vec4i(q, pq, r, s);
                new_tets.push_back(Vec4i(r, pq, pr, s));
                new_tets.push_back(Vec4i(s, pq, pr, ps));
            } else {
                mesh.T(t)=Vec4i(pq, q, r, s);
                new_tets.push_back(Vec4i(pq, r, pr, s));
                new_tets.push_back(Vec4i(pq, s, pr, ps));
            }

        } else if (vphi[q]>0 && vphi[r]<0) { // ++-- two vertices out, two in
            int pr = cut_edge(p, r, mesh, vphi, cut_map),
                ps = cut_edge(p, s, mesh, vphi, cut_map),
                qr = cut_edge(q, r, mesh, vphi, cut_map),
                qs = cut_edge(q, s, mesh, vphi, cut_map);
            if (flipped) {
                mesh.T(t) = Vec4i(qr, pr, r, s);
                new_tets.push_back(Vec4i(qs, pr, qr, s));
                new_tets.push_back(Vec4i(ps, pr, qs, s));
            } else {
                mesh.T(t) = Vec4i(pr, qr, r, s);
                new_tets.push_back(Vec4i(pr, qs, qr, s));
                new_tets.push_back(Vec4i(pr, ps, qs, s));
            }

        } else if (vphi[q]==0 && vphi[r]==0) { // +00- 1 out, 1 in, 2 surface
            int ps = cut_edge(p, s, mesh, vphi, cut_map);
            if (flipped)
                mesh.T(t) = Vec4i(q, ps, r, s);
            else
                mesh.T(t) = Vec4i(ps, q, r, s);

        } else if (vphi[q]==0) { // +0-- 1 out, 2 in, 1 surface
            int pr = cut_edge(p, r, mesh, vphi, cut_map),
                ps = cut_edge(p, s, mesh, vphi, cut_map);
            if (flipped) {
                mesh.T(t) = Vec4i(q, pr, r, s);
                new_tets.push_back(Vec4i(q, ps, pr, s));
            } else {
                mesh.T(t) = Vec4i(pr, q, r, s);
                new_tets.push_back(Vec4i(ps, q, pr, s));
            }

        } else { // ++0- two out, one in, one surface
            int ps = cut_edge(p, s, mesh, vphi, cut_map),
                qs = cut_edge(q, s, mesh, vphi, cut_map);
            if (flipped)
                mesh.T(t) = Vec4i(qs, ps, r, s);
            else
                mesh.T(t) = Vec4i(ps, qs, r, s);
        }
    }
    // append all the remaining new tets
    for (size_t t=0; t<new_tets.size(); ++t)
        mesh.tets().push_back(new_tets[t]);
}
コード例 #14
0
// Fix some edge crossings by warping vertices if it's admissible
static void
warp_vertices(const float threshold,
              TetMesh& mesh,
              std::vector<float>& vphi)
{
    assert(threshold>=0 && threshold<=0.5);
    std::vector<float> warp(mesh.vSize(), FLT_MAX);
    std::vector<int> warp_nbr(mesh.vSize(), -1);
    std::vector<Vec3f> d(mesh.vSize(), Vec3f(0,0,0));
    // it's wasteful to iterate through tets just to look at edges; oh well
    for (size_t t=0; t<mesh.tSize(); ++t) {
        for (int u=0; u<3; ++u) {
            int i = mesh.T(t)[u];
            for (int v=u+1; v<4; ++v) {
                int j = mesh.T(t)[v];
                if ((vphi[i]<0 && vphi[j]>0) || (vphi[i]>0 && vphi[j]<0)) {
                    float alpha = vphi[i]/(vphi[i]-vphi[j]);
                    if (alpha < threshold) { // warp i?
                        float d2 = alpha*dist2(mesh.V(i), mesh.V(j));
                        if (d2 < warp[i]) {
                            warp[i] = d2;
                            warp_nbr[i] = j;
                            d[i] = alpha*(mesh.V(j)-mesh.V(i));
                        }
                    } else if (alpha > 1-threshold) { // warp j?
                        float d2 = (1-alpha)*dist2(mesh.V(i), mesh.V(j));
                        if (d2 < warp[j]) {
                            warp[j] = d2;
                            warp_nbr[j] = i;
                            d[j] = (1-alpha)*(mesh.V(i)-mesh.V(j));
                        }
                    }
                }
            }
        }
    }
    // do the warps (also wasteful to loop over all vertices; oh well)
    for (size_t i=0; i<mesh.vSize(); ++i) if(warp_nbr[i]>=0) {
        mesh.V(i) += d[i];
        vphi[i] = 0; 
    }
}
コード例 #15
0
int main(int argc, char* argv[])
{
	char* inputFileName = "I:/Programs/VegaFEM-v2.1/models/turtle/turtle-volumetric-homogeneous.veg";
	VolumetricMesh* volumetricMesh = VolumetricMeshLoader::load(inputFileName);
	if (volumetricMesh == NULL)
	{
		PRINT_F("load failed!");
	}
	else 
	{
		PRINT_F("%d vertices, %d elements", volumetricMesh->getNumVertices(), volumetricMesh->getNumElements());
	}

	TetMesh* tetMesh;
	if (volumetricMesh->getElementType() == VolumetricMesh::TET)
	{
		tetMesh = (TetMesh*) volumetricMesh;
	}
	else 
		PRINT_F("not a tet mesh\n");

	CorotationalLinearFEM* deformableModel = new CorotationalLinearFEM(tetMesh);
	ForceModel* forceModel = new CorotationalLinearFEMForceModel(deformableModel);

	int nVtx = tetMesh->getNumVertices();
	int r = 3 * nVtx;
	double timestep = 0.0333;

	SparseMatrix* massMatrix;
	GenerateMassMatrix::computeMassMatrix(tetMesh, &massMatrix, true);
	massMatrix->SaveToMatlabFormat("massMatrix.m");

	PRINT_F("%d rows, %d cols\n", massMatrix->GetNumRows(), massMatrix->GetNumColumns());
	int positiveDefiniteSolver = 0;

	int numConstrainedDOFs = 9;
	int constrainedDOFs[9]= {12,13,14,30,31,32,42,43,44};

	double dampingMassCoef = 0.0;
	double dampingStiffnessCoef = 0.01;


	ImplicitBackwardEulerSparse* integrator = new ImplicitBackwardEulerSparse(r, timestep, massMatrix, forceModel, positiveDefiniteSolver, numConstrainedDOFs, constrainedDOFs, dampingMassCoef, dampingStiffnessCoef);

	//CentralDifferencesSparse* integrator = new CentralDifferencesSparse(r, timestep, massMatrix, forceModel, numConstrainedDOFs, constrainedDOFs, dampingMassCoef, dampingStiffnessCoef);

	double * f = new double[r];
	int numTimesteps = 10;
	double*u = new double[r];
	for (int i = 0; i < numTimesteps; ++i)
	{
		integrator->SetExternalForcesToZero();
		if (i==0)
		{
			for (int j = 0; j < r; j++)
				f[j] = 0;
			f[37] = -500;
			integrator->SetExternalForces(f);
		}
		integrator->GetqState(u);
		PRINT_F("v = [", i);
		for (int ithVtx = 0; ithVtx < nVtx; ++ithVtx)
			PRINT_F("%lf, %lf, %lf\n", u[ithVtx*3],u[ithVtx*3+1],u[ithVtx*3+2]);
		PRINT_F("];");

		integrator->DoTimestep();
	}

	return 0;
}
コード例 #16
0
ファイル: tetmesh_fem.C プロジェクト: davidheryanto/sc14
// Write this mesh to the FEM framework's mesh m
void writeFEM(int m,TetMesh &t) {
  int nNode=t.getPoints();
  int nTet=t.getTets();
  FEM_Mesh_data(m,FEM_NODE,FEM_COORD,t.getPointArray(), 0,nNode, FEM_DOUBLE,3);
  FEM_Mesh_data(m,FEM_ELEM+0,FEM_CONN,t.getTetConn(), 0,nTet, FEM_INDEX_0,4);
}