star-enclosures-2d

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

commit 0ba350c43693e11d0512e5b667f6a1539b2a0ad9
parent af4c65de032591da950d4b5640153d0329578e7d
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri,  8 Nov 2019 15:18:53 +0100

Merge branch 'release_0.4.2'

Diffstat:
MREADME.md | 7+++++++
Mcmake/CMakeLists.txt | 2+-
Msrc/senc2d.h | 11++++++++++-
Msrc/senc2d_descriptor.c | 15+++++++++++++++
Msrc/senc2d_scene.c | 23+++++++++++++----------
Msrc/senc2d_scene_analyze.c | 10+++++-----
Msrc/senc2d_scene_c.h | 3+++
Msrc/test_senc2d_descriptor.c | 11+++++++++++
Msrc/test_senc2d_enclosure.c | 2+-
Msrc/test_senc2d_scene.c | 23++++++++++++++++++++++-
Msrc/test_senc2d_undefined_medium_attr.c | 20++++++++++----------
11 files changed, 98 insertions(+), 29 deletions(-)

diff --git a/README.md b/README.md @@ -35,6 +35,13 @@ variable the install directories of its dependencies. Release notes ------------- +### Version 0.4.2 + +- Fix global id of segments; releases 0.4.0 and 0.4.1 are broken + +- Reintroduce an API call to get the global id in user space of + a global unique segment after deduplication + ### Version 0.4.1 - Fix an infinite loop related to a rare numerical accuracy problem. diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -47,7 +47,7 @@ endif() ################################################################################ set(VERSION_MAJOR 0) set(VERSION_MINOR 4) -set(VERSION_PATCH 1) +set(VERSION_PATCH 2) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(SENC2D_FILES_SRC diff --git a/src/senc2d.h b/src/senc2d.h @@ -177,7 +177,8 @@ senc2d_scene_reserve * of SENC_UNDEFINED_MEDIUM that causes no error) and are deduplicated. * The special value SENC2D_UNDEFINED_MEDIUM denotes an undefined medium. * It can be used to define the 2 sides of a segment at different times. - * When deduplicating segments, the first occurence remains. + * When deduplicating segments, the first occurence remains (with its + * original index in user world, regardless of deduplication). * The add_segment and merge_segment callbacks can be used for attributes * management including segment IDs; they allow the client app to store * its own data. They can also fail and stop the add_geometry call. */ @@ -372,6 +373,14 @@ senc2d_descriptor_get_global_segment_enclosures const unsigned iseg, unsigned enclosures[2]); +/* Returns the global id of the iseg_th global unique segment, that is the + * segment index in user world regardless of deduplication. */ +SENC2D_API res_T +senc2d_descriptor_get_global_segment_global_id + (const struct senc2d_descriptor* descriptor, + const unsigned iseg, + unsigned* gid); + /* Returns the number of vertices that are frontier vertices: * - that have arity 1 (single segment using the vertex) * - that connect 2 different media */ diff --git a/src/senc2d_descriptor.c b/src/senc2d_descriptor.c @@ -272,6 +272,21 @@ senc2d_descriptor_get_global_segment_enclosures } res_T +senc2d_descriptor_get_global_segment_global_id + (const struct senc2d_descriptor* desc, + const unsigned iseg, + unsigned* gid) +{ + const struct segment_in* seg; + if(!gid || !desc + || iseg >= darray_segment_in_size_get(&desc->scene->segments_in)) + return RES_BAD_ARG; + seg = darray_segment_in_cdata_get(&desc->scene->segments_in) + iseg; + *gid = seg->global_id; + return RES_OK; +} + +res_T senc2d_descriptor_get_frontier_vertices_count (const struct senc2d_descriptor* desc, unsigned* count) diff --git a/src/senc2d_scene.c b/src/senc2d_scene.c @@ -200,6 +200,8 @@ senc2d_scene_add_geometry struct segment_in tmp, *range_adjust_ptr = NULL; seg_id_t* p_seg; char reversed; + /* Segment index in user world regardless of deduplication. */ + tmp.global_id = (unsigned)(scn->nsegs + i); indices(i, ind, ctx); /* API: indices needs an unsigned */ FOR_EACH(j, 0, 2) { if(ind[j] >= nverts) { @@ -214,7 +216,7 @@ senc2d_scene_add_geometry const union double2* positions = darray_position_cdata_get(&scn->vertices); log_err(scn->dev, "%s: segment %lu is degenerate.\n", - FUNC_NAME, (unsigned long)scn->nsegs + i); + FUNC_NAME, (unsigned long)tmp.global_id); log_err(scn->dev, " (%g %g) (%g %g)\n", SPLIT2(positions[seg[i].vertice_id[0]].vec), SPLIT2(positions[seg[i].vertice_id[1]].vec)); @@ -251,10 +253,11 @@ senc2d_scene_add_geometry = darray_position_cdata_get(&scn->vertices); log_err(scn->dev, "%s: segment %lu is a duplicate" " of segment %lu with incoherent media.\n", - FUNC_NAME, (unsigned long)(scn->nsegs + i), (unsigned long)*p_seg); + FUNC_NAME, (unsigned long)tmp.global_id, + (unsigned long)seg[*p_seg].global_id); log_err(scn->dev, "Segment %lu:\n (%g %g ) (%g %g)\n", - (unsigned long)*p_seg, + (unsigned long)seg[*p_seg].global_id, SPLIT2(positions[seg[*p_seg].vertice_id[0]].vec), SPLIT2(positions[seg[*p_seg].vertice_id[1]].vec)); log_err(scn->dev, "Media: (%lu, %lu) VS (%lu, %lu)\n", @@ -275,13 +278,13 @@ senc2d_scene_add_geometry scn->sides_with_defined_medium_count++; } } - if (merge_segment) { - OK(merge_segment((unsigned)*p_seg, i, same, ctx)); - } - else { + if(merge_segment) { + OK(merge_segment(seg[*p_seg].global_id, i, same, ctx)); + } else { log_warn(scn->dev, "%s: segment %lu is a duplicate of segment %lu.\n", - FUNC_NAME, (unsigned long)(scn->nsegs + i), (unsigned long)*p_seg); + FUNC_NAME, (unsigned long)tmp.global_id, + (unsigned long)seg[*p_seg].global_id); } } } else { @@ -295,8 +298,8 @@ senc2d_scene_add_geometry if(tmp.medium[j] != SENC2D_UNDEFINED_MEDIUM) scn->sides_with_defined_medium_count++; } - if (add_segment) { - OK(add_segment((unsigned)u, i, ctx)); + if(add_segment) { + OK(add_segment(tmp.global_id, i, ctx)); } ++actual_nusegs; } diff --git a/src/senc2d_scene_analyze.c b/src/senc2d_scene_analyze.c @@ -875,8 +875,8 @@ collect_and_link_neighbours prev_id = previous->seg_id; log_err(scn->dev, "%s: found 2 overlying segments (%lu & %lu).\n", FUNC_NAME, - (unsigned long)crt_id, (unsigned long)prev_id); - + (unsigned long)segments_in[crt_id].global_id, + (unsigned long)segments_in[prev_id].global_id); *res = RES_BAD_OP; return; } @@ -906,7 +906,7 @@ collect_and_link_neighbours { log_warn(scn->dev, "%s: found possible frontier involving segment %lu.\n", - FUNC_NAME, (unsigned long)crt_id); + FUNC_NAME, (unsigned long)segments_in[crt_id].global_id); darray_vrtx_id_push_back(frontiers, &v); } } @@ -1086,7 +1086,7 @@ build_result int ii = revert_segment ? 1 - i : i; side_enc->vertice_id[i] = vertice_id[ii]; } - side_enc->side_id = SEGIDxSIDE_2_SEGSIDE(s, SENC2D_FRONT); + side_enc->side_id = SEGIDxSIDE_2_SEGSIDE(seg_in->global_id, SENC2D_FRONT); } if(segments_enc[s].enclosure[SENC2D_BACK] == e) { /* Back side of the original segment is member of the enclosure */ @@ -1100,7 +1100,7 @@ build_result int ii = revert_segment ? 1 - i : i; side_enc->vertice_id[i] = vertice_id[ii]; } - side_enc->side_id = SEGIDxSIDE_2_SEGSIDE(s, SENC2D_BACK); + side_enc->side_id = SEGIDxSIDE_2_SEGSIDE(seg_in->global_id, SENC2D_BACK); } if(fst_idx == sgd_idx) break; } diff --git a/src/senc2d_scene_c.h b/src/senc2d_scene_c.h @@ -48,6 +48,8 @@ struct segment_in { vrtx_id_t vertice_id[2]; /* Ids of this segment's media */ medium_id_t medium[2]; + /* Segment index in user world regardless of deduplication. */ + unsigned global_id; }; static FINLINE void @@ -57,6 +59,7 @@ segment_in_init(struct mem_allocator* alloc, struct segment_in* seg) { ASSERT(seg); FOR_EACH(i, 0, 2) seg->vertice_id[i] = VRTX_NULL__; FOR_EACH(i, 0, 2) seg->medium[i] = SENC2D_UNDEFINED_MEDIUM; + seg->global_id = 0; } #define DARRAY_NAME segment_in diff --git a/src/test_senc2d_descriptor.c b/src/test_senc2d_descriptor.c @@ -167,6 +167,17 @@ main(int argc, char** argv) == RES_OK); CHK(enclosures[0] == 0 && enclosures[1] == 1); + CHK(senc2d_descriptor_get_global_segment_global_id(NULL, 0, indices) + == RES_BAD_ARG); + CHK(senc2d_descriptor_get_global_segment_global_id(NULL, nvertices, indices) + == RES_BAD_ARG); + CHK(senc2d_descriptor_get_global_segment_global_id(desc, 0, NULL) + == RES_BAD_ARG); + CHK(senc2d_descriptor_get_global_segment_global_id(desc, 0, indices) + == RES_OK); + /* No duplicates and no custom id: user id is unique vertex id */ + CHK(indices[0] == 0); + /* Add valid duplicate geometry */ CHK(senc2d_descriptor_ref_put(desc) == RES_OK); desc = NULL; diff --git a/src/test_senc2d_enclosure.c b/src/test_senc2d_enclosure.c @@ -248,7 +248,7 @@ test(const int convention) CHK(senc2d_enclosure_get_segment_global_id(enclosure, s, &gid, &side) == RES_OK); /* The first unique_segment_count segments of an enclosure * are unique segments */ - if (s < header.unique_segment_count) CHK(gid == s); + if(s < header.unique_segment_count) CHK(gid == s); CHK(side == (s < header.unique_segment_count) ? SENC2D_FRONT : SENC2D_BACK); } diff --git a/src/test_senc2d_scene.c b/src/test_senc2d_scene.c @@ -180,6 +180,9 @@ main(int argc, char** argv) CHK(senc2d_scene_get_convention(scn, &convention) == RES_OK); CHK(convention == (SENC2D_CONVENTION_NORMAL_BACK | SENC2D_CONVENTION_NORMAL_INSIDE)); + /* Add the first segment twice to create a shift in numbering */ + CHK(senc2d_scene_add_geometry(scn, 1, get_indices, get_media, + nvertices, get_position, NULL, NULL, &ctx) == RES_OK); CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, nvertices, get_position, NULL, NULL, &ctx) == RES_OK); CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); @@ -188,8 +191,15 @@ main(int argc, char** argv) CHK(senc2d_enclosure_get_header(enc, &header) == RES_OK); CHK(!header.is_infinite); CHK(senc2d_enclosure_ref_put(enc) == RES_OK); - CHK(senc2d_descriptor_get_global_segment_media(desc, 0, medback) == RES_OK); + FOR_EACH(i, 0, nsegments) { + unsigned gid; + CHK(senc2d_descriptor_get_global_segment_global_id(desc, i, &gid) == RES_OK); + /* Check numbering shift */ + CHK(gid == (i ? i + 1 : 0)); + } + + CHK(senc2d_descriptor_get_global_segment_media(desc, 0, medback) == RES_OK); ctx.front_media = medium1_3; CHK(senc2d_scene_ref_put(scn) == RES_OK); CHK(senc2d_descriptor_ref_put(desc) == RES_OK); @@ -219,6 +229,9 @@ main(int argc, char** argv) CHK(senc2d_scene_create(dev, SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, &scn) == RES_OK); + /* Add the first segment twice to create a shift in numbering */ + CHK(senc2d_scene_add_geometry(scn, 1, get_indices, get_media, + nvertices, get_position, NULL, NULL, &ctx) == RES_OK); CHK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, nvertices, get_position, NULL, NULL, &ctx) == RES_OK); CHK(senc2d_scene_analyze(scn, &desc) == RES_OK); @@ -227,6 +240,14 @@ main(int argc, char** argv) CHK(senc2d_enclosure_get_header(enc, &header) == RES_OK); CHK(header.is_infinite); CHK(senc2d_enclosure_ref_put(enc) == RES_OK); + + FOR_EACH(i, 0, nsegments) { + unsigned gid; + CHK(senc2d_descriptor_get_global_segment_global_id(desc, i, &gid) == RES_OK); + /* Check numbering shift */ + CHK(gid == (i ? i + 1 : 0)); + } + CHK(senc2d_descriptor_get_global_segment_media(desc, 0, medfront) == RES_OK); FOR_EACH(i, 0, 2) CHK(medback[i] == medfront[i]); diff --git a/src/test_senc2d_undefined_medium_attr.c b/src/test_senc2d_undefined_medium_attr.c @@ -58,7 +58,7 @@ add_seg interf = merge_ctx->current_add_interf_data[iseg]; /* Keep data */ res = darray_intface_id_resize(&merge_ctx->global_interf_data, global_id + 1); - if (res != RES_OK) return res; + if(res != RES_OK) return res; darray_intface_id_data_get(&merge_ctx->global_interf_data)[global_id] = interf; return res; } @@ -79,18 +79,18 @@ merge_seg ASSERT(ctx); (void)reversed_segment; merge_ctx = ctx->custom; res = darray_intface_id_resize(&merge_ctx->global_interf_data, global_id + 1); - if (res != RES_OK) return res; + if(res != RES_OK) return res; /* Get interface information from ctx */ interf = merge_ctx->current_add_interf_data[iseg]; interf_data = darray_intface_id_data_get(&merge_ctx->global_interf_data); need_merge = (interf_data[global_id] != INVALID_INTFACE_ID); - if (need_merge) { - if (interf_data[global_id] != interf) + if(need_merge) { + if(interf_data[global_id] != interf) /* Previous interface id is different: no possible merge */ return RES_BAD_ARG; } else { - /* Triangle is known, but without interface information: create */ + /* Segment is known, but without interface information: create */ interf_data[global_id] = interf; } /* Same data: no merge needed */ @@ -147,7 +147,7 @@ test(const int convention) /* Can add the same segments again defined/undefined media in any order */ /* Add geometry with no media information on both sides */ - for (i = 0; i < sizeof(media) / sizeof(*media); i++) + for(i = 0; i < sizeof(media) / sizeof(*media); i++) media[i] = SENC2D_UNDEFINED_MEDIUM; OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, NULL, nvertices, get_position, add_seg, merge_seg, &ctx)); @@ -214,7 +214,7 @@ test(const int convention) OK(senc2d_descriptor_ref_put(desc)); /* Same geometry, front media are defined for odd segments */ - for (i = 0; i < sizeof(media) / sizeof(*media); i++) + for(i = 0; i < sizeof(media) / sizeof(*media); i++) media[i] = (i % 2) ? 0 : SENC2D_UNDEFINED_MEDIUM; OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, nvertices, get_position, add_seg, merge_seg, &ctx)); @@ -256,7 +256,7 @@ test(const int convention) OK(senc2d_descriptor_ref_put(desc)); /* Define media for remaining segments, using reversed box */ - for (i = 0; i < sizeof(media) / sizeof(*media); i++) + for(i = 0; i < sizeof(media) / sizeof(*media); i++) media[i] = (i % 2) ? SENC2D_UNDEFINED_MEDIUM : 0; OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, nvertices, get_position, add_seg, merge_seg, &ctx)); @@ -286,7 +286,7 @@ test(const int convention) OK(senc2d_descriptor_ref_put(desc)); /* Define media for all segments, nothing new here */ - for (i = 0; i < sizeof(media) / sizeof(*media); i++) + for(i = 0; i < sizeof(media) / sizeof(*media); i++) media[i] = 0; OK(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, nvertices, get_position, add_seg, merge_seg, &ctx)); @@ -294,7 +294,7 @@ test(const int convention) CHK(scount == 0); /* Define incoherent media for some segments */ - for (i = 0; i < sizeof(media) / sizeof(*media); i++) + for(i = 0; i < sizeof(media) / sizeof(*media); i++) media[i] = (i % 2); BA(senc2d_scene_add_geometry(scn, nsegments, get_indices, get_media, nvertices, get_position, add_seg, merge_seg, &ctx));