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:
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], ¢er_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,