CGAL / cgal

The public CGAL repository, see the README below
https://github.com/CGAL/cgal#readme
Other
5k stars 1.39k forks source link

how can i do offset meshing with a negative offset value using coding as same as with the polyhedron_3.exe ? #7877

Closed liu411417492 closed 7 months ago

liu411417492 commented 12 months ago

Issue Details

when I use the polyhedron_3.exe, I found this demo can do offset meshing with a negative offset value (although the tips said you should input the positive value), and the demo gave me the negative offset mesh as a result。 so my question is how can I do the same thing with code? which API should I call?

I noticed that alpha_wrap_3 can not generate the result when the offset parameter is negative.

Source Code

Mesh sm_extend;

CGAL::alpha_wrap_3(all_teeth_R, 3, 3, sm_extend);

namespace params = CGAL::parameters;

CGAL::Subdivision_method_3::Loop_subdivision(sm_extend, params::number_of_iterations(2));

CGAL::IO::write_polygon_mesh("alpha_out_1121R_before.obj", sm_extend);

Mesh sm_test;

CGAL::alpha_wrap_3(sm_extend, 3, -3, sm_test);

CGAL::IO::write_polygon_mesh("alpha_out_1121R_compare.obj", sm_test);

Environment

MaelRL commented 12 months ago

Here is the code for the offset plugin of the demo.

3D alpha wrapping by default wraps from outside. You can also wrap from inside if you set up seeds, see this example.

liu411417492 commented 12 months ago

Here is the code for the offset plugin of the demo.

3D alpha wrapping by default wraps from outside. You can also wrap from inside if you set up seeds, see this example.

the code for the offset plugin of the demo is too complicated for me ,but I try the example. ,I change the seed to be a point(0,0,0) which is out of input model,but the result did not changed , so how should I modify the example code to achieve my goal

MaelRL commented 12 months ago

The seed point tags the region you want to carve: if you put the point outside, it'll carve outside, if you put it inside, it'll carve inside.

liu411417492 commented 12 months ago

The seed point tags the region you want to carve: if you put the point outside, it'll carve outside, if you put it inside, it'll carve inside.

int testNAmain()

{

    namespace PMP = CGAL::Polygon_mesh_processing;

    using K = CGAL::Exact_predicates_inexact_constructions_kernel;
    using Point_3 = K::Point_3;

    using Mesh = CGAL::Surface_mesh<Point_3>;
    // Read the input
    const std::string filename = CGAL::data_file_path("armadillo.off");
    std::cout << "Reading " << filename << "..." << std::endl;

    Mesh input;
    if (!PMP::IO::read_polygon_mesh(filename, input))
    {
        std::cerr << "Invalid input." << std::endl;
        return EXIT_FAILURE;
    }

    std::cout << "Input: " << num_vertices(input) << " vertices, " << num_faces(input) << " faces" << std::endl;

    const double relative_alpha = 30.;
    const double relative_offset = 600.;

    // Compute the alpha and offset values
    CGAL::Bbox_3 bbox = CGAL::Polygon_mesh_processing::bbox(input);
    const double diag_length = std::sqrt(CGAL::square(bbox.xmax() - bbox.xmin()) +
        CGAL::square(bbox.ymax() - bbox.ymin()) +
        CGAL::square(bbox.zmax() - bbox.zmin()));

    const double alpha = diag_length / relative_alpha;
    const double offset = diag_length / relative_offset;

    // Construct the wrap
    CGAL::Real_timer t;
    t.start();

    // There is no limit on how many seeds can be used.
    // However, the algorithm automatically determines whether a seed can be used
    // to initialize the refinement based on a few conditions (distance to the offset, value of alpha, etc.)
    // See internal function Alpha_wrap_3::initialize_from_cavities() for more information
    std::vector<Point_3> seeds =
    {
      Point_3(0, 0, 0) // a point within the armadillo surface
    };

    Mesh wrap;
    alpha_wrap_3(input, alpha, offset * -1, wrap, CGAL::parameters::seed_points(std::ref(seeds)));

    t.stop();
    std::cout << "Result: " << num_vertices(wrap) << " vertices, " << num_faces(wrap) << " faces" << std::endl;
    std::cout << "Took " << t.time() << " s." << std::endl;

    // Save the result
    std::string input_name = std::string(filename);
    input_name = input_name.substr(input_name.find_last_of("/") + 1, input_name.length() - 1);
    input_name = input_name.substr(0, input_name.find_last_of("."));
    std::string output_name = input_name + "_cavity_" + std::to_string(static_cast<int>(relative_alpha))
        + "_" + std::to_string(static_cast<int>(relative_offset)) + ".off";
    std::cout << "Writing to " << output_name << std::endl;
    CGAL::IO::write_polygon_mesh(output_name, wrap, CGAL::parameters::stream_precision(17));

    return EXIT_SUCCESS;
}

Actually, I changed the example you gave for only the seed point, now the seed point (0,0,0) is on the different side compared with the demo, however, the result did not make any difference

MaelRL commented 12 months ago

Can you please share your input data and complete code?

liu411417492 commented 11 months ago

Can you please share your input data and complete code?

sure! Here's my code, actually, I just want to offset meshing with a negative offset value.

int testNAmain()
{

    namespace PMP = CGAL::Polygon_mesh_processing;

    using K = CGAL::Exact_predicates_inexact_constructions_kernel;
    using Point_3 = K::Point_3;

    using Mesh = CGAL::Surface_mesh<Point_3>;
    // Read the input
    const std::string filename = CGAL::data_file_path("armadillo.off");
    std::cout << "Reading " << filename << "..." << std::endl;

    Mesh input;
    if (!PMP::IO::read_polygon_mesh(filename, input))
    {
        std::cerr << "Invalid input." << std::endl;
        return EXIT_FAILURE;
    }

    std::cout << "Input: " << num_vertices(input) << " vertices, " << num_faces(input) << " faces" << std::endl;

    const double relative_alpha = 30.;
    const double relative_offset = 600.;

    // Compute the alpha and offset values
    CGAL::Bbox_3 bbox = CGAL::Polygon_mesh_processing::bbox(input);
    const double diag_length = std::sqrt(CGAL::square(bbox.xmax() - bbox.xmin()) +
        CGAL::square(bbox.ymax() - bbox.ymin()) +
        CGAL::square(bbox.zmax() - bbox.zmin()));

    const double alpha = diag_length / relative_alpha;
    const double offset = diag_length / relative_offset;

    // Construct the wrap
    CGAL::Real_timer t;
    t.start();

    // There is no limit on how many seeds can be used.
    // However, the algorithm automatically determines whether a seed can be used
    // to initialize the refinement based on a few conditions (distance to the offset, value of alpha, etc.)
    // See internal function Alpha_wrap_3::initialize_from_cavities() for more information
    std::vector<Point_3> seeds =
    {
      Point_3(0, 0, 0) // a point within the armadillo surface
    };

    Mesh wrap;
    alpha_wrap_3(input, alpha, offset * -1, wrap, CGAL::parameters::seed_points(std::ref(seeds)));

    t.stop();
    std::cout << "Result: " << num_vertices(wrap) << " vertices, " << num_faces(wrap) << " faces" << std::endl;
    std::cout << "Took " << t.time() << " s." << std::endl;

    // Save the result
    std::string input_name = std::string(filename);
    input_name = input_name.substr(input_name.find_last_of("/") + 1, input_name.length() - 1);
    input_name = input_name.substr(0, input_name.find_last_of("."));
    std::string output_name = input_name + "_cavity_" + std::to_string(static_cast<int>(relative_alpha))
        + "_" + std::to_string(static_cast<int>(relative_offset)) + ".off";
    std::cout << "Writing to " << output_name << std::endl;
    CGAL::IO::write_polygon_mesh(output_name, wrap, CGAL::parameters::stream_precision(17));

    return EXIT_SUCCESS;
}

int main(){
  testNAmain();
  return 1;
}

Here is the input model armadillo.off armadillo.zip

MaelRL commented 7 months ago

As documented, the offset parameter must be (strictly) positive.

Also, since you are interested in the inward offset, you should use a seed within the armadillo, for example -6.656980991, 25.0099659, 10.5044879. Here is what you get (note that since the alpha is large, you don't get the offset mesh in the tight parts):

image