commit 863b0ef8f4fae8935a5f991f32f435cf3659c9d7
parent 1a2b6ef0f7459e2541e56be74ef2a7749fd1d52d
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 23 Jul 2020 11:23:01 +0200
Merge branch 'feature_closest_point' into develop
Diffstat:
6 files changed, 169 insertions(+), 19 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -29,8 +29,8 @@ CMAKE_DEPENDENT_OPTION(ALL_TESTS
# Check dependencies
###############################################################################
find_package(RCMake 0.4 REQUIRED)
-find_package(Star2D 0.3.1 REQUIRED)
-find_package(Star3D 0.6.2 REQUIRED)
+find_package(Star2D 0.4 REQUIRED)
+find_package(Star3D 0.7 REQUIRED)
find_package(StarSP 0.8 REQUIRED)
find_package(StarEnc2D 0.5 REQUIRED)
find_package(StarEnc3D 0.5 REQUIRED)
diff --git a/src/sdis.h b/src/sdis.h
@@ -43,6 +43,7 @@
#define SDIS_VOLUMIC_POWER_NONE 0 /* <=> No volumic power */
#define SDIS_FLUX_NONE DBL_MAX /* <=> No flux */
+#define SDIS_PRIMITIVE_NONE SIZE_MAX /* Invalid primitive */
/* Forward declaration of external opaque data types */
struct logger;
@@ -809,6 +810,20 @@ sdis_scene_get_aabb
double lower[3],
double upper[3]);
+/* Search the point onto the scene geometry that is the closest of `pos'. The
+ * `radius' parameter controls the maximum search distance around `pos'. The
+ * returned closest point is expressed locally to the geometric primitive onto
+ * which it lies. If not found, the returned primitive is SDIS_PRIMITIVE_NONE.
+ * Note that even though only one point is returned, several position can have
+ * the same minimal distance to the queried position. */
+SDIS_API res_T
+sdis_scene_find_closest_point
+ (const struct sdis_scene* scn,
+ const double pos[3], /* Query position */
+ const double radius, /* Maximum search distance around pos */
+ size_t* iprim, /* Primitive index onto which the closest point lies */
+ double uv[2]); /* Parametric cordinate onto the primitive */
+
/* Define the world space position of a point onto the primitive `iprim' whose
* parametric coordinate is uv. */
SDIS_API res_T
@@ -818,7 +833,7 @@ sdis_scene_get_boundary_position
const double uv[2], /* Parametric coordinate onto the primitive */
double pos[3]); /* World space position */
-/* Project a world space position onto a primitive wrt its normal and compute
+/* roject a world space position onto a primitive wrt its normal and compute
* the parametric coordinates of the projected point onto the primitive. This
* function may help to define the probe position onto a boundary as expected
* by the sdis_solve_probe_boundary function.
diff --git a/src/sdis_scene.c b/src/sdis_scene.c
@@ -24,6 +24,7 @@
#include "sdis.h"
#include "sdis_scene_c.h"
+#include <float.h>
#include <limits.h>
/*******************************************************************************
@@ -182,6 +183,22 @@ sdis_scene_get_aabb
}
res_T
+sdis_scene_find_closest_point
+ (const struct sdis_scene* scn,
+ const double pos[3],
+ const double radius,
+ size_t* iprim,
+ double uv[2])
+{
+ if(!scn) return RES_BAD_ARG;
+ if(scene_is_2d(scn)) {
+ return scene_find_closest_point_2d(scn, pos, radius, iprim, uv);
+ } else {
+ return scene_find_closest_point_3d(scn, pos, radius, iprim, uv);
+ }
+}
+
+res_T
sdis_scene_get_boundary_position
(const struct sdis_scene* scn,
const size_t iprim,
@@ -333,7 +350,7 @@ sdis_scene_get_medium_spread
}
}
*out_spread = spread;
-
+
exit:
return res;
error:
diff --git a/src/sdis_scene_Xd.h b/src/sdis_scene_Xd.h
@@ -24,6 +24,7 @@
#include "sdis_scene_c.h"
#include <star/ssp.h>
+#include <rsys/cstr.h>
#include <rsys/float22.h>
#include <rsys/float33.h>
#include <rsys/rsys.h>
@@ -957,6 +958,64 @@ error:
goto exit;
}
+static res_T
+XD(scene_find_closest_point)
+ (const struct sdis_scene* scn,
+ const double pos[3],
+ const double radius,
+ size_t* iprim,
+ double uv[2])
+{
+ struct sXd(hit) hit;
+ float query_pos[DIM];
+ float query_radius;
+ res_T res = RES_OK;
+
+ if(!scn || !pos || radius <= 0 || !iprim || !uv
+ || scene_is_2d(scn) != (DIM == 2)) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Avoid a null query radius due to casting in single-precision */
+ query_radius = MMAX((float)radius, FLT_MIN);
+
+ fX_set_dX(query_pos, pos);
+ res = sXd(scene_view_closest_point)
+ (scn->sXd(view), query_pos, query_radius, NULL, &hit);
+ if(res != RES_OK) {
+#if DIM == 2
+ log_err(scn->dev,
+ "%s: error querying the closest position at {%g, %g} "
+ "for a radius of %g -- %s.\n",
+ FUNC_NAME, SPLIT2(query_pos), query_radius, res_to_cstr(res));
+#else
+ log_err(scn->dev,
+ "%s: error querying the closest position at {%g, %g, %g} "
+ "for a radius of %g -- %s.\n",
+ FUNC_NAME, SPLIT3(query_pos), query_radius, res_to_cstr(res));
+#endif
+ goto error;
+ }
+
+ if(SXD_HIT_NONE(&hit)) {
+ *iprim = SDIS_PRIMITIVE_NONE;
+ } else {
+ *iprim = hit.prim.scene_prim_id;
+#if DIM == 2
+ uv[0] = hit.u;
+#else
+ uv[0] = hit.uv[0];
+ uv[1] = hit.uv[1];
+#endif
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
/*******************************************************************************
* Local functions
******************************************************************************/
diff --git a/src/test_sdis_scene.c b/src/test_sdis_scene.c
@@ -89,17 +89,19 @@ get_interface(const size_t itri, struct sdis_interface** bound, void* context)
static void
test_scene_3d(struct sdis_device* dev, struct sdis_interface* interf)
{
- struct sdis_scene* scn = NULL;
+ size_t duplicated_indices[] = { 0, 1, 2, 0, 2, 1 };
+ size_t degenerated_indices[] = { 0, 1, 1 };
+ double duplicated_vertices[] = { 0, 0, 0, 1, 1, 1, 0, 0, 0 };
double lower[3], upper[3];
- double uv0[2], uv1[2], pos[3], pos1[3];
+ double uv0[2], uv1[2], uv2[2], pos[3], pos1[3];
struct context ctx;
struct senc2d_scene* scn2d;
struct senc3d_scene* scn3d;
+ struct sdis_scene* scn = NULL;
size_t ntris, npos;
+ size_t iprim;
size_t i;
- size_t duplicated_indices[] = { 0, 1, 2, 0, 2, 1 };
- size_t degenerated_indices[] = { 0, 1, 1 };
- double duplicated_vertices[] = { 0, 0, 0, 1, 1, 1, 0, 0, 0 };
+ double dst = 0;
size_t dup_vrtx_indices[] = { 0, 1, 2 };
enum sdis_scene_dimension dim;
@@ -172,7 +174,32 @@ test_scene_3d(struct sdis_device* dev, struct sdis_interface* interf)
BA(sdis_scene_boundary_project_position(scn, 6, pos, NULL));
OK(sdis_scene_boundary_project_position(scn, 6, pos, uv1));
+ BA(sdis_scene_find_closest_point(NULL, pos, INF, &iprim, uv2));
+ BA(sdis_scene_find_closest_point(scn, NULL, INF, &iprim, uv2));
+ BA(sdis_scene_find_closest_point(scn, pos, 0, &iprim, uv2));
+ BA(sdis_scene_find_closest_point(scn, pos, INF, NULL, uv2));
+ BA(sdis_scene_find_closest_point(scn, pos, INF, &iprim, NULL));
+ OK(sdis_scene_find_closest_point(scn, pos, INF, &iprim, uv2));
+
+ CHK(iprim == 6);
CHK(d2_eq_eps(uv0, uv1, 1.e-6));
+ CHK(d2_eq_eps(uv1, uv2, 1.e-6));
+
+ pos[0] = 0.5;
+ pos[1] = 0.1;
+ pos[2] = 0.25;
+ OK(sdis_scene_find_closest_point(scn, pos, INF, &iprim, uv2));
+ CHK(iprim == 10);
+
+ OK(sdis_scene_boundary_project_position(scn, 10, pos, uv0));
+ CHK(d2_eq_eps(uv0, uv2, 1.e-6));
+
+ OK(sdis_scene_get_boundary_position(scn, iprim, uv2, pos1));
+ dst = d3_len(d3_sub(pos1, pos, pos1));
+ CHK(eq_eps(dst, 0.1, 1.e-6));
+
+ OK(sdis_scene_find_closest_point(scn, pos, 0.09, &iprim, uv2));
+ CHK(iprim == SDIS_PRIMITIVE_NONE);
FOR_EACH(i, 0, 64) {
uv0[0] = rand_canonic();
@@ -180,7 +207,10 @@ test_scene_3d(struct sdis_device* dev, struct sdis_interface* interf)
OK(sdis_scene_get_boundary_position(scn, 4, uv0, pos));
OK(sdis_scene_boundary_project_position(scn, 4, pos, uv1));
+ OK(sdis_scene_find_closest_point(scn, pos, INF, &iprim, uv2));
CHK(d2_eq_eps(uv0, uv1, 1.e-6));
+ CHK(d2_eq_eps(uv1, uv2, 1.e-6));
+ CHK(iprim == 4);
}
pos[0] = 10;
@@ -208,17 +238,19 @@ test_scene_3d(struct sdis_device* dev, struct sdis_interface* interf)
static void
test_scene_2d(struct sdis_device* dev, struct sdis_interface* interf)
{
+ size_t duplicated_indices[] = { 0, 1, 1, 0 };
+ size_t degenerated_indices[] = { 0, 0 };
+ double duplicated_vertices[] = { 0, 0, 0, 0 };
struct sdis_scene* scn = NULL;
double lower[2], upper[2];
- double u0, u1, pos[2];
+ double u0, u1, u2, pos[2], pos1[2];
+ double dst;
struct context ctx;
struct senc2d_scene* scn2d;
struct senc3d_scene* scn3d;
size_t nsegs, npos;
size_t i;
- size_t duplicated_indices[] = { 0, 1, 1, 0 };
- size_t degenerated_indices[] = { 0, 0 };
- double duplicated_vertices[] = { 0, 0, 0, 0 };
+ size_t iprim;
size_t dup_vrtx_indices[] = { 0, 1 };
enum sdis_scene_dimension dim;
@@ -288,14 +320,41 @@ test_scene_2d(struct sdis_device* dev, struct sdis_interface* interf)
BA(sdis_scene_boundary_project_position(scn, 1, pos, NULL));
OK(sdis_scene_boundary_project_position(scn, 1, pos, &u1));
+ BA(sdis_scene_find_closest_point(NULL, pos, INF, &iprim, &u2));
+ BA(sdis_scene_find_closest_point(scn, NULL, INF, &iprim, &u2));
+ BA(sdis_scene_find_closest_point(scn, pos, 0, &iprim, &u2));
+ BA(sdis_scene_find_closest_point(scn, pos, INF, NULL, &u2));
+ BA(sdis_scene_find_closest_point(scn, pos, INF, &iprim, NULL));
+ OK(sdis_scene_find_closest_point(scn, pos, INF, &iprim, &u2));
+
CHK(eq_eps(u0, u1, 1.e-6));
+ CHK(eq_eps(u1, u2, 1.e-6));
+ CHK(iprim == 1);
+
+ pos[0] = 0.5;
+ pos[1] = 0.1;
+ OK(sdis_scene_find_closest_point(scn, pos, INF, &iprim, &u2));
+ CHK(iprim == 0);
+
+ OK(sdis_scene_boundary_project_position(scn, 0, pos, &u0));
+ CHK(eq_eps(u0, u2, 1.e-6));
+
+ OK(sdis_scene_get_boundary_position(scn, iprim, &u2, pos1));
+ dst = d2_len(d2_sub(pos1, pos, pos1));
+ CHK(eq_eps(dst, 0.1, 1.e-6));
+
+ OK(sdis_scene_find_closest_point(scn, pos, 0.09, &iprim, &u2));
+ CHK(iprim == SDIS_PRIMITIVE_NONE);
FOR_EACH(i, 0, 64) {
u0 = rand_canonic();
OK(sdis_scene_get_boundary_position(scn, 2, &u0, pos));
OK(sdis_scene_boundary_project_position(scn, 2, pos, &u1));
+ OK(sdis_scene_find_closest_point(scn, pos, INF, &iprim, &u2));
CHK(eq_eps(u0, u1, 1.e-6));
+ CHK(eq_eps(u1, u2, 1.e-6));
+ CHK(iprim == 2);
}
d2(pos, 5, 0.5);
diff --git a/src/test_sdis_utils.h b/src/test_sdis_utils.h
@@ -52,12 +52,12 @@ static const size_t box_nvertices = sizeof(box_vertices) / sizeof(double[3]);
* Front, right Back, left and Z
* and Top faces bottom faces */
static const size_t box_indices[12/*#triangles*/*3/*#indices per triangle*/] = {
- 0, 2, 1, 1, 2, 3, /* Front face */
- 0, 4, 2, 2, 4, 6, /* Left face*/
- 4, 5, 6, 6, 5, 7, /* Back face */
- 3, 7, 1, 1, 7, 5, /* Right face */
- 2, 6, 3, 3, 6, 7, /* Top face */
- 0, 1, 4, 4, 1, 5 /* Bottom face */
+ 0, 2, 1, 1, 2, 3, /* -Z */
+ 0, 4, 2, 2, 4, 6, /* -X */
+ 4, 5, 6, 6, 5, 7, /* +Z */
+ 3, 7, 5, 5, 1, 3, /* +X */
+ 2, 6, 7, 7, 3, 2, /* +Y */
+ 0, 1, 5, 5, 4, 0 /* -Y */
};
static const size_t box_ntriangles = sizeof(box_indices) / sizeof(size_t[3]);