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 e121adaafbc10b5236569529b7bf2e8021f84d2b
parent f88a075aa1cd720f3b1de42be334f04f013b6f13
Author: Benjamin Piaud <benjamin.piaud@meso-star.com>
Date:   Tue, 18 Oct 2022 15:25:06 +0200

Replace homemade polygon function by star-cpr (based on clipper2)

Diffstat:
Mcmake/CMakeLists.txt | 8++++----
Msrc/cg_building.h | 7++-----
Msrc/cg_building_model0.c | 146++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/cg_ground.h | 2--
Msrc/cg_parsing.c | 32+++++++++++++++++++++++++-------
Dsrc/polygon.c | 232-------------------------------------------------------------------------------
Dsrc/polygon.h | 40----------------------------------------
7 files changed, 131 insertions(+), 336 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -26,6 +26,8 @@ option(NO_TEST "Disable the test" OFF) 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) + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) include(rcmake) @@ -51,8 +53,7 @@ set(CG2_FILES_SRC cg_building_model0.c cg_ground.c cg_args.c - cg_parsing.c - polygon.c) + cg_parsing.c) set(CG2_FILES_INC cg_city.h @@ -60,8 +61,7 @@ set(CG2_FILES_INC cg_building_model0.h cg_ground.h cg_args.h - cg_parsing.h - polygon.h) + cg_parsing.h) set(CG2_FILES_DOC COPYING README.md) diff --git a/src/cg_building.h b/src/cg_building.h @@ -19,8 +19,7 @@ #include <rsys/rsys.h> #include <star/scad.h> - -#include "polygon.h" +#include <star/scpr.h> #ifndef BUILDING_H #define BUILDING_H @@ -39,9 +38,7 @@ struct building { 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 */ + struct scpr_polygon* pg; /* specific data depending model */ void* data; diff --git a/src/cg_building_model0.c b/src/cg_building_model0.c @@ -25,21 +25,52 @@ static res_T +polygon_to_xy + (const struct scpr_polygon* pg, double x[], double y[], size_t* n) +{ + res_T res = RES_OK; + size_t i; + + ERR(scpr_polygon_get_vertices_count(pg, 0, n)); + x = (double*) malloc(*n * sizeof(double)); + y = (double*) malloc(*n * sizeof(double)); + + for (i=0; i<*n; ++i) { + double pos[2]; + ERR(scpr_polygon_get_position(pg, 0, i, pos)); + x[i] = pos[0]; + y[i] = pos[1]; + } + +exit: + return res; +error: + goto exit; +} + +static res_T build_floor_footprint - (const struct pg_polygon* pg, + (const struct scpr_polygon* pg, struct scad_geometry** footprint) { res_T res = RES_OK; + double* x = NULL; + double* y = NULL; + size_t nverts; + ERR(polygon_to_xy(pg, x, y, &nverts)); + ERR(scad_add_polygon (NULL, /* Can be NULL */ - pg->x, - pg->y, + x, + y, 0, - pg->n, /* size of x and y arrays */ + nverts, /* size of x and y arrays */ footprint)); exit: + free(x); + free(y); return res; error: goto exit; @@ -48,7 +79,7 @@ error: static res_T build_floor (const char* prefix, - const struct pg_polygon* pg, + const struct scpr_polygon* pg, struct building* b, struct scad_geometry** floor) { @@ -132,29 +163,37 @@ error: static res_T build_wall_footprint - (const struct pg_polygon* pg, - const struct pg_polygon* pg_int, + (const struct scpr_polygon* pg, + const struct scpr_polygon* pg_int, struct scad_geometry** footprint) { res_T res = RES_OK; /*struct data_cad_model0* data_cad;*/ struct scad_geometry* polygon; struct scad_geometry* polygon_int; + double* x = NULL; + double* y = NULL; + double* x_int = NULL; + double* y_int = NULL; + size_t nverts, nverts_int; + + ERR(polygon_to_xy(pg, x, y, &nverts)); ERR(scad_add_polygon (NULL, - pg->x, - pg->y, + x, + y, 0, - pg->n, + nverts, &polygon)); + ERR(polygon_to_xy(pg_int, x_int, y_int, &nverts_int)); ERR(scad_add_polygon (NULL, - pg_int->x, - pg_int->y, + x_int, + y_int, 0, - pg_int->n, + nverts_int, &polygon_int)); @@ -166,6 +205,10 @@ build_wall_footprint exit: + free(x); + free(y); + free(x_int); + free(y_int); scad_geometry_delete(polygon); scad_geometry_delete(polygon_int); return res; @@ -176,8 +219,8 @@ error: static res_T build_wall (const char* prefix, - const struct pg_polygon* pg, - const struct pg_polygon* pg_int, + const struct scpr_polygon* pg, + const struct scpr_polygon* pg_int, struct building* b, struct scad_geometry** wall) { @@ -220,7 +263,7 @@ error: static res_T build_cavity (const char* prefix, - const struct pg_polygon* pg, + const struct scpr_polygon* pg, const struct building* b, struct scad_geometry** cavity) { @@ -232,6 +275,9 @@ build_cavity char* cavityname = NULL; struct str name; int is_init = 0; + double* x = NULL; + double* y = NULL; + size_t nverts; height = b->height; data = (struct data_model0*)b->data; @@ -245,12 +291,14 @@ build_cavity cavityname = str_get(&name); } + ERR(polygon_to_xy(pg, x, y, &nverts)); + ERR(scad_add_polygon (NULL, /* Can be NULL */ - pg->x, - pg->y, + x, + y, e, - pg->n, /* size of x and y arrays */ + nverts, /* size of x and y arrays */ &polygon)); d[2] = height - e; @@ -260,6 +308,8 @@ build_cavity d, cavity)); exit: + free(x); + free(y); scad_geometry_delete(polygon); if (is_init) str_release(&name); return res; @@ -330,19 +380,24 @@ error: static res_T build_ground -(struct pg_polygon* pg, +(struct scpr_polygon* pg, struct scad_geometry** ground) { res_T res = RES_OK; struct scad_geometry* footprint = NULL; double dir[3] = {0, 0, -1}; + double* x = NULL; + double* y = NULL; + size_t nverts; + + ERR(polygon_to_xy(pg, x, y, &nverts)); ERR(scad_add_polygon (NULL, - pg->x, - pg->y, + x, + y, 0, - pg->n, + nverts, &footprint)); ERR(scad_geometry_extrude @@ -352,6 +407,8 @@ build_ground ground)); exit: + free(x); + free(y); scad_geometry_delete(footprint); return res; error: @@ -449,8 +506,8 @@ build_cad_model0(struct building* building) size_t id = building->id; enum model model = building->model; double height = building->height; - struct pg_polygon pg = building->pg[0]; - struct pg_polygon pg_int, pg_ext; + struct scpr_polygon* pg = building->pg; + struct scpr_polygon* pg_int; struct data_model0* data = (struct data_model0 *)building->data; struct data_cad_model0* data_cad; double e_wall; @@ -477,24 +534,26 @@ build_cad_model0(struct building* building) building->data_cad = (struct data_cad_model0*)data_cad; e_wall = data->wall; - ERR(pg_offset(&pg, e_wall, &pg_int, &pg_ext)); + ERR(scpr_polygon_create(NULL, &pg_int)); + /*ERR(polygon_copy(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)); + 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)); + 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)); + ERR(build_ground(pg, &data_cad->ground)); /* build cavity */ - ERR(build_cavity(str_cget(&prefix), &pg_int, building, &data_cad->cavity)); + ERR(build_cavity(str_cget(&prefix), pg_int, building, &data_cad->cavity)); ERR(scad_scene_partition()); @@ -507,8 +566,7 @@ build_cad_model0(struct building* building) exit: if (is_init) str_release(&prefix); - pg_release(&pg_int); - pg_release(&pg_ext); + scpr_polygon_ref_put(pg_int); return res; error: goto exit; @@ -520,17 +578,19 @@ build_footprint_model0 struct scad_geometry** footprint) { res_T res = RES_OK; - struct pg_polygon pg = building->pg[0]; - struct pg_polygon pg_int, pg_ext; + struct scpr_polygon* pg = building->pg; + struct scpr_polygon* pg_int; struct data_model0* data = (struct data_model0 *)building->data; double e_wall; struct scad_geometry* geom[2]; e_wall = data->wall; - ERR(pg_offset(&pg, e_wall, &pg_int, &pg_ext)); + ERR(scpr_polygon_create(NULL, &pg_int)); + /*ERR(polygon_copy(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(build_wall_footprint(pg, pg_int, &geom[0])); + ERR(build_floor_footprint(pg, &geom[1])); ERR(scad_fragment_geometries (NULL, @@ -541,8 +601,7 @@ build_footprint_model0 exit: scad_geometry_delete(geom[0]); scad_geometry_delete(geom[1]); - pg_release(&pg_int); - pg_release(&pg_ext); + scpr_polygon_ref_put(pg_int); return res; error: goto exit; @@ -587,17 +646,12 @@ 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; - - for (i=0; i<building->polygon_count; ++i) { - pg_release(&building->pg[i]); - } - if (building->pg) free(building->pg); - + scpr_polygon_ref_put(building->pg); + if (data_cad->connection) free(data_cad->connection); if (data) free(data); if (data_cad) free(data_cad); diff --git a/src/cg_ground.h b/src/cg_ground.h @@ -20,8 +20,6 @@ #include <rsys/rsys.h> #include <star/scad.h> -#include "polygon.h" - #ifndef GROUND_H #define GROUND_H diff --git a/src/cg_parsing.c b/src/cg_parsing.c @@ -73,6 +73,23 @@ static enum model get_enum_value(char * val) { return MODEL_COUNT_; } +static void +get_nverts(const size_t icomp, size_t* nverts, void* context) +{ + (void) icomp; (void)context; + *nverts = 4; +} + +static void +get_pos(const size_t icomp, const size_t ivert, double pos[2], void* context) +{ + const double* polygon = context; + + (void)icomp; + pos[0] = polygon[ivert*2 + 0]; + pos[1] = polygon[ivert*2 + 1]; +} + static res_T parse_ground (struct logger* logger, @@ -178,13 +195,14 @@ parse_building if (value) free(value); goto error; } - building->polygon_count = 1; - building->pg = malloc(building->polygon_count * sizeof(struct pg_polygon)); - pg_init(&building->pg[0], 4); - building->pg[0].x[0] = polygon[0]; building->pg[0].y[0] = polygon[1]; - building->pg[0].x[1] = polygon[2]; building->pg[0].y[1] = polygon[3]; - building->pg[0].x[2] = polygon[4]; building->pg[0].y[2] = polygon[5]; - building->pg[0].x[3] = polygon[6]; building->pg[0].y[3] = polygon[7]; + + ERR(scpr_polygon_create(NULL, &building->pg)); + + ERR(scpr_polygon_setup_indexed_vertices( + building->pg, 1, + get_nverts, + get_pos, + polygon)); } if (sscanf(line, "model=%s", value) == 1 ) { diff --git a/src/polygon.c b/src/polygon.c @@ -1,232 +0,0 @@ -/* 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 "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 @@ -1,40 +0,0 @@ -/* 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> - -#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 */