Skip to content

autorefine_triangle_soup sometimes resolves self-intersection by producing non-manifold structure #9192

@pentacular

Description

@pentacular

Issue Details

I am trying to resolve self-intersections which are self-touches -- i.e., no interpenetration.

autorefine_triangle_soup looks like it should do this, but I find that it prefers to resolve self-intersection by producing non-manifold results. :)

Below I include a test-case which builds two tetrahedrons with one common point, but no common vertices.

Is there a way to get it to either cleanly separate or cleanly merge the volumes?

Thanks.

Source Code

#include <cassert>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <set>
#include <utility>
#include <vector>

#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/IO/OBJ.h>
#include <CGAL/Polygon_mesh_processing/autorefinement.h>
#include <CGAL/Polygon_mesh_processing/manifoldness.h>
#include <CGAL/Polygon_mesh_processing/self_intersections.h>
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
#include <CGAL/Polygon_mesh_processing/measure.h>
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
#include <CGAL/Surface_mesh.h>

typedef CGAL::Exact_predicates_exact_constructions_kernel Epeck;
typedef Epeck::Point_3 Point_3;
typedef CGAL::Surface_mesh<Point_3> Surface_mesh;

void test_self_point_touch_repair() {
  std::vector<Point_3> original_soup_points;
  std::vector<std::array<std::size_t, 3>> original_soup_triangles;

  // Tetrahedron 1 points
  original_soup_points.push_back(Point_3(0, 0, 0));
  original_soup_points.push_back(Point_3(1, 0, 0));
  original_soup_points.push_back(Point_3(0, 1, 0));
  original_soup_points.push_back(Point_3(0, 0, 1));

  // Tetrahedron 2 points
  original_soup_points.push_back(Point_3(0, 0, 0));
  original_soup_points.push_back(Point_3(-1, 0, 0));
  original_soup_points.push_back(Point_3(0, -1, 0));
  original_soup_points.push_back(Point_3(0, 0, -1));

  // Faces for Tetrahedron 1 (using indices 0,1,2,3)
  original_soup_triangles.push_back({0, 1, 2});
  original_soup_triangles.push_back({0, 2, 3});
  original_soup_triangles.push_back({0, 3, 1});
  original_soup_triangles.push_back({1, 3, 2});

  // Faces for Tetrahedron 2 (using indices 4,5,6,7)
  original_soup_triangles.push_back({4, 5, 6});
  original_soup_triangles.push_back({4, 6, 7});
  original_soup_triangles.push_back({4, 7, 5});
  original_soup_triangles.push_back({5, 7, 6});

  // Write original soup to OBJ
  std::ofstream original_outfile("original.obj");
  CGAL::IO::write_OBJ(original_outfile, original_soup_points, original_soup_triangles);
  original_outfile.close();

  // The original is a manifold self-intersecting at (0, 0, 0).
  /*
    v 0 0 0
    v 1 0 0
    v 0 1 0
    v 0 0 1
    v 0 0 0
    v -1 0 0
    v 0 -1 0
    v 0 0 -1
    f  1 2 3
    f  1 3 4
    f  1 4 2
    f  2 4 3
    f  5 6 7
    f  5 7 8
    f  5 8 6
    f  6 8 7
  */

  std::vector<Point_3> repaired_soup_points = original_soup_points;
  std::vector<std::array<std::size_t, 3>> repaired_soup_triangles = original_soup_triangles;

  const auto& snap_rounding_option =
      CGAL::parameters::apply_iterative_snap_rounding(true);
  bool success_autorefine =
      CGAL::Polygon_mesh_processing::autorefine_triangle_soup(
          repaired_soup_points, repaired_soup_triangles, snap_rounding_option);
  assert(success_autorefine);

  // Write repaired soup to OBJ
  std::ofstream outfile_soup("result_soup.obj");
  CGAL::IO::write_OBJ(outfile_soup, repaired_soup_points,
                      repaired_soup_triangles);
  outfile_soup.close();

  // autorefine_triangle_soup merges the two (0, 0, 0) resolving the self-intersection
  // but making it non-manifold.
  /*
    v 0 0 0
    v 1 0 0
    v 0 1 0
    v 0 0 1
    v -1 0 0
    v 0 -1 0
    v 0 0 -1
    f  1 2 3
    f  1 3 4
    f  1 4 2
    f  2 4 3
    f  1 5 6
    f  1 6 7
    f  1 7 5
    f  5 7 6
  */

  // Separating the points via snap-rounding would solve the problem correctly,
  // but this solution seems inaccessible.
}

int main() {
  test_self_point_touch_repair();
  return 0;
}

Environment

  • Operating system (Windows/Mac/Linux, 32/64 bits): Linux 64 bit
  • Compiler: gcc
  • Release or debug mode:
  • Specific flags used (if any):
  • CGAL version: head
  • Boost version:
  • Other libraries versions if used (Eigen, TBB, etc.):

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions