commit da676844a8bc3ef7f768b76e18c84ef8accf4ad2
parent 86ea3e4dbb7b0d2180433376275776054ee0466c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 29 Aug 2016 11:31:02 +0200
Remove the ADD and XOR operators
These operators do not make sense when applied per mesh triangle;
add/xor a clip polygon to a mesh triangle may generate primitives that
overlap the adjacent mesh triangles.
Diffstat:
3 files changed, 45 insertions(+), 12 deletions(-)
diff --git a/src/cpr.h b/src/cpr.h
@@ -33,10 +33,8 @@
#endif
enum cpr_operation {
- CPR_ADD,
CPR_AND,
CPR_SUB,
- CPR_XOR,
CPR_OPERATIONS_COUNT__
};
diff --git a/src/cpr_mesh.c b/src/cpr_mesh.c
@@ -24,14 +24,14 @@
#include <polygon.h>
#include <clipper.hpp>
-STATIC_ASSERT(sizeof(ClipperLib::cInt) == sizeof(double), Unexpected_Type_Size);
+STATIC_ASSERT(sizeof(ClipperLib::cInt) >= sizeof(double), Unexpected_Type_Size);
struct vertex { double pos[2]; };
-
static FINLINE int
vertex_eq(const struct vertex* a, const struct vertex* b)
{ return d2_eq(a->pos, b->pos); }
+/* Define the vertex to index hash table */
#define HTABLE_NAME vertex
#define HTABLE_DATA size_t
#define HTABLE_KEY struct vertex
@@ -40,8 +40,7 @@ vertex_eq(const struct vertex* a, const struct vertex* b)
struct poly {
struct darray_double coords;
- double lower[2];
- double upper[2];
+ double lower[2], upper[2]; /* Polygon AABB */
};
struct cpr_mesh {
@@ -63,9 +62,17 @@ double_to_cInt(const double d, const double scale)
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;
}
@@ -87,10 +94,8 @@ cpr_operation_to_clip_type(const enum cpr_operation op)
{
ClipperLib::ClipType ctype = ClipperLib::ctIntersection;
switch(op) {
- case CPR_ADD: ctype = ClipperLib::ctUnion; break;
case CPR_AND: ctype = ClipperLib::ctIntersection; break;
case CPR_SUB: ctype = ClipperLib::ctDifference; break;
- case CPR_XOR: ctype = ClipperLib::ctXor; break;
default: FATAL("Unreachable code\n"); break;
}
return ctype;
@@ -499,7 +504,7 @@ cpr_mesh_clip
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::Clipper clipper(ClipperLib::ioStrictlySimple);
ClipperLib::Paths output;
ClipperLib::Path cand_path;
ClipperLib::Path clip_path;
@@ -545,20 +550,25 @@ cpr_mesh_clip
res = polygon_create(mesh->allocator, &polygon);
if(res != RES_OK) goto error;
+ /* Clip the triangles of the mesh */
CPR(mesh_get_triangles_count(mesh, &ntris));
FOR_EACH(itri, 0, ntris) {
size_t ids[3];
double tri[3][2];
+ /* Fetch the triangle vertices and compute its AABB */
CPR(mesh_get_indices(mesh, itri, ids));
CPR(mesh_get_position(mesh, ids[0], tri[0]));
CPR(mesh_get_position(mesh, ids[1], tri[1]));
CPR(mesh_get_position(mesh, ids[2], tri[2]));
triangle_compute_aabb(tri, lower, upper);
+ /* Do not clip triangles that don not intersect the clip AABB */
if(!aabb_intersect(lower, upper, poly.lower, poly.upper)) {
- res = register_triangle(tri, &coords, &indices, &vertices);
- if(res != RES_OK) goto error;
+ if(op != CPR_AND) {
+ res = register_triangle(tri, &coords, &indices, &vertices);
+ if(res != RES_OK) goto error;
+ }
continue;
}
diff --git a/src/test_cpr_clip.c b/src/test_cpr_clip.c
@@ -84,13 +84,37 @@ test_triangle(struct cpr_mesh* mesh)
CHECK(cpr_mesh_clip(NULL, CPR_SUB, &poly), RES_BAD_ARG);
CHECK(cpr_mesh_clip(mesh, CPR_SUB, &poly), RES_OK);
- dump_obj(stdout, mesh);
+ /*dump_obj(stdout, mesh);*/
CHECK(cpr_mesh_get_triangles_count(mesh, &ntris), RES_OK);
CHECK(ntris, 3);
}
static void
+test_quad(struct cpr_mesh* mesh)
+{
+ const double quad_pos[] = { 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0 };
+ const size_t quad_ids[] = { 0, 1, 3, 3, 1, 2 };
+ const double clip_pos[] = { -0.25, 0.25, -0.25, 0.75, 1.25, 0.75, 1.25, 0.25 };
+ struct cpr_polygon poly;
+ struct mesh_context ctx;
+
+ ctx.coords = quad_pos;
+ ctx.nverts = sizeof(quad_pos)/sizeof(double[2]);
+ ctx.indices = quad_ids;
+ ctx.ntris = sizeof(quad_ids)/sizeof(size_t[3]);
+ CHECK(cpr_mesh_setup_indexed_vertices
+ (mesh, ctx.ntris, get_ids, ctx.nverts, get_pos, &ctx), RES_OK);
+
+ poly.get_position = get_clip_pos;
+ poly.nvertices = sizeof(clip_pos)/sizeof(double[2]);
+ poly.context = (void*)clip_pos;
+ CHECK(cpr_mesh_clip(mesh, CPR_AND, &poly), RES_OK);
+
+ /*dump_obj(stdout, mesh);*/
+}
+
+static void
test_disk(struct cpr_mesh* mesh)
{
const double clip[] = { -1.75, -1.75, 1.75, -1.75, 1.75, 1.75, -1.75, 1.75 };
@@ -178,6 +202,7 @@ main(int argc, char** argv)
CHECK(cpr_mesh_create(&allocator, &mesh), RES_OK);
test_triangle(mesh);
+ test_quad(mesh);
test_disk(mesh);
CHECK(cpr_mesh_ref_put(mesh), RES_OK);