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 c54eda0196e7618e9052b63755afc541a74705c5
parent eb5fe8f2455c41328b7d37c2727962060468b4a8
Author: Benjamin Piaud <benjamin.piaud@meso-star.com>
Date:   Tue, 17 Jan 2023 10:55:03 +0100

Merge remote-tracking branch 'refs/remotes/origin/develop' into develop

Diffstat:
Mcmake/CMakeLists.txt | 14+++++++-------
Mdoc/city_generator2-input.5.txt | 107++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mdoc/city_generator2.1.txt.in | 10+++++-----
Msrc/cg_args.c | 2+-
Msrc/cg_building.h | 26+++++++++++++-------------
Msrc/cg_catalog.c | 14+++++++-------
Msrc/cg_catalog.h | 4++--
Msrc/cg_catalog_parsing.c | 20++++++++++----------
Msrc/cg_catalog_parsing.h | 4++--
Msrc/cg_city.c | 6+++---
Msrc/cg_city_parsing_schemas.h | 12++++++------
Asrc/cg_construction_mode.h | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_construction_mode_0.c | 639+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_construction_mode_0.h | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_construction_mode_0_parsing_schemas.h | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_construction_mode_1.c | 1598+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_construction_mode_1.h | 124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_construction_mode_1_parsing_schemas.h | 124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_construction_modes_parsing_schemas.h | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/cg_constructive_mode.h | 54------------------------------------------------------
Dsrc/cg_constructive_mode_0.c | 639-------------------------------------------------------------------------------
Dsrc/cg_constructive_mode_0.h | 98-------------------------------------------------------------------------------
Dsrc/cg_constructive_mode_0_parsing_schemas.h | 87-------------------------------------------------------------------------------
Dsrc/cg_constructive_mode_1.c | 1598-------------------------------------------------------------------------------
Dsrc/cg_constructive_mode_1.h | 124-------------------------------------------------------------------------------
Dsrc/cg_constructive_mode_1_parsing_schemas.h | 124-------------------------------------------------------------------------------
Dsrc/cg_constructive_modes_parsing_schemas.h | 61-------------------------------------------------------------
Msrc/cg_main.c | 4++--
28 files changed, 2927 insertions(+), 2866 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -106,8 +106,8 @@ set(CG2_FILES_SRC cg_catalog_parsing.c cg_city.c cg_city_parsing.c - cg_constructive_mode_0.c - cg_constructive_mode_1.c + cg_construction_mode_0.c + cg_construction_mode_1.c cg_ground.c cg_main.c) @@ -120,11 +120,11 @@ set(CG2_FILES_INC cg_city.h cg_city_parsing.h cg_city_parsing_schemas.h - cg_constructive_mode.h - cg_constructive_mode_0.h - cg_constructive_mode_0_parsing_schemas.h - cg_constructive_mode_1.h - cg_constructive_mode_1_parsing_schemas.h + cg_construction_mode.h + cg_construction_mode_0.h + cg_construction_mode_0_parsing_schemas.h + cg_construction_mode_1.h + cg_construction_mode_1_parsing_schemas.h cg_default.h.in cg_ground.h cg_version.h.in) diff --git a/doc/city_generator2-input.5.txt b/doc/city_generator2-input.5.txt @@ -25,7 +25,7 @@ == NAME -city_generator2-input - description of the input files formats for +city_generator2-input - description of input file formats for city_generator2(1) == DESCRIPTION @@ -33,53 +33,114 @@ city_generator2(1) *city_generator2-input*(5) are the formats used by the *city_generator2*(1) program to describe a city. They all rely on the yaml 1.1 syntax[1]. *city_generator2*(1) reads two different types of files: a single map file, and -at least one catalog file. The followig two sections describe their formats. +at least one catalog file. The next two sections describe their formats. + +Because these files are yaml files, they must comply with yaml syntax rules, +including the hard part that is spacing. The following grammar rules that begin +with a verbatim text must all start at column 1. From here, the amount of +whitespace characters in verbatim text must be strictly observed. Also, text +appearing between quote marks has to be used verbatim in the input, without the +quote characters. Finally, text introduced by the *#* character in descriptions, +when not verbatim, is a comment and is not part of the description. [1] https://yaml.org/ === CITY MAP FILE FORMAT -b +The city map file aims to describe the ground, that is currently limited to a +single layer, with a depth, and the list of buildings on the ground. Each +building is described in the same way, regardless of its construction mode, that +is part of the description. + +==== GRAMMAR + +[verse] +_______ +<city-map-file> ::= <ground-description> + <building-list> + +<ground-description> ::= "ground:" + " extent: " <extent> + " depth: " <depth> + +<building-list> ::= "building: " + <buildings> + +------------------------------------- + +<extent> ::= "[ <Xmin> "," <Ymin> "," <Xsize> "," <Ysize> ] + +<depth> ::= <REAL> # in ]0, INF) + +<Xmin> ::= <REAL> + +<Ymin> ::= <REAL> + +<buildings> ::= <building> + [ <buildings> ] + +<Xsize> ::= <REAL> # in ]0, INF) + +<Ysize> ::= <REAL> # in ]0, INF) + +------------------------------------- + +<building> ::= " -id: " <name> + " model: " <cmode-name> + " data: " <dataset-name> + " height: " <height> + " polygon: [" <vertices> "]" # At least 3 vertices + +<name> ::= STRING + +<cmode-name> ::= "construction_Mode_0" | "construction_Mode_1" + +<dataset-name> ::= STRING + +<height> ::= <REAL> # in ]0, INF) + +<vertices> ::= <vertex> [ "," <vertices> ] + +------------------------------------- + +<vertex> ::= "[" <X> "," <Y> "]" + +<X> ::= <REAL> + +<Y> ::= <REAL> + +______________ === CATALOG FILE FORMATS There are currently two different catalog file formats, identified by name, and -the way city-generator is designed allows for additional catalog formats to be +the way city-generator2 is designed allows for additional catalog formats to be implemented. -All catalog files contain the name of the constructive mode they add datasets -to, and a list of datasets. What differs among catalog file formats is the -format of the datasets. It is obviously expected that datasets use the format -associated with the named constructive mode. +All catalog files contain the name of the construction mode to which they add +datasets, and a list of datasets. What differs between catalog file formats is +the format of the datasets. It is obviously expected that datasets use the +format associated with the named construction mode. ==== GRAMMAR -Catalog files being yaml files, they must comply with yaml syntax rules, -including the hard part that is spacing. The following grammar rules that start -with a verbatim item are all expected to start at column 1. From there, the -amount of whitespace characters in verbatim items must be strictly observed. -Also, text appearing between quote marks has to be used verbatim in the input, -with or without the quote characters. Finally, text introduced by the *#* -character in descriptions, when not verbatim, is a comment and is not part of -the description. - [verse] _______ <catalog-file> ::= <catalog-file_0 > | <catalog-file_1> -<catalog-file-0> ::= <constructive-mode-0> - "sets:" +<catalog-file-0> ::= <construction-mode-0> + "datasets:" <datasets-0> -<catalog-file-1> ::= <constructive-mode-1> - "sets:" +<catalog-file-1> ::= <construction-mode-1> + "datasets:" <datasets-1> ------------------------------------- -<constructive-mode-0> ::= "constructive_mode_type: Constructive_Mode_0" +<construction-mode-0> ::= "construction_mode_type: construction_Mode_0" -<constructive-mode-1> ::= "constructive_mode_type: Constructive_Mode_1" +<construction-mode-1> ::= "construction_mode_type: construction_Mode_1" ------------------------------------- diff --git a/doc/city_generator2.1.txt.in b/doc/city_generator2.1.txt.in @@ -38,7 +38,7 @@ DESCRIPTION *city_generator2* generates a city as 3D conformal meshes from an ascii description. The description includes the city map (a description of the ground and buildings in a yaml file), and at least one catalog file (a description of -a set of datasets grouped by constructive modes). The provided description must +a set of datasets grouped by construction modes). The provided description must comply with the *city_generator2-input*(5) format. The output of *city_generator2* is a set of *STL* files, either in ascii or in @@ -65,16 +65,16 @@ MANDATORY OPTIONS *-m* _file_:: Read a city map file which is a text file in yaml 1.1 format containing the description of the ground and a list of buildings. The description of an - individual building include its footprint and constructive mode among other + individual building include its footprint and construction mode among other things. Please refer to *city_generator2-input*(5) for more information on formats. *-c* _file_:: Read a catalog file which is a text file in yaml 1.1 format containing datasets - for a given constructive mode. All the datasets in a given file share the - same constructive mode. If the city map uses more than one constructive mode, + for a given construction mode. All the datasets in a given file share the + same construction mode. If the city map uses more than one construction mode, the different datasets must be provided in (at least) as many catalog files - as there are constructive modes involved. + as there are construction modes involved. Please refer to *city_generator2-input*(5) for more information on formats. OTHER OPTIONS diff --git a/src/cg_args.c b/src/cg_args.c @@ -54,7 +54,7 @@ short_help(void) "-m <city_map_filename>\n" " Read a yaml file that describes the city map.\n" "-c <filename>\n" - " Read a yaml file containing datasets for a given constructive mode.\n" + " Read a yaml file containing datasets for a given construction mode.\n" " Can be used more than once.\n" "\nOther options\n" "-------------\n" diff --git a/src/cg_building.h b/src/cg_building.h @@ -32,8 +32,8 @@ struct catalog; struct building; struct parsed_city_building; -/* A type to store the functors of a constructive mode */ -struct constructive_mode_functors { +/* A type to store the functors of a construction mode */ +struct construction_mode_functors { res_T (*init) (struct building* building, struct mem_allocator* allocator, @@ -53,30 +53,30 @@ struct constructive_mode_functors { (struct mem_allocator* allocator, struct logger* logger, void* cad); }; -/* A type to give an ID to constructive modes. - * Add a new entry for each new constructive mode. */ -enum constructive_mode_type { +/* A type to give an ID to construction modes. + * Add a new entry for each new construction mode. */ +enum construction_mode_type { mode_0, mode_1, - CONSTRUCTIVE_MODES_COUNT__ + Construction_MODES_COUNT__ }; -/* The name of the constructive modes, as expected in the city description. */ -extern char const* constructive_mode_name[CONSTRUCTIVE_MODES_COUNT__]; +/* The name of the construction modes, as expected in the city description. */ +extern char const* construction_mode_name[Construction_MODES_COUNT__]; /* The type of buildings as described in the city description */ struct building { - /* constructive mode */ - struct constructive_mode_functors* functors; - enum constructive_mode_type constructive_mode; + /* construction mode */ + struct construction_mode_functors* functors; + enum construction_mode_type construction_mode; - /* generic constructive mode data */ + /* generic construction mode data */ int name_initialized; struct str name; double height; struct scpr_polygon* pg; - /* specific data depending to the constructive mode */ + /* specific data depending to the construction mode */ void* data; }; diff --git a/src/cg_catalog.c b/src/cg_catalog.c @@ -21,10 +21,10 @@ #include "cg_building.h" #include "cg_catalog.h" #include "cg_catalog_parsing.h" -#include "cg_constructive_mode_0.h" -#include "cg_constructive_mode_1.h" -#include "cg_constructive_mode_0_parsing_schemas.h" -#include "cg_constructive_mode_1_parsing_schemas.h" +#include "cg_construction_mode_0.h" +#include "cg_construction_mode_1.h" +#include "cg_construction_mode_0_parsing_schemas.h" +#include "cg_construction_mode_1_parsing_schemas.h" #include <rsys/rsys.h> #include <rsys/mem_allocator.h> @@ -43,8 +43,8 @@ find_first_filename ASSERT(dataset_name && items && count > 0); for(i = 0; i < count; i++) { - if(items[i].constructive_mode != dataset_cmode) continue; - switch(items[i].constructive_mode) { + if(items[i].construction_mode != dataset_cmode) continue; + switch(items[i].construction_mode) { case mode_0: { const struct parsed_catalog_cmode_0* prsd_0 = items[i].parsed_data; for(j = 0; j < prsd_0->datasets_count; j++) { @@ -104,7 +104,7 @@ create_catalog items = darray_parsed_catalog_items_cdata_get(&parsed_catalog->catalog); for(i = 0; i < count; i++) { - switch(items[i].constructive_mode) { + switch(items[i].construction_mode) { case mode_0: { const struct parsed_catalog_cmode_0* parsed_0 = items[i].parsed_data; for(j = 0; j < parsed_0->datasets_count; j++) { diff --git a/src/cg_catalog.h b/src/cg_catalog.h @@ -20,8 +20,8 @@ #ifndef FG_CATALOG__ #define FG_CATALOG__ -#include "cg_constructive_mode_0.h" -#include "cg_constructive_mode_1.h" +#include "cg_construction_mode_0.h" +#include "cg_construction_mode_1.h" struct mem_allocator; struct logger; diff --git a/src/cg_catalog_parsing.c b/src/cg_catalog_parsing.c @@ -20,8 +20,8 @@ #include "cg.h" #include "cg_args.h" #include "cg_catalog_parsing.h" -#include "cg_constructive_mode_0_parsing_schemas.h" -#include "cg_constructive_mode_1_parsing_schemas.h" +#include "cg_construction_mode_0_parsing_schemas.h" +#include "cg_construction_mode_1_parsing_schemas.h" #include "cg_city_parsing_schemas.h" #include "cg_building.h" @@ -36,9 +36,9 @@ get_schema_from_parsed_cmode { switch(parsed_cmode) { case PARSED_CMODE_0: - return &constructive_mode_0_schema; + return &construction_mode_0_schema; case PARSED_CMODE_1: - return &constructive_mode_1_schema; + return &construction_mode_1_schema; default: FATAL("Invalid enum value.\n"); } } @@ -79,23 +79,23 @@ parse_catalog for(i = 0; i < files_count; i++) { const struct cyaml_schema_value* schema; - /* Parse constructive mode only */ + /* Parse construction mode only */ filename = darray_catalog_filenames_cdata_get(files_array)[i]; - err = cyaml_load_file(filename, config, &constructive_mode_schema, + err = cyaml_load_file(filename, config, &construction_mode_schema, (void**)&parsed_cmode, NULL); ERR(cyaml_err_to_res_T(err)); - /* Parse catalog items according to constructive mode */ + /* Parse catalog items according to construction mode */ schema = get_schema_from_parsed_cmode(parsed_cmode->cmode_type); err = cyaml_load_file(filename, config, schema, &items[i].parsed_data, NULL); ERR(cyaml_err_to_res_T(err)); /* Set other fields*/ items[i].filename = filename; - items[i].constructive_mode = parsed_cmode->cmode_type; + items[i].construction_mode = parsed_cmode->cmode_type; /* Free tmp struct */ - err = cyaml_free(config, &constructive_mode_schema, parsed_cmode, 1); + err = cyaml_free(config, &construction_mode_schema, parsed_cmode, 1); CHK(RES_OK == cyaml_err_to_res_T(err)); parsed_cmode = NULL; filename = NULL; @@ -134,7 +134,7 @@ release_parsed_catalog items = darray_parsed_catalog_items_data_get(&parsed->catalog); for(i = 0; i < count; i++) { const struct cyaml_schema_value* schema - = get_schema_from_parsed_cmode(items[i].constructive_mode); + = get_schema_from_parsed_cmode(items[i].construction_mode); cyaml_err_t err = cyaml_free(config, schema, items[i].parsed_data, 1); CHK(RES_OK == cyaml_err_to_res_T(err)); } diff --git a/src/cg_catalog_parsing.h b/src/cg_catalog_parsing.h @@ -20,7 +20,7 @@ #ifndef PARSING_H #define PARSING_H -#include "cg_constructive_modes_parsing_schemas.h" +#include "cg_construction_modes_parsing_schemas.h" #include <rsys/rsys.h> #include <rsys/dynamic_array.h> @@ -31,7 +31,7 @@ struct cyaml_config; struct darray_catalog_filenames; struct parsed_catalog_items { - enum parsed_cmode_type constructive_mode; + enum parsed_cmode_type construction_mode; char* filename; void* parsed_data; }; diff --git a/src/cg_city.c b/src/cg_city.c @@ -19,8 +19,8 @@ #include "cg.h" #include "cg_city.h" -#include "cg_constructive_mode_0.h" -#include "cg_constructive_mode_1.h" +#include "cg_construction_mode_0.h" +#include "cg_construction_mode_1.h" #include "cg_ground.h" #include "cg_catalog_parsing.h" #include "cg_city_parsing.h" @@ -92,7 +92,7 @@ create_city city->ground_depth = parsed_city->ground.depth; d4_set(city->ground_extent, parsed_city->ground.extent); - /* create buildings depending on their constructive modes */ + /* create buildings depending on their construction modes */ for (i = 0; i < city->buildings_count ; i++) { struct parsed_city_building* parsed_data = parsed_city->city_building_list + i; struct building* building = city->buildings + i; diff --git a/src/cg_city_parsing_schemas.h b/src/cg_city_parsing_schemas.h @@ -20,7 +20,7 @@ #ifndef FG_CITY_PARSING_SCHEMAS__ #define FG_CITY_PARSING_SCHEMAS__ -#include "cg_constructive_modes_parsing_schemas.h" +#include "cg_construction_modes_parsing_schemas.h" #include <rsys/str.h> @@ -85,15 +85,15 @@ static const struct cyaml_schema_value double2_schema = { }; static const cyaml_schema_field_t city_building_fields_schema[] = { - CYAML_FIELD_STRING_PTR("id", /* TODO: rename "name" */ + CYAML_FIELD_STRING_PTR("name", CYAML_FLAG_POINTER, struct parsed_city_building, name, 0, CYAML_UNLIMITED), - CYAML_FIELD_ENUM("model", /* TODO: rename "constructive_mode" */ + CYAML_FIELD_ENUM("construction_mode", CYAML_FLAG_CASE_INSENSITIVE, struct parsed_city_building, cmode_type, city_building_types_strings, CYAML_ARRAY_LEN(city_building_types_strings)), - CYAML_FIELD_STRING_PTR("data", /* TODO: rename "parameter_set" */ + CYAML_FIELD_STRING_PTR("dataset", CYAML_FLAG_POINTER, struct parsed_city_building, dataset_name, 0, CYAML_UNLIMITED), { - .key = "polygon", /*TODO: rename "external_polygon" */ + .key = "footprint", .value = { .type = CYAML_SEQUENCE, .flags = CYAML_FLAG_POINTER | CYAML_FLAG_FLOW, @@ -123,7 +123,7 @@ static const cyaml_schema_field_t city_fields_schema[] = { CYAML_FIELD_MAPPING("ground", CYAML_FLAG_DEFAULT, struct parsed_city, ground, ground_fields_schema), { - .key = "building", /* TODO: rename "buildings" */ + .key = "buildings", .value = { .type = CYAML_SEQUENCE, .flags = CYAML_FLAG_POINTER, diff --git a/src/cg_construction_mode.h b/src/cg_construction_mode.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA + * Copyright (C) 2022 CNRS + * Copyright (C) 2022 Sorbonne Université + * Copyright (C) 2022 Université Paul Sabatier + * Copyright (C) 2022 |Meso|Star> (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/>. */ + +#ifndef Construction_MODE_H__ +#define Construction_MODE_H__ + +#include "cg_city_parsing_schemas.h" + +#include <rsys/rsys.h> +#include <star/scpr.h> + +static void +get_nverts(const size_t icomp, size_t* nverts, void* context) +{ + struct parsed_city_building* parsed_data = context; + ASSERT(icomp == 0); (void)icomp; + *nverts = parsed_data->vertice_count; +} + +static void +get_pos(const size_t icomp, const size_t ivert, double pos[2], void* context) +{ + struct parsed_city_building* parsed_data = context; + ASSERT(icomp == 0); (void)icomp; + pos[0] = parsed_data->vertice[ivert*2 + 0]; + pos[1] = parsed_data->vertice[ivert*2 + 1]; +} + +static void get_position_pg + (const size_t ivert, double pos[2], void* ctx) +{ + struct scpr_polygon* pg = ctx; + ASSERT(pos && pg); + CHK(scpr_polygon_get_position(pg, 0, ivert, pos) == RES_OK); +} + +#endif + diff --git a/src/cg_construction_mode_0.c b/src/cg_construction_mode_0.c @@ -0,0 +1,639 @@ +/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA + * Copyright (C) 2022 CNRS + * Copyright (C) 2022 Sorbonne Université + * Copyright (C) 2022 Université Paul Sabatier + * Copyright (C) 2022 |Meso|Star> (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/>. */ + +#include "cg.h" +#include "cg_building.h" +#include "cg_catalog.h" +#include "cg_city.h" +#include "cg_city_parsing_schemas.h" +#include "cg_construction_mode_0.h" +#include "cg_construction_mode.h" + +#include <rsys/rsys.h> +#include <rsys/str.h> +#include <rsys/logger.h> +#include <star/scad.h> + +static res_T +build_floor_footprint + (struct scpr_polygon* pg, + struct scad_geometry** footprint) +{ + res_T res = RES_OK; + size_t nverts; + + ASSERT(pg && footprint); + ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts)); + ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, footprint)); + +exit: + return res; +error: + goto exit; +} + +static res_T +build_floor + (const char* prefix, + struct scpr_polygon* pg, + struct building* b, + struct scad_geometry** floor) +{ + res_T res = RES_OK; + double e; + struct dataset_cmode_0* data; + struct scad_geometry* footprint = NULL; + double d[3] = {0, 0, 0}; + char* floorname = NULL; + struct str name; + int is_init = 0; + + ASSERT(pg && b && floor); + + data = (struct dataset_cmode_0*)b->data; + e = data->floor_thickness; + + str_init(NULL, &name); + is_init = 1; + if (prefix) { + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_S_floor")); + floorname = str_get(&name); + } + + ERR(build_floor_footprint(pg, &footprint)); + + d[2] = e; + ERR(scad_geometry_extrude(footprint, floorname, d, floor)); + +exit: + SCAD(geometry_delete(footprint)); + if (is_init) str_release(&name); + return res; +error: + goto exit; +} + +static res_T +build_roof + (const char* prefix, + const struct building* b, + const struct scad_geometry* floor, + struct scad_geometry** roof) +{ + res_T res = RES_OK; + double height; + double e; + double d[3] = {0, 0, 0}; + struct dataset_cmode_0* data; + char* roofname = NULL; + struct str name; + int is_init = 0; + + ASSERT(b && floor && roof); + + str_init(NULL, &name); + is_init = 1; + if (prefix) { + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_S_roof")); + roofname = str_get(&name); + } + + height = b->height; + data = (struct dataset_cmode_0*)b->data; + e = data->floor_thickness; + + ERR(scad_geometry_copy(floor, roofname, roof)); + d[2] = height - e ; + ERR(scad_geometry_translate(*roof, d)); + +exit: + if (is_init) str_release(&name); + return res; +error: + goto exit; +} + +static res_T +build_wall_footprint + (struct scpr_polygon* pg, + struct scpr_polygon* pg_int, + struct scad_geometry** footprint) +{ + res_T res = RES_OK; + struct scad_geometry* polygon = NULL; + struct scad_geometry* polygon_int = NULL; + size_t nverts, nverts_int; + + ASSERT(pg && pg_int && footprint); + + ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts)); + ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, &polygon)); + + ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts_int)); + ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts_int, &polygon_int)); + + ERR(scad_cut_geometries(NULL, &polygon, 1, &polygon_int, 1, footprint)); + +exit: + if(polygon) SCAD(geometry_delete(polygon)); + if(polygon_int) SCAD(geometry_delete(polygon_int)); + return res; +error: + goto exit; +} + +static res_T +build_wall + (const char* prefix, + struct scpr_polygon* pg, + struct scpr_polygon* pg_int, + struct building* b, + struct scad_geometry** wall) +{ + res_T res = RES_OK; + double height; + struct scad_geometry* footprint = NULL; + double d[3] = {0, 0, 0}; + char* wallname = NULL; + struct str name; + int is_init = 0; + + ASSERT(pg && pg_int && b && wall); + + height = b->height; + + str_init(NULL, &name); + is_init = 1; + if (prefix) { + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_S_wall")); + wallname = str_get(&name); + } + + ERR(build_wall_footprint(pg, pg_int, &footprint)); + + d[2] = height; + ERR(scad_geometry_extrude(footprint, wallname, d, wall)); + +exit: + if(footprint) SCAD(geometry_delete(footprint)); + if (is_init) str_release(&name); + return res; +error: + goto exit; +} + +static res_T +build_cavity + (const char* prefix, + struct scpr_polygon* pg, + const struct building* b, + struct scad_geometry** cavity) +{ + res_T res = RES_OK; + double e, height; + struct dataset_cmode_0* data; + double d[3] = {0, 0, 0}; + struct scad_geometry* polygon = NULL; + char* cavityname = NULL; + struct str name; + int is_init = 0; + size_t nverts; + + ASSERT(pg && b && cavity); + + height = b->height; + data = (struct dataset_cmode_0*)b->data; + e = data->floor_thickness; + + str_init(NULL, &name); + is_init = 1; + if (prefix) { + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_F_cavity")); + cavityname = str_get(&name); + } + + ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts)); + ERR(scad_add_polygon(NULL, get_position_pg, pg, e, nverts, &polygon)); + + d[2] = height - e; + ERR(scad_geometry_extrude(polygon, cavityname, d, cavity)); + +exit: + if(polygon) SCAD(geometry_delete(polygon)); + if (is_init) str_release(&name); + return res; +error: + goto exit; +} + +static res_T +build_connection + (const char* prefix, + struct mem_allocator* allocator, + struct data_cad_cmode_0* cad) +{ + res_T res = RES_OK; + char* cname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && cad); + + cad->connection = MEM_CALLOC(allocator, 3, sizeof(struct scad_geometry*)); + if(!cad->connection) { + res = RES_MEM_ERR; + goto error; + } + cad->n_connection = 3; + + /* cavity/floor connection */ + str_init(NULL, &name); + is_init = 1; + if (prefix) { + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_C_cavity_floor")); + cname = str_get(&name); + } + + ERR(scad_geometries_common_boundaries(cname, &cad->cavity, 1, &cad->floor, 1, + &cad->connection[0])); + + /* cavity/wall connection */ + if (prefix) { + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_C_cavity_wall")); + cname = str_get(&name); + } + + ERR(scad_geometries_common_boundaries(cname, &cad->cavity, 1, &cad->wall, 1, + &cad->connection[1])); + + /* cavity/roof connection */ + if (prefix) { + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_C_cavity_roof")); + cname = str_get(&name); + } + + ERR(scad_geometries_common_boundaries(cname, &cad->cavity, 1, &cad->roof, 1, + &cad->connection[2])); + +exit: + if (is_init) str_release(&name); + return res; +error: + goto exit; +} + +static res_T +build_boundary + (const char* prefix, + struct mem_allocator* allocator, + struct data_cad_cmode_0* cad) +{ + res_T res = RES_OK; + struct scad_geometry** list = NULL; + struct scad_geometry* boundary = NULL; + char* cname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && cad); + + list = MEM_ALLOC(allocator, 4 * sizeof(struct scad_geometry*)); + if(!list) { + res = RES_MEM_ERR; + goto error; + } + list[0] = cad->floor; + list[1] = cad->wall; + list[2] = cad->roof; + list[3] = cad->cavity; + + str_init(NULL, &name); + is_init = 1; + if (prefix) { + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_boundary")); + cname = str_get(&name); + } + + ERR(scad_geometry_boundary(NULL, list, 4, &boundary)); + + ERR(scad_cut_geometries(cname, &boundary, 1, &cad->ground_connection, 1, + &cad->boundary)); + +exit: + if(boundary) SCAD(geometry_delete(boundary)); + MEM_RM(allocator, list); + if (is_init) str_release(&name); + return res; +error: + goto exit; +} + +static res_T +building_ground_connection + (const char* prefix, + struct scpr_polygon* pg, + const double e, + struct scad_geometry** connection) +{ + res_T res = RES_OK; + struct scpr_polygon* pg_int = NULL; + struct scad_geometry* geom[2] = { NULL, NULL }; + char* cname = NULL; + struct str name; + int is_init = 0; + + ASSERT(pg && e > 0 && connection); + + if (prefix) { + str_init(NULL, &name); + is_init = 1; + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_C_building_ground")); + cname = str_get(&name); + } + + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -e, SCPR_JOIN_MITER)); + + ERR(build_wall_footprint(pg, pg_int, &geom[0])); + ERR(build_floor_footprint(pg, &geom[1])); + + ERR(scad_fragment_geometries(cname, &geom[0], 1, &geom[1], 1, connection)); + +exit: + if(is_init) str_release(&name); + if(geom[0]) SCAD(geometry_delete(geom[0])); + if(geom[1]) SCAD(geometry_delete(geom[1])); + if(pg_int) SCPR(polygon_ref_put(pg_int)); + return res; +error: + goto exit; +} + +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ + +res_T +init_cmode_0 + (struct building* building, + struct mem_allocator* allocator, + struct logger* logger, + struct parsed_city_building* parsed_data, + struct catalog* catalog) +{ + res_T res = RES_OK; + struct dataset_cmode_0* dataset; + struct str dataset_name; + int name_initialized = 0; + static struct construction_mode_functors functors_0 + = { + &init_cmode_0, + &build_cad_cmode_0, + &build_footprint_cmode_0, + &export_stl_cmode_0, + &release_cad_cmode_0 + }; + (void)parsed_data; + + if(!building || !allocator || !parsed_data || !catalog) { + res = RES_BAD_ARG; + goto error; + } + + building->construction_mode = mode_0; + building->functors = &functors_0; + building->height = parsed_data->height; + str_init(allocator, &building->name); + building->name_initialized = 1; + str_init(allocator, &dataset_name); + name_initialized = 1; + ERR(str_set(&building->name, parsed_data->name)); + ERR(str_set(&dataset_name, parsed_data->dataset_name)); + + ERR(scpr_polygon_create(allocator, &building->pg)); + ERR(scpr_polygon_setup_indexed_vertices(building->pg, 1, get_nverts, get_pos, + parsed_data)); + dataset = htable_dataset_cmode_0_find(&catalog->catalog_0, &dataset_name); + if (dataset == NULL) { + ERR(logger_print(logger, LOG_ERROR, + "Unknown dataset name: '%s' used by building '%s'.\n", + str_cget(&dataset_name), str_cget(&building->name))); + res = RES_BAD_ARG; + goto error; + } + + building->data = dataset; + +exit: + if(name_initialized) str_release(&dataset_name); + return res; +error: + goto exit; +} + +res_T +build_cad_cmode_0 + (struct building* building, + struct mem_allocator* allocator, + struct logger* logger, + void** cad) +{ + res_T res = RES_OK; + double height; + struct scpr_polygon* pg = NULL; + struct scpr_polygon* pg_int = NULL; + struct dataset_cmode_0* data = NULL; + struct data_cad_cmode_0* data_cad = NULL; + double e_wall; + const char* name; + + if (!building || !allocator || !cad) { + res = RES_BAD_ARG; + goto error; + } + + height = building->height; + pg = building->pg; + data = (struct dataset_cmode_0 *)building->data; + + if (height <= 0 || data->wall_thickness <= 0 || data->floor_thickness <= 0) { + res = RES_BAD_ARG; + goto error; + } + + data_cad = MEM_CALLOC(allocator, 1, sizeof(struct data_cad_cmode_0)); + if(!data_cad) { + res = RES_MEM_ERR; + goto error; + } + + e_wall = data->wall_thickness; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -e_wall, SCPR_JOIN_MITER)); + + /* build floor with pg_int */ + name = str_cget(&building->name); + ERR(build_floor(name, pg_int, building, &data_cad->floor)); + + /* roof is a translated copy of floor */ + ERR(build_roof(name, building, data_cad->floor, &data_cad->roof)); + + /* build wall with pg and pg_int */ + ERR(build_wall(name, pg, pg_int, building, &data_cad->wall)); + + /* build cavity */ + ERR(build_cavity(name, pg_int, building, &data_cad->cavity)); + + ERR(scad_scene_partition()); + + /* build ground/building connection */ + ERR(building_ground_connection(name, pg, e_wall, &data_cad->ground_connection)); + + /* build boundary */ + ERR(build_boundary(name, allocator, data_cad)); + + /* build cavity/floor connectiona*/ + ERR(build_connection(name, allocator, data_cad)); + +exit: + if(pg_int) SCPR(polygon_ref_put(pg_int)); + *(struct data_cad_cmode_0**)cad = data_cad; + return res; +error: + if(data_cad) CHK(RES_OK == release_cad_cmode_0(allocator, logger, data_cad)); + data_cad = NULL; + goto exit; +} + +res_T +build_footprint_cmode_0 + (struct building* building, + struct mem_allocator* allocator, + struct logger* logger, + struct scad_geometry** footprint) +{ + res_T res = RES_OK; + struct scpr_polygon* pg = building->pg; + struct dataset_cmode_0* data = (struct dataset_cmode_0 *)building->data; + double e_wall; + (void)allocator; (void)logger; + + if(!building || ! footprint) { + res = RES_BAD_ARG; + goto error; + } + + e_wall = data->wall_thickness; + + ERR(building_ground_connection(NULL, pg, e_wall, footprint)); + +exit: + return res; +error: + goto exit; +} + +res_T +export_stl_cmode_0 + (void* cad, + struct mem_allocator* allocator, + struct logger* logger, + const int binary) +{ + res_T res = RES_OK; + struct data_cad_cmode_0* data_cad = (struct data_cad_cmode_0*)cad; + size_t i; + (void)allocator; (void)logger; + + if(!cad) { + res = RES_BAD_ARG; + goto error; + } + + /* floor export */ + ERR(scad_stl_export(data_cad->floor, NULL, binary)); + + /* roof export */ + ERR(scad_stl_export(data_cad->roof, NULL, binary)); + + /* wall export */ + ERR(scad_stl_export(data_cad->wall, NULL, binary)); + + /* cavity export */ + ERR(scad_stl_export(data_cad->cavity, NULL, binary)); + + /* connection export */ + for (i = 0; i < data_cad->n_connection; i++) { + ERR(scad_stl_export(data_cad->connection[i], NULL, binary)); + } + + /* boundary export */ + ERR(scad_stl_export(data_cad->boundary, NULL, binary)); + + /* footprint export */ + ERR(scad_stl_export(data_cad->ground_connection, NULL, binary)); + +exit: + return res; +error: + goto exit; +} + +res_T +release_cad_cmode_0 + (struct mem_allocator* allocator, + struct logger* logger, + void* cad) +{ + res_T res = RES_OK; + struct data_cad_cmode_0* data_cad = (struct data_cad_cmode_0 *)cad; + size_t i; + (void)logger; + + if(!allocator || ! cad) { + res = RES_BAD_ARG; + goto error; + } + + if(data_cad->boundary) SCAD(geometry_delete(data_cad->boundary)); + if(data_cad->cavity) SCAD(geometry_delete(data_cad->cavity)); + if(data_cad->floor) SCAD(geometry_delete(data_cad->floor)); + if(data_cad->ground_connection) SCAD(geometry_delete(data_cad->ground_connection)); + if(data_cad->roof) SCAD(geometry_delete(data_cad->roof)); + if(data_cad->wall) SCAD(geometry_delete(data_cad->wall)); + for(i = 0; i < data_cad->n_connection; i++) { + SCAD(geometry_delete(data_cad->connection[i])); + } + MEM_RM(allocator, data_cad->connection); + MEM_RM(allocator, data_cad); + +exit: + return res; +error: + goto exit; +} diff --git a/src/cg_construction_mode_0.h b/src/cg_construction_mode_0.h @@ -0,0 +1,98 @@ +/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA + * Copyright (C) 2022 CNRS + * Copyright (C) 2022 Sorbonne Université + * Copyright (C) 2022 Université Paul Sabatier + * Copyright (C) 2022 |Meso|Star> (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/>. */ + +#ifndef Construction_MODE_0_H +#define Construction_MODE_0_H + +#include <rsys/rsys.h> +#include <rsys/str.h> +#include <rsys/hash_table.h> + +struct scad_geometry; +struct building; +struct mem_allocator; +struct logger; +struct parsed_city_building; +struct catalog; + +/* specific data for construction mode 0 */ +struct dataset_cmode_0 { + double wall_thickness; + double floor_thickness; +}; + +#define HTABLE_NAME dataset_cmode_0 +#define HTABLE_DATA struct dataset_cmode_0 +#define HTABLE_KEY struct str +#define HTABLE_KEY_FUNCTOR_INIT str_init +#define HTABLE_KEY_FUNCTOR_RELEASE str_release +#define HTABLE_KEY_FUNCTOR_COPY str_copy +#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release +#define HTABLE_KEY_FUNCTOR_COPY_AND_CLEAR str_copy_and_clear +#define HTABLE_KEY_FUNCTOR_EQ str_eq +#define HTABLE_KEY_FUNCTOR_HASH str_hash +#include <rsys/hash_table.h> + +struct data_cad_cmode_0 { + struct scad_geometry* wall; + struct scad_geometry* roof; + struct scad_geometry* floor; + struct scad_geometry* cavity; + struct scad_geometry* boundary; + struct scad_geometry** connection; + struct scad_geometry* ground_connection; + size_t n_connection; +}; + +res_T +init_cmode_0 + (struct building* building, + struct mem_allocator* allocator, + struct logger* logger, + struct parsed_city_building* parsed_data, + struct catalog* catalog); + +res_T +build_cad_cmode_0 + (struct building* building, + struct mem_allocator* allocator, + struct logger* logger, + void** cad); + +res_T +build_footprint_cmode_0 + (struct building* building, + struct mem_allocator* allocator, + struct logger* logger, + struct scad_geometry** footprint); + +res_T +export_stl_cmode_0 + (void* cad, + struct mem_allocator* allocator, + struct logger* logger, + const int binary); + +res_T +release_cad_cmode_0 + (struct mem_allocator* allocator, + struct logger* logger, + void* cad); + +#endif /* Construction_MODE_0_H */ diff --git a/src/cg_construction_mode_0_parsing_schemas.h b/src/cg_construction_mode_0_parsing_schemas.h @@ -0,0 +1,87 @@ +/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA + * Copyright (C) 2022 CNRS + * Copyright (C) 2022 Sorbonne Université + * Copyright (C) 2022 Université Paul Sabatier + * Copyright (C) 2022 |Meso|Star> (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/>. */ + +#ifndef FG_MODE0_PARSING_SCHEMAS__ +#define FG_MODE0_PARSING_SCHEMAS__ + +#include <cyaml/cyaml.h> + +struct parsed_dataset_cmode_0 { + char* name; + double wall_thickness; /* must be > 0 */ + double floor_thickness; /* must be > 0 */ +}; + +/********************************************************/ +/* Types used for parsing and to define parsing schemas */ +/********************************************************/ + +struct parsed_catalog_cmode_0 { + struct parsed_dataset_cmode_0* datasets; + size_t datasets_count; +}; + +static const cyaml_schema_field_t dataset_cmode_0_fields_schema[] = { + CYAML_FIELD_STRING_PTR("name", CYAML_FLAG_POINTER, + struct parsed_dataset_cmode_0, name, 0, CYAML_UNLIMITED), + CYAML_FIELD_FLOAT("wall_thickness", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_0, wall_thickness), + CYAML_FIELD_FLOAT("floor_thickness", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_0, floor_thickness), + CYAML_FIELD_END +}; + +static const struct cyaml_schema_value p_dataset_cmode_0_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_dataset_cmode_0, + dataset_cmode_0_fields_schema), +}; + +static const struct cyaml_schema_value dataset_cmode_0_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT, struct parsed_dataset_cmode_0, + dataset_cmode_0_fields_schema), +}; + +static const cyaml_schema_field_t cmode_0_fields_schemas[] = { + CYAML_FIELD_IGNORE("contructive_mode_type", CYAML_FLAG_DEFAULT), + { + .key = "datasets", + .value = { + .type = CYAML_SEQUENCE, + .flags = CYAML_FLAG_POINTER, + .data_size = sizeof(struct parsed_dataset_cmode_0), + .sequence = { + .entry = &dataset_cmode_0_schema, + .min = 1, + .max = CYAML_UNLIMITED, + } + }, + .data_offset = offsetof(struct parsed_catalog_cmode_0, datasets), + .count_size = sizeof(((struct parsed_catalog_cmode_0*)0)->datasets_count), + .count_offset = offsetof(struct parsed_catalog_cmode_0, datasets_count), + }, + CYAML_FIELD_END +}; + +/* Top-level schema. The top level value for the construction mode is a mapping */ +static const cyaml_schema_value_t construction_mode_0_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_catalog_cmode_0, + cmode_0_fields_schemas), +}; + +#endif diff --git a/src/cg_construction_mode_1.c b/src/cg_construction_mode_1.c @@ -0,0 +1,1598 @@ +/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA + * Copyright (C) 2022 CNRS + * Copyright (C) 2022 Sorbonne Université + * Copyright (C) 2022 Université Paul Sabatier + * Copyright (C) 2022 |Meso|Star> (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/>. */ + +#include "cg.h" +#include "cg_building.h" +#include "cg_catalog.h" +#include "cg_city_parsing_schemas.h" +#include "cg_construction_mode.h" +#include "cg_construction_mode_1.h" + +#include <rsys/str.h> +#include <rsys/logger.h> +#include <star/scad.h> +#include <star/scpr.h> + +static res_T +build_floor + (const char* prefix, + struct mem_allocator* allocator, + const struct scpr_polygon* pg, + const struct dataset_cmode_1* data, + struct scad_geometry** floor) +{ + res_T res = RES_OK; + double e_wall = data->wall_thickness; + double e_insulation = data->external_insulation_thickness; + double e_floor = data->floor_thickness; + double offset = 0; + struct scpr_polygon* pg_int = NULL; + size_t nverts = 0; + struct scad_geometry* footprint = NULL; + double d[3] = {0, 0, 0}; + char* floorname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && pg && data && floor); + + if (prefix) { + str_init(allocator, &name); + is_init = 1; + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_S_floor")); + floorname = str_get(&name); + } + + offset = e_wall + e_insulation; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); + + /*footprint*/ + ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); + ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts, &footprint)); + + d[2] = -e_floor; + ERR(scad_geometry_extrude(footprint, floorname, d, floor)); + +exit: + SCAD(geometry_delete(footprint)); + if (is_init) str_release(&name); + if (pg_int) SCPR(polygon_ref_put(pg_int)); + return res; +error: + goto exit; +} + +static res_T +build_wall + (const char* prefix, + const char* suffix, + struct mem_allocator* allocator, + const struct scpr_polygon* pg, + const double height, + const struct dataset_cmode_1* data, + struct scad_geometry** wall) +{ + res_T res = RES_OK; + double e_wall = data->wall_thickness; + double e_insulation = data->external_insulation_thickness; + double offset = 0; + struct scpr_polygon* pg_int = NULL; + struct scpr_polygon* pg_ext = NULL; + size_t nverts = 0; + struct scad_geometry* footprint = NULL; + struct scad_geometry* footprint_int = NULL; + struct scad_geometry* footprint_ext = NULL; + double d[3] = {0, 0, 0}; + char* wallname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && pg && data && wall); + + if (prefix) { + str_init(allocator, &name); + is_init = 1; + ERR(str_set(&name, prefix)); + if (suffix) { + ERR(str_append(&name, "_")); + ERR(str_append(&name, suffix)); + } + wallname = str_get(&name); + } + + offset = e_insulation; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_ext)); + ERR(scpr_offset_polygon(pg_ext, -offset, SCPR_JOIN_MITER)); + + offset = e_wall + e_insulation; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); + + /*wall footprint*/ + ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts)); + ERR(scad_add_polygon( + NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext)); + + ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); + ERR(scad_add_polygon( + NULL, get_position_pg, pg_int, 0, nverts, &footprint_int)); + + ERR(scad_cut_geometries( + NULL, &footprint_ext, 1, &footprint_int, 1, &footprint)); + + d[2] = height; + ERR(scad_geometry_extrude(footprint, wallname, d, wall)); + +exit: + SCAD(geometry_delete(footprint)); + SCAD(geometry_delete(footprint_int)); + SCAD(geometry_delete(footprint_ext)); + if (is_init) str_release(&name); + if (pg_int) SCPR(polygon_ref_put(pg_int)); + if (pg_ext) SCPR(polygon_ref_put(pg_ext)); + return res; +error: + goto exit; +} + +static res_T +build_int_insulation + (const char* prefix, + struct mem_allocator* allocator, + const struct scpr_polygon* pg, + const double height, + const struct dataset_cmode_1* data, + struct scad_geometry* inter_floor, + struct scad_geometry** insulation) +{ + res_T res = RES_OK; + 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; + double e_ext_insulation = data->external_insulation_thickness; + double e_int_insulation = data->internal_insulation_thickness; + double offset = 0; + struct scpr_polygon* pg_int = NULL; + struct scpr_polygon* pg_ext = NULL; + size_t nverts = 0; + struct scad_geometry* footprint = NULL; + struct scad_geometry* footprint_int = NULL; + struct scad_geometry* footprint_ext = NULL; + struct scad_geometry* geom = NULL; + double d[3] = {0, 0, 0}; + char* insulationname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && pg && data && insulation); + + if (prefix) { + str_init(allocator, &name); + is_init = 1; + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_S_int_insulation")); + insulationname = str_get(&name); + } + + offset = e_ext_insulation + e_wall; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_ext)); + ERR(scpr_offset_polygon(pg_ext, -offset, SCPR_JOIN_MITER)); + + offset = e_ext_insulation + e_wall + e_int_insulation; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); + + /* insulation footprint */ + ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts)); + ERR(scad_add_polygon( + NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext)); + + ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); + ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts, &footprint_int)); + + ERR(scad_cut_geometries(NULL, &footprint_ext, 1, &footprint_int, 1, &footprint)); + + d[2] = height - e_roof - attic - e_roof_insulation; + ERR(scad_geometry_extrude(footprint, NULL, d, &geom)); + + if (inter_floor) { + ERR(scad_cut_geometries(insulationname, &geom, 1, &inter_floor, 1, insulation)); + } else { + ERR(scad_geometry_copy(geom, insulationname, insulation)); + } + +exit: + SCAD(geometry_delete(footprint)); + SCAD(geometry_delete(footprint_int)); + SCAD(geometry_delete(footprint_ext)); + SCAD(geometry_delete(geom)); + if (is_init) str_release(&name); + if (pg_int) SCPR(polygon_ref_put(pg_int)); + if (pg_ext) SCPR(polygon_ref_put(pg_ext)); + return res; +error: + goto exit; +} + +static res_T +build_roof + (const char* prefix, + struct mem_allocator* allocator, + const struct scpr_polygon* pg, + const double height, + const struct dataset_cmode_1* data, + struct scad_geometry** roof) +{ + res_T res = RES_OK; + double e_wall = data->wall_thickness; + double e_insulation = data->external_insulation_thickness; + double e_roof = data->roof_thickness; + double offset = 0; + double z_roof = 0; + struct scpr_polygon* pg_int = NULL; + size_t nverts = 0; + struct scad_geometry* footprint = NULL; + double d[3] = {0, 0, 0}; + char* roofname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && pg && data && roof); + + if (prefix) { + str_init(allocator, &name); + is_init = 1; + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_S_roof")); + roofname = str_get(&name); + } + + offset = e_wall + e_insulation; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); + + /*footprint*/ + ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); + z_roof = height - e_roof; + ERR(scad_add_polygon(NULL, get_position_pg, pg_int, z_roof, nverts, &footprint)); + + d[2] = e_roof; + ERR(scad_geometry_extrude(footprint, roofname, d, roof)); + +exit: + SCAD(geometry_delete(footprint)); + if (is_init) str_release(&name); + if (pg_int) SCPR(polygon_ref_put(pg_int)); + return res; +error: + goto exit; +} + +static res_T +build_roof_insulation + (const char* prefix, + struct mem_allocator* allocator, + const struct scpr_polygon* pg, + const double height, + const struct dataset_cmode_1* data, + struct scad_geometry** insulation) +{ + res_T res = RES_OK; + double e_wall = data->wall_thickness; + double e_insulation = data->external_insulation_thickness; + double e_roof = data->roof_thickness; + double attic = data->attic_height; + double e_roof_insulation = data->roof_insulation_thickness; + double offset = 0; + double z_insulation = 0; + struct scpr_polygon* pg_int = NULL; + size_t nverts = 0; + struct scad_geometry* footprint = NULL; + double d[3] = {0, 0, 0}; + char* insulationname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && pg && data && insulation); + + if (prefix) { + str_init(allocator, &name); + is_init = 1; + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_S_roof_insulation")); + insulationname = str_get(&name); + } + + offset = e_wall + e_insulation; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); + + /*footprint*/ + ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); + z_insulation = height - e_roof - attic - e_roof_insulation; + ERR(scad_add_polygon( + NULL, get_position_pg, pg_int, z_insulation, nverts, &footprint)); + + d[2] = e_roof_insulation; + ERR(scad_geometry_extrude(footprint, insulationname, d, insulation)); + +exit: + SCAD(geometry_delete(footprint)); + if (is_init) str_release(&name); + if (pg_int) SCPR(polygon_ref_put(pg_int)); + return res; +error: + goto exit; +} + +static res_T +build_floor_insulation + (const char* prefix, + struct mem_allocator* allocator, + const struct scpr_polygon* pg, + const struct dataset_cmode_1* data, + struct scad_geometry** insulation) +{ + res_T res = RES_OK; + double e_wall = data->wall_thickness; + double e_insulation = data->external_insulation_thickness; + double e_floor = data->floor_thickness; + double e_floor_insulation = data->floor_insulation_thickness; + double offset = 0; + double z_insulation = 0; + struct scpr_polygon* pg_int = NULL; + size_t nverts = 0; + struct scad_geometry* footprint = NULL; + double d[3] = {0, 0, 0}; + char* insulationname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && pg && data && insulation); + + if (prefix) { + str_init(allocator, &name); + is_init = 1; + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_S_floor_insulation")); + insulationname = str_get(&name); + } + + offset = e_wall + e_insulation; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); + + /*footprint*/ + ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); + z_insulation = - e_floor - e_floor_insulation; + ERR(scad_add_polygon( + NULL, get_position_pg, pg_int, z_insulation, nverts, &footprint)); + + d[2] = e_floor_insulation; + ERR(scad_geometry_extrude(footprint, insulationname, d, insulation)); + +exit: + SCAD(geometry_delete(footprint)); + if (is_init) str_release(&name); + if (pg_int) SCPR(polygon_ref_put(pg_int)); + return res; +error: + goto exit; +} + +static res_T +build_inter_floor + (const char* prefix, + struct mem_allocator* allocator, + const struct scpr_polygon* pg, + const double height, + const struct dataset_cmode_1* data, + struct scad_geometry** inter_floor) +{ + res_T res = RES_OK; + size_t i = 0; + size_t floor_n = data->inter_floor_count; + double e_roof = data->roof_thickness; + double e_roof_ins = data->roof_insulation_thickness; + double attic = data->attic_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; + struct darray_geometries floor_array; + double d[3] = {0, 0, 0}; + char* floorname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && pg && data && inter_floor); + + darray_geometries_init(allocator, &floor_array); + + if (prefix) { + str_init(allocator, &name); + is_init = 1; + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_S_inter_floor")); + floorname = str_get(&name); + } + + offset = e_wall + e_insulation; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); + ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); + + h_cavity = height - e_roof - attic - e_roof_ins - (double)floor_n*e_floor; + z_floor = h_cavity/(double)(1 + floor_n); + d[2] = e_floor; + for (i = 0; i < floor_n; i++) { + struct scad_geometry* floor = NULL; + struct scad_geometry* footprint = NULL; + + ERR(scad_add_polygon( + NULL, get_position_pg, pg_int, z_floor, nverts, &footprint)); + ERR(scad_geometry_extrude(footprint, NULL, d, &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); + + 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)); + floor_list = darray_geometries_data_get(&floor_array); + if(floor_list) { + for (i = 0; i < floor_n; i++) { + SCAD(geometry_delete(floor_list[i])); + } + darray_geometries_release(&floor_array); + } + return res; +error: + goto exit; +} + +static res_T +build_ext_insulation + (const char* prefix, + struct mem_allocator* allocator, + const struct scpr_polygon* pg, + const double height, + const struct dataset_cmode_1* data, + struct scad_geometry** insulation) +{ + res_T res = RES_OK; + double e_insulation = data->external_insulation_thickness; + double offset = 0; + struct scpr_polygon* pg_int = NULL; + struct scpr_polygon* pg_ext = NULL; + size_t nverts = 0; + struct scad_geometry* footprint = NULL; + struct scad_geometry* footprint_int = NULL; + struct scad_geometry* footprint_ext = NULL; + double d[3] = {0, 0, 0}; + char* insulationname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && pg && data && insulation); + + if (prefix) { + str_init(allocator, &name); + is_init = 1; + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_S_ext_insulation")); + insulationname = str_get(&name); + } + + offset = e_insulation; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_polygon_create_copy(NULL, pg, &pg_ext)); + ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); + + /*insulation footprint*/ + ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts)); + ERR(scad_add_polygon( + NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext)); + + ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); + ERR(scad_add_polygon( + NULL, get_position_pg, pg_int, 0, nverts, &footprint_int)); + + ERR(scad_cut_geometries( + NULL, &footprint_ext, 1, &footprint_int, 1, &footprint)); + + d[2] = height; + ERR(scad_geometry_extrude(footprint, insulationname, d, insulation)); + +exit: + SCAD(geometry_delete(footprint)); + SCAD(geometry_delete(footprint_int)); + SCAD(geometry_delete(footprint_ext)); + if (is_init) str_release(&name); + if (pg_int) SCPR(polygon_ref_put(pg_int)); + if (pg_ext) SCPR(polygon_ref_put(pg_ext)); + return res; +error: + goto exit; +} + +static res_T +build_crawlspace + (const char* prefix, + struct mem_allocator* allocator, + const struct scpr_polygon* pg, + const struct dataset_cmode_1* data, + struct scad_geometry** crawlspace) +{ + res_T res = RES_OK; + double e_wall = data->wall_thickness; + double e_insulation = data->external_insulation_thickness; + double e_crawl = data->crawl_height; + double e_floor = data->floor_thickness; + double e_floor_insulation = data->floor_insulation_thickness; + double offset = 0; + double z_crawl= 0; + struct scpr_polygon* pg_int = NULL; + size_t nverts = 0; + struct scad_geometry* footprint = NULL; + double d[3] = {0, 0, 0}; + char* crawlname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && pg && data && crawlspace); + + if (prefix) { + str_init(allocator, &name); + is_init = 1; + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_F_crawlspace")); + crawlname = str_get(&name); + } + + offset = e_wall + e_insulation; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); + + /*footprint*/ + ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); + z_crawl = - e_floor - e_floor_insulation - e_crawl; + ERR(scad_add_polygon( + NULL, get_position_pg, pg_int, z_crawl, nverts, &footprint)); + + d[2] = e_crawl; + ERR(scad_geometry_extrude(footprint, crawlname, d, crawlspace)); + +exit: + SCAD(geometry_delete(footprint)); + if (is_init) str_release(&name); + if (pg_int) SCPR(polygon_ref_put(pg_int)); + return res; +error: + goto exit; +} + +static res_T +build_habitable + (const char* prefix, + struct mem_allocator* allocator, + const struct scpr_polygon* pg, + const double height, + const struct dataset_cmode_1* data, + struct scad_geometry* floor, + struct scad_geometry** cavity) +{ + res_T res = RES_OK; + double e_wall = data->wall_thickness; + double e_ext_insulation = data->external_insulation_thickness; + 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; + double offset = 0; + struct scpr_polygon* pg_int = NULL; + size_t nverts = 0; + struct scad_geometry* footprint = NULL; + struct scad_geometry* geom = NULL; + double d[3] = {0, 0, 0}; + char* cavityname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && pg && data && cavity); + + if (prefix) { + str_init(allocator, &name); + is_init = 1; + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_F_cavity")); + cavityname = str_get(&name); + } + + offset = e_wall + e_ext_insulation + e_int_insulation; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); + + /*footprint*/ + ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); + ERR(scad_add_polygon( + NULL, get_position_pg, pg_int, 0, nverts, &footprint)); + + d[2] = height - e_roof - e_attic - e_roof_insulation; + ERR(scad_geometry_extrude(footprint, NULL, d, &geom)); + if (floor) { + ERR(scad_cut_geometries( + cavityname, &geom, 1, &floor, 1, cavity)); + } else { + ERR(scad_geometry_copy(geom, cavityname, cavity)); + } + +exit: + SCAD(geometry_delete(footprint)); + SCAD(geometry_delete(geom)); + if (is_init) str_release(&name); + if (pg_int) SCPR(polygon_ref_put(pg_int)); + return res; +error: + goto exit; +} + +static res_T +build_attic + (const char* prefix, + struct mem_allocator* allocator, + const struct scpr_polygon* pg, + const double height, + const struct dataset_cmode_1* data, + struct scad_geometry** attic) +{ + res_T res = RES_OK; + 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; + double offset = 0; + double z_attic = 0; + struct scpr_polygon* pg_int = NULL; + size_t nverts = 0; + struct scad_geometry* footprint = NULL; + double d[3] = {0, 0, 0}; + char* atticname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && pg && data && attic); + + if (prefix) { + str_init(allocator, &name); + is_init = 1; + ERR(str_set(&name, prefix)); + ERR(str_append(&name, "_F_attic")); + atticname = str_get(&name); + } + + offset = e_wall + e_insulation; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); + + /*footprint*/ + ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); + z_attic = height - e_roof - e_attic; + ERR(scad_add_polygon( + NULL, get_position_pg, pg_int, z_attic, nverts, &footprint)); + + d[2] = e_attic; + ERR(scad_geometry_extrude(footprint, atticname, d, attic)); + +exit: + SCAD(geometry_delete(footprint)); + if (is_init) str_release(&name); + if (pg_int) SCPR(polygon_ref_put(pg_int)); + return res; +error: + goto exit; +} + +static res_T +build_windows + (const char* prefix, + struct mem_allocator* allocator, + const struct dataset_cmode_1* data, + struct data_cad_cmode_1* data_cad) +{ + res_T res = RES_OK; + size_t i = 0; + double N[3]; + double dir[3]; + double scale[3]; + 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; + 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]; + + /* windows are build from the vertical faces of habitable cavities */ + ERR(scad_geometry_boundary(NULL, &data_cad->habitable_cavity, 1, &bcavity)); + ERR(scad_geometry_explode(bcavity, NULL, &list, &list_n)); + + for (i = 0; i < list_n; i++) { + double center[3]; + size_t 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)); + + if (N[2] != 0) { + ERR(scad_geometry_delete(surface)); + surface = NULL; + continue; /* keep only vertical face */ + } + + ERR(scad_geometry_dilate(surface, center, scale)); + + dir[0] = 1.1*N[0] * (data->wall_thickness + + data->internal_insulation_thickness + data->external_insulation_thickness); + dir[1] = 1.1*N[1] * (data->wall_thickness + + data->internal_insulation_thickness + data->external_insulation_thickness); + 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)); + 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)); + 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, array_n, &geom)); + ERR(scad_geometry_swap_names(data_cad->wall, geom)); + ERR(scad_geometry_delete(data_cad->wall)); + data_cad->wall = geom; + geom = NULL; + + /* internal insulation perforation */ + if (data_cad->internal_insulation) { + ERR(scad_cut_geometries(NULL, &data_cad->internal_insulation, 1, + 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; + geom = NULL; + } + + /* external insulation perforation */ + if (data_cad->external_insulation) { + ERR(scad_cut_geometries(NULL, &data_cad->external_insulation, 1, + 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; + geom = NULL; + } + + /* build glass */ + if (prefix) { + str_init(allocator, &gname); + is_init = 1; + ERR(str_set(&gname, prefix)); + ERR(str_append(&gname, "_S_glass")); + } + + ERR(scad_fuse_geometries(str_cget(&gname), glass_list, 1, + 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 < 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 <darray_geometries_size_get(&glass_array); i++) { + struct scad_geometry* g = darray_geometries_data_get(&glass_array)[i]; + SCAD(geometry_delete(g)); + } + 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)); + MEM_RM(allocator, list); + if (is_init) str_release(&gname); + return res; +error: + goto exit; +} + +static res_T +build_boundary + (const char* prefix, + struct mem_allocator* allocator, + struct data_cad_cmode_1* data_cad, + 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; + int is_init = 0; + + ASSERT(allocator && prefix && data_cad && boundary); + + darray_geometries_init(allocator, &array); + darray_geometries_init(allocator, &bound_array); + + str_init(allocator, &name); + is_init = 1; + + /* Ensure enough room for all geometries without error nor mem move */ + ERR(darray_geometries_reserve(&array, 14)); + ERR(darray_geometries_push_back(&array, &data_cad->wall)); + ERR(darray_geometries_push_back(&array, &data_cad->roof)); + ERR(darray_geometries_push_back(&array, &data_cad->floor)); + ERR(darray_geometries_push_back(&array, &data_cad->habitable_cavity)); + ERR(darray_geometries_push_back(&array, &data_cad->fake_ground)); + if (data_cad->foundation) { + ERR(darray_geometries_push_back(&array, &data_cad->foundation)); + } + if (data_cad->intermediate_floor) { + ERR(darray_geometries_push_back(&array, &data_cad->intermediate_floor)); + } + if (data_cad->external_insulation) { + ERR(darray_geometries_push_back(&array, &data_cad->external_insulation)); + } + if (data_cad->internal_insulation) { + ERR(darray_geometries_push_back(&array, &data_cad->internal_insulation)); + } + if (data_cad->roof_insulation) { + ERR(darray_geometries_push_back(&array, &data_cad->roof_insulation)); + } + if (data_cad->floor_insulation) { + ERR(darray_geometries_push_back(&array, &data_cad->floor_insulation)); + } + if (data_cad->attic_cavity) { + ERR(darray_geometries_push_back(&array, &data_cad->attic_cavity)); + } + if (data_cad->crawlspace_cavity) { + ERR(darray_geometries_push_back(&array, &data_cad->crawlspace_cavity)); + } + if (data_cad->glass) { + ERR(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, count, + &data_cad->wall, 1, &bound)); + ERR(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, count, + &data_cad->roof, 1, &bound)); + ERR(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, count, + &data_cad->glass, 1, &bound)); + ERR(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, count, + &data_cad->external_insulation, 1, &bound)); + ERR(darray_geometries_push_back(boundary, &bound)); + } + + if (data_cad->internal_insulation) { + 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, count, + &data_cad->internal_insulation, 1, &bound)); + ERR(scad_geometry_get_count(bound, &bcount)); + if (bcount > 0) { + ERR(darray_geometries_push_back(boundary, &bound)); + } else { + SCAD(geometry_delete(bound)); + } + } + +exit: + if (is_init) str_release(&name); + darray_geometries_release(&array); + return res; +error: + goto exit; +} + +static res_T +build_connection + (const char* prefix, + struct mem_allocator* allocator, + struct data_cad_cmode_1* data_cad, + struct darray_geometries* connection) +{ + res_T res = RES_OK; + struct scad_geometry* connect = NULL; + size_t count = 0; + char* cname = NULL; + struct str name; + int is_init = 0; + + ASSERT(allocator && prefix && data_cad && connection); + + str_init(allocator, &name); + is_init = 1; + +#define CREATE_CONNECT(G1,G2,SUFFIX) ERR(str_set(&name, prefix));\ + ERR(str_append(&name, SUFFIX));\ + cname = str_get(&name);\ + ERR(scad_geometries_common_boundaries(cname, &data_cad->G1, 1,\ + &data_cad->G2, 1, &connect));\ + ERR(scad_geometry_get_count(connect, &count)); \ + if (count > 0) { \ + ERR(darray_geometries_push_back(connection, &connect)); \ + } else { \ + SCAD(geometry_delete(connect)); \ + } + + /* -------------------------------------------------------------------------*/ + /* habitable cavity connections */ + /* -------------------------------------------------------------------------*/ + + /* with floor */ + CREATE_CONNECT(habitable_cavity,floor,"_C_cavity_floor"); + + /* with wall */ + CREATE_CONNECT(habitable_cavity,wall,"_C_cavity_wall"); + + /* with glass */ + if (data_cad->glass) { + CREATE_CONNECT(habitable_cavity,glass,"_C_cavity_glass"); + } + + /* with internal insulation */ + if (data_cad->internal_insulation) { + CREATE_CONNECT(habitable_cavity,internal_insulation,"_C_cavity_internal_insulation"); + } + + /* with roof insulation */ + if (data_cad->roof_insulation) { + CREATE_CONNECT(habitable_cavity,roof_insulation,"_C_roof_insulation"); + } else { + /* with roof */ + CREATE_CONNECT(habitable_cavity,roof,"_C_cavity_roof"); + } + + /* with intermediate floor */ + if (data_cad->intermediate_floor) { + CREATE_CONNECT(habitable_cavity,intermediate_floor,"_C_cavity_intermediate_floor"); + } + + /* -------------------------------------------------------------------------*/ + /* crawlspace cavity connections */ + /* -------------------------------------------------------------------------*/ + + if (data_cad->crawlspace_cavity) { + /* with floor insulation */ + if (data_cad->floor_insulation) { + CREATE_CONNECT(crawlspace_cavity, floor_insulation,"_C_crawlspace_insulation"); + } else { + /* with floor */ + CREATE_CONNECT(crawlspace_cavity, floor,"_C_crawlspace_floor"); + } + + /* with wall */ + CREATE_CONNECT(crawlspace_cavity, foundation,"_C_crawlspace_foundation"); + } + + /* -------------------------------------------------------------------------*/ + /* attic cavity connections */ + /* -------------------------------------------------------------------------*/ + + if (data_cad->attic_cavity) { + /* with roof */ + CREATE_CONNECT(attic_cavity, roof,"_C_attic_roof"); + + /* with roof insulation */ + CREATE_CONNECT(attic_cavity, roof_insulation,"_C_attic_insulation"); + + /* with wall */ + CREATE_CONNECT(attic_cavity, wall,"_C_attic_wall"); + } + +#undef CREATE_CONNECT + +exit: + if (is_init) str_release(&name); + return res; +error: + goto exit; +} + +static res_T +build_footprint + (struct scpr_polygon* pg, + struct scad_geometry** footprint) +{ + res_T res = RES_OK; + size_t nverts = 0; + + ASSERT(pg && footprint); + + ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts)); + ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, footprint)); + +exit: + return res; +error: + goto exit; +} + +static res_T +build_fake_ground + (struct mem_allocator* allocator, + struct data_cad_cmode_1* cad, + struct scpr_polygon* pg, + const double depth, + struct scad_geometry** 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 ); + + 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) { + ERR(darray_geometries_push_back(&array, &cad->foundation)); + } + if (cad->crawlspace_cavity) { + ERR(darray_geometries_push_back(&array, &cad->crawlspace_cavity)); + } + if (cad->floor) { + ERR(darray_geometries_push_back(&array, &cad->floor)); + } + if (cad->floor_insulation) { + ERR(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)); + + ERR(build_footprint(pg_offset, &footprint)); + + dir[2] = -depth*1.1; + ERR(scad_geometry_extrude(footprint, NULL, dir, &geom)); + + ERR(scad_cut_geometries(NULL, &geom, 1, list, count, ground)); + +exit: + if (pg_offset) SCPR(polygon_ref_put(pg_offset)); + darray_geometries_release(&array); + if (footprint) SCAD(geometry_delete(footprint)); + if (geom) SCAD(geometry_delete(geom)); + return res; +error: + goto exit; +} + +static res_T +building_ground_connection + (const char* prefix, + struct mem_allocator* allocator, + struct data_cad_cmode_1* cad, + struct scad_geometry** connection) +{ + res_T res = RES_OK; + 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); + + /* Ensure enough room for all geometries without error nor mem move */ + ERR(darray_geometries_reserve(&array, 6)); + if (cad->foundation) { + ERR(darray_geometries_push_back(&array, &cad->foundation)); + } + if (cad->crawlspace_cavity) { + ERR(darray_geometries_push_back(&array, &cad->crawlspace_cavity)); + } + if (cad->floor) { + ERR(darray_geometries_push_back(&array, &cad->floor)); + } + if (cad->floor_insulation) { + ERR(darray_geometries_push_back(&array, &cad->floor_insulation)); + } + if (cad->external_insulation) { + ERR(darray_geometries_push_back(&array, &cad->external_insulation)); + } + if (cad->wall) { + ERR(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: + darray_geometries_release(&array); + if (is_init) str_release(&name); + if (list_boundary) SCAD(geometry_delete(list_boundary)); + if (footprint) SCAD(geometry_delete(footprint)); + return res; +error: + goto exit; +} + +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ + +res_T +init_cmode_1 + (struct building* building, + struct mem_allocator* allocator, + struct logger* logger, + struct parsed_city_building* parsed_data, + struct catalog* catalog) +{ + res_T res = RES_OK; + struct dataset_cmode_1* dataset; + struct str dataset_name; + int name_initialized = 0; + static struct construction_mode_functors functors_1 + = { + &init_cmode_1, + &build_cad_cmode_1, + &build_footprint_cmode_1, + &export_stl_cmode_1, + &release_cad_cmode_1 + }; + (void) parsed_data; + + if(!building || !allocator || !parsed_data ||!catalog) { + res = RES_BAD_ARG; + goto error; + } + + building->construction_mode = mode_1; + building->functors = &functors_1; + building->height = parsed_data->height; + str_init(allocator, &building->name); + building->name_initialized = 1; + str_init(allocator, &dataset_name); + name_initialized = 1; + ERR(str_set(&building->name, parsed_data->name)); + ERR(str_set(&dataset_name, parsed_data->dataset_name)); + + ERR(scpr_polygon_create(allocator, &building->pg)); + ERR(scpr_polygon_setup_indexed_vertices(building->pg, 1, get_nverts, get_pos, + parsed_data)); + dataset = htable_dataset_cmode_1_find(&catalog->catalog_1, &dataset_name); + if (dataset == NULL) { + ERR(logger_print(logger, LOG_ERROR, + "Unknown dataset name: '%s' used by building '%s'.\n", + str_cget(&dataset_name), str_cget(&building->name))); + res = RES_BAD_ARG; + goto error; + } + + building->data = dataset; + +exit: + if(name_initialized) str_release(&dataset_name); + return res; +error: + goto exit; +} + +res_T +build_cad_cmode_1 + (struct building* building, + struct mem_allocator* allocator, + struct logger* logger, + void** cad) +{ + res_T res = RES_OK; + double height = building->height; + double depth = 0; + struct scpr_polygon* pg = building->pg; + struct dataset_cmode_1* data = (struct dataset_cmode_1 *)building->data; + struct data_cad_cmode_1* data_cad = NULL; + const char* name; + + if (!building || !allocator || !cad) { + res = RES_BAD_ARG; + goto error; + } + + data_cad = MEM_CALLOC(allocator, 1, sizeof(struct data_cad_cmode_1)); + if(!data_cad) { + res = RES_MEM_ERR; + goto error; + } + darray_geometries_init(allocator, &data_cad->boundary); + darray_geometries_init(allocator, &data_cad->connection); + + /* build mandatories elements : + - floor + - wall + - roof + */ + + name = str_cget(&building->name); + ERR(build_floor(name, allocator, pg, data, &data_cad->floor)); + + ERR(build_wall(name, "S_wall", allocator, pg, height, data, &data_cad->wall)); + + ERR(build_roof(name, allocator, pg, height, data, &data_cad->roof)); + + /* build optionnal elements : + - foundation + - intermediate floor + - external insulation + - internal insulation + - roof insulation + - floor insulation + */ + + if (data->foundation_depth > 0) { + depth = -data->foundation_depth; + ERR(build_wall(name, "S_foundation", allocator, pg, depth, data, + &data_cad->foundation)); + } + + if (data->inter_floor_count > 0) { + ERR(build_inter_floor(name, allocator, pg, height, data, + &data_cad->intermediate_floor)); + } + + if (data->external_insulation_thickness> 0) { + ERR(build_ext_insulation(name, allocator, pg, height, data, + &data_cad->external_insulation)); + } + + if (data->internal_insulation_thickness> 0) { + ERR(build_int_insulation(name, allocator, pg, height, data, + data_cad->intermediate_floor, &data_cad->internal_insulation)); + } + + if (data->roof_insulation_thickness > 0) { + ERR(build_roof_insulation(name, allocator, pg, height, data, + &data_cad->roof_insulation)); + } + + if (data->floor_insulation_thickness > 0) { + ERR(build_floor_insulation(name, allocator, pg, data, + &data_cad->floor_insulation)); + } + + /* build cavities : + - attic + - habitable + - crawlspace + */ + + if (data->attic_height > 0) { + ERR(build_attic(name, allocator, pg, height, data, &data_cad->attic_cavity)); + } + + ERR(build_habitable(name, allocator, pg, height, data, + data_cad->intermediate_floor, &data_cad->habitable_cavity)); + + if (data->crawl_height > 0) { + ERR(build_crawlspace(name, allocator, pg, data, &data_cad->crawlspace_cavity)); + } + + /* windows */ + if (data->glass_ratio > 0) { + ERR(build_windows(name, allocator, data, 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, depth, + &data_cad->fake_ground)); + + ERR(scad_scene_partition()); + + /* build ground/buildind connection */ + ERR(building_ground_connection(name, allocator, data_cad, + &data_cad->ground_connection)); + + /* build boundaries */ + ERR(build_boundary(name, allocator, data_cad, &data_cad->boundary)); + + /* build connections */ + ERR(build_connection(name, allocator, data_cad, &data_cad->connection)); + +exit: + *(struct data_cad_cmode_1**)cad = data_cad; + return res; +error: + if(data_cad) CHK(RES_OK == release_cad_cmode_1(allocator, logger, data_cad)); + data_cad = NULL; + goto exit; +} + +res_T +build_footprint_cmode_1 + (struct building* building, + struct mem_allocator* allocator, + struct logger* logger, + struct scad_geometry** footprint) +{ + res_T res = RES_OK; + struct scpr_polygon* pg = building->pg; + (void)allocator; (void)logger; + + if (!building || !footprint) { + res = RES_BAD_ARG; + goto error; + } + + ERR(build_footprint(pg, footprint)); + +exit: + return res; +error: + goto exit; +} + +res_T +export_stl_cmode_1 + (void* cad, + struct mem_allocator* allocator, + struct logger* logger, + const int binary) +{ + res_T res = RES_OK; + struct data_cad_cmode_1* data_cad = (struct data_cad_cmode_1 *)cad; + size_t i = 0; + (void)allocator; (void)logger; + + if (!cad) { + res = RES_BAD_ARG; + goto error; + } + + /* floor export */ + ERR(scad_stl_export(data_cad->floor, NULL, binary)); + + /* wall export */ + ERR(scad_stl_export(data_cad->wall, NULL, binary)); + + /* roof export */ + ERR(scad_stl_export(data_cad->roof, NULL, binary)); + + /* foundation export */ + if (data_cad->foundation) { + ERR(scad_stl_export(data_cad->foundation, NULL, binary)); + } + + /* glass export */ + if (data_cad->glass) { + ERR(scad_stl_export(data_cad->glass, NULL, binary)); + } + + /* intermediate floor export*/ + if (data_cad->intermediate_floor) { + ERR(scad_stl_export(data_cad->intermediate_floor, NULL, binary)); + } + + /* internal insulation export*/ + if (data_cad->internal_insulation) { + ERR(scad_stl_export(data_cad->internal_insulation, NULL, binary)); + } + + /* external insulation export*/ + if (data_cad->external_insulation) { + ERR(scad_stl_export(data_cad->external_insulation, NULL, binary)); + } + + /* roof insulation export*/ + if (data_cad->roof_insulation) { + ERR(scad_stl_export(data_cad->roof_insulation, NULL, binary)); + } + + /* floor insulation export*/ + if (data_cad->floor_insulation) { + ERR(scad_stl_export(data_cad->floor_insulation, NULL, binary)); + } + + /* attic cavity export*/ + if (data_cad->attic_cavity) { + ERR(scad_stl_export(data_cad->attic_cavity, NULL, binary)); + } + + /* habitable cavity export*/ + ERR(scad_stl_export(data_cad->habitable_cavity, NULL, binary)); + + /* crawlspace cavity export*/ + if (data_cad->crawlspace_cavity) { + ERR(scad_stl_export(data_cad->crawlspace_cavity, NULL, binary)); + } + + /* boundary export*/ + 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 < 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*/ + ERR(scad_stl_export(data_cad->ground_connection, NULL, binary)); + +exit: + return res; +error: + goto exit; +} + +res_T +release_cad_cmode_1 + (struct mem_allocator* allocator, + struct logger* logger, + void* cad) +{ + res_T res = RES_OK; + struct data_cad_cmode_1* data_cad = (struct data_cad_cmode_1 *)cad; + size_t i; + (void)logger; + + if (!allocator || !cad) { + res = RES_BAD_ARG; + goto error; + } + + if(data_cad->attic_cavity) SCAD(geometry_delete(data_cad->attic_cavity)); + if(data_cad->crawlspace_cavity) SCAD(geometry_delete(data_cad->crawlspace_cavity)); + if(data_cad->external_insulation) SCAD(geometry_delete(data_cad->external_insulation)); + if(data_cad->fake_ground) SCAD(geometry_delete(data_cad->fake_ground)); + if(data_cad->floor) SCAD(geometry_delete(data_cad->floor)); + if(data_cad->floor_insulation) SCAD(geometry_delete(data_cad->floor_insulation)); + if(data_cad->foundation) SCAD(geometry_delete(data_cad->foundation)); + if(data_cad->glass) SCAD(geometry_delete(data_cad->glass)); + if(data_cad->ground_connection) SCAD(geometry_delete(data_cad->ground_connection)); + if(data_cad->habitable_cavity) SCAD(geometry_delete(data_cad->habitable_cavity)); + if(data_cad->intermediate_floor) SCAD(geometry_delete(data_cad->intermediate_floor)); + if(data_cad->internal_insulation) SCAD(geometry_delete(data_cad->internal_insulation)); + if(data_cad->roof) SCAD(geometry_delete(data_cad->roof)); + if(data_cad->roof_insulation) SCAD(geometry_delete(data_cad->roof_insulation)); + if(data_cad->wall) SCAD(geometry_delete(data_cad->wall)); + 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 < 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)); + } + darray_geometries_release(&data_cad->boundary); + darray_geometries_release(&data_cad->connection); + MEM_RM(allocator, data_cad); + +exit: + return res; +error: + goto exit; +} diff --git a/src/cg_construction_mode_1.h b/src/cg_construction_mode_1.h @@ -0,0 +1,124 @@ +/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA + * Copyright (C) 2022 CNRS + * Copyright (C) 2022 Sorbonne Université + * Copyright (C) 2022 Université Paul Sabatier + * Copyright (C) 2022 |Meso|Star> (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/>. */ + +#ifndef Construction_MODE_1_H +#define Construction_MODE_1_H + +#include <rsys/rsys.h> +#include <rsys/str.h> +#include <rsys/hash_table.h> +#include <rsys/dynamic_array.h> + +struct scad_geometry; +struct building; +struct mem_allocator; +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 construction mode 1 */ +struct dataset_cmode_1 { + size_t inter_floor_count; /* can be 0 */ + double wall_thickness; /* must be > 0 */ + double floor_thickness; /* must be > 0 */ + double inter_floor_thickness; /* must be > 0 */ + double roof_thickness; /* must be > 0 */ + double internal_insulation_thickness; /* can be 0 */ + double external_insulation_thickness; /* can be 0 */ + double floor_insulation_thickness; /* can be 0 */ + 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] */ +}; + +#define HTABLE_NAME dataset_cmode_1 +#define HTABLE_DATA struct dataset_cmode_1 +#define HTABLE_KEY struct str +#define HTABLE_KEY_FUNCTOR_INIT str_init +#define HTABLE_KEY_FUNCTOR_RELEASE str_release +#define HTABLE_KEY_FUNCTOR_COPY str_copy +#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release +#define HTABLE_KEY_FUNCTOR_COPY_AND_CLEAR str_copy_and_clear +#define HTABLE_KEY_FUNCTOR_EQ str_eq +#define HTABLE_KEY_FUNCTOR_HASH str_hash +#include <rsys/hash_table.h> + +struct data_cad_cmode_1 { + struct scad_geometry* wall; + struct scad_geometry* roof; + struct scad_geometry* floor; + struct scad_geometry* foundation; /* can be NULL */ + struct scad_geometry* intermediate_floor; /* can be NULL */ + struct scad_geometry* habitable_cavity; + struct scad_geometry* crawlspace_cavity; /* can be NULL */ + struct scad_geometry* attic_cavity; /* can be NULL */ + struct scad_geometry* internal_insulation; /* can be NULL */ + struct scad_geometry* external_insulation; /* can be NULL */ + struct scad_geometry* floor_insulation; /* can be NULL */ + struct scad_geometry* roof_insulation; /* can be NULL */ + struct scad_geometry* glass; + struct scad_geometry* fake_ground;/*not exported, used for ground connection*/ + struct scad_geometry* ground_connection; + struct darray_geometries boundary; + struct darray_geometries connection; + size_t n_connection; +}; + +res_T +init_cmode_1 + (struct building* building, + struct mem_allocator* allocator, + struct logger* logger, + struct parsed_city_building* parsed_data, + struct catalog* catalog); + +res_T +build_cad_cmode_1 + (struct building* building, + struct mem_allocator* allocator, + struct logger* logger, + void** cad); + +res_T +build_footprint_cmode_1 + (struct building* building, + struct mem_allocator* allocator, + struct logger* logger, + struct scad_geometry** footprint); + +res_T +export_stl_cmode_1 + (void* cad, + struct mem_allocator* allocator, + struct logger* logger, + const int binary); + +res_T +release_cad_cmode_1 + (struct mem_allocator* allocator, + struct logger* logger, + void* cad); + +#endif /* Construction_MODE_1_H */ diff --git a/src/cg_construction_mode_1_parsing_schemas.h b/src/cg_construction_mode_1_parsing_schemas.h @@ -0,0 +1,124 @@ +/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA + * Copyright (C) 2022 CNRS + * Copyright (C) 2022 Sorbonne Université + * Copyright (C) 2022 Université Paul Sabatier + * Copyright (C) 2022 |Meso|Star> (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/>. */ + +#ifndef FG_MODE1_PARSING_SCHEMAS__ +#define FG_MODE1_PARSING_SCHEMAS__ + +#include <cyaml/cyaml.h> + +#include <rsys/str.h> + +struct parsed_dataset_cmode_1 { + char* name; + size_t inter_floor_count; /* can be 0 */ + double wall_thickness; /* must be > 0 */ + double floor_thickness; /* must be > 0 */ + double inter_floor_thickness; /* must be > 0 */ + double roof_thickness; /* must be > 0 */ + double internal_insulation_thickness; /* can be 0 */ + double external_insulation_thickness; /* can be 0 */ + double floor_insulation_thickness; /* can be 0 */ + 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] */ +}; + +/********************************************************/ +/* Types used for parsing and to define parsing schemas */ +/********************************************************/ + +struct parsed_catalog_cmode_1 { + struct parsed_dataset_cmode_1* datasets; + size_t datasets_count; +}; + +static const cyaml_schema_field_t dataset_cmode_1_fields_schema[] = { + CYAML_FIELD_STRING_PTR("name", CYAML_FLAG_POINTER, + struct parsed_dataset_cmode_1, name, 0, CYAML_UNLIMITED), + CYAML_FIELD_INT("inter_floor_count", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, inter_floor_count), + CYAML_FIELD_FLOAT("wall_thickness", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, wall_thickness), + CYAML_FIELD_FLOAT("floor_thickness", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, floor_thickness), + CYAML_FIELD_FLOAT("inter_floor_thickness", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, inter_floor_thickness), + CYAML_FIELD_FLOAT("roof_thickness", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, roof_thickness), + CYAML_FIELD_FLOAT("internal_insulation_thickness", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, internal_insulation_thickness), + CYAML_FIELD_FLOAT("external_insulation_thickness", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, external_insulation_thickness), + CYAML_FIELD_FLOAT("floor_insulation_thickness", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, floor_insulation_thickness), + CYAML_FIELD_FLOAT("roof_insulation_thickness", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, roof_insulation_thickness), + CYAML_FIELD_FLOAT("foundation_depth", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, foundation_depth), + CYAML_FIELD_FLOAT("crawl_height", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, crawl_height), + CYAML_FIELD_FLOAT("attic_height", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, attic_height), + CYAML_FIELD_FLOAT("glass_ratio", CYAML_FLAG_DEFAULT, + struct parsed_dataset_cmode_1, glass_ratio), + CYAML_FIELD_END +}; + +static const struct cyaml_schema_value p_dataset_cmode_1_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_dataset_cmode_1, + dataset_cmode_1_fields_schema), +}; + +static const struct cyaml_schema_value dataset_cmode_1_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT, struct parsed_dataset_cmode_1, + dataset_cmode_1_fields_schema), +}; + +static const cyaml_schema_field_t cmode_1_fields_schemas[] = { + CYAML_FIELD_IGNORE("contructive_mode_type", CYAML_FLAG_DEFAULT), + { + .key = "datasets", + .value = { + .type = CYAML_SEQUENCE, + .flags = CYAML_FLAG_POINTER, + .data_size = sizeof(struct parsed_dataset_cmode_1), + .sequence = { + .entry = &dataset_cmode_1_schema, + .min = 1, + .max = CYAML_UNLIMITED, + } + }, + .data_offset = offsetof(struct parsed_catalog_cmode_1, datasets), + .count_size = sizeof(((struct parsed_catalog_cmode_1*)0)->datasets_count), + .count_offset = offsetof(struct parsed_catalog_cmode_1, datasets_count), + }, + CYAML_FIELD_END +}; + +/* Top-level schema. The top level value for the construction mode is a mapping. + * Its fields are defined in cmode_1_fields_schemas. + */ +static const cyaml_schema_value_t construction_mode_1_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_catalog_cmode_1, + cmode_1_fields_schemas), +}; + +#endif diff --git a/src/cg_construction_modes_parsing_schemas.h b/src/cg_construction_modes_parsing_schemas.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA + * Copyright (C) 2022 CNRS + * Copyright (C) 2022 Sorbonne Université + * Copyright (C) 2022 Université Paul Sabatier + * Copyright (C) 2022 |Meso|Star> (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/>. */ + +#ifndef FG_CMODES_PARSING_SCHEMAS__ +#define FG_CMODES_PARSING_SCHEMAS__ + +#include <cyaml/cyaml.h> + +/********************************************************/ +/* Types used for parsing and to define parsing schemas */ +/********************************************************/ + +/* construction mode type */ +enum parsed_cmode_type { + PARSED_CMODE_0, + PARSED_CMODE_1, + PARSED_CMODE_TYPE_UNDEFINED +}; + +/* Mapping from "construction mode type" strings to enum parsed_cmode_type values for + * schema. */ +static const cyaml_strval_t city_building_types_strings[] = { + { "Construction_Mode_0", PARSED_CMODE_0 }, + { "Construction_Mode_1", PARSED_CMODE_1 } +}; + +struct parsed_cmode { + enum parsed_cmode_type cmode_type; +}; + +static const cyaml_schema_field_t construction_mode_fields_schemas[] = { + CYAML_FIELD_ENUM("contructive_mode_type", + CYAML_FLAG_CASE_INSENSITIVE, struct parsed_cmode, cmode_type, + city_building_types_strings, CYAML_ARRAY_LEN(city_building_types_strings)), + CYAML_FIELD_IGNORE("datasets", CYAML_FLAG_DEFAULT), + CYAML_FIELD_END +}; + +/* Top-level schema. The top level value for the construction mode is a mapping */ +static const cyaml_schema_value_t construction_mode_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_cmode, + construction_mode_fields_schemas), +}; + +#endif diff --git a/src/cg_constructive_mode.h b/src/cg_constructive_mode.h @@ -1,54 +0,0 @@ -/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA - * Copyright (C) 2022 CNRS - * Copyright (C) 2022 Sorbonne Université - * Copyright (C) 2022 Université Paul Sabatier - * Copyright (C) 2022 |Meso|Star> (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/>. */ - -#ifndef CONSTRUCTIVE_MODE_H__ -#define CONSTRUCTIVE_MODE_H__ - -#include "cg_city_parsing_schemas.h" - -#include <rsys/rsys.h> -#include <star/scpr.h> - -static void -get_nverts(const size_t icomp, size_t* nverts, void* context) -{ - struct parsed_city_building* parsed_data = context; - ASSERT(icomp == 0); (void)icomp; - *nverts = parsed_data->vertice_count; -} - -static void -get_pos(const size_t icomp, const size_t ivert, double pos[2], void* context) -{ - struct parsed_city_building* parsed_data = context; - ASSERT(icomp == 0); (void)icomp; - pos[0] = parsed_data->vertice[ivert*2 + 0]; - pos[1] = parsed_data->vertice[ivert*2 + 1]; -} - -static void get_position_pg - (const size_t ivert, double pos[2], void* ctx) -{ - struct scpr_polygon* pg = ctx; - ASSERT(pos && pg); - CHK(scpr_polygon_get_position(pg, 0, ivert, pos) == RES_OK); -} - -#endif - diff --git a/src/cg_constructive_mode_0.c b/src/cg_constructive_mode_0.c @@ -1,639 +0,0 @@ -/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA - * Copyright (C) 2022 CNRS - * Copyright (C) 2022 Sorbonne Université - * Copyright (C) 2022 Université Paul Sabatier - * Copyright (C) 2022 |Meso|Star> (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/>. */ - -#include "cg.h" -#include "cg_building.h" -#include "cg_catalog.h" -#include "cg_city.h" -#include "cg_city_parsing_schemas.h" -#include "cg_constructive_mode_0.h" -#include "cg_constructive_mode.h" - -#include <rsys/rsys.h> -#include <rsys/str.h> -#include <rsys/logger.h> -#include <star/scad.h> - -static res_T -build_floor_footprint - (struct scpr_polygon* pg, - struct scad_geometry** footprint) -{ - res_T res = RES_OK; - size_t nverts; - - ASSERT(pg && footprint); - ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts)); - ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, footprint)); - -exit: - return res; -error: - goto exit; -} - -static res_T -build_floor - (const char* prefix, - struct scpr_polygon* pg, - struct building* b, - struct scad_geometry** floor) -{ - res_T res = RES_OK; - double e; - struct dataset_cmode_0* data; - struct scad_geometry* footprint = NULL; - double d[3] = {0, 0, 0}; - char* floorname = NULL; - struct str name; - int is_init = 0; - - ASSERT(pg && b && floor); - - data = (struct dataset_cmode_0*)b->data; - e = data->floor_thickness; - - str_init(NULL, &name); - is_init = 1; - if (prefix) { - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_S_floor")); - floorname = str_get(&name); - } - - ERR(build_floor_footprint(pg, &footprint)); - - d[2] = e; - ERR(scad_geometry_extrude(footprint, floorname, d, floor)); - -exit: - SCAD(geometry_delete(footprint)); - if (is_init) str_release(&name); - return res; -error: - goto exit; -} - -static res_T -build_roof - (const char* prefix, - const struct building* b, - const struct scad_geometry* floor, - struct scad_geometry** roof) -{ - res_T res = RES_OK; - double height; - double e; - double d[3] = {0, 0, 0}; - struct dataset_cmode_0* data; - char* roofname = NULL; - struct str name; - int is_init = 0; - - ASSERT(b && floor && roof); - - str_init(NULL, &name); - is_init = 1; - if (prefix) { - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_S_roof")); - roofname = str_get(&name); - } - - height = b->height; - data = (struct dataset_cmode_0*)b->data; - e = data->floor_thickness; - - ERR(scad_geometry_copy(floor, roofname, roof)); - d[2] = height - e ; - ERR(scad_geometry_translate(*roof, d)); - -exit: - if (is_init) str_release(&name); - return res; -error: - goto exit; -} - -static res_T -build_wall_footprint - (struct scpr_polygon* pg, - struct scpr_polygon* pg_int, - struct scad_geometry** footprint) -{ - res_T res = RES_OK; - struct scad_geometry* polygon = NULL; - struct scad_geometry* polygon_int = NULL; - size_t nverts, nverts_int; - - ASSERT(pg && pg_int && footprint); - - ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts)); - ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, &polygon)); - - ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts_int)); - ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts_int, &polygon_int)); - - ERR(scad_cut_geometries(NULL, &polygon, 1, &polygon_int, 1, footprint)); - -exit: - if(polygon) SCAD(geometry_delete(polygon)); - if(polygon_int) SCAD(geometry_delete(polygon_int)); - return res; -error: - goto exit; -} - -static res_T -build_wall - (const char* prefix, - struct scpr_polygon* pg, - struct scpr_polygon* pg_int, - struct building* b, - struct scad_geometry** wall) -{ - res_T res = RES_OK; - double height; - struct scad_geometry* footprint = NULL; - double d[3] = {0, 0, 0}; - char* wallname = NULL; - struct str name; - int is_init = 0; - - ASSERT(pg && pg_int && b && wall); - - height = b->height; - - str_init(NULL, &name); - is_init = 1; - if (prefix) { - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_S_wall")); - wallname = str_get(&name); - } - - ERR(build_wall_footprint(pg, pg_int, &footprint)); - - d[2] = height; - ERR(scad_geometry_extrude(footprint, wallname, d, wall)); - -exit: - if(footprint) SCAD(geometry_delete(footprint)); - if (is_init) str_release(&name); - return res; -error: - goto exit; -} - -static res_T -build_cavity - (const char* prefix, - struct scpr_polygon* pg, - const struct building* b, - struct scad_geometry** cavity) -{ - res_T res = RES_OK; - double e, height; - struct dataset_cmode_0* data; - double d[3] = {0, 0, 0}; - struct scad_geometry* polygon = NULL; - char* cavityname = NULL; - struct str name; - int is_init = 0; - size_t nverts; - - ASSERT(pg && b && cavity); - - height = b->height; - data = (struct dataset_cmode_0*)b->data; - e = data->floor_thickness; - - str_init(NULL, &name); - is_init = 1; - if (prefix) { - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_F_cavity")); - cavityname = str_get(&name); - } - - ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts)); - ERR(scad_add_polygon(NULL, get_position_pg, pg, e, nverts, &polygon)); - - d[2] = height - e; - ERR(scad_geometry_extrude(polygon, cavityname, d, cavity)); - -exit: - if(polygon) SCAD(geometry_delete(polygon)); - if (is_init) str_release(&name); - return res; -error: - goto exit; -} - -static res_T -build_connection - (const char* prefix, - struct mem_allocator* allocator, - struct data_cad_cmode_0* cad) -{ - res_T res = RES_OK; - char* cname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && cad); - - cad->connection = MEM_CALLOC(allocator, 3, sizeof(struct scad_geometry*)); - if(!cad->connection) { - res = RES_MEM_ERR; - goto error; - } - cad->n_connection = 3; - - /* cavity/floor connection */ - str_init(NULL, &name); - is_init = 1; - if (prefix) { - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_C_cavity_floor")); - cname = str_get(&name); - } - - ERR(scad_geometries_common_boundaries(cname, &cad->cavity, 1, &cad->floor, 1, - &cad->connection[0])); - - /* cavity/wall connection */ - if (prefix) { - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_C_cavity_wall")); - cname = str_get(&name); - } - - ERR(scad_geometries_common_boundaries(cname, &cad->cavity, 1, &cad->wall, 1, - &cad->connection[1])); - - /* cavity/roof connection */ - if (prefix) { - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_C_cavity_roof")); - cname = str_get(&name); - } - - ERR(scad_geometries_common_boundaries(cname, &cad->cavity, 1, &cad->roof, 1, - &cad->connection[2])); - -exit: - if (is_init) str_release(&name); - return res; -error: - goto exit; -} - -static res_T -build_boundary - (const char* prefix, - struct mem_allocator* allocator, - struct data_cad_cmode_0* cad) -{ - res_T res = RES_OK; - struct scad_geometry** list = NULL; - struct scad_geometry* boundary = NULL; - char* cname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && cad); - - list = MEM_ALLOC(allocator, 4 * sizeof(struct scad_geometry*)); - if(!list) { - res = RES_MEM_ERR; - goto error; - } - list[0] = cad->floor; - list[1] = cad->wall; - list[2] = cad->roof; - list[3] = cad->cavity; - - str_init(NULL, &name); - is_init = 1; - if (prefix) { - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_boundary")); - cname = str_get(&name); - } - - ERR(scad_geometry_boundary(NULL, list, 4, &boundary)); - - ERR(scad_cut_geometries(cname, &boundary, 1, &cad->ground_connection, 1, - &cad->boundary)); - -exit: - if(boundary) SCAD(geometry_delete(boundary)); - MEM_RM(allocator, list); - if (is_init) str_release(&name); - return res; -error: - goto exit; -} - -static res_T -building_ground_connection - (const char* prefix, - struct scpr_polygon* pg, - const double e, - struct scad_geometry** connection) -{ - res_T res = RES_OK; - struct scpr_polygon* pg_int = NULL; - struct scad_geometry* geom[2] = { NULL, NULL }; - char* cname = NULL; - struct str name; - int is_init = 0; - - ASSERT(pg && e > 0 && connection); - - if (prefix) { - str_init(NULL, &name); - is_init = 1; - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_C_building_ground")); - cname = str_get(&name); - } - - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_offset_polygon(pg_int, -e, SCPR_JOIN_MITER)); - - ERR(build_wall_footprint(pg, pg_int, &geom[0])); - ERR(build_floor_footprint(pg, &geom[1])); - - ERR(scad_fragment_geometries(cname, &geom[0], 1, &geom[1], 1, connection)); - -exit: - if(is_init) str_release(&name); - if(geom[0]) SCAD(geometry_delete(geom[0])); - if(geom[1]) SCAD(geometry_delete(geom[1])); - if(pg_int) SCPR(polygon_ref_put(pg_int)); - return res; -error: - goto exit; -} - -/*----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ - -res_T -init_cmode_0 - (struct building* building, - struct mem_allocator* allocator, - struct logger* logger, - struct parsed_city_building* parsed_data, - struct catalog* catalog) -{ - res_T res = RES_OK; - struct dataset_cmode_0* dataset; - struct str dataset_name; - int name_initialized = 0; - static struct constructive_mode_functors functors_0 - = { - &init_cmode_0, - &build_cad_cmode_0, - &build_footprint_cmode_0, - &export_stl_cmode_0, - &release_cad_cmode_0 - }; - (void)parsed_data; - - if(!building || !allocator || !parsed_data || !catalog) { - res = RES_BAD_ARG; - goto error; - } - - building->constructive_mode = mode_0; - building->functors = &functors_0; - building->height = parsed_data->height; - str_init(allocator, &building->name); - building->name_initialized = 1; - str_init(allocator, &dataset_name); - name_initialized = 1; - ERR(str_set(&building->name, parsed_data->name)); - ERR(str_set(&dataset_name, parsed_data->dataset_name)); - - ERR(scpr_polygon_create(allocator, &building->pg)); - ERR(scpr_polygon_setup_indexed_vertices(building->pg, 1, get_nverts, get_pos, - parsed_data)); - dataset = htable_dataset_cmode_0_find(&catalog->catalog_0, &dataset_name); - if (dataset == NULL) { - ERR(logger_print(logger, LOG_ERROR, - "Unknown dataset name: '%s' used by building '%s'.\n", - str_cget(&dataset_name), str_cget(&building->name))); - res = RES_BAD_ARG; - goto error; - } - - building->data = dataset; - -exit: - if(name_initialized) str_release(&dataset_name); - return res; -error: - goto exit; -} - -res_T -build_cad_cmode_0 - (struct building* building, - struct mem_allocator* allocator, - struct logger* logger, - void** cad) -{ - res_T res = RES_OK; - double height; - struct scpr_polygon* pg = NULL; - struct scpr_polygon* pg_int = NULL; - struct dataset_cmode_0* data = NULL; - struct data_cad_cmode_0* data_cad = NULL; - double e_wall; - const char* name; - - if (!building || !allocator || !cad) { - res = RES_BAD_ARG; - goto error; - } - - height = building->height; - pg = building->pg; - data = (struct dataset_cmode_0 *)building->data; - - if (height <= 0 || data->wall_thickness <= 0 || data->floor_thickness <= 0) { - res = RES_BAD_ARG; - goto error; - } - - data_cad = MEM_CALLOC(allocator, 1, sizeof(struct data_cad_cmode_0)); - if(!data_cad) { - res = RES_MEM_ERR; - goto error; - } - - e_wall = data->wall_thickness; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_offset_polygon(pg_int, -e_wall, SCPR_JOIN_MITER)); - - /* build floor with pg_int */ - name = str_cget(&building->name); - ERR(build_floor(name, pg_int, building, &data_cad->floor)); - - /* roof is a translated copy of floor */ - ERR(build_roof(name, building, data_cad->floor, &data_cad->roof)); - - /* build wall with pg and pg_int */ - ERR(build_wall(name, pg, pg_int, building, &data_cad->wall)); - - /* build cavity */ - ERR(build_cavity(name, pg_int, building, &data_cad->cavity)); - - ERR(scad_scene_partition()); - - /* build ground/building connection */ - ERR(building_ground_connection(name, pg, e_wall, &data_cad->ground_connection)); - - /* build boundary */ - ERR(build_boundary(name, allocator, data_cad)); - - /* build cavity/floor connectiona*/ - ERR(build_connection(name, allocator, data_cad)); - -exit: - if(pg_int) SCPR(polygon_ref_put(pg_int)); - *(struct data_cad_cmode_0**)cad = data_cad; - return res; -error: - if(data_cad) CHK(RES_OK == release_cad_cmode_0(allocator, logger, data_cad)); - data_cad = NULL; - goto exit; -} - -res_T -build_footprint_cmode_0 - (struct building* building, - struct mem_allocator* allocator, - struct logger* logger, - struct scad_geometry** footprint) -{ - res_T res = RES_OK; - struct scpr_polygon* pg = building->pg; - struct dataset_cmode_0* data = (struct dataset_cmode_0 *)building->data; - double e_wall; - (void)allocator; (void)logger; - - if(!building || ! footprint) { - res = RES_BAD_ARG; - goto error; - } - - e_wall = data->wall_thickness; - - ERR(building_ground_connection(NULL, pg, e_wall, footprint)); - -exit: - return res; -error: - goto exit; -} - -res_T -export_stl_cmode_0 - (void* cad, - struct mem_allocator* allocator, - struct logger* logger, - const int binary) -{ - res_T res = RES_OK; - struct data_cad_cmode_0* data_cad = (struct data_cad_cmode_0*)cad; - size_t i; - (void)allocator; (void)logger; - - if(!cad) { - res = RES_BAD_ARG; - goto error; - } - - /* floor export */ - ERR(scad_stl_export(data_cad->floor, NULL, binary)); - - /* roof export */ - ERR(scad_stl_export(data_cad->roof, NULL, binary)); - - /* wall export */ - ERR(scad_stl_export(data_cad->wall, NULL, binary)); - - /* cavity export */ - ERR(scad_stl_export(data_cad->cavity, NULL, binary)); - - /* connection export */ - for (i = 0; i < data_cad->n_connection; i++) { - ERR(scad_stl_export(data_cad->connection[i], NULL, binary)); - } - - /* boundary export */ - ERR(scad_stl_export(data_cad->boundary, NULL, binary)); - - /* footprint export */ - ERR(scad_stl_export(data_cad->ground_connection, NULL, binary)); - -exit: - return res; -error: - goto exit; -} - -res_T -release_cad_cmode_0 - (struct mem_allocator* allocator, - struct logger* logger, - void* cad) -{ - res_T res = RES_OK; - struct data_cad_cmode_0* data_cad = (struct data_cad_cmode_0 *)cad; - size_t i; - (void)logger; - - if(!allocator || ! cad) { - res = RES_BAD_ARG; - goto error; - } - - if(data_cad->boundary) SCAD(geometry_delete(data_cad->boundary)); - if(data_cad->cavity) SCAD(geometry_delete(data_cad->cavity)); - if(data_cad->floor) SCAD(geometry_delete(data_cad->floor)); - if(data_cad->ground_connection) SCAD(geometry_delete(data_cad->ground_connection)); - if(data_cad->roof) SCAD(geometry_delete(data_cad->roof)); - if(data_cad->wall) SCAD(geometry_delete(data_cad->wall)); - for(i = 0; i < data_cad->n_connection; i++) { - SCAD(geometry_delete(data_cad->connection[i])); - } - MEM_RM(allocator, data_cad->connection); - MEM_RM(allocator, data_cad); - -exit: - return res; -error: - goto exit; -} diff --git a/src/cg_constructive_mode_0.h b/src/cg_constructive_mode_0.h @@ -1,98 +0,0 @@ -/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA - * Copyright (C) 2022 CNRS - * Copyright (C) 2022 Sorbonne Université - * Copyright (C) 2022 Université Paul Sabatier - * Copyright (C) 2022 |Meso|Star> (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/>. */ - -#ifndef CONSTRUCTIVE_MODE_0_H -#define CONSTRUCTIVE_MODE_0_H - -#include <rsys/rsys.h> -#include <rsys/str.h> -#include <rsys/hash_table.h> - -struct scad_geometry; -struct building; -struct mem_allocator; -struct logger; -struct parsed_city_building; -struct catalog; - -/* specific data for constructive mode 0 */ -struct dataset_cmode_0 { - double wall_thickness; - double floor_thickness; -}; - -#define HTABLE_NAME dataset_cmode_0 -#define HTABLE_DATA struct dataset_cmode_0 -#define HTABLE_KEY struct str -#define HTABLE_KEY_FUNCTOR_INIT str_init -#define HTABLE_KEY_FUNCTOR_RELEASE str_release -#define HTABLE_KEY_FUNCTOR_COPY str_copy -#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release -#define HTABLE_KEY_FUNCTOR_COPY_AND_CLEAR str_copy_and_clear -#define HTABLE_KEY_FUNCTOR_EQ str_eq -#define HTABLE_KEY_FUNCTOR_HASH str_hash -#include <rsys/hash_table.h> - -struct data_cad_cmode_0 { - struct scad_geometry* wall; - struct scad_geometry* roof; - struct scad_geometry* floor; - struct scad_geometry* cavity; - struct scad_geometry* boundary; - struct scad_geometry** connection; - struct scad_geometry* ground_connection; - size_t n_connection; -}; - -res_T -init_cmode_0 - (struct building* building, - struct mem_allocator* allocator, - struct logger* logger, - struct parsed_city_building* parsed_data, - struct catalog* catalog); - -res_T -build_cad_cmode_0 - (struct building* building, - struct mem_allocator* allocator, - struct logger* logger, - void** cad); - -res_T -build_footprint_cmode_0 - (struct building* building, - struct mem_allocator* allocator, - struct logger* logger, - struct scad_geometry** footprint); - -res_T -export_stl_cmode_0 - (void* cad, - struct mem_allocator* allocator, - struct logger* logger, - const int binary); - -res_T -release_cad_cmode_0 - (struct mem_allocator* allocator, - struct logger* logger, - void* cad); - -#endif /* CONSTRUCTIVE_MODE_0_H */ diff --git a/src/cg_constructive_mode_0_parsing_schemas.h b/src/cg_constructive_mode_0_parsing_schemas.h @@ -1,87 +0,0 @@ -/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA - * Copyright (C) 2022 CNRS - * Copyright (C) 2022 Sorbonne Université - * Copyright (C) 2022 Université Paul Sabatier - * Copyright (C) 2022 |Meso|Star> (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/>. */ - -#ifndef FG_MODE0_PARSING_SCHEMAS__ -#define FG_MODE0_PARSING_SCHEMAS__ - -#include <cyaml/cyaml.h> - -struct parsed_dataset_cmode_0 { - char* name; - double wall_thickness; /* must be > 0 */ - double floor_thickness; /* must be > 0 */ -}; - -/********************************************************/ -/* Types used for parsing and to define parsing schemas */ -/********************************************************/ - -struct parsed_catalog_cmode_0 { - struct parsed_dataset_cmode_0* datasets; - size_t datasets_count; -}; - -static const cyaml_schema_field_t dataset_cmode_0_fields_schema[] = { - CYAML_FIELD_STRING_PTR("name", CYAML_FLAG_POINTER, - struct parsed_dataset_cmode_0, name, 0, CYAML_UNLIMITED), - CYAML_FIELD_FLOAT("wall_thickness", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_0, wall_thickness), - CYAML_FIELD_FLOAT("floor_thickness", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_0, floor_thickness), - CYAML_FIELD_END -}; - -static const struct cyaml_schema_value p_dataset_cmode_0_schema = { - CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_dataset_cmode_0, - dataset_cmode_0_fields_schema), -}; - -static const struct cyaml_schema_value dataset_cmode_0_schema = { - CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT, struct parsed_dataset_cmode_0, - dataset_cmode_0_fields_schema), -}; - -static const cyaml_schema_field_t cmode_0_fields_schemas[] = { - CYAML_FIELD_IGNORE("contructive_mode_type", CYAML_FLAG_DEFAULT), - { - .key = "sets", - .value = { - .type = CYAML_SEQUENCE, - .flags = CYAML_FLAG_POINTER, - .data_size = sizeof(struct parsed_dataset_cmode_0), - .sequence = { - .entry = &dataset_cmode_0_schema, - .min = 1, - .max = CYAML_UNLIMITED, - } - }, - .data_offset = offsetof(struct parsed_catalog_cmode_0, datasets), - .count_size = sizeof(((struct parsed_catalog_cmode_0*)0)->datasets_count), - .count_offset = offsetof(struct parsed_catalog_cmode_0, datasets_count), - }, - CYAML_FIELD_END -}; - -/* Top-level schema. The top level value for the constructive mode is a mapping */ -static const cyaml_schema_value_t constructive_mode_0_schema = { - CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_catalog_cmode_0, - cmode_0_fields_schemas), -}; - -#endif diff --git a/src/cg_constructive_mode_1.c b/src/cg_constructive_mode_1.c @@ -1,1598 +0,0 @@ -/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA - * Copyright (C) 2022 CNRS - * Copyright (C) 2022 Sorbonne Université - * Copyright (C) 2022 Université Paul Sabatier - * Copyright (C) 2022 |Meso|Star> (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/>. */ - -#include "cg.h" -#include "cg_building.h" -#include "cg_catalog.h" -#include "cg_city_parsing_schemas.h" -#include "cg_constructive_mode.h" -#include "cg_constructive_mode_1.h" - -#include <rsys/str.h> -#include <rsys/logger.h> -#include <star/scad.h> -#include <star/scpr.h> - -static res_T -build_floor - (const char* prefix, - struct mem_allocator* allocator, - const struct scpr_polygon* pg, - const struct dataset_cmode_1* data, - struct scad_geometry** floor) -{ - res_T res = RES_OK; - double e_wall = data->wall_thickness; - double e_insulation = data->external_insulation_thickness; - double e_floor = data->floor_thickness; - double offset = 0; - struct scpr_polygon* pg_int = NULL; - size_t nverts = 0; - struct scad_geometry* footprint = NULL; - double d[3] = {0, 0, 0}; - char* floorname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && pg && data && floor); - - if (prefix) { - str_init(allocator, &name); - is_init = 1; - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_S_floor")); - floorname = str_get(&name); - } - - offset = e_wall + e_insulation; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); - - /*footprint*/ - ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); - ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts, &footprint)); - - d[2] = -e_floor; - ERR(scad_geometry_extrude(footprint, floorname, d, floor)); - -exit: - SCAD(geometry_delete(footprint)); - if (is_init) str_release(&name); - if (pg_int) SCPR(polygon_ref_put(pg_int)); - return res; -error: - goto exit; -} - -static res_T -build_wall - (const char* prefix, - const char* suffix, - struct mem_allocator* allocator, - const struct scpr_polygon* pg, - const double height, - const struct dataset_cmode_1* data, - struct scad_geometry** wall) -{ - res_T res = RES_OK; - double e_wall = data->wall_thickness; - double e_insulation = data->external_insulation_thickness; - double offset = 0; - struct scpr_polygon* pg_int = NULL; - struct scpr_polygon* pg_ext = NULL; - size_t nverts = 0; - struct scad_geometry* footprint = NULL; - struct scad_geometry* footprint_int = NULL; - struct scad_geometry* footprint_ext = NULL; - double d[3] = {0, 0, 0}; - char* wallname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && pg && data && wall); - - if (prefix) { - str_init(allocator, &name); - is_init = 1; - ERR(str_set(&name, prefix)); - if (suffix) { - ERR(str_append(&name, "_")); - ERR(str_append(&name, suffix)); - } - wallname = str_get(&name); - } - - offset = e_insulation; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_ext)); - ERR(scpr_offset_polygon(pg_ext, -offset, SCPR_JOIN_MITER)); - - offset = e_wall + e_insulation; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); - - /*wall footprint*/ - ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts)); - ERR(scad_add_polygon( - NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext)); - - ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); - ERR(scad_add_polygon( - NULL, get_position_pg, pg_int, 0, nverts, &footprint_int)); - - ERR(scad_cut_geometries( - NULL, &footprint_ext, 1, &footprint_int, 1, &footprint)); - - d[2] = height; - ERR(scad_geometry_extrude(footprint, wallname, d, wall)); - -exit: - SCAD(geometry_delete(footprint)); - SCAD(geometry_delete(footprint_int)); - SCAD(geometry_delete(footprint_ext)); - if (is_init) str_release(&name); - if (pg_int) SCPR(polygon_ref_put(pg_int)); - if (pg_ext) SCPR(polygon_ref_put(pg_ext)); - return res; -error: - goto exit; -} - -static res_T -build_int_insulation - (const char* prefix, - struct mem_allocator* allocator, - const struct scpr_polygon* pg, - const double height, - const struct dataset_cmode_1* data, - struct scad_geometry* inter_floor, - struct scad_geometry** insulation) -{ - res_T res = RES_OK; - 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; - double e_ext_insulation = data->external_insulation_thickness; - double e_int_insulation = data->internal_insulation_thickness; - double offset = 0; - struct scpr_polygon* pg_int = NULL; - struct scpr_polygon* pg_ext = NULL; - size_t nverts = 0; - struct scad_geometry* footprint = NULL; - struct scad_geometry* footprint_int = NULL; - struct scad_geometry* footprint_ext = NULL; - struct scad_geometry* geom = NULL; - double d[3] = {0, 0, 0}; - char* insulationname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && pg && data && insulation); - - if (prefix) { - str_init(allocator, &name); - is_init = 1; - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_S_int_insulation")); - insulationname = str_get(&name); - } - - offset = e_ext_insulation + e_wall; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_ext)); - ERR(scpr_offset_polygon(pg_ext, -offset, SCPR_JOIN_MITER)); - - offset = e_ext_insulation + e_wall + e_int_insulation; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); - - /* insulation footprint */ - ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts)); - ERR(scad_add_polygon( - NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext)); - - ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); - ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts, &footprint_int)); - - ERR(scad_cut_geometries(NULL, &footprint_ext, 1, &footprint_int, 1, &footprint)); - - d[2] = height - e_roof - attic - e_roof_insulation; - ERR(scad_geometry_extrude(footprint, NULL, d, &geom)); - - if (inter_floor) { - ERR(scad_cut_geometries(insulationname, &geom, 1, &inter_floor, 1, insulation)); - } else { - ERR(scad_geometry_copy(geom, insulationname, insulation)); - } - -exit: - SCAD(geometry_delete(footprint)); - SCAD(geometry_delete(footprint_int)); - SCAD(geometry_delete(footprint_ext)); - SCAD(geometry_delete(geom)); - if (is_init) str_release(&name); - if (pg_int) SCPR(polygon_ref_put(pg_int)); - if (pg_ext) SCPR(polygon_ref_put(pg_ext)); - return res; -error: - goto exit; -} - -static res_T -build_roof - (const char* prefix, - struct mem_allocator* allocator, - const struct scpr_polygon* pg, - const double height, - const struct dataset_cmode_1* data, - struct scad_geometry** roof) -{ - res_T res = RES_OK; - double e_wall = data->wall_thickness; - double e_insulation = data->external_insulation_thickness; - double e_roof = data->roof_thickness; - double offset = 0; - double z_roof = 0; - struct scpr_polygon* pg_int = NULL; - size_t nverts = 0; - struct scad_geometry* footprint = NULL; - double d[3] = {0, 0, 0}; - char* roofname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && pg && data && roof); - - if (prefix) { - str_init(allocator, &name); - is_init = 1; - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_S_roof")); - roofname = str_get(&name); - } - - offset = e_wall + e_insulation; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); - - /*footprint*/ - ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); - z_roof = height - e_roof; - ERR(scad_add_polygon(NULL, get_position_pg, pg_int, z_roof, nverts, &footprint)); - - d[2] = e_roof; - ERR(scad_geometry_extrude(footprint, roofname, d, roof)); - -exit: - SCAD(geometry_delete(footprint)); - if (is_init) str_release(&name); - if (pg_int) SCPR(polygon_ref_put(pg_int)); - return res; -error: - goto exit; -} - -static res_T -build_roof_insulation - (const char* prefix, - struct mem_allocator* allocator, - const struct scpr_polygon* pg, - const double height, - const struct dataset_cmode_1* data, - struct scad_geometry** insulation) -{ - res_T res = RES_OK; - double e_wall = data->wall_thickness; - double e_insulation = data->external_insulation_thickness; - double e_roof = data->roof_thickness; - double attic = data->attic_height; - double e_roof_insulation = data->roof_insulation_thickness; - double offset = 0; - double z_insulation = 0; - struct scpr_polygon* pg_int = NULL; - size_t nverts = 0; - struct scad_geometry* footprint = NULL; - double d[3] = {0, 0, 0}; - char* insulationname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && pg && data && insulation); - - if (prefix) { - str_init(allocator, &name); - is_init = 1; - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_S_roof_insulation")); - insulationname = str_get(&name); - } - - offset = e_wall + e_insulation; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); - - /*footprint*/ - ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); - z_insulation = height - e_roof - attic - e_roof_insulation; - ERR(scad_add_polygon( - NULL, get_position_pg, pg_int, z_insulation, nverts, &footprint)); - - d[2] = e_roof_insulation; - ERR(scad_geometry_extrude(footprint, insulationname, d, insulation)); - -exit: - SCAD(geometry_delete(footprint)); - if (is_init) str_release(&name); - if (pg_int) SCPR(polygon_ref_put(pg_int)); - return res; -error: - goto exit; -} - -static res_T -build_floor_insulation - (const char* prefix, - struct mem_allocator* allocator, - const struct scpr_polygon* pg, - const struct dataset_cmode_1* data, - struct scad_geometry** insulation) -{ - res_T res = RES_OK; - double e_wall = data->wall_thickness; - double e_insulation = data->external_insulation_thickness; - double e_floor = data->floor_thickness; - double e_floor_insulation = data->floor_insulation_thickness; - double offset = 0; - double z_insulation = 0; - struct scpr_polygon* pg_int = NULL; - size_t nverts = 0; - struct scad_geometry* footprint = NULL; - double d[3] = {0, 0, 0}; - char* insulationname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && pg && data && insulation); - - if (prefix) { - str_init(allocator, &name); - is_init = 1; - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_S_floor_insulation")); - insulationname = str_get(&name); - } - - offset = e_wall + e_insulation; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); - - /*footprint*/ - ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); - z_insulation = - e_floor - e_floor_insulation; - ERR(scad_add_polygon( - NULL, get_position_pg, pg_int, z_insulation, nverts, &footprint)); - - d[2] = e_floor_insulation; - ERR(scad_geometry_extrude(footprint, insulationname, d, insulation)); - -exit: - SCAD(geometry_delete(footprint)); - if (is_init) str_release(&name); - if (pg_int) SCPR(polygon_ref_put(pg_int)); - return res; -error: - goto exit; -} - -static res_T -build_inter_floor - (const char* prefix, - struct mem_allocator* allocator, - const struct scpr_polygon* pg, - const double height, - const struct dataset_cmode_1* data, - struct scad_geometry** inter_floor) -{ - res_T res = RES_OK; - size_t i = 0; - size_t floor_n = data->inter_floor_count; - double e_roof = data->roof_thickness; - double e_roof_ins = data->roof_insulation_thickness; - double attic = data->attic_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; - struct darray_geometries floor_array; - double d[3] = {0, 0, 0}; - char* floorname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && pg && data && inter_floor); - - darray_geometries_init(allocator, &floor_array); - - if (prefix) { - str_init(allocator, &name); - is_init = 1; - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_S_inter_floor")); - floorname = str_get(&name); - } - - offset = e_wall + e_insulation; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); - ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); - - h_cavity = height - e_roof - attic - e_roof_ins - (double)floor_n*e_floor; - z_floor = h_cavity/(double)(1 + floor_n); - d[2] = e_floor; - for (i = 0; i < floor_n; i++) { - struct scad_geometry* floor = NULL; - struct scad_geometry* footprint = NULL; - - ERR(scad_add_polygon( - NULL, get_position_pg, pg_int, z_floor, nverts, &footprint)); - ERR(scad_geometry_extrude(footprint, NULL, d, &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); - - 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)); - floor_list = darray_geometries_data_get(&floor_array); - if(floor_list) { - for (i = 0; i < floor_n; i++) { - SCAD(geometry_delete(floor_list[i])); - } - darray_geometries_release(&floor_array); - } - return res; -error: - goto exit; -} - -static res_T -build_ext_insulation - (const char* prefix, - struct mem_allocator* allocator, - const struct scpr_polygon* pg, - const double height, - const struct dataset_cmode_1* data, - struct scad_geometry** insulation) -{ - res_T res = RES_OK; - double e_insulation = data->external_insulation_thickness; - double offset = 0; - struct scpr_polygon* pg_int = NULL; - struct scpr_polygon* pg_ext = NULL; - size_t nverts = 0; - struct scad_geometry* footprint = NULL; - struct scad_geometry* footprint_int = NULL; - struct scad_geometry* footprint_ext = NULL; - double d[3] = {0, 0, 0}; - char* insulationname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && pg && data && insulation); - - if (prefix) { - str_init(allocator, &name); - is_init = 1; - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_S_ext_insulation")); - insulationname = str_get(&name); - } - - offset = e_insulation; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_polygon_create_copy(NULL, pg, &pg_ext)); - ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); - - /*insulation footprint*/ - ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts)); - ERR(scad_add_polygon( - NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext)); - - ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); - ERR(scad_add_polygon( - NULL, get_position_pg, pg_int, 0, nverts, &footprint_int)); - - ERR(scad_cut_geometries( - NULL, &footprint_ext, 1, &footprint_int, 1, &footprint)); - - d[2] = height; - ERR(scad_geometry_extrude(footprint, insulationname, d, insulation)); - -exit: - SCAD(geometry_delete(footprint)); - SCAD(geometry_delete(footprint_int)); - SCAD(geometry_delete(footprint_ext)); - if (is_init) str_release(&name); - if (pg_int) SCPR(polygon_ref_put(pg_int)); - if (pg_ext) SCPR(polygon_ref_put(pg_ext)); - return res; -error: - goto exit; -} - -static res_T -build_crawlspace - (const char* prefix, - struct mem_allocator* allocator, - const struct scpr_polygon* pg, - const struct dataset_cmode_1* data, - struct scad_geometry** crawlspace) -{ - res_T res = RES_OK; - double e_wall = data->wall_thickness; - double e_insulation = data->external_insulation_thickness; - double e_crawl = data->crawl_height; - double e_floor = data->floor_thickness; - double e_floor_insulation = data->floor_insulation_thickness; - double offset = 0; - double z_crawl= 0; - struct scpr_polygon* pg_int = NULL; - size_t nverts = 0; - struct scad_geometry* footprint = NULL; - double d[3] = {0, 0, 0}; - char* crawlname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && pg && data && crawlspace); - - if (prefix) { - str_init(allocator, &name); - is_init = 1; - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_F_crawlspace")); - crawlname = str_get(&name); - } - - offset = e_wall + e_insulation; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); - - /*footprint*/ - ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); - z_crawl = - e_floor - e_floor_insulation - e_crawl; - ERR(scad_add_polygon( - NULL, get_position_pg, pg_int, z_crawl, nverts, &footprint)); - - d[2] = e_crawl; - ERR(scad_geometry_extrude(footprint, crawlname, d, crawlspace)); - -exit: - SCAD(geometry_delete(footprint)); - if (is_init) str_release(&name); - if (pg_int) SCPR(polygon_ref_put(pg_int)); - return res; -error: - goto exit; -} - -static res_T -build_habitable - (const char* prefix, - struct mem_allocator* allocator, - const struct scpr_polygon* pg, - const double height, - const struct dataset_cmode_1* data, - struct scad_geometry* floor, - struct scad_geometry** cavity) -{ - res_T res = RES_OK; - double e_wall = data->wall_thickness; - double e_ext_insulation = data->external_insulation_thickness; - 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; - double offset = 0; - struct scpr_polygon* pg_int = NULL; - size_t nverts = 0; - struct scad_geometry* footprint = NULL; - struct scad_geometry* geom = NULL; - double d[3] = {0, 0, 0}; - char* cavityname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && pg && data && cavity); - - if (prefix) { - str_init(allocator, &name); - is_init = 1; - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_F_cavity")); - cavityname = str_get(&name); - } - - offset = e_wall + e_ext_insulation + e_int_insulation; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); - - /*footprint*/ - ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); - ERR(scad_add_polygon( - NULL, get_position_pg, pg_int, 0, nverts, &footprint)); - - d[2] = height - e_roof - e_attic - e_roof_insulation; - ERR(scad_geometry_extrude(footprint, NULL, d, &geom)); - if (floor) { - ERR(scad_cut_geometries( - cavityname, &geom, 1, &floor, 1, cavity)); - } else { - ERR(scad_geometry_copy(geom, cavityname, cavity)); - } - -exit: - SCAD(geometry_delete(footprint)); - SCAD(geometry_delete(geom)); - if (is_init) str_release(&name); - if (pg_int) SCPR(polygon_ref_put(pg_int)); - return res; -error: - goto exit; -} - -static res_T -build_attic - (const char* prefix, - struct mem_allocator* allocator, - const struct scpr_polygon* pg, - const double height, - const struct dataset_cmode_1* data, - struct scad_geometry** attic) -{ - res_T res = RES_OK; - 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; - double offset = 0; - double z_attic = 0; - struct scpr_polygon* pg_int = NULL; - size_t nverts = 0; - struct scad_geometry* footprint = NULL; - double d[3] = {0, 0, 0}; - char* atticname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && pg && data && attic); - - if (prefix) { - str_init(allocator, &name); - is_init = 1; - ERR(str_set(&name, prefix)); - ERR(str_append(&name, "_F_attic")); - atticname = str_get(&name); - } - - offset = e_wall + e_insulation; - ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); - ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER)); - - /*footprint*/ - ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts)); - z_attic = height - e_roof - e_attic; - ERR(scad_add_polygon( - NULL, get_position_pg, pg_int, z_attic, nverts, &footprint)); - - d[2] = e_attic; - ERR(scad_geometry_extrude(footprint, atticname, d, attic)); - -exit: - SCAD(geometry_delete(footprint)); - if (is_init) str_release(&name); - if (pg_int) SCPR(polygon_ref_put(pg_int)); - return res; -error: - goto exit; -} - -static res_T -build_windows - (const char* prefix, - struct mem_allocator* allocator, - const struct dataset_cmode_1* data, - struct data_cad_cmode_1* data_cad) -{ - res_T res = RES_OK; - size_t i = 0; - double N[3]; - double dir[3]; - double scale[3]; - 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; - 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]; - - /* windows are build from the vertical faces of habitable cavities */ - ERR(scad_geometry_boundary(NULL, &data_cad->habitable_cavity, 1, &bcavity)); - ERR(scad_geometry_explode(bcavity, NULL, &list, &list_n)); - - for (i = 0; i < list_n; i++) { - double center[3]; - size_t 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)); - - if (N[2] != 0) { - ERR(scad_geometry_delete(surface)); - surface = NULL; - continue; /* keep only vertical face */ - } - - ERR(scad_geometry_dilate(surface, center, scale)); - - dir[0] = 1.1*N[0] * (data->wall_thickness - + data->internal_insulation_thickness + data->external_insulation_thickness); - dir[1] = 1.1*N[1] * (data->wall_thickness - + data->internal_insulation_thickness + data->external_insulation_thickness); - 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)); - 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)); - 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, array_n, &geom)); - ERR(scad_geometry_swap_names(data_cad->wall, geom)); - ERR(scad_geometry_delete(data_cad->wall)); - data_cad->wall = geom; - geom = NULL; - - /* internal insulation perforation */ - if (data_cad->internal_insulation) { - ERR(scad_cut_geometries(NULL, &data_cad->internal_insulation, 1, - 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; - geom = NULL; - } - - /* external insulation perforation */ - if (data_cad->external_insulation) { - ERR(scad_cut_geometries(NULL, &data_cad->external_insulation, 1, - 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; - geom = NULL; - } - - /* build glass */ - if (prefix) { - str_init(allocator, &gname); - is_init = 1; - ERR(str_set(&gname, prefix)); - ERR(str_append(&gname, "_S_glass")); - } - - ERR(scad_fuse_geometries(str_cget(&gname), glass_list, 1, - 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 < 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 <darray_geometries_size_get(&glass_array); i++) { - struct scad_geometry* g = darray_geometries_data_get(&glass_array)[i]; - SCAD(geometry_delete(g)); - } - 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)); - MEM_RM(allocator, list); - if (is_init) str_release(&gname); - return res; -error: - goto exit; -} - -static res_T -build_boundary - (const char* prefix, - struct mem_allocator* allocator, - struct data_cad_cmode_1* data_cad, - 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; - int is_init = 0; - - ASSERT(allocator && prefix && data_cad && boundary); - - darray_geometries_init(allocator, &array); - darray_geometries_init(allocator, &bound_array); - - str_init(allocator, &name); - is_init = 1; - - /* Ensure enough room for all geometries without error nor mem move */ - ERR(darray_geometries_reserve(&array, 14)); - ERR(darray_geometries_push_back(&array, &data_cad->wall)); - ERR(darray_geometries_push_back(&array, &data_cad->roof)); - ERR(darray_geometries_push_back(&array, &data_cad->floor)); - ERR(darray_geometries_push_back(&array, &data_cad->habitable_cavity)); - ERR(darray_geometries_push_back(&array, &data_cad->fake_ground)); - if (data_cad->foundation) { - ERR(darray_geometries_push_back(&array, &data_cad->foundation)); - } - if (data_cad->intermediate_floor) { - ERR(darray_geometries_push_back(&array, &data_cad->intermediate_floor)); - } - if (data_cad->external_insulation) { - ERR(darray_geometries_push_back(&array, &data_cad->external_insulation)); - } - if (data_cad->internal_insulation) { - ERR(darray_geometries_push_back(&array, &data_cad->internal_insulation)); - } - if (data_cad->roof_insulation) { - ERR(darray_geometries_push_back(&array, &data_cad->roof_insulation)); - } - if (data_cad->floor_insulation) { - ERR(darray_geometries_push_back(&array, &data_cad->floor_insulation)); - } - if (data_cad->attic_cavity) { - ERR(darray_geometries_push_back(&array, &data_cad->attic_cavity)); - } - if (data_cad->crawlspace_cavity) { - ERR(darray_geometries_push_back(&array, &data_cad->crawlspace_cavity)); - } - if (data_cad->glass) { - ERR(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, count, - &data_cad->wall, 1, &bound)); - ERR(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, count, - &data_cad->roof, 1, &bound)); - ERR(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, count, - &data_cad->glass, 1, &bound)); - ERR(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, count, - &data_cad->external_insulation, 1, &bound)); - ERR(darray_geometries_push_back(boundary, &bound)); - } - - if (data_cad->internal_insulation) { - 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, count, - &data_cad->internal_insulation, 1, &bound)); - ERR(scad_geometry_get_count(bound, &bcount)); - if (bcount > 0) { - ERR(darray_geometries_push_back(boundary, &bound)); - } else { - SCAD(geometry_delete(bound)); - } - } - -exit: - if (is_init) str_release(&name); - darray_geometries_release(&array); - return res; -error: - goto exit; -} - -static res_T -build_connection - (const char* prefix, - struct mem_allocator* allocator, - struct data_cad_cmode_1* data_cad, - struct darray_geometries* connection) -{ - res_T res = RES_OK; - struct scad_geometry* connect = NULL; - size_t count = 0; - char* cname = NULL; - struct str name; - int is_init = 0; - - ASSERT(allocator && prefix && data_cad && connection); - - str_init(allocator, &name); - is_init = 1; - -#define CREATE_CONNECT(G1,G2,SUFFIX) ERR(str_set(&name, prefix));\ - ERR(str_append(&name, SUFFIX));\ - cname = str_get(&name);\ - ERR(scad_geometries_common_boundaries(cname, &data_cad->G1, 1,\ - &data_cad->G2, 1, &connect));\ - ERR(scad_geometry_get_count(connect, &count)); \ - if (count > 0) { \ - ERR(darray_geometries_push_back(connection, &connect)); \ - } else { \ - SCAD(geometry_delete(connect)); \ - } - - /* -------------------------------------------------------------------------*/ - /* habitable cavity connections */ - /* -------------------------------------------------------------------------*/ - - /* with floor */ - CREATE_CONNECT(habitable_cavity,floor,"_C_cavity_floor"); - - /* with wall */ - CREATE_CONNECT(habitable_cavity,wall,"_C_cavity_wall"); - - /* with glass */ - if (data_cad->glass) { - CREATE_CONNECT(habitable_cavity,glass,"_C_cavity_glass"); - } - - /* with internal insulation */ - if (data_cad->internal_insulation) { - CREATE_CONNECT(habitable_cavity,internal_insulation,"_C_cavity_internal_insulation"); - } - - /* with roof insulation */ - if (data_cad->roof_insulation) { - CREATE_CONNECT(habitable_cavity,roof_insulation,"_C_roof_insulation"); - } else { - /* with roof */ - CREATE_CONNECT(habitable_cavity,roof,"_C_cavity_roof"); - } - - /* with intermediate floor */ - if (data_cad->intermediate_floor) { - CREATE_CONNECT(habitable_cavity,intermediate_floor,"_C_cavity_intermediate_floor"); - } - - /* -------------------------------------------------------------------------*/ - /* crawlspace cavity connections */ - /* -------------------------------------------------------------------------*/ - - if (data_cad->crawlspace_cavity) { - /* with floor insulation */ - if (data_cad->floor_insulation) { - CREATE_CONNECT(crawlspace_cavity, floor_insulation,"_C_crawlspace_insulation"); - } else { - /* with floor */ - CREATE_CONNECT(crawlspace_cavity, floor,"_C_crawlspace_floor"); - } - - /* with wall */ - CREATE_CONNECT(crawlspace_cavity, foundation,"_C_crawlspace_foundation"); - } - - /* -------------------------------------------------------------------------*/ - /* attic cavity connections */ - /* -------------------------------------------------------------------------*/ - - if (data_cad->attic_cavity) { - /* with roof */ - CREATE_CONNECT(attic_cavity, roof,"_C_attic_roof"); - - /* with roof insulation */ - CREATE_CONNECT(attic_cavity, roof_insulation,"_C_attic_insulation"); - - /* with wall */ - CREATE_CONNECT(attic_cavity, wall,"_C_attic_wall"); - } - -#undef CREATE_CONNECT - -exit: - if (is_init) str_release(&name); - return res; -error: - goto exit; -} - -static res_T -build_footprint - (struct scpr_polygon* pg, - struct scad_geometry** footprint) -{ - res_T res = RES_OK; - size_t nverts = 0; - - ASSERT(pg && footprint); - - ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts)); - ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, footprint)); - -exit: - return res; -error: - goto exit; -} - -static res_T -build_fake_ground - (struct mem_allocator* allocator, - struct data_cad_cmode_1* cad, - struct scpr_polygon* pg, - const double depth, - struct scad_geometry** 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 ); - - 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) { - ERR(darray_geometries_push_back(&array, &cad->foundation)); - } - if (cad->crawlspace_cavity) { - ERR(darray_geometries_push_back(&array, &cad->crawlspace_cavity)); - } - if (cad->floor) { - ERR(darray_geometries_push_back(&array, &cad->floor)); - } - if (cad->floor_insulation) { - ERR(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)); - - ERR(build_footprint(pg_offset, &footprint)); - - dir[2] = -depth*1.1; - ERR(scad_geometry_extrude(footprint, NULL, dir, &geom)); - - ERR(scad_cut_geometries(NULL, &geom, 1, list, count, ground)); - -exit: - if (pg_offset) SCPR(polygon_ref_put(pg_offset)); - darray_geometries_release(&array); - if (footprint) SCAD(geometry_delete(footprint)); - if (geom) SCAD(geometry_delete(geom)); - return res; -error: - goto exit; -} - -static res_T -building_ground_connection - (const char* prefix, - struct mem_allocator* allocator, - struct data_cad_cmode_1* cad, - struct scad_geometry** connection) -{ - res_T res = RES_OK; - 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); - - /* Ensure enough room for all geometries without error nor mem move */ - ERR(darray_geometries_reserve(&array, 6)); - if (cad->foundation) { - ERR(darray_geometries_push_back(&array, &cad->foundation)); - } - if (cad->crawlspace_cavity) { - ERR(darray_geometries_push_back(&array, &cad->crawlspace_cavity)); - } - if (cad->floor) { - ERR(darray_geometries_push_back(&array, &cad->floor)); - } - if (cad->floor_insulation) { - ERR(darray_geometries_push_back(&array, &cad->floor_insulation)); - } - if (cad->external_insulation) { - ERR(darray_geometries_push_back(&array, &cad->external_insulation)); - } - if (cad->wall) { - ERR(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: - darray_geometries_release(&array); - if (is_init) str_release(&name); - if (list_boundary) SCAD(geometry_delete(list_boundary)); - if (footprint) SCAD(geometry_delete(footprint)); - return res; -error: - goto exit; -} - -/*----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ - -res_T -init_cmode_1 - (struct building* building, - struct mem_allocator* allocator, - struct logger* logger, - struct parsed_city_building* parsed_data, - struct catalog* catalog) -{ - res_T res = RES_OK; - struct dataset_cmode_1* dataset; - struct str dataset_name; - int name_initialized = 0; - static struct constructive_mode_functors functors_1 - = { - &init_cmode_1, - &build_cad_cmode_1, - &build_footprint_cmode_1, - &export_stl_cmode_1, - &release_cad_cmode_1 - }; - (void) parsed_data; - - if(!building || !allocator || !parsed_data ||!catalog) { - res = RES_BAD_ARG; - goto error; - } - - building->constructive_mode = mode_1; - building->functors = &functors_1; - building->height = parsed_data->height; - str_init(allocator, &building->name); - building->name_initialized = 1; - str_init(allocator, &dataset_name); - name_initialized = 1; - ERR(str_set(&building->name, parsed_data->name)); - ERR(str_set(&dataset_name, parsed_data->dataset_name)); - - ERR(scpr_polygon_create(allocator, &building->pg)); - ERR(scpr_polygon_setup_indexed_vertices(building->pg, 1, get_nverts, get_pos, - parsed_data)); - dataset = htable_dataset_cmode_1_find(&catalog->catalog_1, &dataset_name); - if (dataset == NULL) { - ERR(logger_print(logger, LOG_ERROR, - "Unknown dataset name: '%s' used by building '%s'.\n", - str_cget(&dataset_name), str_cget(&building->name))); - res = RES_BAD_ARG; - goto error; - } - - building->data = dataset; - -exit: - if(name_initialized) str_release(&dataset_name); - return res; -error: - goto exit; -} - -res_T -build_cad_cmode_1 - (struct building* building, - struct mem_allocator* allocator, - struct logger* logger, - void** cad) -{ - res_T res = RES_OK; - double height = building->height; - double depth = 0; - struct scpr_polygon* pg = building->pg; - struct dataset_cmode_1* data = (struct dataset_cmode_1 *)building->data; - struct data_cad_cmode_1* data_cad = NULL; - const char* name; - - if (!building || !allocator || !cad) { - res = RES_BAD_ARG; - goto error; - } - - data_cad = MEM_CALLOC(allocator, 1, sizeof(struct data_cad_cmode_1)); - if(!data_cad) { - res = RES_MEM_ERR; - goto error; - } - darray_geometries_init(allocator, &data_cad->boundary); - darray_geometries_init(allocator, &data_cad->connection); - - /* build mandatories elements : - - floor - - wall - - roof - */ - - name = str_cget(&building->name); - ERR(build_floor(name, allocator, pg, data, &data_cad->floor)); - - ERR(build_wall(name, "S_wall", allocator, pg, height, data, &data_cad->wall)); - - ERR(build_roof(name, allocator, pg, height, data, &data_cad->roof)); - - /* build optionnal elements : - - foundation - - intermediate floor - - external insulation - - internal insulation - - roof insulation - - floor insulation - */ - - if (data->foundation_depth > 0) { - depth = -data->foundation_depth; - ERR(build_wall(name, "S_foundation", allocator, pg, depth, data, - &data_cad->foundation)); - } - - if (data->inter_floor_count > 0) { - ERR(build_inter_floor(name, allocator, pg, height, data, - &data_cad->intermediate_floor)); - } - - if (data->external_insulation_thickness> 0) { - ERR(build_ext_insulation(name, allocator, pg, height, data, - &data_cad->external_insulation)); - } - - if (data->internal_insulation_thickness> 0) { - ERR(build_int_insulation(name, allocator, pg, height, data, - data_cad->intermediate_floor, &data_cad->internal_insulation)); - } - - if (data->roof_insulation_thickness > 0) { - ERR(build_roof_insulation(name, allocator, pg, height, data, - &data_cad->roof_insulation)); - } - - if (data->floor_insulation_thickness > 0) { - ERR(build_floor_insulation(name, allocator, pg, data, - &data_cad->floor_insulation)); - } - - /* build cavities : - - attic - - habitable - - crawlspace - */ - - if (data->attic_height > 0) { - ERR(build_attic(name, allocator, pg, height, data, &data_cad->attic_cavity)); - } - - ERR(build_habitable(name, allocator, pg, height, data, - data_cad->intermediate_floor, &data_cad->habitable_cavity)); - - if (data->crawl_height > 0) { - ERR(build_crawlspace(name, allocator, pg, data, &data_cad->crawlspace_cavity)); - } - - /* windows */ - if (data->glass_ratio > 0) { - ERR(build_windows(name, allocator, data, 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, depth, - &data_cad->fake_ground)); - - ERR(scad_scene_partition()); - - /* build ground/buildind connection */ - ERR(building_ground_connection(name, allocator, data_cad, - &data_cad->ground_connection)); - - /* build boundaries */ - ERR(build_boundary(name, allocator, data_cad, &data_cad->boundary)); - - /* build connections */ - ERR(build_connection(name, allocator, data_cad, &data_cad->connection)); - -exit: - *(struct data_cad_cmode_1**)cad = data_cad; - return res; -error: - if(data_cad) CHK(RES_OK == release_cad_cmode_1(allocator, logger, data_cad)); - data_cad = NULL; - goto exit; -} - -res_T -build_footprint_cmode_1 - (struct building* building, - struct mem_allocator* allocator, - struct logger* logger, - struct scad_geometry** footprint) -{ - res_T res = RES_OK; - struct scpr_polygon* pg = building->pg; - (void)allocator; (void)logger; - - if (!building || !footprint) { - res = RES_BAD_ARG; - goto error; - } - - ERR(build_footprint(pg, footprint)); - -exit: - return res; -error: - goto exit; -} - -res_T -export_stl_cmode_1 - (void* cad, - struct mem_allocator* allocator, - struct logger* logger, - const int binary) -{ - res_T res = RES_OK; - struct data_cad_cmode_1* data_cad = (struct data_cad_cmode_1 *)cad; - size_t i = 0; - (void)allocator; (void)logger; - - if (!cad) { - res = RES_BAD_ARG; - goto error; - } - - /* floor export */ - ERR(scad_stl_export(data_cad->floor, NULL, binary)); - - /* wall export */ - ERR(scad_stl_export(data_cad->wall, NULL, binary)); - - /* roof export */ - ERR(scad_stl_export(data_cad->roof, NULL, binary)); - - /* foundation export */ - if (data_cad->foundation) { - ERR(scad_stl_export(data_cad->foundation, NULL, binary)); - } - - /* glass export */ - if (data_cad->glass) { - ERR(scad_stl_export(data_cad->glass, NULL, binary)); - } - - /* intermediate floor export*/ - if (data_cad->intermediate_floor) { - ERR(scad_stl_export(data_cad->intermediate_floor, NULL, binary)); - } - - /* internal insulation export*/ - if (data_cad->internal_insulation) { - ERR(scad_stl_export(data_cad->internal_insulation, NULL, binary)); - } - - /* external insulation export*/ - if (data_cad->external_insulation) { - ERR(scad_stl_export(data_cad->external_insulation, NULL, binary)); - } - - /* roof insulation export*/ - if (data_cad->roof_insulation) { - ERR(scad_stl_export(data_cad->roof_insulation, NULL, binary)); - } - - /* floor insulation export*/ - if (data_cad->floor_insulation) { - ERR(scad_stl_export(data_cad->floor_insulation, NULL, binary)); - } - - /* attic cavity export*/ - if (data_cad->attic_cavity) { - ERR(scad_stl_export(data_cad->attic_cavity, NULL, binary)); - } - - /* habitable cavity export*/ - ERR(scad_stl_export(data_cad->habitable_cavity, NULL, binary)); - - /* crawlspace cavity export*/ - if (data_cad->crawlspace_cavity) { - ERR(scad_stl_export(data_cad->crawlspace_cavity, NULL, binary)); - } - - /* boundary export*/ - 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 < 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*/ - ERR(scad_stl_export(data_cad->ground_connection, NULL, binary)); - -exit: - return res; -error: - goto exit; -} - -res_T -release_cad_cmode_1 - (struct mem_allocator* allocator, - struct logger* logger, - void* cad) -{ - res_T res = RES_OK; - struct data_cad_cmode_1* data_cad = (struct data_cad_cmode_1 *)cad; - size_t i; - (void)logger; - - if (!allocator || !cad) { - res = RES_BAD_ARG; - goto error; - } - - if(data_cad->attic_cavity) SCAD(geometry_delete(data_cad->attic_cavity)); - if(data_cad->crawlspace_cavity) SCAD(geometry_delete(data_cad->crawlspace_cavity)); - if(data_cad->external_insulation) SCAD(geometry_delete(data_cad->external_insulation)); - if(data_cad->fake_ground) SCAD(geometry_delete(data_cad->fake_ground)); - if(data_cad->floor) SCAD(geometry_delete(data_cad->floor)); - if(data_cad->floor_insulation) SCAD(geometry_delete(data_cad->floor_insulation)); - if(data_cad->foundation) SCAD(geometry_delete(data_cad->foundation)); - if(data_cad->glass) SCAD(geometry_delete(data_cad->glass)); - if(data_cad->ground_connection) SCAD(geometry_delete(data_cad->ground_connection)); - if(data_cad->habitable_cavity) SCAD(geometry_delete(data_cad->habitable_cavity)); - if(data_cad->intermediate_floor) SCAD(geometry_delete(data_cad->intermediate_floor)); - if(data_cad->internal_insulation) SCAD(geometry_delete(data_cad->internal_insulation)); - if(data_cad->roof) SCAD(geometry_delete(data_cad->roof)); - if(data_cad->roof_insulation) SCAD(geometry_delete(data_cad->roof_insulation)); - if(data_cad->wall) SCAD(geometry_delete(data_cad->wall)); - 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 < 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)); - } - darray_geometries_release(&data_cad->boundary); - darray_geometries_release(&data_cad->connection); - MEM_RM(allocator, data_cad); - -exit: - return res; -error: - goto exit; -} diff --git a/src/cg_constructive_mode_1.h b/src/cg_constructive_mode_1.h @@ -1,124 +0,0 @@ -/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA - * Copyright (C) 2022 CNRS - * Copyright (C) 2022 Sorbonne Université - * Copyright (C) 2022 Université Paul Sabatier - * Copyright (C) 2022 |Meso|Star> (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/>. */ - -#ifndef CONSTRUCTIVE_MODE_1_H -#define CONSTRUCTIVE_MODE_1_H - -#include <rsys/rsys.h> -#include <rsys/str.h> -#include <rsys/hash_table.h> -#include <rsys/dynamic_array.h> - -struct scad_geometry; -struct building; -struct mem_allocator; -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 */ - double wall_thickness; /* must be > 0 */ - double floor_thickness; /* must be > 0 */ - double inter_floor_thickness; /* must be > 0 */ - double roof_thickness; /* must be > 0 */ - double internal_insulation_thickness; /* can be 0 */ - double external_insulation_thickness; /* can be 0 */ - double floor_insulation_thickness; /* can be 0 */ - 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] */ -}; - -#define HTABLE_NAME dataset_cmode_1 -#define HTABLE_DATA struct dataset_cmode_1 -#define HTABLE_KEY struct str -#define HTABLE_KEY_FUNCTOR_INIT str_init -#define HTABLE_KEY_FUNCTOR_RELEASE str_release -#define HTABLE_KEY_FUNCTOR_COPY str_copy -#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release -#define HTABLE_KEY_FUNCTOR_COPY_AND_CLEAR str_copy_and_clear -#define HTABLE_KEY_FUNCTOR_EQ str_eq -#define HTABLE_KEY_FUNCTOR_HASH str_hash -#include <rsys/hash_table.h> - -struct data_cad_cmode_1 { - struct scad_geometry* wall; - struct scad_geometry* roof; - struct scad_geometry* floor; - struct scad_geometry* foundation; /* can be NULL */ - struct scad_geometry* intermediate_floor; /* can be NULL */ - struct scad_geometry* habitable_cavity; - struct scad_geometry* crawlspace_cavity; /* can be NULL */ - struct scad_geometry* attic_cavity; /* can be NULL */ - struct scad_geometry* internal_insulation; /* can be NULL */ - struct scad_geometry* external_insulation; /* can be NULL */ - struct scad_geometry* floor_insulation; /* can be NULL */ - struct scad_geometry* roof_insulation; /* can be NULL */ - struct scad_geometry* glass; - struct scad_geometry* fake_ground;/*not exported, used for ground connection*/ - struct scad_geometry* ground_connection; - struct darray_geometries boundary; - struct darray_geometries connection; - size_t n_connection; -}; - -res_T -init_cmode_1 - (struct building* building, - struct mem_allocator* allocator, - struct logger* logger, - struct parsed_city_building* parsed_data, - struct catalog* catalog); - -res_T -build_cad_cmode_1 - (struct building* building, - struct mem_allocator* allocator, - struct logger* logger, - void** cad); - -res_T -build_footprint_cmode_1 - (struct building* building, - struct mem_allocator* allocator, - struct logger* logger, - struct scad_geometry** footprint); - -res_T -export_stl_cmode_1 - (void* cad, - struct mem_allocator* allocator, - struct logger* logger, - const int binary); - -res_T -release_cad_cmode_1 - (struct mem_allocator* allocator, - struct logger* logger, - void* cad); - -#endif /* CONSTRUCTIVE_MODE_1_H */ diff --git a/src/cg_constructive_mode_1_parsing_schemas.h b/src/cg_constructive_mode_1_parsing_schemas.h @@ -1,124 +0,0 @@ -/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA - * Copyright (C) 2022 CNRS - * Copyright (C) 2022 Sorbonne Université - * Copyright (C) 2022 Université Paul Sabatier - * Copyright (C) 2022 |Meso|Star> (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/>. */ - -#ifndef FG_MODE1_PARSING_SCHEMAS__ -#define FG_MODE1_PARSING_SCHEMAS__ - -#include <cyaml/cyaml.h> - -#include <rsys/str.h> - -struct parsed_dataset_cmode_1 { - char* name; - size_t inter_floor_count; /* can be 0 */ - double wall_thickness; /* must be > 0 */ - double floor_thickness; /* must be > 0 */ - double inter_floor_thickness; /* must be > 0 */ - double roof_thickness; /* must be > 0 */ - double internal_insulation_thickness; /* can be 0 */ - double external_insulation_thickness; /* can be 0 */ - double floor_insulation_thickness; /* can be 0 */ - 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] */ -}; - -/********************************************************/ -/* Types used for parsing and to define parsing schemas */ -/********************************************************/ - -struct parsed_catalog_cmode_1 { - struct parsed_dataset_cmode_1* datasets; - size_t datasets_count; -}; - -static const cyaml_schema_field_t dataset_cmode_1_fields_schema[] = { - CYAML_FIELD_STRING_PTR("name", CYAML_FLAG_POINTER, - struct parsed_dataset_cmode_1, name, 0, CYAML_UNLIMITED), - CYAML_FIELD_INT("inter_floor_count", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, inter_floor_count), - CYAML_FIELD_FLOAT("wall_thickness", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, wall_thickness), - CYAML_FIELD_FLOAT("floor_thickness", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, floor_thickness), - CYAML_FIELD_FLOAT("inter_floor_thickness", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, inter_floor_thickness), - CYAML_FIELD_FLOAT("roof_thickness", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, roof_thickness), - CYAML_FIELD_FLOAT("internal_insulation_thickness", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, internal_insulation_thickness), - CYAML_FIELD_FLOAT("external_insulation_thickness", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, external_insulation_thickness), - CYAML_FIELD_FLOAT("floor_insulation_thickness", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, floor_insulation_thickness), - CYAML_FIELD_FLOAT("roof_insulation_thickness", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, roof_insulation_thickness), - CYAML_FIELD_FLOAT("foundation_depth", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, foundation_depth), - CYAML_FIELD_FLOAT("crawl_height", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, crawl_height), - CYAML_FIELD_FLOAT("attic_height", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, attic_height), - CYAML_FIELD_FLOAT("glass_ratio", CYAML_FLAG_DEFAULT, - struct parsed_dataset_cmode_1, glass_ratio), - CYAML_FIELD_END -}; - -static const struct cyaml_schema_value p_dataset_cmode_1_schema = { - CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_dataset_cmode_1, - dataset_cmode_1_fields_schema), -}; - -static const struct cyaml_schema_value dataset_cmode_1_schema = { - CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT, struct parsed_dataset_cmode_1, - dataset_cmode_1_fields_schema), -}; - -static const cyaml_schema_field_t cmode_1_fields_schemas[] = { - CYAML_FIELD_IGNORE("contructive_mode_type", CYAML_FLAG_DEFAULT), - { - .key = "sets", - .value = { - .type = CYAML_SEQUENCE, - .flags = CYAML_FLAG_POINTER, - .data_size = sizeof(struct parsed_dataset_cmode_1), - .sequence = { - .entry = &dataset_cmode_1_schema, - .min = 1, - .max = CYAML_UNLIMITED, - } - }, - .data_offset = offsetof(struct parsed_catalog_cmode_1, datasets), - .count_size = sizeof(((struct parsed_catalog_cmode_1*)0)->datasets_count), - .count_offset = offsetof(struct parsed_catalog_cmode_1, datasets_count), - }, - CYAML_FIELD_END -}; - -/* Top-level schema. The top level value for the constructive mode is a mapping. - * Its fields are defined in cmode_1_fields_schemas. - */ -static const cyaml_schema_value_t constructive_mode_1_schema = { - CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_catalog_cmode_1, - cmode_1_fields_schemas), -}; - -#endif diff --git a/src/cg_constructive_modes_parsing_schemas.h b/src/cg_constructive_modes_parsing_schemas.h @@ -1,61 +0,0 @@ -/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA - * Copyright (C) 2022 CNRS - * Copyright (C) 2022 Sorbonne Université - * Copyright (C) 2022 Université Paul Sabatier - * Copyright (C) 2022 |Meso|Star> (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/>. */ - -#ifndef FG_CMODES_PARSING_SCHEMAS__ -#define FG_CMODES_PARSING_SCHEMAS__ - -#include <cyaml/cyaml.h> - -/********************************************************/ -/* Types used for parsing and to define parsing schemas */ -/********************************************************/ - -/* constructive mode type */ -enum parsed_cmode_type { - PARSED_CMODE_0, - PARSED_CMODE_1, - PARSED_CMODE_TYPE_UNDEFINED -}; - -/* Mapping from "constructive mode type" strings to enum parsed_cmode_type values for - * schema. */ -static const cyaml_strval_t city_building_types_strings[] = { - { "Constructive_Mode_0", PARSED_CMODE_0 }, - { "Constructive_Mode_1", PARSED_CMODE_1 } -}; - -struct parsed_cmode { - enum parsed_cmode_type cmode_type; -}; - -static const cyaml_schema_field_t constructive_mode_fields_schemas[] = { - CYAML_FIELD_ENUM("contructive_mode_type", - CYAML_FLAG_CASE_INSENSITIVE, struct parsed_cmode, cmode_type, - city_building_types_strings, CYAML_ARRAY_LEN(city_building_types_strings)), - CYAML_FIELD_IGNORE("sets", CYAML_FLAG_DEFAULT), - CYAML_FIELD_END -}; - -/* Top-level schema. The top level value for the constructive mode is a mapping */ -static const cyaml_schema_value_t constructive_mode_schema = { - CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_cmode, - constructive_mode_fields_schemas), -}; - -#endif diff --git a/src/cg_main.c b/src/cg_main.c @@ -24,8 +24,8 @@ #include "cg_city_parsing.h" #include "cg_catalog.h" #include "cg_catalog_parsing.h" -#include "cg_constructive_mode_0_parsing_schemas.h" -#include "cg_constructive_mode_1_parsing_schemas.h" +#include "cg_construction_mode_0_parsing_schemas.h" +#include "cg_construction_mode_1_parsing_schemas.h" #include <cyaml/cyaml.h>