star-2d

Contour structuring for efficient 2D geometric queries
git clone git://git.meso-star.fr/star-2d.git
Log | Files | Refs | README | LICENSE

commit f49564ed4db5ef5d670cc656c346e16c59b046db
parent 61bf2f7516ab20d5176f3e6f98367910c995704f
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 18 Dec 2020 17:02:00 +0100

BugFix: closest point returned wrong hit

Diffstat:
Msrc/s2d_scene_view_closest_point.c | 7++++---
Msrc/test_s2d_closest_point.c | 52+++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/src/s2d_scene_view_closest_point.c b/src/s2d_scene_view_closest_point.c @@ -61,7 +61,7 @@ closest_point_segment /* Orthogonally project the point onto the segment */ f2_sub(v, p, v0); segment_len = f2_len(E); - dst = f2_dot(v, E); + dst = f2_dot(v, E) / segment_len; /* Check if the closest point is the segment vertex 'v0' */ if(dst <= 0) { @@ -75,8 +75,9 @@ closest_point_segment } /* The closest point is on the segment */ - *s = CLAMP(dst / segment_len, 0, 1); - return f2_add(closest_pt, f2_mulf(closest_pt, E, dst/segment_len), v0); + *s = dst / segment_len; + ASSERT(*s == CLAMP(*s, 0, 1)); + return f2_add(closest_pt, f2_mulf(closest_pt, E, *s), v0); } static bool diff --git a/src/test_s2d_closest_point.c b/src/test_s2d_closest_point.c @@ -72,8 +72,8 @@ closest_point_segment f2_sub(v, p, a); f2_sub(E, b, a); - dst = f2_dot(v, E); len = f2_len(E); + dst = f2_dot(v, E) / len; if(dst <= 0) return f2_set(pt, a); if(dst >= len) return f2_set(pt, b); @@ -366,7 +366,7 @@ test_single_segment(struct s2d_device* dev) FOR_EACH(i, 0, 10000) { /* Randomly generate a point in a bounding box that is 10 times the size of - * the triangle AABB */ + * the segment AABB */ pos[0] = mid[0] + (rand_canonic() * 2 - 1) * (upp[0] - low[0]) * 5.f; pos[1] = mid[1] + (rand_canonic() * 2 - 1) * (upp[1] - low[1]) * 5.f; @@ -383,7 +383,7 @@ test_single_segment(struct s2d_device* dev) float radius; /* Randomly generate a point in a bounding box that is 10 times the size of - * the triangle AABB */ + * the segment AABB */ pos[0] = mid[0] + (rand_canonic() * 2 - 1) * (upp[0] - low[0]) * 5.f; pos[1] = mid[1] + (rand_canonic() * 2 - 1) * (upp[1] - low[1]) * 5.f; @@ -403,6 +403,52 @@ test_single_segment(struct s2d_device* dev) CHK(s2d_scene_view_ref_put(view) == RES_OK); CHK(s2d_shape_ref_put(shape) == RES_OK); CHK(s2d_scene_ref_put(scn) == RES_OK); + + FOR_EACH(i, 0, 100) { + float A[2], B[2]; + /* Randomly generate a segment AB on the X axis */ + A[0] = -5 + rand_canonic() * 10; + B[0] = -5 + rand_canonic() * 10; + A[1] = B[1] = 0; + + f2_set(vertices + 0, A); + f2_set(vertices + 2, B); + + CHK(s2d_scene_create(dev, &scn) == RES_OK); + CHK(s2d_shape_create_line_segments(dev, &shape) == RES_OK); + CHK(s2d_scene_attach_shape(scn, shape) == RES_OK); + + vdata.usage = S2D_POSITION; + vdata.type = S2D_FLOAT2; + vdata.get = line_segments_get_position; + desc.vertices = vertices; + desc.indices = indices; + CHK(s2d_line_segments_setup_indexed_vertices + (shape, 1, line_segments_get_ids, 2, &vdata, 1, &desc) == RES_OK); + + CHK(s2d_scene_view_create(scn, S2D_TRACE, &view) == RES_OK); + pos[0] = 0; pos[1] = 1; + CHK(s2d_scene_view_closest_point(view, pos, (float)INF, NULL, &hit) == RES_OK); + CHK(!S2D_HIT_NONE(&hit)); + CHK(s2d_primitive_get_attrib(&hit.prim, S2D_POSITION, hit.u, &attr) == RES_OK); + + /* Cross check the closest point query result */ + closest_point_segment(pos, A, B, closest_pos); + CHK(f2_eq_eps(closest_pos, attr.value, 1.e-4f)); + if(A[0] > pos[0] && B[0] > pos[0]) { + CHK(f2_eq_eps(closest_pos, (A[0] > B[0] ? B : A), 1.e-4f)); + } + else if(A[0] < pos[0] && B[0] < pos[0]) { + CHK(f2_eq_eps(closest_pos, (A[0] < B[0] ? B : A), 1.e-4f)); + } else { + float expected[2] = { 0, 0 }; + CHK(f2_eq_eps(closest_pos, expected, 1.e-4f)); + } + + CHK(s2d_scene_view_ref_put(view) == RES_OK); + CHK(s2d_shape_ref_put(shape) == RES_OK); + CHK(s2d_scene_ref_put(scn) == RES_OK); + } } /*******************************************************************************