commit 6f43c1eb62dd77e8c902ce5b18b1171b5e80634e
parent 1f83d75b99cfbf46a96a129b3436b6b3618b8c18
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Mon, 9 Jan 2023 16:07:48 +0100
Merge branch 'feature_yaml_data' into develop
Diffstat:
31 files changed, 3815 insertions(+), 3035 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,24 +53,32 @@ 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_catalog.c
+ cg_catalog_parsing.c
cg_city.c
- cg_building_model0.c
- cg_building_model1.c
+ cg_city_parsing.c
+ cg_constructive_mode_0.c
+ cg_constructive_mode_1.c
cg_ground.c
- cg_args.c
- cg_parsing.c)
+ cg_main.c)
set(CG2_FILES_INC
cg.h
cg_args.h
cg_building.h
- cg_building_model0.h
- cg_building_model1.h
+ cg_catalog.h
+ cg_catalog_parsing.h
cg_city.h
+ cg_city_parsing.h
+ cg_city_parsing_schemas.h
+ cg_constructive_mode.h
+ cg_constructive_mode_0.h
+ cg_constructive_mode_0_parsing_schemas.h
+ cg_constructive_mode_1.h
+ cg_constructive_mode_1_parsing_schemas.h
cg_default.h.in
cg_ground.h
- cg_parsing.h
cg_version.h.in)
set(CG2_ARGS_DEFAULT_VERBOSE_LEVEL "1")
@@ -95,7 +105,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.h b/src/cg.h
@@ -20,7 +20,51 @@
#ifndef CG_H
#define CG_H
+#include <rsys/rsys.h>
+#include <cyaml/cyaml.h>
+
#define ERR(Expr) if((res = (Expr)) != RES_OK) goto error; else (void)0
+static INLINE void
+log_prt_fn(const char* msg, void* ctx)
+{
+ ASSERT(msg);
+ (void)ctx;
+
+ fprintf(stderr, "\x1b[32moutput:\x1b[0m %s", msg);
+}
+
+static INLINE void
+log_warn_fn(const char* msg, void* ctx)
+{
+ ASSERT(msg);
+ (void)ctx;
+
+ fprintf(stderr, "\x1b[33mwarning:\x1b[0m %s", msg);
+}
+
+static INLINE void
+log_err_fn(const char* msg, void* ctx)
+{
+ ASSERT(msg);
+ (void)ctx;
+
+ fprintf(stderr, "\x1b[31merror:\x1b[0m %s", msg);
+}
+
+static INLINE res_T
+cyaml_err_to_res_T(const cyaml_err_t err)
+{
+ res_T res = RES_OK;
+
+ switch(err) {
+ case CYAML_OK: res = RES_OK; break;
+ case CYAML_ERR_OOM: res = RES_MEM_ERR; break;
+ case CYAML_ERR_FILE_OPEN: res = RES_IO_ERR; break;
+ default: res = RES_UNKNOWN_ERR; break;
+ }
+ return res;
+}
+
#endif /*CG_H*/
diff --git a/src/cg_args.c b/src/cg_args.c
@@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "cg_args.h"
+#include "cg_catalog_parsing.h"
#include "cg_version.h"
#include "cg_default.h"
#include "cg.h"
@@ -41,17 +42,18 @@ short_help(void)
{
print_version();
printf("\nUsage:\n"
- "city_generator2 [-a] -b <FILE> -c <FILE> [-V verbosity]\n"
+ "city_generator2 -m <FILENAME> -c <FILENAME> [-V verbosity]\n"
"city_generator2 [-h]\n"
"city_generator2 [-v]\n"
);
printf(
"\nMandatory options\n"
"-----------------\n"
- "-b <building_model_file>\n"
- " Read a yaml text file that describes the building.\n"
- "-c <city_model_file>\n"
- " Read a yaml text file that describes the city.\n"
+ "-c <filename>\n"
+ " Read a yaml text file containing datasets for a given constructive mode.\n"
+ " Can be used more than once.\n"
+ "-m <city_map_filename>\n"
+ " Read a yaml text file that describes the city map.\n"
"\nOther options\n"
"-------------\n"
"-h\n"
@@ -80,19 +82,35 @@ short_help(void)
res_T
parse_args
- (struct logger* logger,
+ (struct mem_allocator* allocator,
+ struct logger* logger,
int argc,
char** argv,
- struct args* args)
+ struct args** out_args)
{
res_T res = RES_OK;
int opt;
- int info_provided = 0, b_provided = 0, c_provided = 0;
- struct args aaa = ARGS_NULL__;
- const char option_list[] = "b:c:f:hvV:";
+ int info_provided = 0, c_provided = 0, m_provided = 0;
+ struct args* args;
+ const char option_list[] = "c:m:f:hvV:";
+
+ ASSERT(allocator && logger && argv && out_args);
+
+ args = MEM_ALLOC(allocator, sizeof(*args));
+ if(!args) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ args->allocator = allocator;
+ args->logger = logger;
/* Set default values */
- *args = aaa;
+ args->city_filename = NULL;
+ darray_catalog_filenames_init(allocator, &args->catalog_filenames);
+ args->binary_export = CG2_BINARY_EXPORT_DEFAULT;
+ args->verbosity_level = CG2_DEFAULT_VERBOSE_LEVEL;
+ args->print_help = 0;
+ args->print_version = 0;
opterr = 0; /* No default error messages */
while((opt = getopt(argc, argv, option_list)) != -1) {
@@ -113,14 +131,19 @@ parse_args
goto error;
}
- case 'b':
- if(b_provided) {
+ case 'c':
+ c_provided = 1;
+ ERR(darray_catalog_filenames_push_back(&args->catalog_filenames, &optarg));
+ break;
+
+ case 'm':
+ if(m_provided) {
logger_print(logger, LOG_ERROR, "Option -%c provided twice.\n", opt);
res = RES_BAD_ARG;
goto error;
}
- args->building_model_file = optarg;
- b_provided = 1;
+ args->city_filename = optarg;
+ m_provided = 1;
break;
case 'f':
@@ -142,26 +165,16 @@ parse_args
args->print_help = 1;
break;
- case 'c':
- if(c_provided) {
- logger_print(logger, LOG_ERROR, "Option -%c provided twice.\n", opt);
- res = RES_BAD_ARG;
- goto error;
- }
- args->city_model_file = optarg;
- c_provided = 1;
- break;
-
case 'v':
info_provided = 1;
args->print_version = 1;
break;
case 'V':
- res = cstr_to_int(optarg, &args->verbose);
+ res = cstr_to_int(optarg, &args->verbosity_level);
if(res != RES_OK
- || args->verbose < 0
- || args->verbose > 3)
+ || args->verbosity_level < 0
+ || args->verbosity_level > 3)
{
if(res == RES_OK) res = RES_BAD_ARG;
logger_print(logger, LOG_ERROR,
@@ -183,22 +196,35 @@ parse_args
goto error;
}
- if(!b_provided && !info_provided) {
+ if(!c_provided && !info_provided) {
ERR(logger_print(logger, LOG_ERROR,
- "Missing mandatory argument: -b <building_model_file>\n"));
+ "Missing mandatory argument: -b <construction_mode_filename>\n"));
res = RES_BAD_ARG;
goto error;
}
- if(!c_provided && !info_provided) {
+ if(!m_provided && !info_provided) {
ERR(logger_print(logger, LOG_ERROR,
- "Missing mandatory argument: -c <city_model_file>\n"));
+ "Missing mandatory argument: -c <city_filename>\n"));
res = RES_BAD_ARG;
goto error;
}
exit:
+ *out_args = args;
return res;
error:
+ release_args(args);
+ args = NULL;
goto exit;
}
+
+void
+release_args
+ (struct args* args)
+{
+ if(!args) return;
+
+ darray_catalog_filenames_release(&args->catalog_filenames);
+ MEM_RM(args->allocator, args);
+}
diff --git a/src/cg_args.h b/src/cg_args.h
@@ -20,27 +20,37 @@
#ifndef PARSE_ARGS_H
#define PARSE_ARGS_H
-#include "cg_default.h"
-
#include <rsys/rsys.h>
+#include <rsys/dynamic_array.h>
struct logger;
-struct args;
+#define DARRAY_NAME catalog_filenames
+#define DARRAY_DATA char*
+#include <rsys/dynamic_array.h>
struct args {
- char* city_model_file;
- char* building_model_file;
+ struct mem_allocator* allocator;
+ struct logger* logger;
+ char* city_filename;
+ struct darray_catalog_filenames catalog_filenames;
int binary_export;
- int verbose;
+ int verbosity_level;
int print_help;
int print_version;
};
-#define ARGS_NULL__ \
- { NULL, NULL, CG2_BINARY_EXPORT_DEFAULT, CG2_DEFAULT_VERBOSE_LEVEL, 0, 0 }
res_T
-parse_args(struct logger* logger, int argc, char** argv, struct args* args);
+parse_args
+ (struct mem_allocator* allocator,
+ struct logger* logger,
+ int argc,
+ char** argv,
+ struct args** out_args);
+
+void
+release_args
+ (struct args* args);
void
print_version(void);
diff --git a/src/cg_building.h b/src/cg_building.h
@@ -24,73 +24,61 @@
#include <rsys/str.h>
#include <rsys/hash_table.h>
+#include "cg_constructive_mode_0.h"
+#include "cg_constructive_mode_1.h"
+
struct scpr_polygon;
struct scad_geometry;
+struct mem_allocator;
+struct logger;
+struct catalog;
-enum model_type {
- model0,
- model1,
- MODEL_COUNT_
+/* A type to store the functors of a constructive mode */
+struct constructive_mode_functors {
+ res_T (*init)
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ struct parsed_city_building* parsed_data,
+ struct catalog* catalog);
+ res_T (*build_cad)
+ (struct building* building, struct mem_allocator* allocator,
+ struct logger* logger, void** cad);
+ res_T (*build_footprint)
+ (struct building* building, struct mem_allocator* allocator,
+ struct logger* logger, struct scad_geometry** footprint);
+ res_T (*export_stl)
+ (void* cad, struct mem_allocator* allocator, struct logger* logger,
+ const int binary);
+ res_T (*release_cad)
+ (struct mem_allocator* allocator, struct logger* logger, void* cad);
};
-extern char const* model_str[1];
-
-struct building_params {
- enum model_type model;
- struct str name;
- void* data;
+/* A type to give an ID to constructive modes.
+ * Add a new entry for each new constructive mode. */
+enum constructive_mode_type {
+ mode_0,
+ mode_1,
+ CONSTRUCTIVE_MODES_COUNT__
};
+/* The name of the constructive modes, as expected in the city description. */
+extern char const* constructive_mode_name[CONSTRUCTIVE_MODES_COUNT__];
-static INLINE char
-eq_str(const struct str* a, const struct str* b)
-{
- return !strcmp(str_cget(a), str_cget(b));
-}
-
-static INLINE size_t
-hash_str(const struct str* a)
-{
- return hash_fnv32(str_cget(a), str_len(a));
-}
-
-#define HTABLE_NAME building_params
-#define HTABLE_DATA struct building_params
-#define HTABLE_KEY struct str
-#define HTABLE_KEY_FUNCTOR_INIT str_init
-#define HTABLE_KEY_FUNCTOR_RELEASE str_release
-#define HTABLE_KEY_FUNCTOR_COPY str_copy
-#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release
-#define HTABLE_KEY_FUNCTOR_EQ eq_str
-#define HTABLE_KEY_FUNCTOR_HASH hash_str
-#include <rsys/hash_table.h>
-
-
-/* the specific building model functors headers must be included here */
-#include "cg_building_model0.h"
-#include "cg_building_model1.h"
-
+/* The type of buildings as described in the city description */
struct building {
- /* generic building data */
- size_t id;
- enum model_type model;
- struct str* data_name;
+ /* constructive mode */
+ struct constructive_mode_functors* functors;
+ enum constructive_mode_type constructive_mode;
+
+ /* generic constructive mode data */
+ int name_initialized;
+ struct str name;
double height;
struct scpr_polygon* pg;
- /* specific data depending model */
+ /* specific data depending to the constructive mode */
void* data;
- void* data_cad;
-
- /* functors depending model */
- res_T (*init)
- (struct building* building, struct htable_building_params* htparams);
- 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);
};
#endif /* BUILDING_H */
diff --git a/src/cg_building_model0.c b/src/cg_building_model0.c
@@ -1,572 +0,0 @@
-/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
- * Copyright (C) 2022 CNRS
- * Copyright (C) 2022 Sorbonne Université
- * Copyright (C) 2022 Université Paul Sabatier
- * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "cg.h"
-#include "cg_building.h"
-
-#include <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,
- struct scad_geometry** footprint)
-{
- res_T res = RES_OK;
- size_t nverts;
- ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
- ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, footprint));
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_floor
- (const char* prefix,
- struct scpr_polygon* pg,
- struct building* b,
- struct scad_geometry** floor)
-{
- res_T res = RES_OK;
- double e;
- struct data_model0* data;
- struct scad_geometry* footprint = NULL;
- double d[3] = {0, 0, 0};
- char* floorname = NULL;
- struct str name;
- int is_init = 0;
-
- data = (struct data_model0*)b->data;
- e = data->floor;
-
- str_init(NULL, &name);
- is_init = 1;
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_floor"));
- floorname = str_get(&name);
- }
-
- ERR(build_floor_footprint(pg, &footprint));
-
- d[2] = e;
- ERR(scad_geometry_extrude(footprint, floorname, d, floor));
-
-exit:
- scad_geometry_delete(footprint);
- if (is_init) str_release(&name);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_roof
- (const char* prefix,
- const struct building* b,
- const struct scad_geometry* floor,
- struct scad_geometry** roof)
-{
- res_T res = RES_OK;
- double height;
- double e;
- double d[3] = {0, 0, 0};
- struct data_model0* data;
- /*struct data_cad_model0* data_cad;*/
- char* roofname = NULL;
- struct str name;
- int is_init = 0;
-
- str_init(NULL, &name);
- is_init = 1;
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_roof"));
- roofname = str_get(&name);
- }
-
- height = b->height;
- data = (struct data_model0*)b->data;
- /*data_cad = (struct data_cad_model0*)b->data_cad;*/
- e = data->floor;
-
- ERR(scad_geometry_copy(floor, roofname, roof));
- d[2] = height - e ;
- ERR(scad_geometry_translate(*roof, d));
-
-exit:
- if (is_init) str_release(&name);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_wall_footprint
- (struct scpr_polygon* pg,
- struct scpr_polygon* pg_int,
- struct scad_geometry** footprint)
-{
- res_T res = RES_OK;
- /*struct data_cad_model0* data_cad;*/
- struct scad_geometry* polygon = NULL;
- struct scad_geometry* polygon_int = NULL;
- size_t nverts, nverts_int;
-
- ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
- ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, &polygon));
-
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts_int));
- ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts_int, &polygon_int));
-
- ERR(scad_cut_geometries(NULL, &polygon, 1, &polygon_int, 1, footprint));
-
-exit:
- if(polygon) scad_geometry_delete(polygon);
- if(polygon_int) scad_geometry_delete(polygon_int);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_wall
- (const char* prefix,
- struct scpr_polygon* pg,
- struct scpr_polygon* pg_int,
- struct building* b,
- struct scad_geometry** wall)
-{
- res_T res = RES_OK;
- double height;
- struct scad_geometry* footprint = NULL;
- double d[3] = {0, 0, 0};
- char* wallname = NULL;
- struct str name;
- int is_init = 0;
-
- height = b->height;
-
- str_init(NULL, &name);
- is_init = 1;
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_wall"));
- wallname = str_get(&name);
- }
-
- ERR(build_wall_footprint(pg, pg_int, &footprint));
-
- d[2] = height;
- ERR(scad_geometry_extrude(footprint, wallname, d, wall));
-
-exit:
- if(footprint) scad_geometry_delete(footprint);
- if (is_init) str_release(&name);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_cavity
- (const char* prefix,
- struct scpr_polygon* pg,
- const struct building* b,
- struct scad_geometry** cavity)
-{
- res_T res = RES_OK;
- double e, height;
- struct data_model0* data;
- double d[3] = {0, 0, 0};
- struct scad_geometry* polygon = NULL;
- char* cavityname = NULL;
- struct str name;
- int is_init = 0;
- size_t nverts;
-
- height = b->height;
- data = (struct data_model0*)b->data;
- e = data->floor;
-
- str_init(NULL, &name);
- is_init = 1;
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_cavity"));
- cavityname = str_get(&name);
- }
-
- ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
- ERR(scad_add_polygon(NULL, get_position_pg, pg, e, nverts, &polygon));
-
- d[2] = height - e;
- ERR(scad_geometry_extrude(polygon, cavityname, d, cavity));
-
-exit:
- if(polygon) scad_geometry_delete(polygon);
- if (is_init) str_release(&name);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_connection
- (const char* prefix,
- struct data_cad_model0* cad)
-{
- res_T res = RES_OK;
- char* cname = NULL;
- struct str name;
- int is_init = 0;
-
- cad->connection = malloc(3 * sizeof(struct scad_geometry*));
- cad->n_connection = 3;
-
- /* cavity/floor connection */
- str_init(NULL, &name);
- is_init = 1;
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_C_cavity_floor"));
- cname = str_get(&name);
- }
-
- ERR(scad_geometries_common_boundaries
- (cname,
- &cad->cavity, 1,
- &cad->floor, 1,
- &cad->connection[0]));
-
- /* cavity/wall connection */
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_C_cavity_wall"));
- cname = str_get(&name);
- }
-
- ERR(scad_geometries_common_boundaries
- (cname,
- &cad->cavity, 1,
- &cad->wall, 1,
- &cad->connection[1]));
-
- /* cavity/roof connection */
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_C_cavity_roof"));
- cname = str_get(&name);
- }
-
- ERR(scad_geometries_common_boundaries
- (cname,
- &cad->cavity, 1,
- &cad->roof, 1,
- &cad->connection[2]));
-
-exit:
- if (is_init) str_release(&name);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_boundary
- (const char* prefix,
- struct data_cad_model0* cad)
-{
- res_T res = RES_OK;
- struct scad_geometry** list = NULL;
- struct scad_geometry* boundary = NULL;
- /*struct scad_geometry* footprint = NULL;*/
- char* cname = NULL;
- struct str name;
- int is_init = 0;
-
- list = malloc(4 * sizeof(struct scad_geometry*));
- list[0] = cad->floor;
- list[1] = cad->wall;
- list[2] = cad->roof;
- list[3] = cad->cavity;
-
- str_init(NULL, &name);
- is_init = 1;
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_boundary"));
- cname = str_get(&name);
- }
-
- ERR(scad_geometry_boundary(NULL, list, 4, &boundary));
-
- ERR(scad_cut_geometries(cname, &boundary, 1, &cad->ground_connection, 1,
- &cad->boundary));
-
-exit:
- if(boundary) scad_geometry_delete(boundary);
- /*if(footprint) scad_geometry_delete(footprint);*/
- if (list) free(list);
- if (is_init) str_release(&name);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-building_ground_connection
- (const char* prefix,
- struct scpr_polygon* pg,
- const double e,
- struct scad_geometry** connection)
-{
- res_T res = RES_OK;
- struct scpr_polygon* pg_int = NULL;
- struct scad_geometry* geom[2];
- char* cname = NULL;
- struct str name;
- int is_init = 0;
-
- if (prefix) {
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_C_building_ground"));
- cname = str_get(&name);
- }
-
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, -e, SCPR_JOIN_MITER));
-
- ERR(build_wall_footprint(pg, pg_int, &geom[0]));
- ERR(build_floor_footprint(pg, &geom[1]));
-
- ERR(scad_fragment_geometries(cname, &geom[0], 1, &geom[1], 1, connection));
-
-exit:
- if(is_init) str_release(&name);
- if(geom[0]) scad_geometry_delete(geom[0]);
- if(geom[1]) scad_geometry_delete(geom[1]);
- if(pg_int) scpr_polygon_ref_put(pg_int);
- return res;
-error:
- goto exit;
-}
-
-/*----------------------------------------------------------------------------*/
-/*----------------------------------------------------------------------------*/
-/*----------------------------------------------------------------------------*/
-
-res_T
-init_model0
- (struct building* building, struct htable_building_params* htparams)
-{
- res_T res = RES_OK;
- struct data_model0 data;
- struct building_params* params;
-
- params = htable_building_params_find(htparams, building->data_name);
- if (params == NULL) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (params->model != building->model) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- data = *(struct data_model0*)params->data;
- building->data = malloc(sizeof(struct data_model0));
- if (!building->data) {
- res = RES_MEM_ERR;
- goto error;
- }
- *(struct data_model0*)(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;
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-res_T
-build_cad_model0(struct building* building)
-{
- res_T res = RES_OK;
- size_t id = building->id;
- enum model_type model = building->model;
- double height = building->height;
- struct scpr_polygon* pg = building->pg;
- struct scpr_polygon* pg_int = NULL;
- struct data_model0* data = (struct data_model0 *)building->data;
- struct data_cad_model0* data_cad;
- double e_wall;
- struct str prefix;
- int is_init = 0;
-
- if (!building) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (height <= 0 || data->wall <= 0 || data->floor <= 0) {
- 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, model_str[model]));
-
- data_cad = malloc(sizeof(struct data_cad_model0));
- building->data_cad = (struct data_cad_model0*)data_cad;
-
- e_wall = data->wall;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, -e_wall, SCPR_JOIN_MITER));
-
- /* build floor with pg_int */
- ERR(build_floor(str_cget(&prefix), 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));
-
- /* build wall with pg and pg_int */
- ERR(build_wall(str_cget(&prefix), pg, pg_int, building, &data_cad->wall));
-
- /* build cavity */
- ERR(build_cavity(str_cget(&prefix), 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));
-
- /* build boundary */
- ERR(build_boundary(str_cget(&prefix), building->data_cad));
-
- /* build cavity/floor connectiona*/
- ERR(build_connection(str_cget(&prefix), building->data_cad));
-
-
-exit:
- if(is_init) str_release(&prefix);
- if(pg_int) scpr_polygon_ref_put(pg_int);
- return res;
-error:
- goto exit;
-}
-
-res_T
-build_footprint_model0
- (struct building* building,
- struct scad_geometry** footprint)
-{
- res_T res = RES_OK;
- struct scpr_polygon* pg = building->pg;
- struct data_model0* data = (struct data_model0 *)building->data;
- double e_wall;
-
- e_wall = data->wall;
-
- ERR(building_ground_connection(NULL, pg, e_wall, footprint));
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-res_T
-export_stl_model0
- (const struct building* building, const int binary)
-{
- res_T res = RES_OK;
- struct data_cad_model0* data_cad = (struct data_cad_model0 *)building->data_cad;
- size_t i;
-
- /* floor export */
- ERR(scad_stl_export(data_cad->floor, NULL, binary));
-
- /* roof export */
- ERR(scad_stl_export(data_cad->roof, NULL, binary));
-
- /* wall export */
- ERR(scad_stl_export(data_cad->wall, NULL, binary));
-
- /* cavity export */
- ERR(scad_stl_export(data_cad->cavity, NULL, binary));
-
- /* connection export */
- for (i=0; i<data_cad->n_connection; ++i) {
- ERR(scad_stl_export(data_cad->connection[i], NULL, binary));
- }
-
- /* boundary export */
- ERR(scad_stl_export(data_cad->boundary, NULL, binary));
-
- /* footprint export */
- ERR(scad_stl_export(data_cad->ground_connection, NULL, binary));
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-res_T
-release_model0
- (struct building* building)
-{
- res_T res = RES_OK;
-
- struct data_model0* data = (struct data_model0 *)building->data;
- struct data_cad_model0* data_cad = (struct data_cad_model0 *)building->data_cad;
-
- scpr_polygon_ref_put(building->pg);
-
- str_release(building->data_name);
-
- if (data_cad->connection) free(data_cad->connection);
- if (data) free(data);
- if (data_cad) free(data_cad);
-
- return res;
-}
diff --git a/src/cg_building_model0.h b/src/cg_building_model0.h
@@ -1,68 +0,0 @@
-/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
- * Copyright (C) 2022 CNRS
- * Copyright (C) 2022 Sorbonne Université
- * Copyright (C) 2022 Université Paul Sabatier
- * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef BUILDING_MODEL0_H
-#define BUILDING_MODEL0_H
-
-#include <rsys/rsys.h>
-
-struct scad_geometry;
-
-struct building;
-struct htable_building_params;
-struct building_params;
-
-/* specific data for model 0 */
-struct data_model0 {
- double wall; /* wall thickness */
- double floor; /* floor thickness */
-};
-
-struct data_cad_model0 {
- struct scad_geometry* wall;
- struct scad_geometry* roof;
- struct scad_geometry* floor;
- struct scad_geometry* cavity;
- struct scad_geometry* boundary;
- struct scad_geometry** connection;
- struct scad_geometry* ground_connection;
- size_t n_connection;
-};
-
-res_T
-init_model0
- (struct building* building, struct htable_building_params* htparams);
-
-res_T
-build_cad_model0(struct building* building);
-
-res_T
-build_footprint_model0
- (struct building* building,
- struct scad_geometry** footprint);
-
-res_T
-export_stl_model0
- (const struct building* building, const int binary);
-
-res_T
-release_model0
- (struct building* building);
-
-#endif /* BUILDING_MODEL0_H */
diff --git a/src/cg_building_model1.c b/src/cg_building_model1.c
@@ -1,1526 +0,0 @@
-/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
- * Copyright (C) 2022 CNRS
- * Copyright (C) 2022 Sorbonne Université
- * Copyright (C) 2022 Université Paul Sabatier
- * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "cg.h"
-#include "cg_building.h"
-
-#include <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,
- const struct scpr_polygon* pg,
- const struct data_model1* data,
- struct scad_geometry** floor)
-{
- res_T res = RES_OK;
- double e_wall = data->wall;
- double e_insulation = data->ext_insulation;
- double e_floor = data->floor;
- double offset = 0;
- struct scpr_polygon* pg_int = NULL;
- size_t nverts = 0;
- struct scad_geometry* footprint = NULL;
- double d[3] = {0, 0, 0};
- char* floorname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!pg || !data || !floor) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (prefix) {
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_floor"));
- floorname = str_get(&name);
- }
-
- offset = e_wall + e_insulation;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
-
- /*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts, &footprint));
-
- d[2] = -e_floor;
- ERR(scad_geometry_extrude(footprint, floorname, d, floor));
-
-exit:
- scad_geometry_delete(footprint);
- if (is_init) str_release(&name);
- if (pg_int) scpr_polygon_ref_put(pg_int);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_wall
- (const char* prefix,
- const char* suffix,
- const struct scpr_polygon* pg,
- const double height,
- const struct data_model1* data,
- struct scad_geometry** wall)
-{
- res_T res = RES_OK;
- double e_wall = data->wall;
- double e_insulation = data->ext_insulation;
- double offset = 0;
- struct scpr_polygon* pg_int = NULL;
- struct scpr_polygon* pg_ext = NULL;
- size_t nverts = 0;
- struct scad_geometry* footprint = NULL;
- struct scad_geometry* footprint_int = NULL;
- struct scad_geometry* footprint_ext = NULL;
- double d[3] = {0, 0, 0};
- char* wallname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!pg || !data || !wall) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (prefix) {
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- if (suffix) {
- ERR(str_append(&name, "_"));
- ERR(str_append(&name, suffix));
- }
- wallname = str_get(&name);
- }
-
- offset = e_insulation;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_ext));
- ERR(scpr_offset_polygon(pg_ext, -offset, SCPR_JOIN_MITER));
-
- offset = e_wall + e_insulation;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
-
- /*wall footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext));
-
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, 0, nverts, &footprint_int));
-
- ERR(scad_cut_geometries(
- NULL, &footprint_ext, 1, &footprint_int, 1, &footprint));
-
- d[2] = height;
- ERR(scad_geometry_extrude(footprint, wallname, d, wall));
-
-exit:
- scad_geometry_delete(footprint);
- scad_geometry_delete(footprint_int);
- scad_geometry_delete(footprint_ext);
- if (is_init) str_release(&name);
- if (pg_int) scpr_polygon_ref_put(pg_int);
- if (pg_ext) scpr_polygon_ref_put(pg_ext);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_int_insulation
- (const char* prefix,
- const struct scpr_polygon* pg,
- const double height,
- const struct data_model1* data,
- struct scad_geometry* inter_floor,
- struct scad_geometry** insulation)
-{
- res_T res = RES_OK;
- double e_wall = data->wall;
- double e_roof = data->roof;
- double e_roof_insulation = data->roof_insulation;
- double attic = data->attic;
- double e_ext_insulation = data->ext_insulation;
- double e_int_insulation = data->int_insulation;
- double offset = 0;
- struct scpr_polygon* pg_int = NULL;
- struct scpr_polygon* pg_ext = NULL;
- size_t nverts = 0;
- struct scad_geometry* footprint = NULL;
- struct scad_geometry* footprint_int = NULL;
- struct scad_geometry* footprint_ext = NULL;
- struct scad_geometry* geom = NULL;
- double d[3] = {0, 0, 0};
- char* insulationname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!pg || !data || !insulation) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (prefix) {
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_int_insulation"));
- insulationname = str_get(&name);
- }
-
- offset = e_ext_insulation + e_wall;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_ext));
- ERR(scpr_offset_polygon(pg_ext, -offset, SCPR_JOIN_MITER));
-
- offset = e_ext_insulation + e_wall + e_int_insulation;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
-
- /* insulation footprint */
- ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext));
-
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, 0, nverts, &footprint_int));
-
- ERR(scad_cut_geometries(
- NULL, &footprint_ext, 1, &footprint_int, 1, &footprint));
-
- d[2] = height - e_roof - attic - e_roof_insulation;
- ERR(scad_geometry_extrude(footprint, NULL, d, &geom));
-
- if (inter_floor) {
- ERR(scad_cut_geometries(
- insulationname, &geom, 1, &inter_floor, 1, insulation));
- } else {
- ERR(scad_geometry_copy(geom, insulationname, insulation));
- }
-
-
-exit:
- scad_geometry_delete(footprint);
- scad_geometry_delete(footprint_int);
- scad_geometry_delete(footprint_ext);
- scad_geometry_delete(geom);
- if (is_init) str_release(&name);
- if (pg_int) scpr_polygon_ref_put(pg_int);
- if (pg_ext) scpr_polygon_ref_put(pg_ext);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_roof
- (const char* prefix,
- const struct scpr_polygon* pg,
- const double height,
- const struct data_model1* data,
- struct scad_geometry** roof)
-{
- res_T res = RES_OK;
- double e_wall = data->wall;
- double e_insulation = data->ext_insulation;
- double e_roof = data->roof;
- double offset = 0;
- double z_roof = 0;
- struct scpr_polygon* pg_int = NULL;
- size_t nverts = 0;
- struct scad_geometry* footprint = NULL;
- double d[3] = {0, 0, 0};
- char* roofname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!pg || !data || !roof) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (prefix) {
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_roof"));
- roofname = str_get(&name);
- }
-
- offset = e_wall + e_insulation;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
-
- /*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- z_roof = height - e_roof;
- ERR(scad_add_polygon(NULL, get_position_pg, pg_int, z_roof, nverts, &footprint));
-
- d[2] = e_roof;
- ERR(scad_geometry_extrude(footprint, roofname, d, roof));
-
-exit:
- scad_geometry_delete(footprint);
- if (is_init) str_release(&name);
- if (pg_int) scpr_polygon_ref_put(pg_int);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_roof_insulation
- (const char* prefix,
- const struct scpr_polygon* pg,
- const double height,
- const struct data_model1* data,
- struct scad_geometry** insulation)
-{
- res_T res = RES_OK;
- double e_wall = data->wall;
- double e_insulation = data->ext_insulation;
- double e_roof = data->roof;
- double attic = data->attic;
- double e_roof_insulation = data->roof_insulation;
- double offset = 0;
- double z_insulation = 0;
- struct scpr_polygon* pg_int = NULL;
- size_t nverts = 0;
- struct scad_geometry* footprint = NULL;
- double d[3] = {0, 0, 0};
- char* insulationname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!pg || !data || !insulation) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (prefix) {
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_roof_insulation"));
- insulationname = str_get(&name);
- }
-
- offset = e_wall + e_insulation;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
-
- /*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- z_insulation = height - e_roof - attic - e_roof_insulation;
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, z_insulation, nverts, &footprint));
-
- d[2] = e_roof_insulation;
- ERR(scad_geometry_extrude(footprint, insulationname, d, insulation));
-
-exit:
- scad_geometry_delete(footprint);
- if (is_init) str_release(&name);
- if (pg_int) scpr_polygon_ref_put(pg_int);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_floor_insulation
- (const char* prefix,
- const struct scpr_polygon* pg,
- const struct data_model1* data,
- struct scad_geometry** insulation)
-{
- res_T res = RES_OK;
- double e_wall = data->wall;
- double e_insulation = data->ext_insulation;
- double e_floor = data->floor;
- double e_floor_insulation = data->floor_insulation;
- double offset = 0;
- double z_insulation = 0;
- struct scpr_polygon* pg_int = NULL;
- size_t nverts = 0;
- struct scad_geometry* footprint = NULL;
- double d[3] = {0, 0, 0};
- char* insulationname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!pg || !data || !insulation) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (prefix) {
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_floor_insulation"));
- insulationname = str_get(&name);
- }
-
- offset = e_wall + e_insulation;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
-
- /*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- z_insulation = - e_floor - e_floor_insulation;
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, z_insulation, nverts, &footprint));
-
- d[2] = e_floor_insulation;
- ERR(scad_geometry_extrude(footprint, insulationname, d, insulation));
-
-exit:
- scad_geometry_delete(footprint);
- if (is_init) str_release(&name);
- if (pg_int) scpr_polygon_ref_put(pg_int);
- return res;
-error:
- goto exit;
-}
-static res_T
-build_inter_floor
- (const char* prefix,
- const struct scpr_polygon* pg,
- const double height,
- const struct data_model1* data,
- struct scad_geometry** inter_floor)
-{
- res_T res = RES_OK;
- size_t i = 0;
- size_t floor_n = data->inter_floor_n;
- double e_roof = data->roof;
- double e_roof_ins = data->roof_insulation;
- double attic = data->attic;
- double e_floor = data->inter_floor;
- double e_wall = data->wall;
- double e_insulation = data->ext_insulation;
- double offset = 0;
- double z_floor = 0;
- double h_cavity = 0;
- struct scpr_polygon* pg_int = NULL;
- size_t nverts = 0;
- struct scad_geometry** floor_list = NULL;
- double d[3] = {0, 0, 0};
- char* floorname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!pg || !data || !inter_floor) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (prefix) {
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_inter_floor"));
- floorname = str_get(&name);
- }
-
- offset = e_wall + e_insulation;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
-
- h_cavity = height - e_roof - attic - e_roof_ins - (double)floor_n*e_floor;
- z_floor = h_cavity/(double)(1 + floor_n);
- d[2] = e_floor;
- for (i=0; i< floor_n; ++i) {
- struct scad_geometry* floor = NULL;
- struct scad_geometry* footprint = NULL;
-
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, z_floor, nverts, &footprint));
- ERR(scad_geometry_extrude(footprint, NULL, d, &floor));
- sa_push(floor_list, floor);
- ERR(scad_geometry_delete(footprint));
- z_floor += h_cavity/(double)(1 + floor_n) + e_floor;
- }
-
- ERR(scad_fuse_geometries(
- floorname,
- floor_list, sa_size(floor_list),
- floor_list, sa_size(floor_list),
- inter_floor));
-
-exit:
- if (is_init) str_release(&name);
- if (pg_int) scpr_polygon_ref_put(pg_int);
- if (floor_list) {
- for (i=0; i< floor_n; ++i) {
- scad_geometry_delete(floor_list[i]);
- }
- sa_release(floor_list);
- }
- return res;
-error:
- goto exit;
-}
-static res_T
-build_ext_insulation
- (const char* prefix,
- const struct scpr_polygon* pg,
- const double height,
- const struct data_model1* data,
- struct scad_geometry** insulation)
-{
- res_T res = RES_OK;
- double e_insulation = data->ext_insulation;
- double offset = 0;
- struct scpr_polygon* pg_int = NULL;
- struct scpr_polygon* pg_ext = NULL;
- size_t nverts = 0;
- struct scad_geometry* footprint = NULL;
- struct scad_geometry* footprint_int = NULL;
- struct scad_geometry* footprint_ext = NULL;
- double d[3] = {0, 0, 0};
- char* insulationname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!pg || !data || !insulation) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (prefix) {
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_ext_insulation"));
- insulationname = str_get(&name);
- }
-
- offset = e_insulation;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_ext));
- ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
-
- /*insulation footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext));
-
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, 0, nverts, &footprint_int));
-
- ERR(scad_cut_geometries(
- NULL, &footprint_ext, 1, &footprint_int, 1, &footprint));
-
- d[2] = height;
- ERR(scad_geometry_extrude(footprint, insulationname, d, insulation));
-
-exit:
- scad_geometry_delete(footprint);
- scad_geometry_delete(footprint_int);
- scad_geometry_delete(footprint_ext);
- if (is_init) str_release(&name);
- if (pg_int) scpr_polygon_ref_put(pg_int);
- if (pg_ext) scpr_polygon_ref_put(pg_ext);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_crawlspace
- (const char* prefix,
- const struct scpr_polygon* pg,
- const struct data_model1* data,
- struct scad_geometry** crawlspace)
-{
- res_T res = RES_OK;
- double e_wall = data->wall;
- double e_insulation = data->ext_insulation;
- double e_crawl = data->crawl;
- double e_floor = data->floor;
- double e_floor_insulation = data->floor_insulation;
- double offset = 0;
- double z_crawl= 0;
- struct scpr_polygon* pg_int = NULL;
- size_t nverts = 0;
- struct scad_geometry* footprint = NULL;
- double d[3] = {0, 0, 0};
- char* crawlname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!pg || !data || !crawlspace) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (prefix) {
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_crawlspace"));
- crawlname = str_get(&name);
- }
-
- offset = e_wall + e_insulation;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
-
- /*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- z_crawl = - e_floor - e_floor_insulation - e_crawl;
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, z_crawl, nverts, &footprint));
-
- d[2] = e_crawl;
- ERR(scad_geometry_extrude(footprint, crawlname, d, crawlspace));
-
-exit:
- scad_geometry_delete(footprint);
- if (is_init) str_release(&name);
- if (pg_int) scpr_polygon_ref_put(pg_int);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_habitable
- (const char* prefix,
- const struct scpr_polygon* pg,
- const double height,
- const struct data_model1* data,
- struct scad_geometry* floor,
- struct scad_geometry** cavity)
-{
- res_T res = RES_OK;
- double e_wall = data->wall;
- double e_ext_insulation = data->ext_insulation;
- double e_int_insulation = data->int_insulation;
- double e_roof = data->roof;
- double e_roof_insulation = data->roof_insulation;
- double e_attic = data->attic;
- double offset = 0;
- struct scpr_polygon* pg_int = NULL;
- size_t nverts = 0;
- struct scad_geometry* footprint = NULL;
- struct scad_geometry* geom = NULL;
- double d[3] = {0, 0, 0};
- char* cavityname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!pg || !data || !cavity) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (prefix) {
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_cavity"));
- cavityname = str_get(&name);
- }
-
- offset = e_wall + e_ext_insulation + e_int_insulation;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
-
- /*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, 0, nverts, &footprint));
-
- d[2] = height - e_roof - e_attic - e_roof_insulation;
- ERR(scad_geometry_extrude(footprint, NULL, d, &geom));
- if (floor) {
- ERR(scad_cut_geometries(
- cavityname, &geom, 1, &floor, 1, cavity));
- } else {
- ERR(scad_geometry_copy(geom, cavityname, cavity));
- }
-
-exit:
- scad_geometry_delete(footprint);
- scad_geometry_delete(geom);
- if (is_init) str_release(&name);
- if (pg_int) scpr_polygon_ref_put(pg_int);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_attic
- (const char* prefix,
- const struct scpr_polygon* pg,
- const double height,
- const struct data_model1* data,
- struct scad_geometry** attic)
-{
- res_T res = RES_OK;
- double e_wall = data->wall;
- double e_insulation = data->ext_insulation;
- double e_roof = data->roof;
- double e_attic = data->attic;
- double offset = 0;
- double z_attic = 0;
- struct scpr_polygon* pg_int = NULL;
- size_t nverts = 0;
- struct scad_geometry* footprint = NULL;
- double d[3] = {0, 0, 0};
- char* atticname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!pg || !data || !attic) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (prefix) {
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_attic"));
- atticname = str_get(&name);
- }
-
- offset = e_wall + e_insulation;
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
-
- /*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- z_attic = height - e_roof - e_attic;
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, z_attic, nverts, &footprint));
-
- d[2] = e_attic;
- ERR(scad_geometry_extrude(footprint, atticname, d, attic));
-
-exit:
- scad_geometry_delete(footprint);
- if (is_init) str_release(&name);
- if (pg_int) scpr_polygon_ref_put(pg_int);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_windows
- (const char* prefix,
- const struct data_model1* data,
- struct data_cad_model1* data_cad)
-{
- res_T res = RES_OK;
- size_t i = 0;
- double N[3];
- double dir[3];
- double scale[3];
- struct scad_geometry* surface = NULL;
- struct scad_geometry* hole = NULL;
- struct scad_geometry** hole_list = NULL;
- struct scad_geometry* geom = NULL;
- struct scad_geometry* bcavity = NULL;
- struct scad_geometry** list = NULL;
- struct scad_geometry* glass = NULL;
- struct scad_geometry** glass_list = NULL;
- size_t list_n = 0;
- char* name = NULL;
- struct str gname;
- int is_init = 0;
-
- if (!data || !data_cad) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- scale[0] = sqrt(data->glass_ratio);
- scale[1] = scale[0];
- scale[2] = scale[0];
-
- /* windows are build from the vertical faces of habitable cavities */
- ERR(scad_geometry_boundary(NULL, &data_cad->habitable_cavity, 1, &bcavity));
- ERR(scad_geometry_explode(bcavity, NULL, &list, &list_n));
-
- for (i=0; i<list_n; ++i){
- double* center = NULL;
- size_t center_n = 0;
-
- ERR(scad_geometry_get_centerofmass(list[i], ¢er, ¢er_n));
-
- ERR(scad_geometry_normal(list[i], center, N, NULL, &surface));
-
- if (N[2] != 0) {
- ERR(scad_geometry_delete(surface));
- surface = NULL;
- continue; /* keep only vertical face */
- }
-
- ERR(scad_geometry_dilate(surface, center, scale));
-
- dir[0] = 1.1*N[0] * (data->wall + data->int_insulation + data->ext_insulation);
- dir[1] = 1.1*N[1] * (data->wall + data->int_insulation + data->ext_insulation);
- dir[2] = 1.1*N[2] * (data->wall + data->int_insulation + data->ext_insulation);
- ERR(scad_geometry_extrude(surface, NULL, dir, &hole));
- sa_push(hole_list, hole);
-
- dir[0] = N[0] * 0.024;
- dir[1] = N[1] * 0.024;
- dir[2] = N[2] * 0.024;
- ERR(scad_geometry_extrude(surface, NULL, dir, &glass));
- sa_push(glass_list, glass);
-
- ERR(scad_geometry_delete(surface));
- surface = NULL;
- }
-
- /* wall perforation */
- ERR(scad_geometry_get_name(data_cad->wall, &name));
- ERR(scad_cut_geometries(
- NULL, &data_cad->wall, 1, hole_list, sa_size(hole_list), &geom));
- ERR(scad_geometry_delete(data_cad->wall));
- /*data_cad->wall = geom;*/
- ERR(scad_geometry_copy(geom, name, &data_cad->wall));
- ERR(scad_geometry_delete(geom));
- geom = NULL;
-
- /* internal insulation perforation */
- if (data_cad->internal_insulation) {
- ERR(scad_geometry_get_name(data_cad->internal_insulation, &name));
- ERR(scad_cut_geometries(
- NULL, &data_cad->internal_insulation, 1,
- hole_list, sa_size(hole_list), &geom));
- ERR(scad_geometry_delete(data_cad->internal_insulation));
- ERR(scad_geometry_copy(geom, name, &data_cad->internal_insulation));
- ERR(scad_geometry_delete(geom));
- geom = NULL;
- }
-
- /* external insulation perforation */
- if (data_cad->external_insulation) {
- ERR(scad_geometry_get_name(data_cad->external_insulation, &name));
- ERR(scad_cut_geometries(
- NULL, &data_cad->external_insulation, 1,
- hole_list, sa_size(hole_list), &geom));
- ERR(scad_geometry_delete(data_cad->external_insulation));
- ERR(scad_geometry_copy(geom, name, &data_cad->external_insulation));
- ERR(scad_geometry_delete(geom));
- geom = NULL;
- }
-
- /* build glass */
- if (prefix) {
- str_init(NULL, &gname);
- is_init = 1;
- ERR(str_set(&gname, prefix));
- ERR(str_append(&gname, "_glass"));
- }
-
- ERR(scad_fuse_geometries(str_cget(&gname), glass_list, 1,
- glass_list+1, sa_size(glass_list) - 1, &data_cad->glass));
-
-exit:
- for (i=0 ; i<list_n; ++i) {
- scad_geometry_delete(list[i]);
- }
- for (i=0 ; i<sa_size(hole_list); ++i) {
- scad_geometry_delete(hole_list[i]);
- }
- for (i=0 ; i<sa_size(glass_list); ++i) {
- scad_geometry_delete(glass_list[i]);
- }
- if (hole_list) sa_release(hole_list);
- if (glass_list) sa_release(glass_list);
- if (surface) scad_geometry_delete(surface);
- if (geom) scad_geometry_delete(geom);
- if (bcavity) scad_geometry_delete(bcavity);
- /*scad_synchronize();*/
- if (name) free(name);
- if (list) free(list);
- if (is_init) str_release(&gname);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_boundary
- (const char* prefix,
- struct data_cad_model1* data_cad,
- struct scad_geometry*** boundary)
-{
- res_T res = RES_OK;
- struct scad_geometry** list = NULL;
- struct scad_geometry* bound = NULL;
- char* boundaryname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!prefix || !data_cad || !boundary) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- str_init(NULL, &name);
- is_init = 1;
-
- sa_push(list, data_cad->wall);
- sa_push(list, data_cad->roof);
- sa_push(list, data_cad->floor);
- sa_push(list, data_cad->habitable_cavity);
- sa_push(list, data_cad->fake_ground);
- if (data_cad->foundation) sa_push(list, data_cad->foundation);
- if (data_cad->intermediate_floor) sa_push(list, data_cad->intermediate_floor);
- if (data_cad->external_insulation) sa_push(list, data_cad->external_insulation);
- if (data_cad->internal_insulation) sa_push(list, data_cad->internal_insulation);
- if (data_cad->roof_insulation) sa_push(list, data_cad->roof_insulation);
- if (data_cad->floor_insulation) sa_push(list, data_cad->floor_insulation);
- if (data_cad->attic_cavity) sa_push(list, data_cad->attic_cavity);
- if (data_cad->crawlspace_cavity) sa_push(list, data_cad->crawlspace_cavity);
- if (data_cad->glass) sa_push(list, data_cad->glass);
-
-
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_boundary_wall"));
- boundaryname = str_get(&name);
- ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list),
- &data_cad->wall, 1, &bound));
- sa_push(*boundary, bound);
-
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_boundary_roof"));
- boundaryname = str_get(&name);
- ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list),
- &data_cad->roof, 1, &bound));
- sa_push(*boundary, bound);
-
- if (data_cad->glass) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_boundary_glass"));
- boundaryname = str_get(&name);
- ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list),
- &data_cad->glass, 1, &bound));
- sa_push(*boundary, bound);
- }
-
- if (data_cad->external_insulation) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_boundary_ext_insulation"));
- boundaryname = str_get(&name);
- ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list),
- &data_cad->external_insulation, 1, &bound));
- sa_push(*boundary, bound);
- }
-
- if (data_cad->internal_insulation) {
- size_t count = 0;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_boundary_int_insulation"));
- boundaryname = str_get(&name);
- ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list),
- &data_cad->internal_insulation, 1, &bound));
- ERR(scad_geometry_get_count(bound, &count));
- if (count>0) sa_push(*boundary, bound);
- }
-
-exit:
- if (is_init) str_release(&name);
- if (list) sa_release(list);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_connection
- (const char* prefix,
- struct data_cad_model1* data_cad,
- struct scad_geometry*** connection)
-{
- res_T res = RES_OK;
- struct scad_geometry* connect = NULL;
- size_t count = 0;
- char* cname = NULL;
- struct str name;
- int is_init = 0;
-
- if (!prefix || !data_cad || !connection) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- str_init(NULL, &name);
- is_init = 1;
-
-#define CREATE_CONNECT(G1,G2,SUFFIX) ERR(str_set(&name, prefix));\
- ERR(str_append(&name, SUFFIX));\
- cname = str_get(&name);\
- ERR(scad_geometries_common_boundaries\
- (cname,\
- &data_cad->G1, 1,\
- &data_cad->G2, 1,\
- &connect));\
- ERR(scad_geometry_get_count(connect, &count)); \
- if (count>0) sa_push(*connection, connect);
-
-
- /* -------------------------------------------------------------------------*/
- /* habitable cavity connections */
- /* -------------------------------------------------------------------------*/
-
- /* with floor */
- CREATE_CONNECT(habitable_cavity,floor,"_C_cavity_floor");
-
- /* with wall */
- CREATE_CONNECT(habitable_cavity,wall,"_C_cavity_wall");
-
- /* with glass */
- if (data_cad->glass) {
- CREATE_CONNECT(habitable_cavity,glass,"_C_cavity_glass");
- }
-
- /* with internal insulation */
- if (data_cad->internal_insulation) {
- CREATE_CONNECT(habitable_cavity,internal_insulation,"_C_cavity_internal_insulation");
- }
-
- /* with roof insulation */
- if (data_cad->roof_insulation) {
- CREATE_CONNECT(habitable_cavity,roof_insulation,"_C_roof_insulation");
- } else {
- /* with roof */
- CREATE_CONNECT(habitable_cavity,roof,"_C_cavity_roof");
- }
-
- /* with intermediate floor */
- if (data_cad->intermediate_floor) {
- CREATE_CONNECT(habitable_cavity,intermediate_floor,"_C_cavity_intermediate_floor");
- }
-
- /* -------------------------------------------------------------------------*/
- /* crawlspace cavity connections */
- /* -------------------------------------------------------------------------*/
-
- if (data_cad->crawlspace_cavity) {
- /* with floor insulation */
- if (data_cad->floor_insulation) {
- CREATE_CONNECT(crawlspace_cavity, floor_insulation,"_C_crawlspace_insulation");
- } else {
- /* with floor */
- CREATE_CONNECT(crawlspace_cavity, floor,"_C_crawlspace_floor");
- }
-
- /* with wall */
- CREATE_CONNECT(crawlspace_cavity, foundation,"_C_crawlspace_foundation");
- }
-
- /* -------------------------------------------------------------------------*/
- /* attic cavity connections */
- /* -------------------------------------------------------------------------*/
-
- if (data_cad->attic_cavity) {
- /* with roof */
- CREATE_CONNECT(attic_cavity, roof,"_C_attic_roof");
-
- /* with roof insulation */
- CREATE_CONNECT(attic_cavity, roof_insulation,"_C_attic_insulation");
-
- /* with wall */
- CREATE_CONNECT(attic_cavity, wall,"_C_attic_wall");
- }
-
-#undef CREATE_CONNECT
-
-exit:
- if (is_init) str_release(&name);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_footprint
- (struct scpr_polygon* pg, struct scad_geometry** footprint)
-{
- res_T res = RES_OK;
- size_t nverts = 0;
-
- if (!pg || !footprint) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg, 0, nverts, footprint));
-
-exit:
- return res;
-error:
- goto exit;
-
-}
-
-static res_T
-build_fake_ground
- (struct data_cad_model1* cad,
- struct scpr_polygon* pg,
- const double depth,
- struct scad_geometry** ground)
-{
- res_T res = RES_OK;
- double dir[3] = {0, 0, 0};
- struct scpr_polygon* pg_offset = NULL;
- struct scad_geometry** list = NULL;
- struct scad_geometry* footprint = NULL;
- struct scad_geometry* geom = NULL;
-
- if (!cad || !pg || !ground ) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (cad->foundation) sa_push(list, cad->foundation);
- if (cad->crawlspace_cavity) sa_push(list, cad->crawlspace_cavity);
- if (cad->floor) sa_push(list, cad->floor);
- if (cad->floor_insulation) sa_push(list, cad->floor_insulation);
-
- ERR(scpr_polygon_create_copy(NULL, pg, &pg_offset));
- ERR(scpr_offset_polygon(pg_offset, 0.1, SCPR_JOIN_MITER));
-
- ERR(build_footprint(pg_offset, &footprint));
-
- dir[2] = -depth*1.1;
- ERR(scad_geometry_extrude(footprint, NULL, dir, &geom));
-
- ERR(scad_cut_geometries(NULL, &geom, 1, list, sa_size(list), ground));
-
-exit:
- if (pg_offset) scpr_polygon_ref_put(pg_offset);
- if (list) sa_release(list);
- if (footprint) scad_geometry_delete(footprint);
- if (geom) scad_geometry_delete(geom);
- return res;
-error:
- goto exit;
-}
-
-
-static res_T
-building_ground_connection
- (const char* prefix,
- struct data_cad_model1* cad,
- struct scad_geometry** connection)
-{
- res_T res = RES_OK;
- char* cname = NULL;
- struct str name;
- int is_init = 0;
- struct scad_geometry** list = NULL;
- struct scad_geometry* list_boundary = NULL;
- struct scad_geometry* footprint = NULL;
-
- if (!prefix || !cad || !connection) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- str_init(NULL, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_C_building_ground"));
- cname = str_get(&name);
-
- if (cad->foundation) sa_push(list, cad->foundation);
- if (cad->attic_cavity) sa_push(list, cad->attic_cavity);
- if (cad->floor) sa_push(list, cad->floor);
- if (cad->floor_insulation) sa_push(list, cad->floor_insulation);
- if (cad->external_insulation) sa_push(list, cad->external_insulation);
- if (cad->wall) sa_push(list, cad->wall);
-
- ERR(scad_geometries_common_boundaries(
- cname, list, sa_size(list),
- &cad->fake_ground, 1,
- connection));
-
-exit:
- if (list) sa_release(list);
- if (is_init) str_release(&name);
- if (list_boundary) scad_geometry_delete(list_boundary);
- if (footprint) scad_geometry_delete(footprint);
- return res;
-error:
- goto exit;
-}
-
-/*----------------------------------------------------------------------------*/
-/*----------------------------------------------------------------------------*/
-/*----------------------------------------------------------------------------*/
-
-res_T
-init_model1
- (struct building* building, struct htable_building_params* htparams)
-{
- res_T res = RES_OK;
- struct data_model1 data;
- struct building_params* params;
-
- params = htable_building_params_find(htparams, building->data_name);
- if (params == NULL) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- if (params->model != building->model) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- data = *(struct data_model1*)params->data;
- building->data = malloc(sizeof(struct data_model1));
- if (!building->data) {
- res = RES_MEM_ERR;
- goto error;
- }
- *(struct data_model1*)(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;
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-res_T
-build_cad_model1(struct building* building)
-{
- res_T res = RES_OK;
- size_t id = building->id;
- enum model_type model = building->model;
- double height = building->height;
- double depth = 0;
- struct scpr_polygon* pg = building->pg;
- struct data_model1* data = (struct data_model1 *)building->data;
- struct data_cad_model1* data_cad;
- struct str prefix;
- int is_init = 0;
-
- 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, model_str[model]));
-
- data_cad = malloc(sizeof(struct data_cad_model1));
- 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;
- building->data_cad = (struct data_cad_model1*)data_cad;
-
- /* build mandatories elements :
- - floor
- - wall
- - roof
- */
-
- ERR(build_floor(str_cget(&prefix), pg, data, &data_cad->floor));
-
- ERR(build_wall(str_cget(&prefix), "wall", pg, height, data, &data_cad->wall));
-
- ERR(build_roof(str_cget(&prefix), pg, height, data, &data_cad->roof));
-
- /* build optionnal elements :
- - foundation
- - intermediate floor
- - external insulation
- - internal insulation
- - roof insulation
- - floor insulation
- */
-
- if (data->foundation > 0) {
- depth = -data->foundation;
- ERR(build_wall(
- str_cget(&prefix), "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));
- } 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));
- } 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,
- &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));
- } else {
- data_cad->roof_insulation = NULL;
- }
-
- if (data->floor_insulation > 0) {
- ERR(build_floor_insulation(
- str_cget(&prefix), pg, data, &data_cad->floor_insulation));
- } else {
- data_cad->floor_insulation = NULL;
- }
-
- /* build cavities :
- - attic
- - habitable
- - crawlspace
- */
-
- if (data->attic > 0) {
- ERR(build_attic(
- str_cget(&prefix), 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,
- &data_cad->habitable_cavity));
-
- if (data->crawl > 0) {
- ERR(build_crawlspace(
- str_cget(&prefix), 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));
- }
-
- /* fake ground */
- depth = MMAX(data->foundation, data->floor + data->floor_insulation + data->crawl);
- ERR(build_fake_ground(data_cad, pg, depth, &data_cad->fake_ground));
-
- ERR(scad_scene_partition());
-
- /* build ground/buildind connection */
- ERR(building_ground_connection(str_cget(&prefix), data_cad,
- &data_cad->ground_connection));
-
- /* build boundaries */
- data_cad->boundary = NULL;
- ERR(build_boundary(str_cget(&prefix), data_cad, &data_cad->boundary));
-
- /* build connections */
- data_cad->connection = NULL;
- ERR(build_connection(str_cget(&prefix), data_cad, &data_cad->connection));
-
-exit:
- if (is_init) str_release(&prefix);
- return res;
-error:
- goto exit;
-}
-
-res_T
-build_footprint_model1
- (struct building* building,
- struct scad_geometry** footprint)
-{
- res_T res = RES_OK;
- struct scpr_polygon* pg = building->pg;
-
- if (!building || !footprint) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- ERR(build_footprint(pg, footprint));
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-res_T
-export_stl_model1
- (const struct building* building, const int binary)
-{
- res_T res = RES_OK;
- struct data_cad_model1* data_cad = (struct data_cad_model1 *)building->data_cad;
- size_t i = 0;
-
- /* floor export */
- ERR(scad_stl_export(data_cad->floor, NULL, binary));
-
- /* wall export */
- ERR(scad_stl_export(data_cad->wall, NULL, binary));
-
- /* roof export */
- ERR(scad_stl_export(data_cad->roof, NULL, binary));
-
- /* foundation export */
- if (data_cad->foundation) {
- ERR(scad_stl_export(data_cad->foundation, NULL, binary));
- }
-
- /* glass export */
- if (data_cad->glass) {
- ERR(scad_stl_export(data_cad->glass, NULL, binary));
- }
-
- /* intermediate floor export*/
- if (data_cad->intermediate_floor) {
- ERR(scad_stl_export(data_cad->intermediate_floor, NULL, binary));
- }
-
- /* internal insulation export*/
- if (data_cad->internal_insulation) {
- ERR(scad_stl_export(data_cad->internal_insulation, NULL, binary));
- }
-
- /* external insulation export*/
- if (data_cad->external_insulation) {
- ERR(scad_stl_export(data_cad->external_insulation, NULL, binary));
- }
-
- /* roof insulation export*/
- if (data_cad->roof_insulation) {
- ERR(scad_stl_export(data_cad->roof_insulation, NULL, binary));
- }
-
- /* floor insulation export*/
- if (data_cad->floor_insulation) {
- ERR(scad_stl_export(data_cad->floor_insulation, NULL, binary));
- }
-
- /* attic cavity export*/
- if (data_cad->attic_cavity) {
- ERR(scad_stl_export(data_cad->attic_cavity, NULL, binary));
- }
-
- /* habitable cavity export*/
- ERR(scad_stl_export(data_cad->habitable_cavity, NULL, binary));
-
- /* crawlspace cavity export*/
- if (data_cad->crawlspace_cavity) {
- ERR(scad_stl_export(data_cad->crawlspace_cavity, NULL, binary));
- }
-
- /* boundary export*/
- for (i=0; i<sa_size(data_cad->boundary); ++i) {
- ERR(scad_stl_export(data_cad->boundary[i], NULL, binary));
- }
-
- /* connections export*/
- for (i=0; i<sa_size(data_cad->connection); ++i) {
- ERR(scad_stl_export(data_cad->connection[i], NULL, binary));
- }
-
- /* ground/building connection export*/
- ERR(scad_stl_export(data_cad->ground_connection, NULL, binary));
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-res_T
-release_model1
- (struct building* building)
-{
- res_T res = RES_OK;
- struct data_model1* data = (struct data_model1 *)building->data;
- struct data_cad_model1* data_cad = (struct data_cad_model1 *)building->data_cad;
-
- scpr_polygon_ref_put(building->pg);
-
- str_release(building->data_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);
-
- return res;
-}
diff --git a/src/cg_building_model1.h b/src/cg_building_model1.h
@@ -1,89 +0,0 @@
-/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
- * Copyright (C) 2022 CNRS
- * Copyright (C) 2022 Sorbonne Université
- * Copyright (C) 2022 Université Paul Sabatier
- * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef BUILDING_MODEL1_H
-#define BUILDING_MODEL1_H
-
-#include <rsys/rsys.h>
-
-struct scad_geometry;
-
-struct building;
-struct htable_building_params;
-struct building_params;
-
-/* specific data for model 0 */
-struct data_model1 {
- size_t inter_floor_n; /* number of intermediate floor >= 0 */
- double wall; /* wall thickness > 0 */
- double floor; /* floor thickness > 0*/
- double inter_floor; /* intermediate floor thickness > 0 */
- double roof; /* roof thickness > 0*/
- double int_insulation; /* internal insulation thickness >= 0 */
- double ext_insulation; /* external insulation thickness >= 0 */
- double floor_insulation; /* floor insulation thickness >= 0 */
- double roof_insulation; /* roof insulation thickness >= 0*/
- double foundation; /* foundation depth >= 0 */
- double crawl; /* crawl space height >= 0 */
- double attic; /* attic height >= 0 (and only if roof insulation > 0)*/
- double glass_ratio; /* in [0, 1] */
-};
-
-struct data_cad_model1 {
- struct scad_geometry* wall;
- struct scad_geometry* roof;
- struct scad_geometry* floor;
- struct scad_geometry* foundation; /* can be NULL */
- struct scad_geometry* intermediate_floor; /* can be NULL */
- struct scad_geometry* habitable_cavity;
- struct scad_geometry* crawlspace_cavity; /* can be NULL */
- struct scad_geometry* attic_cavity; /* can be NULL */
- struct scad_geometry* internal_insulation; /* can be NULL */
- struct scad_geometry* external_insulation; /* can be NULL */
- struct scad_geometry* floor_insulation; /* can be NULL */
- struct scad_geometry* roof_insulation; /* can be NULL */
- struct scad_geometry* glass;
- struct scad_geometry* fake_ground;/*not exported, used for ground connection*/
- struct scad_geometry* ground_connection;
- struct scad_geometry** boundary;
- struct scad_geometry** connection;
- size_t n_connection;
-};
-
-res_T
-init_model1
- (struct building* building, struct htable_building_params* htparams);
-
-res_T
-build_cad_model1(struct building* building);
-
-res_T
-build_footprint_model1
- (struct building* building,
- struct scad_geometry** footprint);
-
-res_T
-export_stl_model1
- (const struct building* building, const int binary);
-
-res_T
-release_model1
- (struct building* building);
-
-#endif /* BUILDING_MODEL1_H */
diff --git a/src/cg_catalog.c b/src/cg_catalog.c
@@ -0,0 +1,141 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * Copyright (C) 2022 CNRS
+ * Copyright (C) 2022 Sorbonne Université
+ * Copyright (C) 2022 Université Paul Sabatier
+ * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "cg.h"
+#include "cg_catalog.h"
+#include "cg_catalog_parsing.h"
+#include "cg_constructive_mode_0.h"
+#include "cg_constructive_mode_1.h"
+#include "cg_constructive_mode_0_parsing_schemas.h"
+#include "cg_constructive_mode_1_parsing_schemas.h"
+
+#include <rsys/rsys.h>
+#include <rsys/mem_allocator.h>
+#include <rsys/logger.h>
+#include <rsys/str.h>
+
+res_T
+create_catalog
+ (struct mem_allocator* allocator,
+ struct logger* logger,
+ struct parsed_catalog* parsed_catalog,
+ struct catalog** out_catalog)
+{
+ res_T res = RES_OK;
+ size_t i, j, count;
+ const struct parsed_catalog_items* items;
+ struct catalog* catalog;
+ struct str name;
+ int name_initialized = 0;
+
+ ASSERT(allocator && logger && parsed_catalog && out_catalog);
+
+ catalog = MEM_ALLOC(allocator, sizeof(*catalog));
+ if(!catalog) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+
+ str_init(allocator, &name);
+ name_initialized = 0;
+
+ catalog->allocator = allocator;
+ catalog->logger = logger;
+ htable_dataset_cmode_0_init(allocator, &catalog->catalog_0);
+ htable_dataset_cmode_1_init(allocator, &catalog->catalog_1);
+ count = darray_parsed_catalog_items_size_get(&parsed_catalog->catalog);
+ items = darray_parsed_catalog_items_cdata_get(&parsed_catalog->catalog);
+
+ for(i = 0; i < count; i++) {
+ switch(items[i].constructive_mode) {
+ case mode_0: {
+ const struct parsed_catalog_cmode_0* parsed_0 = items[i].parsed_items;
+ for(j = 0; j < parsed_0->datasets_count; j++) {
+ const struct parsed_dataset_cmode_0* parsed_item
+ = parsed_0->datasets + j;
+ struct dataset_cmode_0 item;
+ ERR(str_set(&name, parsed_item->name));
+ if(htable_dataset_cmode_0_find(&catalog->catalog_0, &name)) {
+ logger_print(logger, LOG_ERROR,
+ "Duplicate dataset name: '%s' (in file '%s').\n",
+ parsed_item->name, items[i].filename);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ item.wall_thickness = parsed_item->wall_thickness;
+ item.floor_thickness = parsed_item->floor_thickness;
+ ERR(htable_dataset_cmode_0_set(&catalog->catalog_0, &name, &item));
+ }
+ break;
+ }
+ case mode_1: {
+ const struct parsed_catalog_cmode_1* parsed_1 = items[i].parsed_items;
+ for(j = 0; j < parsed_1->datasets_count; j++) {
+ const struct parsed_dataset_cmode_1* parsed_item
+ = parsed_1->datasets + j;
+ struct dataset_cmode_1 item;
+ ERR(str_set(&name, parsed_item->name));
+ if(htable_dataset_cmode_1_find(&catalog->catalog_1, &name)) {
+ logger_print(logger, LOG_ERROR,
+ "Duplicate dataset name: '%s' (in file '%s').\n",
+ parsed_item->name, items[i].filename);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ item.inter_floor_count = parsed_item->inter_floor_count;
+ item.wall_thickness = parsed_item->wall_thickness;
+ item.floor_thickness = parsed_item->floor_thickness;
+ item.inter_floor_thickness = parsed_item->inter_floor_thickness;
+ item.roof_thickness = parsed_item->roof_thickness;
+ item.internal_insulation_thickness = parsed_item->internal_insulation_thickness;
+ item.external_insulation_thickness = parsed_item->external_insulation_thickness;
+ item.floor_insulation_thickness = parsed_item->floor_insulation_thickness;
+ item.roof_insulation_thickness = parsed_item->roof_insulation_thickness;
+ item.foundation_depth = parsed_item->foundation_depth;
+ item.crawl_height = parsed_item->crawl_height;
+ item.attic_height = parsed_item->attic_height;
+ item.glass_ratio = parsed_item->glass_ratio;
+ ERR(htable_dataset_cmode_1_set(&catalog->catalog_1, &name, &item));
+ }
+ break;
+ }
+ default: FATAL("Invalid enum value.");
+ }
+ }
+exit:
+ if(name_initialized) str_release(&name);
+ *out_catalog = catalog;
+ return res;
+error:
+ release_catalog(catalog);
+ catalog = NULL;
+ goto exit;
+}
+
+void
+release_catalog
+ (struct catalog* catalog)
+{
+ if(!catalog) return;
+
+ htable_dataset_cmode_0_release(&catalog->catalog_0);
+ htable_dataset_cmode_1_release(&catalog->catalog_1);
+ MEM_RM(catalog->allocator, catalog);
+}
+
diff --git a/src/cg_catalog.h b/src/cg_catalog.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * Copyright (C) 2022 CNRS
+ * Copyright (C) 2022 Sorbonne Université
+ * Copyright (C) 2022 Université Paul Sabatier
+ * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef FG_CATALOG__
+#define FG_CATALOG__
+
+#include "cg_constructive_mode_0.h"
+#include "cg_constructive_mode_1.h"
+#include "cg_constructive_mode_0_parsing_schemas.h"
+#include "cg_constructive_mode_1_parsing_schemas.h"
+
+struct mem_allocator;
+struct logger;
+struct parsed_catalog;
+struct catalog;
+
+struct catalog {
+ struct mem_allocator* allocator;
+ struct logger* logger;
+ struct htable_dataset_cmode_0 catalog_0;
+ struct htable_dataset_cmode_1 catalog_1;
+};
+
+res_T
+create_catalog
+ (struct mem_allocator* allocator,
+ struct logger* logger,
+ struct parsed_catalog* parsed_catalog,
+ struct catalog** out_catalog);
+
+void
+release_catalog
+ (struct catalog* catalog);
+
+#endif
diff --git a/src/cg_catalog_parsing.c b/src/cg_catalog_parsing.c
@@ -0,0 +1,141 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * Copyright (C) 2022 CNRS
+ * Copyright (C) 2022 Sorbonne Université
+ * Copyright (C) 2022 Université Paul Sabatier
+ * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "cg.h"
+#include "cg_args.h"
+#include "cg_catalog_parsing.h"
+#include "cg_constructive_modes_parsing_schemas.h"
+#include "cg_building.h"
+
+#include <rsys/logger.h>
+#include <rsys/str.h>
+
+#include <cyaml/cyaml.h>
+
+static const struct cyaml_schema_value*
+get_schema_from_parsed_cmode
+ (const enum parsed_cmode_type parsed_cmode)
+{
+ switch(parsed_cmode) {
+ case PARSED_CMODE_0:
+ return &constructive_mode_0_schema;
+ case PARSED_CMODE_1:
+ return &constructive_mode_1_schema;
+ default: FATAL("Invalid enum value.\n");
+ }
+}
+
+res_T
+parse_catalog
+ (const struct darray_catalog_filenames* files_array,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ const struct cyaml_config* config,
+ struct parsed_catalog** out_parsed)
+{
+ res_T res = RES_OK;
+ cyaml_err_t err;
+ size_t i, files_count;
+ struct parsed_catalog_items* items;
+ struct parsed_catalog* parsed;
+ struct parsed_cmode* parsed_cmode = NULL;
+ char* filename = NULL;
+ (void)logger;
+
+ ASSERT(files_array && allocator && logger && out_parsed);
+
+ parsed = MEM_ALLOC(allocator, sizeof(*parsed));
+ if(!parsed) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+
+ parsed->allocator = allocator;
+ parsed->logger = logger;
+
+ files_count = darray_catalog_filenames_size_get(files_array);
+
+ darray_parsed_catalog_items_init(allocator, &parsed->catalog);
+ ERR(darray_parsed_catalog_items_resize(&parsed->catalog, files_count));
+ items = darray_parsed_catalog_items_data_get(&parsed->catalog);
+ for(i = 0; i < files_count; i++) {
+ const struct cyaml_schema_value* schema;
+
+ /* Parse constructive mode only */
+ filename = darray_catalog_filenames_cdata_get(files_array)[i];
+ err = cyaml_load_file(filename, config, &constructive_mode_schema,
+ (void**)&parsed_cmode, NULL);
+ ERR(cyaml_err_to_res_T(err));
+
+ /* Parse catalog items according to constructive mode */
+ schema = get_schema_from_parsed_cmode(parsed_cmode->cmode_type);
+ err = cyaml_load_file(filename, config, schema, &items[i].parsed_items, NULL);
+ ERR(cyaml_err_to_res_T(err));
+
+ /* Set other fields*/
+ items[i].filename = filename;
+ items[i].constructive_mode = parsed_cmode->cmode_type;
+
+ /* Free tmp struct */
+ err = cyaml_free(config, &constructive_mode_schema, parsed_cmode, 1);
+ CHK(RES_OK == cyaml_err_to_res_T(err));
+ parsed_cmode = NULL;
+ filename = NULL;
+ }
+
+exit:
+ if(parsed_cmode) {
+ err = cyaml_free(config, &city_schema, parsed_cmode, 1);
+ CHK(RES_OK == cyaml_err_to_res_T(err));
+ }
+ *out_parsed = parsed;
+ return res;
+error:
+ if(filename) {
+ logger_print(logger, LOG_ERROR,
+ "Error parsing catalog file '%s'.\n", filename);
+ }
+ release_parsed_catalog(config, parsed);
+ parsed = NULL;
+ goto exit;
+}
+
+void
+release_parsed_catalog
+ (const struct cyaml_config* config,
+ struct parsed_catalog* parsed)
+{
+ struct parsed_catalog_items* items;
+ size_t i, count;
+
+ if(!parsed) return;
+
+ ASSERT(config);
+
+ count = darray_parsed_catalog_items_size_get(&parsed->catalog);
+ items = darray_parsed_catalog_items_data_get(&parsed->catalog);
+ for(i = 0; i < count; i++) {
+ const struct cyaml_schema_value* schema
+ = get_schema_from_parsed_cmode(items[i].constructive_mode);
+ cyaml_err_t err = cyaml_free(config, schema, items[i].parsed_items, 1);
+ CHK(RES_OK == cyaml_err_to_res_T(err));
+ }
+ darray_parsed_catalog_items_release(&parsed->catalog);
+ MEM_RM(parsed->allocator, parsed);
+}
diff --git a/src/cg_catalog_parsing.h b/src/cg_catalog_parsing.h
@@ -0,0 +1,66 @@
+/* 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 PARSING_H
+#define PARSING_H
+
+#include "cg_building.h"
+#include "cg_constructive_mode_0_parsing_schemas.h"
+#include "cg_constructive_mode_1_parsing_schemas.h"
+#include "cg_constructive_modes_parsing_schemas.h"
+
+#include <rsys/rsys.h>
+#include <rsys/dynamic_array.h>
+
+struct logger;
+struct mem_allocator;
+struct cyaml_config;
+struct cyaml_schema_value;
+struct darray_catalog_filenames;
+
+struct parsed_catalog_items {
+ enum parsed_cmode_type constructive_mode;
+ const char* filename;
+ void* parsed_items;
+};
+
+#define DARRAY_NAME parsed_catalog_items
+#define DARRAY_DATA struct parsed_catalog_items
+#include <rsys/dynamic_array.h>
+
+struct parsed_catalog {
+ struct mem_allocator* allocator;
+ struct logger* logger;
+ struct darray_parsed_catalog_items catalog;
+};
+
+res_T
+parse_catalog
+ (const struct darray_catalog_filenames* files,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ const struct cyaml_config* config,
+ struct parsed_catalog** catalog);
+
+void
+release_parsed_catalog
+ (const struct cyaml_config* config,
+ struct parsed_catalog* parsed);
+
+#endif /*PARSING_H*/
diff --git a/src/cg_city.c b/src/cg_city.c
@@ -17,139 +17,177 @@
* 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 "cg.h"
+#include "cg_city.h"
+#include "cg_constructive_mode_0.h"
+#include "cg_ground.h"
+#include "cg_catalog_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 "cg.h"
-#include "cg_city.h"
-#include "cg_parsing.h"
-#include "cg_building.h"
-#include "cg_args.h"
+#include <star/scpr.h>
+
+#include <string.h>
res_T
-city_init(struct logger* logger, struct city* city, struct args* args)
+create_city
+ (struct mem_allocator* allocator,
+ struct logger* logger,
+ const struct args* args,
+ struct parsed_city* parsed_city,
+ struct catalog* catalog,
+ struct city** out_city)
{
res_T res = RES_OK;
size_t i=0;
- struct txtrdr* reader = NULL;
- struct htable_building_params ht_params;
+ struct city* city = NULL;
+ (void)logger;
- city->binary_export = args->binary_export;
+ ASSERT(logger && allocator && args && parsed_city && catalog && out_city);
- ERR(txtrdr_file(NULL, args->city_model_file, '#', &reader));
- ERR(parse_city(logger, reader, city));
+ city = MEM_CALLOC(allocator, 1, sizeof(*city));
+ if(!city) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+
+ 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;
+ }
- ERR(parse_building_params(logger, &ht_params));
+ city->allocator = allocator;
+ city->logger = logger;
+ city->verbosisty_level = args->verbosity_level;
+ city->binary_export = args->binary_export;
- for (i=0; i<city->n ; ++i) {
- city->building[i].release = NULL;
- switch(city->building[i].model) {
- case model0:
- city->building[i].init = &init_model0;
+ city->ground_depth = parsed_city->ground.depth;
+ d4_set(city->ground_extent, parsed_city->ground.extent);
+
+ /* 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_cmode_0(building, allocator, logger, parsed_data, catalog));
break;
- case model1:
- city->building[i].init = &init_model1;
+ case PARSED_CMODE_1:
+ ERR(init_cmode_1(building, allocator, logger, parsed_data, catalog));
break;
default:
res = RES_BAD_ARG;
goto error;
}
- ERR(city->building[i].init(&city->building[i], &ht_params));
}
exit:
- txtrdr_ref_put(reader);
- htable_building_params_release(&ht_params);
+ *out_city = city;
return res;
error:
+ release_city(city);
+ out_city = NULL;
goto exit;
}
-res_T
-city_release(struct city* city)
+void
+release_city(struct city* city)
{
- res_T res = RES_OK;
- size_t i,n;
+ size_t i;
+
+ if(!city) return;
/* 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) {
+ struct building* building = city->buildings + i;
+ SCPR(polygon_ref_put(building->pg));
+ if(building->name_initialized) str_release(&building->name);
}
- ERR(ground_release(&city->ground));
-
- if (city->building) sa_release(city->building);
-
-exit:
- return res;
-error:
- goto exit;
+ MEM_RM(city->allocator, city->buildings);
+ MEM_RM(city->allocator, city);
}
res_T
-city_cad_build(struct logger* logger, struct city* city)
+city_cad_build(struct city* city)
{
res_T res = RES_OK;
struct scad_options options = SCAD_DEFAULT_OPTIONS__;
- size_t i,n;
+ int scad_initialized = 0;
+ size_t i;
- ERR(scad_initialize(logger, NULL, 0));
+ /* Initialize star-cad */
+ ERR(scad_initialize(city->logger, city->allocator, city->verbosisty_level));
+ scad_initialized = 1;
options.Mesh.MeshSizeFromPoints = 0;
ERR(scad_set_options(&options));
- /* iterate on building */
- n = city->n;
- for (i=0; i<n; ++i) {
+ /* iterate on buildings */
+ for(i=0; i<city->buildings_count; ++i) {
+ struct building* building = city->buildings + i;
+ struct data_cad_cmode_0* cad = NULL;
/* create building */
- ERR(city->building[i].build_cad(&city->building[i]));
+ ERR(building->functors->build_cad(building, city->allocator, city->logger,
+ (void**)&cad));
ERR(scad_scene_mesh());
- ERR(city->building[i].export_stl(&city->building[i], city->binary_export));
+ ERR(building->functors->export_stl(cad, city->allocator, city->logger,
+ city->binary_export));
+ ERR(building->functors->release_cad(city->allocator, city->logger, cad));
ERR(scad_scene_clear());
}
exit:
- scad_finalize();
+ if(scad_initialized) CHK(RES_OK == scad_finalize());
return res;
error:
goto exit;
}
res_T
-city_ground_build(struct logger* logger, struct city* city)
+city_ground_build(struct city* city)
{
res_T res = RES_OK;
struct scad_options options = SCAD_DEFAULT_OPTIONS__;
- size_t i,n;
+ int scad_initialized = 0;
+ struct ground ground = GROUND_NULL__;
+ size_t i;
- ERR(scad_initialize(logger, NULL, 0));
+ ERR(ground_allocate(city->allocator, city->buildings_count, &ground));
+
+ /* Initialize star-cad */
+ ERR(scad_initialize(city->logger, city->allocator, city->verbosisty_level));
+ scad_initialized = 1;
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) {
+ /* iterate on buildings */
+ for(i = 0; i < ground.footprints_count ; ++i) {
+ struct building* building = city->buildings + i;
+ struct scad_geometry** footprint = ground.footprints + i;
/* create building footprint */
- ERR(city->building[i].build_footprint
- (&city->building[i],
- &city->ground.footprint[i]));
+ ERR(building->functors->build_footprint(building, city->allocator,
+ city->logger, footprint));
}
-
- ERR(ground_build_cad(&city->ground));
+ ERR(ground_build_cad(city, &ground));
ERR(scad_scene_mesh());
- ERR(ground_export_stl(&city->ground, city->binary_export));
+ ERR(ground_export_stl(&ground, city->binary_export));
exit:
- scad_finalize();
+ ground_release(city->allocator, &ground);
+ if(scad_initialized) CHK(RES_OK == scad_finalize());
return res;
error:
goto exit;
diff --git a/src/cg_city.h b/src/cg_city.h
@@ -20,61 +20,48 @@
#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;
-
-static INLINE void
-log_prt_fn(const char* msg, void* ctx)
-{
- ASSERT(msg);
- (void)ctx;
-
- fprintf(stderr, "\x1b[32moutput:\x1b[0m %s", msg);
-}
-
-static INLINE void
-log_warn_fn(const char* msg, void* ctx)
-{
- ASSERT(msg);
- (void)ctx;
-
- fprintf(stderr, "\x1b[33mwarning:\x1b[0m %s", msg);
-}
-
-static INLINE void
-log_err_fn(const char* msg, void* ctx)
-{
- ASSERT(msg);
- (void)ctx;
-
- fprintf(stderr, "\x1b[31merror:\x1b[0m %s", msg);
-}
+struct parsed_city;
+struct catalog;
struct city {
- struct building* building; /* list of buildings */
- size_t n;
- struct ground ground;
+ double ground_extent[4]; /* [xmin, xmax, ymin, ymax */
+ double ground_depth;
+ struct building* buildings; /* list of buildings */
+ size_t buildings_count;
int binary_export;
-};
-#define CITY_NULL__ {NULL, 0, GROUND_NULL__, 0}
-static const struct city CITY_NULL = CITY_NULL__;
+ struct mem_allocator* allocator;
+ struct logger* logger;
+ int verbosisty_level;
+};
res_T
-city_init(struct logger* logger, struct city* city, struct args* arg);
+create_city
+ (struct mem_allocator* allocator,
+ struct logger* logger,
+ const struct args* args,
+ struct parsed_city* parsed_city,
+ struct catalog* catalog,
+ struct city** out_city);
res_T
-city_cad_build(struct logger* logger, struct city* city);
+city_cad_build
+ (struct city* city);
res_T
-city_ground_build(struct logger* logger, struct city* city);
+city_ground_build
+ (struct city* city);
+
+void
+release_city(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,76 @@
+/* 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;
+
+ ASSERT(allocator && logger && name && config && out_parsed);
+
+ err = cyaml_load_file(name, config, &city_schema, (void**)&parsed, NULL);
+ ERR(cyaml_err_to_res_T(err));
+
+ parsed->allocator = allocator;
+ parsed->logger = logger;
+
+exit:
+ *out_parsed = parsed;
+ return res;
+error:
+ logger_print(logger, LOG_ERROR, "Error parsing city map file '%s'.\n", name);
+ release_parsed_city(config, parsed);
+ parsed = NULL;
+ goto exit;
+}
+
+void
+release_parsed_city
+ (const struct cyaml_config* config,
+ struct parsed_city* parsed)
+{
+ cyaml_err_t err;
+
+ if(!parsed) return;
+
+ ASSERT(config);
+
+ err = cyaml_free(config, &city_schema, parsed, 1);
+ CHK(RES_OK == cyaml_err_to_res_T(err));
+}
diff --git a/src/cg_city_parsing.h b/src/cg_city_parsing.h
@@ -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);
+
+void
+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,145 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * Copyright (C) 2022 CNRS
+ * Copyright (C) 2022 Sorbonne Université
+ * Copyright (C) 2022 Université Paul Sabatier
+ * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef FG_CITY_PARSING_SCHEMAS__
+#define FG_CITY_PARSING_SCHEMAS__
+
+#include "cg_constructive_modes_parsing_schemas.h"
+
+#include <cyaml/cyaml.h>
+
+/********************************************************/
+/* Types used for parsing and to define parsing schemas */
+/********************************************************/
+
+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 mem_allocator* allocator;
+ struct logger* logger;
+ 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
@@ -0,0 +1,634 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * Copyright (C) 2022 CNRS
+ * Copyright (C) 2022 Sorbonne Université
+ * Copyright (C) 2022 Université Paul Sabatier
+ * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "cg.h"
+#include "cg_building.h"
+#include "cg_catalog.h"
+#include "cg_city.h"
+#include "cg_city_parsing_schemas.h"
+#include "cg_constructive_mode_0.h"
+#include "cg_constructive_mode.h"
+
+#include <rsys/rsys.h>
+#include <rsys/str.h>
+#include <rsys/logger.h>
+#include <star/scad.h>
+
+static res_T
+build_floor_footprint
+ (struct scpr_polygon* pg,
+ struct scad_geometry** footprint)
+{
+ res_T res = RES_OK;
+ size_t nverts;
+
+ ASSERT(pg && footprint);
+ ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
+ ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, footprint));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_floor
+ (const char* prefix,
+ struct scpr_polygon* pg,
+ struct building* b,
+ struct scad_geometry** floor)
+{
+ res_T res = RES_OK;
+ double e;
+ struct dataset_cmode_0* data;
+ struct scad_geometry* footprint = NULL;
+ double d[3] = {0, 0, 0};
+ char* floorname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(pg && b && floor);
+
+ data = (struct dataset_cmode_0*)b->data;
+ e = data->floor_thickness;
+
+ str_init(NULL, &name);
+ is_init = 1;
+ if (prefix) {
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_floor"));
+ floorname = str_get(&name);
+ }
+
+ ERR(build_floor_footprint(pg, &footprint));
+
+ d[2] = e;
+ ERR(scad_geometry_extrude(footprint, floorname, d, floor));
+
+exit:
+ SCAD(geometry_delete(footprint));
+ if (is_init) str_release(&name);
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_roof
+ (const char* prefix,
+ const struct building* b,
+ const struct scad_geometry* floor,
+ struct scad_geometry** roof)
+{
+ res_T res = RES_OK;
+ double height;
+ double e;
+ double d[3] = {0, 0, 0};
+ struct dataset_cmode_0* data;
+ char* roofname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(b && floor && roof);
+
+ str_init(NULL, &name);
+ is_init = 1;
+ if (prefix) {
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_roof"));
+ roofname = str_get(&name);
+ }
+
+ height = b->height;
+ data = (struct dataset_cmode_0*)b->data;
+ e = data->floor_thickness;
+
+ ERR(scad_geometry_copy(floor, roofname, roof));
+ d[2] = height - e ;
+ ERR(scad_geometry_translate(*roof, d));
+
+exit:
+ if (is_init) str_release(&name);
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_wall_footprint
+ (struct scpr_polygon* pg,
+ struct scpr_polygon* pg_int,
+ struct scad_geometry** footprint)
+{
+ res_T res = RES_OK;
+ struct scad_geometry* polygon = NULL;
+ struct scad_geometry* polygon_int = NULL;
+ size_t nverts, nverts_int;
+
+ ASSERT(pg && pg_int && footprint);
+
+ ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
+ ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, &polygon));
+
+ ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts_int));
+ ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts_int, &polygon_int));
+
+ ERR(scad_cut_geometries(NULL, &polygon, 1, &polygon_int, 1, footprint));
+
+exit:
+ if(polygon) SCAD(geometry_delete(polygon));
+ if(polygon_int) SCAD(geometry_delete(polygon_int));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_wall
+ (const char* prefix,
+ struct scpr_polygon* pg,
+ struct scpr_polygon* pg_int,
+ struct building* b,
+ struct scad_geometry** wall)
+{
+ res_T res = RES_OK;
+ double height;
+ struct scad_geometry* footprint = NULL;
+ double d[3] = {0, 0, 0};
+ char* wallname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(pg && pg_int && b && wall);
+
+ height = b->height;
+
+ str_init(NULL, &name);
+ is_init = 1;
+ if (prefix) {
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_wall"));
+ wallname = str_get(&name);
+ }
+
+ ERR(build_wall_footprint(pg, pg_int, &footprint));
+
+ d[2] = height;
+ ERR(scad_geometry_extrude(footprint, wallname, d, wall));
+
+exit:
+ if(footprint) SCAD(geometry_delete(footprint));
+ if (is_init) str_release(&name);
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_cavity
+ (const char* prefix,
+ struct scpr_polygon* pg,
+ const struct building* b,
+ struct scad_geometry** cavity)
+{
+ res_T res = RES_OK;
+ double e, height;
+ struct dataset_cmode_0* data;
+ double d[3] = {0, 0, 0};
+ struct scad_geometry* polygon = NULL;
+ char* cavityname = NULL;
+ struct str name;
+ int is_init = 0;
+ size_t nverts;
+
+ ASSERT(pg && b && cavity);
+
+ height = b->height;
+ data = (struct dataset_cmode_0*)b->data;
+ e = data->floor_thickness;
+
+ str_init(NULL, &name);
+ is_init = 1;
+ if (prefix) {
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_cavity"));
+ cavityname = str_get(&name);
+ }
+
+ ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
+ ERR(scad_add_polygon(NULL, get_position_pg, pg, e, nverts, &polygon));
+
+ d[2] = height - e;
+ ERR(scad_geometry_extrude(polygon, cavityname, d, cavity));
+
+exit:
+ if(polygon) SCAD(geometry_delete(polygon));
+ if (is_init) str_release(&name);
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_connection
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ struct data_cad_cmode_0* cad)
+{
+ res_T res = RES_OK;
+ char* cname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && cad);
+
+ cad->connection = MEM_CALLOC(allocator, 3, sizeof(struct scad_geometry*));
+ if(!cad->connection) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ cad->n_connection = 3;
+
+ /* cavity/floor connection */
+ str_init(NULL, &name);
+ is_init = 1;
+ if (prefix) {
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_C_cavity_floor"));
+ cname = str_get(&name);
+ }
+
+ ERR(scad_geometries_common_boundaries(cname, &cad->cavity, 1, &cad->floor, 1,
+ &cad->connection[0]));
+
+ /* cavity/wall connection */
+ if (prefix) {
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_C_cavity_wall"));
+ cname = str_get(&name);
+ }
+
+ ERR(scad_geometries_common_boundaries(cname, &cad->cavity, 1, &cad->wall, 1,
+ &cad->connection[1]));
+
+ /* cavity/roof connection */
+ if (prefix) {
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_C_cavity_roof"));
+ cname = str_get(&name);
+ }
+
+ ERR(scad_geometries_common_boundaries(cname, &cad->cavity, 1, &cad->roof, 1,
+ &cad->connection[2]));
+
+exit:
+ if (is_init) str_release(&name);
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_boundary
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ struct data_cad_cmode_0* cad)
+{
+ res_T res = RES_OK;
+ struct scad_geometry** list = NULL;
+ struct scad_geometry* boundary = NULL;
+ char* cname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && cad);
+
+ list = MEM_ALLOC(allocator, 4 * sizeof(struct scad_geometry*));
+ if(!list) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ list[0] = cad->floor;
+ list[1] = cad->wall;
+ list[2] = cad->roof;
+ list[3] = cad->cavity;
+
+ str_init(NULL, &name);
+ is_init = 1;
+ if (prefix) {
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_boundary"));
+ cname = str_get(&name);
+ }
+
+ ERR(scad_geometry_boundary(NULL, list, 4, &boundary));
+
+ ERR(scad_cut_geometries(cname, &boundary, 1, &cad->ground_connection, 1,
+ &cad->boundary));
+
+exit:
+ if(boundary) SCAD(geometry_delete(boundary));
+ MEM_RM(allocator, list);
+ if (is_init) str_release(&name);
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+building_ground_connection
+ (const char* prefix,
+ struct scpr_polygon* pg,
+ const double e,
+ struct scad_geometry** connection)
+{
+ res_T res = RES_OK;
+ struct scpr_polygon* pg_int = NULL;
+ struct scad_geometry* geom[2] = { NULL, NULL };
+ char* cname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(pg && e > 0 && connection);
+
+ if (prefix) {
+ str_init(NULL, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_C_building_ground"));
+ cname = str_get(&name);
+ }
+
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_offset_polygon(pg_int, -e, SCPR_JOIN_MITER));
+
+ ERR(build_wall_footprint(pg, pg_int, &geom[0]));
+ ERR(build_floor_footprint(pg, &geom[1]));
+
+ ERR(scad_fragment_geometries(cname, &geom[0], 1, &geom[1], 1, connection));
+
+exit:
+ if(is_init) str_release(&name);
+ if(geom[0]) SCAD(geometry_delete(geom[0]));
+ if(geom[1]) SCAD(geometry_delete(geom[1]));
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
+ return res;
+error:
+ goto exit;
+}
+
+/*----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+res_T
+init_cmode_0
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ struct parsed_city_building* parsed_data,
+ struct catalog* catalog)
+{
+ res_T res = RES_OK;
+ struct dataset_cmode_0* dataset;
+ struct str dataset_name;
+ int name_initialized = 0;
+ static struct constructive_mode_functors functors_0
+ = {
+ &init_cmode_0,
+ &build_cad_cmode_0,
+ &build_footprint_cmode_0,
+ &export_stl_cmode_0,
+ &release_cad_cmode_0
+ };
+ (void)parsed_data;
+
+ if(!building || !allocator || !parsed_data || !catalog) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ building->constructive_mode = mode_0;
+ building->functors = &functors_0;
+ building->height = parsed_data->height;
+ str_init(allocator, &building->name);
+ building->name_initialized = 1;
+ str_init(allocator, &dataset_name);
+ name_initialized = 1;
+ ERR(str_set(&building->name, parsed_data->name));
+ ERR(str_set(&dataset_name, parsed_data->dataset_name));
+
+ ERR(scpr_polygon_create(allocator, &building->pg));
+ ERR(scpr_polygon_setup_indexed_vertices(building->pg, 1, get_nverts, get_pos,
+ parsed_data));
+ dataset = htable_dataset_cmode_0_find(&catalog->catalog_0, &dataset_name);
+ if (dataset == NULL) {
+ ERR(logger_print(logger, LOG_ERROR,
+ "Unknown dataset name: '%s' used by building '%s'.\n",
+ str_cget(&dataset_name), str_cget(&building->name)));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ building->data = dataset;
+
+exit:
+ if(name_initialized) str_release(&dataset_name);
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+build_cad_cmode_0
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ void** cad)
+{
+ res_T res = RES_OK;
+ double height;
+ struct scpr_polygon* pg = NULL;
+ struct scpr_polygon* pg_int = NULL;
+ struct dataset_cmode_0* data = NULL;
+ struct data_cad_cmode_0* data_cad = NULL;
+ double e_wall;
+ const char* name;
+
+ if (!building || !allocator || !cad) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ height = building->height;
+ pg = building->pg;
+ data = (struct dataset_cmode_0 *)building->data;
+
+ if (height <= 0 || data->wall_thickness <= 0 || data->floor_thickness <= 0) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ data_cad = MEM_CALLOC(allocator, 1, sizeof(struct data_cad_cmode_0));
+ if(!data_cad) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+
+ e_wall = data->wall_thickness;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_offset_polygon(pg_int, -e_wall, SCPR_JOIN_MITER));
+
+ /* build floor with pg_int */
+ name = str_cget(&building->name);
+ ERR(build_floor(name, pg_int, building, &data_cad->floor));
+
+ /* roof is a translated copy of floor */
+ ERR(build_roof(name, building, data_cad->floor, &data_cad->roof));
+
+ /* build wall with pg and pg_int */
+ ERR(build_wall(name, pg, pg_int, building, &data_cad->wall));
+
+ /* build cavity */
+ ERR(build_cavity(name, pg_int, building, &data_cad->cavity));
+
+ ERR(scad_scene_partition());
+
+ /* build ground/building connection */
+ ERR(building_ground_connection(name, pg, e_wall, &data_cad->ground_connection));
+
+ /* build boundary */
+ ERR(build_boundary(name, allocator, data_cad));
+
+ /* build cavity/floor connectiona*/
+ ERR(build_connection(name, allocator, data_cad));
+
+exit:
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
+ *(struct data_cad_cmode_0**)cad = data_cad;
+ return res;
+error:
+ if(data_cad) CHK(RES_OK == release_cad_cmode_0(allocator, logger, data_cad));
+ data_cad = NULL;
+ goto exit;
+}
+
+res_T
+build_footprint_cmode_0
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ struct scad_geometry** footprint)
+{
+ res_T res = RES_OK;
+ struct scpr_polygon* pg = building->pg;
+ struct dataset_cmode_0* data = (struct dataset_cmode_0 *)building->data;
+ double e_wall;
+ (void)allocator; (void)logger;
+
+ if(!building || ! footprint) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ e_wall = data->wall_thickness;
+
+ ERR(building_ground_connection(NULL, pg, e_wall, footprint));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+export_stl_cmode_0
+ (void* cad,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ const int binary)
+{
+ res_T res = RES_OK;
+ struct data_cad_cmode_0* data_cad = (struct data_cad_cmode_0*)cad;
+ size_t i;
+ (void)allocator; (void)logger;
+
+ if(!cad) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* floor export */
+ ERR(scad_stl_export(data_cad->floor, NULL, binary));
+
+ /* roof export */
+ ERR(scad_stl_export(data_cad->roof, NULL, binary));
+
+ /* wall export */
+ ERR(scad_stl_export(data_cad->wall, NULL, binary));
+
+ /* cavity export */
+ ERR(scad_stl_export(data_cad->cavity, NULL, binary));
+
+ /* connection export */
+ for (i=0; i<data_cad->n_connection; ++i) {
+ ERR(scad_stl_export(data_cad->connection[i], NULL, binary));
+ }
+
+ /* boundary export */
+ ERR(scad_stl_export(data_cad->boundary, NULL, binary));
+
+ /* footprint export */
+ ERR(scad_stl_export(data_cad->ground_connection, NULL, binary));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+release_cad_cmode_0
+ (struct mem_allocator* allocator,
+ struct logger* logger,
+ void* cad)
+{
+ res_T res = RES_OK;
+ struct data_cad_cmode_0* data_cad = (struct data_cad_cmode_0 *)cad;
+ size_t i;
+ (void)logger;
+
+ if(!allocator || ! cad) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(data_cad->boundary) SCAD(geometry_delete(data_cad->boundary));
+ for(i = 0; i < data_cad->n_connection; i++) {
+ SCAD(geometry_delete(data_cad->connection[i]));
+ }
+ MEM_RM(allocator, data_cad->connection);
+ MEM_RM(allocator, data_cad);
+
+exit:
+ return res;
+error:
+ goto exit;
+}
diff --git a/src/cg_constructive_mode_0.h b/src/cg_constructive_mode_0.h
@@ -0,0 +1,99 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * Copyright (C) 2022 CNRS
+ * Copyright (C) 2022 Sorbonne Université
+ * Copyright (C) 2022 Université Paul Sabatier
+ * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef CONSTRUCTIVE_MODE_0_H
+#define CONSTRUCTIVE_MODE_0_H
+
+#include <rsys/rsys.h>
+#include <rsys/str.h>
+#include <rsys/hash_table.h>
+
+struct scad_geometry;
+
+struct building;
+struct mem_allocator;
+struct logger;
+struct parsed_city_building;
+struct catalog;
+
+/* specific data for constructive mode 0 */
+struct dataset_cmode_0 {
+ double wall_thickness;
+ double floor_thickness;
+};
+
+#define HTABLE_NAME dataset_cmode_0
+#define HTABLE_DATA struct dataset_cmode_0
+#define HTABLE_KEY struct str
+#define HTABLE_KEY_FUNCTOR_INIT str_init
+#define HTABLE_KEY_FUNCTOR_RELEASE str_release
+#define HTABLE_KEY_FUNCTOR_COPY str_copy
+#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release
+#define HTABLE_KEY_FUNCTOR_COPY_AND_CLEAR str_copy_and_clear
+#define HTABLE_KEY_FUNCTOR_EQ str_eq
+#define HTABLE_KEY_FUNCTOR_HASH str_hash
+#include <rsys/hash_table.h>
+
+struct data_cad_cmode_0 {
+ struct scad_geometry* wall;
+ struct scad_geometry* roof;
+ struct scad_geometry* floor;
+ struct scad_geometry* cavity;
+ struct scad_geometry* boundary;
+ struct scad_geometry** connection;
+ struct scad_geometry* ground_connection;
+ size_t n_connection;
+};
+
+res_T
+init_cmode_0
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ struct parsed_city_building* parsed_data,
+ struct catalog* catalog);
+
+res_T
+build_cad_cmode_0
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ void** cad);
+
+res_T
+build_footprint_cmode_0
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ struct scad_geometry** footprint);
+
+res_T
+export_stl_cmode_0
+ (void* cad,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ const int binary);
+
+res_T
+release_cad_cmode_0
+ (struct mem_allocator* allocator,
+ struct logger* logger,
+ void* cad);
+
+#endif /* CONSTRUCTIVE_MODE_0_H */
diff --git a/src/cg_constructive_mode_0_parsing_schemas.h b/src/cg_constructive_mode_0_parsing_schemas.h
@@ -0,0 +1,97 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * Copyright (C) 2022 CNRS
+ * Copyright (C) 2022 Sorbonne Université
+ * Copyright (C) 2022 Université Paul Sabatier
+ * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef FG_MODE0_PARSING_SCHEMAS__
+#define FG_MODE0_PARSING_SCHEMAS__
+
+#include "cg_building.h"
+#include "cg_city_parsing_schemas.h"
+
+#include <cyaml/cyaml.h>
+
+#include <rsys/rsys.h>
+#include <rsys/str.h>
+
+struct scpr_polygon;
+struct scad_geometry;
+struct mem_allocator;
+
+struct parsed_dataset_cmode_0 {
+ char* name;
+ double wall_thickness; /* must be > 0 */
+ double floor_thickness; /* must be > 0 */
+};
+
+/********************************************************/
+/* Types used for parsing and to define parsing schemas */
+/********************************************************/
+
+struct parsed_catalog_cmode_0 {
+ struct parsed_dataset_cmode_0* datasets;
+ size_t datasets_count;
+};
+
+static const cyaml_schema_field_t dataset_cmode_0_fields_schema[] = {
+ CYAML_FIELD_STRING_PTR("name", CYAML_FLAG_POINTER,
+ struct parsed_dataset_cmode_0, name, 0, CYAML_UNLIMITED),
+ CYAML_FIELD_FLOAT("wall_thickness", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_0, wall_thickness),
+ CYAML_FIELD_FLOAT("floor_thickness", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_0, floor_thickness),
+ CYAML_FIELD_END
+};
+
+static const struct cyaml_schema_value p_dataset_cmode_0_schema = {
+ CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_dataset_cmode_0,
+ dataset_cmode_0_fields_schema),
+};
+
+static const struct cyaml_schema_value dataset_cmode_0_schema = {
+ CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT, struct parsed_dataset_cmode_0,
+ dataset_cmode_0_fields_schema),
+};
+
+static const cyaml_schema_field_t cmode_0_fields_schemas[] = {
+ CYAML_FIELD_IGNORE("contructive_mode_type", CYAML_FLAG_DEFAULT),
+ {
+ .key = "sets",
+ .value = {
+ .type = CYAML_SEQUENCE,
+ .flags = CYAML_FLAG_POINTER,
+ .data_size = sizeof(struct parsed_dataset_cmode_0),
+ .sequence = {
+ .entry = &dataset_cmode_0_schema,
+ .min = 1,
+ .max = CYAML_UNLIMITED,
+ }
+ },
+ .data_offset = offsetof(struct parsed_catalog_cmode_0, datasets),
+ .count_size = sizeof(((struct parsed_catalog_cmode_0*)0)->datasets_count),
+ .count_offset = offsetof(struct parsed_catalog_cmode_0, datasets_count),
+ },
+ CYAML_FIELD_END
+};
+
+/* Top-level schema. The top level value for the constructive mode is a mapping */
+static const cyaml_schema_value_t constructive_mode_0_schema = {
+ CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_catalog_cmode_0,
+ cmode_0_fields_schemas),
+};
+
+#endif
diff --git a/src/cg_constructive_mode_1.c b/src/cg_constructive_mode_1.c
@@ -0,0 +1,1486 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * Copyright (C) 2022 CNRS
+ * Copyright (C) 2022 Sorbonne Université
+ * Copyright (C) 2022 Université Paul Sabatier
+ * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "cg.h"
+#include "cg_building.h"
+#include "cg_catalog.h"
+#include "cg_city_parsing_schemas.h"
+#include "cg_constructive_mode.h"
+#include "cg_constructive_mode_1.h"
+
+#include <rsys/str.h>
+#include <rsys/logger.h>
+#include <rsys/stretchy_array.h>
+#include <star/scad.h>
+#include <star/scpr.h>
+
+static res_T
+build_floor
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ const struct scpr_polygon* pg,
+ const struct dataset_cmode_1* data,
+ struct scad_geometry** floor)
+{
+ res_T res = RES_OK;
+ double e_wall = data->wall_thickness;
+ double e_insulation = data->external_insulation_thickness;
+ double e_floor = data->floor_thickness;
+ double offset = 0;
+ struct scpr_polygon* pg_int = NULL;
+ size_t nverts = 0;
+ struct scad_geometry* footprint = NULL;
+ double d[3] = {0, 0, 0};
+ char* floorname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && pg && data && floor);
+
+ if (prefix) {
+ str_init(allocator, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_floor"));
+ floorname = str_get(&name);
+ }
+
+ offset = e_wall + e_insulation;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
+
+ /*footprint*/
+ ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
+ ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts, &footprint));
+
+ d[2] = -e_floor;
+ ERR(scad_geometry_extrude(footprint, floorname, d, floor));
+
+exit:
+ SCAD(geometry_delete(footprint));
+ if (is_init) str_release(&name);
+ if (pg_int) SCPR(polygon_ref_put(pg_int));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_wall
+ (const char* prefix,
+ const char* suffix,
+ struct mem_allocator* allocator,
+ const struct scpr_polygon* pg,
+ const double height,
+ const struct dataset_cmode_1* data,
+ struct scad_geometry** wall)
+{
+ res_T res = RES_OK;
+ double e_wall = data->wall_thickness;
+ double e_insulation = data->external_insulation_thickness;
+ double offset = 0;
+ struct scpr_polygon* pg_int = NULL;
+ struct scpr_polygon* pg_ext = NULL;
+ size_t nverts = 0;
+ struct scad_geometry* footprint = NULL;
+ struct scad_geometry* footprint_int = NULL;
+ struct scad_geometry* footprint_ext = NULL;
+ double d[3] = {0, 0, 0};
+ char* wallname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && pg && data && wall);
+
+ if (prefix) {
+ str_init(allocator, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ if (suffix) {
+ ERR(str_append(&name, "_"));
+ ERR(str_append(&name, suffix));
+ }
+ wallname = str_get(&name);
+ }
+
+ offset = e_insulation;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_ext));
+ ERR(scpr_offset_polygon(pg_ext, -offset, SCPR_JOIN_MITER));
+
+ offset = e_wall + e_insulation;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
+
+ /*wall footprint*/
+ ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts));
+ ERR(scad_add_polygon(
+ NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext));
+
+ ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
+ ERR(scad_add_polygon(
+ NULL, get_position_pg, pg_int, 0, nverts, &footprint_int));
+
+ ERR(scad_cut_geometries(
+ NULL, &footprint_ext, 1, &footprint_int, 1, &footprint));
+
+ d[2] = height;
+ ERR(scad_geometry_extrude(footprint, wallname, d, wall));
+
+exit:
+ SCAD(geometry_delete(footprint));
+ SCAD(geometry_delete(footprint_int));
+ SCAD(geometry_delete(footprint_ext));
+ if (is_init) str_release(&name);
+ if (pg_int) SCPR(polygon_ref_put(pg_int));
+ if (pg_ext) SCPR(polygon_ref_put(pg_ext));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_int_insulation
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ const struct scpr_polygon* pg,
+ const double height,
+ const struct dataset_cmode_1* data,
+ struct scad_geometry* inter_floor,
+ struct scad_geometry** insulation)
+{
+ res_T res = RES_OK;
+ double e_wall = data->wall_thickness;
+ double e_roof = data->roof_thickness;
+ double e_roof_insulation = data->roof_insulation_thickness;
+ double attic = data->attic_height;
+ double e_ext_insulation = data->external_insulation_thickness;
+ double e_int_insulation = data->internal_insulation_thickness;
+ double offset = 0;
+ struct scpr_polygon* pg_int = NULL;
+ struct scpr_polygon* pg_ext = NULL;
+ size_t nverts = 0;
+ struct scad_geometry* footprint = NULL;
+ struct scad_geometry* footprint_int = NULL;
+ struct scad_geometry* footprint_ext = NULL;
+ struct scad_geometry* geom = NULL;
+ double d[3] = {0, 0, 0};
+ char* insulationname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && pg && data && insulation);
+
+ if (prefix) {
+ str_init(allocator, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_int_insulation"));
+ insulationname = str_get(&name);
+ }
+
+ offset = e_ext_insulation + e_wall;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_ext));
+ ERR(scpr_offset_polygon(pg_ext, -offset, SCPR_JOIN_MITER));
+
+ offset = e_ext_insulation + e_wall + e_int_insulation;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
+
+ /* insulation footprint */
+ ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts));
+ ERR(scad_add_polygon(
+ NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext));
+
+ ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
+ ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts, &footprint_int));
+
+ ERR(scad_cut_geometries(NULL, &footprint_ext, 1, &footprint_int, 1, &footprint));
+
+ d[2] = height - e_roof - attic - e_roof_insulation;
+ ERR(scad_geometry_extrude(footprint, NULL, d, &geom));
+
+ if (inter_floor) {
+ ERR(scad_cut_geometries(insulationname, &geom, 1, &inter_floor, 1, insulation));
+ } else {
+ ERR(scad_geometry_copy(geom, insulationname, insulation));
+ }
+
+exit:
+ SCAD(geometry_delete(footprint));
+ SCAD(geometry_delete(footprint_int));
+ SCAD(geometry_delete(footprint_ext));
+ SCAD(geometry_delete(geom));
+ if (is_init) str_release(&name);
+ if (pg_int) SCPR(polygon_ref_put(pg_int));
+ if (pg_ext) SCPR(polygon_ref_put(pg_ext));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_roof
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ const struct scpr_polygon* pg,
+ const double height,
+ const struct dataset_cmode_1* data,
+ struct scad_geometry** roof)
+{
+ res_T res = RES_OK;
+ double e_wall = data->wall_thickness;
+ double e_insulation = data->external_insulation_thickness;
+ double e_roof = data->roof_thickness;
+ double offset = 0;
+ double z_roof = 0;
+ struct scpr_polygon* pg_int = NULL;
+ size_t nverts = 0;
+ struct scad_geometry* footprint = NULL;
+ double d[3] = {0, 0, 0};
+ char* roofname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && pg && data && roof);
+
+ if (prefix) {
+ str_init(allocator, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_roof"));
+ roofname = str_get(&name);
+ }
+
+ offset = e_wall + e_insulation;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
+
+ /*footprint*/
+ ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
+ z_roof = height - e_roof;
+ ERR(scad_add_polygon(NULL, get_position_pg, pg_int, z_roof, nverts, &footprint));
+
+ d[2] = e_roof;
+ ERR(scad_geometry_extrude(footprint, roofname, d, roof));
+
+exit:
+ SCAD(geometry_delete(footprint));
+ if (is_init) str_release(&name);
+ if (pg_int) SCPR(polygon_ref_put(pg_int));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_roof_insulation
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ const struct scpr_polygon* pg,
+ const double height,
+ const struct dataset_cmode_1* data,
+ struct scad_geometry** insulation)
+{
+ res_T res = RES_OK;
+ double e_wall = data->wall_thickness;
+ double e_insulation = data->external_insulation_thickness;
+ double e_roof = data->roof_thickness;
+ double attic = data->attic_height;
+ double e_roof_insulation = data->roof_insulation_thickness;
+ double offset = 0;
+ double z_insulation = 0;
+ struct scpr_polygon* pg_int = NULL;
+ size_t nverts = 0;
+ struct scad_geometry* footprint = NULL;
+ double d[3] = {0, 0, 0};
+ char* insulationname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && pg && data && insulation);
+
+ if (prefix) {
+ str_init(allocator, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_roof_insulation"));
+ insulationname = str_get(&name);
+ }
+
+ offset = e_wall + e_insulation;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
+
+ /*footprint*/
+ ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
+ z_insulation = height - e_roof - attic - e_roof_insulation;
+ ERR(scad_add_polygon(
+ NULL, get_position_pg, pg_int, z_insulation, nverts, &footprint));
+
+ d[2] = e_roof_insulation;
+ ERR(scad_geometry_extrude(footprint, insulationname, d, insulation));
+
+exit:
+ SCAD(geometry_delete(footprint));
+ if (is_init) str_release(&name);
+ if (pg_int) SCPR(polygon_ref_put(pg_int));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_floor_insulation
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ const struct scpr_polygon* pg,
+ const struct dataset_cmode_1* data,
+ struct scad_geometry** insulation)
+{
+ res_T res = RES_OK;
+ double e_wall = data->wall_thickness;
+ double e_insulation = data->external_insulation_thickness;
+ double e_floor = data->floor_thickness;
+ double e_floor_insulation = data->floor_insulation_thickness;
+ double offset = 0;
+ double z_insulation = 0;
+ struct scpr_polygon* pg_int = NULL;
+ size_t nverts = 0;
+ struct scad_geometry* footprint = NULL;
+ double d[3] = {0, 0, 0};
+ char* insulationname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && pg && data && insulation);
+
+ if (prefix) {
+ str_init(allocator, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_floor_insulation"));
+ insulationname = str_get(&name);
+ }
+
+ offset = e_wall + e_insulation;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
+
+ /*footprint*/
+ ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
+ z_insulation = - e_floor - e_floor_insulation;
+ ERR(scad_add_polygon(
+ NULL, get_position_pg, pg_int, z_insulation, nverts, &footprint));
+
+ d[2] = e_floor_insulation;
+ ERR(scad_geometry_extrude(footprint, insulationname, d, insulation));
+
+exit:
+ SCAD(geometry_delete(footprint));
+ if (is_init) str_release(&name);
+ if (pg_int) SCPR(polygon_ref_put(pg_int));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_inter_floor
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ const struct scpr_polygon* pg,
+ const double height,
+ const struct dataset_cmode_1* data,
+ struct scad_geometry** inter_floor)
+{
+ res_T res = RES_OK;
+ size_t i = 0;
+ size_t floor_n = data->inter_floor_count;
+ double e_roof = data->roof_thickness;
+ double e_roof_ins = data->roof_insulation_thickness;
+ double attic = data->attic_height;
+ double e_floor = data->inter_floor_thickness;
+ double e_wall = data->wall_thickness;
+ double e_insulation = data->external_insulation_thickness;
+ double offset = 0;
+ double z_floor = 0;
+ double h_cavity = 0;
+ struct scpr_polygon* pg_int = NULL;
+ size_t nverts = 0;
+ struct scad_geometry** floor_list = NULL;
+ double d[3] = {0, 0, 0};
+ char* floorname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && pg && data && inter_floor);
+
+ if (prefix) {
+ str_init(allocator, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_inter_floor"));
+ floorname = str_get(&name);
+ }
+
+ offset = e_wall + e_insulation;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
+ ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
+
+ h_cavity = height - e_roof - attic - e_roof_ins - (double)floor_n*e_floor;
+ z_floor = h_cavity/(double)(1 + floor_n);
+ d[2] = e_floor;
+ for (i=0; i< floor_n; ++i) {
+ struct scad_geometry* floor = NULL;
+ struct scad_geometry* footprint = NULL;
+
+ ERR(scad_add_polygon(
+ NULL, get_position_pg, pg_int, z_floor, nverts, &footprint));
+ ERR(scad_geometry_extrude(footprint, NULL, d, &floor));
+ sa_push(floor_list, floor);
+ ERR(scad_geometry_delete(footprint));
+ z_floor += h_cavity/(double)(1 + floor_n) + e_floor;
+ }
+
+ ERR(scad_fuse_geometries(
+ floorname,
+ floor_list, sa_size(floor_list),
+ floor_list, sa_size(floor_list),
+ inter_floor));
+
+exit:
+ if (is_init) str_release(&name);
+ if (pg_int) SCPR(polygon_ref_put(pg_int));
+ if (floor_list) {
+ for (i=0; i< floor_n; ++i) {
+ SCAD(geometry_delete(floor_list[i]));
+ }
+ sa_release(floor_list);
+ }
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_ext_insulation
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ const struct scpr_polygon* pg,
+ const double height,
+ const struct dataset_cmode_1* data,
+ struct scad_geometry** insulation)
+{
+ res_T res = RES_OK;
+ double e_insulation = data->external_insulation_thickness;
+ double offset = 0;
+ struct scpr_polygon* pg_int = NULL;
+ struct scpr_polygon* pg_ext = NULL;
+ size_t nverts = 0;
+ struct scad_geometry* footprint = NULL;
+ struct scad_geometry* footprint_int = NULL;
+ struct scad_geometry* footprint_ext = NULL;
+ double d[3] = {0, 0, 0};
+ char* insulationname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && pg && data && insulation);
+
+ if (prefix) {
+ str_init(allocator, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_ext_insulation"));
+ insulationname = str_get(&name);
+ }
+
+ offset = e_insulation;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_ext));
+ ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
+
+ /*insulation footprint*/
+ ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts));
+ ERR(scad_add_polygon(
+ NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext));
+
+ ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
+ ERR(scad_add_polygon(
+ NULL, get_position_pg, pg_int, 0, nverts, &footprint_int));
+
+ ERR(scad_cut_geometries(
+ NULL, &footprint_ext, 1, &footprint_int, 1, &footprint));
+
+ d[2] = height;
+ ERR(scad_geometry_extrude(footprint, insulationname, d, insulation));
+
+exit:
+ SCAD(geometry_delete(footprint));
+ SCAD(geometry_delete(footprint_int));
+ SCAD(geometry_delete(footprint_ext));
+ if (is_init) str_release(&name);
+ if (pg_int) SCPR(polygon_ref_put(pg_int));
+ if (pg_ext) SCPR(polygon_ref_put(pg_ext));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_crawlspace
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ const struct scpr_polygon* pg,
+ const struct dataset_cmode_1* data,
+ struct scad_geometry** crawlspace)
+{
+ res_T res = RES_OK;
+ double e_wall = data->wall_thickness;
+ double e_insulation = data->external_insulation_thickness;
+ double e_crawl = data->crawl_height;
+ double e_floor = data->floor_thickness;
+ double e_floor_insulation = data->floor_insulation_thickness;
+ double offset = 0;
+ double z_crawl= 0;
+ struct scpr_polygon* pg_int = NULL;
+ size_t nverts = 0;
+ struct scad_geometry* footprint = NULL;
+ double d[3] = {0, 0, 0};
+ char* crawlname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && pg && data && crawlspace);
+
+ if (prefix) {
+ str_init(allocator, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_crawlspace"));
+ crawlname = str_get(&name);
+ }
+
+ offset = e_wall + e_insulation;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
+
+ /*footprint*/
+ ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
+ z_crawl = - e_floor - e_floor_insulation - e_crawl;
+ ERR(scad_add_polygon(
+ NULL, get_position_pg, pg_int, z_crawl, nverts, &footprint));
+
+ d[2] = e_crawl;
+ ERR(scad_geometry_extrude(footprint, crawlname, d, crawlspace));
+
+exit:
+ SCAD(geometry_delete(footprint));
+ if (is_init) str_release(&name);
+ if (pg_int) SCPR(polygon_ref_put(pg_int));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_habitable
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ const struct scpr_polygon* pg,
+ const double height,
+ const struct dataset_cmode_1* data,
+ struct scad_geometry* floor,
+ struct scad_geometry** cavity)
+{
+ res_T res = RES_OK;
+ double e_wall = data->wall_thickness;
+ double e_ext_insulation = data->external_insulation_thickness;
+ double e_int_insulation = data->internal_insulation_thickness;
+ double e_roof = data->roof_thickness;
+ double e_roof_insulation = data->roof_insulation_thickness;
+ double e_attic = data->attic_height;
+ double offset = 0;
+ struct scpr_polygon* pg_int = NULL;
+ size_t nverts = 0;
+ struct scad_geometry* footprint = NULL;
+ struct scad_geometry* geom = NULL;
+ double d[3] = {0, 0, 0};
+ char* cavityname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && pg && data && cavity);
+
+ if (prefix) {
+ str_init(allocator, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_cavity"));
+ cavityname = str_get(&name);
+ }
+
+ offset = e_wall + e_ext_insulation + e_int_insulation;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
+
+ /*footprint*/
+ ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
+ ERR(scad_add_polygon(
+ NULL, get_position_pg, pg_int, 0, nverts, &footprint));
+
+ d[2] = height - e_roof - e_attic - e_roof_insulation;
+ ERR(scad_geometry_extrude(footprint, NULL, d, &geom));
+ if (floor) {
+ ERR(scad_cut_geometries(
+ cavityname, &geom, 1, &floor, 1, cavity));
+ } else {
+ ERR(scad_geometry_copy(geom, cavityname, cavity));
+ }
+
+exit:
+ SCAD(geometry_delete(footprint));
+ SCAD(geometry_delete(geom));
+ if (is_init) str_release(&name);
+ if (pg_int) SCPR(polygon_ref_put(pg_int));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_attic
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ const struct scpr_polygon* pg,
+ const double height,
+ const struct dataset_cmode_1* data,
+ struct scad_geometry** attic)
+{
+ res_T res = RES_OK;
+ double e_wall = data->wall_thickness;
+ double e_insulation = data->external_insulation_thickness;
+ double e_roof = data->roof_thickness;
+ double e_attic = data->attic_height;
+ double offset = 0;
+ double z_attic = 0;
+ struct scpr_polygon* pg_int = NULL;
+ size_t nverts = 0;
+ struct scad_geometry* footprint = NULL;
+ double d[3] = {0, 0, 0};
+ char* atticname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && pg && data && attic);
+
+ if (prefix) {
+ str_init(allocator, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_attic"));
+ atticname = str_get(&name);
+ }
+
+ offset = e_wall + e_insulation;
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_int));
+ ERR(scpr_offset_polygon(pg_int, -offset, SCPR_JOIN_MITER));
+
+ /*footprint*/
+ ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
+ z_attic = height - e_roof - e_attic;
+ ERR(scad_add_polygon(
+ NULL, get_position_pg, pg_int, z_attic, nverts, &footprint));
+
+ d[2] = e_attic;
+ ERR(scad_geometry_extrude(footprint, atticname, d, attic));
+
+exit:
+ SCAD(geometry_delete(footprint));
+ if (is_init) str_release(&name);
+ if (pg_int) SCPR(polygon_ref_put(pg_int));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_windows
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ const struct dataset_cmode_1* data,
+ struct data_cad_cmode_1* data_cad)
+{
+ res_T res = RES_OK;
+ size_t i = 0;
+ double N[3];
+ double dir[3];
+ double scale[3];
+ struct scad_geometry* surface = NULL;
+ struct scad_geometry* hole = NULL;
+ struct scad_geometry** hole_list = NULL;
+ struct scad_geometry* geom = NULL;
+ struct scad_geometry* bcavity = NULL;
+ struct scad_geometry** list = NULL;
+ struct scad_geometry* glass = NULL;
+ struct scad_geometry** glass_list = NULL;
+ size_t list_n = 0;
+ struct str gname;
+ int is_init = 0;
+
+ ASSERT(allocator && data && data_cad);
+
+ scale[0] = sqrt(data->glass_ratio);
+ scale[1] = scale[0];
+ scale[2] = scale[0];
+
+ /* windows are build from the vertical faces of habitable cavities */
+ ERR(scad_geometry_boundary(NULL, &data_cad->habitable_cavity, 1, &bcavity));
+ ERR(scad_geometry_explode(bcavity, NULL, &list, &list_n));
+
+ for (i=0; i<list_n; ++i){
+ double* center = NULL;
+ size_t center_n = 0;
+
+ ERR(scad_geometry_get_centerofmass(list[i], ¢er, ¢er_n));
+
+ ERR(scad_geometry_normal(list[i], center, N, NULL, &surface));
+
+ if (N[2] != 0) {
+ ERR(scad_geometry_delete(surface));
+ surface = NULL;
+ continue; /* keep only vertical face */
+ }
+
+ ERR(scad_geometry_dilate(surface, center, scale));
+
+ dir[0] = 1.1*N[0] * (data->wall_thickness
+ + data->internal_insulation_thickness + data->external_insulation_thickness);
+ dir[1] = 1.1*N[1] * (data->wall_thickness
+ + data->internal_insulation_thickness + data->external_insulation_thickness);
+ dir[2] = 1.1*N[2] * (data->wall_thickness
+ + data->internal_insulation_thickness + data->external_insulation_thickness);
+ ERR(scad_geometry_extrude(surface, NULL, dir, &hole));
+ sa_push(hole_list, hole);
+
+ dir[0] = N[0] * 0.024;
+ dir[1] = N[1] * 0.024;
+ dir[2] = N[2] * 0.024;
+ ERR(scad_geometry_extrude(surface, NULL, dir, &glass));
+ sa_push(glass_list, glass);
+
+ ERR(scad_geometry_delete(surface));
+ surface = NULL;
+ }
+
+ /* wall perforation */
+ ERR(scad_cut_geometries(NULL, &data_cad->wall, 1,
+ hole_list, sa_size(hole_list), &geom));
+ ERR(scad_geometry_swap_names(data_cad->wall, geom));
+ ERR(scad_geometry_delete(data_cad->wall));
+ data_cad->wall = geom;
+ geom = NULL;
+
+ /* internal insulation perforation */
+ if (data_cad->internal_insulation) {
+ ERR(scad_cut_geometries(NULL, &data_cad->internal_insulation, 1,
+ hole_list, sa_size(hole_list), &geom));
+ ERR(scad_geometry_swap_names(data_cad->internal_insulation, geom));
+ ERR(scad_geometry_delete(data_cad->internal_insulation));
+ data_cad->internal_insulation = geom;
+ geom = NULL;
+ }
+
+ /* external insulation perforation */
+ if (data_cad->external_insulation) {
+ ERR(scad_cut_geometries(NULL, &data_cad->external_insulation, 1,
+ hole_list, sa_size(hole_list), &geom));
+ ERR(scad_geometry_swap_names(data_cad->external_insulation, geom));
+ ERR(scad_geometry_delete(data_cad->external_insulation));
+ data_cad->external_insulation = geom;
+ geom = NULL;
+ }
+
+ /* build glass */
+ if (prefix) {
+ str_init(allocator, &gname);
+ is_init = 1;
+ ERR(str_set(&gname, prefix));
+ ERR(str_append(&gname, "_glass"));
+ }
+
+ ERR(scad_fuse_geometries(str_cget(&gname), glass_list, 1,
+ glass_list+1, sa_size(glass_list) - 1, &data_cad->glass));
+
+exit:
+ for (i=0 ; i<list_n; ++i) {
+ SCAD(geometry_delete(list[i]));
+ }
+ for (i=0 ; i<sa_size(hole_list); ++i) {
+ SCAD(geometry_delete(hole_list[i]));
+ }
+ for (i=0 ; i<sa_size(glass_list); ++i) {
+ SCAD(geometry_delete(glass_list[i]));
+ }
+ if (hole_list) sa_release(hole_list);
+ if (glass_list) sa_release(glass_list);
+ if (surface) SCAD(geometry_delete(surface));
+ if (geom) SCAD(geometry_delete(geom));
+ if (bcavity) SCAD(geometry_delete(bcavity));
+ MEM_RM(allocator, list);
+ if (is_init) str_release(&gname);
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_boundary
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ struct data_cad_cmode_1* data_cad,
+ struct scad_geometry*** boundary)
+{
+ res_T res = RES_OK;
+ struct scad_geometry** list = NULL;
+ struct scad_geometry* bound = NULL;
+ char* boundaryname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && prefix && data_cad && boundary);
+
+ str_init(allocator, &name);
+ is_init = 1;
+
+ sa_push(list, data_cad->wall);
+ sa_push(list, data_cad->roof);
+ sa_push(list, data_cad->floor);
+ sa_push(list, data_cad->habitable_cavity);
+ sa_push(list, data_cad->fake_ground);
+ if (data_cad->foundation) sa_push(list, data_cad->foundation);
+ if (data_cad->intermediate_floor) sa_push(list, data_cad->intermediate_floor);
+ if (data_cad->external_insulation) sa_push(list, data_cad->external_insulation);
+ if (data_cad->internal_insulation) sa_push(list, data_cad->internal_insulation);
+ if (data_cad->roof_insulation) sa_push(list, data_cad->roof_insulation);
+ if (data_cad->floor_insulation) sa_push(list, data_cad->floor_insulation);
+ if (data_cad->attic_cavity) sa_push(list, data_cad->attic_cavity);
+ if (data_cad->crawlspace_cavity) sa_push(list, data_cad->crawlspace_cavity);
+ if (data_cad->glass) sa_push(list, data_cad->glass);
+
+
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_boundary_wall"));
+ boundaryname = str_get(&name);
+ ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list),
+ &data_cad->wall, 1, &bound));
+ sa_push(*boundary, bound);
+
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_boundary_roof"));
+ boundaryname = str_get(&name);
+ ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list),
+ &data_cad->roof, 1, &bound));
+ sa_push(*boundary, bound);
+
+ if (data_cad->glass) {
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_boundary_glass"));
+ boundaryname = str_get(&name);
+ ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list),
+ &data_cad->glass, 1, &bound));
+ sa_push(*boundary, bound);
+ }
+
+ if (data_cad->external_insulation) {
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_boundary_ext_insulation"));
+ boundaryname = str_get(&name);
+ ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list),
+ &data_cad->external_insulation, 1, &bound));
+ sa_push(*boundary, bound);
+ }
+
+ if (data_cad->internal_insulation) {
+ size_t count = 0;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_boundary_int_insulation"));
+ boundaryname = str_get(&name);
+ ERR(scad_geometries_common_boundaries(boundaryname, list, sa_size(list),
+ &data_cad->internal_insulation, 1, &bound));
+ ERR(scad_geometry_get_count(bound, &count));
+ if (count>0) sa_push(*boundary, bound);
+ }
+
+exit:
+ if (is_init) str_release(&name);
+ if (list) sa_release(list);
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_connection
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ struct data_cad_cmode_1* data_cad,
+ struct scad_geometry*** connection)
+{
+ res_T res = RES_OK;
+ struct scad_geometry* connect = NULL;
+ size_t count = 0;
+ char* cname = NULL;
+ struct str name;
+ int is_init = 0;
+
+ ASSERT(allocator && prefix && data_cad && connection);
+
+ str_init(allocator, &name);
+ is_init = 1;
+
+#define CREATE_CONNECT(G1,G2,SUFFIX) ERR(str_set(&name, prefix));\
+ ERR(str_append(&name, SUFFIX));\
+ cname = str_get(&name);\
+ ERR(scad_geometries_common_boundaries\
+ (cname,\
+ &data_cad->G1, 1,\
+ &data_cad->G2, 1,\
+ &connect));\
+ ERR(scad_geometry_get_count(connect, &count)); \
+ if (count>0) sa_push(*connection, connect);
+
+
+ /* -------------------------------------------------------------------------*/
+ /* habitable cavity connections */
+ /* -------------------------------------------------------------------------*/
+
+ /* with floor */
+ CREATE_CONNECT(habitable_cavity,floor,"_C_cavity_floor");
+
+ /* with wall */
+ CREATE_CONNECT(habitable_cavity,wall,"_C_cavity_wall");
+
+ /* with glass */
+ if (data_cad->glass) {
+ CREATE_CONNECT(habitable_cavity,glass,"_C_cavity_glass");
+ }
+
+ /* with internal insulation */
+ if (data_cad->internal_insulation) {
+ CREATE_CONNECT(habitable_cavity,internal_insulation,"_C_cavity_internal_insulation");
+ }
+
+ /* with roof insulation */
+ if (data_cad->roof_insulation) {
+ CREATE_CONNECT(habitable_cavity,roof_insulation,"_C_roof_insulation");
+ } else {
+ /* with roof */
+ CREATE_CONNECT(habitable_cavity,roof,"_C_cavity_roof");
+ }
+
+ /* with intermediate floor */
+ if (data_cad->intermediate_floor) {
+ CREATE_CONNECT(habitable_cavity,intermediate_floor,"_C_cavity_intermediate_floor");
+ }
+
+ /* -------------------------------------------------------------------------*/
+ /* crawlspace cavity connections */
+ /* -------------------------------------------------------------------------*/
+
+ if (data_cad->crawlspace_cavity) {
+ /* with floor insulation */
+ if (data_cad->floor_insulation) {
+ CREATE_CONNECT(crawlspace_cavity, floor_insulation,"_C_crawlspace_insulation");
+ } else {
+ /* with floor */
+ CREATE_CONNECT(crawlspace_cavity, floor,"_C_crawlspace_floor");
+ }
+
+ /* with wall */
+ CREATE_CONNECT(crawlspace_cavity, foundation,"_C_crawlspace_foundation");
+ }
+
+ /* -------------------------------------------------------------------------*/
+ /* attic cavity connections */
+ /* -------------------------------------------------------------------------*/
+
+ if (data_cad->attic_cavity) {
+ /* with roof */
+ CREATE_CONNECT(attic_cavity, roof,"_C_attic_roof");
+
+ /* with roof insulation */
+ CREATE_CONNECT(attic_cavity, roof_insulation,"_C_attic_insulation");
+
+ /* with wall */
+ CREATE_CONNECT(attic_cavity, wall,"_C_attic_wall");
+ }
+
+#undef CREATE_CONNECT
+
+exit:
+ if (is_init) str_release(&name);
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_footprint
+ (struct scpr_polygon* pg,
+ struct scad_geometry** footprint)
+{
+ res_T res = RES_OK;
+ size_t nverts = 0;
+
+ ASSERT(pg && footprint);
+
+ ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
+ ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, footprint));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_fake_ground
+ (struct data_cad_cmode_1* cad,
+ struct scpr_polygon* pg,
+ const double depth,
+ struct scad_geometry** ground)
+{
+ res_T res = RES_OK;
+ double dir[3] = {0, 0, 0};
+ struct scpr_polygon* pg_offset = NULL;
+ struct scad_geometry** list = NULL;
+ struct scad_geometry* footprint = NULL;
+ struct scad_geometry* geom = NULL;
+
+ ASSERT(cad && pg && ground );
+
+ if (cad->foundation) sa_push(list, cad->foundation);
+ if (cad->crawlspace_cavity) sa_push(list, cad->crawlspace_cavity);
+ if (cad->floor) sa_push(list, cad->floor);
+ if (cad->floor_insulation) sa_push(list, cad->floor_insulation);
+
+ ERR(scpr_polygon_create_copy(NULL, pg, &pg_offset));
+ ERR(scpr_offset_polygon(pg_offset, 0.1, SCPR_JOIN_MITER));
+
+ ERR(build_footprint(pg_offset, &footprint));
+
+ dir[2] = -depth*1.1;
+ ERR(scad_geometry_extrude(footprint, NULL, dir, &geom));
+
+ ERR(scad_cut_geometries(NULL, &geom, 1, list, sa_size(list), ground));
+
+exit:
+ if (pg_offset) SCPR(polygon_ref_put(pg_offset));
+ if (list) sa_release(list);
+ if (footprint) SCAD(geometry_delete(footprint));
+ if (geom) SCAD(geometry_delete(geom));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+building_ground_connection
+ (const char* prefix,
+ struct mem_allocator* allocator,
+ struct data_cad_cmode_1* cad,
+ struct scad_geometry** connection)
+{
+ res_T res = RES_OK;
+ char* cname = NULL;
+ struct str name;
+ int is_init = 0;
+ struct scad_geometry** list = NULL;
+ struct scad_geometry* list_boundary = NULL;
+ struct scad_geometry* footprint = NULL;
+
+ ASSERT(prefix && allocator && cad && connection);
+
+ str_init(allocator, &name);
+ is_init = 1;
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_C_building_ground"));
+ cname = str_get(&name);
+
+ if (cad->foundation) sa_push(list, cad->foundation);
+ if (cad->attic_cavity) sa_push(list, cad->attic_cavity);
+ if (cad->floor) sa_push(list, cad->floor);
+ if (cad->floor_insulation) sa_push(list, cad->floor_insulation);
+ if (cad->external_insulation) sa_push(list, cad->external_insulation);
+ if (cad->wall) sa_push(list, cad->wall);
+
+ ERR(scad_geometries_common_boundaries(
+ cname, list, sa_size(list),
+ &cad->fake_ground, 1,
+ connection));
+
+exit:
+ if (list) sa_release(list);
+ if (is_init) str_release(&name);
+ if (list_boundary) SCAD(geometry_delete(list_boundary));
+ if (footprint) SCAD(geometry_delete(footprint));
+ return res;
+error:
+ goto exit;
+}
+
+/*----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+res_T
+init_cmode_1
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ struct parsed_city_building* parsed_data,
+ struct catalog* catalog)
+{
+ res_T res = RES_OK;
+ struct dataset_cmode_1* dataset;
+ struct str dataset_name;
+ int name_initialized = 0;
+ static struct constructive_mode_functors functors_1
+ = {
+ &init_cmode_1,
+ &build_cad_cmode_1,
+ &build_footprint_cmode_1,
+ &export_stl_cmode_1,
+ &release_cad_cmode_1
+ };
+ (void) parsed_data;
+
+ if(!building || !allocator || !parsed_data ||!catalog) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ building->constructive_mode = mode_1;
+ building->functors = &functors_1;
+ building->height = parsed_data->height;
+ str_init(allocator, &building->name);
+ building->name_initialized = 1;
+ str_init(allocator, &dataset_name);
+ name_initialized = 1;
+ ERR(str_set(&building->name, parsed_data->name));
+ ERR(str_set(&dataset_name, parsed_data->dataset_name));
+
+ ERR(scpr_polygon_create(allocator, &building->pg));
+ ERR(scpr_polygon_setup_indexed_vertices(building->pg, 1, get_nverts, get_pos,
+ parsed_data));
+ dataset = htable_dataset_cmode_1_find(&catalog->catalog_1, &dataset_name);
+ if (dataset == NULL) {
+ ERR(logger_print(logger, LOG_ERROR,
+ "Unknown dataset name: '%s' used by building '%s'.\n",
+ str_cget(&dataset_name), str_cget(&building->name)));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ building->data = dataset;
+
+exit:
+ if(name_initialized) str_release(&dataset_name);
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+build_cad_cmode_1
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ void** cad)
+{
+ res_T res = RES_OK;
+ double height = building->height;
+ double depth = 0;
+ struct scpr_polygon* pg = building->pg;
+ struct dataset_cmode_1* data = (struct dataset_cmode_1 *)building->data;
+ struct data_cad_cmode_1* data_cad = NULL;
+ const char* name;
+
+ if (!building || !allocator || !cad) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ data_cad = MEM_CALLOC(allocator, 1, sizeof(struct data_cad_cmode_1));
+ if(!data_cad) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+
+ /* build mandatories elements :
+ - floor
+ - wall
+ - roof
+ */
+
+ name = str_cget(&building->name);
+ ERR(build_floor(name, allocator, pg, data, &data_cad->floor));
+
+ ERR(build_wall(name, "wall", allocator, pg, height, data, &data_cad->wall));
+
+ ERR(build_roof(name, allocator, pg, height, data, &data_cad->roof));
+
+ /* build optionnal elements :
+ - foundation
+ - intermediate floor
+ - external insulation
+ - internal insulation
+ - roof insulation
+ - floor insulation
+ */
+
+ if (data->foundation_depth > 0) {
+ depth = -data->foundation_depth;
+ ERR(build_wall(name, "foundation", allocator, pg, depth, data,
+ &data_cad->foundation));
+ }
+
+ if (data->inter_floor_count > 0) {
+ ERR(build_inter_floor(name, allocator, pg, height, data,
+ &data_cad->intermediate_floor));
+ }
+
+ if (data->external_insulation_thickness> 0) {
+ ERR(build_ext_insulation(name, allocator, pg, height, data,
+ &data_cad->external_insulation));
+ }
+
+ if (data->internal_insulation_thickness> 0) {
+ ERR(build_int_insulation(name, allocator, pg, height, data,
+ data_cad->intermediate_floor, &data_cad->internal_insulation));
+ }
+
+ if (data->roof_insulation_thickness > 0) {
+ ERR(build_roof_insulation(name, allocator, pg, height, data,
+ &data_cad->roof_insulation));
+ }
+
+ if (data->floor_insulation_thickness > 0) {
+ ERR(build_floor_insulation(name, allocator, pg, data,
+ &data_cad->floor_insulation));
+ }
+
+ /* build cavities :
+ - attic
+ - habitable
+ - crawlspace
+ */
+
+ if (data->attic_height > 0) {
+ ERR(build_attic(name, allocator, pg, height, data, &data_cad->attic_cavity));
+ }
+
+ ERR(build_habitable(name, allocator, pg, height, data,
+ data_cad->intermediate_floor, &data_cad->habitable_cavity));
+
+ if (data->crawl_height > 0) {
+ ERR(build_crawlspace(name, allocator, pg, data, &data_cad->crawlspace_cavity));
+ }
+
+ /* windows */
+ if (data->glass_ratio > 0) {
+ ERR(build_windows(name, allocator, data, data_cad));
+ }
+
+ /* fake ground */
+ depth = MMAX(data->foundation_depth, data->floor_thickness
+ + data->floor_insulation_thickness + data->crawl_height);
+ ERR(build_fake_ground(data_cad, pg, depth, &data_cad->fake_ground));
+
+ ERR(scad_scene_partition());
+
+ /* build ground/buildind connection */
+ ERR(building_ground_connection(name, allocator, data_cad,
+ &data_cad->ground_connection));
+
+ /* build boundaries */
+ ERR(build_boundary(name, allocator, data_cad, &data_cad->boundary));
+
+ /* build connections */
+ ERR(build_connection(name, allocator, data_cad, &data_cad->connection));
+
+exit:
+ *(struct data_cad_cmode_1**)cad = data_cad;
+ return res;
+error:
+ if(data_cad) CHK(RES_OK == release_cad_cmode_1(allocator, logger, data_cad));
+ data_cad = NULL;
+ goto exit;
+}
+
+res_T
+build_footprint_cmode_1
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ struct scad_geometry** footprint)
+{
+ res_T res = RES_OK;
+ struct scpr_polygon* pg = building->pg;
+ (void)allocator; (void)logger;
+
+ if (!building || !footprint) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ ERR(build_footprint(pg, footprint));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+export_stl_cmode_1
+ (void* cad,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ const int binary)
+{
+ res_T res = RES_OK;
+ struct data_cad_cmode_1* data_cad = (struct data_cad_cmode_1 *)cad;
+ size_t i = 0;
+ (void)allocator; (void)logger;
+
+ if (!cad) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* floor export */
+ ERR(scad_stl_export(data_cad->floor, NULL, binary));
+
+ /* wall export */
+ ERR(scad_stl_export(data_cad->wall, NULL, binary));
+
+ /* roof export */
+ ERR(scad_stl_export(data_cad->roof, NULL, binary));
+
+ /* foundation export */
+ if (data_cad->foundation) {
+ ERR(scad_stl_export(data_cad->foundation, NULL, binary));
+ }
+
+ /* glass export */
+ if (data_cad->glass) {
+ ERR(scad_stl_export(data_cad->glass, NULL, binary));
+ }
+
+ /* intermediate floor export*/
+ if (data_cad->intermediate_floor) {
+ ERR(scad_stl_export(data_cad->intermediate_floor, NULL, binary));
+ }
+
+ /* internal insulation export*/
+ if (data_cad->internal_insulation) {
+ ERR(scad_stl_export(data_cad->internal_insulation, NULL, binary));
+ }
+
+ /* external insulation export*/
+ if (data_cad->external_insulation) {
+ ERR(scad_stl_export(data_cad->external_insulation, NULL, binary));
+ }
+
+ /* roof insulation export*/
+ if (data_cad->roof_insulation) {
+ ERR(scad_stl_export(data_cad->roof_insulation, NULL, binary));
+ }
+
+ /* floor insulation export*/
+ if (data_cad->floor_insulation) {
+ ERR(scad_stl_export(data_cad->floor_insulation, NULL, binary));
+ }
+
+ /* attic cavity export*/
+ if (data_cad->attic_cavity) {
+ ERR(scad_stl_export(data_cad->attic_cavity, NULL, binary));
+ }
+
+ /* habitable cavity export*/
+ ERR(scad_stl_export(data_cad->habitable_cavity, NULL, binary));
+
+ /* crawlspace cavity export*/
+ if (data_cad->crawlspace_cavity) {
+ ERR(scad_stl_export(data_cad->crawlspace_cavity, NULL, binary));
+ }
+
+ /* boundary export*/
+ for (i=0; i<sa_size(data_cad->boundary); ++i) {
+ ERR(scad_stl_export(data_cad->boundary[i], NULL, binary));
+ }
+
+ /* connections export*/
+ for (i=0; i<sa_size(data_cad->connection); ++i) {
+ ERR(scad_stl_export(data_cad->connection[i], NULL, binary));
+ }
+
+ /* ground/building connection export*/
+ ERR(scad_stl_export(data_cad->ground_connection, NULL, binary));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+release_cad_cmode_1
+ (struct mem_allocator* allocator,
+ struct logger* logger,
+ void* cad)
+{
+ res_T res = RES_OK;
+ struct data_cad_cmode_1* data_cad = (struct data_cad_cmode_1 *)cad;
+ size_t i;
+ (void)logger;
+
+ if (!allocator || !cad) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ for(i = 0; i < sa_size(data_cad->boundary); i++) {
+ ERR(scad_geometry_delete(data_cad->boundary[i]));
+ }
+ for(i = 0; i < sa_size(data_cad->connection); i++) {
+ ERR(scad_geometry_delete(data_cad->connection[i]));
+ }
+ sa_release(data_cad->boundary);
+ sa_release(data_cad->connection);
+ MEM_RM(allocator, data_cad);
+
+exit:
+ return res;
+error:
+ goto exit;
+}
diff --git a/src/cg_constructive_mode_1.h b/src/cg_constructive_mode_1.h
@@ -0,0 +1,120 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * Copyright (C) 2022 CNRS
+ * Copyright (C) 2022 Sorbonne Université
+ * Copyright (C) 2022 Université Paul Sabatier
+ * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef CONSTRUCTIVE_MODE_1_H
+#define CONSTRUCTIVE_MODE_1_H
+
+#include <rsys/rsys.h>
+#include <rsys/str.h>
+#include <rsys/hash_table.h>
+
+struct scad_geometry;
+
+struct building;
+struct mem_allocator;
+struct logger;
+struct parsed_city_building;
+struct catalog;
+
+/* specific data for constructive mode 1 */
+struct dataset_cmode_1 {
+ size_t inter_floor_count; /* can be 0 */
+ double wall_thickness; /* must be > 0 */
+ double floor_thickness; /* must be > 0 */
+ double inter_floor_thickness; /* must be > 0 */
+ double roof_thickness; /* must be > 0 */
+ double internal_insulation_thickness; /* can be 0 */
+ double external_insulation_thickness; /* can be 0 */
+ double floor_insulation_thickness; /* can be 0 */
+ double roof_insulation_thickness; /* can be 0 */
+ double foundation_depth; /* can be 0 */
+ double crawl_height; /* can be 0 */
+ double attic_height; /* can be 0 */
+ double glass_ratio; /* in [0, 1] */
+};
+
+#define HTABLE_NAME dataset_cmode_1
+#define HTABLE_DATA struct dataset_cmode_1
+#define HTABLE_KEY struct str
+#define HTABLE_KEY_FUNCTOR_INIT str_init
+#define HTABLE_KEY_FUNCTOR_RELEASE str_release
+#define HTABLE_KEY_FUNCTOR_COPY str_copy
+#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release
+#define HTABLE_KEY_FUNCTOR_COPY_AND_CLEAR str_copy_and_clear
+#define HTABLE_KEY_FUNCTOR_EQ str_eq
+#define HTABLE_KEY_FUNCTOR_HASH str_hash
+#include <rsys/hash_table.h>
+
+struct data_cad_cmode_1 {
+ struct scad_geometry* wall;
+ struct scad_geometry* roof;
+ struct scad_geometry* floor;
+ struct scad_geometry* foundation; /* can be NULL */
+ struct scad_geometry* intermediate_floor; /* can be NULL */
+ struct scad_geometry* habitable_cavity;
+ struct scad_geometry* crawlspace_cavity; /* can be NULL */
+ struct scad_geometry* attic_cavity; /* can be NULL */
+ struct scad_geometry* internal_insulation; /* can be NULL */
+ struct scad_geometry* external_insulation; /* can be NULL */
+ struct scad_geometry* floor_insulation; /* can be NULL */
+ struct scad_geometry* roof_insulation; /* can be NULL */
+ struct scad_geometry* glass;
+ struct scad_geometry* fake_ground;/*not exported, used for ground connection*/
+ struct scad_geometry* ground_connection;
+ struct scad_geometry** boundary;
+ struct scad_geometry** connection;
+ size_t n_connection;
+};
+
+res_T
+init_cmode_1
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ struct parsed_city_building* parsed_data,
+ struct catalog* catalog);
+
+res_T
+build_cad_cmode_1
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ void** cad);
+
+res_T
+build_footprint_cmode_1
+ (struct building* building,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ struct scad_geometry** footprint);
+
+res_T
+export_stl_cmode_1
+ (void* cad,
+ struct mem_allocator* allocator,
+ struct logger* logger,
+ const int binary);
+
+res_T
+release_cad_cmode_1
+ (struct mem_allocator* allocator,
+ struct logger* logger,
+ void* cad);
+
+#endif /* CONSTRUCTIVE_MODE_1_H */
diff --git a/src/cg_constructive_mode_1_parsing_schemas.h b/src/cg_constructive_mode_1_parsing_schemas.h
@@ -0,0 +1,132 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * Copyright (C) 2022 CNRS
+ * Copyright (C) 2022 Sorbonne Université
+ * Copyright (C) 2022 Université Paul Sabatier
+ * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef FG_MODE1_PARSING_SCHEMAS__
+#define FG_MODE1_PARSING_SCHEMAS__
+
+#include "cg_building.h"
+#include "cg_city_parsing_schemas.h"
+
+#include <cyaml/cyaml.h>
+
+#include <rsys/rsys.h>
+#include <rsys/str.h>
+
+struct scpr_polygon;
+struct scad_geometry;
+struct mem_allocator;
+
+struct parsed_dataset_cmode_1 {
+ char* name;
+ size_t inter_floor_count; /* can be 0 */
+ double wall_thickness; /* must be > 0 */
+ double floor_thickness; /* must be > 0 */
+ double inter_floor_thickness; /* must be > 0 */
+ double roof_thickness; /* must be > 0 */
+ double internal_insulation_thickness; /* can be 0 */
+ double external_insulation_thickness; /* can be 0 */
+ double floor_insulation_thickness; /* can be 0 */
+ double roof_insulation_thickness; /* can be 0 */
+ double foundation_depth; /* can be 0 */
+ double crawl_height; /* can be 0 */
+ double attic_height; /* can be 0 */
+ double glass_ratio; /* in [0, 1] */
+};
+
+/********************************************************/
+/* Types used for parsing and to define parsing schemas */
+/********************************************************/
+
+struct parsed_catalog_cmode_1 {
+ struct parsed_dataset_cmode_1* datasets;
+ size_t datasets_count;
+};
+
+static const cyaml_schema_field_t dataset_cmode_1_fields_schema[] = {
+ CYAML_FIELD_STRING_PTR("name", CYAML_FLAG_POINTER,
+ struct parsed_dataset_cmode_1, name, 0, CYAML_UNLIMITED),
+ CYAML_FIELD_INT("inter_floor_count", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, inter_floor_count),
+ CYAML_FIELD_FLOAT("wall_thickness", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, wall_thickness),
+ CYAML_FIELD_FLOAT("floor_thickness", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, floor_thickness),
+ CYAML_FIELD_FLOAT("inter_floor_thickness", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, inter_floor_thickness),
+ CYAML_FIELD_FLOAT("roof_thickness", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, roof_thickness),
+ CYAML_FIELD_FLOAT("internal_insulation_thickness", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, internal_insulation_thickness),
+ CYAML_FIELD_FLOAT("external_insulation_thickness", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, external_insulation_thickness),
+ CYAML_FIELD_FLOAT("floor_insulation_thickness", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, floor_insulation_thickness),
+ CYAML_FIELD_FLOAT("roof_insulation_thickness", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, roof_insulation_thickness),
+ CYAML_FIELD_FLOAT("foundation_depth", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, foundation_depth),
+ CYAML_FIELD_FLOAT("crawl_height", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, crawl_height),
+ CYAML_FIELD_FLOAT("attic_height", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, attic_height),
+ CYAML_FIELD_FLOAT("glass_ratio", CYAML_FLAG_DEFAULT,
+ struct parsed_dataset_cmode_1, glass_ratio),
+ CYAML_FIELD_END
+};
+
+static const struct cyaml_schema_value p_dataset_cmode_1_schema = {
+ CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_dataset_cmode_1,
+ dataset_cmode_1_fields_schema),
+};
+
+static const struct cyaml_schema_value dataset_cmode_1_schema = {
+ CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT, struct parsed_dataset_cmode_1,
+ dataset_cmode_1_fields_schema),
+};
+
+static const cyaml_schema_field_t cmode_1_fields_schemas[] = {
+ CYAML_FIELD_IGNORE("contructive_mode_type", CYAML_FLAG_DEFAULT),
+ {
+ .key = "sets",
+ .value = {
+ .type = CYAML_SEQUENCE,
+ .flags = CYAML_FLAG_POINTER,
+ .data_size = sizeof(struct parsed_dataset_cmode_1),
+ .sequence = {
+ .entry = &dataset_cmode_1_schema,
+ .min = 1,
+ .max = CYAML_UNLIMITED,
+ }
+ },
+ .data_offset = offsetof(struct parsed_catalog_cmode_1, datasets),
+ .count_size = sizeof(((struct parsed_catalog_cmode_1*)0)->datasets_count),
+ .count_offset = offsetof(struct parsed_catalog_cmode_1, datasets_count),
+ },
+ CYAML_FIELD_END
+};
+
+/* Top-level schema. The top level value for the constructive mode is a mapping.
+ * Its fields are defined in cmode_1_fields_schemas.
+ */
+static const cyaml_schema_value_t constructive_mode_1_schema = {
+ CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_catalog_cmode_1,
+ cmode_1_fields_schemas),
+};
+
+#endif
diff --git a/src/cg_constructive_modes_parsing_schemas.h b/src/cg_constructive_modes_parsing_schemas.h
@@ -0,0 +1,61 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * Copyright (C) 2022 CNRS
+ * Copyright (C) 2022 Sorbonne Université
+ * Copyright (C) 2022 Université Paul Sabatier
+ * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef FG_CMODES_PARSING_SCHEMAS__
+#define FG_CMODES_PARSING_SCHEMAS__
+
+#include <cyaml/cyaml.h>
+
+/********************************************************/
+/* Types used for parsing and to define parsing schemas */
+/********************************************************/
+
+/* constructive mode type */
+enum parsed_cmode_type {
+ PARSED_CMODE_0,
+ PARSED_CMODE_1,
+ PARSED_CMODE_TYPE_UNDEFINED
+};
+
+/* Mapping from "constructive mode type" strings to enum parsed_cmode_type values for
+ * schema. */
+static const cyaml_strval_t city_building_types_strings[] = {
+ { "Constructive_Mode_0", PARSED_CMODE_0 },
+ { "Constructive_Mode_1", PARSED_CMODE_1 }
+};
+
+struct parsed_cmode {
+ enum parsed_cmode_type cmode_type;
+};
+
+static const cyaml_schema_field_t constructive_mode_fields_schemas[] = {
+ CYAML_FIELD_ENUM("contructive_mode_type",
+ CYAML_FLAG_CASE_INSENSITIVE, struct parsed_cmode, cmode_type,
+ city_building_types_strings, CYAML_ARRAY_LEN(city_building_types_strings)),
+ CYAML_FIELD_IGNORE("sets", CYAML_FLAG_DEFAULT),
+ CYAML_FIELD_END
+};
+
+/* Top-level schema. The top level value for the constructive mode is a mapping */
+static const cyaml_schema_value_t constructive_mode_schema = {
+ CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct parsed_cmode,
+ constructive_mode_fields_schemas),
+};
+
+#endif
diff --git a/src/cg_ground.c b/src/cg_ground.c
@@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "cg_ground.h"
+#include "cg_city.h"
#include "cg.h"
#include <rsys/str.h>
@@ -25,52 +26,41 @@
res_T
ground_build_cad
- (struct ground* ground)
+ (struct city* city,
+ struct ground* ground)
{
res_T res = RES_OK;
double origin[3];
double extent[3];
struct scad_geometry* ground_box = NULL;
struct scad_geometry* bound = NULL;
- struct str name;
- int is_init = 0;
- if (!ground) {
+ if (!city || !ground) {
res = RES_BAD_ARG;
goto error;
}
- origin[0] = ground->extent[0];
- origin[1] = ground->extent[2];
- origin[2] = -ground->depth;
+ origin[0] = city->ground_extent[0];
+ origin[1] = city->ground_extent[2];
+ origin[2] = -city->ground_depth;
- extent[0] = ground->extent[1] - ground->extent[0];
- extent[1] = ground->extent[3] - ground->extent[2];
- extent[2] = ground->depth;
+ extent[0] = city->ground_extent[1] - city->ground_extent[0];
+ extent[1] = city->ground_extent[3] - city->ground_extent[2];
+ extent[2] = city->ground_depth;
if (origin[2] > 0 || extent[0] < 0 || extent[1] < 0 || extent[2] < 0 ) {
res = RES_BAD_ARG;
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->footprints, ground->footprints_count, &ground->boundary));
exit:
- if (is_init) str_release(&name);
- if (bound) scad_geometry_delete(bound);
+ if (bound) SCAD(geometry_delete(bound));
return res;
error:
goto exit;
@@ -90,11 +80,32 @@ error:
}
res_T
-ground_release(struct ground* ground)
+ground_allocate
+ (struct mem_allocator* allocator,
+ const size_t count,
+ struct ground* ground)
{
res_T res = RES_OK;
- if (ground->footprint) free(ground->footprint);
+ ground->footprints_count = count;
+ ground->footprints
+ = MEM_ALLOC(allocator, ground->footprints_count * sizeof(*ground->footprints));
+ if(!ground->footprints) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+exit:
return res;
+error:
+ goto exit;
+}
+
+void
+ground_release
+ (struct mem_allocator* allocator,
+ struct ground* ground)
+{
+ SCAD(geometry_delete(ground->boundary));
+ MEM_RM(allocator, ground->footprints);
}
diff --git a/src/cg_ground.h b/src/cg_ground.h
@@ -22,32 +22,39 @@
#include <rsys/rsys.h>
+struct city;
+
struct scad_scene;
struct scad_geometry;
+struct mem_allocator;
struct ground {
- /* generic building data */
- double extent[4]; /* [xmin, xmax, ymin, ymax */
- double depth;
-
/* cad representation */
- struct scad_scene* scene;
- struct scad_geometry* geometry;
struct scad_geometry* boundary;
- struct scad_geometry** footprint; /* list of building footprint */
- size_t n; /* number of footprint */
+ struct scad_geometry** footprints; /* list of building footprint */
+ size_t footprints_count; /* number of footprint */
};
-#define GROUND_NULL__ {{0,0,0,0}, 0, NULL, NULL, NULL, NULL, 0}
+#define GROUND_NULL__ {NULL, NULL, 0}
static const struct ground GROUND_NULL = GROUND_NULL__;
res_T
-ground_build_cad(struct ground* ground);
+ground_build_cad
+ (struct city* city,
+ struct ground* ground);
res_T
ground_export_stl(const struct ground* ground, const int binary);
res_T
-ground_release(struct ground* ground);
+ground_allocate
+ (struct mem_allocator* allocator,
+ const size_t count,
+ struct ground* ground);
+
+void
+ground_release
+ (struct mem_allocator* allocator,
+ struct ground* ground);
#endif /* GROUND */
diff --git a/src/cg_main.c b/src/cg_main.c
@@ -19,24 +19,65 @@
#include "cg.h"
#include "cg_args.h"
+#include "cg_building.h"
#include "cg_city.h"
+#include "cg_city_parsing.h"
+#include "cg_catalog.h"
+#include "cg_catalog_parsing.h"
+#include "cg_constructive_mode_0_parsing_schemas.h"
+#include "cg_constructive_mode_1_parsing_schemas.h"
+
+#include <cyaml/cyaml.h>
#include <rsys/rsys.h>
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
+#include <star/scad.h>
-char const* model_str [2] = {
- "model0",
- "model1"
-};
-
-static void
+static int
check_memory_allocator(struct mem_allocator* allocator) {
if(MEM_ALLOCATED_SIZE(allocator)) {
char dump[4096];
MEM_DUMP(allocator, dump, sizeof(dump)/sizeof(char));
fprintf(stderr, "%s\n", dump);
- FATAL("Memory leaks.\n");
+ fprintf(stderr, "Memory leaks.\n");
+ return 1;
+ }
+ return 0;
+}
+
+static void cg_log
+ (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);
}
}
@@ -45,11 +86,22 @@ int main
{
int err = EXIT_SUCCESS;
res_T res = RES_OK;
- struct args args;
- struct city city = CITY_NULL;
+ struct args* args = NULL;
+ struct city* city = NULL;
struct logger logger;
struct mem_allocator allocator;
+ struct parsed_city* parsed_city = NULL;
+ struct parsed_catalog* parsed_catalog = NULL;
+ struct catalog* catalog = NULL;
int logger_initialized = 0, allocator_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));
@@ -63,39 +115,67 @@ int main
logger_set_stream(&logger, LOG_ERROR, log_err_fn, NULL);
/* parse command line */
- ERR(parse_args(&logger, argc, argv, &args));
- if(args.print_help) {
+ ERR(parse_args(&allocator, &logger, argc, argv, &args));
+ if(args->print_help) {
short_help();
goto exit;
}
- else if(args.print_version) {
+ else if(args->print_version) {
print_version();
goto exit;
}
/* Deactivate some loggin according to the -V arg */
- if(args.verbose < 1)
+ if(args->verbosity_level < 1)
logger_set_stream(&logger, LOG_ERROR, NULL, NULL);
- if(args.verbose < 2)
+ if(args->verbosity_level < 2)
logger_set_stream(&logger, LOG_WARNING, NULL, NULL);
- if(args.verbose < 3)
+ if(args->verbosity_level < 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 catalog.
+ * No semantic validation is done at this stage */
+ ERR(parse_catalog(&args->catalog_filenames, &allocator, &logger, &config,
+ &parsed_catalog));
+
+ /* Create catalog from parsed data.
+ * Semantic validation is done along the process as well as the emission of
+ * informative logs */
+ ERR(create_catalog(&allocator, &logger, parsed_catalog, &catalog));
+ release_parsed_catalog(&config, parsed_catalog);
+ parsed_catalog = NULL;
+
+ /* Parse city description.
+ * No semantic validation is done at this stage */
+ ERR(parse_city(args->city_filename, &allocator, &logger, &config, &parsed_city));
+
+ /* Create city with parsed data.
+ * Semantic validation is done along the process as well as the emission of
+ * informative logs */
+ ERR(create_city(&allocator, &logger, args, parsed_city, catalog, &city));
+ release_parsed_city(&config, parsed_city);
+ parsed_city = NULL;
+ release_args(args);
+ args = NULL;
+
+ ERR(city_ground_build(city));
+ ERR(city_cad_build(city));
exit:
- city_release(&city);
+ release_args(args);
+ release_city(city);
+ release_catalog(catalog);
+ release_parsed_catalog(&config, parsed_catalog);
+ release_parsed_city(&config, parsed_city);
if(logger_initialized) logger_release(&logger);
if(allocator_initialized) {
- check_memory_allocator(&allocator);
+ if(check_memory_allocator(&allocator)) err = EXIT_FAILURE;
mem_shutdown_proxy_allocator(&allocator);
CHK(mem_allocated_size() == 0);
}
return err;
error:
err = EXIT_FAILURE;
- printf("ERROR\n");
+ printf("City generator failed.\n");
goto exit;
}
diff --git a/src/cg_parsing.c b/src/cg_parsing.c
@@ -1,465 +0,0 @@
-/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
- * Copyright (C) 2022 CNRS
- * Copyright (C) 2022 Sorbonne Université
- * Copyright (C) 2022 Université Paul Sabatier
- * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "cg.h"
-#include "cg_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 model_type get_enum_value(char * val)
-{
- int i=0;
- for (i=0; i<MODEL_COUNT_; ++i)
- if (!strcmp(model_str[i], val))
- return (enum model_type)i;
- return MODEL_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->model = model0;
- break;
- case 1:
- building->model = model1;
- break;
- default:
- res = RES_BAD_ARG;
- goto error;
- }
- }
-
- else if (sscanf(line, "data=%s", value) == 1 ) {
- building->data_name = malloc(sizeof(struct str));
- str_init(NULL, building->data_name);
- str_set(building->data_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->model == MODEL_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_building_params
- (struct logger* logger,
- struct htable_building_params* ht_params)
-{
- res_T res = RES_OK;
- struct data_model0* data0;
- struct data_model1* data1;
- struct building_params* params0;
- (void)logger;
-
- htable_building_params_init(NULL, ht_params);
-
- params0 = malloc(2*sizeof(struct building_params));
- if (!params0) {
- res = RES_MEM_ERR;
- goto error;
- }
-
- data0 = malloc(sizeof(struct data_model0));
- if (!data0) {
- res = RES_MEM_ERR;
- goto error;
- }
- params0[0].model = model0;
- str_init(NULL, ¶ms0[0].name);
- str_set(¶ms0[0].name, "b0");
- data0->wall = 0.2;
- data0->floor = 0.3;
- params0[0].data = malloc(sizeof(struct data_model0));
- params0[0].data = (void*)data0;
- ERR(htable_building_params_set(ht_params, ¶ms0[0].name, ¶ms0[0]));
-
- data1 = malloc(sizeof(struct data_model1));
- if (!data1) {
- res = RES_MEM_ERR;
- goto error;
- }
- params0[1].model = model1;
- str_init(NULL, ¶ms0[1].name);
- str_set(¶ms0[1].name, "b1");
- data1->wall = 0.25;
- data1->floor = 0.35;
- data1->inter_floor = 0.2;
- data1->inter_floor_n = 0;
- data1->roof = 0.3;
- data1->int_insulation = 0.1;
- data1->ext_insulation = 0.2;
- data1->floor_insulation = 0;
- data1->roof_insulation = 0;
- data1->foundation = 2;
- data1->crawl = 0;
- data1->attic = 0;
- data1->glass_ratio = 0.5;
- params0[1].data = malloc(sizeof(struct data_model1));
- params0[1].data = (void*)data1;
- ERR(htable_building_params_set(ht_params, ¶ms0[1].name, ¶ms0[1]));
-
- /* check coherence */
- if (data1->roof_insulation <= 0) data1->attic = 0;
- if (data1->inter_floor <= 0) data1->inter_floor_n = 0;
- if (data1->inter_floor_n <= 0) data1->inter_floor = 0;
-
-
-exit:
- free(params0);
- return res;
-error:
- htable_building_params_release(ht_params);
- goto exit;
-}
-
-res_T
-release_params_building(struct building_params* params)
-{
- res_T res = RES_OK;
- size_t i;
-
- if (!params) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- printf("size params %lu \n", sa_size(params));
-
- for (i=0; i<sa_size(params); ++i) {
- free(params[i].data);
- }
-
- sa_release(params);
-
-exit:
- return res;
-error:
- goto exit;
-}
-
diff --git a/src/cg_parsing.h b/src/cg_parsing.h
@@ -1,48 +0,0 @@
-/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
- * Copyright (C) 2022 CNRS
- * Copyright (C) 2022 Sorbonne Université
- * Copyright (C) 2022 Université Paul Sabatier
- * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef PARSING_H
-#define PARSING_H
-
-#include <ctype.h>
-
-#include <rsys/rsys.h>
-
-struct txtrdr;
-struct logger;
-struct htable_building_params;
-
-struct city;
-struct building_params;
-
-res_T
-parse_city
- (struct logger* logger,
- struct txtrdr* reader,
- struct city* city);
-
-res_T
-parse_building_params
- (struct logger* logger,
- struct htable_building_params* ht_params);
-
-res_T
-release_params_building(struct building_params* params);
-
-#endif /*PARSING_H*/