项目作者: pierre-b-geom

项目描述 :
A Java libray for creating and editing half-edge data structure
高级语言: Java
项目地址: git://github.com/pierre-b-geom/hgeom.git
创建时间: 2018-06-14T15:50:17Z
项目社区:https://github.com/pierre-b-geom/hgeom

开源协议:GNU Lesser General Public License v3.0

下载


HGeom

HGeom is a Java library for creating and manipulating half-edge data structure

A half-edge data structure is a model for representing a polygon mesh

It allows efficient topological operations on a mesh such as removing a vertex or an edge, splitting a polygon or merging 2 polygons

Traversals of meshes along vertices, edges or polygons are also efficiently performed with the help of a half-edge data structure

A half-edge data structure is modelized in HGeom by the Java class HMesh

To create a HMesh, see below

Go here to find a description of HMesh and to know how to edit a HMesh

Go here to learn how to navigate inside a HMesh

Go here for some examples of HMesh uses

Creation of a half-edge data structure in HGeom

There are two ways to create a half-edge data structure with HGeom:

1. Creation of a half-edge data structure from a list of polygons

A HMesh can be automatically generated from a list of polygons where each polygon is defined by a list of indices to vertices.

Let’s take this mesh as an example:



The mesh contains 7 vertices:

Vertex indices Vertices
0 v0
1 v1
2 v2
3 v3
4 v4
5 v5
6 v6

and 3 polygons:

Polygon indices Polygon Polygon definition as indices to vertices
0 p0 [0, 1, 2, 6]
1 p1 [2, 5, 6]
2 p2 [2, 3, 4, 5]

To generate a HMesh from this mesh, we first create a FaceSource from the collection of polygons:

  1. // The polygons as arrays of indices to vertices:
  2. int[][] polygons = {{0, 1, 2, 6}, {2, 5, 6}, {2, 3, 4, 5}};
  3. // Build the face source. a FaceSource can be built from
  4. // various types of iterable collection of faces / polygons
  5. FaceSource faceSource = new FaceSource(polygons);

We then convert the FaceSource into a HMesh:

  1. Optional<HMesh> mesh = faceSource.toHMesh();

Or, by extracting the result from the Optional:

  1. HMesh mesh = faceSource.toHMesh().orElseThrow(
  2. () -> new IllegalStateException(
  3. "couldn't convert polygons into a half-edge DS"));

Each initial edge is splitted into 2 half-edges in the generated half-edge data structure:



The generated half-edge data structure contains 4 polygons, that is, one more than the initial number of polygons:

  • 3 polygons modelizing the 3 intial polygons : [0, 1, 2, 6], [2, 5, 6], [2, 3, 4, 5] (in the half-edge data structure, a polygon is a cycle of half-edges, each one connecting 2 vertices)
  • An extra polygon which is the outer border of the mesh : [0 6 5 4 3 2 1]

The half-edge data structure is automatically generated by an algorithm wich uses the topological links between the initial polygons to produce half-edges and connect them together. A generated HMesh is always consistent

If 2D coordinates are attached to the vertices:



Vertex indices Vertices 2D coords
0 v0 [0, 0]
1 v1 [0, 1]
2 v2 [1, 1]
3 v3 [2, 1]
4 v4 [2, 0]
5 v5 [1.7, 0]
6 v6 [1, 0]

Then a HMesh2D (a version of HMesh for the 2D space) can be created using these coordinates:

  1. int[][] polygons = {{0, 1, 2, 6}, {2, 5, 6}, {2, 3, 4, 5}};
  2. double[][] vertexCoords = {{0, 0}, {0, 1}, {1, 1}, {2, 1}, {2, 0}, {1.7, 0}, {1, 0}};
  3. FaceSource faceSource = new FaceSource(polygons);
  4. // Wrap the vertex coordinates into a Coords2DSource. a Coords2DSource can wrap
  5. // various types of iterable collection of 2D coordinates
  6. Coords2DSource coordSource = new Coords2DSource(vertexCoords);
  7. // Crate the HMesh using both the FaceSource and the Coords2DSource
  8. HMesh2D mesh = faceSource.toHMesh2D(coordSource).orElseThrow(...);

If 3D coordinates are attached to the vertices, a HMesh3D can similarly be created with the help of a Coords3DSource

If some data are attached either to the polygons or to the vertices :

Vertex indices Vertices Weights
0 v0 3.5
1 v1 2.1
2 v2 5.5
3 v3 7.4
4 v4 2.3
5 v5 6.7
6 v6 4.7
Polygon indices Polygon Colors
0 p0 Green
1 p1 Red
2 p2 Yellow

Then, these data can be associated to the HMesh’s elements with a more elaborate conversion process:

  1. int[][] polygons = {{0, 1, 2, 6}, {2, 5, 6}, {2, 3, 4, 5}};
  2. double[] vertexWeights = {3.5, 2.1, 5.5, 7.4, 2.3, 6.7, 4.7};
  3. Color[] polygonColors = {Color.Green, Color.Red, Color.Yellow};
  4. FaceSource faceSource = new FaceSource(faces);
  5. // Create a converter to HMesh
  6. ToHMeshConverter converter = new ToHMeshConverter();
  7. // Convert the face source using the converter. The result is a HConversion
  8. HConversion<HMesh> conversion = converter.convert(faceSource).orElseThrow(...);
  9. // Extract the HMesh from the HConversion
  10. HMesh mesh = conversion.mesh();
  11. // Use the HConversion to convert the initial data into
  12. // data associated to the vertices of the HMesh
  13. HDData<HVertex> meshVertexWeights = conversion.meshVertexDoubleData(i -> vertexWeights[i]);
  14. // Use the HConversion to convert the initial data into
  15. // data associated to the faces of the HMesh
  16. HData<HFace> meshFaceColors = conversion.meshFaceData(i -> polygonColors[i]);

2. Creation of a half-edge data structure from a list of edges

A HMesh can automatically be generated from a list of edges where each edge is defined by a pair of indices to vertices.

Let’s take this set of edges as an example:



The edges are defined as pair of indices to vertices:

Edge indices Edge Edge definition as pair of indices to vertices
0 e0 [1, 0]
1 e1 [2, 1]
2 e2 [2, 5]
3 e3 [3, 2]
4 e4 [5, 3]
5 e5 [3, 4]
6 e6 [5, 4]
7 e7 [5, 6]
8 e8 [0, 6]

To generate a HMesh from this mesh, we first create a EdgeSource from the collection of edges:

  1. // The edges as arrays of pairs of indices to vertices:
  2. int[][] edges = {{1, 0}, {2, 1}, {2, 5}, {3, 2}, {5, 3}, {3, 4}, {5, 4}, {5, 6}, {0, 6}};
  3. // Build the edge source. a EdgeSource can be build from
  4. // various types of iterable collection of edges
  5. EdgeSource edgeSource = new EdgeSource(edges);

We can then convert the EdgeSource into a HMesh using a PolygonWindingProvider:

  1. PolygonWindingProvider polygonWindingProvider = ...
  2. HMesh mesh = faceSource.toHMesh(polygonWindingProvider).orElseThrow(...);

A polygon winding provider is a tool used by the half-edge data structure conversion process for making the right connections between the edges

  1. Another possibility is to use 2D coordinates associated with the vertices:
  1. // The edges as arrays of pairs of indices to vertices:
  2. int[][] edges = {{1, 0}, {2, 1}, {2, 5}, {3, 2}, {5, 3}, {3, 4}, {5, 4}, {5, 6}, {0, 6}};
  3. double[][] vertexCoords = {{0, 0}, {0, 1}, {.5, 1}, {2, 1}, {2, 0}, {1.5, 0}, {.5, 0}};
  4. EdgeSource edgeSource = new EdgeSource(edges);
  5. Coords2DSource coordSource = new Coords2DSource(vertexCoords);
  6. HMesh2D mesh = edgeSource.toHMesh(coordSource).orElseThrow(...);

Here, it is the 2D coordinates that are used to connect the edges

Extra data can be associated with both the vertices and the edges in the similar way than for the polygons:

  1. int[][] edges = {{1, 0}, {2, 1}, {2, 5}, {3, 2}, {5, 3}, {3, 4}, {5, 4}, {5, 6}, {0, 6}};
  2. double[][] vertexCoords = {{0, 0}, {0, 1}, {.5, .5}, {2, 1}, {2, 0}, {1.5, 0}, {.5, 0}};
  3. double[] vertexWeights = {3.5, 2.1, 5.5, 7.4, 2.3, 6.7, 4.7};
  4. Color[] edgeColors = {Color.Green, Color.Red, Color.Yellow, Color.Blue, ...};
  5. EdgeSource edgeSource = new EdgeSource(edges);
  6. Coords2DSource coordSource = new Coords2DSource(vertexCoords);
  7. // Create a converter to HMesh
  8. ToHMeshConverter converter = new ToHMeshConverter();
  9. // Convert the edge source using the converter.
  10. HConversion<HMesh> conversion = converter.convert(edgeSource, coordSource).orElseThrow(...);
  11. // Extract the HMesh from the HConversion
  12. HMesh mesh = conversion.mesh();
  13. // Use the HConversion to convert the initial data into
  14. // data associated to the vertices of the HMesh
  15. HDData<HVertex> meshVertexWeights = conversion.meshVertexDoubleData(i -> vertexWeights[i]);
  16. // Use the HConversion to convert the initial data into
  17. // data associated to the edges of the HMesh
  18. HData<HEdge> meshEdgeColors = conversion.meshEdgeData(i -> edgeColors[i]);