There are many ways of managing these sorts of relationships but if you want efficiency and you want to share vertices between edges and share edges between faces then I suggest your Solid
should own a complete list of Vertex
and Edges
.
Then Edge
has some sort of non-owning reference to its vertices and Face
has some sort of non-owning reference to its edges. Those non-owning references could be something like a pointer but you then have to be careful you don't invalidate those pointers by reallocating the main list of vertices or edges. It is safer if you store indices instead. But that does mean you have to refer to Solid
to find out what a vertex/edge index refers to:
class Solid {
std::vector<Vertex> vertices;
std::vector<Edge> edges;
std::vector<Face> faces;
public:
Solid(std::vector<Vertex> vertices) : vertices(std::move(vertices)) {}
void addEdge(int vertex_index1, int vertex_index2) {
edges.emplace_back(vertex_index1, vertex_index2);
}
void addFace(std::vector<int> edge_indices) {
faces.emplace_back(std::move(edge_indices));
}
const Vertex &getVertex(int vertex_index) const { return vertices[vertex_index]; }
const Edge &getEdge(int edge_index) const { return edges[edge_index]; }
};
class Edge {
int vertex_first;
int vertex_second;
public:
Edge(int vertex_first, int vertex_second)
: vertex_first(vertex_first), vertex_second(vertex_second) {}
const Vertex &getVertexFirst(const Solid &solid) const {
return solid.getVertex(vertex_first);
}
const Vertex &getVertexSecond(const Solid &solid) const {
return solid.getVertex(vertex_second);
}
};
class Face {
std::vector<int> edge_indices;
int getEdgeIndex(int face_edge_index) const {
return edge_indices[face_edge_index];
}
public:
Face(std::vector<int> edge_indices) : edge_indices(std::move(edge_indices)) {}
const Edge &getEdge(int face_edge_index, const Solid &solid) const {
return solid.getEdge(getEdgeIndex(face_edge_index));
}
};
Live demo.
An alternative is to use std::shared_ptr
for Edge
and Vertex
but then you have to pay for the dynamic memory allocation and poorer data locality.
It is tempting to store a back-reference to Solid
inside Face
and Edge
for better encapsulation. You could do that but then the vector
of Face
and Edge
effectively contain a lot of duplicate pointers. If that sort of encapsulation is important to you I suggest you create some sort of wrapper classes for working with edges and faces that contain the raw edge/face object and also a back-reference to the Solid
.