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 6ce1e8ac1816b1f4847232017d643cb3116fd1a9
parent ae792e88b88b9527b231ff22f7a483858aab02c0
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 17 Jan 2025 15:25:12 +0100

Implement levels creation using specified heights

Every single level is now created at its specified height. To keep it
simple, we manage to have the total building height being the sum of
level heights. This means that the specified height include the concrete
and insulation thicknesses and that, if present, the attic height is
the last of the level heights.
As a consequence, attic presence in now defined as a boolean in
construction mode 2 (it is an height in mode 1, with 0 meaning no attic).

Diffstat:
Msrc/cg_catalog.c | 2+-
Msrc/cg_construction_mode_2.c | 92++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/cg_construction_mode_2.h | 2+-
Msrc/cg_construction_mode_2_parsing_schemas.h | 6+++---
4 files changed, 61 insertions(+), 41 deletions(-)

diff --git a/src/cg_catalog.c b/src/cg_catalog.c @@ -209,7 +209,7 @@ create_catalog item.roof_insulation_thickness = parsed_item->roof_insulation_thickness; item.foundation_depth = parsed_item->foundation_depth; item.crawl_height = parsed_item->crawl_height; - item.attic_height = parsed_item->attic_height; + item.has_attic = parsed_item->has_attic; item.glass_ratio = parsed_item->glass_ratio; item.windows_min_width = parsed_item->windows_min_width; item.windows_max_width = parsed_item->windows_max_width; diff --git a/src/cg_construction_mode_2.c b/src/cg_construction_mode_2.c @@ -244,7 +244,11 @@ build_int_insulation double e_wall = data->wall_thickness; double e_roof = data->roof_thickness; double e_roof_insulation = data->roof_insulation_thickness; - double attic = data->attic_height; + size_t levels_n = data->has_attic ? + darray_double_size_get(&building->levels_height) - 1 : + darray_double_size_get(&building->levels_height); + const double* levels = darray_double_cdata_get(&building->levels_height); + double e_attic = data->has_attic ? levels[levels_n] : 0; double e_ext_insulation = data->external_insulation_thickness; double e_int_insulation = data->internal_insulation_thickness; double offset = 0; @@ -280,7 +284,7 @@ build_int_insulation ERR(build_footprint(pg_ext, 0, &footprint_ext)); ERR(scad_cut_geometries(NULL, &footprint_ext, 1, &footprint_int, 1, &footprint)); - d[2] = height - e_roof - attic - e_roof_insulation; + d[2] = height - e_roof - e_attic - e_roof_insulation; ERR(scad_geometry_extrude(footprint, NULL, d, &geom)); if(inter_floor) { @@ -371,7 +375,11 @@ build_roof_insulation double e_wall = data->wall_thickness; double e_insulation = data->external_insulation_thickness; double e_roof = data->roof_thickness; - double attic = data->attic_height; + size_t levels_n = data->has_attic ? + darray_double_size_get(&building->levels_height) - 1 : + darray_double_size_get(&building->levels_height); + const double* levels = darray_double_cdata_get(&building->levels_height); + double e_attic = data->has_attic ? levels[levels_n] : 0; double e_roof_insulation = data->roof_insulation_thickness; double offset = 0; double z_insulation = 0; @@ -395,7 +403,7 @@ build_roof_insulation offset, &pg_int)); /*footprint*/ - z_insulation = height - e_roof - attic - e_roof_insulation; + z_insulation = height - e_roof - e_attic - e_roof_insulation; ERR(build_footprint(pg_int, z_insulation, &footprint)); d[2] = e_roof_insulation; @@ -468,7 +476,6 @@ static res_T build_inter_floor (struct building* building, int *error_msg_printed, - const double height, const struct dataset_cmode_2* data, struct scpr_intersector* overlapping_intersector, struct htable_polygons* polygons, @@ -477,16 +484,15 @@ build_inter_floor { res_T res = RES_OK; size_t i = 0; - size_t levels_n = darray_double_size_get(&building->levels_height); - double e_roof = data->roof_thickness; - double e_roof_ins = data->roof_insulation_thickness; - double attic = data->attic_height; + size_t levels_n = data->has_attic ? + darray_double_size_get(&building->levels_height) - 1 : + darray_double_size_get(&building->levels_height); + const double* levels = darray_double_cdata_get(&building->levels_height); double e_floor = data->inter_floor_thickness; double e_wall = data->wall_thickness; double e_insulation = data->external_insulation_thickness; double offset = 0; double z_floor = 0; - double h_cavity = 0; struct scpr_polygon* pg_int = NULL; size_t nverts = 0; struct scad_geometry** floor_list = NULL; @@ -512,10 +518,9 @@ build_inter_floor offset, &pg_int)); ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); - h_cavity = height - e_roof - attic - e_roof_ins - (double)(levels_n - 1)*e_floor; - z_floor = h_cavity/(double)levels_n; + z_floor = levels[0] - e_floor; d[2] = e_floor; - for(i = 0; i < levels_n - 1; i++) { + for(i = 1; i < levels_n; i++) { ERR(scad_add_polygon(NULL, get_position_pg, pg_int, z_floor, nverts, &footprint)); ERR(scad_geometry_extrude(footprint, NULL, d, &floor)); @@ -524,7 +529,7 @@ build_inter_floor ERR(darray_geometries_push_back(&floor_array, &floor)); ERR(scad_geometry_ref_put(floor)); floor = NULL; /* Avoid double free */ - z_floor += h_cavity/(double)levels_n + e_floor; + z_floor += levels[i]; } ASSERT(darray_geometries_size_get(&floor_array) == levels_n - 1); @@ -678,7 +683,11 @@ build_habitable double e_int_insulation = data->internal_insulation_thickness; double e_roof = data->roof_thickness; double e_roof_insulation = data->roof_insulation_thickness; - double e_attic = data->attic_height; + size_t levels_n = data->has_attic ? + darray_double_size_get(&building->levels_height) - 1 : + darray_double_size_get(&building->levels_height); + const double* levels = darray_double_cdata_get(&building->levels_height); + double e_attic = data->has_attic ? levels[levels_n] : 0; double offset = 0; struct scpr_polygon* pg_int = NULL; struct scad_geometry* footprint = NULL; @@ -735,7 +744,11 @@ build_attic double e_wall = data->wall_thickness; double e_insulation = data->external_insulation_thickness; double e_roof = data->roof_thickness; - double e_attic = data->attic_height; + size_t levels_n = data->has_attic ? + darray_double_size_get(&building->levels_height) - 1 : + darray_double_size_get(&building->levels_height); + const double* levels = darray_double_cdata_get(&building->levels_height); + double e_attic = data->has_attic ? levels[levels_n] : 0; double offset = 0; double z_attic = 0; struct scpr_polygon* pg_int = NULL; @@ -810,8 +823,7 @@ build_windows struct scad_geometry* env = NULL; struct scad_geometry* benv = NULL; struct scad_geometry* problem = NULL; - size_t levels_n; - double e_roof, e_roof_ins, attic, wall_height, e_floor; + double wall_height; struct str name; struct adjoining_data* adj; struct city* city; @@ -827,15 +839,6 @@ build_windows darray_geometries_init(allocator, &glass_array); str_init(allocator, &name); - /* Compute wall height to help compute the minimum for windows area */ - levels_n = darray_double_size_get(&data_cad->building->levels_height); - e_roof = data->roof_thickness; - e_roof_ins = data->roof_insulation_thickness; - attic = data->attic_height; - e_floor = data->inter_floor_thickness; - wall_height = (data_cad->building->total_height - e_roof - attic - e_roof_ins - - (double)(levels_n -1)*e_floor) / (double)levels_n; - /* windows are build from the vertical faces of habitable cavities */ ERR(scad_geometry_boundary("cavity_boundary", &data_cad->habitable_cavity, 1, &bcavity)); @@ -856,6 +859,7 @@ build_windows double hsz, wall_surface, wall_width, center[3]; size_t center_n, count, n; int removed_wall = 0; + double mi[3], ma[3]; ERR(scad_geometry_get_count(list[i], &center_n)); ASSERT(center_n == 1); @@ -867,14 +871,16 @@ build_windows /* keep only vertical face */ removed_wall = 1; } - d3_normalize(N, N); - ERR(scad_geometry_get_mass(list[i], &wall_surface)); - wall_width = wall_surface / wall_height; - total_wall_surface += wall_surface; if(!removed_wall) { double window_height, expected_total_width_from_ratio; double wc, best_wc, best_wc_score, best_wc_spacing, best_wc_width; + d3_normalize(N, N); + ERR(scad_geometry_get_mass(list[i], &wall_surface)); + total_wall_surface += wall_surface; + ERR(scad_geometry_get_bounding_box(list[i], mi, ma)); + wall_height = ma[2] - mi[2]; + wall_width = wall_surface / wall_height; /* The basic result is: no window */ best_wc = 0; best_wc_score = 0; @@ -1617,12 +1623,20 @@ init_cmode_2 ERR(str_set(&building->external_layer_name, (has_external_insulation ? "external_insulation" : "walls"))); + if(data->has_attic && parsed_data->levels_height_count <= 1) { + ERR(logger_print(city->logger, LOG_ERROR, + "Building '%s' height definition is invalid " + "(At least 2 level heights needed when there is an attic).\n", + str_cget(&building->name))); + res = RES_BAD_ARG; + goto error; + } + ERR(darray_double_resize(&building->levels_height, parsed_data->levels_height_count)); lh = darray_double_data_get(&building->levels_height); - building->total_height = data->attic_height - + data->roof_thickness + data->roof_insulation_thickness; + building->total_height = 0; for(count = 0; count < parsed_data->levels_height_count; count++) { lh[count] = parsed_data->levels_height[count]; if(lh[count] <= 0) { @@ -1664,6 +1678,8 @@ build_cad_cmode_2 double depth = 0; struct dataset_cmode_2* data = (struct dataset_cmode_2 *)building->data; struct data_cad_cmode_2* data_cad = NULL; + double e_attic; + const double* levels; const char* name; struct scpr_intersector* overlapping_intersector = NULL; struct scpr_intersector_check_callbacks callbacks @@ -1691,7 +1707,11 @@ build_cad_cmode_2 name = str_cget(&building->name); allocator = building->city->allocator; logger = building->city->logger; - levels_n = darray_double_size_get(&building->levels_height); + levels = darray_double_cdata_get(&building->levels_height); + levels_n = data->has_attic ? + darray_double_size_get(&building->levels_height) - 1 : + darray_double_size_get(&building->levels_height); + e_attic = data->has_attic ? levels[levels_n] : 0; logger_print(logger, LOG_OUTPUT, "Building '%s' construction mode 2, dataset '%s', %g m tall, %lu levels.\n", @@ -1751,7 +1771,7 @@ build_cad_cmode_2 } if(levels_n > 1) { - ERR(build_inter_floor(building, &error_msg_printed, height, data, + ERR(build_inter_floor(building, &error_msg_printed, data, overlapping_intersector, &polygons, current_cad, &data_cad->intermediate_floor)); } @@ -1782,7 +1802,7 @@ build_cad_cmode_2 - crawlspace */ - if(data->attic_height > 0) { + if(e_attic > 0) { ERR(build_attic(building, &error_msg_printed, height, data, overlapping_intersector, &polygons, current_cad, &data_cad->attic_cavity)); } diff --git a/src/cg_construction_mode_2.h b/src/cg_construction_mode_2.h @@ -45,12 +45,12 @@ struct dataset_cmode_2 { double roof_insulation_thickness; /* can be 0 */ double foundation_depth; /* can be 0 */ double crawl_height; /* can be 0 */ - double attic_height; /* can be 0 */ double glass_ratio; /* in [0, 1] */ double windows_min_width; /* must be > 0 */ double windows_max_width; /* must be >= windows_min_width */ double windows_min_spacing; /* must be > 0 */ double windows_height_ratio; /* in [0, 1] */ + int has_attic; }; #define HTABLE_NAME dataset_cmode_2 diff --git a/src/cg_construction_mode_2_parsing_schemas.h b/src/cg_construction_mode_2_parsing_schemas.h @@ -36,12 +36,12 @@ struct parsed_dataset_cmode_2 { double roof_insulation_thickness; /* can be 0 */ double foundation_depth; /* can be 0 */ double crawl_height; /* can be 0 */ - double attic_height; /* can be 0 */ double glass_ratio; /* in [0, 1] */ double windows_min_width; /* must be > 0 */ double windows_max_width; /* must be >= windows_min_width */ double windows_min_spacing; /* must be > 0 */ double windows_height_ratio; /* in [0, 1] */ + int has_attic; }; /********************************************************/ @@ -76,8 +76,8 @@ static const cyaml_schema_field_t dataset_cmode_2_fields_schema[] = { struct parsed_dataset_cmode_2, foundation_depth), CYAML_FIELD_FLOAT("crawl_height", CYAML_FLAG_DEFAULT, struct parsed_dataset_cmode_2, crawl_height), - CYAML_FIELD_FLOAT("attic_height", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_2, attic_height), + CYAML_FIELD_BOOL("has_attic", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_2, has_attic), CYAML_FIELD_FLOAT("glass_ratio", CYAML_FLAG_DEFAULT, struct parsed_dataset_cmode_2, glass_ratio), CYAML_FIELD_FLOAT("windows_min_width", CYAML_FLAG_DEFAULT,