Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cut holes in mesh #144

Open
mariuszhermansdorfer opened this issue Mar 1, 2023 · 2 comments
Open

Cut holes in mesh #144

mariuszhermansdorfer opened this issue Mar 1, 2023 · 2 comments

Comments

@mariuszhermansdorfer
Copy link

First of all, a huge thanks for creating this fantastic library!

I've been experimenting with GC inside of Rhino to work with modelling terrains. One thing I'm struggling with is cutting holes in the mesh. Consider this basic example:

Initial mesh:
image

Faces to remove:
image

Resulting mesh with a hole inside:
image

I tried several approaches:

  1. Omit the interior faces while constructing a new mesh:
    ManifoldSurfaceMesh::ManifoldSurfaceMesh(const std::vector<std::vector<size_t>>& polygons) : SurfaceMesh(true) {

This fails here:

std::vector<char> vertexOnBoundary(nVerticesCount, false);
for (size_t iHe = 0; iHe < nHalfedgesCount; iHe++) {
if (heNextArr[iHe] == INVALID_IND) {
size_t v = heVertexArr[iHe];
GC_SAFETY_ASSERT(!vertexOnBoundary[v],
"vertex " + std::to_string(v) + " appears in more than one boundary loop");
vertexOnBoundary[v] = true;
}

  1. Pass the edges defining the interior boundary to the SeparateEdge function
    std::tuple<Halfedge, Halfedge> ManifoldSurfaceMesh::separateEdge(Edge e) {

Which fails here;

// === Case 4: both vertices are same boundaries
// need to split off disconnected compoent of surface
// TODO implement
if (vAIsBoundary && vBIsBoundary && boundaryLoopA == boundaryLoopB) {
throw std::runtime_error("not implemented: separateEdge() creating disconnected components");
return std::tuple<Halfedge, Halfedge>{Halfedge(), Halfedge()};
}

Is there a straight-forward way to define an edge loop as a boundary?
@nmwsharp, @MarkGillespie, @keenancrane

@mariuszhermansdorfer
Copy link
Author

Progress update:

It is stated in the comments that input polygons need to be dense. This means that naively omitting selected faces will obviously not work.

ManifoldSurfaceMesh::ManifoldSurfaceMesh(const std::vector<std::vector<size_t>>& polygons) : SurfaceMesh(true) {
// Assumes that the input index set is dense. This sometimes isn't true of (eg) obj files floating around the
// internet, so consider removing unused vertices first when reading from foreign sources.

A workaround I found is to first construct a SimplePolygonMesh, compress it and then create a ManifoldSurfaceMesh

  SimplePolygonMesh simpleMesh(meshFaces, vertexPositions);
  simpleMesh.stripUnusedVertices();
  auto lvals = makeManifoldSurfaceMeshAndGeometry(simpleMesh.polygons, simpleMesh.vertexCoordinates);

This works, but is relatively slow for larger meshes and recreating all connectivity from scratch on each mutation definitely feels heavy-handed.

I'd still like to understand how to correctly delete faces from an existing mesh. I found the following description in the docs:

Deleted halfedges and their edges are implicitly encoded by heNext[he] == INVALID_IND, while deleted edges and vertices are encoded by vHalfedge[v] == INVALID_IND and fHalfedge[f] == INVALID_IND.

Does deleting a face mean setting all the core arrays to INVALID_IND for all halfedges describing this face?

  std::vector<size_t> heNextArr;    // he.next(), forms a circular singly-linked list in each face
  std::vector<size_t> heVertexArr;  // he.vertex()
  std::vector<size_t> heFaceArr;    // he.face()
  std::vector<size_t> vHalfedgeArr; // v.halfedge()
  std::vector<size_t> fHalfedgeArr; // f.halfedge()

@HarryRos
Copy link

+1 for a feature request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants