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:
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));