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 9adb85a69edb8446b132b25f9a2e7ed49f669ee5
parent a06b1a701f2d3e11094d068a1bfd57f444e565e6
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Mon, 19 Dec 2022 14:17:05 +0100

Replace the ini city file by a yaml one

Diffstat:
Mcmake/CMakeLists.txt | 17++++++++++++-----
Msrc/cg_building.h | 20++++++++++++++------
Msrc/cg_city.c | 127+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/cg_city.h | 32++++++++++++++++++++++----------
Asrc/cg_city_parsing.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_city_parsing.h | 43+++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_city_parsing_schemas.h | 151++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_constructive_mode.h | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/cg_constructive_mode_0.c | 108+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/cg_constructive_mode_0.h | 13+++++++++----
Msrc/cg_constructive_mode_1.c | 147++++++++++++++++++++++++++++++++++---------------------------------------------
Msrc/cg_constructive_mode_1.h | 13+++++++++----
Msrc/cg_ground.c | 16++--------------
Msrc/cg_ground.h | 2+-
Msrc/cg_main.c | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/cg_parsing.c | 345+------------------------------------------------------------------------------
Msrc/cg_parsing.h | 9+--------
17 files changed, 687 insertions(+), 583 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -27,6 +27,7 @@ find_package(RCMake 0.4.1 REQUIRED) find_package(RSys 0.12.1 REQUIRED) find_package(StarCAD 0.1 REQUIRED) find_package(StarCPR 0.1.3 REQUIRED) +find_package(libcyaml 1.3 REQUIRED) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) include(rcmake) @@ -36,10 +37,11 @@ include_directories( ${StarCAD_INCLUDE_DIR} ${RSys_INCLUDE_DIR} ${StarCPR_INCLUDE_DIR} + ${LIBCYAML_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) if(CMAKE_COMPILER_IS_GNUCC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c89") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") endif() ################################################################################ @@ -51,21 +53,25 @@ set(CG2_VERSION_PATCH 0) set(CG2_VERSION ${CG2_VERSION_MAJOR}.${CG2_VERSION_MINOR}.${CG2_VERSION_PATCH}) set(CG2_FILES_SRC - cg_main.c + cg_args.c cg_city.c + cg_city_parsing.c cg_constructive_mode_0.c cg_constructive_mode_1.c cg_ground.c - cg_args.c + cg_main.c cg_parsing.c) set(CG2_FILES_INC cg.h cg_args.h cg_building.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_1.h - cg_city.h cg_default.h.in cg_ground.h cg_parsing.h @@ -95,7 +101,8 @@ add_executable(city_generator2 ${CG2_FILES_SRC} ${CG2_FILES_INC}) -target_link_libraries(city_generator2 RSys StarCAD StarCPR ${MATH_LIB}) +target_link_libraries(city_generator2 + RSys StarCAD StarCPR ${LIBCYAML_LIBRARY} ${MATH_LIB}) set_target_properties(city_generator2 PROPERTIES VERSION ${CG2_VERSION}) diff --git a/src/cg_building.h b/src/cg_building.h @@ -30,6 +30,7 @@ struct scpr_polygon; struct scad_geometry; +struct mem_allocator; /* A type to give an ID to constructive modes. * Add a new entry for each new constructive mode. */ @@ -79,9 +80,10 @@ hash_str(const struct str* a) /* The type of buildings as described in the city description */ struct building { /* generic constructive mode data */ - size_t id; + struct str name; + struct str dataset_name; + int names_initialized; enum constructive_mode_type constructive_mode; - struct str* constructive_mode_name; double height; struct scpr_polygon* pg; @@ -91,13 +93,19 @@ struct building { /* functors depending to the constructive mode */ res_T (*init) - (struct building* building, struct htable_parameter_set* catalog); - res_T (*build_cad)(struct building* building); + (struct building* building, + struct mem_allocator* allocator, + struct parsed_city_building* parsed_data, + struct htable_parameter_set* catalog); + res_T (*build_cad) + (struct building* building); res_T (*build_footprint) (struct building* building, struct scad_geometry** footprint); - res_T (*export_stl)(const struct building* building, const int binary); - res_T (*release)(struct building* building); + res_T (*export_stl) + (const struct building* building, const int binary); + res_T (*release) + (struct building* building); }; #endif /* BUILDING_H */ diff --git a/src/cg_city.c b/src/cg_city.c @@ -17,54 +17,83 @@ * 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 <string.h> - -#include <rsys/text_reader.h> -#include <rsys/cstr.h> -#include <rsys/stretchy_array.h> - #include "cg.h" #include "cg_city.h" +#include "cg_constructive_mode_0.h" #include "cg_parsing.h" +#include "cg_city_parsing.h" #include "cg_building.h" #include "cg_args.h" +#include "cg_city_parsing_schemas.h" + +#include <rsys/text_reader.h> +#include <rsys/cstr.h> +#include <rsys/logger.h> +#include <rsys/mem_allocator.h> +#include <rsys/stretchy_array.h> +#include <rsys/double4.h> + +#include <string.h> res_T -city_init(struct logger* logger, struct city* city, struct args* args) +city_create + (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) { res_T res = RES_OK; size_t i=0; - struct txtrdr* reader = NULL; - struct htable_parameter_set catalog; + struct city* city = NULL; + (void)logger; - city->binary_export = args->binary_export; + ASSERT(logger && allocator && args && parsed_city && catalog && out_city); + + city = MEM_CALLOC(allocator, 1, sizeof(*city)); + if(!city) { + res = RES_MEM_ERR; + goto error; + } - ERR(txtrdr_file(NULL, args->city_filename, '#', &reader)); - ERR(parse_city(logger, reader, city)); + city->buildings_count = parsed_city->city_building_list_count; + city->buildings = MEM_CALLOC(allocator, city->buildings_count, + sizeof(*city->buildings)); + if(!city->buildings) { + res = RES_MEM_ERR; + goto error; + } + + city->allocator = allocator; + city->binary_export = args->binary_export; - ERR(parse_catalog(logger, &catalog)); + city->ground.depth = parsed_city->ground.depth; + d4_set(city->ground.extent, parsed_city->ground.extent); - for (i=0; i<city->n ; ++i) { - city->building[i].release = NULL; - switch(city->building[i].constructive_mode) { - case mode_0: - city->building[i].init = &init_model0; + /* create buildings depending on their constructive 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; + switch(parsed_data->cmode_type) { + case PARSED_CMODE_0: + ERR(init_model0(building, allocator, parsed_data, catalog)); break; - case mode_1: - city->building[i].init = &init_model1; + case PARSED_CMODE_1: + ERR(init_model1(building, allocator, parsed_data, catalog)); break; default: res = RES_BAD_ARG; goto error; } - ERR(city->building[i].init(&city->building[i], &catalog)); } exit: - txtrdr_ref_put(reader); - htable_parameter_set_release(&catalog); + *out_city = city; return res; error: + if(city) city_release(city); + out_city = NULL; goto exit; } @@ -72,19 +101,17 @@ res_T city_release(struct city* city) { res_T res = RES_OK; - size_t i,n; + size_t i; /* iterate on building */ - n = city->n; - for (i=0; i<n; ++i) { - if (city->building[i].release) { - ERR(city->building[i].release(&city->building[i])); - } + for (i=0; i<city->buildings_count; ++i) { + ERR(city->buildings[i].release(&city->buildings[i])); } ERR(ground_release(&city->ground)); - if (city->building) sa_release(city->building); + MEM_RM(city->allocator, city->buildings); + MEM_RM(city->allocator, city); exit: return res; @@ -97,19 +124,20 @@ city_cad_build(struct logger* logger, struct city* city) { res_T res = RES_OK; struct scad_options options = SCAD_DEFAULT_OPTIONS__; - size_t i,n; + size_t i; + (void)logger; - ERR(scad_initialize(logger, NULL, 0)); + ERR(scad_initialize(logger, NULL, 3)); options.Mesh.MeshSizeFromPoints = 0; ERR(scad_set_options(&options)); /* iterate on building */ - n = city->n; - for (i=0; i<n; ++i) { + for (i=0; i<city->buildings_count; ++i) { + struct building* building = city->buildings + i; /* create building */ - ERR(city->building[i].build_cad(&city->building[i])); + ERR(building->build_cad(building)); ERR(scad_scene_mesh()); - ERR(city->building[i].export_stl(&city->building[i], city->binary_export)); + ERR(building->export_stl(building, city->binary_export)); ERR(scad_scene_clear()); } @@ -125,24 +153,27 @@ city_ground_build(struct logger* logger, struct city* city) { res_T res = RES_OK; struct scad_options options = SCAD_DEFAULT_OPTIONS__; - size_t i,n; + size_t i; + (void)logger; - ERR(scad_initialize(logger, NULL, 0)); + ERR(scad_initialize(logger, NULL, 3)); options.Mesh.MeshSizeFromPoints = 0; ERR(scad_set_options(&options)); - - /* iterate on building */ - n = city->n; - city->ground.n = n; - city->ground.footprint = malloc(n * sizeof(struct scad_geometry*)); - for (i=0; i<n; ++i) { - /* create building footprint */ - ERR(city->building[i].build_footprint - (&city->building[i], - &city->ground.footprint[i])); + city->ground.footprints_count = city->buildings_count; + city->ground.footprint + = malloc(city->ground.footprints_count * sizeof(*city->ground.footprint)); + if(!city->ground.footprint) { + res = RES_MEM_ERR; + goto error; } + for (i = 0; i < city->ground.footprints_count ; ++i) { + struct building* building = city->buildings + i; + struct scad_geometry** footprint = city->ground.footprint + i; + /* create building footprint */ + ERR(building->build_footprint(building, footprint)); + } ERR(ground_build_cad(&city->ground)); ERR(scad_scene_mesh()); diff --git a/src/cg_city.h b/src/cg_city.h @@ -20,14 +20,17 @@ #ifndef CITY_H #define CITY_H -#include <star/scad.h> - #include "cg_ground.h" +#include <star/scad.h> + struct logger; +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) @@ -57,24 +60,33 @@ log_err_fn(const char* msg, void* ctx) } struct city { - struct building* building; /* list of buildings */ - size_t n; + struct building* buildings; /* list of buildings */ + size_t buildings_count; struct ground ground; int binary_export; -}; -#define CITY_NULL__ {NULL, 0, GROUND_NULL__, 0} -static const struct city CITY_NULL = CITY_NULL__; + struct mem_allocator* allocator; +}; res_T -city_init(struct logger* logger, struct city* city, struct args* arg); +city_create + (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); res_T -city_cad_build(struct logger* logger, struct city* city); +city_cad_build + (struct logger* logger, + struct city* city); res_T -city_ground_build(struct logger* logger, struct city* city); +city_ground_build + (struct logger* logger, + struct city* city); res_T city_release(struct city* city); + #endif /*CITY_H*/ diff --git a/src/cg_city_parsing.c b/src/cg_city_parsing.c @@ -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/>. */ + +#include "cg.h" +#include "cg_city_parsing.h" +#include "cg_city_parsing_schemas.h" +#include "cg_ground.h" +#include "cg_city.h" + +#include <star/scpr.h> + +#include <rsys/logger.h> +#include <rsys/mem_allocator.h> + +#include <cyaml/cyaml.h> + +res_T +parse_city + (const char* name, + struct mem_allocator* allocator, + struct logger* logger, + const struct cyaml_config* config, + struct parsed_city** out_parsed) +{ + res_T res = RES_OK; + struct parsed_city *parsed = NULL; + cyaml_err_t err; + + (void)allocator; (void)logger; + + if(!name || !config || !out_parsed) { + res = RES_BAD_ARG; + goto error; + } + + err = cyaml_load_file(name, config, &city_schema, (void**)&parsed, NULL); + + 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; + +exit: + return res; +error: + cyaml_free(config, &city_schema, parsed, 1); + parsed = NULL; + goto exit; +} + +res_T +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; + } + + err = cyaml_free(config, &city_schema, parsed, 1); + + 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; +} diff --git a/src/cg_city_parsing.h b/src/cg_city_parsing.h @@ -0,0 +1,43 @@ +/* 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 CITY_PARSING_H +#define CITY_PARSING_H + +#include <rsys/rsys.h> + +struct cyaml_config; +struct parsed_city; +struct mem_allocator; +struct logger; + +res_T +parse_city + (const char* name, + struct mem_allocator* allocator, + struct logger* logger, + const struct cyaml_config* config, + struct parsed_city** out_parsed); + +res_T +release_parsed_city + (const struct cyaml_config* config, + struct parsed_city* parsed); + +#endif /*CITY_PARSING_H*/ diff --git a/src/cg_city_parsing_schemas.h b/src/cg_city_parsing_schemas.h @@ -0,0 +1,151 @@ +/* Copyright (C) 2022 AMMR (ArcelorMital Maizieres Research SA) + * + * 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_CITY_PARSING_SCHEMAS__ +#define FG_CITY_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_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; + char* dataset_name; + double* vertice; /* flat array of vertice: { x0 y0 x1 y1 x2 y2... } */ + double height; + + unsigned vertice_count; +}; + +struct parsed_ground { + double extent[4]; + double depth; +}; + +struct parsed_city { + struct parsed_city_building* city_building_list; + struct parsed_ground ground; + + unsigned city_building_list_count; +}; + +static const struct cyaml_schema_value coord_schema = { + CYAML_VALUE_FLOAT(CYAML_FLAG_DEFAULT, double), +}; + +static const cyaml_schema_field_t ground_fields_schema[] = { + CYAML_FIELD_FLOAT("depth", CYAML_FLAG_DEFAULT, struct parsed_ground, + depth), + CYAML_FIELD_SEQUENCE_FIXED("extent", CYAML_FLAG_FLOW, struct parsed_ground, + extent, &coord_schema, 4), + CYAML_FIELD_END +}; + +static const struct cyaml_schema_value p_ground_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_ground, + ground_fields_schema), +}; + +static const struct cyaml_schema_value entry_schema_double = { + CYAML_VALUE_FLOAT(CYAML_FLAG_DEFAULT, double), +}; + +static const struct cyaml_schema_value double2_schema = { + CYAML_VALUE_SEQUENCE_FIXED(CYAML_FLAG_DEFAULT, double, + &entry_schema_double, 2), +}; + +static const cyaml_schema_field_t city_building_fields_schema[] = { + CYAML_FIELD_STRING_PTR("id", /* TODO: rename "name" */ + CYAML_FLAG_POINTER, struct parsed_city_building, name, 0, CYAML_UNLIMITED), + CYAML_FIELD_ENUM("model", /* TODO: rename "constructive_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_FLAG_POINTER, struct parsed_city_building, dataset_name, 0, CYAML_UNLIMITED), + { + .key = "polygon", /*TODO: rename "external_polygon" */ + .value = { + .type = CYAML_SEQUENCE, + .flags = CYAML_FLAG_POINTER | CYAML_FLAG_FLOW, + .data_size = sizeof(double[2]), + .sequence = { + .entry = &double2_schema, + .min = 3, + .max = CYAML_UNLIMITED, + } + }, + /* TODO: add list of polygons "internal_polygons" */ + .data_offset = offsetof(struct parsed_city_building, vertice), + .count_size = sizeof(((struct parsed_city_building*)0)->vertice_count), + .count_offset = offsetof(struct parsed_city_building, vertice_count), + }, + CYAML_FIELD_FLOAT("height", CYAML_FLAG_DEFAULT, struct parsed_city_building, + height), + CYAML_FIELD_END +}; + +static const struct cyaml_schema_value city_building_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT, struct parsed_city_building, + city_building_fields_schema), +}; + +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" */ + .value = { + .type = CYAML_SEQUENCE, + .flags = CYAML_FLAG_POINTER, + .data_size = sizeof(struct parsed_city_building), + .sequence = { + .entry = &city_building_schema, + .min = 1, + .max = CYAML_UNLIMITED, + } + }, + .data_offset = offsetof(struct parsed_city, city_building_list), + .count_size = sizeof(((struct parsed_city*)0)->city_building_list_count), + .count_offset = offsetof(struct parsed_city, city_building_list_count), + }, + CYAML_FIELD_END +}; + +/* Top-level schema. The top level value for the city is a mapping. + * Its fields are defined in plan_fields_schema. + */ +static const cyaml_schema_value_t city_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_city, city_fields_schema), +}; + +#endif diff --git a/src/cg_constructive_mode.h b/src/cg_constructive_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 CONSTRUCTIVE_MODE_H__ +#define CONSTRUCTIVE_MODE_H__ + +#include <rsys/rsys.h> +#include "cg_city_parsing_schemas.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 @@ -19,19 +19,15 @@ #include "cg.h" #include "cg_building.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 <star/scad.h> #include <star/scpr.h> -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); -} - static res_T build_floor_footprint (struct scpr_polygon* pg, @@ -344,7 +340,7 @@ error: static res_T building_ground_connection - (const char* prefix, + (const char* prefix, struct scpr_polygon* pg, const double e, struct scad_geometry** connection) @@ -388,34 +384,46 @@ error: res_T init_model0 - (struct building* building, struct htable_parameter_set* catalog) + (struct building* building, + struct mem_allocator* allocator, + struct parsed_city_building* parsed_data, + struct htable_parameter_set* catalog) { res_T res = RES_OK; - struct data_set_cmode_0 data; struct parameter_set* params; + (void)parsed_data; + + building->init = &init_model0; + building->build_cad = &build_cad_model0; + building->export_stl = &export_stl_model0; + building->release = &release_model0; + building->build_footprint = &build_footprint_model0; - params = htable_parameter_set_find(catalog, building->constructive_mode_name); + building->constructive_mode = mode_0; + building->height = parsed_data->height; + str_init(allocator, &building->name); + str_init(allocator, &building->dataset_name); + building->names_initialized = 1; + ERR(str_set(&building->name, parsed_data->name)); + ERR(str_set(&building->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)); + params = htable_parameter_set_find(catalog, &building->dataset_name); if (params == NULL) { res = RES_BAD_ARG; goto error; } - if (params->constructive_mode != building->constructive_mode) { + if (params->constructive_mode != mode_0 + || parsed_data->cmode_type != PARSED_CMODE_0) + { res = RES_BAD_ARG; goto error; } - data = *(struct data_set_cmode_0*)params->data; - building->data = malloc(sizeof(struct data_set_cmode_0)); - if (!building->data) { - res = RES_MEM_ERR; - goto error; - } - *(struct data_set_cmode_0*)(building->data) = data; - building->build_cad = &build_cad_model0; - building->export_stl = &export_stl_model0; - building->release = &release_model0; - building->build_footprint = &build_footprint_model0; + building->data = params->data; exit: return res; @@ -427,16 +435,13 @@ res_T build_cad_model0(struct building* building) { res_T res = RES_OK; - size_t id = building->id; - enum constructive_mode_type model = building->constructive_mode; double height = building->height; struct scpr_polygon* pg = building->pg; struct scpr_polygon* pg_int = NULL; struct data_set_cmode_0* data = (struct data_set_cmode_0 *)building->data; struct data_cad_cmode_0* data_cad; double e_wall; - struct str prefix; - int is_init = 0; + const char* name; if (!building) { res = RES_BAD_ARG; @@ -448,13 +453,7 @@ build_cad_model0(struct building* building) goto error; } - str_init(NULL, &prefix); - is_init = 1; - ERR(str_set(&prefix, "building_")); - ERR(str_append_printf(&prefix, "%lu_", (unsigned long)id)); - ERR(str_append(&prefix, constructive_mode_name[model])); - - data_cad = malloc(sizeof(struct data_cad_cmode_0)); + data_cad = calloc(1, sizeof(struct data_cad_cmode_0)); building->data_cad = (struct data_cad_cmode_0*)data_cad; e_wall = data->wall; @@ -462,32 +461,31 @@ build_cad_model0(struct building* building) ERR(scpr_offset_polygon(pg_int, -e_wall, SCPR_JOIN_MITER)); /* build floor with pg_int */ - ERR(build_floor(str_cget(&prefix), pg_int, building, &data_cad->floor)); + 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(str_cget(&prefix), building, data_cad->floor, &data_cad->roof)); + ERR(build_roof(name, building, data_cad->floor, &data_cad->roof)); /* build wall with pg and pg_int */ - ERR(build_wall(str_cget(&prefix), pg, pg_int, building, &data_cad->wall)); + ERR(build_wall(name, pg, pg_int, building, &data_cad->wall)); /* build cavity */ - ERR(build_cavity(str_cget(&prefix), pg_int, building, &data_cad->cavity)); + ERR(build_cavity(name, pg_int, building, &data_cad->cavity)); ERR(scad_scene_partition()); /* build ground/building connection */ - ERR(building_ground_connection(str_cget(&prefix), pg, e_wall, - &data_cad->ground_connection)); + ERR(building_ground_connection(name, pg, e_wall, &data_cad->ground_connection)); /* build boundary */ - ERR(build_boundary(str_cget(&prefix), building->data_cad)); + ERR(build_boundary(name, building->data_cad)); /* build cavity/floor connectiona*/ - ERR(build_connection(str_cget(&prefix), building->data_cad)); + ERR(build_connection(name, building->data_cad)); exit: - if(is_init) str_release(&prefix); if(pg_int) scpr_polygon_ref_put(pg_int); return res; error: @@ -506,7 +504,7 @@ build_footprint_model0 e_wall = data->wall; - ERR(building_ground_connection(NULL, pg, e_wall, footprint)); + ERR(building_ground_connection(NULL, pg, e_wall, footprint)); exit: return res; @@ -556,17 +554,23 @@ release_model0 (struct building* building) { res_T res = RES_OK; - - struct data_set_cmode_0* data = (struct data_set_cmode_0 *)building->data; struct data_cad_cmode_0* data_cad = (struct data_cad_cmode_0 *)building->data_cad; scpr_polygon_ref_put(building->pg); - str_release(building->constructive_mode_name); - - if (data_cad->connection) free(data_cad->connection); - if (data) free(data); - if (data_cad) free(data_cad); + if(building->names_initialized) { + str_release(&building->name); + str_release(&building->dataset_name); + } + if(data_cad) { + size_t i; + if(data_cad->boundary) scad_geometry_delete(data_cad->boundary); + for(i = 0; i < data_cad->n_connection; i++) { + scad_geometry_delete(data_cad->connection[i]); + } + free(data_cad->connection); + free(data_cad); + } return res; } diff --git a/src/cg_constructive_mode_0.h b/src/cg_constructive_mode_0.h @@ -17,8 +17,8 @@ * 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 BUILDING_MODEL0_H -#define BUILDING_MODEL0_H +#ifndef CONSTRUCTIVE_MODE_0_H +#define CONSTRUCTIVE_MODE_0_H #include <rsys/rsys.h> @@ -27,6 +27,8 @@ struct scad_geometry; struct building; struct htable_parameter_set; struct parameter_set; +struct mem_allocator; +struct parsed_city_building; /* specific data for model 0 */ struct data_set_cmode_0 { @@ -47,7 +49,10 @@ struct data_cad_cmode_0 { res_T init_model0 - (struct building* building, struct htable_parameter_set* catalog); + (struct building* building, + struct mem_allocator* allocator, + struct parsed_city_building* parsed_data, + struct htable_parameter_set* catalog); res_T build_cad_model0(struct building* building); @@ -65,4 +70,4 @@ res_T release_model0 (struct building* building); -#endif /* BUILDING_MODEL0_H */ +#endif /* CONSTRUCTIVE_MODE_0_H */ diff --git a/src/cg_constructive_mode_1.c b/src/cg_constructive_mode_1.c @@ -19,20 +19,14 @@ #include "cg.h" #include "cg_building.h" +#include "cg_city_parsing_schemas.h" +#include "cg_constructive_mode.h" #include <rsys/str.h> #include <rsys/stretchy_array.h> #include <star/scad.h> #include <star/scpr.h> -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); -} - static res_T build_floor (const char* prefix, @@ -1201,34 +1195,46 @@ error: res_T init_model1 - (struct building* building, struct htable_parameter_set* catalog) + (struct building* building, + struct mem_allocator* allocator, + struct parsed_city_building* parsed_data, + struct htable_parameter_set* catalog) { res_T res = RES_OK; - struct data_set_cmode_1 data; struct parameter_set* params; + (void) parsed_data; + + building->init = &init_model1; + building->build_cad = &build_cad_model1; + building->export_stl = &export_stl_model1; + building->release = &release_model1; + building->build_footprint = &build_footprint_model1; - params = htable_parameter_set_find(catalog, building->constructive_mode_name); + building->constructive_mode = mode_1; + building->height = parsed_data->height; + str_init(allocator, &building->name); + str_init(allocator, &building->dataset_name); + building->names_initialized = 1; + ERR(str_set(&building->name, parsed_data->name)); + ERR(str_set(&building->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)); + params = htable_parameter_set_find(catalog, &building->dataset_name); if (params == NULL) { res = RES_BAD_ARG; goto error; } - if (params->constructive_mode != building->constructive_mode) { + if (params->constructive_mode != mode_1 + || parsed_data->cmode_type != PARSED_CMODE_1) + { res = RES_BAD_ARG; goto error; } - data = *(struct data_set_cmode_1*)params->data; - building->data = malloc(sizeof(struct data_set_cmode_1)); - if (!building->data) { - res = RES_MEM_ERR; - goto error; - } - *(struct data_set_cmode_1*)(building->data) = data; - building->build_cad = &build_cad_model1; - building->export_stl = &export_stl_model1; - building->release = &release_model1; - building->build_footprint = &build_footprint_model1; + building->data = params->data; exit: return res; @@ -1240,43 +1246,18 @@ res_T build_cad_model1(struct building* building) { res_T res = RES_OK; - size_t id = building->id; - enum constructive_mode_type model = building->constructive_mode; double height = building->height; struct scpr_polygon* pg = building->pg; struct data_set_cmode_1* data = (struct data_set_cmode_1 *)building->data; struct data_cad_cmode_1* data_cad; - struct str prefix; - int is_init = 0; + const char* name; if (!building) { res = RES_BAD_ARG; goto error; } - str_init(NULL, &prefix); - is_init = 1; - ERR(str_set(&prefix, "building_")); - ERR(str_append_printf(&prefix, "%lu_", (unsigned long)id)); - ERR(str_append(&prefix, constructive_mode_name[model])); - - data_cad = malloc(sizeof(struct data_cad_cmode_1)); - data_cad->wall = NULL; - data_cad->roof = NULL; - data_cad->floor = NULL; - data_cad->intermediate_floor = NULL; - data_cad->habitable_cavity = NULL; - data_cad->crawlspace_cavity = NULL; - data_cad->attic_cavity = NULL; - data_cad->internal_insulation = NULL; - data_cad->external_insulation = NULL; - data_cad->floor_insulation = NULL; - data_cad->roof_insulation = NULL; - data_cad->foundation = NULL; - data_cad->glass = NULL; - data_cad->ground_connection = NULL; - data_cad->boundary = NULL; - data_cad->connection = NULL; + data_cad = calloc(1, sizeof(struct data_cad_cmode_1)); building->data_cad = (struct data_cad_cmode_1*)data_cad; /* build mandatories elements : @@ -1285,11 +1266,12 @@ build_cad_model1(struct building* building) - roof */ - ERR(build_floor(str_cget(&prefix), pg, data, &data_cad->floor)); + name = str_cget(&building->name); + ERR(build_floor(name, pg, data, &data_cad->floor)); - ERR(build_wall(str_cget(&prefix), "wall", pg, height, data, &data_cad->wall)); + ERR(build_wall(name, "wall", pg, height, data, &data_cad->wall)); - ERR(build_roof(str_cget(&prefix), pg, height, data, &data_cad->roof)); + ERR(build_roof(name, pg, height, data, &data_cad->roof)); /* build optionnal elements : - foundation @@ -1302,44 +1284,38 @@ build_cad_model1(struct building* building) if (data->foundation > 0) { double depth = -data->foundation; - ERR(build_wall( - str_cget(&prefix), "foundation", pg, depth, data, &data_cad->foundation)); + ERR(build_wall(name, "foundation", pg, depth, data, &data_cad->foundation)); } else { data_cad->foundation = NULL; } if (data->inter_floor_n > 0) { - ERR(build_inter_floor( - str_cget(&prefix), pg, height, data, &data_cad->intermediate_floor)); + ERR(build_inter_floor(name, pg, height, data, &data_cad->intermediate_floor)); } else { data_cad->intermediate_floor = NULL; } if (data->ext_insulation > 0) { - ERR(build_ext_insulation( - str_cget(&prefix), pg, height, data, &data_cad->external_insulation)); + ERR(build_ext_insulation(name, pg, height, data, &data_cad->external_insulation)); } else { data_cad->external_insulation = NULL; } if (data->int_insulation > 0) { - ERR(build_int_insulation( - str_cget(&prefix), pg, height, data, data_cad->intermediate_floor, + ERR(build_int_insulation(name, pg, height, data, data_cad->intermediate_floor, &data_cad->internal_insulation)); } else { data_cad->internal_insulation = NULL; } if (data->roof_insulation > 0) { - ERR(build_roof_insulation( - str_cget(&prefix), pg, height, data, &data_cad->roof_insulation)); + ERR(build_roof_insulation(name, pg, height, data, &data_cad->roof_insulation)); } else { data_cad->roof_insulation = NULL; } if (data->floor_insulation > 0) { - ERR(build_floor_insulation( - str_cget(&prefix), pg, data, &data_cad->floor_insulation)); + ERR(build_floor_insulation(name, pg, data, &data_cad->floor_insulation)); } else { data_cad->floor_insulation = NULL; } @@ -1351,26 +1327,23 @@ build_cad_model1(struct building* building) */ if (data->attic > 0) { - ERR(build_attic( - str_cget(&prefix), pg, height, data, &data_cad->attic_cavity)); + ERR(build_attic(name, pg, height, data, &data_cad->attic_cavity)); } else { data_cad->attic_cavity = NULL; } - ERR(build_habitable( - str_cget(&prefix), pg, height, data, data_cad->intermediate_floor, + ERR(build_habitable(name, pg, height, data, data_cad->intermediate_floor, &data_cad->habitable_cavity)); if (data->crawl > 0) { - ERR(build_crawlspace( - str_cget(&prefix), pg, data, &data_cad->crawlspace_cavity)); + ERR(build_crawlspace(name, pg, data, &data_cad->crawlspace_cavity)); } else { data_cad->crawlspace_cavity = NULL; } /* windows */ if (data->glass_ratio > 0) { - ERR(build_windows(str_cget(&prefix), data, data_cad)); + ERR(build_windows(name, data, data_cad)); } /* fake ground */ @@ -1379,19 +1352,17 @@ build_cad_model1(struct building* building) ERR(scad_scene_partition()); /* build ground/buildind connection */ - ERR(building_ground_connection(str_cget(&prefix), data_cad, - &data_cad->ground_connection)); + ERR(building_ground_connection(name, data_cad, &data_cad->ground_connection)); /* build boundaries */ data_cad->boundary = NULL; - ERR(build_boundary(str_cget(&prefix), data_cad, &data_cad->boundary)); + ERR(build_boundary(name, data_cad, &data_cad->boundary)); /* build connections */ data_cad->connection = NULL; - ERR(build_connection(str_cget(&prefix), data_cad, &data_cad->connection)); + ERR(build_connection(name, data_cad, &data_cad->connection)); exit: - if (is_init) str_release(&prefix); return res; error: goto exit; @@ -1507,17 +1478,27 @@ release_model1 (struct building* building) { res_T res = RES_OK; - struct data_set_cmode_1* data = (struct data_set_cmode_1 *)building->data; struct data_cad_cmode_1* data_cad = (struct data_cad_cmode_1 *)building->data_cad; scpr_polygon_ref_put(building->pg); - str_release(building->constructive_mode_name); + if(building->names_initialized) { + str_release(&building->name); + str_release(&building->dataset_name); + } - if (data_cad->boundary) sa_release(data_cad->boundary); - if (data_cad->connection) sa_release(data_cad->connection); - if (data) free(data); - if (data_cad) free(data_cad); + if(data_cad) { + size_t i; + for(i = 0; i < sa_size(data_cad->boundary); i++) { + scad_geometry_delete(data_cad->boundary[i]); + } + for(i = 0; i < data_cad->n_connection; i++) { + scad_geometry_delete(data_cad->connection[i]); + } + sa_release(data_cad->boundary); + sa_release(data_cad->connection); + free(data_cad); + } return res; } diff --git a/src/cg_constructive_mode_1.h b/src/cg_constructive_mode_1.h @@ -17,8 +17,8 @@ * 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 BUILDING_MODEL1_H -#define BUILDING_MODEL1_H +#ifndef CONSTRUCTIVE_MODE_1_H +#define CONSTRUCTIVE_MODE_1_H #include <rsys/rsys.h> @@ -27,6 +27,8 @@ struct scad_geometry; struct building; struct htable_parameter_set; struct parameter_set; +struct mem_allocator; +struct parsed_city_building; /* specific data for constructive mode 1 */ struct data_set_cmode_1 { @@ -68,7 +70,10 @@ struct data_cad_cmode_1 { res_T init_model1 - (struct building* building, struct htable_parameter_set* catalog); + (struct building* building, + struct mem_allocator* allocator, + struct parsed_city_building* parsed_data, + struct htable_parameter_set* catalog); res_T build_cad_model1(struct building* building); @@ -86,4 +91,4 @@ res_T release_model1 (struct building* building); -#endif /* BUILDING_MODEL1_H */ +#endif /* CONSTRUCTIVE_MODE_1_H */ diff --git a/src/cg_ground.c b/src/cg_ground.c @@ -32,8 +32,6 @@ ground_build_cad double extent[3]; struct scad_geometry* ground_box = NULL; struct scad_geometry* bound = NULL; - struct str name; - int is_init = 0; if (!ground) { res = RES_BAD_ARG; @@ -53,23 +51,13 @@ ground_build_cad goto error; } - str_init(NULL, &name); - is_init = 1; - ERR(str_set(&name, "ground")); - - ERR(scad_add_box - (NULL /*str_cget(&name)*/, - origin, - extent, - &ground_box)); - + ERR(scad_add_box(NULL, origin, extent, &ground_box)); ERR(scad_geometry_boundary(NULL, &ground_box, 1, &bound)); ERR(scad_cut_geometries(NULL, &bound, 1, - ground->footprint, ground->n, &ground->boundary)); + ground->footprint, ground->footprints_count, &ground->boundary)); exit: - if (is_init) str_release(&name); if (bound) scad_geometry_delete(bound); return res; error: diff --git a/src/cg_ground.h b/src/cg_ground.h @@ -35,7 +35,7 @@ struct ground { struct scad_geometry* geometry; struct scad_geometry* boundary; struct scad_geometry** footprint; /* list of building footprint */ - size_t n; /* number of footprint */ + size_t footprints_count; /* number of footprint */ }; #define GROUND_NULL__ {{0,0,0,0}, 0, NULL, NULL, NULL, NULL, 0} diff --git a/src/cg_main.c b/src/cg_main.c @@ -21,6 +21,10 @@ #include "cg_args.h" #include "cg_building.h" #include "cg_city.h" +#include "cg_city_parsing.h" +#include "cg_parsing.h" + +#include <cyaml/cyaml.h> #include <rsys/rsys.h> #include <rsys/logger.h> @@ -41,16 +45,62 @@ check_memory_allocator(struct mem_allocator* allocator) { } } +static void cg_log + (enum cyaml_log_e level, + void *_ctx, + const char *fmt, + va_list args) +{ + struct logger* logger = (struct logger*)_ctx; + enum log_type type; + ASSERT(logger && fmt); + + switch(level) { + case CYAML_LOG_ERROR: type = LOG_ERROR; break; + case CYAML_LOG_WARNING: type = LOG_WARNING; break; + case CYAML_LOG_NOTICE: type = LOG_OUTPUT; break; + default: return; /* Do not log this level of messages */ + } + logger_vprint(logger, type, fmt, args); +} + +static void* cg_mem + (void *ctx, + void *ptr, + size_t size) +{ + struct mem_allocator* allocator = (struct mem_allocator*)ctx; + ASSERT(allocator); + if(size == 0) { + /* free() request */ + MEM_RM(allocator, ptr); + return NULL; + } else { + return MEM_REALLOC(allocator, ptr, size); + } +} + int main (int argc, char** argv) { int err = EXIT_SUCCESS; res_T res = RES_OK; struct args args; - struct city city = CITY_NULL; + struct city* city = NULL; struct logger logger; struct mem_allocator allocator; + struct parsed_city* parsed_city; + struct htable_parameter_set catalog; 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, + .mem_fn = cg_mem, + .mem_ctx = &allocator, + .log_level = CYAML_LOG_WARNING, /* Logging errors and warnings only. */ + .flags = CYAML_CFG_DEFAULT, + }; /* init allocator and logger */ ERR(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); @@ -82,12 +132,28 @@ int main if(args.verbose < 3) logger_set_stream(&logger, LOG_OUTPUT, NULL, NULL); - ERR(city_init(&logger, &city, &args)); - ERR(city_cad_build(&logger, &city)); - ERR(city_ground_build(&logger, &city)); + /* Parse city description. + * No semantic validation is done at this stage */ + ERR(parse_city(args.city_filename, &allocator, &logger, &config, &parsed_city)); + parsed_city_initialized = 1; + + /* Parse catalog. */ + ERR(parse_catalog(&logger, &catalog)); + + /* Feed 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(city_ground_build(&logger, city)); + ERR(city_cad_build(&logger, city)); exit: - city_release(&city); + if(cg_initialized) city_release(city); + if(parsed_city_initialized) release_parsed_city(&config, parsed_city); if(logger_initialized) logger_release(&logger); if(allocator_initialized) { check_memory_allocator(&allocator); diff --git a/src/cg_parsing.c b/src/cg_parsing.c @@ -19,353 +19,12 @@ #include "cg.h" #include "cg_parsing.h" -#include "cg_ground.h" #include "cg_building.h" -#include "cg_city.h" -#include <star/scpr.h> - -#include <rsys/cstr.h> #include <rsys/logger.h> #include <rsys/str.h> -#include <rsys/text_reader.h> #include <rsys/stretchy_array.h> - /*Funtion removing spaces from string*/ -static char* -remove_spaces(char *string) -{ - /*non_space_count to keep the frequency of non space characters*/ - int i; - int non_space_count = 0; - - /*Traverse a string and if it is non space character then, place it at - * index non_space_count*/ - for (i = 0; string[i] != '\0'; i++) { - if (string[i] != ' ') { - string[non_space_count] = string[i]; - non_space_count++; /* non_space_count incremented */ - } - } - - /*Finally placing final character at the string end*/ - string[non_space_count] = '\0'; - return string; -} - -static res_T -strtolower(const char * src, char* dst ) -{ - res_T res = RES_OK; - - if (!src || !dst) { - res = RES_BAD_ARG; - goto error; - } - - while((*dst++ = (char)tolower(*src++ ))); - -exit: - return res; -error: - goto exit; -} - -static enum constructive_mode_type get_enum_value(char * val) -{ - int i=0; - for (i=0; i<CONSTRUCTIVE_MODES_COUNT__; ++i) - if (!strcmp(constructive_mode_name[i], val)) - return (enum constructive_mode_type)i; - return CONSTRUCTIVE_MODES_COUNT__; -} - -static res_T -parse_ground - (struct logger* logger, - struct txtrdr* reader, - struct ground* ground) -{ - res_T res = RES_OK; - char* line = NULL; - - ERR(txtrdr_read_line(reader)); - while (txtrdr_get_line(reader)){ - double depth = 0; - char* value = NULL; - - line = remove_spaces(txtrdr_get_line(reader)); - ERR(strtolower(line, line)); - - if (sscanf(line, "depth=%lf", &depth) == 1 ) { - ground->depth = depth; - } - - value = malloc((1 + strlen(line )) * sizeof(char)); - if (sscanf(line, "extent=%s", value) == 1 ) { - size_t sz = 0; - if (cstr_to_list_double(value, ',', ground->extent, &sz, 4) - != RES_OK || sz != 4) - { - logger_print(logger, LOG_ERROR, - "[ground] extent value not valid: 4 values required.\n"); - res = RES_BAD_ARG; - if (value) free(value); - goto error; - } - } - if (value) free(value); - - /*if new section break*/ - if (sscanf(line, "[%[^]]", value) == 1 ) { - break; - } - ERR(txtrdr_read_line(reader)); - } - - /*check depth*/ - if (ground->depth <= 0) { - logger_print(logger, LOG_ERROR, - "[ground] depth value not valid: must be > 0.\n"); - res = RES_BAD_ARG; - goto error; - } - - /*check extent*/ - if (ground->extent[0] >= ground->extent[1] - || ground->extent[2] >= ground->extent[3]) { - logger_print(logger, LOG_ERROR, - "[ground] extent value not valid: xmax must be > xmin and ymax must be > ymin.\n"); - res = RES_BAD_ARG; - goto error; - } - -exit: - return res; -error: - goto exit; -} - -struct polygon_context{ - double* pos; - size_t* nvert; - size_t ncomps; -}; - -static void -get_nverts(const size_t icomp, size_t* nverts, void* context) -{ - const struct polygon_context* pg_ctx = context; - *nverts = pg_ctx->nvert[icomp]; -} - -static void -get_pos(const size_t icomp, const size_t ivert, double pos[2], void* context) -{ - const struct polygon_context* pg_ctx = context; - size_t i, begin = 0; - - for (i=0; i<icomp; ++i) { - begin += pg_ctx->nvert[i]*2; - } - pos[0] = pg_ctx->pos[begin + ivert*2 + 0]; - pos[1] = pg_ctx->pos[begin + ivert*2 + 1]; -} - -static res_T -parse_polygon(const char* str, void* data) -{ - res_T res = RES_OK; - struct polygon_context* pg_ctx = data; - double value; - - ERR(cstr_to_double(str, &value)); - - pg_ctx->nvert[pg_ctx->ncomps] += 1; - sa_push(pg_ctx->pos, value); - -exit: - return res; -error: - goto exit; -} - -static res_T -parse_polygon_list(const char* str, void* data) -{ - res_T res = RES_OK; - struct polygon_context* pg_ctx = data; - double* pos = NULL; - - sa_push(pg_ctx->nvert, 0); - ERR(cstr_parse_list(str, ',', parse_polygon, pg_ctx)); - if (pg_ctx->nvert[pg_ctx->ncomps]%2 != 0) { - res = RES_BAD_ARG; - goto error; - } else { - pg_ctx->nvert[pg_ctx->ncomps] /= 2; - } - pg_ctx->ncomps += 1; - -exit: - if (pos) sa_release(pos); - return res; -error: - goto exit; -} - -static res_T -parse_building - (struct logger* logger, - struct txtrdr* reader, - struct building* building) -{ - res_T res = RES_OK; - char* line = NULL; - int m; - (void)logger; - - ERR(txtrdr_read_line(reader)); - while (txtrdr_get_line(reader)){ - size_t id = 0; - double height = 0; - char* value = NULL; - char* tmp; - - tmp = txtrdr_get_line(reader); - line = remove_spaces(tmp); - ERR(strtolower(line, line)); - value = malloc(( strlen(line )) * sizeof(char)); - - if (sscanf(line, "id=%lu", &id) == 1 ) { - building->id = id; - } - - else if (sscanf(line, "height=%lf", &height) == 1 ) { - building->height = height; - } - - else if (sscanf(line, "polygon=%s", value) == 1 ) { - struct polygon_context pg_ctx = {NULL, NULL, 0}; - - ERR(scpr_polygon_create(NULL, &building->pg)); - if (cstr_parse_list(value, ';', parse_polygon_list, &pg_ctx) != RES_OK ) { - size_t line_num; - line_num = txtrdr_get_line_num(reader); - logger_print(logger, LOG_ERROR, - "[polygon] description not valid on line: %lu\n", - (unsigned long)line_num); - goto error; - } - - ERR(scpr_polygon_setup_indexed_vertices( - building->pg, pg_ctx.ncomps, - get_nverts, - get_pos, - &pg_ctx)); - - sa_release(pg_ctx.pos); - sa_release(pg_ctx.nvert); - } - - else if (sscanf(line, "model=model%d", &m) == 1 ) { - switch(m) { - case 0: - building->constructive_mode = mode_0; - break; - case 1: - building->constructive_mode = mode_1; - break; - default: - res = RES_BAD_ARG; - goto error; - } - } - - else if (sscanf(line, "data=%s", value) == 1 ) { - building->constructive_mode_name = malloc(sizeof(struct str)); - str_init(NULL, building->constructive_mode_name); - str_set(building->constructive_mode_name, value); - } - - /*if new section break*/ - else if (sscanf(line, "[%[^]]", value) == 1 ) { - break; - } - - else { - printf("===> %s \n", line); - res = RES_BAD_ARG; - goto error; - } - - free(value); - ERR(txtrdr_read_line(reader)); - } - - /*check height*/ - if (building->height <= 0) { - logger_print(logger, LOG_ERROR, - "[building] height value not valid: must be > 0.\n"); - res = RES_BAD_ARG; - goto error; - } - - /*check model*/ - if (building->constructive_mode == CONSTRUCTIVE_MODES_COUNT__) { - logger_print(logger, LOG_ERROR, - "[model] not recognized.\n"); - res = RES_BAD_ARG; - goto error; - } - - /*TODO : check polygon and unique id*/ - -exit: - return res; -error: - goto exit; -} - -/*----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ - -res_T -parse_city - (struct logger* logger, - struct txtrdr* reader, - struct city* city) -{ - res_T res = RES_OK; - char* line = NULL; - struct building b; - - ERR(txtrdr_read_line(reader)); - - while (txtrdr_get_line(reader)){ - line = txtrdr_get_line(reader); - ERR(strtolower(line, line)); - if (strcmp(line, "[building]") == 0) { - ERR(parse_building(logger, reader, &b)); - sa_push(city->building, b); - continue; - } - if (strcmp(line, "[ground]") == 0) { - ERR(parse_ground(logger, reader, &city->ground)); - continue; - } - ERR(txtrdr_read_line(reader)); - } - - city->n = sa_size(city->building); - -exit: - return res; -error: - goto exit; -} - res_T parse_catalog (struct logger* logger, @@ -392,7 +51,7 @@ parse_catalog } params0[0].constructive_mode = mode_0; str_init(NULL, &params0[0].name); - str_set(&params0[0].name, "b0"); + 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)); @@ -406,7 +65,7 @@ parse_catalog } params0[1].constructive_mode = mode_1; str_init(NULL, &params0[1].name); - str_set(&params0[1].name, "b1"); + ERR(str_set(&params0[1].name, "b1")); data1->wall = 0.25; data1->floor = 0.35; data1->inter_floor = 0.2; diff --git a/src/cg_parsing.h b/src/cg_parsing.h @@ -28,19 +28,12 @@ struct txtrdr; struct logger; struct htable_parameter_set; -struct city; struct parameter_set; res_T -parse_city - (struct logger* logger, - struct txtrdr* reader, - struct city* city); - -res_T parse_catalog (struct logger* logger, - struct htable_parameter_set* ht_params); + struct htable_parameter_set* catalog); res_T release_params_building(struct parameter_set* params);