From 99b6bd66f91b64a2434726d64761970c43119cf8 Mon Sep 17 00:00:00 2001 From: adam-ce <5292991+adam-ce@users.noreply.github.com> Date: Thu, 29 Oct 2026 19:53:43 +0100 Subject: [PATCH 1/2] Use pinned dependency archives and remove unused libigl integration --- cmake/SetupGDAL.cmake | 22 +- cmake/SetupOpenCV.cmake | 5 +- src/CMakeLists.txt | 34 ++- src/terrainlib/CMakeLists.txt | 9 - src/terrainlib/mesh/igl/convert.h | 286 ---------------------- src/terrainlib/mesh/igl/cut.cpp | 76 ------ src/terrainlib/mesh/igl/cut.h | 66 ----- src/terrainlib/mesh/igl/cut.inl | 119 --------- src/terrainlib/mesh/igl/cut_to_disk.cpp | 149 ----------- src/terrainlib/mesh/igl/cut_to_disk.h | 60 ----- src/terrainlib/mesh/igl/cut_to_disk.inl | 153 ------------ src/terrainlib/mesh/igl/igl.cpp | 24 -- src/terrainlib/mesh/igl/manifold.cpp | 55 ----- src/terrainlib/mesh/igl/manifold.h | 64 ----- src/terrainlib/mesh/igl/orient.cpp | 56 ----- src/terrainlib/mesh/igl/orient.h | 39 --- unittests/CMakeLists.txt | 2 - unittests/terrainlib/mesh_cut.cpp | 136 ---------- unittests/terrainlib/mesh_cut_to_disk.cpp | 131 ---------- 19 files changed, 40 insertions(+), 1446 deletions(-) delete mode 100644 src/terrainlib/mesh/igl/convert.h delete mode 100644 src/terrainlib/mesh/igl/cut.cpp delete mode 100644 src/terrainlib/mesh/igl/cut.h delete mode 100644 src/terrainlib/mesh/igl/cut.inl delete mode 100644 src/terrainlib/mesh/igl/cut_to_disk.cpp delete mode 100644 src/terrainlib/mesh/igl/cut_to_disk.h delete mode 100644 src/terrainlib/mesh/igl/cut_to_disk.inl delete mode 100644 src/terrainlib/mesh/igl/igl.cpp delete mode 100644 src/terrainlib/mesh/igl/manifold.cpp delete mode 100644 src/terrainlib/mesh/igl/manifold.h delete mode 100644 src/terrainlib/mesh/igl/orient.cpp delete mode 100644 src/terrainlib/mesh/igl/orient.h delete mode 100644 unittests/terrainlib/mesh_cut.cpp delete mode 100644 unittests/terrainlib/mesh_cut_to_disk.cpp diff --git a/cmake/SetupGDAL.cmake b/cmake/SetupGDAL.cmake index 27e2b6b6..88f3bfa6 100644 --- a/cmake/SetupGDAL.cmake +++ b/cmake/SetupGDAL.cmake @@ -21,19 +21,24 @@ if(NOT COMMAND alp_setup_cmake_project) endif() function(alp_setup_gdal) - set(oneValueArgs GDAL_VERSION GEOS_VERSION PROJ_VERSION) + set(oneValueArgs GDAL_VERSION GDAL_SHA256 GEOS_VERSION GEOS_SHA256 PROJ_VERSION PROJ_SHA256) cmake_parse_arguments(ARG "" "${oneValueArgs}" "" ${ARGN}) - if(NOT ARG_GDAL_VERSION OR NOT ARG_GEOS_VERSION OR NOT ARG_PROJ_VERSION) - message(FATAL_ERROR "alp_setup_gdal() needs: GDAL_VERSION GEOS_VERSION PROJ_VERSION ") + if(NOT ARG_GDAL_VERSION OR NOT ARG_GDAL_SHA256 + OR NOT ARG_GEOS_VERSION OR NOT ARG_GEOS_SHA256 + OR NOT ARG_PROJ_VERSION OR NOT ARG_PROJ_SHA256) + message(FATAL_ERROR "alp_setup_gdal() needs VERSION and SHA256 arguments for GDAL, GEOS and PROJ") endif() - alp_setup_cmake_project(proj URL https://github.com/OSGeo/PROJ.git COMMITISH ${ARG_PROJ_VERSION} CMAKE_ARGUMENTS -DBUILD_TESTING=OFF -DBUILD_APPS=OFF) + alp_setup_cmake_project(proj + URL https://download.osgeo.org/proj/proj-${ARG_PROJ_VERSION}.tar.gz + SHA256 ${ARG_PROJ_SHA256} + CMAKE_ARGUMENTS -DBUILD_TESTING=OFF -DBUILD_APPS=OFF) find_package(PROJ CONFIG REQUIRED) alp_setup_cmake_project(geos - URL https://github.com/libgeos/geos.git - COMMITISH ${ARG_GEOS_VERSION} + URL https://download.osgeo.org/geos/geos-${ARG_GEOS_VERSION}.tar.bz2 + SHA256 ${ARG_GEOS_SHA256} CMAKE_ARGUMENTS -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=OFF @@ -41,9 +46,10 @@ function(alp_setup_gdal) -DCMAKE_POSITION_INDEPENDENT_CODE=ON ) + string(REGEX REPLACE "^v" "" _gdal_version "${ARG_GDAL_VERSION}") alp_setup_cmake_project(gdal - URL https://github.com/OSGeo/gdal.git - COMMITISH ${ARG_GDAL_VERSION} + URL https://github.com/OSGeo/gdal/releases/download/v${_gdal_version}/gdal-${_gdal_version}.tar.gz + SHA256 ${ARG_GDAL_SHA256} CMAKE_ARGUMENTS -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF -DGDAL_ENABLE_DRIVER_HFA=ON diff --git a/cmake/SetupOpenCV.cmake b/cmake/SetupOpenCV.cmake index f4be5639..190ff313 100644 --- a/cmake/SetupOpenCV.cmake +++ b/cmake/SetupOpenCV.cmake @@ -20,14 +20,15 @@ if(NOT COMMAND alp_setup_cmake_project) include(${CMAKE_CURRENT_LIST_DIR}/SetupCMakeProject.cmake) endif() -function(alp_setup_opencv version) +function(alp_setup_opencv version sha256) set(_alp_opencv_sanitizer_arguments) if(ALP_ENABLE_ADDRESS_SANITIZER OR ALP_ENABLE_THREAD_SANITIZER) list(APPEND _alp_opencv_sanitizer_arguments -DOPENCV_SKIP_LINK_NO_UNDEFINED=ON) endif() alp_setup_cmake_project(opencv - URL https://github.com/opencv/opencv.git COMMITISH ${version} + URL https://github.com/opencv/opencv/archive/refs/tags/${version}.tar.gz + SHA256 ${sha256} CMAKE_ARGUMENTS ${_alp_opencv_sanitizer_arguments} -DBUILD_TESTS=OFF diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dfd5de9a..f4221f62 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,9 +27,13 @@ find_package(ZLIB REQUIRED) alp_add_git_repository(fmt URL https://github.com/fmtlib/fmt COMMITISH 12.2.0) -alp_add_git_repository(eigen URL https://gitlab.com/libeigen/eigen.git COMMITISH 3.4.0 DO_NOT_ADD_SUBPROJECT) +alp_setup_cmake_project(eigen + URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz + SHA256 8586084f71f9bde545ee7fa6d00288b264a2b7ac3607b974e54d13e7162c1c72 + CMAKE_ARGUMENTS -DBUILD_TESTING=OFF -DEIGEN_BUILD_DOC=OFF) +find_package(Eigen3 CONFIG REQUIRED) add_library(Eigen3 INTERFACE) -target_include_directories(Eigen3 SYSTEM INTERFACE ${eigen_SOURCE_DIR}) +target_link_libraries(Eigen3 INTERFACE Eigen3::Eigen) alp_setup_cmake_project(boost URL https://github.com/boostorg/boost/releases/download/boost-1.88.0/boost-1.88.0-cmake.tar.xz @@ -40,17 +44,29 @@ alp_setup_cmake_project(boost "-DBOOST_INCLUDE_LIBRARIES=graph\;multiprecision\;heap\;format\;logic") find_package(Boost CONFIG REQUIRED) -alp_setup_cmake_project(tbb URL https://github.com/uxlfoundation/oneTBB.git COMMITISH v2023.1.0 CMAKE_ARGUMENTS -DTBB_TEST=OFF -DTBBMALLOC_BUILD=OFF) +alp_setup_cmake_project(tbb + URL https://github.com/uxlfoundation/oneTBB/archive/refs/tags/v2023.1.0.tar.gz + SHA256 191288b52e1e6b17198000b64d77d194bb65e791be46ebc606e9b091781e2070 + CMAKE_ARGUMENTS -DTBB_TEST=OFF -DTBBMALLOC_BUILD=OFF) find_package(TBB REQUIRED) include(../cmake/SetupGDAL.cmake) -alp_setup_gdal(GDAL_VERSION v3.10.3 GEOS_VERSION 3.13.1 PROJ_VERSION 9.6.0) - -alp_setup_cmake_project(cgal URL https://github.com/CGAL/cgal.git COMMITISH "v6.0.1" CMAKE_ARGUMENTS -DBUILD_TESTING=OFF -DWITH_examples=OFF) +alp_setup_gdal( + GDAL_VERSION v3.10.3 + GDAL_SHA256 e4bf7f104acbcb3e2d16c97fd1af2b92b28d0ba59d17d976e3ef08b794f4153b + GEOS_VERSION 3.13.1 + GEOS_SHA256 df2c50503295f325e7c8d7b783aca8ba4773919cde984193850cf9e361dfd28c + PROJ_VERSION 9.6.0 + PROJ_SHA256 d8cae521c311c39513193657e75767f7cfbf2f91bd202fcd4a200028d3b57e14) + +alp_setup_cmake_project(cgal + URL https://github.com/CGAL/cgal/releases/download/v6.0.1/CGAL-6.0.1-library.tar.xz + SHA256 c752737f91d1af71fa96038f0e37945ce82a5f1fffb6200172cfcdd77755a356 + CMAKE_ARGUMENTS -DBUILD_TESTING=OFF -DWITH_examples=OFF) find_package(CGAL REQUIRED) include(../cmake/SetupOpenCV.cmake) -alp_setup_opencv(4.11.0) +alp_setup_opencv(4.11.0 9a7c11f924eff5f8d8070e297b322ee68b9227e003fd600d4b8122198091665f) include(../cmake/SetupJpegXL.cmake) alp_setup_jpegxl(v0.12.0) @@ -98,10 +114,6 @@ alp_add_git_repository(meshoptimizer URL https://github.com/zeux/meshoptimizer.g alp_add_git_repository(wideinteger URL https://github.com/ckormanyos/wide-integer.git COMMITISH 719cbbd557fe974f48b055568e2b149b2444bee9) -set(LIBIGL_COPYLEFT_CORE ON) -set(LIBIGL_RESTRICTED_TRIANGLE ON) -alp_add_git_repository(libigl URL https://github.com/libigl/libigl.git COMMITISH v2.6.0) - alp_add_git_repository(radix URL https://github.com/AlpineMapsOrg/radix.git COMMITISH 799db1af54a1f58454800e899bfc7fc544711834 NOT_SYSTEM) set(ALP_CLI_COMPONENT_OPTIONS diff --git a/src/terrainlib/CMakeLists.txt b/src/terrainlib/CMakeLists.txt index ce8121b6..a7bb0bb0 100644 --- a/src/terrainlib/CMakeLists.txt +++ b/src/terrainlib/CMakeLists.txt @@ -113,12 +113,6 @@ add_library(terrainlib mesh/encode.h mesh/geometry.h mesh/geometry.cpp mesh/holes.h mesh/holes.cpp - mesh/igl/convert.h - mesh/igl/cut.h - mesh/igl/cut_to_disk.h - mesh/igl/igl.cpp - mesh/igl/manifold.h - mesh/igl/orient.h mesh/io.h mesh/io.cpp mesh/io/gltf.h mesh/io/gltf.cpp mesh/io/options.h @@ -246,7 +240,6 @@ add_library(terrainlib uv/unwrap.h uv/unwrap.cpp ) set_source_files_properties( - mesh/igl/igl.cpp mesh/io/gltf.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON ) @@ -280,8 +273,6 @@ target_link_libraries(terrainlib PUBLIC magic_enum::magic_enum meshoptimizer WideInteger - igl::core - igl_restricted::triangle xatlas ) diff --git a/src/terrainlib/mesh/igl/convert.h b/src/terrainlib/mesh/igl/convert.h deleted file mode 100644 index 3933c6a6..00000000 --- a/src/terrainlib/mesh/igl/convert.h +++ /dev/null @@ -1,286 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace detail { -template -inline constexpr int span_extent_to_eigen_v = - (Extent == std::dynamic_extent) ? Eigen::Dynamic - : static_cast(Extent); - -template -inline constexpr std::size_t eigen_extent_to_span_v = - (E == Eigen::Dynamic) ? std::dynamic_extent - : static_cast(E); -} - -// span -> eigen -template < - typename TIn, - typename TOut = TIn, - size_t SIn = std::dynamic_extent, - int SOut = detail::span_extent_to_eigen_v> -void to_eigen_vector( - const std::span data, - Eigen::Vector &out) { - static_assert(std::is_convertible_v); - static_assert(SIn == SOut || SOut == Eigen::Dynamic); - - if constexpr (SOut == Eigen::Dynamic) { - out.resize(data.size()); - } - - for (size_t i = 0; i < out.rows(); i++) { - out(i) = static_cast(data[i]); - } -} -template < - typename TIn, - size_t SIn = std::dynamic_extent, - typename TOut = TIn, - int SOut = detail::span_extent_to_eigen_v> -Eigen::Vector to_eigen_vector(const std::span data) { - Eigen::Vector out; - to_eigen_vector(data, out); - return out; -} - -// eigen -> span -template < - typename Derived, - typename TOut = typename Derived::Scalar> -void to_stl_span( - const Eigen::MatrixBase &data, - std::span out) { - using TIn = typename Derived::Scalar; - static_assert(std::is_convertible_v); - static_assert(Derived::ColsAtCompileTime == 1); - - ASSERT(out.size() == data.size()); - for (size_t i = 0; i < static_cast(data.size()); i++) { - out[i] = static_cast(data(i)); - } -} - -// eigen -> vector -template < - typename Derived, - typename TOut = typename Derived::Scalar> -void to_stl_vector( - const Eigen::MatrixBase &data, - std::vector &out) { - out.resize(data.size()); - to_stl_span(data, std::span(out)); -} -template < - typename Derived, - typename TOut = typename Derived::Scalar> -std::vector to_stl_vector(const Eigen::MatrixBase &data) { - std::vector out; - to_stl_vector(data, out); - return out; -} - -// glm -> eigen -template < - typename TIn, - glm::length_t SIn, - typename TOut = TIn, - int SOut = SIn, - glm::qualifier Q = glm::defaultp> -void to_eigen_vector( - const glm::vec &data, - Eigen::Vector &out) { - const std::span span(glm::value_ptr(data), SIn); - to_eigen_vector(span, out); -} -template < - typename TIn, - glm::length_t SIn, - typename TOut = TIn, - int SOut = SIn, - glm::qualifier Q = glm::defaultp> -Eigen::Vector to_eigen_vector(const glm::vec &data) { - Eigen::Vector out; - to_eigen_vector(data, out); - return out; -} - -// eigen -> glm -template < - typename Derived, - typename TOut = typename Derived::Scalar, - glm::qualifier Q = glm::defaultp> -void to_glm_vector( - const Eigen::MatrixBase &data, - glm::vec &out) { - using TIn = typename Derived::Scalar; - static_assert(std::is_convertible_v); - static_assert(Derived::ColsAtCompileTime == 1); - static_assert(Derived::RowsAtCompileTime != Eigen::Dynamic); - - for (size_t i = 0; i < data.size(); i++) { - out[i] = static_cast(data(i)); - } -} -template < - typename Derived, - typename TOut = typename Derived::Scalar, - glm::qualifier Q = glm::defaultp> -glm::vec to_glm_vector( - const Eigen::MatrixBase &data) { - glm::vec out; - to_glm_vector(data, out); - return out; -} - -// span -> eigen -template < - typename TIn, - size_t RIn, - glm::length_t CIn, - typename TOut = TIn, - int ROut = detail::span_extent_to_eigen_v, - int COut = CIn, - glm::qualifier Q = glm::defaultp> -void to_eigen_matrix( - const std::span, RIn> data, - Eigen::Matrix &out) { - static_assert(std::is_convertible_v); - static_assert(RIn == ROut || ROut == Eigen::Dynamic); - static_assert(CIn == COut || COut == Eigen::Dynamic); - - if constexpr (ROut == Eigen::Dynamic || COut == Eigen::Dynamic) { - out.resize(data.size(), CIn); - } - - for (size_t i = 0; i < data.size(); i++) { - for (size_t j = 0; j < CIn; j++) { - out(i, j) = static_cast(data[i][j]); - } - } -} -template < - typename TIn, - size_t RIn, - glm::length_t CIn, - typename TOut = TIn, - int ROut = detail::span_extent_to_eigen_v, - int COut = CIn, - glm::qualifier Q = glm::defaultp> -Eigen::Matrix to_eigen_matrix(const std::span, RIn> data) { - Eigen::Matrix out; - to_eigen_matrix(data, out); - return out; -} - -// vector -> eigen -template < - typename TIn, - glm::length_t CIn, - typename TOut = TIn, - int ROut = Eigen::Dynamic, - int COut = CIn, - glm::qualifier Q = glm::defaultp> -void to_eigen_matrix( - const std::vector> &data, - Eigen::Matrix &out) { - to_eigen_matrix(std::span>(data), out); -} -template < - typename TIn, - glm::length_t CIn, - typename TOut = TIn, - int ROut = Eigen::Dynamic, - int COut = CIn, - glm::qualifier Q = glm::defaultp> -Eigen::Matrix to_eigen_matrix(const std::vector>& data) { - return to_eigen_matrix(std::span>(data)); -} - -// eigen -> span -template < - typename Derived, - typename TOut = typename Derived::Scalar, - glm::qualifier Q = glm::defaultp> -void to_stl_glm_span( - const Eigen::MatrixBase &data, - std::span> out) { - using TIn = typename Derived::Scalar; - static_assert(std::is_convertible_v); - static_assert(Derived::ColsAtCompileTime != Eigen::Dynamic); - - ASSERT(out.size() == data.rows()); - - for (size_t i = 0; i < static_cast(data.rows()); i++) { - for (size_t j = 0; j < static_cast(data.cols()); j++) { - out[i][j] = static_cast(data(i, j)); - } - } -} - -// eigen -> vector -template < - typename Derived, - typename TOut = typename Derived::Scalar, - glm::qualifier Q = glm::defaultp> -void to_stl_glm_vector( - const Eigen::MatrixBase &data, - std::vector> &out) { - out.resize(data.rows()); - to_stl_glm_span(data, std::span(out)); -} -template < - typename Derived, - typename TOut = typename Derived::Scalar, - glm::qualifier Q = glm::defaultp> -std::vector> to_stl_glm_vector(const Eigen::MatrixBase &data) { - std::vector> out; - to_stl_glm_vector(data, out); - return out; -} - -[[nodiscard]] inline Eigen::MatrixX3d convert_vertices(const std::span positions) { - return to_eigen_matrix(positions); -} -[[nodiscard]] inline std::vector convert_vertices(const Eigen::Ref &V) { - return to_stl_glm_vector(V); -} -[[nodiscard]] inline Eigen::MatrixX3i convert_triangles(const std::span triangles) { - Eigen::MatrixX3i out; - to_eigen_matrix(triangles, out); - return out; -} -[[nodiscard]] inline std::vector convert_triangles(const Eigen::Ref &F) { - DEBUG_ASSERT((F.array() >= 0).all()); - std::vector out; - to_stl_glm_vector(F, out); - return out; -} diff --git a/src/terrainlib/mesh/igl/cut.cpp b/src/terrainlib/mesh/igl/cut.cpp deleted file mode 100644 index ee8d03f0..00000000 --- a/src/terrainlib/mesh/igl/cut.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#include - -#include -#include -#include - -#include - -#include "mesh/igl/convert.h" -#include "mesh/igl/cut.h" -#include "mesh/connectivity/vertex_index_range.h" - -namespace mesh { - -namespace detail { -inline Eigen::VectorX create_dummy_vertices(const std::span triangles) { - const uint32_t max_vertex_index = mesh::find_max_vertex_index(triangles); - return Eigen::VectorX::Zero(max_vertex_index + 1); -} -} - -std::vector cut( - std::span triangles, - const std::span edge_cut_mask) { - auto F = convert_triangles(triangles); - auto V = detail::create_dummy_vertices(triangles); - const auto C = to_eigen_matrix(edge_cut_mask); - Eigen::VectorXi I; - igl::cut_mesh(V, F, C, I); - to_stl_glm_span(F, triangles); - return to_stl_vector(I); -} - -template -std::vector cut( - std::span triangles, - std::vector> &positions, - const std::span edge_cut_mask) { - auto F = convert_triangles(triangles); - auto V = to_eigen_matrix(positions); - const auto C = to_eigen_matrix(edge_cut_mask); - Eigen::VectorXi I; - igl::cut_mesh(V, F, C, I); - to_stl_glm_span(F, triangles); - to_stl_glm_vector(V, positions); - return to_stl_vector(I); -} - -template std::vector cut<3, double>( - std::span triangles, - std::vector> &positions, - std::span edge_cut_mask); - -template std::vector cut<1, uint32_t>( - std::span triangles, - std::vector> &positions, - std::span edge_cut_mask); -} diff --git a/src/terrainlib/mesh/igl/cut.h b/src/terrainlib/mesh/igl/cut.h deleted file mode 100644 index 487f056b..00000000 --- a/src/terrainlib/mesh/igl/cut.h +++ /dev/null @@ -1,66 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#pragma once - -#include -#include -#include -#include - -#include - -#include "mesh/SimpleMesh.h" -#include "mesh/View.h" -#include "enumerate.h" - -namespace mesh { - -template -std::vector cuts_to_edge_mask( - const Cuts cuts, - const std::span triangles); - -template -std::vector cut( - mesh::Simple_ &mesh, - const std::span edge_cut_mask); -template -std::vector cut( - std::span triangles, - std::vector> &positions, - const std::span edge_cut_mask); -template -std::vector cut( - std::span triangles, - std::vector> &positions, - std::vector> &uvs, - const std::span edge_cut_mask); -std::vector cut( - std::span triangles, - const std::span edge_cut_mask); -template -std::vector cut( - std::span triangles, - const std::span edge_cut_mask, - Reserve &&reserve, - Duplicate &&duplicate); - -} // namespace mesh - -#include "cut.inl" diff --git a/src/terrainlib/mesh/igl/cut.inl b/src/terrainlib/mesh/igl/cut.inl deleted file mode 100644 index b9d634e4..00000000 --- a/src/terrainlib/mesh/igl/cut.inl +++ /dev/null @@ -1,119 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#include -#include -#include -#include - -#include - -#include "enumerate.h" -#include "mesh/SimpleMesh.h" -#include "mesh/View.h" -#include "mesh/normalize.h" -#include "mesh/connectivity/vertex_index_range.h" - -namespace mesh { - -template -std::vector cuts_to_edge_mask( - const Cuts cuts, - const std::span triangles) { - std::unordered_set cut_edges; - for (const auto &cut : cuts) { - if (cut.size() < 2) { - continue; - } - - for (size_t i = 0; i + 1 < cut.size(); i++) { - cut_edges.insert(mesh::normalize_edge(glm::uvec2(cut[i], cut[i + 1]))); - } - } - - std::vector edge_cut_mask(triangles.size(), glm::bvec3(false)); - for (const auto &[i, triangle] : enumerate(triangles)) { - for (uint8_t k = 0; k < 3; k++) { - const uint32_t a = triangle[k]; - const uint32_t b = triangle[(k + 1) % 3]; - const glm::uvec2 edge = mesh::normalize_edge(glm::uvec2(a, b)); - edge_cut_mask[i][k] = cut_edges.contains(edge); - } - } - - return edge_cut_mask; -} - -template -std::vector cut( - mesh::Simple_ &mesh, - const std::span edge_cut_mask) { - return cut(mesh.triangles, mesh.positions, mesh.uvs, edge_cut_mask); -} -template -std::vector cut( - std::span triangles, - std::vector> &positions, - std::vector> &uvs, - const std::span edge_cut_mask) { - if (uvs.empty()) { - return cut(triangles, positions, edge_cut_mask); - } - DEBUG_ASSERT(positions.size() == uvs.size()); - auto reserve = [&](const uint32_t new_vertex_count) { - DEBUG_ASSERT(new_vertex_count >= positions.size()); - positions.resize(new_vertex_count); - uvs.resize(new_vertex_count); - }; - auto duplicate = [&](const uint32_t old_index, const uint32_t new_index) { - positions[new_index] = positions[old_index]; - uvs[new_index] = uvs[old_index]; - }; - return cut(triangles, edge_cut_mask, reserve, duplicate); -} -template -std::vector cut( - std::span triangles, - const std::span edge_cut_mask, - Reserve &&reserve, - Duplicate &&duplicate) { - const uint32_t old_vertex_count = mesh::compute_vertex_count(triangles); - - const std::vector mapping = cut(triangles, edge_cut_mask); - const uint32_t new_vertex_count = mapping.size(); - if (new_vertex_count == old_vertex_count) { - return mapping; - } - - DEBUG_ASSERT(new_vertex_count > old_vertex_count); - reserve(new_vertex_count); - - std::vector encountered(old_vertex_count, false); - for (const auto [new_vertex_index, old_vertex_index] : enumerate(mapping)) { - if (!encountered[old_vertex_index]) { - encountered[old_vertex_index] = true; - continue; - } - - duplicate(old_vertex_index, new_vertex_index); - } - - return mapping; -} - -} // namespace mesh diff --git a/src/terrainlib/mesh/igl/cut_to_disk.cpp b/src/terrainlib/mesh/igl/cut_to_disk.cpp deleted file mode 100644 index 3cd186e8..00000000 --- a/src/terrainlib/mesh/igl/cut_to_disk.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "mesh/igl/convert.h" -#include "mesh/igl/cut_to_disk.h" -#include "mesh/connectivity/boundary.h" -#include "mesh/bfs.h" -#include "mesh/connectivity/topology.h" -#include "mesh/connectivity/connected_components.h" -#include "mesh/reindex.h" -#include "vector_utils.h" - -namespace mesh { - -namespace detail { -uint32_t find_farthest_vertex(const BFS& bfs) { - const auto it = std::max_element(bfs.dist.begin(), bfs.dist.end()); - return std::distance(bfs.dist.begin(), it); -} - -std::vector find_sphere_cut( - const std::span &triangles) { - if (triangles.empty()) { - return {}; - } - const uint32_t start = triangles[0][0]; - const BFS bfs = run_bfs(start, triangles); - const uint32_t farthest = find_farthest_vertex(bfs); - std::vector path = reconstruct_path(start, farthest, bfs.parent); - // Since cut_mesh ignores cuts consisting of a single edge, we need to ensure that the cut has at least 3 vertices - DEBUG_ASSERT(path.size() >= 2); - if (path.size() == 2) { - for (const uint32_t vertex : path) { - for (const uint32_t neighbor : bfs.adjacency[vertex]) { - if (!contains(path, neighbor)) { - // found a vertex not in the path -> add it to the path - path.push_back(neighbor); - break; - } - } - if (path.size() == 3) { - break; - } - } - } - return path; -} - -void find_cut_to_disk_for_sphere(const std::span &triangles, std::vector> &cuts) { - const auto [reindexed, index_map] = reindex_with_map(triangles); - - if (!compute_topology(reindexed).is_sphere()) { - return; - } - - auto cut = find_sphere_cut(reindexed); - for (auto& vertex_index : cut) { - vertex_index = index_map.map_backward(vertex_index); - } - cuts.push_back(cut); -} - -void find_cut_to_disk_igl(const std::span &triangles, std::vector> &cuts) { - const auto F = convert_triangles(triangles); - igl::cut_to_disk(F, cuts); -} - -void remove_boundary_from_cuts(const std::span &triangles, std::vector> &cuts) { - const auto boundary_edges = find_boundary_edges(triangles); - - std::vector cuts_to_remove; - std::vector> cuts_to_add; - - for (auto& [i, cut] : enumerate(cuts)) { - // Remove empty cuts - if (cut.size() < 2) { - cuts_to_remove.push_back(i); - continue; - } - - // Iterate over cut and remove boundary segments - for (uint32_t j = cut.size() - 1; j > 0; j--) { - const uint32_t current_vertex = cut[j]; - const uint32_t next_vertex = cut[j - 1]; - const glm::uvec2 edge(next_vertex, current_vertex); - const bool is_boundary = boundary_edges.contains(edge); - if (is_boundary) { - // found boundary edge - if (cut.size() - j > 1) { - // not at the end -> copy segment - std::vector new_cut(cut.begin() + j, cut.end()); - cuts_to_add.push_back(new_cut); - } - - // remove boundary edge - cut.resize(j); - } - } - - if (cut.size() < 2) { - cuts_to_remove.push_back(i); - } - } - - // Remove boundary cuts - for (const uint32_t cut_index : std::views::reverse(cuts_to_remove)) { - erase_by_index(cuts, cut_index); - } - - // Add partial cuts - cuts.insert(cuts.end(), cuts_to_add.begin(), cuts_to_add.end()); -} -} // namespace detail - -void find_cut_to_disk(const std::span &triangles, std::vector> &cuts) { - detail::find_cut_to_disk_igl(triangles, cuts); - detail::remove_boundary_from_cuts(triangles, cuts); - - std::vector> triangles_per_component = split_into_connected_components(triangles); - for (const auto& component : triangles_per_component) { - detail::find_cut_to_disk_for_sphere(component, cuts); - } -} -} diff --git a/src/terrainlib/mesh/igl/cut_to_disk.h b/src/terrainlib/mesh/igl/cut_to_disk.h deleted file mode 100644 index 4cc0e374..00000000 --- a/src/terrainlib/mesh/igl/cut_to_disk.h +++ /dev/null @@ -1,60 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#pragma once - -#include -#include -#include - -#include - -#include "mesh/SimpleMesh.h" -#include "mesh/VertexMap.h" -#include "mesh/View.h" - -namespace mesh { - -void find_cut_to_disk(const std::span &triangles, std::vector> &cuts); -inline std::vector> find_cut_to_disk(const std::span &triangles); -template -std::vector> find_cut_to_disk(const mesh::Simple_ &mesh); -template -std::vector> find_cut_to_disk(const mesh::View_ &mesh); - -template -std::vector cut_to_disk(mesh::Simple_ &mesh); -template -std::vector cut_to_disk( - std::span triangles, - std::vector> &positions); -template -std::vector cut_to_disk( - std::span triangles, - std::vector> &positions, - std::vector> &uvs); -std::vector cut_to_disk(std::span triangles); -template -std::vector cut_to_disk( - std::span triangles, - Reserve &&reserve, - Duplicate &&duplicate); - -} // namespace mesh - -#include "cut_to_disk.inl" diff --git a/src/terrainlib/mesh/igl/cut_to_disk.inl b/src/terrainlib/mesh/igl/cut_to_disk.inl deleted file mode 100644 index ac2518a8..00000000 --- a/src/terrainlib/mesh/igl/cut_to_disk.inl +++ /dev/null @@ -1,153 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * Copyright (C) 2026 Adam Celarek-Litofcenko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#include -#include -#include -#include - -#include - -#include "build_config.h" -#include "mesh/SimpleMesh.h" -#include "mesh/View.h" -#include "mesh/igl/cut.h" -#include "enumerate.h" -#include "mesh/connectivity/vertex_index_range.h" -#include "mesh/connectivity/topology.h" - -#include "mesh/connectivity/connected_components.h" - -namespace mesh { - -inline std::vector> find_cut_to_disk(const std::span &triangles) { - std::vector> cuts; - find_cut_to_disk(triangles, cuts); - return cuts; -} -template -std::vector> find_cut_to_disk(const mesh::Simple_ &mesh) { - return find_cut_to_disk(mesh.triangles); -} -template -std::vector> find_cut_to_disk(const mesh::View_ &mesh) { - return find_cut_to_disk(mesh.triangles); -} - -template -std::vector cut_to_disk(mesh::Simple_ &mesh) { - return cut_to_disk(mesh.triangles, mesh.positions, mesh.uvs); -} - -namespace detail { -inline std::vector identity_map(const uint32_t vertex_count) { - std::vector map(vertex_count); - std::iota(map.begin(), map.end(), 0); - return map; -} -inline std::vector identity_map(const std::span triangles) { - const uint32_t max_vertex_index = find_max_vertex_index(triangles); - return identity_map(max_vertex_index + 1); -} -inline void assert_disks(const std::span triangles) { -#ifndef NDEBUG - const Topology topology = compute_topology(triangles); - for (const auto &component : topology.components()) { - DEBUG_ASSERT(component.is_disk(true)); - } - DEBUG_ASSERT(topology.is_disks(true)); -#else - ALP_UNUSED(triangles); -#endif -} -} - -template -std::vector cut_to_disk( - std::span triangles, - std::span> positions) { - const auto cuts = find_cut_to_disk(triangles); - if (cuts.empty()) { - return detail::identity_map(positions.size()); - } - const auto cut_edge_mask = cuts_to_edge_mask(cuts, triangles); - const auto map = cut(triangles, positions, cut_edge_mask); - detail::assert_disks(triangles); - return map; -} - -template -std::vector cut_to_disk( - std::span triangles, - std::vector> &positions) { - const auto cuts = find_cut_to_disk(triangles); - if (cuts.empty()) { - return detail::identity_map(positions.size()); - } - const auto cut_edge_mask = cuts_to_edge_mask(cuts, triangles); - const auto map = cut(triangles, positions, cut_edge_mask); - detail::assert_disks(triangles); - return map; -} - -template -std::vector cut_to_disk( - std::span triangles, - std::vector> &positions, - std::vector> &uvs) { - const auto cuts = find_cut_to_disk(triangles); - if (cuts.empty()) { - return detail::identity_map(positions.size()); - } - const auto cut_edge_mask = cuts_to_edge_mask(cuts, triangles); - const auto map = cut(triangles, positions, uvs, cut_edge_mask); - detail::assert_disks(triangles); - return map; -} - -inline std::vector cut_to_disk(std::span triangles) { - const auto cuts = find_cut_to_disk(triangles); - if (cuts.empty()) { - return detail::identity_map(triangles); - } - const auto cut_edge_mask = cuts_to_edge_mask(cuts, triangles); - const auto map = cut(triangles, cut_edge_mask); - detail::assert_disks(triangles); - return map; -} - -template -std::vector cut_to_disk( - std::span triangles, - Reserve &&reserve, - Duplicate &&duplicate) { - const auto cuts = find_cut_to_disk(triangles); - if (cuts.empty()) { - return detail::identity_map(triangles); - } - const auto cut_edge_mask = cuts_to_edge_mask(cuts, triangles); - const auto map = cut( - triangles, - cut_edge_mask, - std::forward(reserve), - std::forward(duplicate)); - detail::assert_disks(triangles); - return map; -} -} diff --git a/src/terrainlib/mesh/igl/igl.cpp b/src/terrainlib/mesh/igl/igl.cpp deleted file mode 100644 index 31ff277e..00000000 --- a/src/terrainlib/mesh/igl/igl.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -// single file that includes all .cpp's that use libigl - -#include "cut.cpp" -#include "cut_to_disk.cpp" -#include "orient.cpp" -#include "manifold.cpp" \ No newline at end of file diff --git a/src/terrainlib/mesh/igl/manifold.cpp b/src/terrainlib/mesh/igl/manifold.cpp deleted file mode 100644 index f7aa6ff5..00000000 --- a/src/terrainlib/mesh/igl/manifold.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#include -#include - -#include -#include -#include -#include - -#include "mesh/igl/convert.h" - -namespace mesh::igl { - -bool is_manifold(const std::span triangles) { - auto F = convert_triangles(triangles); - return ::igl::is_edge_manifold(F) && ::igl::is_vertex_manifold(F); -} -bool is_edge_manifold(const std::span triangles) { - auto F = convert_triangles(triangles); - return ::igl::is_edge_manifold(F); -} -bool is_vertex_manifold(const std::span triangles) { - auto F = convert_triangles(triangles); - return ::igl::is_vertex_manifold(F); -} - -TrianglesAndIndexMap make_manifold(const std::span triangles) { - auto F = convert_triangles(triangles); - Eigen::MatrixX3i SF; - Eigen::VectorXi SVI; - ::igl::split_nonmanifold(F, SF, SVI); - return { - convert_triangles(SF), - to_stl_vector(SVI) - }; -} - -} // namespace mesh diff --git a/src/terrainlib/mesh/igl/manifold.h b/src/terrainlib/mesh/igl/manifold.h deleted file mode 100644 index 418f7b08..00000000 --- a/src/terrainlib/mesh/igl/manifold.h +++ /dev/null @@ -1,64 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#pragma once - -#include -#include - -#include -#include - -#include "enumerate.h" -#include "mesh/SimpleMesh.h" - -namespace mesh::igl { - -bool is_manifold(const std::span triangles); -bool is_edge_manifold(const std::span triangles); -bool is_vertex_manifold(const std::span triangles); - -struct TrianglesAndIndexMap { - std::vector triangles; - std::vector backwards; -}; -TrianglesAndIndexMap make_manifold(const std::span triangles); - -template -void make_manifold( - std::vector &triangles, - std::vector> &positions) { - const auto [new_triangles, backwards] = make_manifold(triangles); - triangles = new_triangles; - - const size_t old_position_count = positions.size(); - positions.reserve(backwards.size()); - for (const auto [i, original_index] : enumerate(backwards)) { - if (i < old_position_count) { - DEBUG_ASSERT(original_index == i); - } else { - positions.push_back(positions[original_index]); - } - } -} -template -void make_manifold(mesh::Simple_ &mesh) { - make_manifold(mesh.triangles, mesh.positions); -} - -} // namespace mesh diff --git a/src/terrainlib/mesh/igl/orient.cpp b/src/terrainlib/mesh/igl/orient.cpp deleted file mode 100644 index 5760d807..00000000 --- a/src/terrainlib/mesh/igl/orient.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#include -#include - -#include -#include - -#include "mesh/igl/convert.h" -#include "mesh/connectivity/adjacency.h" - -#include "mesh/connectivity/manifold.h" -#include "mesh/igl/manifold.h" - -namespace mesh { - -namespace detail { -void orient_triangles_core( - const std::span triangles_in, - const std::span triangles_out) { - auto F = convert_triangles(triangles_in); - Eigen::MatrixX3i FF; - Eigen::VectorXi C; - ::igl::bfs_orient(F, FF, C); - to_stl_glm_span(FF, triangles_out); - DEBUG_ASSERT(is_consistently_oriented(triangles_out)); -} -} - -void orient_triangles_inplace(const std::span triangles) { - detail::orient_triangles_core(triangles, triangles); -} - -std::vector orient_triangles(const std::span triangles) { - std::vector reoriented(triangles.size()); - detail::orient_triangles_core(triangles, reoriented); - return reoriented; -} - -} // namespace mesh diff --git a/src/terrainlib/mesh/igl/orient.h b/src/terrainlib/mesh/igl/orient.h deleted file mode 100644 index bb37ae88..00000000 --- a/src/terrainlib/mesh/igl/orient.h +++ /dev/null @@ -1,39 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#pragma once - -#include -#include - -#include - -#include "mesh/SimpleMesh.h" - -namespace mesh { - -void orient_triangles_inplace(const std::span triangles); -std::vector orient_triangles(const std::span triangles); - -template -void orient_inplace(mesh::Simple_ &mesh) { - orient_triangles_inplace(mesh.triangles); -} - -} // namespace mesh - diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index e28ae820..70056d69 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -74,8 +74,6 @@ add_executable(unittests_terrainlib terrainlib/mesh_clip.cpp terrainlib/mesh_combine.cpp terrainlib/mesh_connected_components.cpp - terrainlib/mesh_cut.cpp - terrainlib/mesh_cut_to_disk.cpp terrainlib/mesh_holes.cpp terrainlib/mesh_io.cpp terrainlib/mesh_manifold.cpp diff --git a/unittests/terrainlib/mesh_cut.cpp b/unittests/terrainlib/mesh_cut.cpp deleted file mode 100644 index dc197b47..00000000 --- a/unittests/terrainlib/mesh_cut.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#include -#include - -#include -#include - -#include "../catch2_helpers.h" -#include "mesh/TriangleSoup.h" -#include "mesh/connectivity/connected_components.h" -#include "mesh/igl/cut.h" -#include "mesh/igl/cut_to_disk.h" - -TEST_CASE("cuts_to_edge_mask single edge") { - const std::vector triangles = { - {0, 1, 2}, - {2, 1, 3} - }; - - const std::vector> cuts = { - {1, 2} - }; - - const auto edge_cut_mask = mesh::cuts_to_edge_mask(cuts, triangles); - - REQUIRE(edge_cut_mask.size() == 2); - CHECK(edge_cut_mask[0] == glm::bvec3(false, true, false)); - CHECK(edge_cut_mask[1] == glm::bvec3(true, false, false)); -} - -TEST_CASE("cuts_to_edge_mask multiple edges") { - const std::vector triangles = { - {0, 1, 2}, - {2, 1, 3} - }; - - const std::vector> cuts = { - {0, 1, 3} - }; - - const auto edge_cut_mask = mesh::cuts_to_edge_mask(cuts, triangles); - - REQUIRE(edge_cut_mask.size() == 2); - CHECK(edge_cut_mask[0] == glm::bvec3(true, false, false)); - CHECK(edge_cut_mask[1] == glm::bvec3(false, true, false)); -} - -TEST_CASE("cuts_to_edge_mask multiple single edges") { - const std::vector triangles = { - {0, 1, 2}, - {2, 1, 3} - }; - - const std::vector> cuts = { - {0, 1}, - {1, 2}, - {1, 3} - }; - - const auto edge_cut_mask = mesh::cuts_to_edge_mask(cuts, triangles); - - REQUIRE(edge_cut_mask.size() == 2); - CHECK(edge_cut_mask[0] == glm::bvec3(true, true, false)); - CHECK(edge_cut_mask[1] == glm::bvec3(true, true, false)); -} - -TEST_CASE("cut shared edge in open quad") { - mesh::Simple mesh({ - {0, 1, 2}, - {2, 1, 3} - }, { - {0, 0, 0}, - {1, 0, 0}, - {1, 1, 0}, - {0, 1, 0}, - }); - - const size_t original_vertex_count = mesh.vertex_count(); - - const std::vector edge_cut_mask = { - glm::bvec3(false, true, false), - glm::bvec3(true, false, false), - }; - - const auto mapping = mesh::cut(mesh, edge_cut_mask); - CHECK(mapping.size() == original_vertex_count + 2); - - const auto actual = mesh::split_into_connected_components(mesh); - const auto actual_soups = to_sorted_triangle_soups(actual); - const std::vector> expected_soup1 = - {{glm::dvec3(0, 0, 0), glm::dvec3(1, 0, 0), glm::dvec3(1, 1, 0)}}; - const std::vector> expected_soup2 = - {{glm::dvec3(0, 1, 0), glm::dvec3(1, 1, 0), glm::dvec3(1, 0, 0)}}; - CAPTURE(actual_soups); - REQUIRE(actual.size() == 2); - CHECK(actual_soups[0] == expected_soup1); - CHECK(actual_soups[1] == expected_soup2); -} - -TEST_CASE("cut shared edge in double-sided triangle") { - mesh::Simple mesh({ - {0, 1, 2}, - {0, 2, 1} - }, { - {0, 0, 0}, - {1, 0, 0}, - {0, 1, 0}, - }); - - const size_t original_vertex_count = mesh.vertex_count(); - - const std::vector edge_cut_mask = { - glm::bvec3(true, true, false), - glm::bvec3(false, true, true), - }; - - const auto mapping = mesh::cut(mesh, edge_cut_mask); - CHECK(mapping.size() == original_vertex_count + 1); -} diff --git a/unittests/terrainlib/mesh_cut_to_disk.cpp b/unittests/terrainlib/mesh_cut_to_disk.cpp deleted file mode 100644 index ea394d3a..00000000 --- a/unittests/terrainlib/mesh_cut_to_disk.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2026 Martin Braunsperger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#include -#include - -#include -#include - -#include "../catch2_helpers.h" -#include "mesh/connectivity/topology.h" -#include "mesh/igl/cut_to_disk.h" -#include "mesh/validate.h" - -TEST_CASE("cut_to_disk works on double-sided triangle") { - mesh::Simple mesh({ - {0, 1, 2}, - {0, 2, 1} - }, { - {0, 0, 0}, - {1, 0, 0}, - {0, 1, 0}, - }); - - const mesh::Topology old_topology = mesh::compute_topology(mesh); - CHECK(old_topology.is_sphere()); - CHECK(!old_topology.is_disk(false)); - - mesh::cut_to_disk(mesh); - mesh::validate(mesh); - const mesh::Topology new_topology = mesh::compute_topology(mesh); - CHECK(!new_topology.is_sphere()); - CHECK(new_topology.is_disk(false)); -} - -TEST_CASE("cut_to_disk works on tetrahedron") { - mesh::Simple mesh({ - {0, 1, 2}, - {2, 3, 0}, - {3, 2, 1}, - {1, 0, 3}, - }, { - {0, 0, 0}, - {1, 0, 0}, - {1, 1, 0}, - {0, 1, 0}, - }); - - const mesh::Topology old_topology = mesh::compute_topology(mesh); - CHECK(old_topology.is_sphere()); - CHECK(!old_topology.is_disk(false)); - - mesh::cut_to_disk(mesh); - mesh::validate(mesh); - const mesh::Topology new_topology = mesh::compute_topology(mesh); - CHECK(!new_topology.is_sphere()); - CHECK(new_topology.is_disk(false)); -} - -TEST_CASE("cut_to_disk works on tetrahedron triangles only") { - std::vector triangles = { - {0, 1, 2}, - {2, 3, 0}, - {3, 2, 1}, - {1, 0, 3}, - }; - - const mesh::Topology old_topology = mesh::compute_topology(triangles); - CHECK(old_topology.is_sphere()); - CHECK(!old_topology.is_disk(false)); - - mesh::cut_to_disk(triangles); - const mesh::Topology new_topology = mesh::compute_topology(triangles); - CHECK(!new_topology.is_sphere()); - CHECK(new_topology.is_disk(false)); -} - -TEST_CASE("cut_to_disk works on multiple tetrahedrons") { - mesh::Simple mesh({ - {0, 1, 2}, - {2, 3, 0}, - {3, 2, 1}, - {1, 0, 3}, - - {4, 5, 6}, - {6, 7, 4}, - {7, 6, 5}, - {5, 4, 7}, - }, { - {0, 0, 0}, - {1, 0, 0}, - {1, 1, 0}, - {0, 1, 0}, - - {2, 0, 0}, - {3, 0, 0}, - {3, 1, 0}, - {2, 1, 0}, - }); - - const mesh::Topology old_topology = mesh::compute_topology(mesh); - REQUIRE(old_topology.component_count() == 2); - CHECK(old_topology.component(0).is_sphere()); - CHECK(old_topology.component(1).is_sphere()); - CHECK(!old_topology.is_disks(false)); - - mesh::cut_to_disk(mesh); - mesh::validate(mesh); - const mesh::Topology new_topology = mesh::compute_topology(mesh); - REQUIRE(new_topology.component_count() == 2); - CHECK(!new_topology.component(0).is_sphere()); - CHECK(!new_topology.component(1).is_sphere()); - CHECK(new_topology.component(0).is_disk(false)); - CHECK(new_topology.component(1).is_disk(false)); - CHECK(new_topology.is_disks(false)); -} From c2df9d7f59ce431ccb7e27800e69a98f9cc9a8d4 Mon Sep 17 00:00:00 2001 From: adam-ce <5292991+adam-ce@users.noreply.github.com> Date: Thu, 29 Oct 2026 21:19:34 +0100 Subject: [PATCH 2/2] Match OpenCV archive paths in UBSan suppressions Archive sources use an opencv_ directory, so the previous path patterns no longer matched. Keep the existing diagnostic and file restrictions while accepting both Git and archive source paths. --- misc/suppression/ubsan.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/misc/suppression/ubsan.txt b/misc/suppression/ubsan.txt index 3899c176..c77586b1 100644 --- a/misc/suppression/ubsan.txt +++ b/misc/suppression/ubsan.txt @@ -13,12 +13,12 @@ bool:CGAL::Trapezoidal_decomposition_2<*::set_with_guarantees(bool) # OpenCV's random-number dispatch casts typed functions to a common signature. # Suppress only function-type diagnostics in that implementation. -function:*opencv/modules/core/src/rand.cpp +function:*opencv*/modules/core/src/rand.cpp # OpenCV's IPP color conversion dispatch casts typed functions to a common signature. # Suppress only function-type diagnostics in that implementation. -function:*opencv/modules/imgproc/src/color.hpp +function:*opencv*/modules/imgproc/src/color.hpp # OpenCV's IPP resize fallback uses -1 as an unsupported-interpolation sentinel. # Suppress only enum diagnostics in that implementation. -enum:*opencv/modules/imgproc/src/resize.cpp +enum:*opencv*/modules/imgproc/src/resize.cpp