city_generator2

Generated conformal 3D meshes representing a city
git clone git://git.meso-star.fr/city_generator2.git
Log | Files | Refs | README | LICENSE

commit 938659482e1e884e7a4fe1eda9c6ad70834ca9c1
parent 5c1c133d1f31bd37eafdac868a8e7be47536631c
Author: Benjamin Piaud <benjamin.piaud@meso-star.com>
Date:   Wed,  2 Nov 2022 11:38:29 +0100

Copy model0 files to prepare model1 building model

Diffstat:
Mcmake/CMakeLists.txt | 2++
Msrc/cg_building.h | 2++
Asrc/cg_building_model1.c | 565+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cg_building_model1.h | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/cg_city.c | 3+++
Msrc/cg_main.c | 5+++--
Msrc/cg_parsing.c | 2+-
7 files changed, 644 insertions(+), 3 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -51,6 +51,7 @@ set(CG2_FILES_SRC cg_main.c cg_city.c cg_building_model0.c + cg_building_model1.c cg_ground.c cg_args.c cg_parsing.c) @@ -60,6 +61,7 @@ set(CG2_FILES_INC cg_city.h cg_building.h cg_building_model0.h + cg_building_model1.h cg_ground.h cg_args.h cg_parsing.h) diff --git a/src/cg_building.h b/src/cg_building.h @@ -29,6 +29,7 @@ struct scad_geometry; enum model_type { model0, + model1, MODEL_COUNT_ }; @@ -67,6 +68,7 @@ hash_str(const struct str* a) /* the specific building model functors headers must be included here */ #include "cg_building_model0.h" +#include "cg_building_model1.h" struct building { /* generic building data */ diff --git a/src/cg_building_model1.c b/src/cg_building_model1.c @@ -0,0 +1,565 @@ +/* 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_model1* 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_model1*)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_model1* data; + /*struct data_cad_model1* 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_model1*)b->data; + /*data_cad = (struct data_cad_model1*)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_model1* 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_model1* 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_model1*)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_model1* 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_ground +(struct scpr_polygon* pg, + struct scad_geometry** ground) +{ + res_T res = RES_OK; + struct scad_geometry* footprint = NULL; + double dir[3] = {0, 0, -1}; + size_t nverts; + + + ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts)); + ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, &footprint)); + + ERR(scad_geometry_extrude(footprint, NULL, dir, ground)); + +exit: + if(footprint) scad_geometry_delete(footprint); + return res; +error: + goto exit; +} + +static res_T +build_boundary + (const char* prefix, + struct data_cad_model1* 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_geometries_common_boundaries(NULL, list, 4, &cad->ground, 1, + &footprint)); + + ERR(scad_cut_geometries(cname, &boundary, 1, &footprint, 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; +} + +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ + +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; + struct scpr_polygon* pg = building->pg; + struct scpr_polygon* pg_int = NULL; + struct data_model1* data = (struct data_model1 *)building->data; + struct data_cad_model1* 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_model1)); + building->data_cad = (struct data_cad_model1*)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 ground */ + /*This is a 'local' ground. It is required to build boundary condition. */ + /*It is not exported.*/ + ERR(build_ground(pg, &data_cad->ground)); + + /* build cavity */ + ERR(build_cavity(str_cget(&prefix), pg_int, building, &data_cad->cavity)); + + ERR(scad_scene_partition()); + + /* build boundary */ + ERR(build_boundary(str_cget(&prefix), building->data_cad)); + + /* build connection cavity/floor */ + 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_model1 + (struct building* building, + struct scad_geometry** footprint) +{ + res_T res = RES_OK; + struct scpr_polygon* pg = building->pg; + struct scpr_polygon* pg_int = NULL; + struct data_model1* data = (struct data_model1 *)building->data; + double e_wall; + struct scad_geometry* geom[2]; + + e_wall = data->wall; + ERR(scpr_polygon_create_copy(NULL, pg, &pg_int)); + ERR(scpr_offset_polygon(pg_int, -e_wall, SCPR_JOIN_MITER)); + + ERR(build_wall_footprint(pg, pg_int, &geom[0])); + ERR(build_floor_footprint(pg, &geom[1])); + + ERR(scad_fragment_geometries(NULL, &geom[0], 1, &geom[1], 1, footprint)); + +exit: + scad_geometry_delete(geom[0]); + scad_geometry_delete(geom[1]); + if(pg_int) scpr_polygon_ref_put(pg_int); + 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; + + /* 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)); + +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->connection) free(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 @@ -0,0 +1,68 @@ +/* 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 { + double wall; /* wall thickness */ + double floor; /* floor thickness */ +}; + +struct data_cad_model1 { + struct scad_geometry* wall; + struct scad_geometry* roof; + struct scad_geometry* floor; + struct scad_geometry* cavity; + struct scad_geometry* ground; + 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_city.c b/src/cg_city.c @@ -49,6 +49,9 @@ city_init(struct logger* logger, struct city* city, struct args* args) case model0: city->building[i].init = &init_model0; break; + case model1: + city->building[i].init = &init_model1; + break; default: res = RES_BAD_ARG; goto error; diff --git a/src/cg_main.c b/src/cg_main.c @@ -24,8 +24,9 @@ #include <rsys/rsys.h> #include <rsys/logger.h> -char const* model_str [1] = { - "model0" +char const* model_str [2] = { + "model0", + "model1" }; int main diff --git a/src/cg_parsing.c b/src/cg_parsing.c @@ -383,7 +383,7 @@ parse_building_params res = RES_MEM_ERR; goto error; } - params0[1].model = model0; + params0[1].model = model1; str_init(NULL, &params0[1].name); str_set(&params0[1].name, "b1"); data->wall = 0.25;