We say "primarily" because half-edge data structures can be used to represent somewhat more general combinatorial structures, such as, for example, a checker board surface with white squares removed.
Here, surface means two-dimensional manifold, possibly with boundary; and a cell decomposition of a surface is a graph embedded in the surface such that the complement of the graph is (topologically) a disjoint union of open disks. The term map on a surface means the same. Thus, a cell decomposition decomposes a surface into vertices, edges, and faces.
Every half-edge object holds references to:
• its oppositely oriented companion edge
• the next edge in the boundary of the face on its left hand side
• the previous edge in the boundary of the face on its left hand side
• the face on its left hand side
• the vertex it points to.
The face and vertex objects hold back references to a half-edge referencing them.
Finally, there is the class {@link de.jtem.halfedge.HalfEdgeDataStructure} representing a whole half-edge data structure. It acts as a container for (and sort of factory of) its vertices, edges, and faces.
Our half-edge data structure facilitates this by using generic classes as abstract base classes for vertex, edge, and face types: The classes {@link de.jtem.halfedge.Vertex}, {@link de.jtem.halfedge.Edge}, {@link de.jtem.halfedge.Face} are all parameterized with the associated vertex, edge, and face types.
Example. To create a half-edge data structure with vertices that have 2D coordinates, proceed as follows.
• Step 1. Define appropriate subclasses of {@link de.jtem.halfedge.Vertex}, {@link de.jtem.halfedge.Edge},
{@link de.jtem.halfedge.Face}, for example:
{@code public class MyVertex extends Vertex
{@code public class MyEdge extends Edge
{@code public class MyFace extends Face
(Of course you might make the property p
of MyEdge
private and provide getter and setter methods, etc.)
Note that you always have to subclass {@link de.jtem.halfedge.Vertex}, {@link de.jtem.halfedge.Edge},
and {@link de.jtem.halfedge.Face}, even if you do not define any additional functionality or properties.
• Step 2. Instantiate a {@link de.jtem.halfedge.HalfEdgeDataStructure}:
{@code HalfEdgeDataStructure
The parameters of the constructor serve as run time type tokens.
• Step 3. Instantiate vertices, edges, and faces using {@link de.jtem.halfedge.HalfEdgeDataStructure#addNewVertex() addNewVertex()},
{@link de.jtem.halfedge.HalfEdgeDataStructure#addNewEdge() addNewEdge()}, and {@link de.jtem.halfedge.HalfEdgeDataStructure#addNewFace() addNewFace()},
like this:
{@code MyVertex v = heds.addNewVertex();}
{@code MyEdge e = heds.addNewEdge();}
{@code MyFace f = heds.addNewFace();}