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:
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, ¶ms0[0].name);
- str_set(¶ms0[0].name, "b0");
+ ERR(str_set(¶ms0[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, ¶ms0[1].name);
- str_set(¶ms0[1].name, "b1");
+ ERR(str_set(¶ms0[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);