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:
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, ¶ms0[1].name);
str_set(¶ms0[1].name, "b1");
data->wall = 0.25;