Пример #1
0
 void write_texture(std::ofstream& fout, const VectorF& uv) {
     assert(uv.size() % 2 == 0);
     const size_t num_uvs = uv.size() / 2;
     for (size_t i=0; i<num_uvs; i++) {
         fout << "vt " << uv[i*2] << " " << uv[i*2+1] << std::endl;
     }
 }
Пример #2
0
void InflatorEngine::with_abs_geometry_correction(const VectorF& correction) {
    if (correction.size() != m_wire_network->get_dim()) {
        std::stringstream err_msg;
        err_msg << "Absolute geometry offset dimension mismatch.  Expect "
            << m_wire_network->get_dim() << " but get "
            << correction.size() << " instead.";
        throw RuntimeError(err_msg.str());
    }
    m_abs_correction = correction;
}
Пример #3
0
void WireNetwork::translate(const VectorF& offset) {
    if (offset.size() != m_dim) {
        std::stringstream err_msg;
        err_msg << "Offset is of dim ("
            << offset.size() << "), expecting (" << m_dim << ")";
        throw RuntimeError(err_msg.str());
    }

    const size_t num_vertices = get_num_vertices();
    for (size_t i=0; i<num_vertices; i++) {
        m_vertices.row(i) += offset;
    }
    update_bbox();
}
Пример #4
0
    VectorF convert_face_attribute_to_vertex_attribute(
            Mesh& mesh, const VectorF& attribute) {
        const size_t num_vertices = mesh.get_num_vertices();
        const size_t vertex_per_face = mesh.get_vertex_per_face();
        const size_t num_faces = mesh.get_num_faces();
        const size_t attr_size = attribute.size();
        const size_t stride = attr_size / num_faces;

        const VectorI& faces = mesh.get_faces();
        const VectorF& weights = mesh.get_attribute("face_area");

        VectorF result = VectorF::Zero(num_vertices * stride);
        VectorF result_weights = VectorF::Zero(num_vertices);
        for (size_t i=0; i<num_faces; i++) {
            const VectorI& face =
                faces.segment(i*vertex_per_face, vertex_per_face);
            Float per_vertex_weight = weights[i] / vertex_per_face;
            for (size_t j=0; j<vertex_per_face; j++) {
                result_weights[face[j]] += per_vertex_weight;
                result.segment(face[j]*stride, stride) +=
                    per_vertex_weight * attribute.segment(i*stride, stride);
            }
        }

        for (size_t i=0; i<num_vertices; i++) {
            result.segment(i*stride, stride) /= result_weights[i];
        }
        return result;
    }
Пример #5
0
    VectorF convert_voxel_attribute_to_vertex_attribute(
            Mesh& mesh, const VectorF& attribute) {
        const size_t num_vertices = mesh.get_num_vertices();
        const size_t vertex_per_voxel = mesh.get_vertex_per_voxel();
        const size_t num_voxels = mesh.get_num_voxels();
        const size_t attr_size = attribute.size();
        const size_t stride = attr_size / num_voxels;

        const VectorI& voxels = mesh.get_voxels();
        if (!mesh.has_attribute("voxel_volume")) {
            mesh.add_attribute("voxel_volume");
        }
        const VectorF& weights = mesh.get_attribute("voxel_volume");

        VectorF result = VectorF::Zero(num_vertices * stride);
        VectorF result_weights = VectorF::Zero(num_vertices);
        for (size_t i=0; i<num_voxels; i++) {
            const VectorI& voxel =
                voxels.segment(i*vertex_per_voxel, vertex_per_voxel);
            Float per_vertex_weight = weights[i] / vertex_per_voxel;
            for (size_t j=0; j<vertex_per_voxel; j++) {
                result_weights[voxel[j]] += per_vertex_weight;
                result.segment(voxel[j]*stride, stride) +=
                    per_vertex_weight * attribute.segment(i*stride, stride);
            }
        }

        for (size_t i=0; i<num_vertices; i++) {
            result.segment(i*stride, stride) /= result_weights[i];
        }
        return result;
    }
Пример #6
0
void OBJWriter::write_mesh(Mesh& mesh) {
    using namespace OBJWriterHelper;
    std::ofstream fout(m_filename.c_str());
    if (!is_anonymous()) {
        fout << "# Generated with PyMesh" << std::endl;
    }
    VectorF texture;
    VectorI texture_indices;
    if (mesh.has_attribute("corner_texture")) {
        texture = mesh.get_attribute("corner_texture");
        const size_t num_faces = mesh.get_num_faces();
        const size_t vertex_per_face = mesh.get_vertex_per_face();
        if (texture.size() != num_faces * vertex_per_face * 2) {
            // Texture invalid.
            texture.resize(0);
        } else {
            write_texture(fout, texture);
            texture_indices.resize(num_faces * vertex_per_face);
            for (size_t i=0; i<num_faces; i++) {
                for (size_t j=0; j<vertex_per_face; j++) {
                    texture_indices[i*vertex_per_face+j] = i*vertex_per_face+j;
                }
            }
        }
    }

    write_vertices(fout, mesh.get_vertices(), mesh.get_dim());
    write_faces(fout, mesh.get_faces(), mesh.get_vertex_per_face(),
            texture_indices);
    fout.close();
}
Пример #7
0
void WireNetwork::scale(const VectorF& factors) {
    if (factors.size() != m_dim) {
        std::stringstream err_msg;
        err_msg << "Scaling factors is of dim ("
            << factors.size() << "), expecting (" << m_dim << ")";
        throw RuntimeError(err_msg.str());
    }

    const size_t num_vertices = get_num_vertices();
    for (size_t i=0; i<num_vertices; i++) {
        const VectorF& v = m_vertices.row(i);
        m_vertices.row(i) = v.cwiseProduct(factors);
    }

    update_bbox();
}
Пример #8
0
void VertexOffsetParameter::apply(VectorF& results,
        const PatternParameter::Variables& vars) {
    const VectorF bbox_min = m_wire_network->get_bbox_min();
    const VectorF bbox_max = m_wire_network->get_bbox_max();
    const VectorF center = 0.5 * (bbox_min + bbox_max);
    const VectorF half_bbox_size = bbox_max - center;

    const size_t dim = m_wire_network->get_dim();
    const size_t num_vertices = m_wire_network->get_num_vertices();
    const size_t roi_size = m_roi.size();
    assert(m_axis < dim);
    assert(results.size() == dim * num_vertices);

    if (m_formula != "") evaluate_formula(vars);

    const MatrixFr& vertices = m_wire_network->get_vertices();

    for (size_t i=0; i<roi_size; i++) {
        size_t v_idx = m_roi[i];
        assert(v_idx < num_vertices);
        const VectorF& v = vertices.row(v_idx);
        assert(fabs(v[m_axis] - center[m_axis]) > 1e-12);
        Float sign = v[m_axis] - center[m_axis] > 0.0 ? 1.0 : -1.0;

        results[v_idx * dim + m_axis] =
            sign * half_bbox_size[m_axis] * m_value;
    }
}
void VertexIsotropicOffsetParameter::apply(VectorF& results,
        const PatternParameter::Variables& vars) {
    const size_t dim = m_wire_network->get_dim();
    const size_t num_vertices = m_wire_network->get_num_vertices();
    const size_t roi_size = m_roi.size();
    const VectorF center = m_wire_network->center();
    const VectorF bbox_max = m_wire_network->get_bbox_max();
    assert(results.size() == dim * num_vertices);
    assert(roi_size == m_transforms.size());

    if (m_formula != "") evaluate_formula(vars);

    const MatrixFr& vertices = m_wire_network->get_vertices();
    size_t seed_vertex_index = m_roi.minCoeff();
    VectorF seed_vertex = vertices.row(seed_vertex_index);
    VectorF seed_offset = VectorF::Zero(dim);
    seed_offset = (bbox_max - center).cwiseProduct(m_dof_dir) * m_value;

    for (size_t i=0; i<roi_size; i++) {
        size_t v_idx = m_roi[i];
        assert(v_idx < num_vertices);
        const MatrixF& trans = m_transforms[i];
        results.segment(v_idx*dim, dim) += trans * seed_offset;
    }
}
Пример #10
0
std::vector<VectorF> IsotropicDofExtractor::extract_dofs(const VectorF& v) {
    const size_t dim = m_wire_network->get_dim();
    assert(v.size() == dim);
    if (dim == 3) {
        return extract_3D_dofs(v);
    } else if (dim == 2) {
        return extract_2D_dofs(v);
    } else {
        std::stringstream err_msg;
        err_msg << "Unsupported dim: " << dim;
        throw NotImplementedError(err_msg.str());
    }
}
Пример #11
0
void VertexMeanCurvatureAttribute::compute_from_mesh(Mesh& mesh) {
    const size_t dim = mesh.get_dim();
    const size_t num_vertices = mesh.get_num_vertices();
    VectorF laplacian = compute_laplacian_vectors(mesh);
    VectorF normals = compute_vertex_normals(mesh);
    assert(laplacian.size() == dim*num_vertices);
    assert(normals.size() == dim*num_vertices);

    if (!mesh.has_attribute("vertex_voronoi_area")) {
        mesh.add_attribute("vertex_voronoi_area");
    }

    const auto& area = mesh.get_attribute("vertex_voronoi_area");
    VectorF& mean_curvature = m_values;
    mean_curvature = VectorF::Zero(num_vertices);
    for (size_t i=0; i<num_vertices; i++) {
        mean_curvature[i] = laplacian.segment(dim*i,dim).norm() * 0.5;
        Float sign = laplacian.segment(dim*i, dim).dot(normals.segment(dim*i,dim));
        if (sign < 0) {
            mean_curvature[i] *= -1;
        }
    }
    mean_curvature = mean_curvature.array() / area.array();
}
Пример #12
0
void Deform::set_soft_ctrs(const VectorF &T, const VectorI &idx_T)
{
    assert(T.size()/3 == idx_T.size());

    for (int i = 0, i_end = idx_T.size(); i < i_end; ++ i)
    {
        int cid = idx_T[i];

        Eigen::Vector3f ctr; 
        ctr << T[3*i], T[3*i+1], T[3*i+2];

        soft_ctrs.push_back(Constraint(ctr, cid));
    }

    std::sort(soft_ctrs.begin(), soft_ctrs.end(), ConstraintCompare());
}
Пример #13
0
void TilerEngine::normalize_unit_wire(const VectorF& cell_size) {
    if (cell_size.minCoeff() <= 1e-30) {
        const size_t dim = cell_size.size();
        if (dim == 3)
            throw RuntimeError("It seems the 3D wires are flat.");
        else if (dim == 2)
            throw RuntimeError("It seems the 2D wires are degenerated/linear.");
        else
            throw NotImplementedError("Unsupported dimension!");
    }

    VectorF factors = cell_size.cwiseQuotient(
            m_unit_wire_network->get_bbox_max() - m_unit_wire_network->get_bbox_min());
    m_unit_wire_network->center_at_origin();
    m_unit_wire_network->scale(factors);
}
Пример #14
0
 void write_vertices(std::ofstream& fout,
         const VectorF& vertices, const size_t dim) {
     if (dim != 2 && dim != 3) {
         throw IOError("Unsupported mesh dimension: " + std::to_string(dim));
     }
     fout.precision(16);
     size_t num_vertices = vertices.size() / dim;
     for (size_t i=0; i<num_vertices; i++) {
         const auto& v = vertices.segment(i*dim, dim);
         fout << "v";
         for (size_t j=0; j<dim; j++) {
             fout << " " << v[j];
         }
         fout << std::endl;
     }
 }
Пример #15
0
void EigenSolver::compute_batch_symmetric_2x2(const VectorF& matrices) {
    const size_t dim = 2;
    const size_t flatten_size = 3;
    const size_t num_matrices = matrices.size() / flatten_size;
    m_eigen_values = VectorF(num_matrices * dim);
    m_eigen_vectors = MatrixF(num_matrices * dim, dim);
    for (size_t i=0; i<num_matrices; i++) {
        const VectorF& entries = matrices.segment(i*flatten_size, flatten_size);
        MatrixF M(dim, dim);
        size_t base_idx = i*flatten_size;
        M << matrices[base_idx  ], matrices[base_idx+2],
             matrices[base_idx+2], matrices[base_idx+1],
        m_solver.compute(M);
        m_eigen_values.segment(i*dim, dim) = m_solver.eigenvalues().real();
        m_eigen_vectors.block(i*dim, 0, dim, dim) =
            m_solver.eigenvectors().real();
    }
}
Пример #16
0
VectorF AttributeUtils::convert_to_face_attribute(Mesh& mesh, const VectorF& attribute) {
    const size_t dim = mesh.get_dim();
    const size_t num_vertices = mesh.get_num_vertices();
    const size_t num_faces = mesh.get_num_faces();
    const size_t num_voxels = mesh.get_num_voxels();

    size_t attr_size = attribute.size();

    if (attr_size == num_vertices || attr_size == dim*num_vertices) {
        return convert_vertex_attribute_to_face_attribute(mesh, attribute);
    } else if (attr_size == num_faces || attr_size == dim*num_faces) {
        std::cerr << "Warning: attribute is already face attribute!  "
            << "This copy is unnecessary!" << std::endl;
        return attribute;
    } else if (attr_size == num_voxels || attr_size == dim*num_voxels) {
        return convert_voxel_attribute_to_face_attribute(mesh, attribute);
    } else {
        throw RuntimeError("Unknow attribute type.");
    }
}
Пример #17
0
    VectorF convert_vertex_attribute_to_face_attribute(Mesh& mesh,
            const VectorF& attribute) {
        const size_t num_vertices = mesh.get_num_vertices();
        const size_t num_faces = mesh.get_num_faces();
        const size_t vertex_per_face = mesh.get_vertex_per_face();
        const size_t attr_size = attribute.size();
        const size_t stride = attr_size / num_vertices;

        const VectorI& faces = mesh.get_faces();
        VectorF result = VectorF::Zero(num_faces * stride);

        for (size_t i=0; i<num_faces; i++) {
            const VectorI& face = faces.segment(i*vertex_per_face,
                    vertex_per_face);
            for (size_t j=0; j<vertex_per_face; j++) {
                result.segment(i*stride, stride) +=
                    attribute.segment(face[j]*stride, stride);
            }
        }
        result /= vertex_per_face;
        return result;
    }
Пример #18
0
    VectorF convert_vertex_attribute_to_voxel_attribute(Mesh& mesh,
            const VectorF& attribute) {
        const size_t num_vertices = mesh.get_num_vertices();
        const size_t num_voxels = mesh.get_num_voxels();
        const size_t vertex_per_voxel = mesh.get_vertex_per_voxel();
        const size_t attr_size = attribute.size();
        const size_t stride = attr_size / num_vertices;

        const VectorI& voxels = mesh.get_voxels();
        VectorF result = VectorF::Zero(num_voxels * stride);

        for (size_t i=0; i<num_voxels; i++) {
            const VectorI& voxel = voxels.segment(i*vertex_per_voxel,
                    vertex_per_voxel);
            for (size_t j=0; j<vertex_per_voxel; j++) {
                result.segment(i*stride, stride) +=
                    attribute.segment(voxel[j]*stride, stride);
            }
        }
        result /= vertex_per_voxel;
        return result;
    }
Пример #19
0
    VectorF convert_voxel_attribute_to_face_attribute(
            Mesh& mesh, const VectorF& attribute) {
        const size_t num_faces = mesh.get_num_faces();
        const size_t num_voxels = mesh.get_num_voxels();
        const size_t attr_size = attribute.size();
        const size_t stride = attr_size / num_voxels;
        const size_t vertex_per_voxel = mesh.get_vertex_per_voxel();
        const size_t vertex_per_face = mesh.get_vertex_per_face();

        if (vertex_per_voxel != 4)
            throw NotImplementedError("Voxel type is not yet supported");
        if (vertex_per_face != 3)
            throw NotImplementedError("Face type is not yet supported");

        const VectorI& faces = mesh.get_faces();
        const VectorI& voxels = mesh.get_voxels();

        std::map<Triplet, VectorF> per_face_values;
        for (size_t i=0; i<num_voxels; i++) {
            const VectorI& voxel = voxels.segment(
                    i*vertex_per_voxel, vertex_per_voxel);
            const VectorF& value = attribute.segment(
                    i*stride, stride);
            per_face_values[Triplet(voxel[0], voxel[1], voxel[2])] = value;
            per_face_values[Triplet(voxel[0], voxel[1], voxel[3])] = value;
            per_face_values[Triplet(voxel[0], voxel[2], voxel[3])] = value;
            per_face_values[Triplet(voxel[1], voxel[2], voxel[3])] = value;
        }

        VectorF result = VectorF::Zero(num_faces*stride);
        for (size_t i=0; i<num_faces; i++) {
            const VectorI& face = faces.segment(i*vertex_per_face, vertex_per_face);
            result.segment(i*stride, stride) = per_face_values[
                Triplet(face[0], face[1], face[2])];
        }

        return result;
    }
Пример #20
0
void NodeWriter::write_elem_file(const std::string& filename, Mesh& mesh) {
    const size_t num_voxels = mesh.get_num_voxels();
    const size_t vertex_per_voxel = mesh.get_vertex_per_voxel();
    if (num_voxels == 0) return;
    if (vertex_per_voxel != 4) {
        throw IOError("Only tet element is supported in .ele file.");
    }

    std::ofstream fout(filename.c_str());
    fout.precision(16);
    if (!is_anonymous()) {
        fout << "# Generated with PyMesh" << std::endl;
    }
    VectorF region;
    if (m_with_region_attribute) {
        if (!mesh.has_attribute("region")) {
            throw IOError("Attribute \"region\" does not exist.");
        } else {
            region = mesh.get_attribute("region");
            assert(num_voxels == region.size());
        }
    }

    const VectorI& voxels = mesh.get_voxels();
    fout << num_voxels << " 4 " << m_with_region_attribute << std::endl;
    for (size_t i=0; i<num_voxels; i++) {
        fout << i;
        for (size_t j=0; j<4; j++) {
            fout << " " << voxels[i*4+ j];
        }
        if (m_with_region_attribute) {
            fout << " " << region[i];
        }
        fout << std::endl;
    }
}
Пример #21
0
void MSHWriter::write_attribute(MshSaver& saver, const std::string& name,
        VectorF& value, size_t dim, size_t num_vertices, size_t num_elements) {
    size_t attr_size = value.size();

    if (attr_size == num_vertices) {
        saver.save_scalar_field(name, value);
    } else if (attr_size == num_vertices * dim) {
        saver.save_vector_field(name, value);
    } else if (attr_size == num_vertices * (dim * (dim+1)) / 2) {
        throw NotImplementedError("Per-vertex tensor field is not supported.");
    } else if (attr_size == num_elements) {
        saver.save_elem_scalar_field(name, value);
    } else if (attr_size == num_elements * dim) {
        saver.save_elem_vector_field(name, value);
    } else if (attr_size == num_elements * (dim * (dim + 1)) / 2) {
        saver.save_elem_tensor_field(name, value);
    } else {
        std::stringstream err_msg;
        err_msg << "Attribute " << name << " has length " << attr_size << std::endl;
        err_msg << "Unable to interpret the attribute type.";
        std::cerr << "Warning: ";
        std::cerr << err_msg.str() << std::endl;
    }
}