-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
405 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Copyright © 2024 Forschungszentrum Jülich GmbH | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
#include "disjoint_set.hpp" | ||
|
||
#include <cassert> | ||
#include <numeric> | ||
#include <stdexcept> | ||
|
||
DisjointSet::DisjointSet(size_t count_elements) : parent(count_elements) | ||
{ | ||
std::iota(std::begin(parent), std::end(parent), 0); | ||
} | ||
|
||
size_t DisjointSet::Find(size_t id) | ||
{ | ||
if(id >= parent.size()) { | ||
throw std::runtime_error("Unknown id"); | ||
}; | ||
if(parent[id] != id) { | ||
parent[id] = Find(id); | ||
} | ||
return parent[id]; | ||
} | ||
|
||
void DisjointSet::Union(size_t id_a, size_t id_b) | ||
{ | ||
const auto a = Find(id_a); | ||
const auto b = Find(id_b); | ||
parent[b] = a; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright © 2024 Forschungszentrum Jülich GmbH | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
#pragma once | ||
|
||
#include <cstddef> | ||
#include <vector> | ||
|
||
class DisjointSet | ||
{ | ||
std::vector<size_t> parent{}; | ||
|
||
public: | ||
DisjointSet(size_t count_elements); | ||
~DisjointSet() = default; | ||
size_t Find(size_t id); | ||
void Union(size_t id_a, size_t id_b); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
// Copyright © 2024 Forschungszentrum Jülich GmbH | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
#include "mesh.hpp" | ||
#include "disjoint_set.hpp" | ||
#include "wkt.hpp" | ||
|
||
#include <CGAL/number_utils.h> | ||
|
||
#include <_types/_uint16_t.h> | ||
#include <algorithm> | ||
#include <vector> | ||
|
||
template <typename T> | ||
T into(const Point& p) | ||
{ | ||
return {CGAL::to_double(p.x()), CGAL::to_double(p.y())}; | ||
}; | ||
|
||
Mesh::Mesh(const CDT& cdt) | ||
{ | ||
vertices.resize(cdt.finite_vertex_handles().size()); | ||
for(const auto& v : cdt.finite_vertex_handles()) { | ||
vertices.at(v->info()) = into<glm::dvec2>(v->point()); | ||
} | ||
polygons.reserve(cdt.finite_face_handles().size()); | ||
|
||
std::unordered_map<CDT::Face_handle, size_t> handle_map{}; | ||
std::vector<std::vector<CDT::Face_handle>> neighbor_face_handles{}; | ||
neighbor_face_handles.reserve(polygons.capacity()); | ||
for(const CDT::Face_handle& t : cdt.finite_face_handles()) { | ||
if(!t->get_in_domain()) { | ||
continue; | ||
} | ||
Polygon p{}; | ||
p.vertices.reserve(3); | ||
p.vertices.push_back(t->vertex(0)->info()); | ||
p.vertices.push_back(t->vertex(1)->info()); | ||
p.vertices.push_back(t->vertex(2)->info()); | ||
|
||
polygons.push_back(p); | ||
neighbor_face_handles.emplace_back(); | ||
for(int index = 0; index < 3; ++index) { | ||
const auto& n = t->neighbor(index); | ||
if(n->get_in_domain()) { | ||
neighbor_face_handles.back().emplace_back(n); | ||
} | ||
} | ||
handle_map[t] = polygons.size() - 1; | ||
} | ||
assert(polygons.size() == neighbor_face_handles.size()); | ||
for(size_t index = 0; index < polygons.size(); ++index) { | ||
auto& p = polygons[index]; | ||
const auto& neighbors = neighbor_face_handles[index]; | ||
p.neighbors.reserve(neighbors.size()); | ||
for(const auto& n : neighbors) { | ||
p.neighbors.emplace_back(handle_map.at(n)); | ||
} | ||
} | ||
}; | ||
|
||
void Mesh::MergeGreedy() | ||
{ | ||
DisjointSet djs{polygons.size()}; | ||
// 1) Merge polygons with only one nieghbor, aka "dead-ends" | ||
mergeDeadEnds(djs); | ||
// 2) "Smart" merge remaining polygons | ||
// 3) Validate correctness | ||
} | ||
|
||
void Mesh::mergeDeadEnds(DisjointSet& djs) | ||
{ | ||
while(true) { | ||
for(auto&& p : polygons) { | ||
if(p.neighbors.size() != 1) { | ||
continue; | ||
} | ||
} | ||
} | ||
} | ||
|
||
void Mesh::smartMerge() | ||
{ | ||
} | ||
|
||
bool Mesh::isValid() const | ||
{ | ||
return true; | ||
} | ||
|
||
std::vector<glm::vec2> Mesh::FVertices() const | ||
{ | ||
std::vector<glm::vec2> f_vertices{}; | ||
f_vertices.reserve(vertices.size()); | ||
std::transform( | ||
std::begin(vertices), | ||
std::end(vertices), | ||
std::back_inserter(f_vertices), | ||
[](const auto& v) { | ||
return glm::vec2{v.x, v.y}; | ||
}); | ||
return f_vertices; | ||
} | ||
|
||
std::vector<uint16_t> Mesh::TriangleIndices() const | ||
{ | ||
std::vector<uint16_t> indices{}; | ||
indices.reserve(polygons.size() * 3); | ||
|
||
for(const auto& p : polygons) { | ||
const uint16_t first = p.vertices.front(); | ||
const auto count_indices = p.vertices.size(); | ||
for(size_t index = 2; index < count_indices; ++index) { | ||
indices.push_back(first); | ||
indices.push_back(p.vertices[index - 1]); | ||
indices.push_back(p.vertices[index]); | ||
} | ||
} | ||
return indices; | ||
} | ||
|
||
std::vector<uint16_t> Mesh::SegmentIndices() const | ||
{ | ||
using segment = std::tuple<uint16_t, uint16_t>; | ||
const auto make_segment = [](uint16_t a, uint16_t b) { | ||
if(a < b) { | ||
return std::make_tuple(a, b); | ||
} | ||
return std::make_tuple(b, a); | ||
}; | ||
|
||
std::set<segment> segments{}; | ||
|
||
for(const auto& p : polygons) { | ||
const auto vertex_count = p.vertices.size(); | ||
uint16_t a = p.vertices[vertex_count - 1]; | ||
for(size_t index = 0; index < vertex_count; ++index) { | ||
uint16_t b = p.vertices[index]; | ||
segments.insert(make_segment(a, b)); | ||
a = b; | ||
} | ||
} | ||
|
||
std::vector<uint16_t> indices{}; | ||
indices.reserve(segments.size() * 2); | ||
for(const auto& s : segments) { | ||
indices.emplace_back(std::get<0>(s)); | ||
indices.emplace_back(std::get<1>(s)); | ||
} | ||
return indices; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright © 2024 Forschungszentrum Jülich GmbH | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
#pragma once | ||
|
||
#include "disjoint_set.hpp" | ||
#include "wkt.hpp" | ||
|
||
#include <glm/vec2.hpp> | ||
|
||
#include <vector> | ||
|
||
class Mesh | ||
{ | ||
public: | ||
struct Polygon { | ||
/// Index into the vertices store of the Mesh | ||
std::vector<size_t> vertices{}; | ||
/// Index into the polygon store of the Mesh | ||
std::vector<size_t> neighbors{}; | ||
}; | ||
|
||
private: | ||
/// All vertices in this Mesh | ||
std::vector<glm::dvec2> vertices{}; | ||
/// All convex polygons in this Mesh in CCW orientation. | ||
std::vector<Polygon> polygons{}; | ||
|
||
public: | ||
Mesh(const CDT& cdt); | ||
~Mesh() = default; | ||
void MergeGreedy(); | ||
std::vector<glm::vec2> FVertices() const; | ||
std::vector<uint16_t> TriangleIndices() const; | ||
std::vector<uint16_t> SegmentIndices() const; | ||
|
||
private: | ||
Mesh(const Mesh& other) = delete; | ||
void operator=(const Mesh& other) = delete; | ||
Mesh(Mesh&& other) = delete; | ||
void operator=(Mesh&& other) = delete; | ||
void mergeDeadEnds(DisjointSet& djs); | ||
void smartMerge(); | ||
bool isValid() const; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Copyright © 2024 Forschungszentrum Jülich GmbH | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
#include "rendering_mesh.hpp" | ||
#include "mesh.hpp" | ||
|
||
RenderingMesh::RenderingMesh(const Mesh& data) | ||
{ | ||
glGenVertexArrays(2, vaos); | ||
glGenBuffers(3, buffer); | ||
|
||
const auto vertices = data.FVertices(); | ||
const auto triangle_indices = data.TriangleIndices(); | ||
index_count[0] = triangle_indices.size(); | ||
|
||
glBindVertexArray(vaos[0]); | ||
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]); | ||
glBufferData( | ||
GL_ARRAY_BUFFER, | ||
vertices.size() * sizeof(decltype(vertices)::value_type), | ||
reinterpret_cast<const GLvoid*>(vertices.data()), | ||
GL_STATIC_DRAW); | ||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), nullptr); | ||
glEnableVertexAttribArray(0); | ||
|
||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer[1]); | ||
glBufferData( | ||
GL_ELEMENT_ARRAY_BUFFER, | ||
index_count[0] * sizeof(decltype(triangle_indices)::value_type), | ||
reinterpret_cast<const GLvoid*>(triangle_indices.data()), | ||
GL_STATIC_DRAW); | ||
|
||
const auto segment_indices = data.SegmentIndices(); | ||
index_count[1] = segment_indices.size(); | ||
|
||
glBindVertexArray(vaos[1]); | ||
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]); | ||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), nullptr); | ||
glEnableVertexAttribArray(0); | ||
|
||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer[2]); | ||
glBufferData( | ||
GL_ELEMENT_ARRAY_BUFFER, | ||
index_count[1] * sizeof(decltype(segment_indices)::value_type), | ||
reinterpret_cast<const GLvoid*>(segment_indices.data()), | ||
GL_STATIC_DRAW); | ||
} | ||
|
||
RenderingMesh::~RenderingMesh() | ||
{ | ||
glDeleteBuffers(3, buffer); | ||
glDeleteBuffers(2, vaos); | ||
} | ||
|
||
void RenderingMesh::Draw(Shader& shader) const | ||
{ | ||
shader.Activate(); | ||
|
||
shader.SetUniform("color", glm::vec4(0.0f, 0.0f, 0.75f, 1.0f)); | ||
glBindVertexArray(vaos[0]); | ||
glDrawElements(GL_TRIANGLES, index_count[0], GL_UNSIGNED_SHORT, nullptr); | ||
|
||
shader.SetUniform("color", glm::vec4(0.0f, 0.75f, 0.0f, 1.0f)); | ||
glBindVertexArray(vaos[1]); | ||
glDrawElements(GL_LINES, index_count[1], GL_UNSIGNED_SHORT, nullptr); | ||
} |
Oops, something went wrong.