star-enclosures-3d

Extract enclosures from 3D geometry
git clone git://git.meso-star.fr/star-enclosures-3d.git
Log | Files | Refs | README | LICENSE

commit 980cb99ba865ddb2649c1f9bcc3273f3454724ff
parent 00b401cd586b47fa9bfa7a316b6ae428b94739eb
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu, 30 Jul 2020 18:35:29 +0200

Fix the senc3d_scene_get_max_medium API call

Diffstat:
Msrc/senc3d.h | 21+++++++++++----------
Msrc/senc3d_descriptor.c | 53++++++++++++++++++++++++++++++++++++++++++-----------
Msrc/senc3d_enclosure_data.h | 13++++++-------
Msrc/senc3d_scene.c | 8++------
Msrc/senc3d_scene_analyze.c | 41+++++++++++++++++++++++------------------
Msrc/senc3d_scene_c.h | 1-
Msrc/test_senc3d_scene.c | 16++++++++++++++++
7 files changed, 100 insertions(+), 53 deletions(-)

diff --git a/src/senc3d.h b/src/senc3d.h @@ -188,7 +188,7 @@ senc3d_scene_create const unsigned itri, unsigned ids[SENC3D_GEOMETRY_DIMENSION], void* context), - /* User function that provides media ids for triangles */ + /* User function that provides medium ids for triangles */ void(*get_media) /* Can be NULL <=> SENC3D_UNSPECIFIED_MEDIUM medium used */ (const unsigned itri, unsigned med[2], void* context), /* Number of vertices */ @@ -242,9 +242,10 @@ senc3d_scene_get_vertex const unsigned ivert, double coord[SENC3D_GEOMETRY_DIMENSION]); -/* Returns the greater medium id found in added geometry. In API calls using a - * medium, any value in the [0 max_medium_id[ range is valid. However there can - * be unused ids (no geometry refered to this medium id). */ +/* Returns the greater medium id found in geometry or SENC3D_UNSPECIFIED_MEDIUM + * if the geometry only used SENC3D_UNSPECIFIED_MEDIUM. Any value in range + * [0 max_medium_id[ as well as SENC3D_UNSPECIFIED_MEDIUM is valid in API calls + * requiring a medium (even if this medium id is unused). */ SENC3D_API res_T senc3d_scene_get_max_medium (const struct senc3d_scene* scene, @@ -257,11 +258,11 @@ senc3d_scene_get_enclosure_count unsigned* count); /* Returns the number of enclosures that have some geometry refering to the - * imed_th medium or SENC3D_UNSPECIFIED_MEDIUM. */ + * medium med (including SENC3D_UNSPECIFIED_MEDIUM). */ SENC3D_API res_T senc3d_scene_get_enclosure_count_by_medium (const struct senc3d_scene* scene, - const unsigned imed, + const unsigned med, unsigned* count); /* Returns the idx_th enclosure. */ @@ -271,12 +272,12 @@ senc3d_scene_get_enclosure const unsigned idx, struct senc3d_enclosure** enclosure); -/* Returns the idx_th enclosure using the imed_th medium or - * SENC3D_UNSPECIFIED_MEDIUM. */ +/* Returns the idx_th enclosure using the medium med (including + * SENC3D_UNSPECIFIED_MEDIUM). */ SENC3D_API res_T senc3d_scene_get_enclosure_by_medium (struct senc3d_scene* scene, - const unsigned imed, + const unsigned med, const unsigned idx, struct senc3d_enclosure** enclosure); @@ -376,7 +377,7 @@ senc3d_enclosure_get_triangle_id unsigned* gid, enum senc3d_side* side); -/* Returns the id of the imed_th medium of an enclosure. */ +/* Returns the the imed_th medium id of an enclosure. */ SENC3D_API res_T senc3d_enclosure_get_medium (const struct senc3d_enclosure* enclosure, diff --git a/src/senc3d_descriptor.c b/src/senc3d_descriptor.c @@ -29,7 +29,16 @@ senc3d_scene_get_max_medium (const struct senc3d_scene* scn, medium_id_t* max_medium_id) { if(!scn || !max_medium_id) return RES_BAD_ARG; - *max_medium_id = scn->next_medium_idx - 1; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == darray_side_range_size_get(&scn->media_use)); + ASSERT(darray_side_range_size_get(&scn->media_use) >= 1); + if(darray_side_range_size_get(&scn->media_use) == 1) + *max_medium_id = SENC3D_UNSPECIFIED_MEDIUM; + else { + size_t sz = darray_side_range_size_get(&scn->media_use) - 2; + ASSERT(sz <= MEDIUM_MAX__); + *max_medium_id = (medium_id_t)sz; + } return RES_OK; } @@ -55,13 +64,15 @@ senc3d_scene_get_enclosure_count_by_medium size_t tmp; size_t m_idx; const struct darray_enc_id* enc_ids; - if(!scn || !count - || (imed != SENC3D_UNSPECIFIED_MEDIUM && imed >= scn->next_medium_idx)) + if(!scn || !count) return RES_BAD_ARG; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == darray_side_range_size_get(&scn->media_use)); + ASSERT(darray_side_range_size_get(&scn->media_use) >= 1); + if(imed != SENC3D_UNSPECIFIED_MEDIUM + && imed >= darray_side_range_size_get(&scn->media_use)) return RES_BAD_ARG; if(darray_trg_id_size_get(&scn->analyze.overlapping_ids)) return RES_BAD_OP; - ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) - == 1 + scn->next_medium_idx); m_idx = medium_id_2_medium_idx(imed); enc_ids = darray_enc_ids_array_cdata_get(&scn->analyze.enc_ids_array_by_medium) + m_idx; @@ -79,6 +90,9 @@ senc3d_scene_get_enclosure { struct senc3d_enclosure* enc; if(!scn || !out_enc) return RES_BAD_ARG; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == darray_side_range_size_get(&scn->media_use)); + ASSERT(darray_side_range_size_get(&scn->media_use) >= 1); if(darray_trg_id_size_get(&scn->analyze.overlapping_ids)) return RES_BAD_OP; if(idx >= darray_enclosure_size_get(&scn->analyze.enclosures)) @@ -99,16 +113,18 @@ senc3d_scene_get_enclosure_by_medium size_t m_idx; const struct darray_enc_id* enc_ids; enclosure_id_t index; - if(!scn || !out_enc - || (imed != SENC3D_UNSPECIFIED_MEDIUM && imed >= scn->next_medium_idx)) + if(!scn || !out_enc) return RES_BAD_ARG; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == darray_side_range_size_get(&scn->media_use)); + ASSERT(darray_side_range_size_get(&scn->media_use) >= 1); + if(imed != SENC3D_UNSPECIFIED_MEDIUM + && imed >= darray_side_range_size_get(&scn->media_use)) return RES_BAD_ARG; if(darray_trg_id_size_get(&scn->analyze.overlapping_ids)) return RES_BAD_OP; - ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) - == 1 + scn->next_medium_idx); m_idx = medium_id_2_medium_idx(imed); - enc_ids = - darray_enc_ids_array_cdata_get(&scn->analyze.enc_ids_array_by_medium) + m_idx; + enc_ids = darray_enc_ids_array_cdata_get(&scn->analyze.enc_ids_array_by_medium) + + m_idx; if(idx >= darray_enc_id_size_get(enc_ids)) return RES_BAD_ARG; index = darray_enc_id_cdata_get(enc_ids)[idx]; return senc3d_scene_get_enclosure(scn, index, out_enc); @@ -123,6 +139,9 @@ senc3d_scene_get_triangle_enclosures const struct triangle_enc* trg; int i; if(!enclosures || !scn) return RES_BAD_ARG; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == darray_side_range_size_get(&scn->media_use)); + ASSERT(darray_side_range_size_get(&scn->media_use) >= 1); if(darray_trg_id_size_get(&scn->analyze.overlapping_ids)) return RES_BAD_OP; if(itri >= darray_triangle_enc_size_get(&scn->analyze.triangles_enc)) @@ -140,6 +159,9 @@ senc3d_scene_get_frontier_segments_count size_t tmp; if(!scn || !count) return RES_BAD_ARG; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == darray_side_range_size_get(&scn->media_use)); + ASSERT(darray_side_range_size_get(&scn->media_use) >= 1); if(darray_trg_id_size_get(&scn->analyze.overlapping_ids)) return RES_BAD_OP; tmp = darray_frontier_edge_size_get(&scn->analyze.frontiers); @@ -159,6 +181,9 @@ senc3d_scene_get_frontier_segment if(!vrtx_id || !scn || !trg_id || iseg >= darray_frontier_edge_size_get(&scn->analyze.frontiers)) return RES_BAD_ARG; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == darray_side_range_size_get(&scn->media_use)); + ASSERT(darray_side_range_size_get(&scn->media_use) >= 1); if(darray_trg_id_size_get(&scn->analyze.overlapping_ids)) return RES_BAD_OP; edge = darray_frontier_edge_cdata_get(&scn->analyze.frontiers) + iseg; @@ -178,6 +203,9 @@ senc3d_scene_get_overlapping_triangles_count size_t tmp; if(!scn || !count) return RES_BAD_ARG; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == darray_side_range_size_get(&scn->media_use)); + ASSERT(darray_side_range_size_get(&scn->media_use) >= 1); tmp = darray_trg_id_size_get(&scn->analyze.overlapping_ids); ASSERT(tmp <= VRTX_MAX__); *count = (trg_id_t)tmp; /* Back to API type */ @@ -193,6 +221,9 @@ senc3d_scene_get_overlapping_triangle if(!scn || !trg_id || idx >= darray_trg_id_size_get(&scn->analyze.overlapping_ids)) return RES_BAD_ARG; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == darray_side_range_size_get(&scn->media_use)); + ASSERT(darray_side_range_size_get(&scn->media_use) >= 1); *trg_id = darray_trg_id_cdata_get(&scn->analyze.overlapping_ids)[idx]; return RES_OK; } \ No newline at end of file diff --git a/src/senc3d_enclosure_data.h b/src/senc3d_enclosure_data.h @@ -79,10 +79,10 @@ static FINLINE res_T bool_array_of_media_merge (struct darray_uchar* dst, const uchar* src, - const medium_id_t sz) + const size_t sz) { res_T res = RES_OK; - medium_id_t i; + size_t i; uchar* data_dst; ASSERT(src && dst); @@ -103,20 +103,19 @@ static FINLINE res_T bool_array_of_media_to_darray_media (struct darray_media* dst, const struct darray_uchar* src, - const medium_id_t next_medium_idx) + const size_t sz) { res_T res = RES_OK; int64_t m_idx; const uchar* data; - ASSERT(src && dst); + ASSERT(src && dst && sz < INT64_MAX); data = darray_uchar_cdata_get(src); - ASSERT(next_medium_idx + 1 == darray_uchar_size_get(src)); + ASSERT(sz == darray_uchar_size_get(src)); darray_media_clear(dst); if(res != RES_OK) goto error; - ASSERT(next_medium_idx <= MEDIUM_MAX__ + 1); - FOR_EACH(m_idx, 0, 1 + (int64_t)next_medium_idx) { + FOR_EACH(m_idx, 0, (int64_t)sz) { medium_id_t medium = medium_idx_2_medium_id(m_idx); if(!data[m_idx]) continue; res = darray_media_push_back(dst, &medium); diff --git a/src/senc3d_scene.c b/src/senc3d_scene.c @@ -99,7 +99,6 @@ senc3d_scene_create scn->dev = dev; scn->convention = conv; scn->ntris = ntris; - scn->next_medium_idx = 0; scn->nverts = nverts; darray_triangle_in_init(dev->allocator, &scn->triangles_in); darray_position_init(dev->allocator, &scn->vertices); @@ -206,10 +205,7 @@ senc3d_scene_create struct side_range* media_use; size_t m_idx = medium_id_2_medium_idx(med[s]); tmp.medium[s] = med[s]; - if(m_idx >= scn->next_medium_idx) { - medium_id_t medium; - medium = (medium_id_t)m_idx; - scn->next_medium_idx = medium; + if(m_idx >= darray_side_range_size_get(&scn->media_use)) { OK(darray_side_range_resize(&scn->media_use, 1 + m_idx)); } /* media_use 0 is for SENC3D_UNSPECIFIED_MEDIUM */ @@ -226,7 +222,7 @@ senc3d_scene_create } OK(darray_enc_ids_array_resize(&scn->analyze.enc_ids_array_by_medium, - 1 + scn->next_medium_idx)); /* +1 is for unspecified */ + darray_side_range_size_get(&scn->media_use))); /* Proceed to the analyze */ OK(scene_analyze(scn)); diff --git a/src/senc3d_scene_analyze.c b/src/senc3d_scene_analyze.c @@ -89,7 +89,7 @@ get_side_not_in_connex_component ASSERT(trgsides && processed && first_side_not_in_component); { side_id_t i = *first_side_not_in_component; - while (i <= last_side + while(i <= last_side && (trgsides[i].medium != medium || (processed[TRGSIDE_2_TRG(i)] & TRGSIDE_2_SIDEFLAG(i)))) ++i; @@ -273,9 +273,12 @@ extract_connex_components #endif /* We loop on sides to build connex components. */ + ASSERT(darray_side_range_size_get(&scn->media_use) <= INT64_MAX); #pragma omp for schedule(dynamic) nowait /* Process all media, including unspecified */ - for(m_idx = 0; m_idx < 1 + (int64_t)scn->next_medium_idx; m_idx++) { + for(m_idx = 0; m_idx < (int64_t)darray_side_range_size_get(&scn->media_use); + m_idx++) + { const medium_id_t medium = medium_idx_2_medium_id(m_idx); /* media_use 0 is for SENC3D_UNSPECIFIED_MEDIUM, n+1 is for n */ const struct side_range* media_use = @@ -328,10 +331,10 @@ extract_connex_components /* Reuse array if possible, or create a new one */ if(current_media) { /* current_media 0 is for SENC3D_UNSPECIFIED_MEDIUM, n+1 is for n */ - memset(current_media, 0, 1 + scn->next_medium_idx); + memset(current_media, 0, darray_side_range_size_get(&scn->media_use)); } else { - current_media = MEM_CALLOC(alloc, 1 + scn->next_medium_idx, - sizeof(*current_media)); + current_media = MEM_CALLOC(alloc, + darray_side_range_size_get(&scn->media_use), sizeof(*current_media)); if(!current_media) { *p_res = RES_MEM_ERR; continue; @@ -403,8 +406,7 @@ extract_connex_components side_id_t used_side = darray_side_id_cdata_get(&current_component)[ii]; trg_id_t used_trg_id = TRGSIDE_2_TRG(used_side); - enum side_flag used_side_flag - = TRGSIDE_2_SIDEFLAG(used_side); + enum side_flag used_side_flag = TRGSIDE_2_SIDEFLAG(used_side); uchar* used = processed + used_trg_id; ASSERT(*used & (uchar)used_side_flag); /* Set the used flag for sides in cancelled component as leading @@ -771,7 +773,7 @@ group_connex_components enc->side_range.last = MMAX(enc->side_range.last, cc->side_range.last); enc->side_count += cc->side_count; tmp_res = bool_array_of_media_merge(&enc->tmp_enclosed_media, cc->media, - scn->next_medium_idx + 1); + darray_side_range_size_get(&scn->media_use)); if(tmp_res != RES_OK) { *res = tmp_res; break; @@ -1017,9 +1019,9 @@ collect_and_link_neighbours p_crt_side->medium = triangles_in[crt_id].medium[crt_side]; p_ccw_side->medium = triangles_in[ccw_id].medium[ccw_side]; ASSERT(p_crt_side->medium == SENC3D_UNSPECIFIED_MEDIUM - || p_crt_side->medium < scn->next_medium_idx); + || p_crt_side->medium < darray_side_range_size_get(&scn->media_use) - 1); ASSERT(p_ccw_side->medium == SENC3D_UNSPECIFIED_MEDIUM - || p_ccw_side->medium < scn->next_medium_idx); + || p_ccw_side->medium < darray_side_range_size_get(&scn->media_use) - 1); /* Detect triangles that could surround a hole: * - single triangle on (one of) its edge * - different media on its sides */ @@ -1171,9 +1173,10 @@ build_result == enc->header.enclosure_id); enc->header.is_infinite = (e == 0); - ASSERT(enc->header.enclosed_media_count < 1 + scn->next_medium_idx); - OK2(bool_array_of_media_to_darray_media - (&enc->enclosed_media, &enc->tmp_enclosed_media, scn->next_medium_idx)); + ASSERT(enc->header.enclosed_media_count + < darray_side_range_size_get(&scn->media_use)); + OK2(bool_array_of_media_to_darray_media(&enc->enclosed_media, + &enc->tmp_enclosed_media, darray_side_range_size_get(&scn->media_use))); ASSERT(darray_media_size_get(&enc->enclosed_media) <= MEDIUM_MAX__); enc->header.enclosed_media_count = (medium_id_t)darray_media_size_get(&enc->enclosed_media); @@ -1184,11 +1187,13 @@ build_result medium_id_t medium = darray_media_cdata_get(&enc->enclosed_media)[m]; size_t m_idx = medium_id_2_medium_idx(medium); struct darray_enc_id* enc_ids_array_by_medium; - ASSERT(medium == SENC3D_UNSPECIFIED_MEDIUM || medium < scn->next_medium_idx); + ASSERT(medium == SENC3D_UNSPECIFIED_MEDIUM + || medium < darray_side_range_size_get(&scn->media_use) - 1); ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) - == 1 + scn->next_medium_idx); + == darray_side_range_size_get(&scn->media_use)); enc_ids_array_by_medium = - darray_enc_ids_array_data_get(&scn->analyze.enc_ids_array_by_medium) + m_idx; + darray_enc_ids_array_data_get(&scn->analyze.enc_ids_array_by_medium) + + m_idx; #pragma omp critical { tmp_res = darray_enc_id_push_back(enc_ids_array_by_medium, &e); @@ -1364,7 +1369,7 @@ scene_analyze connex_components_initialized = 1; /* Just a hint; to limit contention */ OK2(darray_ptr_component_descriptor_reserve(&connex_components, - 2 + 2 * scn->next_medium_idx)); + 2 * darray_side_range_size_get(&scn->media_use))); darray_triangle_comp_init(scn->dev->allocator, &triangles_comp); triangles_comp_initialized = 1; OK2(darray_triangle_comp_resize(&triangles_comp, scn->ntris)); @@ -1384,7 +1389,7 @@ scene_analyze tmp_res = darray_trg_id_reserve(&scn->analyze.overlapping_ids, htable_overlap_size_get(&overlaps)); if(tmp_res != RES_OK) goto tmp_error2; - while (!htable_overlap_iterator_eq(&it, &end)) { + while(!htable_overlap_iterator_eq(&it, &end)) { tmp_res = darray_trg_id_push_back(&scn->analyze.overlapping_ids, htable_overlap_iterator_key_get(&it)); if(tmp_res != RES_OK) goto tmp_error2; diff --git a/src/senc3d_scene_c.h b/src/senc3d_scene_c.h @@ -300,7 +300,6 @@ struct senc3d_scene { /* Keep sizes */ trg_id_t ntris; /* Trg count */ vrtx_id_t nverts; /* Vrtx count */ - medium_id_t next_medium_idx; /* media_use 0 is for SENC3D_UNSPECIFIED_MEDIUM, n+1 is for n */ struct darray_side_range media_use; diff --git a/src/test_senc3d_scene.c b/src/test_senc3d_scene.c @@ -290,6 +290,9 @@ main(int argc, char** argv) CHK(count == 0); /* Medium 2 unused */ OK(senc3d_scene_get_enclosure_count_by_medium(scn, 3, &count)); CHK(count == 1); /* Medium 3 used */ + OK(senc3d_scene_get_enclosure_count_by_medium(scn, SENC3D_UNSPECIFIED_MEDIUM, + &count)); + CHK(count == 0); OK(senc3d_scene_ref_put(scn)); @@ -308,6 +311,19 @@ main(int argc, char** argv) FOR_EACH(i, 0, 2) CHK(medback[i] == medfront[i]); OK(senc3d_scene_ref_put(scn)); + + /* Geometry with no media information */ + OK(senc3d_scene_create(dev, + SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE, + ntriangles, get_indices, NULL, + nvertices, get_position, &ctx, &scn)); + OK(senc3d_scene_get_max_medium(scn, &maxm)); + CHK(maxm == SENC3D_UNSPECIFIED_MEDIUM); + OK(senc3d_scene_get_enclosure_count_by_medium(scn, SENC3D_UNSPECIFIED_MEDIUM, + &count)); + CHK(count == 2); + + OK(senc3d_scene_ref_put(scn)); OK(senc3d_device_ref_put(dev)); check_memory_allocator(&allocator);