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 ef4aac3409715b8d77498dc2b3c42b2a5db5b34e
parent 7fdd7d84f4467f165458d0e59cb98e9051d64a3a
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Tue, 21 Jul 2020 18:23:35 +0200

BugFix: broken enclosure whith multiple media inside

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/senc2d_scene_analyze.c | 33++++++++++++++++++++++-----------
Asrc/test_senc2d_multi_media.c | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 123 insertions(+), 11 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -155,6 +155,7 @@ if(NOT NO_TEST) new_test(test_senc2d_enclosure) new_test(test_senc2d_inconsistant_square) new_test(test_senc2d_invalid_scenes) + new_test(test_senc2d_multi_media) new_test(test_senc2d_sample_enclosure) new_test(test_senc2d_scene) new_test(test_senc2d_some_enclosures) diff --git a/src/senc2d_scene_analyze.c b/src/senc2d_scene_analyze.c @@ -215,6 +215,8 @@ extract_connex_components side_id_t max_ny_side_id; const side_id_t last_side = media_use->last; int component_canceled = 0, max_y_is_2sided = 0, fst_ny = 1; + side_id_t cc_start_side_id = SIDE_NULL__; + side_id_t cc_last_side_id = SIDE_NULL__; res_T tmp_res = RES_OK; ATOMIC id; @@ -225,25 +227,30 @@ extract_connex_components ASSERT(darray_side_id_size_get(&stack) == 0); ASSERT(darray_side_id_size_get(&current_component) == 0); for(;;) { /* Process all components for this medium */ - const side_id_t start_side_id = get_side_not_in_connex_component + side_id_t crt_side_id = get_side_not_in_connex_component (last_side, segsides, processed, &first_side_not_in_component, medium); - side_id_t crt_side_id = start_side_id; - side_id_t last_side_id = start_side_id; vrtx_id_t max_y_vrtx_id = VRTX_NULL__; struct cc_descriptor *cc; double max_y = -DBL_MAX; component_canceled = 0; - ASSERT(start_side_id == SIDE_NULL__ || start_side_id < 2 * scn->nsegs); + ASSERT(crt_side_id == SIDE_NULL__ || crt_side_id < 2 * scn->nsegs); darray_side_id_clear(&current_component); if(*p_res != RES_OK) break; - if(start_side_id == SIDE_NULL__) + if(crt_side_id == SIDE_NULL__) break; /* start_side_id=SIDE_NULL__ => component done! */ + if(cc_start_side_id == SIDE_NULL__) { + cc_start_side_id = cc_last_side_id = crt_side_id; + } else { + cc_start_side_id = MMIN(cc_start_side_id, crt_side_id); + cc_last_side_id = MMAX(cc_last_side_id, crt_side_id); + } + #ifndef NDEBUG { - seg_id_t sid = SEGSIDE_2_SEG(start_side_id); - enum senc2d_side s = SEGSIDE_2_SIDE(start_side_id); + seg_id_t sid = SEGSIDE_2_SEG(crt_side_id); + enum senc2d_side s = SEGSIDE_2_SIDE(crt_side_id); medium_id_t side_med = darray_segment_in_data_get(&scn->segments_in)[sid].medium[s]; ASSERT(side_med == medium); @@ -351,7 +358,8 @@ extract_connex_components if(sz == 0) break; /* Empty stack => component is done! */ crt_side_id = darray_side_id_cdata_get(&stack)[sz - 1]; darray_side_id_pop_back(&stack); - last_side_id = MMAX(last_side_id, crt_side_id); + cc_start_side_id = MMIN(cc_start_side_id, crt_side_id); + cc_last_side_id = MMAX(cc_last_side_id, crt_side_id); } canceled: if(component_canceled) continue; @@ -361,7 +369,6 @@ extract_connex_components if(!cc) *p_res = RES_MEM_ERR; if(*p_res != RES_OK) break; - ASSERT(medium == segsides[start_side_id].medium); ASSERT(max_y_vrtx_id != VRTX_NULL__); cc_descriptor_init(alloc, cc); id = ATOMIC_INCR(component_count) - 1; @@ -370,14 +377,18 @@ extract_connex_components sz = darray_side_id_size_get(&current_component); ASSERT(sz > 0 && sz <= SIDE_MAX__); cc->side_count = (side_id_t)sz; - cc->side_range.first = start_side_id; - cc->side_range.last = last_side_id; + cc->side_range.first = cc_start_side_id; + cc->side_range.last = cc_last_side_id; cc->max_y_vrtx_id = max_y_vrtx_id; /* Tranfer ownership of the array to component */ ASSERT(!cc->media && current_media); cc->media = current_media; current_media = NULL; + /* Reset for next component */ + cc_start_side_id = SIDE_NULL__; + cc_last_side_id = SIDE_NULL__; + /* Write component membership in the global structure * No need for sync here as an unique thread writes a given side */ {STATIC_ASSERT(sizeof(cc->cc_id) >= 4, Cannot_write_IDs_sync_free);} diff --git a/src/test_senc2d_multi_media.c b/src/test_senc2d_multi_media.c @@ -0,0 +1,100 @@ +/* Copyright (C) |Meso|Star> 2016-2020 (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + /* This test has been created using the sg3_geometry_dump_as_C_code feature + * of star-geometry. It uses output from test_sg3_cube_on_cube. */ + +#define _POSIX_C_SOURCE 200112L /* snprintf */ + +#include "senc2d.h" +#include "test_senc2d_utils.h" + +#include <rsys/double2.h> + +#include <stdio.h> + +static const unsigned multi_media_vertices_count = 4; +static const double multi_media_vertices[8] = +{ + 0, 0, + 1, 0, + 0, 1, + 1, 1 +}; +static const unsigned multi_media_segments_count = 4; +static const unsigned multi_media_segments[8] = +{ + 0, 2, + 2, 3, + 3, 1, + 1, 0 +}; +static const unsigned multi_media_properties[12] = +{ + 0, 4, 4, + 0, 3, 3, + 0, 2, 2, + 0, 1, 1 +}; + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct senc2d_device* dev = NULL; + struct senc2d_scene* scn = NULL; + struct context ctx = CONTEXT_NULL__; + unsigned ecount, scount, s, e; + struct senc2d_enclosure* enc; + (void)argc, (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(senc2d_device_create(NULL, &allocator, SENC2D_NTHREADS_DEFAULT, 1, &dev)); + + /* Degenerated triangle: duplicated vertex */ + ctx.positions = multi_media_vertices; + ctx.indices = multi_media_segments; + ctx.properties = multi_media_properties; + OK(senc2d_scene_create(dev, + SENC2D_CONVENTION_NORMAL_FRONT | SENC2D_CONVENTION_NORMAL_INSIDE, + multi_media_segments_count, get_indices, get_media_from_properties, + multi_media_vertices_count, get_position, &ctx, &scn)); + + OK(senc2d_scene_get_segments_count(scn, &scount)); + CHK(scount == multi_media_segments_count); + FOR_EACH(s, 0, scount) { + unsigned ids[2]; + OK(senc2d_scene_get_segment_enclosures(scn, s, ids)); + CHK(ids[0] == 0 && ids[1] == 1); + } + OK(senc2d_scene_get_enclosure_count(scn, &ecount)); + CHK(ecount == 2); + FOR_EACH(e, 0, ecount) { + struct senc2d_enclosure_header header; + OK(senc2d_scene_get_enclosure(scn, e, &enc)); + OK(senc2d_enclosure_get_header(enc, &header)); + CHK(header.primitives_count == multi_media_segments_count); + CHK(header.enclosed_media_count == (header.is_infinite ? 1u : 4u)); + OK(senc2d_enclosure_ref_put(enc)); + } + + OK(senc2d_scene_ref_put(scn)); + OK(senc2d_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +}