commit e28310d88d073315b3a6352c7c31c1df4c05e110
parent 55496e24f8a6e32635c3d177a4e54e0d04605f0f
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 25 Nov 2022 16:29:51 +0100
Another try at geometry partition
Diffstat:
| M | src/scad.h | | | 28 | ++++++++++++++-------------- |
| M | src/scad_geometry.c | | | 208 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
2 files changed, 119 insertions(+), 117 deletions(-)
diff --git a/src/scad.h b/src/scad.h
@@ -182,7 +182,7 @@ SCAD_API res_T
scad_add_polygon
(const char* name, /* Can be NULL */
void (*get_position)(const size_t ivert, double pos[2], void* data),
- void* data, /* Custom data */
+ void* data, /* Custom data; can be NULL if get_position don't use it */
const double z,
const size_t count, /* size of x and y arrays */
struct scad_geometry** polygon); /* Can be NULL: no handler returned. */
@@ -216,10 +216,6 @@ scad_add_sphere
const double radius,
struct scad_geometry** sphere); /* Can be NULL: no handler returned. */
-SCAD_API res_T
-scad_scene_mesh
- (void);
-
/* Compute the boolean union (the fusion) of the geometries in `geometries' and
* `tools'. */
SCAD_API res_T
@@ -265,21 +261,25 @@ scad_geometries_common_boundaries
struct scad_geometry** out_geometry);
/* Compute the boolean fragments (general fuse) resulting from the
- * intersection of every single geometry in `geometries' and the
- * other geometries in `geometries' used as tools, making all interfaces
+ * intersection of the geometries in `geometries', making all interfaces
* conformal.
- * Geometries are considered one at a time against the other ones, producing one
- * output by geometry in `geometries'.
+ * If overlapping is allowed `out_geometries' is constructed and the new
+ * geometries are created unnamed; if overlapping is not allowed
+ * `out_geometries' is expected to be NULL.
* When applied to geometries of different dimensions, the lower dimensional
* geometries will be automatically embedded in the higher dimensional
* geometries if they are not on their boundary. */
SCAD_API res_T
scad_geometries_partition
- (char** names, /* Can be NULL */
- struct scad_geometry** geometries,
+ (struct scad_geometry** geometries,
const size_t geometries_count,
const int allow_overlapping,
- struct scad_geometry** out_geometries);
+ struct scad_geometry** out_geometries); /* NULL if overlapping not allowed */
+
+/* Same as above for the whole scene */
+SCAD_API res_T
+scad_scene_partition
+ (void);
SCAD_API res_T
scad_fragment_geometries
@@ -378,8 +378,8 @@ SCAD_API res_T /* FIXME remove this */
scad_run_ui
(void);
-SCAD_API res_T /* FIXME TEMPORARY */
-scad_scene_partition
+SCAD_API res_T
+scad_scene_mesh
(void);
SCAD_API res_T
diff --git a/src/scad_geometry.c b/src/scad_geometry.c
@@ -141,7 +141,6 @@ static res_T
gather_tags
(struct scad_geometry** geometries,
const size_t geometries_count,
- const size_t except, /* if not SIZE_MAX, this one is not gathered */
int** out_dimTags,
size_t* out_dimTags_n)
{
@@ -154,7 +153,6 @@ gather_tags
struct htable_tags_iterator it, end;
ASSERT((geometries || !geometries_count) && (out_dimTags || !out_dimTags_n));
- ASSERT(except == SIZE_MAX || except < geometries_count);
allocator = dev->allocator;
htable_tags_init(allocator, &t2);
@@ -162,7 +160,6 @@ gather_tags
/* list tags and remove duplicates */
for(i = 0; i < geometries_count; i++) {
- if(i == except) continue;
for(j = 0; j < geometries[i]->gmsh_dimTags_n; j += 2) {
char one = 1;
int dim = geometries[i]->gmsh_dimTags[j];
@@ -345,7 +342,7 @@ scad_geometry_get_mass
ASSERT(geom->gmsh_dimTags_n % 2 == 0);
count = geom->gmsh_dimTags_n / 2;
- ERR(gather_tags(&geom, 1, SIZE_MAX, &data, &sz));
+ ERR(gather_tags(&geom, 1, &data, &sz));
dim = data[0];
*mass = 0;
@@ -385,9 +382,9 @@ scad_geometry_get_centerofmass
*center_n = geom->gmsh_dimTags_n / 2;
*center = (double*)malloc(*center_n * 3 * sizeof(double));
-
- ERR(gather_tags(&geom, 1, SIZE_MAX, &data, &sz));
-
+
+ ERR(gather_tags(&geom, 1, &data, &sz));
+
for (i=0; i<*center_n; ++i) {
double x, y, z;
int ierr = 0;
@@ -746,8 +743,8 @@ scad_fuse_geometries
ERR(scad_synchronize());
}
- ERR(gather_tags(geometries, geometries_count, SIZE_MAX, &data1, &sz1));
- ERR(gather_tags(tools, tools_count, SIZE_MAX, &data2, &sz2));
+ ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
+ ERR(gather_tags(tools, tools_count, &data2, &sz2));
/* We don't remove gmsh objects here; they are only removed when their tags are
* no longuer used by any star-cad geometry */
@@ -810,8 +807,8 @@ scad_cut_geometries
ERR(scad_synchronize());
}
- ERR(gather_tags(geometries, geometries_count, SIZE_MAX, &data1, &sz1));
- ERR(gather_tags(tools, tools_count, SIZE_MAX, &data2, &sz2));
+ ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
+ ERR(gather_tags(tools, tools_count, &data2, &sz2));
/* We don't remove gmsh objects here; they are only removed when their tags are
* no longuer used by any star-cad geometry */
@@ -874,8 +871,8 @@ scad_intersect_geometries
ERR(scad_synchronize());
}
- ERR(gather_tags(geometries, geometries_count, SIZE_MAX, &data1, &sz1));
- ERR(gather_tags(tools, tools_count, SIZE_MAX, &data2, &sz2));
+ ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
+ ERR(gather_tags(tools, tools_count, &data2, &sz2));
/* We don't remove gmsh objects here; they are only removed when their tags are
* no longuer used by any star-cad geometry */
@@ -941,8 +938,8 @@ scad_geometries_common_boundaries
ERR(scad_synchronize());
}
- ERR(gather_tags(geometries, geometries_count, SIZE_MAX, &data1, &sz1));
- ERR(gather_tags(tools, tools_count, SIZE_MAX, &data2, &sz2));
+ ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
+ ERR(gather_tags(tools, tools_count, &data2, &sz2));
/* We don't remove gmsh objects here; they are only removed when their tags are
* no longuer used by any star-cad geometry */
@@ -1267,8 +1264,7 @@ error:
res_T
scad_geometries_partition
- (char** names, /* Can be NULL */
- struct scad_geometry** geometries,
+ (struct scad_geometry** geometries,
const size_t geometries_count,
const int allow_overlapping,
struct scad_geometry** out_geometries)
@@ -1284,33 +1280,36 @@ scad_geometries_partition
struct scad_geometry** geoms = NULL;
struct htable_mappings m2, m3;
int hm_initialized = 0;
- struct mem_allocator* allocator;
struct scad_device* dev = get_device();
struct htable_tags t2, t3;
struct htable_tags_iterator it, end;
int ht_initialized = 0;
- if(!geometries || !geometries_count || !out_geometries) {
+ if(!geometries || !geometries_count || (allow_overlapping && !out_geometries)) {
res = RES_BAD_ARG;
goto error;
}
- allocator = dev->allocator;
ERR(check_device(FUNC_NAME));
if(get_device()->need_synchro) {
ERR(scad_synchronize());
}
- ERR(gather_tags(geometries, geometries_count, SIZE_MAX, &data, &sz));
+ ERR(gather_tags(geometries, geometries_count, &data, &sz));
- /* We don't remove gmsh objects here; they are only removed when their tags
- * are no longuer used by any star-cad geometry */
+ /* As a general principle, we don't remove gmsh objects directly; they are
+ * only removed from scad_geometry_delete when their tags are no longuer used
+ * by any star-cad geometry.
+ * Here we can safely use the remove flag in the non-overlapping case, as
+ * this ends in the same tags being reused for output. */
gmshModelOccFragment(data, sz, NULL, 0, &tagout, &tagoutn, &map, &mapn,
- &mapnn, -1, 0, 0, &ierr);
+ &mapnn, -1, (allow_overlapping == 0), 0, &ierr);
ERR(gmsh_err_to_res_T(ierr));
ASSERT(sz == 2*mapnn); /* Because input tags where deduplicated */
- /* Check first if there is an overlapping problem */
+ get_device()->need_synchro = 1;
+
+ /* Check first if there was an overlapping problem */
if(!allow_overlapping) {
/* No overlapping means that each tag in geometries is translated into a
* single tag in map */
@@ -1325,92 +1324,95 @@ scad_geometries_partition
str_cget(&geometries[i]->name));
}
}
+ /* Additionally, with the delete flag ON we expect the tags to remain
+ * unchanged in the non-overlapping case. */
+ /*ASSERT(res != RES_OK || map[i][1] == data[2*i+1]);*/
}
if(ucount) {
log_error(get_device(), "%lu unamed overlapping geometries.\n", ucount);
}
if(res != RES_OK) goto error;
- }
-
- /* Create htables of mappings to ease access */
- htable_mappings_init(allocator, &m2);
- htable_mappings_init(allocator, &m3);
- hm_initialized = 1;
- for(i = 0; i < sz; i += 2) {
- int dim = data[i];
- int tag = data[i+1];
- size_t mapping = i/2;
- struct htable_mappings* mn = (dim == 2) ? &m2 : &m3;
- ASSERT(dim == 2 || dim == 3);
- ERR(htable_mappings_set(mn, &tag, &mapping));
- }
-
- /* Create output geometries from mapping */
- geoms = calloc(geometries_count, sizeof(*geoms));
- if(!geoms) {
- res = RES_MEM_ERR;
- goto error;
- }
- htable_tags_init(allocator, &t2);
- htable_tags_init(allocator, &t3);
- ht_initialized = 1;
- for(i = 0; i < geometries_count; i++) {
- const char* name = names ? names[i] : NULL;
- struct scad_geometry* geom = geometries[i];
- size_t c, n, j;
- int* dt = NULL;
- /* For each tag in geometries[i] out_geometries[i] includes the mapped tags.
- * The resulting tags need to be deduplicated though. */
- htable_tags_clear(&t2);
- htable_tags_clear(&t3);
- for(j = 0; j < geom->gmsh_dimTags_n; j += 2) {
- int dim = geom->gmsh_dimTags[j];
- int tag = geom->gmsh_dimTags[j+1];
+ } else {
+ struct mem_allocator* allocator = dev->allocator;
+ /* Create htables of mappings to ease access */
+ htable_mappings_init(allocator, &m2);
+ htable_mappings_init(allocator, &m3);
+ hm_initialized = 1;
+ for(i = 0; i < sz; i += 2) {
+ int dim = data[i];
+ int tag = data[i+1];
+ size_t mapping = i/2;
struct htable_mappings* mn = (dim == 2) ? &m2 : &m3;
- size_t k;
- size_t* mapping = htable_mappings_find(mn, &tag);
ASSERT(dim == 2 || dim == 3);
- ASSERT(mapping && *mapping < mapnn);
- for(k = 0; k < mapn[*mapping]; k += 2) {
- char one = 1;
- int d = map[*mapping][k];
- int t = map[*mapping][k+1];
- struct htable_tags* tn = (d == 2) ? &t2 : &t3;
- ERR(htable_tags_set(tn, &t, &one));
- }
+ ERR(htable_mappings_set(mn, &tag, &mapping));
}
- /* Allocate result */
- n = htable_tags_size_get(&t2) + htable_tags_size_get(&t3);
- dt = malloc(sizeof(*dt) * 2 * n);
- if(!dt) {
+
+ /* Create output geometries from mapping */
+ geoms = calloc(geometries_count, sizeof(*geoms));
+ if(!geoms) {
res = RES_MEM_ERR;
goto error;
}
- /* Copy tags */
- c = 0;
- htable_tags_begin(&t2, &it);
- htable_tags_end(&t2, &end);
- while(!htable_tags_iterator_eq(&it, &end)) {
- dt[c++] = 2;
- dt[c++] = *htable_tags_iterator_key_get(&it);
- htable_tags_iterator_next(&it);
- }
- htable_tags_begin(&t3, &it);
- htable_tags_end(&t3, &end);
- while(!htable_tags_iterator_eq(&it, &end)) {
- dt[c++] = 3;
- dt[c++] = *htable_tags_iterator_key_get(&it);
- htable_tags_iterator_next(&it);
- }
- ASSERT(c == 2*n);
+ htable_tags_init(allocator, &t2);
+ htable_tags_init(allocator, &t3);
+ ht_initialized = 1;
+ for(i = 0; i < geometries_count; i++) {
+ struct scad_geometry* geom = geometries[i];
+ size_t c, n, j;
+ int* dt = NULL;
+ /* For each tag in geometries[i] out_geometries[i] includes the mapped tags.
+ * The resulting tags need to be deduplicated though. */
+ htable_tags_clear(&t2);
+ htable_tags_clear(&t3);
+ for(j = 0; j < geom->gmsh_dimTags_n; j += 2) {
+ int dim = geom->gmsh_dimTags[j];
+ int tag = geom->gmsh_dimTags[j+1];
+ struct htable_mappings* mn = (dim == 2) ? &m2 : &m3;
+ size_t k;
+ size_t* mapping = htable_mappings_find(mn, &tag);
+ ASSERT(dim == 2 || dim == 3);
+ ASSERT(mapping && *mapping < mapnn);
+ for(k = 0; k < mapn[*mapping]; k += 2) {
+ char one = 1;
+ int d = map[*mapping][k];
+ int t = map[*mapping][k+1];
+ struct htable_tags* tn = (d == 2) ? &t2 : &t3;
+ ERR(htable_tags_set(tn, &t, &one));
+ }
+ }
+ /* Allocate result */
+ n = htable_tags_size_get(&t2) + htable_tags_size_get(&t3);
+ dt = malloc(sizeof(*dt) * 2 * n);
+ if(!dt) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ /* Copy tags */
+ c = 0;
+ htable_tags_begin(&t2, &it);
+ htable_tags_end(&t2, &end);
+ while(!htable_tags_iterator_eq(&it, &end)) {
+ dt[c++] = 2;
+ dt[c++] = *htable_tags_iterator_key_get(&it);
+ htable_tags_iterator_next(&it);
+ }
+ htable_tags_begin(&t3, &it);
+ htable_tags_end(&t3, &end);
+ while(!htable_tags_iterator_eq(&it, &end)) {
+ dt[c++] = 3;
+ dt[c++] = *htable_tags_iterator_key_get(&it);
+ htable_tags_iterator_next(&it);
+ }
+ ASSERT(c == 2*n);
- /* Create geometry */
- ERR(scad_geometry_create(name, geoms+i));
- geoms[i]->gmsh_dimTags_n = c;
- geoms[i]->gmsh_dimTags = dt;
- ERR(device_register_tags(geoms[i]));
+ /* Create geometry */
+ ERR(scad_geometry_create(NULL, geoms+i));
+ geoms[i]->gmsh_dimTags_n = c;
+ geoms[i]->gmsh_dimTags = dt;
+ ERR(device_register_tags(geoms[i]));
+ }
+ memcpy(out_geometries, geoms, geometries_count * sizeof(*geoms));
}
- memcpy(out_geometries, geoms, geometries_count * sizeof(*geoms));
exit:
for(i = 0; i < mapnn; i++) free(map[i]);
@@ -1468,8 +1470,8 @@ scad_fragment_geometries
ERR(scad_synchronize());
}
- ERR(gather_tags(geometries, geometries_count, SIZE_MAX, &data1, &sz1));
- ERR(gather_tags(tools, tools_count, SIZE_MAX, &data2, &sz2));
+ ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
+ ERR(gather_tags(tools, tools_count, &data2, &sz2));
/* We don't remove gmsh objects here; they are only removed when their tags are
* no longuer used by any star-cad geometry */
@@ -1528,7 +1530,7 @@ scad_geometry_boundary
ERR(scad_synchronize());
}
- ERR(gather_tags(geometries, geometries_count, SIZE_MAX, &data, &sz));
+ ERR(gather_tags(geometries, geometries_count, &data, &sz));
gmshModelGetBoundary(data, sz, &tagout, &tagoutn, 1, 0, 0, &ierr);
ERR(gmsh_err_to_res_T(ierr));
@@ -1661,7 +1663,7 @@ scad_geometry_normal
goto error;
}
- ERR(gather_tags(&surface, 1, SIZE_MAX, &data, &sz));
+ ERR(gather_tags(&surface, 1, &data, &sz));
for (i=0; sz/2; ++i) {
double* coord;
@@ -1728,7 +1730,7 @@ scad_geometry_dilate
ERR(check_device(FUNC_NAME));
- ERR(gather_tags(&geom, 1, SIZE_MAX, &data, &sz));
+ ERR(gather_tags(&geom, 1, &data, &sz));
gmshModelOccDilate(data, sz, SPLIT3(center), SPLIT3(scale), &ierr);
ERR(gmsh_err_to_res_T(ierr));