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:
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 */