commit 26d5fae0ce66c4f870b0cc409e13e481ad717e0d
Author: Benjamin Piaud <benjamin.piaud@meso-star.com>
Date: Tue, 2 Aug 2022 17:50:51 +0200
First commit
Diffstat:
| A | src/building.c | | | 532 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/building.h | | | 93 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/city.c | | | 180 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/city.h | | | 48 | ++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/ground.c | | | 107 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/ground.h | | | 48 | ++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/main.c | | | 46 | ++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/polygon.c | | | 220 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/polygon.h | | | 25 | +++++++++++++++++++++++++ |
9 files changed, 1299 insertions(+), 0 deletions(-)
diff --git a/src/building.c b/src/building.c
@@ -0,0 +1,532 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * 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 <rsys/str.h>
+
+#include "building.h"
+
+#define ERR(Expr) if((res = (Expr)) != RES_OK) goto error; else (void)0
+
+
+static res_T
+build_slab
+(const struct pg_polygon* pg,
+ struct building* b)
+{
+ res_T res = RES_OK;
+ size_t id;
+ enum model model;
+ double e;
+ struct data_model0* data;
+ struct data_cad_model0* data_cad;
+ struct scad_geometry* footprint;
+ double d[3] = {0, 0, 0};
+ struct str name;
+
+ id = b->id;
+ model = b->model;
+ data = (struct data_model0*)b->data;
+ data_cad = (struct data_cad_model0*)b->data_cad;
+ e = data->slab;
+
+ str_init(NULL, &name);
+ ERR(str_set(&name, "building_"));
+ ERR(str_append_printf(&name, "%lu", (unsigned long)id));
+ ERR(str_append(&name, "_model_"));
+ ERR(str_append_printf(&name, "%lu", (unsigned long)model));
+ ERR(str_append(&name, "_slab"));
+
+ ERR(scad_scene_add_polygon
+ (b->scene,
+ NULL, /* Can be NULL */
+ pg->x,
+ pg->y,
+ 0,
+ pg->n, /* size of x and y arrays */
+ &footprint));
+
+ d[2] = e;
+ ERR(scad_geometry_extrude
+ (footprint,
+ str_cget(&name),
+ d,
+ &data_cad->slab));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_roof(const struct scad_geometry* slab, struct building* b)
+{
+ res_T res = RES_OK;
+ size_t id;
+ enum model model;
+ double height;
+ double e;
+ double d[3] = {0, 0, 0};
+ struct data_model0* data;
+ struct data_cad_model0* data_cad;
+ struct str name;
+
+ id = b->id;
+ model = b->model;
+ height = b->height;
+ data = (struct data_model0*)b->data;
+ data_cad = (struct data_cad_model0*)b->data_cad;
+ e = data->slab;
+
+ str_init(NULL, &name);
+ ERR(str_set(&name, "building_"));
+ ERR(str_append_printf(&name, "%lu", (unsigned long)id));
+ ERR(str_append(&name, "_model_"));
+ ERR(str_append_printf(&name, "%lu", (unsigned long)model));
+ ERR(str_append(&name, "_roof"));
+
+ ERR(scad_geometry_copy(slab, str_cget(&name), &data_cad->roof));
+ d[2] = height - e ;
+ ERR(scad_geometry_translate(data_cad->roof, d));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_wall
+ (const struct pg_polygon* pg,
+ const struct pg_polygon* pg_int,
+ struct building* b)
+{
+ res_T res = RES_OK;
+ size_t id;
+ enum model model;
+ double height;
+ struct data_cad_model0* data_cad;
+ struct scad_geometry* polygon;
+ struct scad_geometry* polygon_int;
+ struct scad_geometry* footprint;
+ double d[3] = {0, 0, 0};
+ struct str name;
+
+ id = b->id;
+ model = b->model;
+ height = b->height;
+ data_cad = (struct data_cad_model0*)b->data_cad;
+
+ str_init(NULL, &name);
+ ERR(str_set(&name, "building_"));
+ ERR(str_append_printf(&name, "%lu", (unsigned long)id));
+ ERR(str_append(&name, "_model_"));
+ ERR(str_append_printf(&name, "%lu", (unsigned long)model));
+ ERR(str_append(&name, "_wall"));
+
+ ERR(scad_scene_add_polygon
+ (b->scene,
+ NULL,
+ pg->x,
+ pg->y,
+ 0,
+ pg->n,
+ &polygon));
+
+ ERR(scad_scene_add_polygon
+ (b->scene,
+ NULL,
+ pg_int->x,
+ pg_int->y,
+ 0,
+ pg_int->n,
+ &polygon_int));
+
+
+ ERR(scad_scene_cut_geometries
+ (b->scene,
+ NULL,
+ polygon,
+ polygon_int,
+ &footprint,
+ 0));
+
+ d[2] = height;
+ ERR(scad_geometry_extrude
+ (footprint,
+ str_cget(&name),
+ d,
+ &data_cad->wall));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_cavity(const struct pg_polygon* pg, struct building* b)
+{
+ res_T res = RES_OK;
+ size_t id;
+ enum model model;
+ double e, height;
+ struct data_model0* data;
+ struct data_cad_model0* data_cad;
+ double d[3] = {0, 0, 0};
+ struct scad_geometry* polygon;
+ struct str name;
+
+ id = b->id;
+ model = b->model;
+ height = b->height;
+ data = (struct data_model0*)b->data;
+ data_cad = (struct data_cad_model0*)b->data_cad;
+ e = data->slab;
+
+ str_init(NULL, &name);
+ ERR(str_set(&name, "building_"));
+ ERR(str_append_printf(&name, "%lu", (unsigned long)id));
+ ERR(str_append(&name, "_model_"));
+ ERR(str_append_printf(&name, "%lu", (unsigned long)model));
+ ERR(str_append(&name, "_cavity"));
+
+ ERR(scad_scene_add_polygon
+ (b->scene,
+ NULL, /* Can be NULL */
+ pg->x,
+ pg->y,
+ e,
+ pg->n, /* size of x and y arrays */
+ &polygon));
+
+ d[2] = height - e;
+ ERR(scad_geometry_extrude
+ (polygon,
+ str_cget(&name),
+ d,
+ &data_cad->cavity));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_connection(struct building* b)
+{
+ res_T res = RES_OK;
+ size_t id;
+ enum model model;
+ struct data_cad_model0* data_cad;
+ struct str slab_name, wall_name, roof_name;
+
+ id = b->id;
+ model = b->model;
+ data_cad = (struct data_cad_model0*)b->data_cad;
+
+ data_cad->connection = malloc(3 * sizeof(struct scad_geometry*));
+ data_cad->n_connection = 3;
+
+ /* cavity/slab connection */
+ str_init(NULL, &slab_name);
+ ERR(str_set(&slab_name, "building_"));
+ ERR(str_append_printf(&slab_name, "%lu", (unsigned long)id));
+ ERR(str_append(&slab_name, "_model_"));
+ ERR(str_append_printf(&slab_name, "%lu", (unsigned long)model));
+ ERR(str_append(&slab_name, "_C_cavity_slab"));
+
+ ERR(scad_scene_geometries_common_boundaries
+ (b->scene,
+ str_cget(&slab_name),
+ data_cad->cavity,
+ data_cad->slab,
+ &data_cad->connection[0],
+ 0));
+
+ /* cavity/wall connection */
+ str_init(NULL, &wall_name);
+ ERR(str_set(&wall_name, "building_"));
+ ERR(str_append_printf(&wall_name, "%lu", (unsigned long)id));
+ ERR(str_append(&wall_name, "_model_"));
+ ERR(str_append_printf(&wall_name, "%lu", (unsigned long)model));
+ ERR(str_append(&wall_name, "_C_cavity_wall"));
+
+ ERR(scad_scene_geometries_common_boundaries
+ (b->scene,
+ str_cget(&wall_name),
+ data_cad->cavity,
+ data_cad->wall,
+ &data_cad->connection[1],
+ 0));
+
+ /* cavity/roof connection */
+ str_init(NULL, &roof_name);
+ ERR(str_set(&roof_name, "building_"));
+ ERR(str_append_printf(&roof_name, "%lu", (unsigned long)id));
+ ERR(str_append(&roof_name, "_model_"));
+ ERR(str_append_printf(&roof_name, "%lu", (unsigned long)model));
+ ERR(str_append(&roof_name, "_C_cavity_roof"));
+
+ ERR(scad_scene_geometries_common_boundaries
+ (b->scene,
+ str_cget(&roof_name),
+ data_cad->cavity,
+ data_cad->roof,
+ &data_cad->connection[2],
+ 0));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+build_boundary(struct building* b)
+{
+ res_T res = RES_OK;
+ size_t id;
+ enum model model;
+ struct data_cad_model0* data_cad;
+ struct scad_geometry** list;
+ struct str name;
+
+ id = b->id;
+ model = b->model;
+ data_cad = (struct data_cad_model0*)b->data_cad;
+
+ list = malloc(4 * sizeof(struct scad_geometry*));
+ list[0] = data_cad->slab;
+ list[1] = data_cad->wall;
+ list[2] = data_cad->roof;
+ list[3] = data_cad->cavity;
+
+ str_init(NULL, &name);
+ ERR(str_set(&name, "building_"));
+ ERR(str_append_printf(&name, "%lu", (unsigned long)id));
+ ERR(str_append(&name, "_model_"));
+ ERR(str_append_printf(&name, "%lu", (unsigned long)model));
+ ERR(str_append(&name, "_boundary"));
+
+ ERR(scad_scene_create_group
+ (b->scene,
+ str_cget(&name),
+ 3,
+ list,
+ 4,
+ &data_cad->boundary));
+
+exit:
+ if (list) free(list);
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+build_cad_model0
+(struct scad_device* dev,
+ struct building* building)
+{
+ res_T res = RES_OK;
+ double height = building->height;
+ struct pg_polygon pg = building->pg[0];
+ struct pg_polygon pg_int, pg_ext;
+ struct data_model0* data = (struct data_model0 *)building->data;
+ struct data_cad_model0* data_cad;
+ double e_wall;
+
+ if (!building || !dev) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if (height <= 0 || data->wall <= 0 || data->slab <= 0) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ data_cad = malloc(sizeof(struct data_cad_model0));
+ building->data_cad = (struct data_cad_model0*)data_cad;
+
+ ERR(scad_scene_create(dev, &building->scene));
+
+ e_wall = data->wall;
+ ERR(pg_offset(&pg, e_wall, &pg_int, &pg_ext));
+
+ /* build slab with pg_int */
+ ERR(build_slab(&pg_int, building));
+
+ /* roof is a translated copy of slab */
+ ERR(build_roof(data_cad->slab, building));
+
+ /* build wall with pg and pg_int */
+ ERR(build_wall(&pg, &pg_int, building));
+
+ /* build cavity */
+ ERR(build_cavity(&pg_int, building));
+
+ ERR(scad_scene_conformal_mesh(building->scene));
+
+ /* build connection cavity/slab */
+ ERR(build_connection(building));
+
+ /* build boundary */
+ ERR(build_boundary(building));
+
+exit:
+ pg_release(&pg_int);
+ pg_release(&pg_ext);
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+build_footprint_model0
+(struct scad_scene* scene,
+ struct building* building,
+ struct scad_geometry** footprint)
+{
+ res_T res = RES_OK;
+ struct pg_polygon pg = building->pg[0];
+ struct pg_polygon pg_int, pg_ext;
+ struct data_model0* data = (struct data_model0 *)building->data;
+ double e_wall;
+ struct scad_geometry* geom[2];
+ struct scad_geometry* polygon;
+ enum model model = building->model;
+ size_t id = building->id;
+ struct str name;
+
+ e_wall = data->wall;
+ ERR(pg_offset(&pg, e_wall, &pg_int, &pg_ext));
+
+ ERR(scad_scene_add_polygon
+ (scene,
+ NULL,
+ pg.x,
+ pg.y,
+ 0,
+ pg.n,
+ &polygon));
+
+ ERR(scad_scene_add_polygon
+ (scene,
+ NULL,
+ pg_int.x,
+ pg_int.y,
+ 0,
+ pg_int.n,
+ &geom[0]));
+
+
+ ERR(scad_scene_cut_geometries
+ (scene,
+ NULL,
+ polygon,
+ geom[0],
+ &geom[1],
+ 0));
+
+ str_init(NULL, &name);
+ ERR(str_set(&name, "building_"));
+ ERR(str_append_printf(&name, "%lu", (unsigned long)id));
+ ERR(str_append(&name, "_model_"));
+ ERR(str_append_printf(&name, "%lu", (unsigned long)model));
+ ERR(str_append(&name, "_footprint"));
+
+ ERR(scad_scene_create_group
+ (scene,
+ str_cget(&name),
+ 3,
+ geom,
+ 2,
+ footprint));
+
+exit:
+ pg_release(&pg_int);
+ pg_release(&pg_ext);
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+export_stl_model0
+(const struct building* building)
+{
+ res_T res = RES_OK;
+ struct data_cad_model0* data_cad = (struct data_cad_model0 *)building->data_cad;
+ size_t i;
+
+ /* slab export */
+ ERR(scad_stl_export(data_cad->slab, NULL, 0));
+
+ /* roof export */
+ ERR(scad_stl_export(data_cad->roof, NULL, 0));
+
+ /* wall export */
+ ERR(scad_stl_export(data_cad->wall, NULL, 0));
+
+ /* cavity export */
+ ERR(scad_stl_export(data_cad->cavity, NULL, 0));
+
+ /* connection export */
+ for (i=0; i<data_cad->n_connection; ++i) {
+ ERR(scad_stl_export(data_cad->connection[i], NULL, 0));
+ }
+
+ /* boundary export */
+ ERR(scad_stl_export(data_cad->boundary, NULL, 0));
+
+ /* footprint export */
+ /*ERR(scad_stl_export(building->footprint, NULL, 0)); */
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+release_model0
+(struct building* building)
+{
+ res_T res = RES_OK;
+ size_t i;
+
+ struct data_model0* data = (struct data_model0 *)building->data;
+ struct data_cad_model0* data_cad = (struct data_cad_model0 *)building->data_cad;
+
+ ERR(scad_scene_ref_put(building->scene));
+
+ for (i=0; i<building->polygon_count; ++i) {
+ pg_release(&building->pg[i]);
+ }
+ if (building->pg) free(building->pg);
+
+ if (data_cad->connection) free(data_cad->connection);
+ if (data) free(data);
+ if (data_cad) free(data_cad);
+
+exit:
+ return res;
+error:
+ goto exit;
+}
diff --git a/src/building.h b/src/building.h
@@ -0,0 +1,93 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * 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 <rsys/rsys.h>
+#include <star/scad.h>
+
+#include "polygon.h"
+
+#ifndef BUILDING_H
+#define BUILDING_H
+
+enum model {
+ MODEL0,
+ MODEL_COUNT_
+};
+
+struct building {
+ /* generic building data */
+ size_t id;
+ enum model model;
+ double height;
+ struct pg_polygon* pg; /* list of polygons. First is external footprint.
+ * Others describe internal holes*/
+ size_t polygon_count; /* number of polygon */
+
+ /* each building has his own scene */
+ struct scad_scene* scene;
+ /* footprint for ground scene */
+ struct scad_geometry* footprint;
+
+ /* specific data depending model */
+ void* data;
+ void* data_cad;
+
+ /* functors depending model */
+ res_T (*build_cad)(struct scad_device* dev, struct building* building);
+ res_T (*build_footprint)
+ (struct scad_scene* scene,
+ struct building* building,
+ struct scad_geometry** footprint);
+ res_T (*export_stl)(const struct building* building);
+ res_T (*release)(struct building* building);
+};
+
+/* specific data for model 0 */
+struct data_model0 {
+ double wall; /* wall thickness */
+ double slab; /* slab thickness */
+};
+
+struct data_cad_model0 {
+ struct scad_geometry* wall;
+ struct scad_geometry* roof;
+ struct scad_geometry* slab;
+ struct scad_geometry* cavity;
+ struct scad_geometry* boundary;
+ struct scad_geometry** connection;
+ size_t n_connection;
+};
+
+res_T
+build_cad_model0
+(struct scad_device* dev,
+ struct building* building);
+
+res_T
+build_footprint_model0
+(struct scad_scene* scene,
+ struct building* building,
+ struct scad_geometry** footprint);
+
+res_T
+export_stl_model0
+(const struct building* building);
+
+res_T
+release_model0
+(struct building* building);
+
+#endif /* BUILDING_H */
diff --git a/src/city.c b/src/city.c
@@ -0,0 +1,180 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * 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 "city.h"
+
+res_T
+city_init(struct city* city)
+{
+ res_T res = RES_OK;
+ struct building* building = NULL;
+ struct data_model0 data0, data1;
+ /*struct ground ground;*/
+
+#define NBUILD 2
+ building = malloc(NBUILD * sizeof(struct building));
+
+ building[0].id = 0;
+ building[0].model = MODEL0;
+ building[0].height = 3;
+ building[0].polygon_count = 1;
+ building[0].pg = malloc(building[0].polygon_count * sizeof(struct pg_polygon));
+ ERR(pg_init(&building[0].pg[0], 4));
+ building[0].pg[0].x[0] = 0; building[0].pg[0].y[0] = 0;
+ building[0].pg[0].x[1] = 0; building[0].pg[0].y[1] = 10;
+ building[0].pg[0].x[2] = 10; building[0].pg[0].y[2] = 10;
+ building[0].pg[0].x[3] = 10; building[0].pg[0].y[3] = 0;
+ building[0].data = malloc(sizeof(struct data_model0));
+ data0.wall = 0.2;
+ data0.slab = 0.3;
+ *(struct data_model0*)(building[0].data) = data0;
+ building[0].build_cad = &build_cad_model0;
+ building[0].export_stl = &export_stl_model0;
+ building[0].release = &release_model0;
+ building[0].build_footprint = &build_footprint_model0;
+
+ building[1].id = 1;
+ building[1].model = MODEL0;
+ building[1].height = 3.5;
+ building[1].polygon_count = 1;
+ building[1].pg = malloc(building[1].polygon_count * sizeof(struct pg_polygon));
+ ERR(pg_init(&building[1].pg[0], 3));
+ building[1].pg[0].x[0] = 20; building[1].pg[0].y[0] = 0;
+ building[1].pg[0].x[1] = 25; building[1].pg[0].y[1] = 10;
+ building[1].pg[0].x[2] = 30; building[1].pg[0].y[2] = 1;
+ building[1].data = malloc(sizeof(struct data_model0));
+ data1.wall = 0.15;
+ data1.slab = 0.1;
+ *(struct data_model0*)(building[1].data) = data1;
+ building[1].build_cad = &build_cad_model0;
+ building[1].export_stl = &export_stl_model0;
+ building[1].release = &release_model0;
+ building[1].build_footprint = &build_footprint_model0;
+
+ city->n = NBUILD;
+ city->building = building;
+
+ city->ground.extent[0] = -100;
+ city->ground.extent[1] = 100;
+ city->ground.extent[2] = -100;
+ city->ground.extent[3] = 100;
+ city->ground.depth = 3;
+
+ ERR(scad_device_create(NULL, NULL, 1, &city->scad_device));
+
+exit:
+ return res;
+
+error:
+ if (building[0].pg) free(building[0].pg);
+ if (building[1].pg) free(building[1].pg);
+ if (building) free(building);
+ goto exit;
+}
+
+res_T
+city_release(struct city* city)
+{
+ res_T res = RES_OK;
+ size_t i,n;
+
+ /* iterate on building */
+ n = city->n;
+ for (i=0; i<n; ++i) {
+ ERR(city->building[i].release(&city->building[i]));
+ }
+
+ ERR(ground_release(&city->ground));
+
+ if (city->scad_device) scad_device_ref_put(city->scad_device);
+ if (city->building) free(city->building);
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+city_cad_build(struct city* city)
+{
+ res_T res = RES_OK;
+ size_t i,n;
+
+ /* iterate on building */
+ n = city->n;
+ for (i=0; i<n; ++i) {
+ /* create building */
+ ERR(city->building[i].build_cad(city->scad_device, &city->building[i]));
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+city_ground_build(struct city* city)
+{
+ res_T res = RES_OK;
+ size_t i,n;
+
+ ERR(scad_scene_create(city->scad_device, &city->ground.scene));
+
+ /* iterate on building */
+ n = city->n;
+ city->ground.n = n;
+ city->ground.footprint = malloc(n * sizeof(struct scad_geometry*));
+
+ for (i=0; i<n; ++i) {
+ /* create building footprint */
+ ERR(city->building[i].build_footprint
+ (city->ground.scene,
+ &city->building[i],
+ &city->ground.footprint[i]));
+ }
+
+ ERR(ground_build_cad(&city->ground));
+
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+
+res_T
+city_export_stl(const struct city* city)
+{
+ res_T res = RES_OK;
+ size_t i,n;
+
+ /* iterate on building */
+ n = city->n;
+ for (i=0; i<n; ++i) {
+ ERR(city->building[i].export_stl(&city->building[i]));
+ }
+
+ /* ground */
+ ERR(ground_export_stl(&city->ground));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
diff --git a/src/city.h b/src/city.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * 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 <star/scad.h>
+
+#include "building.h"
+#include "ground.h"
+
+
+#define ERR(Expr) if((res = (Expr)) != RES_OK) goto error; else (void)0
+
+#ifndef CITY_H
+#define CITY_H
+
+struct city {
+ struct scad_device* scad_device;
+ struct building* building; /* list of buildings */
+ size_t n;
+ struct ground ground;
+};
+
+res_T
+city_init(struct city* city);
+
+res_T
+city_cad_build(struct city* city);
+
+res_T
+city_ground_build(struct city* city);
+
+res_T
+city_export_stl(const struct city* city);
+
+res_T
+city_release(struct city* city);
+#endif /*CITY_H*/
diff --git a/src/ground.c b/src/ground.c
@@ -0,0 +1,107 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * 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 <rsys/str.h>
+
+#include "ground.h"
+
+#define ERR(Expr) if((res = (Expr)) != RES_OK) goto error; else (void)0
+
+
+res_T
+ground_build_cad
+( struct ground* ground)
+{
+ res_T res = RES_OK;
+ size_t i;
+ double origin[3];
+ double extent[3];
+ struct str name;
+
+ if (!ground) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ origin[0] = ground->extent[0];
+ origin[1] = ground->extent[2];
+ origin[2] = -ground->depth;
+
+ extent[0] = ground->extent[1] - ground->extent[0];
+ extent[1] = ground->extent[3] - ground->extent[2];
+ extent[2] = 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);
+ ERR(str_set(&name, "ground"));
+
+ ERR(scad_scene_add_box
+ (ground->scene,
+ str_cget(&name),
+ origin,
+ extent,
+ &ground->geometry));
+
+ for (i=0; i<ground->n; ++i) {
+ ERR(scad_scene_geometries_fragment
+ (ground->scene,
+ NULL,
+ ground->geometry,
+ ground->footprint[i],
+ &ground->geometry,
+ 0));
+ }
+
+ ERR(scad_scene_conformal_mesh(ground->scene));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+
+res_T
+ground_export_stl(const struct ground* ground)
+{
+ res_T res = RES_OK;
+
+ ERR(scad_stl_export(ground->geometry, "ground", 0));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+
+res_T
+ground_release(struct ground* ground)
+{
+ res_T res = RES_OK;
+
+ if (ground->scene) {ERR(scad_scene_ref_get(ground->scene));}
+ if (ground->footprint) free(ground->footprint);
+
+exit:
+ return res;
+error:
+ goto exit;
+}
diff --git a/src/ground.h b/src/ground.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * 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 <rsys/rsys.h>
+#include <star/scad.h>
+
+#include "polygon.h"
+
+#ifndef GROUND_H
+#define GROUND_H
+
+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** footprint; /* list of building footprint */
+ size_t n; /* number of footprint */
+};
+
+
+res_T
+ground_build_cad
+(struct ground* ground);
+
+res_T
+ground_export_stl(const struct ground* ground);
+
+res_T
+ground_release(struct ground* ground);
+
+#endif /* GROUND */
diff --git a/src/main.c b/src/main.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
+ * 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 <rsys/rsys.h>
+#include <star/scad.h>
+
+#include "city.h"
+
+int main
+(int argc, char** argv)
+{
+ int err = EXIT_SUCCESS;
+ res_T res = RES_OK;
+ struct city city;
+
+ (void)argc; (void)argv;
+
+
+ ERR(city_init(&city));
+ ERR(city_cad_build(&city));
+ ERR(city_ground_build(&city));
+ ERR(city_export_stl(&city));
+ ERR(city_release(&city));
+
+exit:
+ return err;
+error:
+ err = EXIT_FAILURE;
+ printf("ERROR\n");
+ goto exit;
+}
diff --git a/src/polygon.c b/src/polygon.c
@@ -0,0 +1,220 @@
+#include "polygon.h"
+#include <rsys/double3.h>
+#include <rsys/double2.h>
+
+
+static
+res_T
+set_polygon(const double* x, const double* y, const size_t n, struct pg_polygon* pg)
+{
+ res_T res = RES_OK;
+ size_t i;
+
+ res = pg_init(pg, n);
+
+ for (i=0; i<n; ++i) {
+ pg->x[i] = x[i];
+ pg->y[i] = y[i];
+ }
+
+ return res;
+}
+
+
+/******************************************************************************/
+
+res_T
+pg_init(struct pg_polygon* pg, const size_t n)
+{
+ res_T res = RES_OK;
+
+ if (!pg || n < 3) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ pg->x = malloc(n * sizeof(double));
+ pg->y = malloc(n * sizeof(double));
+ pg->n = n;
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+pg_release(struct pg_polygon* pg)
+{
+ res_T res = RES_OK;
+
+ if (!pg) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if (pg->x) free(pg->x);
+ if (pg->y) free(pg->y);
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+pg_offset
+(const struct pg_polygon* pg, const double delta,
+ struct pg_polygon* pg_int,
+ struct pg_polygon* pg_ext)
+{
+ res_T res = RES_OK;
+ size_t i, sz;
+ double* x1 = NULL;
+ double* y1 = NULL;
+ double* x2 = NULL;
+ double* y2 = NULL;
+ double len1, len2;
+
+ if (!pg || delta <= 0) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ sz = pg->n;
+
+ x1 = malloc(sz * sizeof(double));
+ y1 = malloc(sz * sizeof(double));
+ x2 = malloc(sz * sizeof(double));
+ y2 = malloc(sz * sizeof(double));
+
+ /*iterate on vertices*/
+ for (i = 0; i < sz; ++i) {
+ size_t i_prev, i_next;
+ double pt[3];
+ double pt_displace1[3];
+ double pt_displace2[3];
+ double pt_prev[3];
+ double pt_next[3];
+ double u[3];
+ double v[3];
+ double d[3];
+ double u_x_d[3];
+ double u_x_v[3];
+ double l;
+
+ i_prev = i - 1;
+ i_next = i + 1;
+ if (i==0) i_prev = sz - 1;
+ if (i==(sz-1)) i_next = 0;
+
+ pt[0] = pg->x[i];
+ pt[1] = pg->y[i];
+ pt[2] = 0;
+
+ pt_prev[0] = pg->x[i_prev];
+ pt_prev[1] = pg->y[i_prev];
+ pt_prev[2] = 0;
+
+ pt_next[0] = pg->x[i_next];
+ pt_next[1] = pg->y[i_next];
+ pt_next[2] = 0;
+
+ /*u is unit vector from pt to pt_prev*/
+ d3_sub(u, pt_prev, pt);
+ d3_normalize(u, u);
+ /*v is unit vector from pt to pt_next*/
+ d3_sub(v, pt_next, pt);
+ d3_normalize(v, v);
+
+ /*displacement direction along the (u,v) bisector*/
+ d3_add(d, u, v);
+ d3_normalize(d, d);
+
+ /*displacement lenght*/
+ d3_cross(u_x_d ,u, d);
+ l = delta/d3_len(u_x_d);
+ /*printf("l %g\n", l);*/
+
+ d3_muld(d, d, l);
+ d3_add(pt_displace1, pt, d);
+
+ d3_muld(d, d, -1);
+ d3_add(pt_displace2, pt, d);
+
+ /* order pt_displace by side*/
+ d3_sub(u, pt_displace1, pt_prev);
+ d3_sub(v, pt, pt_prev);
+ d3_cross(u_x_v ,u, v);
+ if (u_x_v[2] > 0) {
+ x1[i] = pt_displace1[0];
+ y1[i] = pt_displace1[1];
+ x2[i] = pt_displace2[0];
+ y2[i] = pt_displace2[1];
+ } else {
+ x1[i] = pt_displace2[0];
+ y1[i] = pt_displace2[1];
+ x2[i] = pt_displace1[0];
+ y2[i] = pt_displace1[1];
+ }
+ }
+
+
+ len1 = 0;
+ len2 = 0;
+ for (i=0; i<sz; ++i) {
+ double pt1[2];
+ double pt2[2];
+ double pt1_next[2];
+ double pt2_next[2];
+ double u1[2], u2[2];
+ double l1 = 0;
+ double l2 = 0;
+
+ pt1[0] = x1[i];
+ pt1[1] = y1[i];
+ pt2[0] = x2[i];
+ pt2[1] = y2[i];
+
+ if (i == sz-1) {
+ pt1_next[0] = x1[0];
+ pt1_next[1] = y1[0];
+ pt2_next[0] = x2[0];
+ pt2_next[1] = y2[0];
+ } else {
+ pt1_next[0] = x1[i+1];
+ pt1_next[1] = y1[i+1];
+ pt2_next[0] = x2[i+1];
+ pt2_next[1] = y2[i+1];
+ }
+
+ d2_sub(u1, pt1_next, pt1);
+ l1 = d2_len(u1);
+ len1 += l1;
+
+ d2_sub(u2, pt2_next, pt2);
+ l2 = d2_len(u2);
+ len2 += l2;
+ }
+
+ if (len1 < len2) {
+ res = set_polygon(x1, y1, sz, pg_int);
+ res = set_polygon(x2, y2, sz, pg_ext);
+ } else {
+ res = set_polygon(x1, y1, sz, pg_ext);
+ res = set_polygon(x2, y2, sz, pg_int);
+ }
+
+exit:
+ if (x1) free(x1);
+ if (y1) free(y1);
+ if (x2) free(x2);
+ if (y2) free(y2);
+ return res;
+
+error:
+ if (pg_int->x || pg_int->y) pg_release(pg_int);
+ if (pg_ext->x || pg_ext->y) pg_release(pg_ext);
+ goto exit;
+
+}
diff --git a/src/polygon.h b/src/polygon.h
@@ -0,0 +1,25 @@
+#include <rsys/rsys.h>
+
+#ifndef POLYGON_H
+#define POLYGON_H
+
+struct pg_polygon
+{
+ double* x;
+ double* y;
+ size_t n;
+};
+
+res_T
+pg_init(struct pg_polygon* pg, const size_t n);
+
+res_T
+pg_release(struct pg_polygon* pg);
+
+res_T
+pg_offset
+(const struct pg_polygon* pg, const double delta,
+ struct pg_polygon* pg_int,
+ struct pg_polygon* pg_ext);
+
+#endif /* POLYGON_H */