Beispiel #1
0
void SimpleInflator::generate_joint(
        const MatrixFr& pts, const VectorI& source_ids, size_t vertex_index) {
    const size_t dim = m_wire_network->get_dim();
    ConvexHullEngine::Ptr convex_hull = ConvexHullEngine::create(dim, "qhull");
    convex_hull->run(pts);

    MatrixFr vertices = convex_hull->get_vertices();
    MatrixIr faces = convex_hull->get_faces();
    VectorI  index_map = convex_hull->get_index_map();

    if (dim == 2) {
        // Need to triangulate the loop.
        const size_t num_vertices = vertices.rows();
        TriangleWrapper tri(vertices, faces);
        tri.run(std::numeric_limits<Float>::max(), false, false, false);
        vertices = tri.get_vertices();
        faces = tri.get_faces();
        assert(vertices.rows() == num_vertices);
    }

    m_vertex_list.push_back(vertices);
    const size_t num_faces = faces.rows();
    for (size_t i=0; i<num_faces; i++) {
        const auto& face = faces.row(i);
        if (dim == 3) {
            auto ori_indices = map_indices(face, index_map);
            if (belong_to_the_same_loop(ori_indices, source_ids)) continue;
        }
        m_face_list.push_back(face.array() + m_num_vertex_accumulated);
        m_face_source_list.push_back(vertex_index+1);
    }

    m_num_vertex_accumulated += vertices.rows();
}
void GeometryCorrectionTable::apply_z_correction(
        const Vector3F& edge_dir, MatrixFr& loop) {
    //const Float max_z_error = 0.125;
    //const Float max_z_error = 0.09;
    const Float max_z_error = 0.00;
    VectorF bbox_min = loop.colwise().minCoeff();
    VectorF bbox_max = loop.colwise().maxCoeff();
    VectorF bbox_center = 0.5 * (bbox_min + bbox_max);

    Vector3F side_dir = edge_dir.cross(Vector3F::UnitZ());
    Float sin_val = side_dir.norm();
    if (sin_val < 1e-3) return;

    const size_t num_vts = loop.rows();
    for (size_t i=0; i<num_vts; i++) {
        Vector3F v = loop.row(i) - bbox_center.transpose();
        Float side_component = side_dir.dot(v) / sin_val;
        Vector3F proj_v = v - side_component * side_dir / sin_val;
        Float proj_component = proj_v.norm();
        if (proj_component > 1e-3) {
            proj_v -= proj_v / proj_component * (sin_val * max_z_error);
        }
        loop.row(i) = bbox_center + proj_v + side_component * side_dir / sin_val;
    }
}
VectorF FastWindingNumberEngine::run(const MatrixFr& queries) {
    const auto num_vertices = m_vertices.rows();
    const auto num_faces = m_faces.rows();
    const auto num_queries = queries.rows();
    using Vector = HDK_Sample::UT_Vector3T<float>;
    using Engine = HDK_Sample::UT_SolidAngle<float, float>;

    std::vector<Vector> vertices(num_vertices);
    for (size_t i=0; i<num_vertices; i++) {
        vertices[i][0] = static_cast<float>(m_vertices(i, 0));
        vertices[i][1] = static_cast<float>(m_vertices(i, 1));
        vertices[i][2] = static_cast<float>(m_vertices(i, 2));
    }

    Engine engine;
    engine.init(num_faces, m_faces.data(), num_vertices, vertices.data());

    VectorF winding_numbers(num_queries);
    for (size_t i=0; i<num_queries; i++) {
        Vector q;
        q[0] = static_cast<float>(queries(i, 0));
        q[1] = static_cast<float>(queries(i, 1));
        q[2] = static_cast<float>(queries(i, 2));
        winding_numbers[i] = engine.computeSolidAngle(q);
    }
    winding_numbers /= 4 * M_PI;

    return winding_numbers;
}
Beispiel #4
0
SelfIntersection::SelfIntersection(
        const MatrixFr& vertices, const MatrixIr& faces)
: m_faces(faces) {
    const size_t num_vertices = vertices.rows();
    const size_t dim = vertices.cols();
    const size_t num_faces = faces.rows();
    const size_t vertex_per_face = faces.cols();

    if (dim != 3) {
        throw NotImplementedError(
                "Self intersection check only support 3D");
    }
    if (vertex_per_face != 3) {
        throw NotImplementedError(
                "Self intersection check only works with triangles");
    }

    m_points.resize(num_vertices);
    for (size_t i=0; i<num_vertices; i++) {
        m_points[i] = Point_3(
                vertices(i,0),
                vertices(i,1),
                vertices(i,2));
    }
}
void GeometryCorrectionTable::apply_correction_to_in_plane_edge(
        const Vector3F& edge_dir, MatrixFr& loop) {
    VectorF bbox_min = loop.colwise().minCoeff();
    VectorF bbox_max = loop.colwise().maxCoeff();
    VectorF bbox_center = 0.5 * (bbox_min + bbox_max);

    size_t num_vts = loop.rows();
    size_t dim = loop.cols();
    assert(dim == 3);
    MatrixFr proj_loop(num_vts, dim);

    for (size_t i=0; i<num_vts; i++) {
        const VectorF& v = loop.row(i) - bbox_center.transpose();
        proj_loop.row(i) = Vector3F(v[0], v[1], 0.0);
    }
    Float target_half_height = 1e3; // Something huge to represent inf
    Float target_half_width = proj_loop.row(0).norm();

    Vector2F correction_1 = lookup(target_half_width, target_half_height);
    Vector2F correction_2 = lookup(target_half_height, target_half_width);
    Float half_width  = 0.5 * (correction_1[0] + correction_2[1])
        + 0.05 * num_offset_pixel;
    half_width = std::max(half_width, min_thickness);

    for (size_t i=0; i<num_vts; i++) {
        loop.row(i) += proj_loop.row(i) *
            (-target_half_width + half_width) / target_half_width;
    }
}
Beispiel #6
0
GeoMeshPtr GeogramMeshUtils::wire_network_to_geomesh(
        const MatrixFr& vertices, const Matrix2Ir& edges) {
    const size_t dim = vertices.cols();
    const size_t num_vertices = vertices.rows();
    const size_t num_edges = edges.rows();

    auto geo_mesh = std::make_shared<GeoMesh>(dim, false);
    geo_mesh->vertices.clear();
    geo_mesh->vertices.create_vertices(num_vertices);
    geo_mesh->edges.clear();
    geo_mesh->edges.create_edges(num_edges);

    for (size_t i=0; i<num_vertices; i++) {
        auto& p = geo_mesh->vertices.point(i);
        for (size_t j=0; j<dim; j++) {
            p[j] = vertices(i,j);
        }
    }

    for (size_t i=0; i<num_edges; i++) {
        geo_mesh->edges.set_vertex(i, 0, edges(i,0));
        geo_mesh->edges.set_vertex(i, 1, edges(i,1));
    }

    return geo_mesh;
}
Beispiel #7
0
GeoMeshPtr GeogramMeshUtils::raw_to_geomesh(
        const MatrixFr& vertices, const MatrixIr& faces) {
    const size_t dim = vertices.cols();
    const size_t vertex_per_face = faces.cols();
    const size_t num_vertices = vertices.rows();
    const size_t num_faces = faces.rows();

    if (vertex_per_face != 3) {
        throw NotImplementedError("Converting non-triangle mesh to "
                "Geogram mesh is not yet implemented");
    }

    auto geo_mesh = std::make_shared<GeoMesh>(dim, false);
    geo_mesh->vertices.clear();
    geo_mesh->vertices.create_vertices(num_vertices);
    geo_mesh->facets.clear();
    geo_mesh->facets.create_triangles(num_faces);

    for (size_t i=0; i<num_vertices; i++) {
        auto& p = geo_mesh->vertices.point(i);
        for (size_t j=0; j<dim; j++) {
            p[j] = vertices(i,j);
        }
    }

    for (size_t i=0; i<num_faces; i++) {
        geo_mesh->facets.set_vertex(i, 0, faces(i,0));
        geo_mesh->facets.set_vertex(i, 1, faces(i,1));
        geo_mesh->facets.set_vertex(i, 2, faces(i,2));
    }

    return geo_mesh;
}
Beispiel #8
0
    CarveMeshPtr create_mesh(const MatrixFr& vertices, const MatrixIr& faces) {
        const size_t num_vertices = vertices.rows();
        const size_t num_faces = faces.rows();

        if (vertices.cols() != 3) {
            throw NotImplementedError("Only 3D mesh is supported.");
        }
        if (faces.cols() != 3) {
            throw NotImplementedError("Only triangle mesh is supported.");
        }

        std::vector<CarveVector> points;

        for (size_t i=0; i<num_vertices; i++) {
            const auto& v = vertices.row(i);
            CarveVector p;
            p.v[0] = v[0];
            p.v[1] = v[1];
            p.v[2] = v[2];
            points.push_back(p);
        }

        std::vector<int> raw_faces;
        raw_faces.reserve(num_faces * 4);
        for (size_t i=0; i<num_faces; i++) {
            raw_faces.push_back(3);
            raw_faces.push_back(faces(i,0));
            raw_faces.push_back(faces(i,1));
            raw_faces.push_back(faces(i,2));
        }

        return CarveMeshPtr(new CarveMesh(points, num_faces, raw_faces));
    }
Beispiel #9
0
 Polyhedron generate_polyhedron(
         const MatrixFr& vertices, const MatrixIr& faces) {
     Polyhedron P;
     PolyhedronBuilder<HalfedgeDS> triangle(vertices, faces);
     P.delegate(triangle);
     assert(vertices.rows() == P.size_of_vertices());
     assert(faces.rows() == P.size_of_facets());
     return P;
 }
Beispiel #10
0
 HashGrid::Ptr compute_vertex_grid(const MatrixFr& vertices, Float cell_size) {
     const size_t dim = vertices.cols();
     const size_t num_vertices = vertices.rows();
     HashGrid::Ptr grid = HashGrid::create(cell_size, dim);
     for (size_t i=0; i<num_vertices; i++) {
         const VectorF& v = vertices.row(i);
         grid->insert(i, v);
     }
     return grid;
 }
Beispiel #11
0
void InflatorEngine::save_mesh(const std::string& filename,
        const MatrixFr& vertices, const MatrixIr& faces, VectorF debug) {
    VectorF flattened_vertices(vertices.rows() * vertices.cols());
    std::copy(vertices.data(), vertices.data() + vertices.rows() *
            vertices.cols(), flattened_vertices.data());
    VectorI flattened_faces(faces.rows() * faces.cols());
    std::copy(faces.data(), faces.data() + faces.rows() * faces.cols(),
            flattened_faces.data());
    VectorI voxels = VectorI::Zero(0);

    Mesh::Ptr mesh = MeshFactory().load_data(
            flattened_vertices, flattened_faces, voxels,
            vertices.cols(), faces.cols(), 0).create_shared();
    mesh->add_attribute("debug");
    mesh->set_attribute("debug", debug);

    MeshWriter::Ptr writer = MeshWriter::create(filename);
    writer->with_attribute("debug");
    writer->write_mesh(*mesh);
}
Beispiel #12
0
void CGALConvexHull3D::run(const MatrixFr& points) {
    std::list<Point_3> cgal_pts;
    const size_t num_pts = points.rows();
    const size_t dim = points.cols();
    if (dim != 3) {
        std::stringstream err_msg;
        err_msg << "Invalid dim: " << dim << "  Expect dim=3.";
        throw RuntimeError(err_msg.str());
    }

    for (size_t i=0; i<num_pts; i++) {
        const VectorF& p = points.row(i);
        cgal_pts.push_back(Point_3(p[0], p[1], p[2]));
    }

    Polyhedron_3 hull;
    CGAL::convex_hull_3(cgal_pts.begin(), cgal_pts.end(), hull);
    assert(hull.is_closed());
    assert(hull.is_pure_triangle());

    const size_t num_vertices = hull.size_of_vertices();
    const size_t num_faces = hull.size_of_facets();

    m_vertices.resize(num_vertices, dim);
    m_faces.resize(num_faces, 3);

    size_t vertex_count=0;
    for (auto itr=hull.vertices_begin(); itr!=hull.vertices_end(); itr++) {
        const Point_3& p = itr->point();
        m_vertices.coeffRef(vertex_count, 0) = p.x();
        m_vertices.coeffRef(vertex_count, 1) = p.y();
        m_vertices.coeffRef(vertex_count, 2) = p.z();
        itr->id() = vertex_count;
        vertex_count++;
    }

    size_t face_count=0;
    for (auto f_itr=hull.facets_begin(); f_itr!=hull.facets_end(); f_itr++) {
        size_t edge_count=0;
        auto h_itr = f_itr->facet_begin();
        do {
            m_faces.coeffRef(face_count, edge_count) = h_itr->vertex()->id();
            edge_count++;
            h_itr++;
        } while (h_itr != f_itr->facet_begin());
        face_count++;
    }

    compute_index_map(points);
    reorient_faces();
}
Beispiel #13
0
    void triangulate(MatrixFr vertices, MatrixIr edges,
            MatrixFr& output_vertices, MatrixIr& output_faces, Float max_area) {
        assert(edges.rows() >= 3);
        MeshCleaner cleaner;
        cleaner.remove_isolated_vertices(vertices, edges);
        cleaner.remove_duplicated_vertices(vertices, edges, 1e-12);
        assert(vertices.rows() >= 3);

        TriangleWrapper triangle(vertices, edges);
        triangle.run(max_area, false, true, true);

        output_vertices = triangle.get_vertices();
        output_faces = triangle.get_faces();
    }
Beispiel #14
0
Boundary::Ptr Boundary::extract_surface_boundary_raw(
        MatrixFr& vertices, MatrixIr& faces) {
    VectorF flattened_vertices = Eigen::Map<VectorF>(vertices.data(),
            vertices.rows() * vertices.cols());
    VectorI flattened_faces = Eigen::Map<VectorI>(faces.data(),
            faces.rows() * faces.cols());
    VectorI voxels = VectorI::Zero(0);

    MeshFactory factory;
    Mesh::Ptr mesh = factory.load_data(flattened_vertices, flattened_faces,
            voxels, vertices.cols(), faces.cols(), 0).create();

    return extract_surface_boundary(*mesh);
}
Beispiel #15
0
WireNetwork::Ptr MixedMeshTiler::tile() {
    const size_t num_cells = get_num_cells();
    auto transforms = get_tiling_operators();
    auto vars_array = extract_attributes(m_mesh);
    VectorI pattern_id = m_mesh->get_attribute("pattern_id").cast<int>();
    assert(pattern_id.size() == num_cells);

    m_tiled_vertices.clear();
    m_tiled_edges.clear();
    m_tiled_thicknesses.clear();
    m_tiled_offsets.clear();

    size_t v_count = 0;
    auto transform_itr = transforms.begin();
    for (size_t i=0; i<num_cells; i++) {
        set_active_wire_network(pattern_id[i]);
        scale_to_unit_box();
        append_vertices(*transform_itr);
        append_edges(v_count);
        append_thicknesses(vars_array[i]);
        append_offsets(vars_array[i], *transform_itr);

        v_count += m_unit_wire_network->get_num_vertices();
        transform_itr++;
    }

    MatrixFr vertices = vstack(m_tiled_vertices);
    MatrixIr edges = vstack(m_tiled_edges);
    MatrixFr thicknesses = vstack(m_tiled_thicknesses);
    MatrixFr offsets = vstack(m_tiled_offsets);
    assert(edges.minCoeff() >= 0);
    assert(edges.maxCoeff() < vertices.rows());

    WireNetwork::Ptr tiled_network =
        WireNetwork::create_raw(vertices, edges);

    tiled_network->add_attribute("thickness",
            m_target_type == ParameterCommon::VERTEX);
    tiled_network->set_attribute("thickness", thicknesses);
    tiled_network->add_attribute("vertex_offset", true);
    tiled_network->set_attribute("vertex_offset", offsets);

    clean_up(*tiled_network);
    return tiled_network;
}
Beispiel #16
0
void PointLocator::locate(const MatrixFr& points) {
    const Float eps = 1e-6;
    const size_t num_pts = points.rows();
    m_voxel_idx = VectorI::Zero(num_pts);
    m_barycentric_coords = MatrixFr::Zero(num_pts, m_vertex_per_element);

    for (size_t i=0; i<num_pts; i++) {
        VectorF v = points.row(i);
        VectorI candidate_elems = m_grid->get_items_near_point(v);

        VectorF barycentric_coord;
        VectorF best_barycentric_coord;

        bool found = false;
        Float least_negative_coordinate = -std::numeric_limits<Float>::max();
        const size_t num_candidates = candidate_elems.size();
        for (size_t j=0; j<num_candidates; j++) {
            barycentric_coord = compute_barycentric_coord(
                    v, candidate_elems[j]);
            Float min_barycentric_coord = barycentric_coord.minCoeff();
            if (min_barycentric_coord > least_negative_coordinate) {
                found = true;
                least_negative_coordinate = min_barycentric_coord;
                m_voxel_idx[i] = candidate_elems[j];
                best_barycentric_coord = barycentric_coord;
                if (min_barycentric_coord >= -eps) {
                    break;
                }
            }
        }

        if (!found) {
            std::stringstream err_msg;
            err_msg << "Point ( ";
            for (size_t i=0; i<m_mesh->get_dim(); i++) {
                err_msg << v[i] << " ";
            }
            err_msg << ") is not inside of any voxels" << std::endl;
            throw RuntimeError(err_msg.str());
        }

        m_barycentric_coords.row(i) = best_barycentric_coord;
    }
}
Beispiel #17
0
bool MeshValidation::is_periodic(
        const MatrixFr& vertices, const MatrixIr& faces) {
    const Float EPS = 1e-6;
    HashGrid::Ptr grid = compute_vertex_grid(vertices, EPS);

    Vector3F bbox_min = vertices.colwise().minCoeff();
    Vector3F bbox_max = vertices.colwise().maxCoeff();
    Vector3F bbox_size = bbox_max - bbox_min;

    Vector3F offsets[] = {
        Vector3F( bbox_size[0], 0.0, 0.0),
        Vector3F(-bbox_size[0], 0.0, 0.0),
        Vector3F(0.0, bbox_size[1], 0.0),
        Vector3F(0.0,-bbox_size[1], 0.0),
        Vector3F(0.0, 0.0, bbox_size[2]),
        Vector3F(0.0, 0.0,-bbox_size[2])
    };

    bool result = true;
    const size_t num_vertices = vertices.rows();
    for (size_t i=0; i<num_vertices; i++) {
        const VectorF& v = vertices.row(i);
        if (fabs(v[0] - bbox_min[0]) < EPS) {
            result = result && match(grid, v + offsets[0]);
        }
        if (fabs(v[0] - bbox_max[0]) < EPS) {
            result = result && match(grid, v + offsets[1]);
        }
        if (fabs(v[1] - bbox_min[1]) < EPS) {
            result = result && match(grid, v + offsets[2]);
        }
        if (fabs(v[1] - bbox_max[1]) < EPS) {
            result = result && match(grid, v + offsets[3]);
        }
        if (fabs(v[2] - bbox_min[2]) < EPS) {
            result = result && match(grid, v + offsets[4]);
        }
        if (fabs(v[2] - bbox_max[2]) < EPS) {
            result = result && match(grid, v + offsets[5]);
        }
    }
    return result;
}
Beispiel #18
0
VectorI MeshCleaner::compute_importance_level(const MatrixFr& vertices) {
    VectorF bbox_min = vertices.colwise().minCoeff();
    VectorF bbox_max = vertices.colwise().maxCoeff();
    BoxChecker checker(bbox_min, bbox_max);

    const size_t num_vertices = vertices.rows();
    VectorI level = VectorI::Zero(num_vertices);
    for (size_t i=0; i<num_vertices; i++) {
        const VectorF& v = vertices.row(i);
        if (checker.is_on_boundary_corners(v)) {
            level[i] = 3;
        } else if (checker.is_on_boundary_edges(v)) {
            level[i] = 2;
        } else if (checker.is_on_boundary(v)) {
            level[i] = 1;
        }
    }

    return level;
}
Beispiel #19
0
bool PeriodicExploration::run_tetgen(Float max_tet_vol) {
    const size_t dim = m_vertices.cols();
    const size_t num_vertices = m_vertices.rows();
    TetgenWrapper tetgen(m_vertices, m_faces);
    std::stringstream flags;
    if (max_tet_vol == 0.0) {
        max_tet_vol =
            pow(m_default_thickness * pow(0.5, m_refine_order), dim);
    }
    flags << "pqYQa" << max_tet_vol;
    try {
        tetgen.run(flags.str());
    } catch (TetgenException& e) {
        save_mesh("tetgen_debug.msh");
        std::cerr << "Tetgen failed!  Flags: " << flags.str() << std::endl;
        std::cerr << e.what() << std::endl;
        std::cerr << "Data saved in tetgen_debug.msh" << std::endl;
        return false;
    }

    // Important note:
    //
    // The following code is based on rather shaky the observation that tetgen
    // will only append to the existing list of vertices.  Therefore, the face
    // arrays are still valid given the "Y" flag is used.
    MatrixFr vertices = tetgen.get_vertices();
    assert(vertices.rows() > 0);
    assert((vertices.block(0, 0, num_vertices, dim).array()==m_vertices.array()).all());
    m_vertices = vertices;
    m_voxels = tetgen.get_voxels();

    const size_t num_vol_vertices = m_vertices.rows();
    for (auto& velocity : m_shape_velocities) {
        velocity.conservativeResize(num_vol_vertices, dim);
        velocity.block(num_vertices, 0,
                num_vol_vertices-num_vertices, dim).setZero();
    }
    update_mesh();

    return true;
}
Beispiel #20
0
Boundary::Ptr Boundary::extract_volume_boundary_raw(
        MatrixFr& vertices, MatrixIr& voxels) {
    VectorF flattened_vertices = Eigen::Map<VectorF>(vertices.data(),
            vertices.rows() * vertices.cols());
    VectorI faces = VectorI::Zero(0);
    VectorI flattened_voxels = Eigen::Map<VectorI>(voxels.data(),
            voxels.rows() * voxels.cols());

    size_t vertex_per_voxel = voxels.cols();
    size_t vertex_per_face=0;
    if (vertex_per_voxel == 4) vertex_per_face = 3;
    else if (vertex_per_voxel == 8) vertex_per_face = 4;
    else {
        throw RuntimeError("Unknown voxel type.");
    }

    MeshFactory factory;
    Mesh::Ptr mesh = factory.load_data(flattened_vertices, faces,
            flattened_voxels, vertices.cols(), vertex_per_face,
            vertex_per_voxel).create();

    return extract_volume_boundary(*mesh);
}
 VectorI get_vertex_labels(const MatrixFr& vertices, Operators& ops) {
     SymmetryConnectivity connectivity =
         compute_vertex_connectivity(vertices, ops);
     return label_connected_components(vertices.rows(), connectivity);
 }
void GeometryCorrectionTable::apply_correction_to_out_plane_edge(
        const Vector3F& edge_dir, MatrixFr& loop) {
    const Float EPS = 1e-3;
    assert(fabs(edge_dir[2]) > 0.0);
    VectorF bbox_min = loop.colwise().minCoeff();
    VectorF bbox_max = loop.colwise().maxCoeff();
    VectorF bbox_center = 0.5 * (bbox_min + bbox_max);

    size_t num_vts = loop.rows();
    size_t dim = loop.cols();
    assert(dim == 3);
    MatrixFr proj_loop(num_vts, 3);
    Vector3F proj_edge_dir(edge_dir[0], edge_dir[1], 0.0);

    if (loop.rows() != 4) {
        throw NotImplementedError(
                "Geometry correction supports only square wires");
    }

    for (size_t i=0; i<num_vts; i++) {
        VectorF v = loop.row(i) - bbox_center.transpose();
        Float edge_dir_offset = v[2] / edge_dir[2];
        VectorF proj_v = v - edge_dir * edge_dir_offset;
        proj_loop.row(i) = proj_v;
        assert(fabs(proj_v[2]) < EPS);
    }

    Float dist_01 = (proj_loop.row(0) - proj_loop.row(1)).norm();
    Float dist_12 = (proj_loop.row(1) - proj_loop.row(2)).norm();
    if (dist_01 > dist_12) {
        proj_edge_dir = (proj_loop.row(0) - proj_loop.row(1)) / dist_01;
    } else {
        proj_edge_dir = (proj_loop.row(1) - proj_loop.row(2)) / dist_12;
    }

    const VectorF& corner = proj_loop.row(0);
    Float target_half_height = proj_edge_dir.dot(corner);
    Float target_half_width =
        (corner - proj_edge_dir * target_half_height).norm();
    target_half_height = fabs(target_half_height);

    Vector2F correction_1 = lookup(target_half_width, target_half_height);
    Vector2F correction_2 = lookup(target_half_height, target_half_width);
    Float half_width  = 0.5 * (correction_1[0] + correction_2[1])
        + 0.05 * num_offset_pixel;
    Float half_height = 0.5 * (correction_1[1] + correction_2[0])
        + 0.05 * num_offset_pixel;
    half_width = std::max(half_width, min_thickness);
    half_height = std::max(half_height, min_thickness);

    for (size_t i=0; i<num_vts; i++) {
        const VectorF& proj_v = proj_loop.row(i);
        Float height = proj_edge_dir.dot(proj_v);
        VectorF width_dir = (proj_v - proj_edge_dir * height).normalized();
        assert(!isnan(width_dir[0]));
        assert(!isnan(width_dir[1]));
        assert(!isnan(width_dir[2]));

        Float height_sign = (height < 0.0)? -1: 1;
        proj_loop.row(i) = proj_edge_dir * height_sign * half_height
            + width_dir * half_width;
    }

    for (size_t i=0; i<num_vts; i++) {
        const VectorF& proj_v = proj_loop.row(i);
        loop.row(i) = (bbox_center + proj_v - edge_dir *
                edge_dir.dot(proj_v)).transpose();
    }
}
Beispiel #23
0
void MMG::Delaunay::refine(const MatrixFr& metric) {
    const size_t num_input_vertices = m_vertices.rows();
    const size_t num_input_faces = m_faces.rows();

    if (num_input_vertices == 0) {
        return;
    }

    MMG5_pMesh mmgMesh;
    MMG5_pSol mmgSol;

    mmgMesh = NULL;
    mmgSol  = NULL;
    if (MMG2D_Init_mesh(MMG5_ARG_start,
                MMG5_ARG_ppMesh, &mmgMesh,
                MMG5_ARG_ppMet, &mmgSol,
                MMG5_ARG_end) != 1) {
        throw RuntimeError("MMG2D_Init_mesh failed.");
    }

    const Vector2F bbox_min = m_vertices.colwise().minCoeff();
    const Vector2F bbox_max = m_vertices.colwise().maxCoeff();
    const Float tol = (bbox_max - bbox_min).norm() / 20.0;

    if (MMG2D_Set_iparameter(mmgMesh, mmgSol, MMG2D_IPARAM_verbose, 1) != 1) {
        throw RuntimeError("Setting MMG2D_IPARAM_verbose failed.");
    }
    if (MMG2D_Set_dparameter(mmgMesh, mmgSol, MMG2D_DPARAM_hmax, tol) != 1) {
        throw RuntimeError("Setting MMG2D_DPARAM_hmax failed.");
    }

    if (MMG2D_Set_meshSize(mmgMesh,num_input_vertices,num_input_faces,0) != 1) {
        throw RuntimeError("MMG2D_Set_meshSize failed.");
    }

    for (size_t i=0; i<num_input_vertices; i++) {
        if (MMG2D_Set_vertex(mmgMesh, m_vertices(i,0), m_vertices(i, 1), i+1, i+1) != 1) {
            throw RuntimeError("MMG2D_Set_vertex failed for vertex "
                    + std::to_string(i) + ".");
        }
    }

    for (size_t i=0; i<num_input_faces; i++) {
        if (MMG2D_Set_triangle(mmgMesh,
                    m_faces(i, 0) + 1,
                    m_faces(i, 1) + 1,
                    m_faces(i, 2) + 1,
                    i+1, i+1) != 1 )  {
            throw RuntimeError("MMG2D_Set_edge failed for edge "
                    + std::to_string(i) + ".");
        }
    }

    // Set per-vertex metric.  This must be done after mmgMesh is initialized.
    const size_t num_metrics = metric.rows();
    if (num_metrics == 0) {
        if (MMG2D_Set_solSize(mmgMesh, mmgSol, MMG5_Vertex, 0, MMG5_Scalar) != 1) {
            throw RuntimeError("MMG2D_Set_solSize failed.");
        }
    } else if (num_metrics == num_input_vertices) {
        if (MMG2D_Set_solSize(mmgMesh, mmgSol, MMG5_Vertex, num_metrics, MMG5_Scalar) != 1) {
            throw RuntimeError("MMG2D_Set_solSize failed.");
        }
        for (size_t i=0; i<num_metrics; i++) {
            if (MMG2D_Set_scalarSol(mmgSol, metric(i,0), i+1) != 1 ) {
                throw RuntimeError("MMG2D_Set_scalarSol failed.");
            }
        }
    }


    if (MMG2D_Chk_meshData(mmgMesh, mmgSol) != 1) {
        throw RuntimeError("MMG2D_Chk_meshData failed");
    }

    int r = MMG2D_mmg2dlib(mmgMesh,mmgSol);
    switch (r) {
        case MMG5_SUCCESS:
            break;
        case MMG5_LOWFAILURE:
            std::cerr << "Warning: MMG encountered low failure.  Results may not not be valid."
                << std::endl;
            break;
        case MMG5_STRONGFAILURE:
            throw RuntimeError("MMG strong failure!");
        default:
            throw NotImplementedError("Unknown MMG failure encountered.");
    }

    int num_vertices, num_triangles, num_edges;
    if (MMG2D_Get_meshSize(mmgMesh,
                &num_vertices, &num_triangles, &num_edges) !=1) {
        throw RuntimeError("MMG2D_Get_meshSize failed.");
    }

    m_vertices.resize(num_vertices, 2);
    int ref, is_corner, is_required;
    for (size_t i=0; i<num_vertices; i++) {
        if (MMG2D_Get_vertex(mmgMesh,
                    &m_vertices(i, 0),
                    &m_vertices(i, 1),
                    &ref,
                    &is_corner,
                    &is_required) != 1 ) {
            throw RuntimeError("MMG2D_Get_vertex failed.");
        }
    }

    m_faces.resize(num_triangles, 3);
    for (size_t i=0; i<num_triangles; i++) {
        if (MMG2D_Get_triangle(mmgMesh,
                    &m_faces(i, 0),
                    &m_faces(i, 1),
                    &m_faces(i, 2),
                    &ref,
                    &is_required) != 1 ) {
            throw RuntimeError("MMG2D_Get_triangle failed.");
        }
    }

    // MMG is 1 based unfortunately.
    m_faces.array() -= 1;

    //MMG2D_saveMesh(mmgMesh, "mmg_debug.mesh");

    MMG2D_Free_all(MMG5_ARG_start,
            MMG5_ARG_ppMesh,&mmgMesh,MMG5_ARG_ppMet,&mmgSol,
            MMG5_ARG_end);
}
Beispiel #24
0
bool MeshValidation::face_source_is_valid(
        const MatrixFr& vertices,
        const MatrixIr& faces,
        const VectorI& face_sources) {
    const Float EPS = 1e-6;
    const size_t num_vertices = vertices.rows();
    const size_t num_faces = faces.rows();

    Vector3F bbox_min = vertices.colwise().minCoeff();
    Vector3F bbox_max = vertices.colwise().maxCoeff();

    bool result = true;
    for (size_t i=0; i<num_faces; i++) {
        const Vector3I& f = faces.row(i);
        const Vector3F& v0 = vertices.row(f[0]);
        const Vector3F& v1 = vertices.row(f[1]);
        const Vector3F& v2 = vertices.row(f[2]);

        if (fabs(v0[0] - bbox_min[0]) < EPS &&
            fabs(v1[0] - bbox_min[0]) < EPS &&
            fabs(v2[0] - bbox_min[0]) < EPS) {
            result = result && (face_sources[i] == 0);
            continue;
        }

        if (fabs(v0[1] - bbox_min[1]) < EPS &&
            fabs(v1[1] - bbox_min[1]) < EPS &&
            fabs(v2[1] - bbox_min[1]) < EPS) {
            result = result && (face_sources[i] == 0);
            continue;
        }

        if (fabs(v0[2] - bbox_min[2]) < EPS &&
            fabs(v1[2] - bbox_min[2]) < EPS &&
            fabs(v2[2] - bbox_min[2]) < EPS) {
            result = result && (face_sources[i] == 0);
            continue;
        }

        if (fabs(v0[0] - bbox_max[0]) < EPS &&
            fabs(v1[0] - bbox_max[0]) < EPS &&
            fabs(v2[0] - bbox_max[0]) < EPS) {
            result = result && (face_sources[i] == 0);
            continue;
        }

        if (fabs(v0[1] - bbox_max[1]) < EPS &&
            fabs(v1[1] - bbox_max[1]) < EPS &&
            fabs(v2[1] - bbox_max[1]) < EPS) {
            result = result && (face_sources[i] == 0);
            continue;
        }

        if (fabs(v0[2] - bbox_max[2]) < EPS &&
            fabs(v1[2] - bbox_max[2]) < EPS &&
            fabs(v2[2] - bbox_max[2]) < EPS) {
            result = result && (face_sources[i] == 0);
            continue;
        }
        result = result && (face_sources[i] != 0);
        if (!result) {
            std::cout << i << ":  ";
            std::cout << face_sources[i] << std::endl;
            std::cout << v0.transpose() << std::endl;
            std::cout << v1.transpose() << std::endl;
            std::cout << v2.transpose() << std::endl;
            return result;
        }
    }
    return result;
}