city_generator2

Generated conformal 3D meshes representing a city
git clone git://git.meso-star.fr/city_generator2.git
Log | Files | Refs | README | LICENSE

commit 9e8f1afac3d9e6120f59ce07e4853224f950efc1
parent f01864cac4e5947885dc199339cef5a98adbf816
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed, 11 Jan 2023 17:41:32 +0100

Improve memory management

Stop using default allocator and fix memory leaks

Diffstat:
Msrc/cg_constructive_mode_1.c | 241++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/cg_constructive_mode_1.h | 9+++++++--
2 files changed, 161 insertions(+), 89 deletions(-)

diff --git a/src/cg_constructive_mode_1.c b/src/cg_constructive_mode_1.c @@ -26,7 +26,6 @@ #include <rsys/str.h> #include <rsys/logger.h> -#include <rsys/stretchy_array.h> #include <star/scad.h> #include <star/scpr.h> @@ -424,6 +423,7 @@ build_inter_floor struct scpr_polygon* pg_int = NULL; size_t nverts = 0; struct scad_geometry** floor_list = NULL; + struct darray_geometries floor_array; double d[3] = {0, 0, 0}; char* floorname = NULL; struct str name; @@ -431,6 +431,8 @@ build_inter_floor ASSERT(allocator && pg && data && inter_floor); + darray_geometries_init(allocator, &floor_array); + if (prefix) { str_init(allocator, &name); is_init = 1; @@ -454,25 +456,25 @@ build_inter_floor ERR(scad_add_polygon( NULL, get_position_pg, pg_int, z_floor, nverts, &footprint)); ERR(scad_geometry_extrude(footprint, NULL, d, &floor)); - sa_push(floor_list, floor); + ERR(darray_geometries_push_back(&floor_array, &floor)); ERR(scad_geometry_delete(footprint)); z_floor += h_cavity/(double)(1 + floor_n) + e_floor; } + ASSERT(darray_geometries_size_get(&floor_array) == floor_n); - ERR(scad_fuse_geometries( - floorname, - floor_list, sa_size(floor_list), - floor_list, sa_size(floor_list), - inter_floor)); + floor_list = darray_geometries_data_get(&floor_array); + ERR(scad_fuse_geometries(floorname, floor_list, floor_n, floor_list, floor_n, + inter_floor)); exit: if (is_init) str_release(&name); if (pg_int) SCPR(polygon_ref_put(pg_int)); - if (floor_list) { + floor_list = darray_geometries_data_get(&floor_array); + if(floor_list) { for (i = 0; i < floor_n; i++) { SCAD(geometry_delete(floor_list[i])); } - sa_release(floor_list); + darray_geometries_release(&floor_array); } return res; error: @@ -736,17 +738,22 @@ build_windows struct scad_geometry* surface = NULL; struct scad_geometry* hole = NULL; struct scad_geometry** hole_list = NULL; + struct darray_geometries hole_array; struct scad_geometry* geom = NULL; struct scad_geometry* bcavity = NULL; struct scad_geometry** list = NULL; struct scad_geometry* glass = NULL; struct scad_geometry** glass_list = NULL; - size_t list_n = 0; + struct darray_geometries glass_array; + size_t list_n = 0, array_n; struct str gname; int is_init = 0; ASSERT(allocator && data && data_cad); + darray_geometries_init(allocator, &hole_array); + darray_geometries_init(allocator, &glass_array); + scale[0] = sqrt(data->glass_ratio); scale[1] = scale[0]; scale[2] = scale[0]; @@ -756,10 +763,12 @@ build_windows ERR(scad_geometry_explode(bcavity, NULL, &list, &list_n)); for (i = 0; i < list_n; i++) { - double* center = NULL; - size_t center_n = 0; + double center[3]; + size_t center_n; - ERR(scad_geometry_get_centerofmass(list[i], &center, &center_n)); + ERR(scad_geometry_get_count(list[i], &center_n)); + ASSERT(center_n == 1); + ERR(scad_geometry_get_centerofmass(list[i], center)); ERR(scad_geometry_normal(list[i], center, N, NULL, &surface)); @@ -778,21 +787,27 @@ build_windows dir[2] = 1.1*N[2] * (data->wall_thickness + data->internal_insulation_thickness + data->external_insulation_thickness); ERR(scad_geometry_extrude(surface, NULL, dir, &hole)); - sa_push(hole_list, hole); + ERR(darray_geometries_push_back(&hole_array, &hole)); dir[0] = N[0] * 0.024; dir[1] = N[1] * 0.024; dir[2] = N[2] * 0.024; ERR(scad_geometry_extrude(surface, NULL, dir, &glass)); - sa_push(glass_list, glass); + ERR(darray_geometries_push_back(&glass_array, &glass)); ERR(scad_geometry_delete(surface)); surface = NULL; } + ASSERT(darray_geometries_size_get(&hole_array) + == darray_geometries_size_get(&glass_array)); + + hole_list = darray_geometries_data_get(&hole_array); + glass_list = darray_geometries_data_get(&glass_array); + array_n = darray_geometries_size_get(&hole_array); /* wall perforation */ ERR(scad_cut_geometries(NULL, &data_cad->wall, 1, - hole_list, sa_size(hole_list), &geom)); + hole_list, array_n, &geom)); ERR(scad_geometry_swap_names(data_cad->wall, geom)); ERR(scad_geometry_delete(data_cad->wall)); data_cad->wall = geom; @@ -801,7 +816,7 @@ build_windows /* internal insulation perforation */ if (data_cad->internal_insulation) { ERR(scad_cut_geometries(NULL, &data_cad->internal_insulation, 1, - hole_list, sa_size(hole_list), &geom)); + hole_list, array_n, &geom)); ERR(scad_geometry_swap_names(data_cad->internal_insulation, geom)); ERR(scad_geometry_delete(data_cad->internal_insulation)); data_cad->internal_insulation = geom; @@ -811,7 +826,7 @@ build_windows /* external insulation perforation */ if (data_cad->external_insulation) { ERR(scad_cut_geometries(NULL, &data_cad->external_insulation, 1, - hole_list, sa_size(hole_list), &geom)); + hole_list, array_n, &geom)); ERR(scad_geometry_swap_names(data_cad->external_insulation, geom)); ERR(scad_geometry_delete(data_cad->external_insulation)); data_cad->external_insulation = geom; @@ -827,20 +842,23 @@ build_windows } ERR(scad_fuse_geometries(str_cget(&gname), glass_list, 1, - glass_list+1, sa_size(glass_list) - 1, &data_cad->glass)); + glass_list+1, array_n - 1, &data_cad->glass)); exit: + glass_list = darray_geometries_data_get(&glass_array); for (i = 0 ; i < list_n; i++) { SCAD(geometry_delete(list[i])); } - for (i = 0 ; i < sa_size(hole_list); i++) { - SCAD(geometry_delete(hole_list[i])); + for (i = 0 ; i < darray_geometries_size_get(&hole_array); i++) { + struct scad_geometry* h = darray_geometries_data_get(&hole_array)[i]; + SCAD(geometry_delete(h)); } - for (i = 0 ; i < sa_size(glass_list); i++) { - SCAD(geometry_delete(glass_list[i])); + for (i = 0 ; i <darray_geometries_size_get(&glass_array); i++) { + struct scad_geometry* g = darray_geometries_data_get(&glass_array)[i]; + SCAD(geometry_delete(g)); } - if (hole_list) sa_release(hole_list); - if (glass_list) sa_release(glass_list); + darray_geometries_release(&hole_array); + darray_geometries_release(&glass_array); if (surface) SCAD(geometry_delete(surface)); if (geom) SCAD(geometry_delete(geom)); if (bcavity) SCAD(geometry_delete(bcavity)); @@ -856,10 +874,13 @@ build_boundary (const char* prefix, struct mem_allocator* allocator, struct data_cad_cmode_1* data_cad, - struct scad_geometry*** boundary) + struct darray_geometries* boundary) { res_T res = RES_OK; + size_t count; + struct darray_geometries array; struct scad_geometry** list = NULL; + struct darray_geometries bound_array; struct scad_geometry* bound = NULL; char* boundaryname = NULL; struct str name; @@ -867,71 +888,90 @@ build_boundary ASSERT(allocator && prefix && data_cad && boundary); + darray_geometries_init(allocator, &array); + darray_geometries_init(allocator, &bound_array); + str_init(allocator, &name); is_init = 1; - sa_push(list, data_cad->wall); - sa_push(list, data_cad->roof); - sa_push(list, data_cad->floor); - sa_push(list, data_cad->habitable_cavity); - sa_push(list, data_cad->fake_ground); - if (data_cad->foundation) sa_push(list, data_cad->foundation); - if (data_cad->intermediate_floor) sa_push(list, data_cad->intermediate_floor); - if (data_cad->external_insulation) sa_push(list, data_cad->external_insulation); - if (data_cad->internal_insulation) sa_push(list, data_cad->internal_insulation); - if (data_cad->roof_insulation) sa_push(list, data_cad->roof_insulation); - if (data_cad->floor_insulation) sa_push(list, data_cad->floor_insulation); - if (data_cad->attic_cavity) sa_push(list, data_cad->attic_cavity); - if (data_cad->crawlspace_cavity) sa_push(list, data_cad->crawlspace_cavity); - if (data_cad->glass) sa_push(list, data_cad->glass); - + /* Ensure enough room for all geometries without error nor mem move */ + ERR(darray_geometries_reserve(&array, 14)); + darray_geometries_push_back(&array, &data_cad->wall); + darray_geometries_push_back(&array, &data_cad->roof); + darray_geometries_push_back(&array, &data_cad->floor); + darray_geometries_push_back(&array, &data_cad->habitable_cavity); + darray_geometries_push_back(&array, &data_cad->fake_ground); + if (data_cad->foundation) + darray_geometries_push_back(&array, &data_cad->foundation); + if (data_cad->intermediate_floor) + darray_geometries_push_back(&array, &data_cad->intermediate_floor); + if (data_cad->external_insulation) + darray_geometries_push_back(&array, &data_cad->external_insulation); + if (data_cad->internal_insulation) + darray_geometries_push_back(&array, &data_cad->internal_insulation); + if (data_cad->roof_insulation) + darray_geometries_push_back(&array, &data_cad->roof_insulation); + if (data_cad->floor_insulation) + darray_geometries_push_back(&array, &data_cad->floor_insulation); + if (data_cad->attic_cavity) + darray_geometries_push_back(&array, &data_cad->attic_cavity); + if (data_cad->crawlspace_cavity) + darray_geometries_push_back(&array, &data_cad->crawlspace_cavity); + if (data_cad->glass) + darray_geometries_push_back(&array, &data_cad->glass); + + count = darray_geometries_size_get(&array); + list = darray_geometries_data_get(&array); + + /* Ensure enough room for all geometries without error nor mem move */ + ERR(darray_geometries_reserve(boundary, 5+darray_geometries_size_get(boundary))); ERR(str_set(&name, prefix)); ERR(str_append(&name, "_boundary_wall")); boundaryname = str_get(&name); - ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list), + ERR(scad_geometries_common_boundaries(boundaryname, list, count, &data_cad->wall, 1, &bound)); - sa_push(*boundary, bound); + darray_geometries_push_back(boundary, &bound); ERR(str_set(&name, prefix)); ERR(str_append(&name, "_boundary_roof")); boundaryname = str_get(&name); - ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list), + ERR(scad_geometries_common_boundaries(boundaryname, list, count, &data_cad->roof, 1, &bound)); - sa_push(*boundary, bound); + darray_geometries_push_back(boundary, &bound); if (data_cad->glass) { ERR(str_set(&name, prefix)); ERR(str_append(&name, "_boundary_glass")); boundaryname = str_get(&name); - ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list), + ERR(scad_geometries_common_boundaries(boundaryname, list, count, &data_cad->glass, 1, &bound)); - sa_push(*boundary, bound); + darray_geometries_push_back(boundary, &bound); } if (data_cad->external_insulation) { ERR(str_set(&name, prefix)); ERR(str_append(&name, "_boundary_ext_insulation")); boundaryname = str_get(&name); - ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list), + ERR(scad_geometries_common_boundaries(boundaryname, list, count, &data_cad->external_insulation, 1, &bound)); - sa_push(*boundary, bound); + darray_geometries_push_back(boundary, &bound); } if (data_cad->internal_insulation) { - size_t count = 0; + size_t bcount = 0; ERR(str_set(&name, prefix)); ERR(str_append(&name, "_boundary_int_insulation")); boundaryname = str_get(&name); - ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list), + ERR(scad_geometries_common_boundaries(boundaryname, list, count, &data_cad->internal_insulation, 1, &bound)); - ERR(scad_geometry_get_count(bound, &count)); - if (count>0) sa_push(*boundary, bound); + ERR(scad_geometry_get_count(bound, &bcount)); + if (bcount>0) darray_geometries_push_back(boundary, &bound); } exit: if (is_init) str_release(&name); - if (list) sa_release(list); + darray_geometries_release(&array); return res; error: goto exit; @@ -942,7 +982,7 @@ build_connection (const char* prefix, struct mem_allocator* allocator, struct data_cad_cmode_1* data_cad, - struct scad_geometry*** connection) + struct darray_geometries* connection) { res_T res = RES_OK; struct scad_geometry* connect = NULL; @@ -965,7 +1005,7 @@ build_connection &data_cad->G2, 1,\ &connect));\ ERR(scad_geometry_get_count(connect, &count)); \ - if (count>0) sa_push(*connection, connect); + if (count>0) { ERR(darray_geometries_push_back(connection, &connect)); } /* -------------------------------------------------------------------------*/ @@ -1063,7 +1103,8 @@ error: static res_T build_fake_ground - (struct data_cad_cmode_1* cad, + (struct mem_allocator* allocator, + struct data_cad_cmode_1* cad, struct scpr_polygon* pg, const double depth, struct scad_geometry** ground) @@ -1071,16 +1112,26 @@ build_fake_ground res_T res = RES_OK; double dir[3] = {0, 0, 0}; struct scpr_polygon* pg_offset = NULL; + size_t count; + struct darray_geometries array; struct scad_geometry** list = NULL; struct scad_geometry* footprint = NULL; struct scad_geometry* geom = NULL; ASSERT(cad && pg && ground ); - if (cad->foundation) sa_push(list, cad->foundation); - if (cad->crawlspace_cavity) sa_push(list, cad->crawlspace_cavity); - if (cad->floor) sa_push(list, cad->floor); - if (cad->floor_insulation) sa_push(list, cad->floor_insulation); + darray_geometries_init(allocator, &array); + + /* Ensure enough room for all geometries without error nor mem move */ + ERR(darray_geometries_reserve(&array, 4)); + if (cad->foundation) darray_geometries_push_back(&array, &cad->foundation); + if (cad->crawlspace_cavity) darray_geometries_push_back(&array, &cad->crawlspace_cavity); + if (cad->floor) darray_geometries_push_back(&array, &cad->floor); + if (cad->floor_insulation) + darray_geometries_push_back(&array, &cad->floor_insulation); + + count = darray_geometries_size_get(&array); + list = darray_geometries_data_get(&array); ERR(scpr_polygon_create_copy(NULL, pg, &pg_offset)); ERR(scpr_offset_polygon(pg_offset, 0.1, SCPR_JOIN_MITER)); @@ -1090,11 +1141,11 @@ build_fake_ground dir[2] = -depth*1.1; ERR(scad_geometry_extrude(footprint, NULL, dir, &geom)); - ERR(scad_cut_geometries(NULL, &geom, 1, list, sa_size(list), ground)); + ERR(scad_cut_geometries(NULL, &geom, 1, list, count, ground)); exit: if (pg_offset) SCPR(polygon_ref_put(pg_offset)); - if (list) sa_release(list); + darray_geometries_release(&array); if (footprint) SCAD(geometry_delete(footprint)); if (geom) SCAD(geometry_delete(geom)); return res; @@ -1113,32 +1164,41 @@ building_ground_connection char* cname = NULL; struct str name; int is_init = 0; + size_t count; + struct darray_geometries array; struct scad_geometry** list = NULL; struct scad_geometry* list_boundary = NULL; struct scad_geometry* footprint = NULL; ASSERT(prefix && allocator && cad && connection); + darray_geometries_init(allocator, &array); + str_init(allocator, &name); is_init = 1; ERR(str_set(&name, prefix)); ERR(str_append(&name, "_C_building_ground")); cname = str_get(&name); - if (cad->foundation) sa_push(list, cad->foundation); - if (cad->attic_cavity) sa_push(list, cad->attic_cavity); - if (cad->floor) sa_push(list, cad->floor); - if (cad->floor_insulation) sa_push(list, cad->floor_insulation); - if (cad->external_insulation) sa_push(list, cad->external_insulation); - if (cad->wall) sa_push(list, cad->wall); - - ERR(scad_geometries_common_boundaries( - cname, list, sa_size(list), - &cad->fake_ground, 1, + /* Ensure enough room for all geometries without error nor mem move */ + ERR(darray_geometries_reserve(&array, 6)); + if (cad->foundation) darray_geometries_push_back(&array, &cad->foundation); + if (cad->attic_cavity) darray_geometries_push_back(&array, &cad->attic_cavity); + if (cad->floor) darray_geometries_push_back(&array, &cad->floor); + if (cad->floor_insulation) + darray_geometries_push_back(&array, &cad->floor_insulation); + if (cad->external_insulation) + darray_geometries_push_back(&array, &cad->external_insulation); + if (cad->wall) darray_geometries_push_back(&array, &cad->wall); + + count = darray_geometries_size_get(&array); + list = darray_geometries_data_get(&array); + + ERR(scad_geometries_common_boundaries(cname, list,count, &cad->fake_ground, 1, connection)); exit: - if (list) sa_release(list); + darray_geometries_release(&array); if (is_init) str_release(&name); if (list_boundary) SCAD(geometry_delete(list_boundary)); if (footprint) SCAD(geometry_delete(footprint)); @@ -1234,6 +1294,8 @@ build_cad_cmode_1 res = RES_MEM_ERR; goto error; } + darray_geometries_init(allocator, &data_cad->boundary); + darray_geometries_init(allocator, &data_cad->connection); /* build mandatories elements : - floor @@ -1311,9 +1373,10 @@ build_cad_cmode_1 } /* fake ground */ - depth = MMAX(data->foundation_depth, data->floor_thickness - + data->floor_insulation_thickness + data->crawl_height); - ERR(build_fake_ground(data_cad, pg, depth, &data_cad->fake_ground)); + depth = MMAX(data->foundation_depth, + data->floor_thickness + data->floor_insulation_thickness + data->crawl_height); + ERR(build_fake_ground(allocator, data_cad, pg, data->foundation_depth, + &data_cad->fake_ground)); ERR(scad_scene_partition()); @@ -1435,13 +1498,15 @@ export_stl_cmode_1 } /* boundary export*/ - for(i = 0; i < sa_size(data_cad->boundary); i++) { - ERR(scad_stl_export(data_cad->boundary[i], NULL, binary)); + for(i = 0; i < darray_geometries_size_get(&data_cad->boundary); i++) { + struct scad_geometry* b = darray_geometries_data_get(&data_cad->boundary)[i]; + ERR(scad_stl_export(b, NULL, binary)); } /* connections export*/ - for(i = 0; i < sa_size(data_cad->connection); i++) { - ERR(scad_stl_export(data_cad->connection[i], NULL, binary)); + for(i = 0; i < darray_geometries_size_get(&data_cad->connection); i++) { + struct scad_geometry* c = darray_geometries_data_get(&data_cad->connection)[i]; + ERR(scad_stl_export(c, NULL, binary)); } /* ground/building connection export*/ @@ -1469,14 +1534,16 @@ release_cad_cmode_1 goto error; } - for(i = 0; i < sa_size(data_cad->boundary); i++) { - ERR(scad_geometry_delete(data_cad->boundary[i])); + for(i = 0; i < darray_geometries_size_get(&data_cad->boundary); i++) { + struct scad_geometry* b = darray_geometries_data_get(&data_cad->boundary)[i]; + ERR(scad_geometry_delete(b)); } - for(i = 0; i < sa_size(data_cad->connection); i++) { - ERR(scad_geometry_delete(data_cad->connection[i])); + for(i = 0; i < darray_geometries_size_get(&data_cad->connection); i++) { + struct scad_geometry* c = darray_geometries_data_get(&data_cad->connection)[i]; + ERR(scad_geometry_delete(c)); } - sa_release(data_cad->boundary); - sa_release(data_cad->connection); + darray_geometries_release(&data_cad->boundary); + darray_geometries_release(&data_cad->connection); MEM_RM(allocator, data_cad); exit: diff --git a/src/cg_constructive_mode_1.h b/src/cg_constructive_mode_1.h @@ -23,6 +23,7 @@ #include <rsys/rsys.h> #include <rsys/str.h> #include <rsys/hash_table.h> +#include <rsys/dynamic_array.h> struct scad_geometry; @@ -32,6 +33,10 @@ struct logger; struct parsed_city_building; struct catalog; +#define DARRAY_NAME geometries +#define DARRAY_DATA struct scad_geometry* +#include <rsys/dynamic_array.h> + /* specific data for constructive mode 1 */ struct dataset_cmode_1 { size_t inter_floor_count; /* can be 0 */ @@ -77,8 +82,8 @@ struct data_cad_cmode_1 { struct scad_geometry* glass; struct scad_geometry* fake_ground;/*not exported, used for ground connection*/ struct scad_geometry* ground_connection; - struct scad_geometry** boundary; - struct scad_geometry** connection; + struct darray_geometries boundary; + struct darray_geometries connection; size_t n_connection; };