Update triangulation example: use input GeoJSON and support multipolygon
All checks were successful
Run tests / Run tests (push) Successful in 7m5s
All checks were successful
Run tests / Run tests (push) Successful in 7m5s
This commit is contained in:
parent
e032f8d54b
commit
63f247c877
3 changed files with 71 additions and 3109 deletions
|
|
@ -17,8 +17,15 @@
|
||||||
#include <psemek/math/swizzle.hpp>
|
#include <psemek/math/swizzle.hpp>
|
||||||
#include <psemek/random/generator.hpp>
|
#include <psemek/random/generator.hpp>
|
||||||
#include <psemek/random/uniform.hpp>
|
#include <psemek/random/uniform.hpp>
|
||||||
|
#include <psemek/io/file_stream.hpp>
|
||||||
|
|
||||||
#include <fstream>
|
// #include <boost/preprocessor/stringize.hpp>
|
||||||
|
|
||||||
|
// #define RAPIDJSON_ASSERT(x) if (!(x)) throw ::psemek::util::exception("Error parsing glTF: " BOOST_PP_STRINGIZE(x));
|
||||||
|
// #define RAPIDJSON_NOEXCEPT_ASSERT(x)
|
||||||
|
|
||||||
|
#include <rapidjson/document.h>
|
||||||
|
#include <rapidjson/istreamwrapper.h>
|
||||||
|
|
||||||
using namespace psemek;
|
using namespace psemek;
|
||||||
|
|
||||||
|
|
@ -27,54 +34,79 @@ struct triangulation_app
|
||||||
{
|
{
|
||||||
triangulation_app(options const &, context const &)
|
triangulation_app(options const &, context const &)
|
||||||
{
|
{
|
||||||
std::ifstream in(PSEMEK_EXAMPLES_DIR "/turkey");
|
std::vector<std::vector<math::point<float, 2>>> rings;
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
math::point<float, 2> p;
|
auto input_json = io::read_full(io::file_istream(PSEMEK_EXAMPLES_DIR "/turkey.geo.json")).string();
|
||||||
in >> p[0] >> p[1];
|
|
||||||
if (!in)
|
|
||||||
break;
|
|
||||||
points_.push_back(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::reverse(points_.begin(), points_.end());
|
rapidjson::Document document;
|
||||||
|
document.ParseInsitu(input_json.data());
|
||||||
|
|
||||||
for (std::size_t i = 0; i < points_.size();)
|
for (auto const & polygon : document["features"].GetArray()[0]["geometry"]["coordinates"].GetArray())
|
||||||
{
|
|
||||||
std::size_t j = (i + 1) % points_.size();
|
|
||||||
if (points_[i] == points_[j])
|
|
||||||
{
|
{
|
||||||
points_.erase(points_.begin() + i);
|
// Ignore inner rings (holes)
|
||||||
}
|
auto const & outer_ring = polygon.GetArray()[0].GetArray();
|
||||||
else
|
|
||||||
{
|
std::vector<math::point<float, 2>> ring;
|
||||||
++i;
|
|
||||||
|
for (auto const & p : outer_ring)
|
||||||
|
ring.push_back({p.GetArray()[0].GetFloat(), p.GetArray()[1].GetFloat()});
|
||||||
|
|
||||||
|
log::info() << "Ring with " << ring.size() << " vertices";
|
||||||
|
|
||||||
|
std::reverse(ring.begin(), ring.end());
|
||||||
|
ring.erase(std::unique(ring.begin(), ring.end()), ring.end());
|
||||||
|
|
||||||
|
rings.push_back(std::move(ring));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info() << points_.size() << " input points";
|
{
|
||||||
|
prof::profiler prof("triangulate");
|
||||||
|
|
||||||
|
for (auto const & ring : rings)
|
||||||
|
{
|
||||||
|
auto dcel = cg::monotone_triangulation<std::uint16_t>(math::fast, ring.begin(), ring.end());
|
||||||
|
|
||||||
|
auto const index_offset = points_.size();
|
||||||
|
points_.insert(points_.end(), ring.begin(), ring.end());
|
||||||
|
|
||||||
|
auto edges = cg::edge_mesh(dcel);
|
||||||
|
auto triangles = cg::triangle_mesh(dcel);
|
||||||
|
|
||||||
|
for (auto & e : edges)
|
||||||
|
for (auto & i : e.points)
|
||||||
|
i += index_offset;
|
||||||
|
|
||||||
|
for (auto & t : triangles)
|
||||||
|
for (auto & i : t.points)
|
||||||
|
i += index_offset;
|
||||||
|
|
||||||
|
edges_.insert(edges_.end(), edges.begin(), edges.end());
|
||||||
|
triangles_.insert(triangles_.end(), triangles.begin(), triangles.end());
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < ring.size(); ++i)
|
||||||
|
{
|
||||||
|
std::size_t j = (i + 1) % ring.size();
|
||||||
|
contour_edges_.push_back({index_offset + i, index_offset + j});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info() << rings.size() << " rings";
|
||||||
|
log::info() << points_.size() << " total input vertices";
|
||||||
|
|
||||||
bbox_ = cg::bbox(points_.begin(), points_.end());
|
bbox_ = cg::bbox(points_.begin(), points_.end());
|
||||||
camera_center_ = bbox_.center();
|
camera_center_ = bbox_.center();
|
||||||
camera_size_ = std::max(bbox_[0].length(), bbox_[1].length()) * 1.125f;
|
camera_size_ = std::max(bbox_[0].length(), bbox_[1].length()) * 1.125f;
|
||||||
camera_size_tgt_ = camera_size_;
|
camera_size_tgt_ = camera_size_;
|
||||||
|
|
||||||
{
|
|
||||||
prof::profiler prof("triangulate");
|
|
||||||
|
|
||||||
// auto dcel = cg::ear_clipping<std::uint16_t>(math::fast, points_.begin(), points_.end());
|
|
||||||
auto dcel = cg::monotone_triangulation<std::uint16_t>(math::fast, points_.begin(), points_.end());
|
|
||||||
edges_ = cg::edge_mesh(dcel);
|
|
||||||
triangles_ = cg::triangle_mesh(dcel);
|
|
||||||
}
|
|
||||||
|
|
||||||
prof::dump();
|
|
||||||
|
|
||||||
log::info() << edges_.size() << " edges";
|
log::info() << edges_.size() << " edges";
|
||||||
log::info() << triangles_.size() << " triangles";
|
log::info() << triangles_.size() << " triangles";
|
||||||
log::info() << "Euler chi: " << (points_.size() - edges_.size() + triangles_.size());
|
log::info() << "Euler chi: " << (points_.size() - edges_.size() + triangles_.size());
|
||||||
|
|
||||||
|
prof::dump();
|
||||||
|
|
||||||
closest_points_.resize(points_.size());
|
closest_points_.resize(points_.size());
|
||||||
std::iota(closest_points_.begin(), closest_points_.end(), std::uint16_t{0});
|
std::iota(closest_points_.begin(), closest_points_.end(), std::uint16_t{0});
|
||||||
}
|
}
|
||||||
|
|
@ -130,19 +162,16 @@ struct triangulation_app
|
||||||
for (auto const & t : triangles_)
|
for (auto const & t : triangles_)
|
||||||
{
|
{
|
||||||
gfx::color_rgba c;
|
gfx::color_rgba c;
|
||||||
c[0] = random::uniform<std::uint8_t>(rng, {0, 255});
|
c[0] = random::uniform<std::uint8_t>(rng, {63, 255});
|
||||||
c[1] = random::uniform<std::uint8_t>(rng, {0, 255});
|
c[1] = random::uniform<std::uint8_t>(rng, {63, 255});
|
||||||
c[2] = random::uniform<std::uint8_t>(rng, {0, 255});
|
c[2] = random::uniform<std::uint8_t>(rng, {63, 255});
|
||||||
c[3] = 255;
|
c[3] = 255;
|
||||||
|
|
||||||
painter_.triangle(points_[t[0]], points_[t[1]], points_[t[2]], c);
|
painter_.triangle(points_[t[0]], points_[t[1]], points_[t[2]], c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// for (auto const & e : edges_)
|
for (auto const & e : contour_edges_)
|
||||||
// edge(e[0], e[1], gfx::black);
|
edge(e[0], e[1], gfx::black);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < points_.size(); ++i)
|
|
||||||
edge(i, (i + 1) % points_.size(), gfx::black);
|
|
||||||
|
|
||||||
auto camera_transform = math::orthographic_camera{view_bbox}.transform();
|
auto camera_transform = math::orthographic_camera{view_bbox}.transform();
|
||||||
|
|
||||||
|
|
@ -188,6 +217,7 @@ struct triangulation_app
|
||||||
private:
|
private:
|
||||||
std::vector<math::point<float, 2>> points_;
|
std::vector<math::point<float, 2>> points_;
|
||||||
std::vector<math::segment<std::uint16_t>> edges_;
|
std::vector<math::segment<std::uint16_t>> edges_;
|
||||||
|
std::vector<math::segment<std::uint16_t>> contour_edges_;
|
||||||
std::vector<math::triangle<std::uint16_t>> triangles_;
|
std::vector<math::triangle<std::uint16_t>> triangles_;
|
||||||
math::box<float, 2> bbox_;
|
math::box<float, 2> bbox_;
|
||||||
math::point<float, 2> camera_center_;
|
math::point<float, 2> camera_center_;
|
||||||
|
|
@ -207,20 +237,7 @@ namespace psemek::app
|
||||||
|
|
||||||
std::unique_ptr<application::factory> make_application_factory()
|
std::unique_ptr<application::factory> make_application_factory()
|
||||||
{
|
{
|
||||||
return default_application_factory<triangulation_app>({.name = "Triangulation example"
|
return default_application_factory<triangulation_app>({.name = "Triangulation example"});
|
||||||
""
|
|
||||||
""
|
|
||||||
""
|
|
||||||
""
|
|
||||||
""
|
|
||||||
""
|
|
||||||
""
|
|
||||||
""
|
|
||||||
""
|
|
||||||
""
|
|
||||||
""
|
|
||||||
""
|
|
||||||
""});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3056
examples/turkey
3056
examples/turkey
File diff suppressed because it is too large
Load diff
1
examples/turkey.geo.json
Normal file
1
examples/turkey.geo.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue