From 2f6f35591e43aa22e3a4b4a652bc12f5568de268 Mon Sep 17 00:00:00 2001 From: jaseg Date: Mon, 15 Dec 2025 14:25:57 +0100 Subject: [PATCH] Fix WASM build of skeleton tool --- cgal_skeleton_core/.gitignore | 1 + cgal_skeleton_core/Makefile | 67 ++++++++++++++++++ cgal_skeleton_core/exception_stubs.cpp | 13 ++++ cgal_skeleton_core/skeleton_wrapper.cpp | 90 +++++++++++++++++++++++++ 4 files changed, 171 insertions(+) create mode 100644 cgal_skeleton_core/.gitignore create mode 100644 cgal_skeleton_core/Makefile create mode 100644 cgal_skeleton_core/exception_stubs.cpp create mode 100644 cgal_skeleton_core/skeleton_wrapper.cpp diff --git a/cgal_skeleton_core/.gitignore b/cgal_skeleton_core/.gitignore new file mode 100644 index 0000000..06cf653 --- /dev/null +++ b/cgal_skeleton_core/.gitignore @@ -0,0 +1 @@ +cache diff --git a/cgal_skeleton_core/Makefile b/cgal_skeleton_core/Makefile new file mode 100644 index 0000000..c9a1d7c --- /dev/null +++ b/cgal_skeleton_core/Makefile @@ -0,0 +1,67 @@ + +CXX ?= clang++ + +BUILDDIR ?= build +CACHEDIR ?= cache + +CGAL ?= CGAL-6.1 +CGAL_URL ?= https://github.com/CGAL/cgal/releases/download/v6.1/CGAL-6.1-library.tar.xz + +BOOST ?= boost_1_90_0 +BOOST_URL ?= https://archives.boost.io/release/1.90.0/source/boost_1_90_0.tar.gz + +WASI_SDK_URL ?= https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-x86_64-linux.tar.gz +WASI_SDK ?= $(CACHEDIR)/wasi-sdk-29.0-x86_64-linux + +SOURCES := \ + skeleton_wrapper.cpp + +WASI_SOURCES := \ + $(SOURCES) \ + exception_stubs.cpp \ + +INCLUDES := -I$(CACHEDIR)/$(CGAL)/include -I$(CACHEDIR)/$(BOOST) +CXXFLAGS := -std=c++20 -g -Wall -Wextra -O2 +WASI_CXXFLAGS := -DCGAL_ALWAYS_ROUND_TO_NEAREST -DCGAL_CORE_USE_BOOST_BACKEND -DCGAL_DISABLE_GMP -DCGAL_USE_BOOST_MP -DFE_UPWARD=FE_TONEAREST -D_WASI_EMULATED_PROCESS_CLOCKS $(CXXFLAGS) +LDFLAGS := +HOST_LDFLAGS := $(LDFLAGS) -lgmp -lmpfr +WASI_LDFLAGS := $(LDFLAGS) -lwasi-emulated-process-clocks + +WASI_CXX ?= $(WASI_SDK)/bin/clang++ + + +BINARY := skeleton + +all: $(BUILDDIR)/$(BINARY) wasm + +.PHONY: wasm +wasm: $(BUILDDIR)/$(BINARY).wasm + +$(BUILDDIR)/$(BINARY): $(SOURCES) + $(CXX) $(CXXFLAGS) $(HOST_LDFLAGS) -o $@ $^ + +$(WASI_SDK): + mkdir -p $(dir $@) + cd $(dir $@); curl -L ${WASI_SDK_URL} | tar xzf - + +$(CACHEDIR)/$(BOOST): + cd $(dir $@); curl -L ${BOOST_URL} | tar xzf - + +$(CACHEDIR)/$(CGAL): + cd $(dir $@); curl -L ${CGAL_URL} | tar xJf - + +$(BUILDDIR)/wasi/%.o: %.cpp $(WASI_SDK) + @mkdir -p $(dir $@) + $(WASI_CXX) -c $(WASI_CXXFLAGS) $(INCLUDES) -o $@ $< + +$(BUILDDIR)/$(BINARY).wasm: $(patsubst %.cpp,$(BUILDDIR)/wasi/%.o,$(WASI_SOURCES)) + @mkdir -p $(dir $@) + $(WASI_CXX) $(WASI_LDFLAGS) -o $@ $^ + +.PHONY: clean +clean: + rm -rf $(BUILDDIR) + +.PHONY: mrproper +mrproper: clean + rm -rf $(CACHEDIR) diff --git a/cgal_skeleton_core/exception_stubs.cpp b/cgal_skeleton_core/exception_stubs.cpp new file mode 100644 index 0000000..3b34075 --- /dev/null +++ b/cgal_skeleton_core/exception_stubs.cpp @@ -0,0 +1,13 @@ + +#include + +extern "C" { + void* __cxa_allocate_exception(size_t) { + abort(); + } + + void __cxa_throw(void *, void *, void (*)(void *)) { + abort(); + } +} + diff --git a/cgal_skeleton_core/skeleton_wrapper.cpp b/cgal_skeleton_core/skeleton_wrapper.cpp new file mode 100644 index 0000000..1e0af3d --- /dev/null +++ b/cgal_skeleton_core/skeleton_wrapper.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_2 Point; +typedef CGAL::Polygon_2 Polygon_2; +typedef CGAL::Straight_skeleton_2 Ss; +typedef std::shared_ptr SsPtr; + +int main() +{ + // Read polygon from stdin + Polygon_2 poly; + std::string line; + + while (std::getline(std::cin, line)) { + if (line.empty()) { + continue; + } + + std::istringstream iss(line); + double x, y; + if (iss >> x >> y) { + poly.push_back(Point(x, y)); + } else { + std::cerr << "Error: Invalid input line: " << line << std::endl; + return EXIT_FAILURE; + } + } + + if (poly.size() < 3) { + std::cerr << "Error: Polygon must have at least 3 vertices" << std::endl; + return EXIT_FAILURE; + } + + // Ensure counter-clockwise orientation + if (!poly.is_counterclockwise_oriented()) { + poly.reverse_orientation(); + } + + // Create interior straight skeleton + SsPtr ss = CGAL::create_interior_straight_skeleton_2(poly.vertices_begin(), poly.vertices_end()); + + if (!ss) { + std::cerr << "Error: Failed to create straight skeleton" << std::endl; + return EXIT_FAILURE; + } + + // Output skeleton edges + // Iterate through all halfedges in the skeleton + for (auto he = ss->halfedges_begin(); he != ss->halfedges_end(); ++he) { + // Only output each edge once (skip the opposite halfedge) + if (he->id() < he->opposite()->id()) { + continue; + } + + // Get the vertices at both ends of the halfedge + auto v_source = he->vertex(); + auto v_target = he->opposite()->vertex(); + + // Get times (distance from boundary) + double t1 = CGAL::to_double(v_source->time()); + double t2 = CGAL::to_double(v_target->time()); + + // Skip contour edges (outline of the input polygon) + // Contour edges have both vertices at time 0 + if (t1 == 0.0 && t2 == 0.0) { + continue; + } + + // Get coordinates + double x1 = CGAL::to_double(v_source->point().x()); + double y1 = CGAL::to_double(v_source->point().y()); + double x2 = CGAL::to_double(v_target->point().x()); + double y2 = CGAL::to_double(v_target->point().y()); + + // Output: start_x start_y end_x end_y start_time end_time + std::cout << std::setprecision(12) << x1 << " " << y1 << " " + << x2 << " " << y2 << " " + << t1 << " " << t2 << std::endl; + } + + return EXIT_SUCCESS; +} +