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:
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(¤t_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(¤t_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(¤t_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;
+}