Add support for obj files with multiple connected components

pull/170/head
James Ball 2023-01-20 21:39:21 +00:00
rodzic 56efe597cb
commit d8256ac812
1 zmienionych plików z 106 dodań i 39 usunięć

Wyświetl plik

@ -8,6 +8,36 @@ struct pair_hash {
}
};
std::vector<std::vector<int>> ConnectedComponents(const Graph& G) {
std::vector<std::vector<int>> components;
std::vector<bool> visited(G.GetNumVertices(), false);
list<int> L;
for (int i = 0; i < visited.size(); i++) {
// if condition should only be true for the first element in
// a new connected component
if (!visited[i]) {
components.emplace_back();
// Breadth First Search
L.push_back(i);
while (not L.empty()) {
int u = L.back();
L.pop_back();
if (visited[u]) continue;
visited[u] = true;
components.back().push_back(u);
for (int v : G.AdjList(u)) {
L.push_back(v);
}
}
}
}
return components;
}
WorldObject::WorldObject(juce::InputStream& stream) {
tinyobj::ObjReaderConfig reader_config;
tinyobj::ObjReader reader;
@ -16,35 +46,6 @@ WorldObject::WorldObject(juce::InputStream& stream) {
vs = reader.GetAttrib().vertices;
numVertices = vs.size() / 3;
std::vector<tinyobj::shape_t> shapes = reader.GetShapes();
std::unordered_set<std::pair<int, int>, pair_hash> edge_set;
for (auto& shape : shapes) {
int i = 0;
int face = 0;
while (i < shape.mesh.indices.size()) {
int prevVertex = -1;
for (int j = 0; j < shape.mesh.num_face_vertices[face]; j++) {
int vertex = shape.mesh.indices[i].vertex_index;
if (prevVertex != -1) {
edge_set.insert(std::make_pair(prevVertex, vertex));
}
prevVertex = vertex;
i++;
}
face++;
}
}
std::list<std::pair<int, int>> edge_list;
for (auto& edge : edge_set) {
edge_list.push_back(edge);
}
Graph graph(numVertices, edge_list);
pair<list<int>, double> solution = ChinesePostman(graph);
list<int>& path = solution.first;
double x = 0.0, y = 0.0, z = 0.0;
double max = 0.0;
@ -73,8 +74,73 @@ WorldObject::WorldObject(juce::InputStream& stream) {
vs[i * 3 + 2] = (vs[i * 3 + 2] - z) / max;
}
std::vector<tinyobj::shape_t> shapes = reader.GetShapes();
std::unordered_set<std::pair<int, int>, pair_hash> edge_set;
for (auto& shape : shapes) {
int i = 0;
int face = 0;
while (i < shape.mesh.indices.size()) {
int prevVertex = -1;
for (auto& vertex : path) {
for (int j = 0; j < shape.mesh.num_face_vertices[face]; j++) {
int vertex = shape.mesh.indices[i].vertex_index;
if (prevVertex != -1) {
edge_set.insert(std::make_pair(prevVertex, vertex));
}
prevVertex = vertex;
i++;
}
face++;
}
}
std::list<std::pair<int, int>> edge_list;
for (auto& edge : edge_set) {
edge_list.push_back(edge);
}
Graph graph(numVertices, edge_list);
std::vector<std::vector<int>> connected_components = ConnectedComponents(graph);
for (auto& connected_component : connected_components) {
std::vector<bool> present_vertices(graph.GetNumVertices(), false);
for (int vertex : connected_component) {
present_vertices[vertex] = true;
}
std::unordered_map<int, int> obj_to_graph_vertex;
std::unordered_map<int, int> graph_to_obj_vertex;
int count = 0;
for (int i = 0; i < graph.GetNumVertices(); i++) {
if (present_vertices[i]) {
obj_to_graph_vertex[i] = i - count;
graph_to_obj_vertex[i - count] = i;
} else {
count++;
}
}
std::list<std::pair<int, int>> sub_edge_list;
for (int obj_start : connected_component) {
for (int obj_end : graph.AdjList(obj_start)) {
int graph_start = obj_to_graph_vertex[obj_start];
int graph_end = obj_to_graph_vertex[obj_end];
sub_edge_list.push_back(std::make_pair(graph_start, graph_end));
}
}
Graph subgraph(connected_component.size(), sub_edge_list);
pair<list<int>, double> solution = ChinesePostman(subgraph);
list<int>& path = solution.first;
int prevVertex = -1;
for (auto& graph_vertex : path) {
int vertex = graph_to_obj_vertex[graph_vertex];
if (prevVertex != -1) {
double x1 = vs[prevVertex * 3];
double y1 = vs[prevVertex * 3 + 1];
@ -87,4 +153,5 @@ WorldObject::WorldObject(juce::InputStream& stream) {
}
prevVertex = vertex;
}
}
}