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 d586516b973d19f472d97256d4605250fce34797
parent e26c0b1c7d435b81ebf582ec253626c46baacc3f
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Mon,  9 Jan 2023 12:11:08 +0100

Replace hard-coded catalog by yaml files parsing

Diffstat:
Mcmake/CMakeLists.txt | 4++++
Msrc/cg.h | 44++++++++++++++++++++++++++++++++++++++++++++
Msrc/cg_args.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/cg_args.h | 24+++++++++++++++++-------
Msrc/cg_building.h | 50++++++++++----------------------------------------
Asrc/cg_catalog.c | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_catalog.h | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/cg_catalog_parsing.c | 162++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/cg_catalog_parsing.h | 41+++++++++++++++++++++++++++++++++--------
Msrc/cg_city.c | 41++++++++++++++++++-----------------------
Msrc/cg_city.h | 38++++++--------------------------------
Msrc/cg_city_parsing.c | 45++++++++++++---------------------------------
Msrc/cg_city_parsing.h | 2+-
Msrc/cg_city_parsing_schemas.h | 18++++--------------
Msrc/cg_constructive_mode_0.c | 88+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/cg_constructive_mode_0.h | 44++++++++++++++++++++++++++++++++------------
Asrc/cg_constructive_mode_0_parsing_schemas.h | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/cg_constructive_mode_1.c | 204+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/cg_constructive_mode_1.h | 62+++++++++++++++++++++++++++++++++++++++++---------------------
Asrc/cg_constructive_mode_1_parsing_schemas.h | 132+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_constructive_modes_parsing_schemas.h | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/cg_main.c | 74+++++++++++++++++++++++++++++++++++++++++++-------------------------------
22 files changed, 1042 insertions(+), 455 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -54,6 +54,7 @@ set(CG2_VERSION ${CG2_VERSION_MAJOR}.${CG2_VERSION_MINOR}.${CG2_VERSION_PATCH}) set(CG2_FILES_SRC cg_args.c + cg_catalog.c cg_catalog_parsing.c cg_city.c cg_city_parsing.c @@ -66,13 +67,16 @@ set(CG2_FILES_INC cg.h cg_args.h cg_building.h + cg_catalog.h cg_catalog_parsing.h 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_default.h.in cg_ground.h cg_version.h.in) diff --git a/src/cg.h b/src/cg.h @@ -20,7 +20,51 @@ #ifndef CG_H #define CG_H +#include <rsys/rsys.h> +#include <cyaml/cyaml.h> + #define ERR(Expr) if((res = (Expr)) != RES_OK) goto error; else (void)0 +static INLINE void +log_prt_fn(const char* msg, void* ctx) +{ + ASSERT(msg); + (void)ctx; + + fprintf(stderr, "\x1b[32moutput:\x1b[0m %s", msg); +} + +static INLINE void +log_warn_fn(const char* msg, void* ctx) +{ + ASSERT(msg); + (void)ctx; + + fprintf(stderr, "\x1b[33mwarning:\x1b[0m %s", msg); +} + +static INLINE void +log_err_fn(const char* msg, void* ctx) +{ + ASSERT(msg); + (void)ctx; + + fprintf(stderr, "\x1b[31merror:\x1b[0m %s", msg); +} + +static INLINE res_T +cyaml_err_to_res_T(const cyaml_err_t err) +{ + res_T res = RES_OK; + + switch(err) { + case CYAML_OK: res = RES_OK; break; + case CYAML_ERR_OOM: res = RES_MEM_ERR; break; + case CYAML_ERR_FILE_OPEN: res = RES_IO_ERR; break; + default: res = RES_UNKNOWN_ERR; break; + } + return res; +} + #endif /*CG_H*/ diff --git a/src/cg_args.c b/src/cg_args.c @@ -18,6 +18,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "cg_args.h" +#include "cg_catalog_parsing.h" #include "cg_version.h" #include "cg_default.h" #include "cg.h" @@ -41,17 +42,18 @@ short_help(void) { print_version(); printf("\nUsage:\n" - "city_generator2 [-a] -b <FILENAME> -c <FILENAME> [-V verbosity]\n" + "city_generator2 -m <FILENAME> -c <FILENAME> [-V verbosity]\n" "city_generator2 [-h]\n" "city_generator2 [-v]\n" ); printf( "\nMandatory options\n" "-----------------\n" - "-b <construction_mode_filename>\n" - " Read a yaml text file that describes the building.\n" - "-c <city_filename>\n" - " Read a yaml text file that describes the city.\n" + "-c <filename>\n" + " Read a yaml text file containing datasets for a given constructive mode.\n" + " Can be used more than once.\n" + "-m <city_map_filename>\n" + " Read a yaml text file that describes the city map.\n" "\nOther options\n" "-------------\n" "-h\n" @@ -80,19 +82,35 @@ short_help(void) res_T parse_args - (struct logger* logger, + (struct mem_allocator* allocator, + struct logger* logger, int argc, char** argv, - struct args* args) + struct args** out_args) { res_T res = RES_OK; int opt; - int info_provided = 0, b_provided = 0, c_provided = 0; - struct args aaa = ARGS_NULL__; - const char option_list[] = "b:c:f:hvV:"; + int info_provided = 0, c_provided = 0, m_provided = 0; + struct args* args; + const char option_list[] = "c:m:f:hvV:"; + + ASSERT(allocator && logger && argv && out_args); + + args = MEM_ALLOC(allocator, sizeof(*args)); + if(!args) { + res = RES_MEM_ERR; + goto error; + } + args->allocator = allocator; + args->logger = logger; /* Set default values */ - *args = aaa; + args->city_filename = NULL; + darray_catalog_filenames_init(allocator, &args->catalog_filenames); + args->binary_export = CG2_BINARY_EXPORT_DEFAULT; + args->verbosity_level = CG2_DEFAULT_VERBOSE_LEVEL; + args->print_help = 0; + args->print_version = 0; opterr = 0; /* No default error messages */ while((opt = getopt(argc, argv, option_list)) != -1) { @@ -113,24 +131,19 @@ parse_args goto error; } - case 'b': - if(b_provided) { - logger_print(logger, LOG_ERROR, "Option -%c provided twice.\n", opt); - res = RES_BAD_ARG; - goto error; - } - args->constructive_mode_filename = optarg; - b_provided = 1; + case 'c': + c_provided = 1; + ERR(darray_catalog_filenames_push_back(&args->catalog_filenames, &optarg)); break; - case 'c': - if(c_provided) { + case 'm': + if(m_provided) { logger_print(logger, LOG_ERROR, "Option -%c provided twice.\n", opt); res = RES_BAD_ARG; goto error; } args->city_filename = optarg; - c_provided = 1; + m_provided = 1; break; case 'f': @@ -183,14 +196,14 @@ parse_args goto error; } - if(!b_provided && !info_provided) { + if(!c_provided && !info_provided) { ERR(logger_print(logger, LOG_ERROR, "Missing mandatory argument: -b <construction_mode_filename>\n")); res = RES_BAD_ARG; goto error; } - if(!c_provided && !info_provided) { + if(!m_provided && !info_provided) { ERR(logger_print(logger, LOG_ERROR, "Missing mandatory argument: -c <city_filename>\n")); res = RES_BAD_ARG; @@ -198,7 +211,20 @@ parse_args } exit: + *out_args = args; return res; error: + release_args(args); + args = NULL; goto exit; } + +void +release_args + (struct args* args) +{ + if(!args) return; + + darray_catalog_filenames_release(&args->catalog_filenames); + MEM_RM(args->allocator, args); +} diff --git a/src/cg_args.h b/src/cg_args.h @@ -20,27 +20,37 @@ #ifndef PARSE_ARGS_H #define PARSE_ARGS_H -#include "cg_default.h" - #include <rsys/rsys.h> +#include <rsys/dynamic_array.h> struct logger; -struct args; +#define DARRAY_NAME catalog_filenames +#define DARRAY_DATA char* +#include <rsys/dynamic_array.h> struct args { + struct mem_allocator* allocator; + struct logger* logger; char* city_filename; - char* constructive_mode_filename; + struct darray_catalog_filenames catalog_filenames; int binary_export; int verbosity_level; int print_help; int print_version; }; -#define ARGS_NULL__ \ - { NULL, NULL, CG2_BINARY_EXPORT_DEFAULT, CG2_DEFAULT_VERBOSE_LEVEL, 0, 0 } res_T -parse_args(struct logger* logger, int argc, char** argv, struct args* args); +parse_args + (struct mem_allocator* allocator, + struct logger* logger, + int argc, + char** argv, + struct args** out_args); + +void +release_args + (struct args* args); void print_version(void); diff --git a/src/cg_building.h b/src/cg_building.h @@ -24,30 +24,34 @@ #include <rsys/str.h> #include <rsys/hash_table.h> -/* The specific constructive modes headers must be included here. */ #include "cg_constructive_mode_0.h" #include "cg_constructive_mode_1.h" struct scpr_polygon; struct scad_geometry; struct mem_allocator; +struct logger; +struct catalog; /* A type to store the functors of a constructive mode */ struct constructive_mode_functors { res_T (*init) (struct building* building, struct mem_allocator* allocator, + struct logger* logger, struct parsed_city_building* parsed_data, - struct htable_parameter_set* catalog); + struct catalog* catalog); res_T (*build_cad) - (struct building* building, struct mem_allocator* allocator, void** cad); + (struct building* building, struct mem_allocator* allocator, + struct logger* logger, void** cad); res_T (*build_footprint) (struct building* building, struct mem_allocator* allocator, - struct scad_geometry** footprint); + struct logger* logger, struct scad_geometry** footprint); res_T (*export_stl) - (void* cad, const int binary); + (void* cad, struct mem_allocator* allocator, struct logger* logger, + const int binary); res_T (*release_cad) - (struct mem_allocator* allocator, void* cad); + (struct mem_allocator* allocator, struct logger* logger, void* cad); }; /* A type to give an ID to constructive modes. @@ -61,40 +65,6 @@ enum constructive_mode_type { /* The name of the constructive modes, as expected in the city description. */ extern char const* constructive_mode_name[CONSTRUCTIVE_MODES_COUNT__]; -/* A type to store the parameter sets. - * As each constructive mode has its own parameters, the actual struct is hidden - * behind a void* data pointer. */ -struct parameter_set { - enum constructive_mode_type constructive_mode; - struct str name; - void* data; -}; - -/* Utility function to define a hash table */ -static INLINE char -eq_str(const struct str* a, const struct str* b) -{ - return !strcmp(str_cget(a), str_cget(b)); -} - -static INLINE size_t -hash_str(const struct str* a) -{ - return hash_fnv32(str_cget(a), str_len(a)); -} - -/* A hash table to store building parameter-sets by name */ -#define HTABLE_NAME parameter_set -#define HTABLE_DATA struct parameter_set -#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_EQ eq_str -#define HTABLE_KEY_FUNCTOR_HASH hash_str -#include <rsys/hash_table.h> - /* The type of buildings as described in the city description */ struct building { /* constructive mode */ diff --git a/src/cg_catalog.c b/src/cg_catalog.c @@ -0,0 +1,141 @@ +/* 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_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 <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/logger.h> +#include <rsys/str.h> + +res_T +create_catalog + (struct mem_allocator* allocator, + struct logger* logger, + struct parsed_catalog* parsed_catalog, + struct catalog** out_catalog) +{ + res_T res = RES_OK; + size_t i, j, count; + const struct parsed_catalog_items* items; + struct catalog* catalog; + struct str name; + int name_initialized = 0; + + ASSERT(allocator && logger && parsed_catalog && out_catalog); + + catalog = MEM_ALLOC(allocator, sizeof(*catalog)); + if(!catalog) { + res = RES_MEM_ERR; + goto error; + } + + str_init(allocator, &name); + name_initialized = 0; + + catalog->allocator = allocator; + catalog->logger = logger; + htable_dataset_cmode_0_init(allocator, &catalog->catalog_0); + htable_dataset_cmode_1_init(allocator, &catalog->catalog_1); + count = darray_parsed_catalog_items_size_get(&parsed_catalog->catalog); + items = darray_parsed_catalog_items_cdata_get(&parsed_catalog->catalog); + + for(i = 0; i < count; i++) { + switch(items[i].constructive_mode) { + case mode_0: { + const struct parsed_catalog_cmode_0* parsed_0 = items[i].parsed_items; + for(j = 0; j < parsed_0->datasets_count; j++) { + const struct parsed_dataset_cmode_0* parsed_item + = parsed_0->datasets + j; + struct dataset_cmode_0 item; + ERR(str_set(&name, parsed_item->name)); + if(htable_dataset_cmode_0_find(&catalog->catalog_0, &name)) { + logger_print(logger, LOG_ERROR, + "Duplicate dataset name: '%s' (in file '%s').\n", + parsed_item->name, items[i].filename); + res = RES_BAD_ARG; + goto error; + } + item.wall_thickness = parsed_item->wall_thickness; + item.floor_thickness = parsed_item->floor_thickness; + ERR(htable_dataset_cmode_0_set(&catalog->catalog_0, &name, &item)); + } + break; + } + case mode_1: { + const struct parsed_catalog_cmode_1* parsed_1 = items[i].parsed_items; + for(j = 0; j < parsed_1->datasets_count; j++) { + const struct parsed_dataset_cmode_1* parsed_item + = parsed_1->datasets + j; + struct dataset_cmode_1 item; + ERR(str_set(&name, parsed_item->name)); + if(htable_dataset_cmode_1_find(&catalog->catalog_1, &name)) { + logger_print(logger, LOG_ERROR, + "Duplicate dataset name: '%s' (in file '%s').\n", + parsed_item->name, items[i].filename); + res = RES_BAD_ARG; + goto error; + } + item.inter_floor_count = parsed_item->inter_floor_count; + item.wall_thickness = parsed_item->wall_thickness; + item.floor_thickness = parsed_item->floor_thickness; + item.inter_floor_thickness = parsed_item->inter_floor_thickness; + item.roof_thickness = parsed_item->roof_thickness; + item.internal_insulation_thickness = parsed_item->internal_insulation_thickness; + item.external_insulation_thickness = parsed_item->external_insulation_thickness; + item.floor_insulation_thickness = parsed_item->floor_insulation_thickness; + item.roof_insulation_thickness = parsed_item->roof_insulation_thickness; + item.foundation_depth = parsed_item->foundation_depth; + item.crawl_height = parsed_item->crawl_height; + item.attic_height = parsed_item->attic_height; + item.glass_ratio = parsed_item->glass_ratio; + ERR(htable_dataset_cmode_1_set(&catalog->catalog_1, &name, &item)); + } + break; + } + default: FATAL("Invalid enum value."); + } + } +exit: + if(name_initialized) str_release(&name); + *out_catalog = catalog; + return res; +error: + release_catalog(catalog); + catalog = NULL; + goto exit; +} + +void +release_catalog + (struct catalog* catalog) +{ + if(!catalog) return; + + htable_dataset_cmode_0_release(&catalog->catalog_0); + htable_dataset_cmode_1_release(&catalog->catalog_1); + MEM_RM(catalog->allocator, catalog); +} + diff --git a/src/cg_catalog.h b/src/cg_catalog.h @@ -0,0 +1,51 @@ +/* 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_CATALOG__ +#define FG_CATALOG__ + +#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" + +struct mem_allocator; +struct logger; +struct parsed_catalog; +struct catalog; + +struct catalog { + struct mem_allocator* allocator; + struct logger* logger; + struct htable_dataset_cmode_0 catalog_0; + struct htable_dataset_cmode_1 catalog_1; +}; + +res_T +create_catalog + (struct mem_allocator* allocator, + struct logger* logger, + struct parsed_catalog* parsed_catalog, + struct catalog** out_catalog); + +void +release_catalog + (struct catalog* catalog); + +#endif diff --git a/src/cg_catalog_parsing.c b/src/cg_catalog_parsing.c @@ -18,106 +18,124 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "cg.h" +#include "cg_args.h" #include "cg_catalog_parsing.h" +#include "cg_constructive_modes_parsing_schemas.h" #include "cg_building.h" #include <rsys/logger.h> #include <rsys/str.h> -#include <rsys/stretchy_array.h> + +#include <cyaml/cyaml.h> + +static const struct cyaml_schema_value* +get_schema_from_parsed_cmode + (const enum parsed_cmode_type parsed_cmode) +{ + switch(parsed_cmode) { + case PARSED_CMODE_0: + return &constructive_mode_0_schema; + case PARSED_CMODE_1: + return &constructive_mode_1_schema; + default: FATAL("Invalid enum value.\n"); + } +} res_T parse_catalog - (struct logger* logger, - struct htable_parameter_set* catalog) + (const struct darray_catalog_filenames* files_array, + struct mem_allocator* allocator, + struct logger* logger, + const struct cyaml_config* config, + struct parsed_catalog** out_parsed) { res_T res = RES_OK; - struct data_set_cmode_0* data0; - struct data_set_cmode_1* data1; - struct parameter_set* params0; + cyaml_err_t err; + size_t i, files_count; + struct parsed_catalog_items* items; + struct parsed_catalog* parsed; + struct parsed_cmode* parsed_cmode = NULL; + char* filename = NULL; (void)logger; - htable_parameter_set_init(NULL, catalog); + ASSERT(files_array && allocator && logger && out_parsed); - params0 = malloc(2*sizeof(struct parameter_set)); - if (!params0) { + parsed = MEM_ALLOC(allocator, sizeof(*parsed)); + if(!parsed) { res = RES_MEM_ERR; goto error; } - data0 = malloc(sizeof(struct data_set_cmode_0)); - if (!data0) { - res = RES_MEM_ERR; - goto error; + parsed->allocator = allocator; + parsed->logger = logger; + + files_count = darray_catalog_filenames_size_get(files_array); + + darray_parsed_catalog_items_init(allocator, &parsed->catalog); + ERR(darray_parsed_catalog_items_resize(&parsed->catalog, files_count)); + items = darray_parsed_catalog_items_data_get(&parsed->catalog); + for(i = 0; i < files_count; i++) { + const struct cyaml_schema_value* schema; + + /* Parse constructive mode only */ + filename = darray_catalog_filenames_cdata_get(files_array)[i]; + err = cyaml_load_file(filename, config, &constructive_mode_schema, + (void**)&parsed_cmode, NULL); + ERR(cyaml_err_to_res_T(err)); + + /* Parse catalog items according to constructive mode */ + schema = get_schema_from_parsed_cmode(parsed_cmode->cmode_type); + err = cyaml_load_file(filename, config, schema, &items[i].parsed_items, NULL); + ERR(cyaml_err_to_res_T(err)); + + /* Set other fields*/ + items[i].filename = filename; + items[i].constructive_mode = parsed_cmode->cmode_type; + + /* Free tmp struct */ + err = cyaml_free(config, &constructive_mode_schema, parsed_cmode, 1); + CHK(RES_OK == cyaml_err_to_res_T(err)); + parsed_cmode = NULL; + filename = NULL; } - params0[0].constructive_mode = mode_0; - str_init(NULL, &params0[0].name); - ERR(str_set(&params0[0].name, "b0")); - data0->wall = 0.2; - data0->floor = 0.3; - params0[0].data = malloc(sizeof(struct data_set_cmode_0)); - params0[0].data = (void*)data0; - ERR(htable_parameter_set_set(catalog, &params0[0].name, &params0[0])); - - data1 = malloc(sizeof(struct data_set_cmode_1)); - if (!data1) { - res = RES_MEM_ERR; - goto error; - } - params0[1].constructive_mode = mode_1; - str_init(NULL, &params0[1].name); - ERR(str_set(&params0[1].name, "b1")); - data1->wall = 0.25; - data1->floor = 0.35; - data1->inter_floor = 0.2; - data1->inter_floor_n = 0; - data1->roof = 0.3; - data1->int_insulation = 0.1; - data1->ext_insulation = 0.2; - data1->floor_insulation = 0; - data1->roof_insulation = 0; - data1->foundation = 2; - data1->crawl = 0; - data1->attic = 0; - data1->glass_ratio = 0.5; - params0[1].data = malloc(sizeof(struct data_set_cmode_1)); - params0[1].data = (void*)data1; - ERR(htable_parameter_set_set(catalog, &params0[1].name, &params0[1])); - - /* check coherence */ - if (data1->roof_insulation <= 0) data1->attic = 0; - if (data1->inter_floor <= 0) data1->inter_floor_n = 0; - if (data1->inter_floor_n <= 0) data1->inter_floor = 0; exit: - free(params0); + if(parsed_cmode) { + err = cyaml_free(config, &city_schema, parsed_cmode, 1); + CHK(RES_OK == cyaml_err_to_res_T(err)); + } + *out_parsed = parsed; return res; error: - htable_parameter_set_release(catalog); + if(filename) { + logger_print(logger, LOG_ERROR, + "Error parsing catalog file '%s'.\n", filename); + } + release_parsed_catalog(config, parsed); + parsed = NULL; goto exit; } -res_T -release_params_building(struct parameter_set* params) +void +release_parsed_catalog + (const struct cyaml_config* config, + struct parsed_catalog* parsed) { - res_T res = RES_OK; - size_t i; + struct parsed_catalog_items* items; + size_t i, count; - if (!params) { - res = RES_BAD_ARG; - goto error; - } + if(!parsed) return; - printf("size params %lu \n", sa_size(params)); + ASSERT(config); - for (i=0; i<sa_size(params); ++i) { - free(params[i].data); + count = darray_parsed_catalog_items_size_get(&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); + cyaml_err_t err = cyaml_free(config, schema, items[i].parsed_items, 1); + CHK(RES_OK == cyaml_err_to_res_T(err)); } - - sa_release(params); - -exit: - return res; -error: - goto exit; + darray_parsed_catalog_items_release(&parsed->catalog); + MEM_RM(parsed->allocator, parsed); } - diff --git a/src/cg_catalog_parsing.h b/src/cg_catalog_parsing.h @@ -20,22 +20,47 @@ #ifndef PARSING_H #define PARSING_H -#include <ctype.h> +#include "cg_building.h" +#include "cg_constructive_mode_0_parsing_schemas.h" +#include "cg_constructive_mode_1_parsing_schemas.h" +#include "cg_constructive_modes_parsing_schemas.h" #include <rsys/rsys.h> +#include <rsys/dynamic_array.h> -struct txtrdr; struct logger; -struct htable_parameter_set; +struct mem_allocator; +struct cyaml_config; +struct cyaml_schema_value; +struct darray_catalog_filenames; -struct parameter_set; +struct parsed_catalog_items { + enum parsed_cmode_type constructive_mode; + const char* filename; + void* parsed_items; +}; + +#define DARRAY_NAME parsed_catalog_items +#define DARRAY_DATA struct parsed_catalog_items +#include <rsys/dynamic_array.h> + +struct parsed_catalog { + struct mem_allocator* allocator; + struct logger* logger; + struct darray_parsed_catalog_items catalog; +}; res_T parse_catalog - (struct logger* logger, - struct htable_parameter_set* catalog); + (const struct darray_catalog_filenames* files, + struct mem_allocator* allocator, + struct logger* logger, + const struct cyaml_config* config, + struct parsed_catalog** catalog); -res_T -release_params_building(struct parameter_set* params); +void +release_parsed_catalog + (const struct cyaml_config* config, + struct parsed_catalog* parsed); #endif /*PARSING_H*/ diff --git a/src/cg_city.c b/src/cg_city.c @@ -39,12 +39,12 @@ #include <string.h> res_T -city_create +create_city (struct mem_allocator* allocator, struct logger* logger, const struct args* args, struct parsed_city* parsed_city, - struct htable_parameter_set* catalog, + struct catalog* catalog, struct city** out_city) { res_T res = RES_OK; @@ -82,10 +82,10 @@ city_create struct building* building = city->buildings + i; switch(parsed_data->cmode_type) { case PARSED_CMODE_0: - ERR(init_model0(building, allocator, parsed_data, catalog)); + ERR(init_cmode_0(building, allocator, logger, parsed_data, catalog)); break; case PARSED_CMODE_1: - ERR(init_model1(building, allocator, parsed_data, catalog)); + ERR(init_cmode_1(building, allocator, logger, parsed_data, catalog)); break; default: res = RES_BAD_ARG; @@ -97,35 +97,27 @@ exit: *out_city = city; return res; error: - if(city) city_release(city); + release_city(city); out_city = NULL; goto exit; } -res_T -city_release(struct city* city) +void +release_city(struct city* city) { - res_T res = RES_OK; size_t i; + if(!city) return; + /* iterate on building */ for (i=0; i<city->buildings_count; ++i) { struct building* building = city->buildings + i; - - ERR(scpr_polygon_ref_put(building->pg)); - - if(building->name_initialized) { - str_release(&building->name); - } + SCPR(polygon_ref_put(building->pg)); + if(building->name_initialized) str_release(&building->name); } MEM_RM(city->allocator, city->buildings); MEM_RM(city->allocator, city); - -exit: - return res; -error: - goto exit; } res_T @@ -147,10 +139,12 @@ city_cad_build(struct city* city) struct building* building = city->buildings + i; struct data_cad_cmode_0* cad = NULL; /* create building */ - ERR(building->functors->build_cad(building, city->allocator, (void**)&cad)); + ERR(building->functors->build_cad(building, city->allocator, city->logger, + (void**)&cad)); ERR(scad_scene_mesh()); - ERR(building->functors->export_stl(cad, city->binary_export)); - ERR(building->functors->release_cad(city->allocator, cad)); + ERR(building->functors->export_stl(cad, city->allocator, city->logger, + city->binary_export)); + ERR(building->functors->release_cad(city->allocator, city->logger, cad)); ERR(scad_scene_clear()); } @@ -183,7 +177,8 @@ city_ground_build(struct city* city) struct building* building = city->buildings + i; struct scad_geometry** footprint = ground.footprints + i; /* create building footprint */ - ERR(building->functors->build_footprint(building, city->allocator, footprint)); + ERR(building->functors->build_footprint(building, city->allocator, + city->logger, footprint)); } ERR(ground_build_cad(city, &ground)); diff --git a/src/cg_city.h b/src/cg_city.h @@ -30,34 +30,7 @@ struct mem_allocator; struct building; struct args; struct parsed_city; -struct htable_parameter_set; - -static INLINE void -log_prt_fn(const char* msg, void* ctx) -{ - ASSERT(msg); - (void)ctx; - - fprintf(stderr, "\x1b[32moutput:\x1b[0m %s", msg); -} - -static INLINE void -log_warn_fn(const char* msg, void* ctx) -{ - ASSERT(msg); - (void)ctx; - - fprintf(stderr, "\x1b[33mwarning:\x1b[0m %s", msg); -} - -static INLINE void -log_err_fn(const char* msg, void* ctx) -{ - ASSERT(msg); - (void)ctx; - - fprintf(stderr, "\x1b[31merror:\x1b[0m %s", msg); -} +struct catalog; struct city { double ground_extent[4]; /* [xmin, xmax, ymin, ymax */ @@ -72,12 +45,13 @@ struct city { }; res_T -city_create +create_city (struct mem_allocator* allocator, struct logger* logger, const struct args* args, struct parsed_city* parsed_city, - struct htable_parameter_set* catalog, struct city** out_city); + struct catalog* catalog, + struct city** out_city); res_T city_cad_build @@ -87,7 +61,7 @@ res_T city_ground_build (struct city* city); -res_T -city_release(struct city* city); +void +release_city(struct city* city); #endif /*CITY_H*/ diff --git a/src/cg_city_parsing.c b/src/cg_city_parsing.c @@ -42,56 +42,35 @@ parse_city struct parsed_city *parsed = NULL; cyaml_err_t err; - (void)allocator; (void)logger; - - if(!name || !config || !out_parsed) { - res = RES_BAD_ARG; - goto error; - } + ASSERT(allocator && logger && name && config && out_parsed); err = cyaml_load_file(name, config, &city_schema, (void**)&parsed, NULL); + ERR(cyaml_err_to_res_T(err)); - switch(err) { - case CYAML_OK: break; - case CYAML_ERR_OOM: res = RES_MEM_ERR; goto error; - case CYAML_ERR_FILE_OPEN: res = RES_IO_ERR; goto error; - default: res = RES_UNKNOWN_ERR; goto error; - } - - *out_parsed = parsed; + parsed->allocator = allocator; + parsed->logger = logger; exit: + *out_parsed = parsed; return res; error: - cyaml_free(config, &city_schema, parsed, 1); + logger_print(logger, LOG_ERROR, "Error parsing city map file '%s'.\n", name); + release_parsed_city(config, parsed); parsed = NULL; goto exit; } -res_T +void release_parsed_city (const struct cyaml_config* config, struct parsed_city* parsed) { - res_T res = RES_OK; cyaml_err_t err; - if(!parsed || !config) { - res = RES_BAD_ARG; - goto error; - } + if(!parsed) return; - err = cyaml_free(config, &city_schema, parsed, 1); + ASSERT(config); - switch(err) { - case CYAML_OK: break; - case CYAML_ERR_OOM: res = RES_MEM_ERR; goto error; - case CYAML_ERR_FILE_OPEN: res = RES_IO_ERR; goto error; - default: res = RES_UNKNOWN_ERR; goto error; - } - -exit: - return res; -error: - goto exit; + err = cyaml_free(config, &city_schema, parsed, 1); + CHK(RES_OK == cyaml_err_to_res_T(err)); } diff --git a/src/cg_city_parsing.h b/src/cg_city_parsing.h @@ -35,7 +35,7 @@ parse_city const struct cyaml_config* config, struct parsed_city** out_parsed); -res_T +void release_parsed_city (const struct cyaml_config* config, struct parsed_city* parsed); diff --git a/src/cg_city_parsing_schemas.h b/src/cg_city_parsing_schemas.h @@ -20,26 +20,14 @@ #ifndef FG_CITY_PARSING_SCHEMAS__ #define FG_CITY_PARSING_SCHEMAS__ +#include "cg_constructive_modes_parsing_schemas.h" + #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_model_type values for - * schema. */ -static const cyaml_strval_t city_building_types_strings[] = { - { "Model0", PARSED_CMODE_0 }, - { "Model1", PARSED_CMODE_1 } -}; - struct parsed_city_building { char* name; enum parsed_cmode_type cmode_type; @@ -56,6 +44,8 @@ struct parsed_ground { }; struct parsed_city { + struct mem_allocator* allocator; + struct logger* logger; struct parsed_city_building* city_building_list; struct parsed_ground ground; diff --git a/src/cg_constructive_mode_0.c b/src/cg_constructive_mode_0.c @@ -19,12 +19,15 @@ #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 @@ -54,7 +57,7 @@ build_floor { res_T res = RES_OK; double e; - struct data_set_cmode_0* data; + struct dataset_cmode_0* data; struct scad_geometry* footprint = NULL; double d[3] = {0, 0, 0}; char* floorname = NULL; @@ -63,8 +66,8 @@ build_floor ASSERT(pg && b && floor); - data = (struct data_set_cmode_0*)b->data; - e = data->floor; + data = (struct dataset_cmode_0*)b->data; + e = data->floor_thickness; str_init(NULL, &name); is_init = 1; @@ -98,7 +101,7 @@ build_roof double height; double e; double d[3] = {0, 0, 0}; - struct data_set_cmode_0* data; + struct dataset_cmode_0* data; char* roofname = NULL; struct str name; int is_init = 0; @@ -114,8 +117,8 @@ build_roof } height = b->height; - data = (struct data_set_cmode_0*)b->data; - e = data->floor; + data = (struct dataset_cmode_0*)b->data; + e = data->floor_thickness; ERR(scad_geometry_copy(floor, roofname, roof)); d[2] = height - e ; @@ -207,7 +210,7 @@ build_cavity { res_T res = RES_OK; double e, height; - struct data_set_cmode_0* data; + struct dataset_cmode_0* data; double d[3] = {0, 0, 0}; struct scad_geometry* polygon = NULL; char* cavityname = NULL; @@ -218,8 +221,8 @@ build_cavity ASSERT(pg && b && cavity); height = b->height; - data = (struct data_set_cmode_0*)b->data; - e = data->floor; + data = (struct dataset_cmode_0*)b->data; + e = data->floor_thickness; str_init(NULL, &name); is_init = 1; @@ -396,23 +399,24 @@ error: /*----------------------------------------------------------------------------*/ res_T -init_model0 +init_cmode_0 (struct building* building, struct mem_allocator* allocator, + struct logger* logger, struct parsed_city_building* parsed_data, - struct htable_parameter_set* catalog) + struct catalog* catalog) { res_T res = RES_OK; - struct parameter_set* params; + struct dataset_cmode_0* dataset; struct str dataset_name; int name_initialized = 0; static struct constructive_mode_functors functors_0 = { - &init_model0, - &build_cad_model0, - &build_footprint_model0, - &export_stl_model0, - &release_cad_model0 + &init_cmode_0, + &build_cad_cmode_0, + &build_footprint_cmode_0, + &export_stl_cmode_0, + &release_cad_cmode_0 }; (void)parsed_data; @@ -434,20 +438,16 @@ init_model0 ERR(scpr_polygon_create(allocator, &building->pg)); ERR(scpr_polygon_setup_indexed_vertices(building->pg, 1, get_nverts, get_pos, parsed_data)); - params = htable_parameter_set_find(catalog, &dataset_name); - if (params == NULL) { + 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; } - if (params->constructive_mode != mode_0 - || parsed_data->cmode_type != PARSED_CMODE_0) - { - res = RES_BAD_ARG; - goto error; - } - - building->data = params->data; + building->data = dataset; exit: if(name_initialized) str_release(&dataset_name); @@ -457,16 +457,17 @@ error: } res_T -build_cad_model0 +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 data_set_cmode_0* data = NULL; + struct dataset_cmode_0* data = NULL; struct data_cad_cmode_0* data_cad = NULL; double e_wall; const char* name; @@ -478,9 +479,9 @@ build_cad_model0 height = building->height; pg = building->pg; - data = (struct data_set_cmode_0 *)building->data; + data = (struct dataset_cmode_0 *)building->data; - if (height <= 0 || data->wall <= 0 || data->floor <= 0) { + if (height <= 0 || data->wall_thickness <= 0 || data->floor_thickness <= 0) { res = RES_BAD_ARG; goto error; } @@ -491,7 +492,7 @@ build_cad_model0 goto error; } - e_wall = data->wall; + 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)); @@ -524,29 +525,30 @@ exit: *(struct data_cad_cmode_0**)cad = data_cad; return res; error: - if(data_cad) CHK(RES_OK == release_cad_model0(allocator, data_cad)); + if(data_cad) CHK(RES_OK == release_cad_cmode_0(allocator, logger, data_cad)); data_cad = NULL; goto exit; } res_T -build_footprint_model0 +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 data_set_cmode_0* data = (struct data_set_cmode_0 *)building->data; + struct dataset_cmode_0* data = (struct dataset_cmode_0 *)building->data; double e_wall; - (void)allocator; + (void)allocator; (void)logger; if(!building || ! footprint) { res = RES_BAD_ARG; goto error; } - e_wall = data->wall; + e_wall = data->wall_thickness; ERR(building_ground_connection(NULL, pg, e_wall, footprint)); @@ -557,12 +559,16 @@ error: } res_T -export_stl_model0 - (void* cad, const int binary) +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; @@ -599,13 +605,15 @@ error: } res_T -release_cad_model0 +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; diff --git a/src/cg_constructive_mode_0.h b/src/cg_constructive_mode_0.h @@ -21,21 +21,35 @@ #define CONSTRUCTIVE_MODE_0_H #include <rsys/rsys.h> +#include <rsys/str.h> +#include <rsys/hash_table.h> struct scad_geometry; struct building; -struct htable_parameter_set; -struct parameter_set; struct mem_allocator; +struct logger; struct parsed_city_building; +struct catalog; -/* specific data for model 0 */ -struct data_set_cmode_0 { - double wall; /* wall thickness */ - double floor; /* floor thickness */ +/* 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; @@ -48,32 +62,38 @@ struct data_cad_cmode_0 { }; res_T -init_model0 +init_cmode_0 (struct building* building, struct mem_allocator* allocator, + struct logger* logger, struct parsed_city_building* parsed_data, - struct htable_parameter_set* catalog); + struct catalog* catalog); res_T -build_cad_model0 +build_cad_cmode_0 (struct building* building, struct mem_allocator* allocator, + struct logger* logger, void** cad); res_T -build_footprint_model0 +build_footprint_cmode_0 (struct building* building, struct mem_allocator* allocator, + struct logger* logger, struct scad_geometry** footprint); res_T -export_stl_model0 +export_stl_cmode_0 (void* cad, + struct mem_allocator* allocator, + struct logger* logger, const int binary); res_T -release_cad_model0 +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 @@ -0,0 +1,97 @@ +/* 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 "cg_building.h" +#include "cg_city_parsing_schemas.h" + +#include <cyaml/cyaml.h> + +#include <rsys/rsys.h> +#include <rsys/str.h> + +struct scpr_polygon; +struct scad_geometry; +struct mem_allocator; + +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 @@ -19,11 +19,13 @@ #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 <rsys/stretchy_array.h> #include <star/scad.h> #include <star/scpr.h> @@ -33,13 +35,13 @@ build_floor (const char* prefix, struct mem_allocator* allocator, const struct scpr_polygon* pg, - const struct data_set_cmode_1* data, + const struct dataset_cmode_1* data, struct scad_geometry** floor) { res_T res = RES_OK; - double e_wall = data->wall; - double e_insulation = data->ext_insulation; - double e_floor = data->floor; + 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; @@ -86,12 +88,12 @@ build_wall struct mem_allocator* allocator, const struct scpr_polygon* pg, const double height, - const struct data_set_cmode_1* data, + const struct dataset_cmode_1* data, struct scad_geometry** wall) { res_T res = RES_OK; - double e_wall = data->wall; - double e_insulation = data->ext_insulation; + 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; @@ -158,17 +160,17 @@ build_int_insulation struct mem_allocator* allocator, const struct scpr_polygon* pg, const double height, - const struct data_set_cmode_1* data, + 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; - double e_roof = data->roof; - double e_roof_insulation = data->roof_insulation; - double attic = data->attic; - double e_ext_insulation = data->ext_insulation; - double e_int_insulation = data->int_insulation; + double e_wall = data->wall_thickness; + double e_roof = data->roof_thickness; + double e_roof_insulation = data->roof_insulation_thickness; + double attic = data->attic_height; + 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; @@ -238,13 +240,13 @@ build_roof struct mem_allocator* allocator, const struct scpr_polygon* pg, const double height, - const struct data_set_cmode_1* data, + const struct dataset_cmode_1* data, struct scad_geometry** roof) { res_T res = RES_OK; - double e_wall = data->wall; - double e_insulation = data->ext_insulation; - double e_roof = data->roof; + 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; @@ -292,15 +294,15 @@ build_roof_insulation struct mem_allocator* allocator, const struct scpr_polygon* pg, const double height, - const struct data_set_cmode_1* data, + const struct dataset_cmode_1* data, struct scad_geometry** insulation) { res_T res = RES_OK; - double e_wall = data->wall; - double e_insulation = data->ext_insulation; - double e_roof = data->roof; - double attic = data->attic; - double e_roof_insulation = data->roof_insulation; + double e_wall = data->wall_thickness; + double e_insulation = data->external_insulation_thickness; + double e_roof = data->roof_thickness; + double attic = data->attic_height; + double e_roof_insulation = data->roof_insulation_thickness; double offset = 0; double z_insulation = 0; struct scpr_polygon* pg_int = NULL; @@ -348,14 +350,14 @@ build_floor_insulation (const char* prefix, struct mem_allocator* allocator, const struct scpr_polygon* pg, - const struct data_set_cmode_1* data, + const struct dataset_cmode_1* data, struct scad_geometry** insulation) { res_T res = RES_OK; - double e_wall = data->wall; - double e_insulation = data->ext_insulation; - double e_floor = data->floor; - double e_floor_insulation = data->floor_insulation; + 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; @@ -404,18 +406,18 @@ build_inter_floor struct mem_allocator* allocator, const struct scpr_polygon* pg, const double height, - const struct data_set_cmode_1* data, + 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_n; - double e_roof = data->roof; - double e_roof_ins = data->roof_insulation; - double attic = data->attic; - double e_floor = data->inter_floor; - double e_wall = data->wall; - double e_insulation = data->ext_insulation; + 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; @@ -483,11 +485,11 @@ build_ext_insulation struct mem_allocator* allocator, const struct scpr_polygon* pg, const double height, - const struct data_set_cmode_1* data, + const struct dataset_cmode_1* data, struct scad_geometry** insulation) { res_T res = RES_OK; - double e_insulation = data->ext_insulation; + double e_insulation = data->external_insulation_thickness; double offset = 0; struct scpr_polygon* pg_int = NULL; struct scpr_polygon* pg_ext = NULL; @@ -547,15 +549,15 @@ build_crawlspace (const char* prefix, struct mem_allocator* allocator, const struct scpr_polygon* pg, - const struct data_set_cmode_1* data, + const struct dataset_cmode_1* data, struct scad_geometry** crawlspace) { res_T res = RES_OK; - double e_wall = data->wall; - double e_insulation = data->ext_insulation; - double e_crawl = data->crawl; - double e_floor = data->floor; - double e_floor_insulation = data->floor_insulation; + 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; @@ -604,17 +606,17 @@ build_habitable struct mem_allocator* allocator, const struct scpr_polygon* pg, const double height, - const struct data_set_cmode_1* data, + const struct dataset_cmode_1* data, struct scad_geometry* floor, struct scad_geometry** cavity) { res_T res = RES_OK; - double e_wall = data->wall; - double e_ext_insulation = data->ext_insulation; - double e_int_insulation = data->int_insulation; - double e_roof = data->roof; - double e_roof_insulation = data->roof_insulation; - double e_attic = data->attic; + 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; @@ -669,14 +671,14 @@ build_attic struct mem_allocator* allocator, const struct scpr_polygon* pg, const double height, - const struct data_set_cmode_1* data, + const struct dataset_cmode_1* data, struct scad_geometry** attic) { res_T res = RES_OK; - double e_wall = data->wall; - double e_insulation = data->ext_insulation; - double e_roof = data->roof; - double e_attic = data->attic; + double e_wall = data->wall_thickness; + double e_insulation = data->external_insulation_thickness; + double e_roof = data->roof_thickness; + double e_attic = data->attic_height; double offset = 0; double z_attic = 0; struct scpr_polygon* pg_int = NULL; @@ -723,7 +725,7 @@ static res_T build_windows (const char* prefix, struct mem_allocator* allocator, - const struct data_set_cmode_1* data, + const struct dataset_cmode_1* data, struct data_cad_cmode_1* data_cad) { res_T res = RES_OK; @@ -769,9 +771,12 @@ build_windows ERR(scad_geometry_dilate(surface, center, scale)); - dir[0] = 1.1*N[0] * (data->wall + data->int_insulation + data->ext_insulation); - dir[1] = 1.1*N[1] * (data->wall + data->int_insulation + data->ext_insulation); - dir[2] = 1.1*N[2] * (data->wall + data->int_insulation + data->ext_insulation); + 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)); sa_push(hole_list, hole); @@ -1146,23 +1151,24 @@ error: /*----------------------------------------------------------------------------*/ res_T -init_model1 +init_cmode_1 (struct building* building, struct mem_allocator* allocator, + struct logger* logger, struct parsed_city_building* parsed_data, - struct htable_parameter_set* catalog) + struct catalog* catalog) { res_T res = RES_OK; - struct parameter_set* params; + struct dataset_cmode_1* dataset; struct str dataset_name; int name_initialized = 0; static struct constructive_mode_functors functors_1 = { - &init_model1, - &build_cad_model1, - &build_footprint_model1, - &export_stl_model1, - &release_cad_model1 + &init_cmode_1, + &build_cad_cmode_1, + &build_footprint_cmode_1, + &export_stl_cmode_1, + &release_cad_cmode_1 }; (void) parsed_data; @@ -1184,20 +1190,16 @@ init_model1 ERR(scpr_polygon_create(allocator, &building->pg)); ERR(scpr_polygon_setup_indexed_vertices(building->pg, 1, get_nverts, get_pos, parsed_data)); - params = htable_parameter_set_find(catalog, &dataset_name); - if (params == NULL) { + 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; } - if (params->constructive_mode != mode_1 - || parsed_data->cmode_type != PARSED_CMODE_1) - { - res = RES_BAD_ARG; - goto error; - } - - building->data = params->data; + building->data = dataset; exit: if(name_initialized) str_release(&dataset_name); @@ -1207,15 +1209,16 @@ error: } res_T -build_cad_model1 +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; struct scpr_polygon* pg = building->pg; - struct data_set_cmode_1* data = (struct data_set_cmode_1 *)building->data; + struct dataset_cmode_1* data = (struct dataset_cmode_1 *)building->data; struct data_cad_cmode_1* data_cad = NULL; const char* name; @@ -1252,33 +1255,33 @@ build_cad_model1 - floor insulation */ - if (data->foundation > 0) { - double depth = -data->foundation; + if (data->foundation_depth > 0) { + double depth = -data->foundation_depth; ERR(build_wall(name, "foundation", allocator, pg, depth, data, &data_cad->foundation)); } - if (data->inter_floor_n > 0) { + if (data->inter_floor_count > 0) { ERR(build_inter_floor(name, allocator, pg, height, data, &data_cad->intermediate_floor)); } - if (data->ext_insulation > 0) { + if (data->external_insulation_thickness> 0) { ERR(build_ext_insulation(name, allocator, pg, height, data, &data_cad->external_insulation)); } - if (data->int_insulation > 0) { + 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 > 0) { + if (data->roof_insulation_thickness > 0) { ERR(build_roof_insulation(name, allocator, pg, height, data, &data_cad->roof_insulation)); } - if (data->floor_insulation > 0) { + if (data->floor_insulation_thickness > 0) { ERR(build_floor_insulation(name, allocator, pg, data, &data_cad->floor_insulation)); } @@ -1289,14 +1292,14 @@ build_cad_model1 - crawlspace */ - if (data->attic > 0) { + 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 > 0) { + if (data->crawl_height > 0) { ERR(build_crawlspace(name, allocator, pg, data, &data_cad->crawlspace_cavity)); } @@ -1306,7 +1309,7 @@ build_cad_model1 } /* fake ground */ - ERR(build_fake_ground(data_cad, pg, data->foundation, &data_cad->fake_ground)); + ERR(build_fake_ground(data_cad, pg, data->foundation_depth, &data_cad->fake_ground)); ERR(scad_scene_partition()); @@ -1324,20 +1327,21 @@ exit: *(struct data_cad_cmode_1**)cad = data_cad; return res; error: - if(data_cad) CHK(RES_OK == release_cad_model1(allocator, data_cad)); + if(data_cad) CHK(RES_OK == release_cad_cmode_1(allocator, logger, data_cad)); data_cad = NULL; goto exit; } res_T -build_footprint_model1 +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)allocator; (void)logger; if (!building || !footprint) { res = RES_BAD_ARG; @@ -1353,12 +1357,16 @@ error: } res_T -export_stl_model1 - (void* cad, const int binary) +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; @@ -1442,13 +1450,15 @@ error: } res_T -release_cad_model1 +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; diff --git a/src/cg_constructive_mode_1.h b/src/cg_constructive_mode_1.h @@ -21,32 +21,46 @@ #define CONSTRUCTIVE_MODE_1_H #include <rsys/rsys.h> +#include <rsys/str.h> +#include <rsys/hash_table.h> struct scad_geometry; struct building; -struct htable_parameter_set; -struct parameter_set; struct mem_allocator; +struct logger; struct parsed_city_building; +struct catalog; /* specific data for constructive mode 1 */ -struct data_set_cmode_1 { - size_t inter_floor_n; /* number of intermediate floor >= 0 */ - double wall; /* wall thickness > 0 */ - double floor; /* floor thickness > 0*/ - double inter_floor; /* intermediate floor thickness > 0 */ - double roof; /* roof thickness > 0*/ - double int_insulation; /* internal insulation thickness >= 0 */ - double ext_insulation; /* external insulation thickness >= 0 */ - double floor_insulation; /* floor insulation thickness >= 0 */ - double roof_insulation; /* roof insulation thickness >= 0*/ - double foundation; /* foundation depth >= 0 */ - double crawl; /* crawl space height >= 0 */ - double attic; /* attic height >= 0 (and only if roof insulation > 0)*/ +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; @@ -69,32 +83,38 @@ struct data_cad_cmode_1 { }; res_T -init_model1 +init_cmode_1 (struct building* building, struct mem_allocator* allocator, + struct logger* logger, struct parsed_city_building* parsed_data, - struct htable_parameter_set* catalog); + struct catalog* catalog); res_T -build_cad_model1 +build_cad_cmode_1 (struct building* building, struct mem_allocator* allocator, + struct logger* logger, void** cad); res_T -build_footprint_model1 +build_footprint_cmode_1 (struct building* building, struct mem_allocator* allocator, + struct logger* logger, struct scad_geometry** footprint); res_T -export_stl_model1 +export_stl_cmode_1 (void* cad, + struct mem_allocator* allocator, + struct logger* logger, const int binary); res_T -release_cad_model1 +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 @@ -0,0 +1,132 @@ +/* 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 "cg_building.h" +#include "cg_city_parsing_schemas.h" + +#include <cyaml/cyaml.h> + +#include <rsys/rsys.h> +#include <rsys/str.h> + +struct scpr_polygon; +struct scad_geometry; +struct mem_allocator; + +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 @@ -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 */ +/********************************************************/ + +/* 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 @@ -22,7 +22,10 @@ #include "cg_building.h" #include "cg_city.h" #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 <cyaml/cyaml.h> @@ -31,19 +34,16 @@ #include <rsys/mem_allocator.h> #include <star/scad.h> -char const* constructive_mode_name[CONSTRUCTIVE_MODES_COUNT__] = { - "model0", - "model1" -}; - -static void +static int check_memory_allocator(struct mem_allocator* allocator) { if(MEM_ALLOCATED_SIZE(allocator)) { char dump[4096]; MEM_DUMP(allocator, dump, sizeof(dump)/sizeof(char)); fprintf(stderr, "%s\n", dump); - FATAL("Memory leaks.\n"); + fprintf(stderr, "Memory leaks.\n"); + return 1; } + return 0; } static void cg_log @@ -86,14 +86,14 @@ int main { int err = EXIT_SUCCESS; res_T res = RES_OK; - struct args args; + struct args* args = NULL; struct city* city = NULL; struct logger logger; struct mem_allocator allocator; - struct parsed_city* parsed_city; - struct htable_parameter_set catalog; + struct parsed_city* parsed_city = NULL; + struct parsed_catalog* parsed_catalog = NULL; + struct catalog* catalog = NULL; int logger_initialized = 0, allocator_initialized = 0; - int parsed_city_initialized = 0, cg_initialized = 0; const struct cyaml_config config = { .log_fn = cg_log, .log_ctx = &logger, @@ -115,55 +115,67 @@ int main logger_set_stream(&logger, LOG_ERROR, log_err_fn, NULL); /* parse command line */ - ERR(parse_args(&logger, argc, argv, &args)); - if(args.print_help) { + ERR(parse_args(&allocator, &logger, argc, argv, &args)); + if(args->print_help) { short_help(); goto exit; } - else if(args.print_version) { + else if(args->print_version) { print_version(); goto exit; } /* Deactivate some loggin according to the -V arg */ - if(args.verbosity_level < 1) + if(args->verbosity_level < 1) logger_set_stream(&logger, LOG_ERROR, NULL, NULL); - if(args.verbosity_level < 2) + if(args->verbosity_level < 2) logger_set_stream(&logger, LOG_WARNING, NULL, NULL); - if(args.verbosity_level < 3) + if(args->verbosity_level < 3) logger_set_stream(&logger, LOG_OUTPUT, NULL, NULL); - /* Parse city description. + /* Parse catalog. * No semantic validation is done at this stage */ - ERR(parse_city(args.city_filename, &allocator, &logger, &config, &parsed_city)); - parsed_city_initialized = 1; + ERR(parse_catalog(&args->catalog_filenames, &allocator, &logger, &config, + &parsed_catalog)); - /* Parse catalog. */ - ERR(parse_catalog(&logger, &catalog)); + /* Create catalog from parsed data. + * Semantic validation is done along the process as well as the emission of + * informative logs */ + ERR(create_catalog(&allocator, &logger, parsed_catalog, &catalog)); + release_parsed_catalog(&config, parsed_catalog); + parsed_catalog = NULL; + + /* Parse city description. + * No semantic validation is done at this stage */ + ERR(parse_city(args->city_filename, &allocator, &logger, &config, &parsed_city)); - /* Feed city with parsed data + /* Create city with parsed data. * Semantic validation is done along the process as well as the emission of * informative logs */ - ERR(city_create(&allocator, &logger, &args, parsed_city, &catalog, &city)); - cg_initialized = 1; - ERR(release_parsed_city(&config, parsed_city)); - parsed_city_initialized = 0; + ERR(create_city(&allocator, &logger, args, parsed_city, catalog, &city)); + release_parsed_city(&config, parsed_city); + parsed_city = NULL; + release_args(args); + args = NULL; ERR(city_ground_build(city)); ERR(city_cad_build(city)); exit: - if(cg_initialized) city_release(city); + release_args(args); + release_city(city); + release_catalog(catalog); + release_parsed_catalog(&config, parsed_catalog); + release_parsed_city(&config, parsed_city); if(logger_initialized) logger_release(&logger); - if(parsed_city_initialized) release_parsed_city(&config, parsed_city); if(allocator_initialized) { - check_memory_allocator(&allocator); + if(check_memory_allocator(&allocator)) err = EXIT_FAILURE; mem_shutdown_proxy_allocator(&allocator); CHK(mem_allocated_size() == 0); } return err; error: err = EXIT_FAILURE; - printf("ERROR\n"); + printf("City generator failed.\n"); goto exit; }