star-cpr

Clip 2D meshes with 2D polygons
git clone git://git.meso-star.fr/star-cpr.git
Log | Files | Refs | README | LICENSE

commit 7cd0a118a05c25332792fcb754c006f5e7fafa86
parent 188a299ab4625cf5306af94f2c2d156623f0acd7
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Tue, 21 Feb 2023 18:20:24 +0100

Allow callbacks to be NULL when checking for intersections

Diffstat:
Msrc/scpr.h | 10+++++++---
Msrc/scpr_intersector.c | 21+++++++++++++++------
Msrc/test_scpr_intersector.c | 31++++++++++++++++++++-----------
3 files changed, 42 insertions(+), 20 deletions(-)

diff --git a/src/scpr.h b/src/scpr.h @@ -84,13 +84,17 @@ struct scpr_callback_segment { }; /* A struct holding callbacks that are called when carying an intersection check - * on a bunch of segments. */ + * on a bunch of segments. + * If a callbacks is NULL, the corresponding events are unreported, but at least + * 1 callback must be non NULL. + * If a callback call returns non-zero, the whole scpr_intersector_check call + * exits whith a RES_BAD_ARG error status without further processing. */ struct scpr_intersector_check_callbacks { - void(*simple_intersection) + int(*simple_intersection) (struct scpr_callback_segment* segment1, struct scpr_callback_segment* segment2, void* ctx); - void(*colinear_segments) + int(*collinear_segments) (struct scpr_callback_segment* segment1, struct scpr_callback_segment* segment2, void* ctx); diff --git a/src/scpr_intersector.c b/src/scpr_intersector.c @@ -531,7 +531,7 @@ check_two_segments_intersection /* No intersection at all */ } else if(ccw1 == 0 && ccw2 == 0 && ccw3 == 0 && ccw4 == 0) { - /* Colinear segments */ + /* collinear segments */ struct scpr_callback_segment arg1, arg2; arg1.polygon = polygon1; arg1.component = comp_idx1; @@ -541,7 +541,12 @@ check_two_segments_intersection arg2.component = comp_idx2; arg2.first_vertex = r21; arg2.last_vertex = r22; - callbacks->colinear_segments(&arg1, &arg2, data); + if(callbacks->collinear_segments + && callbacks->collinear_segments(&arg1, &arg2, data)) + { + res = RES_BAD_ARG; + goto error; + } } else if(ccw1 * ccw2 < 0 && ccw3 * ccw4 < 0) { /* Basic segment intersection */ @@ -554,8 +559,13 @@ check_two_segments_intersection arg2.component = comp_idx2; arg2.first_vertex = r21; arg2.last_vertex = r22; - callbacks->simple_intersection(&arg1, &arg2, data); - } + if(callbacks->simple_intersection + && callbacks->simple_intersection(&arg1, &arg2, data)) + { + res = RES_BAD_ARG; + goto error; + } +} exit: return res; @@ -769,8 +779,7 @@ scpr_intersector_check res_T res = RES_OK; if(!intersector || !callbacks - || !callbacks->simple_intersection - || !callbacks->colinear_segments) + || (!callbacks->simple_intersection && !callbacks->collinear_segments)) { res = RES_BAD_ARG; goto error; diff --git a/src/test_scpr_intersector.c b/src/test_scpr_intersector.c @@ -23,11 +23,11 @@ #include <memory.h> struct cpt { - size_t basic, colinear; + size_t simple, collinear; }; -static void -basic_intersection +static int +simple_intersection (struct scpr_callback_segment* segment1, struct scpr_callback_segment* segment2, void* data) @@ -35,11 +35,12 @@ basic_intersection struct cpt* cpt = (struct cpt*)data; (void)segment1; (void)segment2; ASSERT(cpt); - cpt->basic++; + cpt->simple++; + return 0; } -static void -colinear_segments +static int +collinear_segments (struct scpr_callback_segment* segment1, struct scpr_callback_segment* segment2, void* data) @@ -47,7 +48,8 @@ colinear_segments struct cpt* cpt = (struct cpt*)data; (void)segment1; (void)segment2; ASSERT(cpt); - cpt->colinear++; + cpt->collinear++; + return 0; } int @@ -173,11 +175,18 @@ main(int argc, char** argv) BAD(scpr_intersector_check(NULL, &cb, NULL)); BAD(scpr_intersector_check(inter, NULL, NULL)); BAD(scpr_intersector_check(inter, &cb, NULL)); - cb.simple_intersection = basic_intersection; - cb.colinear_segments = colinear_segments; + BAD(scpr_intersector_check(inter, &cb, &cpt)); /* Callbacks are all NULL */ + /* Report only intersections */ + cb.simple_intersection = simple_intersection; + OK(scpr_intersector_check(inter, &cb, &cpt)); + CHK(cpt.simple == 2); + CHK(cpt.collinear == 0); + /* Report intersections and collinearity */ + cb.collinear_segments = collinear_segments; + cpt.simple = cpt.collinear = 0; OK(scpr_intersector_check(inter, &cb, &cpt)); - CHK(cpt.basic == 2); - CHK(cpt.colinear == 2); + CHK(cpt.simple == 2); + CHK(cpt.collinear == 2); OK(scpr_polygon_ref_put(p01)); OK(scpr_polygon_ref_put(p23));