commit 3ca458e690c1bbf66f3f6384e0548f4b5598a642
parent 9aefd234d7c7b3da83d5b5ec9f6fbc26b110fa6b
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Wed, 28 Sep 2022 14:27:59 +0200
Merge branch 'feature-clipper2' into develop
Diffstat:
3 files changed, 64 insertions(+), 96 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -25,15 +25,15 @@ set(SCPR_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src)
# Dependencies
################################################################################
get_filename_component(_current_source_dir ${CMAKE_CURRENT_LIST_FILE} PATH)
-set(Clipper_DIR ${_current_source_dir}/)
+set(Clipper2_DIR ${_current_source_dir}/)
-find_package(Clipper REQUIRED)
find_package(RCMake REQUIRED)
find_package(RSys 0.6 REQUIRED)
+find_package(Clipper2 1 REQUIRED)
find_package(Polygon 0.0.5 REQUIRED)
include_directories(
- ${Clipper_INCLUDE_DIR}
+ ${Clipper2_INCLUDE_DIR}
${Polygon_INCLUDE_DIR}
${RSys_INCLUDE_DIR})
@@ -41,7 +41,7 @@ set(CMAKE_MODULE_PATH ${RCMAKE_SOURCE_DIR})
include(rcmake)
include(rcmake_runtime)
-rcmake_append_runtime_dirs(_runtime_dirs RSys Polygon)
+rcmake_append_runtime_dirs(_runtime_dirs RSys Polygon Clipper2)
################################################################################
# Define targets
@@ -64,7 +64,7 @@ set_target_properties(scpr PROPERTIES
DEFINE_SYMBOL SCPR_SHARED_BUILD
VERSION ${VERSION}
SOVERSION ${VERSION_MAJOR})
-target_link_libraries(scpr RSys Polygon Clipper)
+target_link_libraries(scpr RSys Polygon Clipper2)
if(CMAKE_COMPILER_IS_GNUCXX)
set_target_properties(scpr PROPERTIES COMPILE_FLAGS "-Wno-long-long")
diff --git a/cmake/ClipperConfig.cmake b/cmake/ClipperConfig.cmake
@@ -31,21 +31,21 @@
cmake_minimum_required(VERSION 3.1)
-# Try to find the Clipper devel. Once done this will define:
-# - Clipper_FOUND: system has Clipper
-# - Clipper_INCLUDE_DIR: the include directory
-# - Clipper: Link this to use Clipper
+# Try to find the Clipper2 devel. Once done this will define:
+# - Clipper2_FOUND: system has Clipper2
+# - Clipper2_INCLUDE_DIR: the include directory
+# - Clipper2: Link this to use Clipper2
-find_path(Clipper_INCLUDE_DIR polyclipping/clipper.hpp)
-set(Clipper_INCLUDE_DIR ${Clipper_INCLUDE_DIR}/polyclipping/)
+find_path(Clipper2_INCLUDE_DIR polyclipping/clipper.hpp)
+set(Clipper2_INCLUDE_DIR ${Clipper2_INCLUDE_DIR}/polyclipping/)
-unset(Clipper_LIBRARY CACHE)
-unset(Clipper_LIBRARY_DEBUG CACHE)
-unset(Clipper_LIBRARY_RELWITHDEBINFO CACHE)
-unset(Clipper_LIBRARY_MINSIZEREL CACHE)
-find_library(Clipper_LIBRARY polyclipping
+unset(Clipper2_LIBRARY CACHE)
+unset(Clipper2_LIBRARY_DEBUG CACHE)
+unset(Clipper2_LIBRARY_RELWITHDEBINFO CACHE)
+unset(Clipper2_LIBRARY_MINSIZEREL CACHE)
+find_library(Clipper2_LIBRARY polyclipping
DOC "Path to the clipper library used during release builds.")
-find_library(Clipper_LIBRARY_DEBUG polyclipping-dbg
+find_library(Clipper2_LIBRARY_DEBUG polyclipping-dbg
DOC "Path to the clipper library used during debug builds.")
# Create the imported library target
@@ -53,22 +53,22 @@ if(CMAKE_HOST_WIN32)
set(_property IMPORTED_IMPLIB)
else(CMAKE_HOST_WIN32)
set(_property IMPORTED_LOCATION)
- if(NOT Clipper_LIBRARY_DEBUG) # Fallback lib
- get_property(_doc CACHE Clipper_LIBRARY_DEBUG PROPERTY HELPSTRING)
- set(Clipper_LIBRARY_DEBUG ${Clipper_LIBRARY} CACHE PATH ${_doc} FORCE)
+ if(NOT Clipper2_LIBRARY_DEBUG) # Fallback lib
+ get_property(_doc CACHE Clipper2_LIBRARY_DEBUG PROPERTY HELPSTRING)
+ set(Clipper2_LIBRARY_DEBUG ${Clipper2_LIBRARY} CACHE PATH ${_doc} FORCE)
endif()
endif()
-add_library(Clipper SHARED IMPORTED)
-set_target_properties(Clipper PROPERTIES
- ${_property} ${Clipper_LIBRARY_DEBUG}
- ${_property}_DEBUG ${Clipper_LIBRARY_DEBUG}
- ${_property}_RELEASE ${Clipper_LIBRARY})
+add_library(Clipper2 SHARED IMPORTED)
+set_target_properties(Clipper2 PROPERTIES
+ ${_property} ${Clipper2_LIBRARY_DEBUG}
+ ${_property}_DEBUG ${Clipper2_LIBRARY_DEBUG}
+ ${_property}_RELEASE ${Clipper2_LIBRARY})
# Check the package
include(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(Clipper DEFAULT_MSG
- Clipper_INCLUDE_DIR
- Clipper_LIBRARY
- Clipper_LIBRARY_DEBUG)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Clipper2 DEFAULT_MSG
+ Clipper2_INCLUDE_DIR
+ Clipper2_LIBRARY
+ Clipper2_LIBRARY_DEBUG)
diff --git a/src/scpr_mesh.c b/src/scpr_mesh.c
@@ -15,6 +15,8 @@
#include "scpr.h"
+#include <clipper.core.h>
+#include <clipper.engine.h>
#include <rsys/double2.h>
#include <rsys/dynamic_array_double.h>
#include <rsys/dynamic_array_size_t.h>
@@ -23,8 +25,7 @@
#include <rsys/ref_count.h>
#include <polygon.h>
-#include <clipper.hpp>
-STATIC_ASSERT(sizeof(ClipperLib::cInt) >= sizeof(double), Unexpected_Type_Size);
+#include <clipper.h>
struct vertex { double pos[2]; };
static FINLINE int
@@ -54,48 +55,13 @@ struct scpr_mesh {
/*******************************************************************************
* Helper functions
******************************************************************************/
-static FINLINE ClipperLib::cInt
-double_to_cInt(const double d, const double scale)
-{
- double dbl = d;
- union { int64_t i; double d; } ucast;
- ClipperLib::cInt i;
- ASSERT(scale > 0);
-
- /* Map 'd' in [1, 2] => Fix the exponent */
- ucast.d = 1 + fabs(d / scale);
-
- /* Store the positive or null exponent in the 52^th bit. This ensure that if
- * 'd' is equal to 2 then it is not encoded as 0. */
- i = (((ucast.i >> 52) & 0x7FF) - 1023) << 52;
-
- /* Store the mantissa in the [0 .. 51] bits */
- i = (ucast.i & 0x000FFFFFFFFFFFFF) | i;
-
- /* Apply the sign to the resulting integer */
- return dbl < 0 ? -i : i;
-}
-
-static FINLINE double
-cInt_to_double(const ClipperLib::cInt i, const double scale)
-{
- double dbl;
- union { int64_t i; double d; } ucast;
- ASSERT(scale > 0);
-
- ucast.i = llabs(i);
- ucast.i = ((1023 + (ucast.i >> 52)) << 52) | (ucast.i & 0x000FFFFFFFFFFFFF);
- dbl = (ucast.d - 1) * scale;
- return i < 0 ? -dbl : dbl;
-}
-
-static FINLINE ClipperLib::ClipType
+static FINLINE Clipper2Lib::ClipType
scpr_operation_to_clip_type(const enum scpr_operation op)
{
- ClipperLib::ClipType ctype = ClipperLib::ctIntersection;
+ Clipper2Lib::ClipType ctype;
switch(op) {
- case SCPR_AND: ctype = ClipperLib::ctIntersection; break;
- case SCPR_SUB: ctype = ClipperLib::ctDifference; break;
+ case SCPR_AND: ctype = Clipper2Lib::ClipType::Intersection; break;
+ case SCPR_SUB: ctype = Clipper2Lib::ClipType::Difference; break;
default: FATAL("Unreachable code\n"); break;
}
return ctype;
@@ -249,11 +215,10 @@ register_triangle
static res_T
register_paths
- (const ClipperLib::Paths& paths,
+ (const Clipper2Lib::PathsD& paths,
struct darray_double* coords, /* Vertex buffer */
struct darray_size_t* indices, /* Index buffer */
struct htable_vertex* vertices, /* Map a vertex to its index */
- const double extend[2], /* Scale to apply to the cInt coordinates */
struct polygon* polygon) /* Use to triangulate the clipped polygons */
{
size_t ivert;
@@ -265,8 +230,8 @@ register_paths
if(paths[ipath].size() == 3) {
FOR_EACH(ivert, 0, 3) {
double pos[2];
- pos[0] = cInt_to_double(paths[ipath][ivert].X, extend[0]);
- pos[1] = cInt_to_double(paths[ipath][ivert].Y, extend[1]);
+ pos[0] = paths[ipath][ivert].x;
+ pos[1] = paths[ipath][ivert].y;
res = register_vertex(pos, coords, indices, vertices);
if(res != RES_OK) goto error;
}
@@ -281,8 +246,8 @@ register_paths
float fpos[3] = {0.f, 0.f, 0.f};
double pos[2];
- pos[0] = cInt_to_double(paths[ipath][ivert].X, extend[0]);
- pos[1] = cInt_to_double(paths[ipath][ivert].Y, extend[1]);
+ pos[0] = paths[ipath][ivert].x;
+ pos[1] = paths[ipath][ivert].y;
fpos[0] = (float)pos[0], fpos[1] = (float)pos[1];
res = polygon_vertex_add(polygon, fpos);
@@ -500,17 +465,18 @@ scpr_mesh_clip
const enum scpr_operation op,
struct scpr_polygon* poly_desc)
{
- double lower[2], upper[2], extend[2];
+ double lower[2], upper[2];
struct poly poly;
struct polygon* polygon = NULL; /* Use to triangulate clipped polygons */
struct darray_double coords; /* Coordinates of the clipped mesh */
struct darray_size_t indices; /* Indices of the clipped mesh */
struct htable_vertex vertices; /* Map a coordinate to its index */
- ClipperLib::Clipper clipper(ClipperLib::ioStrictlySimple);
- ClipperLib::Paths output; /* Contour of the clipped polgyon */
- ClipperLib::Path cand_path; /* Contour of the candidate polygon */
- ClipperLib::Path clip_path; /* Contour of the clip polygon */
- ClipperLib::ClipType clip_type; /* Type of clipping to perform */
+ Clipper2Lib::ClipperD clipper;
+ Clipper2Lib::PathsD output; /* Contour of the clipped polgyon */
+ Clipper2Lib::PathsD cand_path; /* Contour of the candidate polygon */
+ Clipper2Lib::PathD tmp;
+ Clipper2Lib::PathsD clip_path; /* Contour of the clip polygon */
+ Clipper2Lib::ClipType clip_type; /* Type of clipping to perform */
size_t ivert, nverts;
size_t itri, ntris;
@@ -536,17 +502,18 @@ scpr_mesh_clip
/* Compute the overall aabb of the candidate and the clip polygon */
d2_min(lower, lower, poly.lower);
d2_max(upper, upper, poly.upper);
- d2_sub(extend, upper, lower);
/* Setup the clip path */
nverts = darray_double_size_get(&poly.coords) / 2/*#coords per vertex*/;
+ tmp.clear();
FOR_EACH(ivert, 0, nverts) {
const double* v = darray_double_cdata_get(&poly.coords) + ivert*2;
- ClipperLib::IntPoint pt;
- pt.X = double_to_cInt(v[0], extend[0]);
- pt.Y = double_to_cInt(v[1], extend[1]);
- clip_path.push_back(pt);
+ Clipper2Lib::PointD pt;
+ pt.x = v[0];
+ pt.y = v[1];
+ tmp.push_back(pt);
}
+ clip_path.push_back(tmp);
/* Create the polygon structure used to triangulate the clipped polygons */
res = polygon_create(mesh->allocator, &polygon);
@@ -576,22 +543,23 @@ scpr_mesh_clip
/* Setup the candidate path */
cand_path.clear();
+ tmp.clear();
FOR_EACH(ivert, 0, 3) {
- ClipperLib::IntPoint pt;
- pt.X = double_to_cInt(tri[ivert][0], extend[0]);
- pt.Y = double_to_cInt(tri[ivert][1], extend[1]);
- cand_path.push_back(pt);
+ Clipper2Lib::PointD pt;
+ pt.x = tri[ivert][0];
+ pt.y = tri[ivert][1];
+ tmp.push_back(pt);
}
+ cand_path.push_back(tmp);
/* Clip the polygon */
clipper.Clear();
- clipper.AddPath(cand_path, ClipperLib::ptSubject, 1);
- clipper.AddPath(clip_path, ClipperLib::ptClip, 1);
- clipper.Execute(clip_type, output);
+ clipper.AddSubject(cand_path);
+ clipper.AddClip(clip_path);
+ clipper.Execute(clip_type, Clipper2Lib::FillRule::EvenOdd, output);
/* Register the resulting clipped polygons */
- res = register_paths
- (output, &coords, &indices, &vertices, extend, polygon);
+ res = register_paths (output, &coords, &indices, &vertices, polygon);
if(res != RES_OK) goto error;
}