commit c7576e1b9fcbd86d10927be07f288ce801b14f1f
parent edbef1f867e2f1b75c5c2ff3d24fc4bf64573494
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 8 Sep 2023 17:57:21 +0200
Large debug step.
Change management of removed buildings. Improve output. Change
management of common parts between neighbour buildings.
Diffstat:
21 files changed, 1449 insertions(+), 1126 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -114,7 +114,8 @@ set(CG2_FILES_SRC
cg_construction_mode_0.c
cg_construction_mode_1.c
cg_ground.c
- cg_main.c)
+ cg_main.c
+ cg_types.c)
set(CG2_FILES_INC
cg.h
@@ -132,6 +133,7 @@ set(CG2_FILES_INC
cg_construction_mode_1_parsing_schemas.h
cg_default.h.in
cg_ground.h
+ cg_types.h
cg_version.h.in)
set(CG2_FILES_DOC COPYING README.md)
diff --git a/src/cg.h b/src/cg.h
@@ -29,7 +29,7 @@
* Some constants used in city_generator
*/
-#define CLIPPER_PRECISON 3 /* Input footprints are rounded to mm */
+#define CLIPPER_PRECISON 2 /* Input footprints are rounded to cm */
/* Utility functions */
static INLINE void
@@ -59,6 +59,33 @@ log_err_fn(const char* msg, void* ctx)
fprintf(stderr, "\x1b[31merror:\x1b[0m %s", msg);
}
+static INLINE void
+log_prt_fn_ne(const char* msg, void* ctx)
+{
+ ASSERT(msg);
+ (void)ctx;
+
+ fprintf(stderr, "output: %s", msg);
+}
+
+static INLINE void
+log_warn_fn_ne(const char* msg, void* ctx)
+{
+ ASSERT(msg);
+ (void)ctx;
+
+ fprintf(stderr, "warning: %s", msg);
+}
+
+static INLINE void
+log_err_fn_ne(const char* msg, void* ctx)
+{
+ ASSERT(msg);
+ (void)ctx;
+
+ fprintf(stderr, "error: %s", msg);
+}
+
static INLINE res_T
cyaml_err_to_res_T(const cyaml_err_t err)
{
diff --git a/src/cg_args.c b/src/cg_args.c
@@ -29,6 +29,7 @@
#include <rsys/cstr.h>
#include <getopt.h>
+#include <stdio.h>
void
print_version(void)
@@ -43,7 +44,7 @@ short_help(void)
{
print_version();
printf("\nUsage:\n"
- "city_generator2 -m <FILENAME> { -c <FILENAME> }+ -[%c] [-s] [-V verbosity] [-k] [-f <NAME>] [-F]\n"
+ "city_generator2 -m <FILENAME> { -c <FILENAME> }+ -[%c] [-s] [-V verbosity] [-k] [-f <NAME>] [-F][-E]\n"
"city_generator2 [-h]\n"
"city_generator2 [-v]\n",
CG2_ARGS_CHANGE_BINARY_DEFAULT_OPTION
@@ -65,12 +66,17 @@ short_help(void)
" (default "STR(CG2_ARGS_STL_DEFAULT_STR)").\n"
"-k\n"
" Keep running on errors.\n"
+ "-E\n"
+ " Don't use escape characters in logs.\n"
+ " Use as first option to avoid escape characters in initial log messages.\n"
"-f <NAME>.\n"
" Dump the footprint of the building with the given name.\n"
" Can be used more than once.\n"
- "-F\n"
- " Dump the footprint of any building not generated due to an error.\n"
- " Process the whole file and exit if any error was found unless -k is used.\n"
+ "-F <level>\n"
+ " Dump the footprint of some buildings, depending on level:\n"
+ " - With level 1 dump the footprint of any building not generated due to an error.\n"
+ " - With level 2 dump the footprint of any building.\n"
+ " Process the whole file regardless of errors, and exit if any error was found unless -k is used.\n"
"-s\n"
" Force single threaded execution. By default use as many threads as available.\n"
"-v\n"
@@ -104,7 +110,7 @@ parse_args
int opt;
int info_provided = 0, c_provided = 0, m_provided = 0;
struct args* args;
- char option_list[] = "?c:m:hkFf:vV:";
+ char option_list[] = "?c:m:hkEF:f:svV:";
ASSERT(allocator && logger && argv && out_args);
@@ -168,8 +174,24 @@ parse_args
/* Optional */
+ case 'E':
+ args->no_escape = 1;
+ /* Immediate effect on logs */
+ logger_set_stream(logger, LOG_OUTPUT, log_prt_fn_ne, NULL);
+ logger_set_stream(logger, LOG_WARNING, log_warn_fn_ne, NULL);
+ logger_set_stream(logger, LOG_ERROR, log_err_fn_ne, NULL);
+ break;
+
case 'F':
- args->dump_footprints_on_error = 1;
+ res = cstr_to_int(optarg, &args->dump_footprints_level);
+ if(res != RES_OK
+ || args->dump_footprints_level < 1 || args->dump_footprints_level > 2)
+ {
+ if(res == RES_OK) res = RES_BAD_ARG;
+ logger_print(logger, LOG_ERROR, "Invalid arg for option %c: '%s'.\n",
+ opt, optarg);
+ goto error;
+ }
break;
case 'f':
diff --git a/src/cg_args.h b/src/cg_args.h
@@ -42,7 +42,8 @@ struct args {
int print_version;
int single_thread;
int keep_running_on_errors;
- int dump_footprints_on_error;
+ int dump_footprints_level;
+ int no_escape;
};
res_T
diff --git a/src/cg_building.c b/src/cg_building.c
@@ -69,9 +69,49 @@ adjoining_data_copy_and_release
return RES_OK;
}
+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);
+}
+
+res_T
+build_envelop
+ (struct building* building,
+ struct scad_geometry** envelop)
+{
+ res_T res = RES_OK;
+ size_t nverts = 0;
+ double height = building->height;
+ double d[3] = {0, 0, 0};
+ struct scpr_polygon* pg = building->pg;
+ struct scad_geometry* footprint = NULL;
+ struct str name;
+
+ str_init(building->city->allocator, &name);
+
+ ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
+ ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, &footprint));
+
+ /* wall envelop */
+ d[2] = height;
+ ERR(str_printf(&name, "%s_envelop", str_cget(&building->name)));
+ ERR(scad_geometry_extrude(footprint, str_cget(&name), d, envelop));
+
+exit:
+ str_release(&name);
+ if (footprint) SCAD(geometry_ref_put(footprint));
+ return res;
+error:
+ goto exit;
+}
+
res_T
build_adjoining
(struct building* building,
+ struct darray_geometries* current_cad,
struct darray_adjoining_data* adjoining)
{
res_T res = RES_OK;
@@ -106,7 +146,8 @@ build_adjoining
ASSERT(flags & CLOSE_PROXIMITY); (void)flags;
close_building = *htable_building_iterator_key_get(&it);
adj = darray_adjoining_data_data_get(adjoining) + prev + i;
- ERR(close_building->functors->build_envelop(close_building, &adj->envelop));
+ ERR(build_envelop(close_building, &adj->envelop));
+ ERR(darray_geometries_push_back(current_cad, &adj->envelop));
adj->main_building = building;
adj->adjoining_building = close_building;
ERR(str_append_printf(&msg, " '%s'", str_cget(&close_building->name)));
diff --git a/src/cg_building.h b/src/cg_building.h
@@ -33,6 +33,8 @@ struct building;
struct parsed_city_building;
struct city;
struct darray_adjoining_data;
+struct darray_double;
+struct darray_geometries;
/* An htable to uniquely associate flags to buildings */
#define HTABLE_NAME building
@@ -42,13 +44,16 @@ struct darray_adjoining_data;
/* An enum to encode building events types. */
enum building_event {
- BUILDING_NO_EVENT,
+ BUILDING_NO_EVENT = 0,
BUILDING_WITH_OVERLAPPING = BIT(0),
- BUILDING_WITH_CLOSE_NEIGHBOR = BIT(1),
- BUILDING_OUT_OF_GROUND_EXTENT = BIT(2),
- BUILDING_DUMPED_TO_OBJ = BIT(3),
- BUILDING_CREATED = BIT(4),
- BUILDING_CAD_EXPORTED_TO_STL = BIT(5)
+ BUILDING_OUT_OF_GROUND_EXTENT = BIT(1),
+ BUILDING_INSIDE_BUILDING = BIT(2),
+ BUILDING_REMOVED = BIT(5),
+ BUILDING_WITH_CLOSE_NEIGHBOR = BIT(6),
+ BUILDING_DUMPED_TO_OBJ = BIT(7),
+ BUILDING_CREATED = BIT(11),
+ BUILDING_CAD_EXPORTED_TO_STL = BIT(12),
+ BUILDING_ALREADY_UNREGISTRED = BIT(13)
};
/* A type to store the functors of a construction mode */
@@ -67,13 +72,14 @@ struct construction_mode_functors {
int dump_footprints_on_error,
int keep_running_on_errors,
struct darray_adjoining_data* adjoining_data,
+ struct darray_geometries* current_cad,
void** cad);
res_T (*build_footprint)
(struct building* building,
struct scad_geometry** footprint);
- res_T (*build_envelop)
- (struct building* building,
- struct scad_geometry** envelop);
+ res_T (*save_ground_connection_triangles)
+ (void* cad,
+ struct darray_double* triangles);
res_T (*export_stl)
(void* cad,
const int binary);
@@ -109,6 +115,7 @@ struct building {
/* specific data depending to the construction mode */
void* data;
+ void* data_cad;
};
#define DARRAY_NAME pbuilding
@@ -121,7 +128,7 @@ struct adjoining_data {
/* Only valid for building save */
struct scad_geometry* envelop;
struct scad_geometry* common_geometry;
- int save;
+ int save, really_adjoining;
};
static FINLINE void
adjoining_data_init(struct mem_allocator* alloc, struct adjoining_data* data)
@@ -146,9 +153,18 @@ res_T adjoining_data_copy_and_release
#define DARRAY_FUNCTOR_COPY_AND_RELEASE adjoining_data_copy_and_release
#include <rsys/dynamic_array.h>
+void get_position_pg
+ (const size_t ivert, double pos[2], void* ctx);
+
+res_T
+build_envelop
+ (struct building* building,
+ struct scad_geometry** envelop);
+
res_T
build_adjoining
(struct building* building,
+ struct darray_geometries* current_cad,
struct darray_adjoining_data* adjoining);
#endif /* BUILDING_H */
diff --git a/src/cg_catalog_parsing.c b/src/cg_catalog_parsing.c
@@ -20,14 +20,13 @@
#include "cg.h"
#include "cg_args.h"
#include "cg_catalog_parsing.h"
-#include "cg_construction_mode_0.h"
#include "cg_construction_mode_0_parsing_schemas.h"
#include "cg_construction_mode_1_parsing_schemas.h"
#include "cg_city_parsing_schemas.h"
-#include "cg_building.h"
#include <rsys/logger.h>
#include <rsys/str.h>
+#include <rsys/clock_time.h>
#include <cyaml/cyaml.h>
@@ -60,6 +59,8 @@ parse_catalog
struct parsed_cmode* parsed_cmode = NULL;
const char* filename = NULL;
FILE* f;
+ struct time t0, dt;
+ char buf[128];
(void)logger;
ASSERT(files_array && allocator && logger && out_parsed);
@@ -82,6 +83,7 @@ parse_catalog
const struct cyaml_schema_value* schema;
size_t set_count;
+ time_current(&t0);
/* Parse construction mode only */
filename = darray_names_cdata_get(files_array)[i];
err = cyaml_load_file(filename, config, &construction_mode_schema,
@@ -107,11 +109,14 @@ parse_catalog
break;
default: FATAL("Invalid enum value.\n");
}
+ time_sub(&dt, time_current(&dt), &t0);
+ time_dump(&dt, TIME_SEC | TIME_MSEC, NULL, buf, sizeof(buf));
logger_print(logger, LOG_OUTPUT,
- "Catalog file '%s' parsed: mode '%s', %zu dataset(s) read.\n",
+ "Catalog file '%s' parsed: mode '%s', %zu dataset(s) read. in %s\n",
filename,
city_building_types_strings[items[i].construction_mode].str,
- set_count);
+ set_count,
+ buf);
/* Free tmp struct */
err = cyaml_free(config, &construction_mode_schema, parsed_cmode, 1);
diff --git a/src/cg_city.c b/src/cg_city.c
@@ -29,17 +29,61 @@
#include "cg_args.h"
#include "cg_city_parsing_schemas.h"
+#include <rsys/rsys.h>
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
#include <rsys/double4.h>
#include <rsys/hash_table.h>
#include <rsys/dynamic_array.h>
-
+#include <rsys/clock_time.h>
#include <rsys/str.h>
+
#include <star/scad.h>
#include <star/scpr.h>
#include <string.h>
+
+static int
+non_overlap_is_inside
+ (struct building* b1,
+ struct building* b2)
+{
+ size_t count, i;
+ double pt[2];
+ int situation;
+ ASSERT(b1 && b2);
+ SCPR(polygon_get_components_count(b1->pg, &count));
+ ASSERT(count == 1);
+ SCPR(polygon_get_components_count(b2->pg, &count));
+ ASSERT(count == 1);
+ SCPR(polygon_get_vertices_count(b2->pg, 0, &count));
+ for(i = 0; i < count; i++) {
+ SCPR(polygon_get_position(b2->pg, 0, i, pt));
+ SCPR(point_in_component(b1->pg, 0, pt, &situation));
+ if(situation != 0) break;
+ /* If vertex is shared test the next one */
+ }
+ return (situation != -1);
+}
+
+/* Unregister building from adjoining information of other buildings */
+static void
+unregister_close_building
+ (struct city* city,
+ struct building* building)
+{
+ size_t i, n;
+ ASSERT(city && building);
+ for(i = 0; i < city->allocated_buildings_count; i++) {
+ struct building *b = city->buildings+i;
+ unsigned char *ptr;
+ ptr = htable_building_find(&b->close_buildings, &building);
+ if(!ptr) continue; /* No registered information */
+ n = htable_building_erase(&b->close_buildings, &building);
+ ASSERT(n == 1); (void)n;
+ }
+}
+
void
make_b_pair
(struct b_pair* pair,
@@ -82,24 +126,6 @@ error:
goto exit;
}
-/* Unregister building from adjoining information of other buildings */
-static void
-unregister_close_building
- (struct city* city,
- struct building* building)
-{
- size_t i, n;
- ASSERT(city && building);
- for(i = 0; i < city->allocated_buildings_count; i++) {
- struct building *b = city->buildings+i;
- unsigned char *ptr;
- ptr = htable_building_find(&b->close_buildings, &building);
- if(!ptr) continue; /* No registered information */
- n = htable_building_erase(&b->close_buildings, &building);
- ASSERT(n == 1); (void)n;
- }
-}
-
#define STORE_CLOSE_INFO(Building1, Building2, Proximity) {\
unsigned char *ptr__, tmp__; \
ptr__ = htable_building_find(&(Building1)->close_buildings, &(Building2)); \
@@ -123,18 +149,17 @@ int overlapping_segments
/* Search polygons in the city (slow, but OK) */
for(i = 0; i < ctx->buildings_count; i++) {
struct building* building = ctx->buildings + i;
- enum building_event flag = BUILDING_WITH_CLOSE_NEIGHBOR;
const struct scpr_polygon* pg =
ctx->alternate_polygons ? ctx->alternate_polygons[i] : building->pg;
if(pg == segment1->polygon) {
building1 = building;
name1 = str_cget(&building->name);
- building1->event_flags |= flag;
+ building1->event_flags |= BUILDING_WITH_CLOSE_NEIGHBOR;
}
if(pg == segment2->polygon) {
building2 = building;
name2 = str_cget(&building->name);
- building2->event_flags |= flag;
+ building2->event_flags |= BUILDING_WITH_CLOSE_NEIGHBOR;
}
}
CHK(name1 && name2);
@@ -170,8 +195,8 @@ int simple_intersection
struct callback_ctx* ctx = (struct callback_ctx*)ctx__;
const char *name1 = NULL, *name2 = NULL;
struct building *building1 = NULL, *building2 = NULL;
- enum building_event flag = ctx->search_type == OVERLAPPING_PROXIMITY
- ? BUILDING_WITH_OVERLAPPING : BUILDING_WITH_CLOSE_NEIGHBOR;
+ const enum building_event flag = (ctx->search_type == OVERLAPPING_PROXIMITY)
+ ? BUILDING_WITH_OVERLAPPING | BUILDING_REMOVED : BUILDING_WITH_CLOSE_NEIGHBOR;
struct logger* logger;
struct mem_allocator* allocator;
@@ -190,7 +215,8 @@ int simple_intersection
building1 = building;
name1 = str_cget(&building->name);
building1->event_flags |= flag;
- } else if(pg == segment2->polygon) {
+ }
+ if(pg == segment2->polygon) {
building2 = building;
name2 = str_cget(&building->name);
building2->event_flags |= flag;
@@ -198,33 +224,57 @@ int simple_intersection
}
CHK(name1 && name2);
- switch(ctx->search_type) {
- case OVERLAPPING_PROXIMITY:
- if(ctx->keep_running_on_errors) {
- logger_print(logger, LOG_WARNING,
- "Intersection detected between buildings '%s' and '%s'.\n",
- name1, name2);
- logger_print(logger, LOG_WARNING,
- "Buildings will not be part of the output.\n");
- } else {
- logger_print(logger, LOG_ERROR,
- "Intersection detected between buildings '%s' and '%s'.\n",
+ if(building1 == building2) {
+ switch(ctx->search_type) {
+ case OVERLAPPING_PROXIMITY:
+ if(ctx->keep_running_on_errors) {
+ logger_print(logger, LOG_WARNING,
+ "Self intersection detected for building '%s'.\n", name1);
+ logger_print(logger, LOG_WARNING,
+ "Building will not be part of the output.\n");
+ } else {
+ logger_print(logger, LOG_ERROR,
+ "Self intersection detected for building '%s'.\n", name1);
+ }
+ /* Dump error polygons in OBJ files */
+ if(ctx->dump_footprints_level == 1) {
+ ERR(dump_obj(allocator, building1, NULL));
+ }
+ ERR(darray_pbuilding_push_back(&ctx->city->removed_buildings, &building1));
+ break;
+ case CLOSE_PROXIMITY:
+ break;
+ default: FATAL("Invalid type.");
+ }
+ } else {
+ switch(ctx->search_type) {
+ case OVERLAPPING_PROXIMITY:
+ if(ctx->keep_running_on_errors) {
+ logger_print(logger, LOG_WARNING,
+ "Intersection detected between buildings '%s' and '%s'.\n",
+ name1, name2);
+ logger_print(logger, LOG_WARNING,
+ "Buildings will not be part of the output.\n");
+ } else {
+ logger_print(logger, LOG_ERROR,
+ "Intersection detected between buildings '%s' and '%s'.\n",
+ name1, name2);
+ }
+ /* Dump error polygons in OBJ files */
+ if(ctx->dump_footprints_level == 1) {
+ ERR(dump_obj(allocator, building1, NULL));
+ ERR(dump_obj(allocator, building2, NULL));
+ }
+ ERR(darray_pbuilding_push_back(&ctx->city->removed_buildings, &building1));
+ ERR(darray_pbuilding_push_back(&ctx->city->removed_buildings, &building2));
+ break;
+ case CLOSE_PROXIMITY:
+ logger_print(logger, LOG_OUTPUT,
+ "Buildings '%s' and '%s' are in close proximity.\n",
name1, name2);
- }
- /* Dump the polygons in OBJ files */
- if(ctx->dump_footprints_on_error) {
- ERR(dump_obj(allocator, building1, NULL));
- ERR(dump_obj(allocator, building2, NULL));
- }
- ERR(darray_pbuilding_push_back(&ctx->city->removed_buildings, &building1));
- ERR(darray_pbuilding_push_back(&ctx->city->removed_buildings, &building2));
- break;
- case CLOSE_PROXIMITY:
- logger_print(logger, LOG_OUTPUT,
- "Buildings '%s' and '%s' are in close proximity.\n",
- name1, name2);
- break;
- default: FATAL("Invalid type.");
+ break;
+ default: FATAL("Invalid type.");
+ }
}
/* store other polygon on building information */
@@ -234,7 +284,7 @@ int simple_intersection
/* Return 1 to stop the process unless whe are in proximity search or the user
* asked to go further */
if(ctx->search_type == CLOSE_PROXIMITY
- || ctx->keep_running_on_errors || ctx->dump_footprints_on_error)
+ || ctx->keep_running_on_errors || ctx->dump_footprints_level >= 1)
return 0;
return 1;
error:
@@ -267,9 +317,12 @@ create_city
int error_occured = 0;
struct building* building = NULL;
struct darray_polygons offset_polygons;
+ struct time t0, dt;
+ char buf[128];
ASSERT(logger && allocator && args && parsed_city && catalog && out_city);
+ time_current(&t0);
str_init(allocator, &name);
darray_polygons_init(allocator, &offset_polygons);
htable_names_init(allocator, &names);
@@ -280,7 +333,6 @@ create_city
goto error;
}
- darray_pbuilding_init(allocator, &city->removed_buildings);
city->allocated_buildings_count = parsed_city->city_building_list_count;
city->buildings = MEM_CALLOC(allocator, city->allocated_buildings_count,
sizeof(*city->buildings));
@@ -299,10 +351,12 @@ create_city
city->verbosisty_level = args->verbosity_level;
city->binary_export = args->binary_export;
city->keep_running_on_errors = args->keep_running_on_errors;
- city->dump_footprints_on_error = args->dump_footprints_on_error;
+ city->dump_footprints_level = args->dump_footprints_level;
htable_names_init(allocator, &city->dump_footprint_names);
- htable_common_triangles_init(allocator, &city->common_triangles);
- city->tables_initialized = 1;
+ htable_common_init(allocator, &city->common);
+ darray_pbuilding_init(allocator, &city->removed_buildings);
+ ground_init(allocator, &city->ground);
+ city->array_and_tables_initialized = 1;
/* Some specific building footprints will be dumped (command line request) */
for(i = 0; i < darray_names_size_get(&args->dump_footprint_names); i++) {
char one = 1;
@@ -340,7 +394,8 @@ create_city
}
/* Dump polygon if required */
dump = htable_names_find(&city->dump_footprint_names, &building->name)
- || (tmp_res != RES_OK && city->dump_footprints_on_error);
+ || (tmp_res != RES_OK && city->dump_footprints_level == 1)
+ || city->dump_footprints_level == 2;
if(dump) {
ERR(dump_obj(allocator, building, NULL));
}
@@ -349,6 +404,7 @@ create_city
logger_print(city->logger, LOG_WARNING,
"Building '%s' will not be part of the output.\n",
str_cget(&building->name));
+ ERR(darray_pbuilding_push_back(&city->removed_buildings, &building));
continue;
}
res = tmp_res;
@@ -385,7 +441,7 @@ create_city
ctx.buildings_count = city->initialized_buildings_count;
ctx.intersection_found = &error_occured;
ctx.search_type = OVERLAPPING_PROXIMITY;
- ctx.dump_footprints_on_error = city->dump_footprints_on_error;
+ ctx.dump_footprints_level = city->dump_footprints_level;
ctx.keep_running_on_errors = city->keep_running_on_errors;
callbacks.simple_intersection = simple_intersection;
callbacks.overlapping_segments = overlapping_segments;
@@ -395,9 +451,63 @@ create_city
res = RES_BAD_ARG;
goto error;
}
+ /* Check for polygons in polygons.
+ * As remaining polygons do not overlap, its enough to check a single vertex
+ * to detect a polygon is inside another */
+ for(i = 0; i < city->allocated_buildings_count ; i++) {
+ struct building* b1 = city->buildings + i;
+ size_t j;
+ if(b1->event_flags & BUILDING_REMOVED) continue;
+ for(j = 0; j < i; j++) {
+ struct building* b2 = city->buildings + j;
+ int in = 0;
+ if((b2->event_flags & BUILDING_REMOVED)) continue;
+ /* b1 and b2 and 2 different valid buildings */
+ if(non_overlap_is_inside(b1, b2)) {
+ ASSERT(!non_overlap_is_inside(b2, b1));
+ ERR(darray_pbuilding_push_back(&city->removed_buildings, &b2));
+ b2->event_flags |= BUILDING_INSIDE_BUILDING | BUILDING_REMOVED;
+ if(city->keep_running_on_errors) {
+ logger_print(logger, LOG_WARNING,
+ "Building '%s' is inside building '%s'.\n",
+ str_cget(&b2->name), str_cget(&b1->name));
+ logger_print(logger, LOG_WARNING,
+ "Building '%s' will not be part of the output.\n",
+ str_cget(&b2->name));
+ } else {
+ logger_print(logger, LOG_ERROR,
+ "Building '%s' is inside building '%s'.\n",
+ str_cget(&b2->name), str_cget(&b1->name));
+ }
+ }
+ else if(non_overlap_is_inside(b2, b1)) {
+ ERR(darray_pbuilding_push_back(&city->removed_buildings, &b1));
+ b1->event_flags |= BUILDING_INSIDE_BUILDING | BUILDING_REMOVED;
+ if(city->keep_running_on_errors) {
+ logger_print(logger, LOG_WARNING,
+ "Building '%s' is inside building '%s'.\n",
+ str_cget(&b1->name), str_cget(&b2->name));
+ logger_print(logger, LOG_WARNING,
+ "Building '%s' will not be part of the output.\n",
+ str_cget(&b1->name));
+ } else {
+ logger_print(logger, LOG_ERROR,
+ "Building '%s' is inside building '%s'.\n",
+ str_cget(&b1->name), str_cget(&b2->name));
+ }
+ }
+ if(in && !city->keep_running_on_errors) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ }
+ }
/* Remove removed buildings from proximity information of other buildings */
for(i = 0; i < darray_pbuilding_size_get(&city->removed_buildings); i++) {
struct building* b = darray_pbuilding_data_get(&city->removed_buildings)[i];
+ if(b->event_flags & BUILDING_ALREADY_UNREGISTRED)
+ continue; /* Do not unregister twice! */
+ b->event_flags |= BUILDING_ALREADY_UNREGISTRED;
unregister_close_building(city, b);
}
@@ -415,6 +525,9 @@ exit:
if(close_intersector) SCPR(intersector_ref_put(close_intersector));
htable_names_release(&names);
*out_city = city;
+ time_sub(&dt, time_current(&dt), &t0);
+ time_dump(&dt, TIME_SEC | TIME_MSEC, NULL, buf, sizeof(buf));
+ logger_print(city->logger, LOG_OUTPUT, "Map implantation analyzed in %s.\n", buf);
return res;
error:
if(building) {
@@ -440,17 +553,19 @@ release_city(struct city* city)
}
if(city->scpr) SCPR(device_ref_put(city->scpr));
- if(city->tables_initialized) {
- htable_common_triangles_release(&city->common_triangles);
+ if(city->array_and_tables_initialized) {
+ htable_common_release(&city->common);
htable_names_release(&city->dump_footprint_names);
+ darray_pbuilding_release(&city->removed_buildings);
}
/* iterate on building */
for (i = 0; i < city->allocated_buildings_count; i++) {
struct building* building = city->buildings + i;
- ERR(building->functors->release(building));
+ if(building->functors) {
+ ERR(building->functors->release(building));
+ }
}
- darray_pbuilding_release(&city->removed_buildings);
MEM_RM(city->allocator, city->buildings);
MEM_RM(city->allocator, city);
exit:
@@ -468,47 +583,65 @@ city_cad_build(struct city* city)
size_t i, a, generated_buildings_count = 0;
struct building *building = NULL;
struct darray_adjoining_data adjoining_data;
- struct darray_double trg;
- struct data_cad_cmode_0* cad = NULL;
+ struct darray_double common;
+ void* cad = NULL;
+ struct darray_geometries current_cad;
+ struct time t0, dt;
+ char buf[128];
ASSERT(city);
+ darray_geometries_init(city->allocator, ¤t_cad);
darray_adjoining_data_init(city->allocator, &adjoining_data);
- darray_double_init(city->allocator, &trg);
+ darray_double_init(city->allocator, &common);
/* Initialize star-cad */
ERR(scad_initialize(city->logger, city->allocator, city->verbosisty_level));
scad_initialized = 1;
options.Mesh.MeshSizeFromPoints = 0;
- options.Misc.LogOpenCascadeTagsRefCounting = Scad_log_only_undeleted;
+#ifdef NDEBUG
+ options.Misc.LogRefCounting = Scad_log_dimTags_only_undeleted;
+#else
+ options.Misc.LogRefCounting = Scad_log_dimTags_all | Scad_log_geometry;
+#endif
ERR(scad_set_options(&options));
/* iterate on buildings */
for(i = 0; i < city->allocated_buildings_count; i++) {
building = city->buildings + i;
- if(building->event_flags & BUILDING_WITH_OVERLAPPING
- || !(building->event_flags & BUILDING_CREATED))
- {
- /* No fix for these problems */
- if(city->dump_footprints_on_error) {
+ if(city->dump_footprints_level == 2) {
+ ERR(dump_obj(city->allocator, building, NULL));
+ }
+ if(building->event_flags & BUILDING_REMOVED) {
+ if(city->dump_footprints_level == 1) {
ERR(dump_obj(city->allocator, building, NULL));
}
} else {
- /* create building */
+ /* create building CAD */
struct adjoining_data* adj;
- res = building->functors->build_cad(building, city->dump_footprints_on_error,
- city->keep_running_on_errors, &adjoining_data, (void**)&cad);
+ time_current(&t0);
+ logger_print(city->logger, LOG_OUTPUT,
+ "Start processing building '%s'.\n", str_cget(&building->name));
+ darray_geometries_clear(¤t_cad);
+ res = building->functors->build_cad(building, city->dump_footprints_level,
+ city->keep_running_on_errors, &adjoining_data, ¤t_cad,
+ (void**)&cad);
if(res != RES_OK) {
- if(city->dump_footprints_on_error) {
+ if(city->dump_footprints_level == 1) {
ERR(dump_obj(city->allocator, building, NULL));
}
+ time_sub(&dt, time_current(&dt), &t0);
+ time_dump(&dt, TIME_SEC | TIME_MSEC, NULL, buf, sizeof(buf));
+ logger_print(city->logger, LOG_OUTPUT,
+ "Building '%s': stopped after %s.\n", str_cget(&building->name), buf);
if(city->keep_running_on_errors) {
logger_print(city->logger, LOG_WARNING,
"Building '%s' will not be part of the output.\n",
str_cget(&building->name));
/* Unregister building from adjoining information of other buildings */
unregister_close_building(city, building);
+ darray_adjoining_data_clear(&adjoining_data);
/* FIXME: adjoining buildings may have been built already, taking this
* building into account. There is no simple way to undo this other
* than rebuild them after this building removal. The visible effects
@@ -521,6 +654,10 @@ city_cad_build(struct city* city)
}
ERR(res);
ERR(scad_scene_mesh());
+ /* Keep ground/building's boundary triangles now as the geometry will be
+ * released before ground is built */
+ ERR(building->functors->save_ground_connection_triangles(cad,
+ &city->ground.ground_trg));
/* Keep the mesh of some geometry if planned */
adj = darray_adjoining_data_data_get(&adjoining_data);
for(a = 0; a < darray_adjoining_data_size_get(&adjoining_data); a++) {
@@ -536,16 +673,12 @@ city_cad_build(struct city* city)
* (as geom lifetime is limited to a single iteration) */
continue;
}
- darray_double_clear(&trg);
- /* Warning: one could think that reversing the triangles here would do
- * the job of having them correctly oriented when reused from the
- * other building's point of view. The fact is that this lead to a
- * non-consistent orientation. As a consequence, triangle's orientation
- * has to be set when the mesh is reused, based on the CAD normal. */
- ERR(scad_stl_get_data(adj[a].common_geometry, &trg));
+ darray_double_clear(&common);
+ ERR(scad_stl_get_data(adj[a].common_geometry, &common));
make_b_pair(&pair, building, adj[a].adjoining_building);
- ERR(htable_common_triangles_set(&building->city->common_triangles,
- &pair, &trg));
+ ASSERT(darray_double_size_get(&common) > 0
+ && darray_double_size_get(&common) % 9 == 0);
+ ERR(htable_common_set(&city->common, &pair, &common));
}
ERR(building->functors->export_stl(cad, city->binary_export));
building->event_flags |= BUILDING_CAD_EXPORTED_TO_STL;
@@ -556,20 +689,24 @@ city_cad_build(struct city* city)
ERR(building->functors->release_cad(cad));
cad = NULL; /* Avoid double release */
darray_adjoining_data_clear(&adjoining_data);
+ darray_geometries_clear(¤t_cad);
ERR(scad_scene_clear());
generated_buildings_count++;
+ time_sub(&dt, time_current(&dt), &t0);
+ time_dump(&dt, TIME_SEC | TIME_MSEC, NULL, buf, sizeof(buf));
logger_print(city->logger, LOG_OUTPUT,
- "Building '%s': done.\n", str_cget(&building->name));
+ "Building '%s': done in %s.\n", str_cget(&building->name), buf);
}
}
building = NULL;
city->cad_generated_buildings_count = generated_buildings_count;
exit:
+ darray_geometries_release(¤t_cad);
darray_adjoining_data_release(&adjoining_data);
if(cad) CHK(RES_OK == building->functors->release_cad(cad));
if(scad_initialized) SCAD(finalize());
- darray_double_release(&trg);
+ darray_double_release(&common);
return res;
error:
if(building) {
@@ -585,42 +722,51 @@ city_ground_build(struct city* city)
res_T res = RES_OK;
struct scad_options options = SCAD_DEFAULT_OPTIONS__;
int scad_initialized = 0;
- struct ground ground = GROUND_NULL__;
- size_t i = 0, g = 0;
+ size_t i = 0;
struct building *building = NULL;
+ struct time t0, dt;
+ char buf[128];
- ERR(ground_init(city->allocator, city->logger,
- city->cad_generated_buildings_count, &ground));
-
+ time_current(&t0);
+ logger_print(city->logger, LOG_OUTPUT, "Start processing ground.\n");
/* Initialize star-cad */
ERR(scad_initialize(city->logger, city->allocator, city->verbosisty_level));
scad_initialized = 1;
options.Mesh.MeshSizeFromPoints = 0;
- options.Misc.LogOpenCascadeTagsRefCounting = Scad_log_only_undeleted;
+#ifdef NDEBUG
+ options.Misc.LogRefCounting = Scad_log_dimTags_only_undeleted;
+#else
+ options.Misc.LogRefCounting = Scad_log_dimTags_all | Scad_log_geometry;
+#endif
ERR(scad_set_options(&options));
/* iterate on buildings */
+ ERR(darray_geometries_reserve(&city->ground.footprints,
+ city->allocated_buildings_count));
for(i = 0; i < city->allocated_buildings_count; i++) {
building = city->buildings + i;
- struct scad_geometry** footprint;
+ struct scad_geometry* footprint;
if(!(building->event_flags & BUILDING_CAD_EXPORTED_TO_STL))
continue;
- footprint = ground.footprints + g++;
-
/* create building footprint */
- ERR(building->functors->build_footprint(building, footprint));
+ ERR(building->functors->build_footprint(building, &footprint));
+ ERR(darray_geometries_push_back(&city->ground.footprints, &footprint));
+ ERR(scad_geometry_ref_put(footprint)); /* Ownership transfered */
}
building = NULL;
- ERR(ground_build_cad(city->allocator, city, &ground));
+ ERR(ground_build_cad(city->allocator, city));
ERR(scad_scene_mesh());
- ERR(ground_export_stl(&ground, city->binary_export));
+ ERR(ground_export_stl(&city->ground, city->binary_export));
exit:
- ground_clear(city->allocator, &ground);
+ ground_clear(&city->ground);
if(scad_initialized) SCAD(finalize());
+ time_sub(&dt, time_current(&dt), &t0);
+ time_dump(&dt, TIME_SEC | TIME_MSEC, NULL, buf, sizeof(buf));
+ logger_print(city->logger, LOG_OUTPUT, "Ground done in %s.\n", buf);
return res;
error:
if(building) {
diff --git a/src/cg_city.h b/src/cg_city.h
@@ -21,10 +21,12 @@
#define CITY_H
#include "cg_building.h"
+#include "cg_ground.h"
#include <star/scpr.h>
#include <star/scad.h>
+#include <rsys/rsys.h>
#include <rsys/str.h>
#include <rsys/hash_table.h>
#include <rsys/dynamic_array.h>
@@ -93,9 +95,9 @@ ppoly_copy_and_release
#define HTABLE_KEY_FUNCTOR_HASH str_hash
#include <rsys/hash_table.h>
-/* A table to link a bunch of triangles to a pair of buildings.
- * Used to store the common triangles to ensure conformity despite the fact
- * that buildings are meshed during differents star-cad sessions. */
+/* A table to link a bunch of triangles and their normals to a pair of buildings.
+ * Used to store the common triangles and normals to ensure conformity despite
+ * the fact that buildings are meshed during differents star-cad sessions. */
struct b_pair {
struct building* b1;
struct building* b2;
@@ -110,13 +112,12 @@ make_b_pair
(struct b_pair* pair,
struct building* b1,
struct building* b2);
-#define HTABLE_NAME common_triangles
+#define HTABLE_NAME common
#define HTABLE_DATA struct darray_double
#define HTABLE_DATA_FUNCTOR_INIT darray_double_init
#define HTABLE_DATA_FUNCTOR_RELEASE darray_double_release
#define HTABLE_DATA_FUNCTOR_COPY darray_double_copy
#define HTABLE_DATA_FUNCTOR_COPY_AND_RELEASE darray_double_copy_and_release
-#define HTABLE_DATA_FUNCTOR_COPY_AND_CLEAR darray_double_copy_and_clear
#define HTABLE_KEY struct b_pair
#define HTABLE_KEY_FUNCTOR_EQ b_pair_eq
#include <rsys/hash_table.h>
@@ -125,10 +126,11 @@ struct city {
double lower[2], upper[2]; /* Bbox */
double ground_depth;
struct building* buildings; /* list of buildings */
+ struct ground ground;
size_t cad_generated_buildings_count, allocated_buildings_count,
initialized_buildings_count;
struct htable_names dump_footprint_names;
- struct htable_common_triangles common_triangles;
+ struct htable_common common;
struct darray_pbuilding removed_buildings;
struct mem_allocator* allocator;
struct logger* logger;
@@ -136,8 +138,8 @@ struct city {
int binary_export;
int verbosisty_level;
int keep_running_on_errors;
- int dump_footprints_on_error;
- int tables_initialized;
+ int dump_footprints_level;
+ int array_and_tables_initialized;
};
res_T
@@ -181,7 +183,7 @@ struct callback_ctx {
size_t buildings_count;
int* intersection_found; /* Can be NULL if not to be registered */
enum building_proximity search_type;
- int dump_footprints_on_error;
+ int dump_footprints_level;
int keep_running_on_errors;
};
diff --git a/src/cg_city_parsing.c b/src/cg_city_parsing.c
@@ -25,8 +25,10 @@
#include <star/scpr.h>
+#include <rsys/rsys.h>
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
+#include <rsys/clock_time.h>
#include <cyaml/cyaml.h>
@@ -44,9 +46,12 @@ parse_city
struct parsed_city *parsed = NULL;
FILE* f;
cyaml_err_t err;
+ struct time t0, dt;
+ char buf[128];
ASSERT(allocator && logger && filename && config && out_parsed);
+ time_current(&t0);
err = cyaml_load_file(filename, config, &city_schema, (void**)&parsed, NULL);
ERR(cyaml_err_to_res_T(err));
@@ -55,10 +60,12 @@ parse_city
str_init(allocator, &parsed->filename);
ERR(str_set(&parsed->filename, filename));
+ time_sub(&dt, time_current(&dt), &t0);
+ time_dump(&dt, TIME_SEC | TIME_MSEC, NULL, buf, sizeof(buf));
/* Log outcome */
logger_print(logger, LOG_OUTPUT,
- "City map file '%s' parsed: %u building(s) read.\n",
- filename, ((struct parsed_city*)parsed)->city_building_list_count);
+ "City map file '%s' parsed: %u building(s) read in %s.\n",
+ filename, ((struct parsed_city*)parsed)->city_building_list_count, buf);
exit:
*out_parsed = parsed;
diff --git a/src/cg_construction_mode.c b/src/cg_construction_mode.c
@@ -18,8 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "cg.h"
+#include "cg_types.h"
#include "cg_building.h"
-#include "cg_catalog.h"
#include "cg_city.h"
#include "cg_city_parsing_schemas.h"
#include "cg_construction_mode.h"
@@ -31,20 +31,6 @@
#include <star/scpr.h>
void
-pgeom_release(struct scad_geometry** data) {
- ASSERT(data);
- SCAD(geometry_ref_put(*data));
-}
-
-res_T
-pgeom_copy(struct scad_geometry** dst, struct scad_geometry* const* src) {
- ASSERT(dst && src);
- *dst = *src;
- SCAD(geometry_ref_get(*src));
- return RES_OK;
-}
-
-void
get_nverts(const size_t icomp, size_t* nverts, void* context)
{
struct parsed_city_building* parsed_data = context;
@@ -61,14 +47,6 @@ get_pos(const size_t icomp, const size_t ivert, double pos[2], void* context)
pos[1] = parsed_data->vertice[ivert*2 + 1];
}
-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);
-}
-
res_T
init_building_base
(struct building* building,
@@ -77,7 +55,8 @@ init_building_base
const double lower[2],
const double upper[2])
{
- int inside;
+ int inside, cw;
+ size_t count;
res_T res = RES_OK;
ASSERT(city && building && parsed_data && lower && upper);
@@ -91,16 +70,27 @@ init_building_base
ERR(scpr_polygon_create(city->scpr, &building->pg));
ERR(scpr_polygon_setup_indexed_vertices(building->pg, 1, get_nverts, get_pos,
parsed_data));
+ ERR(scpr_polygon_get_vertices_count(building->pg, 0, &count));
+ if(parsed_data->vertice_count != count) {
+ logger_print(city->logger, LOG_WARNING,
+ "Building '%s' had quasi-identical vertices that have been merged.\n",
+ str_cget(&building->name));
+ }
ERR(scpr_polygon_in_bbox(building->pg, lower, upper, &inside));
if(!inside) {
logger_print(city->logger,
(city->keep_running_on_errors ? LOG_WARNING : LOG_ERROR),
"Building '%s' is out of the ground extent.\n",
str_cget(&building->name));
- building->event_flags |= BUILDING_OUT_OF_GROUND_EXTENT;
+ building->event_flags |= BUILDING_OUT_OF_GROUND_EXTENT | BUILDING_REMOVED;
res = RES_BAD_ARG;
goto error;
}
+ /* Force orientation so that pg's normal is downward */
+ ERR(scpr_polygon_is_component_cw(building->pg, 0, &cw));
+ if(!cw) {
+ ERR(scpr_polygon_reverse_component(building->pg, 0));
+ }
exit:
return res;
diff --git a/src/cg_construction_mode.h b/src/cg_construction_mode.h
@@ -21,6 +21,7 @@
#define Construction_MODE_H__
#include "cg_city_parsing_schemas.h"
+#include "cg_city.h"
#include <rsys/rsys.h>
#include <star/scpr.h>
@@ -36,26 +37,7 @@ struct scad_geometry;
struct darray_double;
#define DARRAY_NAME common_trg
-#define DARRAY_DATA struct darray_double*
-#include <rsys/dynamic_array.h>
-
-void
-pgeom_release(struct scad_geometry** data);
-res_T
-pgeom_copy(struct scad_geometry** dst, struct scad_geometry* const* src);
-static FINLINE res_T
-pgeom_copy_and_release
- (struct scad_geometry** dst, struct scad_geometry* const* src)
-{
- ASSERT(dst && src);
- *dst = *src;
- return RES_OK;
-}
-#define DARRAY_NAME geometries
-#define DARRAY_DATA struct scad_geometry*
-#define DARRAY_FUNCTOR_RELEASE pgeom_release
-#define DARRAY_FUNCTOR_COPY pgeom_copy
-#define DARRAY_FUNCTOR_COPY_AND_RELEASE pgeom_copy_and_release
+#define DARRAY_DATA struct b_pair
#include <rsys/dynamic_array.h>
void
@@ -64,9 +46,6 @@ get_nverts(const size_t icomp, size_t* nverts, void* context);
void
get_pos(const size_t icomp, const size_t ivert, double pos[2], void* context);
-void get_position_pg
- (const size_t ivert, double pos[2], void* ctx);
-
res_T
init_building_base
(struct building* building,
diff --git a/src/cg_construction_mode_0.c b/src/cg_construction_mode_0.c
@@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "cg.h"
+#include "cg_types.h"
#include "cg_building.h"
#include "cg_catalog.h"
#include "cg_city.h"
@@ -32,21 +33,20 @@
#include <star/scad.h>
#include <star/scpr.h>
-#include <star/sstl.h>
-
-#include <limits.h>
static res_T
-build_floor_footprint
+build_footprint
(struct scpr_polygon* pg,
+ const double z,
struct scad_geometry** footprint)
{
res_T res = RES_OK;
- size_t nverts;
+ size_t nverts = 0;
ASSERT(pg && footprint);
+
ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
- ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, footprint));
+ ERR(scad_add_polygon(NULL, get_position_pg, pg, z, nverts, footprint));
exit:
return res;
@@ -59,57 +59,33 @@ build_floor
(const char* prefix,
struct scpr_polygon* pg,
struct building* b,
+ struct darray_geometries* current_cad,
struct scad_geometry** floor)
{
res_T res = RES_OK;
- double e;
struct dataset_cmode_0* data;
struct scad_geometry* footprint = NULL;
double d[3] = {0, 0, 0};
char* floorname = NULL;
struct str name;
- int is_init = 0;
- ASSERT(pg && b && floor);
-
- data = (struct dataset_cmode_0*)b->data;
- e = data->floor_thickness;
+ ASSERT(prefix && pg && b && floor);
str_init(NULL, &name);
- is_init = 1;
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_S_floor"));
- floorname = str_get(&name);
- }
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_S_floor"));
+ floorname = str_get(&name);
- ERR(build_floor_footprint(pg, &footprint));
+ ERR(build_footprint(pg, 0, &footprint));
- d[2] = e;
+ data = (struct dataset_cmode_0*)b->data;
+ d[2] = data->floor_thickness;
ERR(scad_geometry_extrude(footprint, floorname, d, floor));
+ ERR(darray_geometries_push_back(current_cad, floor));
exit:
- SCAD(geometry_ref_put(footprint));
- if (is_init) str_release(&name);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_footprint
- (struct scpr_polygon* pg,
- struct scad_geometry** footprint)
-{
- res_T res = RES_OK;
- size_t nverts = 0;
-
- ASSERT(pg && footprint);
-
- ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
- ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, footprint));
-
-exit:
+ if(footprint) SCAD(geometry_ref_put(footprint));
+ str_release(&name);
return res;
error:
goto exit;
@@ -126,12 +102,11 @@ build_fake_ground
ASSERT(pg && fake_ground);
- ERR(build_floor_footprint(pg, &footprint));
-
- ERR(scad_geometry_extrude(footprint, NULL, d, fake_ground));
+ ERR(build_footprint(pg, 0, &footprint));
+ ERR(scad_geometry_extrude(footprint, "fake_ground", d, fake_ground));
exit:
- SCAD(geometry_ref_put(footprint));
+ if(footprint) SCAD(geometry_ref_put(footprint));
return res;
error:
goto exit;
@@ -140,8 +115,9 @@ error:
static res_T
build_roof
(const char* prefix,
- const struct building* b,
+ struct building* b,
const struct scad_geometry* floor,
+ struct darray_geometries* current_cad,
struct scad_geometry** roof)
{
res_T res = RES_OK;
@@ -151,28 +127,23 @@ build_roof
struct dataset_cmode_0* data;
char* roofname = NULL;
struct str name;
- int is_init = 0;
- ASSERT(b && floor && roof);
+ ASSERT(prefix && b && floor && roof);
str_init(NULL, &name);
- is_init = 1;
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_S_roof"));
- roofname = str_get(&name);
- }
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_S_roof"));
+ roofname = str_get(&name);
height = b->height;
data = (struct dataset_cmode_0*)b->data;
e = data->floor_thickness;
-
- ERR(scad_geometry_copy(floor, roofname, roof));
d[2] = height - e ;
- ERR(scad_geometry_translate(*roof, d));
+ ERR(scad_geometry_translate(floor, d, roofname, roof));
+ ERR(darray_geometries_push_back(current_cad, roof));
exit:
- if (is_init) str_release(&name);
+ str_release(&name);
return res;
error:
goto exit;
@@ -180,23 +151,18 @@ error:
static res_T
build_wall_footprint
- (struct scpr_polygon* pg,
- struct scpr_polygon* pg_int,
- struct scad_geometry** footprint)
+ (struct scpr_polygon* pg,
+ struct scpr_polygon* pg_int,
+ struct scad_geometry** footprint)
{
res_T res = RES_OK;
struct scad_geometry* polygon = NULL;
struct scad_geometry* polygon_int = NULL;
- size_t nverts, nverts_int;
ASSERT(pg && pg_int && footprint);
- 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(build_footprint(pg, 0, &polygon));
+ ERR(build_footprint(pg_int, 0, &polygon_int));
ERR(scad_cut_geometries(NULL, &polygon, 1, &polygon_int, 1, footprint));
exit:
@@ -209,40 +175,35 @@ error:
static res_T
build_wall
- (const char* prefix,
- struct scpr_polygon* pg,
- struct scpr_polygon* pg_int,
- struct building* b,
- struct scad_geometry** wall)
+ (const char* prefix,
+ struct scpr_polygon* pg,
+ struct scpr_polygon* pg_int,
+ struct building* b,
+ struct darray_geometries* current_cad,
+ 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;
-
- ASSERT(pg && pg_int && b && wall);
- height = b->height;
+ ASSERT(prefix && pg && pg_int && b && wall);
str_init(NULL, &name);
- is_init = 1;
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_S_walls"));
- wallname = str_get(&name);
- }
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_S_walls"));
+ wallname = str_get(&name);
ERR(build_wall_footprint(pg, pg_int, &footprint));
- d[2] = height;
+ d[2] = b->height;
ERR(scad_geometry_extrude(footprint, wallname, d, wall));
+ ERR(darray_geometries_push_back(current_cad, wall));
exit:
if(footprint) SCAD(geometry_ref_put(footprint));
- if (is_init) str_release(&name);
+ str_release(&name);
return res;
error:
goto exit;
@@ -252,7 +213,8 @@ static res_T
build_cavity
(const char* prefix,
struct scpr_polygon* pg,
- const struct building* b,
+ struct building* b,
+ struct darray_geometries* current_cad,
struct scad_geometry** cavity)
{
res_T res = RES_OK;
@@ -262,32 +224,27 @@ build_cavity
struct scad_geometry* polygon = NULL;
char* cavityname = NULL;
struct str name;
- int is_init = 0;
- size_t nverts;
- ASSERT(pg && b && cavity);
+ ASSERT(prefix && pg && b && cavity);
height = b->height;
data = (struct dataset_cmode_0*)b->data;
e = data->floor_thickness;
str_init(NULL, &name);
- is_init = 1;
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_F_internal"));
- cavityname = str_get(&name);
- }
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_F_internal"));
+ 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));
+ ERR(build_footprint(pg, e, &polygon));
d[2] = height - 2*e;
ERR(scad_geometry_extrude(polygon, cavityname, d, cavity));
+ ERR(darray_geometries_push_back(current_cad, cavity));
exit:
if(polygon) SCAD(geometry_ref_put(polygon));
- if (is_init) str_release(&name);
+ str_release(&name);
return res;
error:
goto exit;
@@ -304,7 +261,7 @@ build_connection
struct str name;
int is_init = 0;
- ASSERT(allocator && cad);
+ ASSERT(prefix && allocator && cad);
cad->connection = MEM_CALLOC(allocator, 3, sizeof(struct scad_geometry*));
if(!cad->connection) {
@@ -316,37 +273,28 @@ build_connection
/* cavity/floor connection */
str_init(allocator, &name);
is_init = 1;
- if (prefix) {
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_C_internal_floor"));
- cname = str_get(&name);
- }
-
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_C_internal_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_internal_walls"));
- cname = str_get(&name);
- }
-
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_C_internal_walls"));
+ 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_internal_roof"));
- cname = str_get(&name);
- }
-
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_C_internal_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);
+ if(is_init) str_release(&name);
return res;
error:
goto exit;
@@ -365,17 +313,17 @@ build_boundary
struct str name;
int is_init = 0;
struct adjoining_data* adj;
- size_t adjoining_n, i = 0, count = 0;
+ size_t adjoining_n, i = 0, maxc, count = 0;
- ASSERT(allocator && prefix && adjoining_data && data_cad);
+ ASSERT(prefix && allocator && adjoining_data && data_cad);
adjoining_n = darray_adjoining_data_size_get(adjoining_data);
adj = darray_adjoining_data_data_get(adjoining_data);
str_init(allocator, &name);
is_init = 1;
- count = 5 + adjoining_n;
- list = MEM_CALLOC(allocator, count, sizeof(struct scad_geometry*));
+ maxc = 5 + adjoining_n;
+ list = MEM_CALLOC(allocator, maxc, sizeof(struct scad_geometry*));
if(!list) {
res = RES_MEM_ERR;
goto error;
@@ -384,12 +332,19 @@ build_boundary
* of conformity wrt the adjoining building. The reason is that the common
* part that could end to be not conformal is not part of the boundary. As a
* consequence it cannot be part of the result. */
+ count = 5;
list[0] = data_cad->floor;
list[1] = data_cad->roof;
list[2] = data_cad->wall;
list[3] = data_cad->cavity;
list[4] = data_cad->fake_ground;
- for (i=0; i<adjoining_n; i++) list[5+i] = adj[i].envelop;
+ for (i=0; i<adjoining_n; i++) {
+ if(adj[i].really_adjoining) {
+ list[count] = adj[i].envelop;
+ count++;
+ }
+ }
+ ASSERT(maxc >= count);
ERR(str_set(&name, prefix));
ERR(str_append(&name, "_B_walls"));
@@ -405,7 +360,7 @@ build_boundary
exit:
MEM_RM(allocator, list);
- if (is_init) str_release(&name);
+ if(is_init) str_release(&name);
return res;
error:
goto exit;
@@ -437,6 +392,7 @@ building_ground_connection
ERR(scad_geometries_common_boundaries(cname, list, 2, &cad->fake_ground, 1,
connection));
+
exit:
if(is_init) str_release(&name);
return res;
@@ -461,13 +417,13 @@ init_cmode_0
struct str dataset_name;
int name_initialized = 0;
static struct construction_mode_functors functors_0 = {
- &init_cmode_0,
- &release_cmode_0,
- &build_cad_cmode_0,
- &build_footprint_cmode_0,
- &build_envelop_cmode_0,
- &export_stl_cmode_0,
- &release_cad_cmode_0
+ &init_cmode_0,
+ &release_cmode_0,
+ &build_cad_cmode_0,
+ &build_footprint_cmode_0,
+ &save_ground_connection_triangles_0,
+ &export_stl_cmode_0,
+ &release_cad_cmode_0
};
struct mem_allocator* allocator;
struct logger* logger;
@@ -516,9 +472,10 @@ release_cmode_0
res_T
build_cad_cmode_0
(struct building* building,
- int dump_footprints_on_error,
+ int dump_footprints_level,
int keep_running_on_errors,
struct darray_adjoining_data* adjoining_data,
+ struct darray_geometries* current_cad,
void** cad)
{
res_T res = RES_OK;
@@ -528,7 +485,6 @@ build_cad_cmode_0
struct data_cad_cmode_0* data_cad = NULL;
double e_wall;
const char* name;
- struct scad_geometry *tmp = NULL;
size_t adjoining_n = 0;
struct scpr_intersector* overlapping_intersector = NULL;
struct scpr_intersector_check_callbacks callbacks
@@ -538,13 +494,16 @@ build_cad_cmode_0
struct scpr_device* scpr;
struct mem_allocator* allocator;
struct logger* logger = NULL;
- size_t c;
+ size_t i, c, cad_count;
+ struct scad_geometry** cur_cad = NULL;
+ struct scad_geometry** partitioned = NULL;
if (!building || !cad || !adjoining_data) {
res = RES_BAD_ARG;
goto error;
}
+ name = str_cget(&building->name);
scpr = building->city->scpr;
allocator = building->city->allocator;
logger = building->city->logger;
@@ -561,7 +520,8 @@ build_cad_cmode_0
res = RES_MEM_ERR;
goto error;
}
- data_cad->allocator = allocator;
+ building->data_cad = data_cad;
+ data_cad->building = building;
darray_common_trg_init(allocator, &data_cad->common_trg);
darray_geometries_init(allocator, &data_cad->adj_walls);
@@ -572,11 +532,9 @@ build_cad_cmode_0
ERR(scpr_polygon_create_copy(scpr, building->pg, &pg_int));
ERR(scpr_offset_polygon(pg_int, -e_wall, SCPR_JOIN_MITER));
ERR(scpr_polygon_get_components_count(pg_int, &c));
- if(c == 0) {
- /* Building is too small wrt wall thickness */
+ if(c != 1) {
logger_print(logger, (keep_running_on_errors ? LOG_WARNING : LOG_ERROR),
- "Building '%s' is too small with respect to wall thickness.\n",
- str_cget(&building->name));
+ "Building '%s' is too small with respect to wall thickness.\n", name);
error_msg_printed = 1;
res = RES_BAD_ARG;
goto error;
@@ -589,14 +547,13 @@ build_cad_cmode_0
ctx.buildings_count = 1;
ctx.intersection_found = &error_occured;
ctx.search_type = OVERLAPPING_PROXIMITY;
- ctx.dump_footprints_on_error = dump_footprints_on_error;
+ ctx.dump_footprints_level = dump_footprints_level;
ctx.keep_running_on_errors = keep_running_on_errors;
callbacks.simple_intersection = simple_intersection;
ERR(scpr_intersector_check(overlapping_intersector, &callbacks, &ctx));
if(error_occured) {
logger_print(logger, LOG_ERROR,
- "Internal error building CAD for building '%s'.\n",
- str_cget(&building->name));
+ "Internal error building CAD for building '%s'.\n", name);
ERR(darray_pbuilding_push_back(&building->city->removed_buildings, &building));
error_msg_printed = 1;
res = RES_BAD_ARG;
@@ -604,35 +561,46 @@ build_cad_cmode_0
}
/* build floor with pg_int */
- name = str_cget(&building->name);
- ERR(build_floor(name, pg_int, building, &data_cad->floor));
+ ERR(build_floor(name, pg_int, building, current_cad, &data_cad->floor));
/* roof is a translated copy of floor */
- ERR(build_roof(name, building, data_cad->floor, &data_cad->roof));
+ ERR(build_roof(name, building, data_cad->floor, current_cad, &data_cad->roof));
/* build wall with pg and pg_int */
- ERR(build_wall(name, building->pg, pg_int, building, &data_cad->wall));
+ ERR(build_wall(name, building->pg, pg_int, building, current_cad, &data_cad->wall));
/* build cavity */
- ERR(build_cavity(name, pg_int, building, &data_cad->cavity));
+ ERR(build_cavity(name, pg_int, building, current_cad, &data_cad->cavity));
/* build adjoining envelop */
adjoining_n = htable_building_size_get(&building->close_buildings);
if (adjoining_n > 0) {
- ERR(build_adjoining(building, adjoining_data));
+ ERR(build_adjoining(building, current_cad, adjoining_data));
ASSERT(adjoining_n == darray_adjoining_data_size_get(adjoining_data));
}
/* build fake ground */
ERR(build_fake_ground(building->pg, &data_cad->fake_ground));
+ ERR(darray_geometries_push_back(current_cad, &data_cad->fake_ground));
- ERR(scad_scene_partition());
+ /* Partition CAD */
+ cad_count = darray_geometries_size_get(current_cad);
+ partitioned = MEM_CALLOC(allocator, cad_count, sizeof(*partitioned));
+ if(!partitioned) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ cur_cad = darray_geometries_data_get(current_cad);
+ ERR(scad_geometries_partition(cur_cad, cad_count, 0, partitioned));
+ /* Swap original geometry and partitioned geometry in data_cad (was
+ * accumulated into current_cad) */
+ ERR(scad_geometries_swap(cur_cad, partitioned, cad_count, Scad_swap_geometry));
/* After partitioning, manage common parts with other buildings */
if(adjoining_n > 0) {
size_t a;
struct b_pair pair;
- struct darray_double* common_trg;
+ struct darray_double* common;
struct adjoining_data* adjoining
= darray_adjoining_data_data_get(adjoining_data);
for(a = 0; a < adjoining_n; a++) {
@@ -640,8 +608,8 @@ build_cad_cmode_0
ERR(scad_geometries_common_boundaries(NULL, &data_cad->wall, 1,
&adj->envelop, 1, &adj->common_geometry));
ERR(scad_geometry_get_count(adj->common_geometry, &c));
- if(c == 0) {
- /* Not really adjoining */
+ adj->really_adjoining = (c != 0);
+ if(!adj->really_adjoining) {
logger_print(logger, LOG_OUTPUT,
"building '%s': neighbor '%s' not really adjoining.\n",
str_cget(&building->name),
@@ -649,20 +617,15 @@ build_cad_cmode_0
continue;
}
make_b_pair(&pair, building, adj->adjoining_building);
- common_trg
- = htable_common_triangles_find(&building->city->common_triangles, &pair);
- if(common_trg) {
- /* The common geometry has already been processed when creating a
- * previous building, and the very same mesh must be used for this one.
- * Keep track of the geometry to replace and the mesh to output instead */
- ERR(darray_geometries_push_back(&data_cad->adj_walls,
- &adj->common_geometry));
- ERR(darray_common_trg_push_back(&data_cad->common_trg, &common_trg));
- } else {
+ /* Keep track of the geometry to replace and the mesh to output instead */
+ ERR(darray_geometries_push_back(&data_cad->adj_walls, &adj->common_geometry));
+ ERR(darray_common_trg_push_back(&data_cad->common_trg, &pair));
+ common = htable_common_find(&building->city->common, &pair);
+ if(!common) {
/* The mesh doesn't exist yet and won't be created until a further step.
* We need to store the geometry id so that the mesh can be stored when
* created. */
- adjoining[a].save = 1;
+ adj->save = 1;
}
}
}
@@ -678,7 +641,12 @@ build_cad_cmode_0
ERR(build_connection(name, allocator, data_cad));
exit:
- if(tmp) SCAD(geometry_ref_put(tmp));
+ if(partitioned) {
+ for(i = 0; i < cad_count; i++) {
+ if(partitioned[i]) SCAD(geometry_ref_put(partitioned[i]));
+ }
+ MEM_RM(allocator, partitioned);
+ }
if(pg_int) SCPR(polygon_ref_put(pg_int));
if(overlapping_intersector) SCPR(intersector_ref_put(overlapping_intersector));
if(cad) *(struct data_cad_cmode_0**)cad = data_cad;
@@ -706,7 +674,7 @@ build_footprint_cmode_0
goto error;
}
- ERR(build_footprint(building->pg, footprint));
+ ERR(build_footprint(building->pg, 0, footprint));
exit:
return res;
@@ -714,26 +682,21 @@ error:
goto exit;
}
-res_T
-build_envelop_cmode_0
- (struct building* building,
- struct scad_geometry** envelop)
+res_T save_ground_connection_triangles_0
+ (void* cad,
+ struct darray_double* triangles)
{
res_T res = RES_OK;
- size_t nverts = 0;
- double height = building->height;
- double d[3] = {0, 0, 0};
- struct scpr_polygon* pg = building->pg;
- struct scad_geometry* footprint = NULL;
+ struct data_cad_cmode_0* data_cad = cad;
- ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
- ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, &footprint));
+ if(!cad || !triangles) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
- d[2] = height;
- ERR(scad_geometry_extrude(footprint, NULL, d, envelop));
+ ERR(scad_stl_get_data(data_cad->ground_connection, triangles));
exit:
- if (footprint) SCAD(geometry_ref_put(footprint));
return res;
error:
goto exit;
@@ -746,87 +709,64 @@ export_stl_cmode_0
{
res_T res = RES_OK;
struct data_cad_cmode_0* data_cad = (struct data_cad_cmode_0*)cad;
- size_t i, j, common_n = 0, coord_count = 0;
+ size_t i, j, coord_count = 0;
struct darray_double trg;
struct str name;
int initialized = 0;
- struct scad_geometry** list = NULL;
+ struct mem_allocator* allocator = NULL;
if(!cad) {
res = RES_BAD_ARG;
goto error;
}
+ allocator = data_cad->building->city->allocator;
+
/* floor export */
- ERR(scad_stl_export(data_cad->floor, NULL, binary));
+ ERR(scad_stl_export(data_cad->floor, NULL, Scad_force_normals_outward, binary));
/* roof export */
- ERR(scad_stl_export(data_cad->roof, NULL, binary));
+ ERR(scad_stl_export(data_cad->roof, NULL, Scad_force_normals_outward, binary));
/* wall export */
if(darray_geometries_size_get(&data_cad->adj_walls) == 0) {
- ERR(scad_stl_export(data_cad->wall, NULL, binary));
+ ERR(scad_stl_export(data_cad->wall, NULL, Scad_force_normals_outward, binary));
} else {
/* There is some adjoining building(s) to manage */
- struct darray_double **common
- = darray_common_trg_data_get(&data_cad->common_trg);
size_t common_count = darray_common_trg_size_get(&data_cad->common_trg);
const char* tmp;
- darray_double_init(data_cad->allocator, &trg);
- str_init(data_cad->allocator, &name);
+ darray_double_init(allocator, &trg);
+ str_init(allocator, &name);
initialized = 1;
/* Get the triangles that are not common with adjoining buildings */
ERR(scad_stl_get_data_partial(data_cad->wall,
darray_geometries_data_get(&data_cad->adj_walls),
- darray_geometries_size_get(&data_cad->adj_walls),
- &trg));
+ darray_geometries_size_get(&data_cad->adj_walls), &trg));
coord_count = darray_double_size_get(&trg);
/* Add the triangles from adjoining buildings */
for(i = 0; i < common_count; i++) {
size_t sz;
- int found = 0;
- const double* t9 = darray_double_cdata_get(common[i]);
+ struct b_pair* pair = darray_common_trg_data_get(&data_cad->common_trg)+ i;
+ const double *t9;
double* tgt;
- struct scad_geometry* common_g
- = darray_geometries_data_get(&data_cad->adj_walls)[i];
- double n[3], e1[3], e2[3], reverse;
- /* Determine the normal orientation for common triangles */
- d3_sub(e1, t9 + 3, t9);
- d3_sub(e2, t9 + 6, t9);
- d3_cross(n, e1, e2);
- ERR(scad_geometry_explode(common_g, NULL, &list, &common_n));
- for(j = 0; j < common_n; j++) {
- double center[3], N[3];
- struct scad_geometry* surface;
- ERR(scad_geometry_get_centerofmass(list[j], center));
- ERR(scad_geometry_normal(list[j], center, N, NULL, &surface));
- ERR(scad_geometry_ref_put(surface));
- reverse = d3_dot(N, n);
- if(fabs(reverse) > 0.99*d3_len(n)*d3_len(N)) {
- found = 1;
- break;
- }
- }
- for(j = 0; j < common_n; j++) {
- ERR(scad_geometry_ref_put(list[j]));
- }
- MEM_RM(data_cad->allocator, list);
- common_n = 0; list = NULL; /* Avoid double free */
- if(!found) {
+ struct city* city = data_cad->building->city;
+ struct darray_double* common = NULL;
+ /* Get triangles */
+ common = htable_common_find(&city->common, pair);
+ if(!common) {
res = RES_BAD_ARG;
goto error;
}
+ t9 = darray_double_cdata_get(common);
/* Add common triangles */
- sz = darray_double_size_get(common[i]);
+ sz = darray_double_size_get(common);
ASSERT(sz % 9 == 0);
ASSERT(coord_count == darray_double_size_get(&trg));
ERR(darray_double_resize(&trg, coord_count + sz));
tgt = darray_double_data_get(&trg);
- for(j = 0; j < sz; j += 9) {
- d3_set(tgt + coord_count + j+0, t9 + j+0);
- d3_set(tgt + coord_count + j+3, t9 + j+(reverse>0 ? 3 : 6));
- d3_set(tgt + coord_count + j+6, t9 + j+(reverse>0 ? 6 : 3));
+ for(j = 0; j < sz; j++) {
+ tgt[coord_count + j] = t9[j];
}
coord_count += sz;
ASSERT(coord_count % 9 == 0);
@@ -834,30 +774,30 @@ export_stl_cmode_0
ERR(scad_geometry_get_name(data_cad->wall, &tmp));
ERR(str_set(&name, tmp));
ERR(str_append(&name, ".stl"));
- ERR(scad_stl_data_write(&trg, str_cget(&name), binary));
+ ERR(scad_stl_data_write(&trg, str_cget(&name), Scad_force_normals_outward,
+ binary));
}
/* cavity export */
- ERR(scad_stl_export(data_cad->cavity, NULL, binary));
+ ERR(scad_stl_export(data_cad->cavity, NULL, Scad_force_normals_outward, binary));
/* connection export */
for (i = 0; i < data_cad->n_connection; i++) {
- ERR(scad_stl_export(data_cad->connection[i], NULL, binary));
+ ERR(scad_stl_export(data_cad->connection[i], NULL,
+ Scad_keep_normals_unchanged, binary));
}
/* boundary export */
- ERR(scad_stl_export(data_cad->boundary_wall, NULL, binary));
- ERR(scad_stl_export(data_cad->boundary_roof, NULL, binary));
+ ERR(scad_stl_export(data_cad->boundary_wall, NULL, Scad_keep_normals_unchanged,
+ binary));
+ ERR(scad_stl_export(data_cad->boundary_roof, NULL, Scad_keep_normals_unchanged,
+ binary));
/* footprint export */
- ERR(scad_geometry_reverse(data_cad->ground_connection));
- ERR(scad_stl_export(data_cad->ground_connection, NULL, binary));
+ ERR(scad_stl_export(data_cad->ground_connection, NULL,
+ Scad_keep_normals_unchanged, binary));
exit:
- for(j = 0; j < common_n; j++) {
- if(list[j]) SCAD(geometry_ref_put(list[j]));
- }
- MEM_RM(data_cad->allocator, list);
if(initialized) {
darray_double_release(&trg);
str_release(&name);
@@ -881,7 +821,7 @@ release_cad_cmode_0
goto error;
}
- allocator = data_cad->allocator;
+ allocator = data_cad->building->city->allocator;
darray_common_trg_release(&data_cad->common_trg);
darray_geometries_release(&data_cad->adj_walls);
diff --git a/src/cg_construction_mode_0.h b/src/cg_construction_mode_0.h
@@ -54,9 +54,9 @@ struct dataset_cmode_0 {
#include <rsys/hash_table.h>
struct data_cad_cmode_0 {
- struct mem_allocator* allocator;
struct darray_common_trg common_trg;
struct darray_geometries adj_walls;
+ struct building* building;
struct scad_geometry* wall;
struct scad_geometry* roof;
struct scad_geometry* floor;
@@ -88,6 +88,7 @@ build_cad_cmode_0
int dump_footprints_on_error,
int keep_running_on_errors,
struct darray_adjoining_data* adjoining_data,
+ struct darray_geometries* current_cad,
void** cad);
res_T
@@ -96,9 +97,13 @@ build_footprint_cmode_0
struct scad_geometry** footprint);
res_T
-build_envelop_cmode_0
+get_ground_connection_0
(struct building* building,
- struct scad_geometry** envelop);
+ struct scad_geometry** connection);
+
+res_T save_ground_connection_triangles_0
+ (void* cad,
+ struct darray_double* triangles);
res_T
export_stl_cmode_0
diff --git a/src/cg_construction_mode_1.c b/src/cg_construction_mode_1.c
@@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "cg.h"
+#include "cg_types.h"
#include "cg_default.h"
#include "cg_building.h"
#include "cg_catalog.h"
@@ -26,25 +27,93 @@
#include "cg_construction_mode.h"
#include "cg_construction_mode_1.h"
+#include <rsys/rsys.h>
#include <rsys/str.h>
#include <rsys/logger.h>
#include <rsys/hash_table.h>
#include <rsys/double3.h>
+
#include <star/scad.h>
#include <star/scpr.h>
+STATIC_ASSERT((CG2_CLOSE_NEIGHBOR_DISTANCE > 0.1), Close_neighbor_distance_cannot_be_less_than_10cm);
+
+static res_T
+build_footprint
+ (struct scpr_polygon* pg,
+ const double z,
+ struct scad_geometry** footprint)
+{
+ res_T res = RES_OK;
+ size_t nverts = 0;
+
+ ASSERT(pg && footprint);
+
+ ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
+ ERR(scad_add_polygon(NULL, get_position_pg, pg, z, nverts, footprint));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+/* Return a polygon with the given offset.
+ * Get a reference: do put a reference on the result! */
+static res_T
+do_offset
+ (struct building* building,
+ struct htable_polygons* polygons,
+ struct scpr_intersector* overlapping_intersector,
+ int *error_msg_printed,
+ const double offset,
+ struct scpr_polygon** p_out)
+{
+ res_T res = RES_OK;
+ struct scpr_polygon** ptr_p;
+
+ ASSERT(building && polygons && overlapping_intersector
+ && error_msg_printed && p_out);
+
+ ptr_p = htable_polygons_find(polygons, &offset);
+ if(ptr_p) {
+ *p_out = *ptr_p;
+ ERR(scpr_polygon_ref_get(*p_out));
+ } else {
+ size_t c;
+ ERR(scpr_polygon_create_copy(building->city->scpr, building->pg, p_out));
+ ERR(scpr_offset_polygon(*p_out, offset, SCPR_JOIN_MITER));
+ ERR(scpr_polygon_get_components_count(*p_out, &c));
+ if(c != 1) {
+ ASSERT(offset < 0);
+ logger_print(building->city->logger,
+ (building->city->keep_running_on_errors ? LOG_WARNING : LOG_ERROR),
+ "Building '%s' is too small with respect to wall thickness.\n",
+ str_cget(&building->name));
+ *error_msg_printed = 1;
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ ERR(scpr_intersector_register_polygon(overlapping_intersector, *p_out));
+ ERR(htable_polygons_set(polygons, &offset, p_out));
+ }
+
+exit:
+ return res;
+error:
+ if(!ptr_p) SCPR(polygon_ref_put(*p_out)); /* Created here */
+ *p_out = NULL;
+ goto exit;
+}
+
static res_T
build_floor
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- struct logger* logger,
+ (struct building* building,
int *error_msg_printed,
- int keep_running_on_errors,
- const char* prefix,
- const struct scpr_polygon* pg,
const struct dataset_cmode_1* data,
struct scpr_intersector* overlapping_intersector,
struct htable_polygons* polygons,
+ struct darray_geometries* current_cad,
struct scad_geometry** floor)
{
res_T res = RES_OK;
@@ -53,58 +122,35 @@ build_floor
double e_floor = data->floor_thickness;
double offset = 0;
struct scpr_polygon* pg_int = NULL;
- struct scpr_polygon** ptr_p = NULL;
- size_t nverts = 0;
struct scad_geometry* footprint = NULL;
double d[3] = {0, 0, 0};
char* floorname = NULL;
struct str name;
- int is_init = 0;
+ const char* prefix;
- ASSERT(allocator && pg && data && floor);
+ ASSERT(building && error_msg_printed && data && floor);
- if (prefix) {
- str_init(allocator, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_S_floor"));
- floorname = str_get(&name);
- }
+ prefix = str_cget(&building->name);
+ str_init(building->city->allocator, &name);
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_S_floor"));
+ floorname = str_get(&name);
offset = -(e_wall + e_insulation);
- ptr_p = htable_polygons_find(polygons, &offset);
- if(ptr_p) {
- pg_int = *ptr_p;
- } else {
- size_t c;
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, offset, SCPR_JOIN_MITER));
- ERR(scpr_polygon_get_components_count(pg_int, &c));
- if(c == 0) {
- /* Building is too small wrt wall thickness */
- logger_print(logger,
- (keep_running_on_errors ? LOG_WARNING : LOG_ERROR),
- "Building '%s' is too small with respect to wall thickness.\n",
- prefix);
- *error_msg_printed = 1;
- res = RES_BAD_ARG;
- goto error;
- }
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_int));
- htable_polygons_set(polygons, &offset, &pg_int);
- }
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_int));
/*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts, &footprint));
+ ERR(build_footprint(pg_int, 0, &footprint));
d[2] = -e_floor;
ERR(scad_geometry_extrude(footprint, floorname, d, floor));
+ ERR(darray_geometries_push_back(current_cad, floor));
exit:
if(footprint) SCAD(geometry_ref_put(footprint));
- if(!ptr_p) SCPR(polygon_ref_put(pg_int));
- if (is_init) str_release(&name);
+ str_release(&name);
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
return res;
error:
goto exit;
@@ -112,15 +158,15 @@ error:
static res_T
build_wall
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
+ (struct building* building,
+ int *error_msg_printed,
+ const int is_foundation,
const char* suffix,
- const struct scpr_polygon* pg,
const double height,
const struct dataset_cmode_1* data,
struct scpr_intersector* overlapping_intersector,
struct htable_polygons* polygons,
+ struct darray_geometries* current_cad,
struct scad_geometry** wall)
{
res_T res = RES_OK;
@@ -129,78 +175,53 @@ build_wall
double offset = 0;
struct scpr_polygon* pg_int = NULL;
struct scpr_polygon* pg_ext = NULL;
- struct scpr_polygon** ptr_pi = NULL;
- struct scpr_polygon** ptr_pe = NULL;
- size_t nverts = 0;
struct scad_geometry* footprint = NULL;
struct scad_geometry* footprint_int = NULL;
struct scad_geometry* footprint_ext = NULL;
double d[3] = {0, 0, 0};
char* wallname = NULL;
struct str name;
- int is_init = 0;
+ const char* prefix;
- ASSERT(allocator && pg && data && wall);
+ ASSERT(building && error_msg_printed && data && wall);
- if (prefix) {
- str_init(allocator, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- if (suffix) {
- ERR(str_append(&name, "_"));
- ERR(str_append(&name, suffix));
- }
- wallname = str_get(&name);
+ prefix = str_cget(&building->name);
+ str_init(building->city->allocator, &name);
+ ERR(str_set(&name, prefix));
+ if (suffix) {
+ ERR(str_append(&name, "_"));
+ ERR(str_append(&name, suffix));
}
+ wallname = str_get(&name);
- if (strcmp(suffix, "S_foundation") == 0) {
+ if(is_foundation) {
offset = -(e_insulation + 0.1*e_wall);
} else {
offset = -e_insulation;
}
- ptr_pe = htable_polygons_find(polygons, &offset);
- if(ptr_pe) {
- pg_ext = *ptr_pe;
- } else {
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_ext));
- ERR(scpr_offset_polygon(pg_ext, offset, SCPR_JOIN_MITER));
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_ext));
- htable_polygons_set(polygons, &offset, &pg_ext);
- }
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_ext));
offset = -(e_wall + e_insulation);
- ptr_pi = htable_polygons_find(polygons, &offset);
- if(ptr_pi) {
- pg_int = *ptr_pi;
- } else {
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, offset, SCPR_JOIN_MITER));
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_int));
- htable_polygons_set(polygons, &offset, &pg_int);
- }
-
- /*wall footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext));
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_int));
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, 0, nverts, &footprint_int));
-
- ERR(scad_cut_geometries(
- NULL, &footprint_ext, 1, &footprint_int, 1, &footprint));
+ /* wall footprint*/
+ ERR(build_footprint(pg_int, 0, &footprint_int));
+ ERR(build_footprint(pg_ext, 0, &footprint_ext));
+ ERR(scad_cut_geometries(NULL, &footprint_ext, 1, &footprint_int, 1, &footprint));
d[2] = height;
ERR(scad_geometry_extrude(footprint, wallname, d, wall));
+ ERR(darray_geometries_push_back(current_cad, wall));
exit:
- if(!ptr_pi) SCPR(polygon_ref_put(pg_int));
- if(!ptr_pe) SCPR(polygon_ref_put(pg_ext));
if(footprint) SCAD(geometry_ref_put(footprint));
if(footprint_int) SCAD(geometry_ref_put(footprint_int));
if(footprint_ext) SCAD(geometry_ref_put(footprint_ext));
- if (is_init) str_release(&name);
+ str_release(&name);
+ if(pg_ext) SCPR(polygon_ref_put(pg_ext));
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
return res;
error:
goto exit;
@@ -208,15 +229,14 @@ error:
static res_T
build_int_insulation
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
- const struct scpr_polygon* pg,
+ (struct building* building,
+ int *error_msg_printed,
const double height,
const struct dataset_cmode_1* data,
struct scad_geometry* inter_floor,
struct scpr_intersector* overlapping_intersector,
struct htable_polygons* polygons,
+ struct darray_geometries* current_cad,
struct scad_geometry** insulation)
{
res_T res = RES_OK;
@@ -229,9 +249,6 @@ build_int_insulation
double offset = 0;
struct scpr_polygon* pg_int = NULL;
struct scpr_polygon* pg_ext = NULL;
- struct scpr_polygon** ptr_pi = NULL;
- struct scpr_polygon** ptr_pe = NULL;
- size_t nverts = 0;
struct scad_geometry* footprint = NULL;
struct scad_geometry* footprint_int = NULL;
struct scad_geometry* footprint_ext = NULL;
@@ -239,48 +256,27 @@ build_int_insulation
double d[3] = {0, 0, 0};
char* insulationname = NULL;
struct str name;
- int is_init = 0;
+ const char* prefix;
- ASSERT(allocator && pg && data && insulation);
+ ASSERT(building && error_msg_printed && data && insulation);
- if (prefix) {
- str_init(allocator, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_S_internal_insulation"));
- insulationname = str_get(&name);
- }
+ prefix = str_cget(&building->name);
+ str_init(building->city->allocator, &name);
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_S_internal_insulation"));
+ insulationname = str_get(&name);
offset = -(e_ext_insulation + e_wall);
- ptr_pe = htable_polygons_find(polygons, &offset);
- if(ptr_pe) {
- pg_ext = *ptr_pe;
- } else {
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_ext));
- ERR(scpr_offset_polygon(pg_ext, offset, SCPR_JOIN_MITER));
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_ext));
- htable_polygons_set(polygons, &offset, &pg_ext);
- }
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_ext));
offset = -(e_ext_insulation + e_wall + e_int_insulation);
- ptr_pi = htable_polygons_find(polygons, &offset);
- if(ptr_pi) {
- pg_int = *ptr_pi;
- } else {
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, offset, SCPR_JOIN_MITER));
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_int));
- htable_polygons_set(polygons, &offset, &pg_int);
- }
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_int));
/* insulation footprint */
- ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext));
-
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- ERR(scad_add_polygon(NULL, get_position_pg, pg_int, 0, nverts, &footprint_int));
-
+ ERR(build_footprint(pg_int, 0, &footprint_int));
+ ERR(build_footprint(pg_ext, 0, &footprint_ext));
ERR(scad_cut_geometries(NULL, &footprint_ext, 1, &footprint_int, 1, &footprint));
d[2] = height - e_roof - attic - e_roof_insulation;
@@ -291,15 +287,16 @@ build_int_insulation
} else {
ERR(scad_geometry_copy(geom, insulationname, insulation));
}
+ ERR(darray_geometries_push_back(current_cad, insulation));
exit:
- if(!ptr_pi) SCPR(polygon_ref_put(pg_int));
- if(!ptr_pe) SCPR(polygon_ref_put(pg_ext));
if(footprint) SCAD(geometry_ref_put(footprint));
if(footprint_int) SCAD(geometry_ref_put(footprint_int));
if(footprint_ext) SCAD(geometry_ref_put(footprint_ext));
if(geom) SCAD(geometry_ref_put(geom));
- if (is_init) str_release(&name);
+ str_release(&name);
+ if(pg_ext) SCPR(polygon_ref_put(pg_ext));
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
return res;
error:
goto exit;
@@ -307,14 +304,13 @@ error:
static res_T
build_roof
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
- const struct scpr_polygon* pg,
+ (struct building* building,
+ int *error_msg_printed,
const double height,
const struct dataset_cmode_1* data,
struct scpr_intersector* overlapping_intersector,
struct htable_polygons* polygons,
+ struct darray_geometries* current_cad,
struct scad_geometry** roof)
{
res_T res = RES_OK;
@@ -324,46 +320,36 @@ build_roof
double offset = 0;
double z_roof = 0;
struct scpr_polygon* pg_int = NULL;
- struct scpr_polygon** ptr_p;
- size_t nverts = 0;
struct scad_geometry* footprint = NULL;
double d[3] = {0, 0, 0};
char* roofname = NULL;
struct str name;
- int is_init = 0;
+ const char* prefix;
- ASSERT(allocator && pg && data && roof);
+ ASSERT(building && error_msg_printed && data && roof);
- if (prefix) {
- str_init(allocator, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_S_roof"));
- roofname = str_get(&name);
- }
+ prefix = str_cget(&building->name);
+ str_init(building->city->allocator, &name);
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_S_roof"));
+ roofname = str_get(&name);
offset = -(e_wall + e_insulation);
- ptr_p = htable_polygons_find(polygons, &offset);
- if(ptr_p) {
- pg_int = *ptr_p;
- } else {
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, offset, SCPR_JOIN_MITER));
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_int));
- htable_polygons_set(polygons, &offset, &pg_int);
- }
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_int));
/*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
z_roof = height - e_roof;
- ERR(scad_add_polygon(NULL, get_position_pg, pg_int, z_roof, nverts, &footprint));
+ ERR(build_footprint(pg_int, z_roof, &footprint));
d[2] = e_roof;
ERR(scad_geometry_extrude(footprint, roofname, d, roof));
+ ERR(darray_geometries_push_back(current_cad, roof));
exit:
if(footprint) SCAD(geometry_ref_put(footprint));
- if (is_init) str_release(&name);
+ str_release(&name);
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
return res;
error:
goto exit;
@@ -371,14 +357,13 @@ error:
static res_T
build_roof_insulation
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
- const struct scpr_polygon* pg,
+ (struct building* building,
+ int *error_msg_printed,
const double height,
const struct dataset_cmode_1* data,
struct scpr_intersector* overlapping_intersector,
struct htable_polygons* polygons,
+ struct darray_geometries* current_cad,
struct scad_geometry** insulation)
{
res_T res = RES_OK;
@@ -390,47 +375,36 @@ build_roof_insulation
double offset = 0;
double z_insulation = 0;
struct scpr_polygon* pg_int = NULL;
- struct scpr_polygon** ptr_p;
- size_t nverts = 0;
struct scad_geometry* footprint = NULL;
double d[3] = {0, 0, 0};
char* insulationname = NULL;
struct str name;
- int is_init = 0;
+ const char* prefix;
- ASSERT(allocator && pg && data && insulation);
+ ASSERT(building && error_msg_printed && data && insulation);
- if (prefix) {
- str_init(allocator, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_S_roof_insulation"));
- insulationname = str_get(&name);
- }
+ prefix = str_cget(&building->name);
+ str_init(building->city->allocator, &name);
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_S_roof_insulation"));
+ insulationname = str_get(&name);
offset = -(e_wall + e_insulation);
- ptr_p = htable_polygons_find(polygons, &offset);
- if(ptr_p) {
- pg_int = *ptr_p;
- } else {
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, offset, SCPR_JOIN_MITER));
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_int));
- htable_polygons_set(polygons, &offset, &pg_int);
- }
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_int));
/*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
z_insulation = height - e_roof - attic - e_roof_insulation;
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, z_insulation, nverts, &footprint));
+ ERR(build_footprint(pg_int, z_insulation, &footprint));
d[2] = e_roof_insulation;
ERR(scad_geometry_extrude(footprint, insulationname, d, insulation));
+ ERR(darray_geometries_push_back(current_cad, insulation));
exit:
if(footprint) SCAD(geometry_ref_put(footprint));
- if (is_init) str_release(&name);
+ str_release(&name);
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
return res;
error:
goto exit;
@@ -438,13 +412,12 @@ error:
static res_T
build_floor_insulation
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
- const struct scpr_polygon* pg,
+ (struct building* building,
+ int *error_msg_printed,
const struct dataset_cmode_1* data,
struct scpr_intersector* overlapping_intersector,
struct htable_polygons* polygons,
+ struct darray_geometries* current_cad,
struct scad_geometry** insulation)
{
res_T res = RES_OK;
@@ -455,47 +428,36 @@ build_floor_insulation
double offset = 0;
double z_insulation = 0;
struct scpr_polygon* pg_int = NULL;
- struct scpr_polygon** ptr_p;
- size_t nverts = 0;
struct scad_geometry* footprint = NULL;
double d[3] = {0, 0, 0};
char* insulationname = NULL;
struct str name;
- int is_init = 0;
+ const char* prefix;
- ASSERT(allocator && pg && data && insulation);
+ ASSERT(building && error_msg_printed && data && insulation);
- if (prefix) {
- str_init(allocator, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_S_floor_insulation"));
- insulationname = str_get(&name);
- }
+ prefix = str_cget(&building->name);
+ str_init(building->city->allocator, &name);
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_S_floor_insulation"));
+ insulationname = str_get(&name);
offset = -(e_wall + e_insulation);
- ptr_p = htable_polygons_find(polygons, &offset);
- if(ptr_p) {
- pg_int = *ptr_p;
- } else {
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, offset, SCPR_JOIN_MITER));
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_int));
- htable_polygons_set(polygons, &offset, &pg_int);
- }
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_int));
/*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
z_insulation = - e_floor - e_floor_insulation;
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, z_insulation, nverts, &footprint));
+ ERR(build_footprint(pg_int, z_insulation, &footprint));
d[2] = e_floor_insulation;
ERR(scad_geometry_extrude(footprint, insulationname, d, insulation));
+ ERR(darray_geometries_push_back(current_cad, insulation));
exit:
if(footprint) SCAD(geometry_ref_put(footprint));
- if (is_init) str_release(&name);
+ str_release(&name);
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
return res;
error:
goto exit;
@@ -503,14 +465,13 @@ error:
static res_T
build_inter_floor
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
- const struct scpr_polygon* pg,
+ (struct building* building,
+ int *error_msg_printed,
const double height,
const struct dataset_cmode_1* data,
struct scpr_intersector* overlapping_intersector,
struct htable_polygons* polygons,
+ struct darray_geometries* current_cad,
struct scad_geometry** inter_floor)
{
res_T res = RES_OK;
@@ -526,7 +487,6 @@ build_inter_floor
double z_floor = 0;
double h_cavity = 0;
struct scpr_polygon* pg_int = NULL;
- struct scpr_polygon** ptr_p;
size_t nverts = 0;
struct scad_geometry** floor_list = NULL;
struct darray_geometries floor_array;
@@ -534,37 +494,28 @@ build_inter_floor
double d[3] = {0, 0, 0};
char* floorname = NULL;
struct str name;
- int is_init = 0;
+ const char* prefix;
- ASSERT(allocator && pg && data && inter_floor);
+ ASSERT(building && error_msg_printed && data && inter_floor);
- darray_geometries_init(allocator, &floor_array);
+ darray_geometries_init(building->city->allocator, &floor_array);
- if (prefix) {
- str_init(allocator, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_S_intermediate_floors"));
- floorname = str_get(&name);
- }
+ prefix = str_cget(&building->name);
+ str_init(building->city->allocator, &name);
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_S_intermediate_floors"));
+ floorname = str_get(&name);
offset = -(e_wall + e_insulation);
- ptr_p = htable_polygons_find(polygons, &offset);
- if(ptr_p) {
- pg_int = *ptr_p;
- } else {
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, offset, SCPR_JOIN_MITER));
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_int));
- htable_polygons_set(polygons, &offset, &pg_int);
- }
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_int));
ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
h_cavity = height - e_roof - attic - e_roof_ins - (double)floor_n*e_floor;
z_floor = h_cavity/(double)(1 + floor_n);
d[2] = e_floor;
for (i = 0; i < floor_n; i++) {
- ERR(scad_add_polygon( NULL, get_position_pg, pg_int, z_floor, nverts,
+ ERR(scad_add_polygon(NULL, get_position_pg, pg_int, z_floor, nverts,
&footprint));
ERR(scad_geometry_extrude(footprint, NULL, d, &floor));
ERR(scad_geometry_ref_put(footprint));
@@ -579,12 +530,14 @@ build_inter_floor
floor_list = darray_geometries_data_get(&floor_array);
ERR(scad_fuse_geometries(floorname, floor_list, floor_n, floor_list, floor_n,
inter_floor));
+ ERR(darray_geometries_push_back(current_cad, inter_floor));
exit:
- if (is_init) str_release(&name);
+ str_release(&name);
if(footprint) SCAD(geometry_ref_put(footprint));
if(floor) SCAD(geometry_ref_put(floor));
if(floor_list) darray_geometries_release(&floor_array);
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
return res;
error:
goto exit;
@@ -592,14 +545,13 @@ error:
static res_T
build_ext_insulation
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
- const struct scpr_polygon* pg,
+ (struct building* building,
+ int *error_msg_printed,
const double height,
const struct dataset_cmode_1* data,
struct scpr_intersector* overlapping_intersector,
struct htable_polygons* polygons,
+ struct darray_geometries* current_cad,
struct scad_geometry** insulation)
{
res_T res = RES_OK;
@@ -608,35 +560,25 @@ build_ext_insulation
struct scpr_polygon* pg_int = NULL;
struct scpr_polygon* pg_ext = NULL;
struct scpr_polygon** ptr_p;
- size_t nverts = 0;
struct scad_geometry* footprint = NULL;
struct scad_geometry* footprint_int = NULL;
struct scad_geometry* footprint_ext = NULL;
double d[3] = {0, 0, 0};
char* insulationname = NULL;
struct str name;
- int is_init = 0;
+ const char* prefix;
- ASSERT(allocator && pg && data && insulation);
+ ASSERT(building && data && polygons && insulation);
- if (prefix) {
- str_init(allocator, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_S_external_insulation"));
- insulationname = str_get(&name);
- }
+ prefix = str_cget(&building->name);
+ str_init(building->city->allocator, &name);
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_S_external_insulation"));
+ insulationname = str_get(&name);
offset = -e_insulation;
- ptr_p = htable_polygons_find(polygons, &offset);
- if(ptr_p) {
- pg_int = *ptr_p;
- } else {
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, offset, SCPR_JOIN_MITER));
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_int));
- htable_polygons_set(polygons, &offset, &pg_int);
- }
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_int));
offset = 0;
ptr_p = htable_polygons_find(polygons, &offset);
@@ -644,25 +586,20 @@ build_ext_insulation
pg_ext = *ptr_p;
/*insulation footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_ext, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_ext, 0, nverts, &footprint_ext));
-
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, 0, nverts, &footprint_int));
-
- ERR(scad_cut_geometries(
- NULL, &footprint_ext, 1, &footprint_int, 1, &footprint));
+ ERR(build_footprint(pg_int, 0, &footprint_int));
+ ERR(build_footprint(pg_ext, 0, &footprint_ext));
+ ERR(scad_cut_geometries(NULL, &footprint_ext, 1, &footprint_int, 1, &footprint));
d[2] = height;
ERR(scad_geometry_extrude(footprint, insulationname, d, insulation));
+ ERR(darray_geometries_push_back(current_cad, insulation));
exit:
if(footprint) SCAD(geometry_ref_put(footprint));
if(footprint_int) SCAD(geometry_ref_put(footprint_int));
if(footprint_ext) SCAD(geometry_ref_put(footprint_ext));
- if (is_init) str_release(&name);
+ str_release(&name);
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
return res;
error:
goto exit;
@@ -670,13 +607,12 @@ error:
static res_T
build_crawlspace
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
- const struct scpr_polygon* pg,
+ (struct building* building,
+ int *error_msg_printed,
const struct dataset_cmode_1* data,
struct scpr_intersector* overlapping_intersector,
struct htable_polygons* polygons,
+ struct darray_geometries* current_cad,
struct scad_geometry** crawlspace)
{
res_T res = RES_OK;
@@ -688,47 +624,36 @@ build_crawlspace
double offset = 0;
double z_crawl= 0;
struct scpr_polygon* pg_int = NULL;
- struct scpr_polygon** ptr_p;
- size_t nverts = 0;
struct scad_geometry* footprint = NULL;
double d[3] = {0, 0, 0};
char* crawlname = NULL;
struct str name;
- int is_init = 0;
+ const char* prefix;
- ASSERT(allocator && pg && data && crawlspace);
+ ASSERT(building && error_msg_printed && data && crawlspace);
- if (prefix) {
- str_init(allocator, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_F_crawlspace"));
- crawlname = str_get(&name);
- }
+ prefix = str_cget(&building->name);
+ str_init(building->city->allocator, &name);
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_F_crawlspace"));
+ crawlname = str_get(&name);
offset = -(e_wall + e_insulation);
- ptr_p = htable_polygons_find(polygons, &offset);
- if(ptr_p) {
- pg_int = *ptr_p;
- } else {
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, offset, SCPR_JOIN_MITER));
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_int));
- htable_polygons_set(polygons, &offset, &pg_int);
- }
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_int));
/*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
z_crawl = - e_floor - e_floor_insulation - e_crawl;
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, z_crawl, nverts, &footprint));
+ ERR(build_footprint(pg_int, z_crawl, &footprint));
d[2] = e_crawl;
ERR(scad_geometry_extrude(footprint, crawlname, d, crawlspace));
+ ERR(darray_geometries_push_back(current_cad, crawlspace));
exit:
if(footprint) SCAD(geometry_ref_put(footprint));
- if (is_init) str_release(&name);
+ str_release(&name);
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
return res;
error:
goto exit;
@@ -736,15 +661,14 @@ error:
static res_T
build_habitable
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
- const struct scpr_polygon* pg,
+ (struct building* building,
+ int *error_msg_printed,
const double height,
const struct dataset_cmode_1* data,
struct scad_geometry* floor,
struct scpr_intersector* overlapping_intersector,
struct htable_polygons* polygons,
+ struct darray_geometries* current_cad,
struct scad_geometry** cavity)
{
res_T res = RES_OK;
@@ -756,40 +680,25 @@ build_habitable
double e_attic = data->attic_height;
double offset = 0;
struct scpr_polygon* pg_int = NULL;
- struct scpr_polygon** ptr_p;
- size_t nverts = 0;
struct scad_geometry* footprint = NULL;
struct scad_geometry* geom = NULL;
double d[3] = {0, 0, 0};
char* cavityname = NULL;
struct str name;
- int is_init = 0;
+ const char* prefix;
- ASSERT(allocator && pg && data && cavity);
+ ASSERT(building && error_msg_printed && data && cavity);
- if (prefix) {
- str_init(allocator, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_F_levels"));
- cavityname = str_get(&name);
- }
+ prefix = str_cget(&building->name);
+ str_init(building->city->allocator, &name);
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_F_levels"));
+ cavityname = str_get(&name);
offset = -(e_wall + e_ext_insulation + e_int_insulation);
- ptr_p = htable_polygons_find(polygons, &offset);
- if(ptr_p) {
- pg_int = *ptr_p;
- } else {
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, offset, SCPR_JOIN_MITER));
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_int));
- htable_polygons_set(polygons, &offset, &pg_int);
- }
-
- /*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, 0, nverts, &footprint));
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_int));
+ ERR(build_footprint(pg_int, 0, &footprint));
d[2] = height - e_roof - e_attic - e_roof_insulation;
ERR(scad_geometry_extrude(footprint, NULL, d, &geom));
@@ -799,11 +708,13 @@ build_habitable
} else {
ERR(scad_geometry_copy(geom, cavityname, cavity));
}
+ ERR(darray_geometries_push_back(current_cad, cavity));
exit:
if(footprint) SCAD(geometry_ref_put(footprint));
if(geom) SCAD(geometry_ref_put(geom));
- if (is_init) str_release(&name);
+ str_release(&name);
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
return res;
error:
goto exit;
@@ -811,14 +722,13 @@ error:
static res_T
build_attic
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
- const struct scpr_polygon* pg,
+ (struct building* building,
+ int *error_msg_printed,
const double height,
const struct dataset_cmode_1* data,
struct scpr_intersector* overlapping_intersector,
struct htable_polygons* polygons,
+ struct darray_geometries* current_cad,
struct scad_geometry** attic)
{
res_T res = RES_OK;
@@ -829,47 +739,36 @@ build_attic
double offset = 0;
double z_attic = 0;
struct scpr_polygon* pg_int = NULL;
- struct scpr_polygon** ptr_p;
- size_t nverts = 0;
struct scad_geometry* footprint = NULL;
double d[3] = {0, 0, 0};
char* atticname = NULL;
struct str name;
- int is_init = 0;
+ const char* prefix;
- ASSERT(allocator && pg && data && attic);
+ ASSERT(building && error_msg_printed && data && attic);
- if (prefix) {
- str_init(allocator, &name);
- is_init = 1;
- ERR(str_set(&name, prefix));
- ERR(str_append(&name, "_F_attic"));
- atticname = str_get(&name);
- }
+ prefix = str_cget(&building->name);
+ str_init(building->city->allocator, &name);
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_F_attic"));
+ atticname = str_get(&name);
offset = -(e_wall + e_insulation);
- ptr_p = htable_polygons_find(polygons, &offset);
- if(ptr_p) {
- pg_int = *ptr_p;
- } else {
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_int));
- ERR(scpr_offset_polygon(pg_int, offset, SCPR_JOIN_MITER));
- ERR(scpr_intersector_register_polygon(overlapping_intersector, pg_int));
- htable_polygons_set(polygons, &offset, &pg_int);
- }
+ ERR(do_offset(building, polygons, overlapping_intersector, error_msg_printed,
+ offset, &pg_int));
/*footprint*/
- ERR(scpr_polygon_get_vertices_count(pg_int, 0, &nverts));
z_attic = height - e_roof - e_attic;
- ERR(scad_add_polygon(
- NULL, get_position_pg, pg_int, z_attic, nverts, &footprint));
+ ERR(build_footprint(pg_int, z_attic, &footprint));
d[2] = e_attic;
ERR(scad_geometry_extrude(footprint, atticname, d, attic));
+ ERR(darray_geometries_push_back(current_cad, attic));
exit:
if(footprint) SCAD(geometry_ref_put(footprint));
- if (is_init) str_release(&name);
+ str_release(&name);
+ if(pg_int) SCPR(polygon_ref_put(pg_int));
return res;
error:
goto exit;
@@ -877,21 +776,24 @@ error:
static res_T
build_windows
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- struct logger* logger,
- const char* prefix,
- const struct dataset_cmode_1* data,
+ (const struct dataset_cmode_1* data,
struct data_cad_cmode_1* data_cad,
+ struct darray_geometries* current_cad,
struct darray_adjoining_data* adjoining_data)
{
res_T res = RES_OK;
- size_t i, j, adjoining_n, removed_windows = 0;
+ size_t i, j, adjoining_n, removed_count, removed_hor = 0;
+ size_t removed_windows_sz = 0, removed_windows_adj = 0, removed_windows_self = 0;
+ size_t list_n = 0, array_n;
+ const char* prefix;
double N[3];
double dir[3];
- double scale[3];
+ double scale[3], scale_[3];
struct scad_geometry* surface = NULL;
+ struct scad_geometry* win_surface = NULL;
+ struct scad_geometry* surface_ = NULL;
struct scad_geometry* hole = NULL;
+ struct scad_geometry* detect = NULL;
struct scad_geometry** hole_list = NULL;
struct darray_geometries hole_array;
struct scad_geometry* geom = NULL;
@@ -902,91 +804,191 @@ build_windows
struct scad_geometry* glass = NULL;
struct scad_geometry** glass_list = NULL;
struct darray_geometries glass_array;
- size_t list_n = 0, array_n;
- struct str gname;
- int is_init = 0;
+ struct scad_geometry* env = NULL;
+ struct scad_geometry* benv = NULL;
+ struct scad_geometry* problem = NULL;
+ struct str name;
struct adjoining_data* adj;
- (void)scpr;
+ struct mem_allocator* allocator;
- ASSERT(scpr && allocator && logger && data && data_cad && adjoining_data);
+ ASSERT(data && data_cad && adjoining_data);
+ allocator = data_cad->building->city->allocator;
adjoining_n = darray_adjoining_data_size_get(adjoining_data);
adj = darray_adjoining_data_data_get(adjoining_data);
darray_geometries_init(allocator, &hole_array);
darray_geometries_init(allocator, &glass_array);
+ str_init(allocator, &name);
d3_splat(scale, sqrt(data->glass_ratio));
+ d3_splat(scale_, MMIN(1, 1.05 * sqrt(data->glass_ratio)));
/* windows are build from the vertical faces of habitable cavities */
- ERR(scad_geometry_boundary(NULL, &data_cad->habitable_cavity, 1, &bcavity));
- ERR(scad_geometry_explode(bcavity, NULL, &list, &list_n));
-
+ ERR(scad_geometry_boundary("cavity_boundary", &data_cad->habitable_cavity, 1,
+ &bcavity));
+ ERR(scad_geometry_explode(bcavity, "cavity_elt", &list, &list_n));
+ ERR(scad_geometry_ref_put(bcavity));
+ bcavity = NULL;
+
+ /* The boundary of the envelop of the building.
+ * To be used for windows validation */
+ ERR(build_envelop(data_cad->building, &env));
+ ERR(scad_geometry_boundary("envelop_boundary", &env, 1, &benv));
+ ERR(scad_geometry_ref_put(env));
+ env = NULL;
+
+ ERR(darray_geometries_reserve(&hole_array, list_n));
+ ERR(darray_geometries_reserve(&glass_array, list_n));
for (i = 0; i < list_n; i++) {
- double hsz, center[3];
+ double hsz, mass, center[3];
size_t center_n;
size_t count;
+ int removed = 0;
ERR(scad_geometry_get_count(list[i], ¢er_n));
ASSERT(center_n == 1);
ERR(scad_geometry_get_centerofmass(list[i], center));
- ERR(scad_geometry_normal(list[i], center, N, NULL, &surface));
+ ERR(str_printf(&name, "surface_%lu", (long unsigned)i));
+ ERR(scad_geometry_normal(list[i], center, N, str_cget(&name), &surface));
- if (N[2] != 0) {
+ if(N[2] != 0) {
ERR(scad_geometry_ref_put(surface));
surface = NULL;
+ removed_hor++;
continue; /* keep only vertical face */
}
- ERR(scad_geometry_dilate(surface, center, scale));
+ ERR(scad_geometry_get_mass(list[i], &mass));
+ if(mass < 0.1) {
+ /* this window would be too small */
+ ERR(scad_geometry_ref_put(surface));
+ surface = NULL;
+ removed = 1;
+ removed_windows_sz++;
+ }
+
+ if(!removed) {
+ /* Used to check for validity with a slitghly bigger size */
+ ERR(str_printf(&name, "surface+_%lu", (long unsigned)i));
+ ERR(scad_geometry_dilate(surface, center, scale_, str_cget(&name),
+ &surface_));
+ }
- /* Use the same distance used in early stages for close neighbor detection */
- hsz = CG2_CLOSE_NEIGHBOR_DISTANCE + data->wall_thickness +
- data->internal_insulation_thickness + data->external_insulation_thickness;
- d3_muld(dir, N, hsz);
- ERR(scad_geometry_extrude(surface, NULL, dir, &hole));
+ if(!removed && adjoining_n) {
+ /* Use the same distance used in early stages for close neighbor detection */
+ hsz = CG2_CLOSE_NEIGHBOR_DISTANCE + data->wall_thickness +
+ data->internal_insulation_thickness + data->external_insulation_thickness;
+ d3_muld(dir, N, hsz);
+ ERR(str_printf(&name, "detect_adj_%lu", (long unsigned)i));
+ ERR(scad_geometry_extrude(surface_, str_cget(&name), dir, &detect));
- /* Check if hole intersects adjoining envelops */
- /* Push only if don't intersect */
- if (adjoining_n) {
+ /* Check if detect intersects adjoining envelops */
+ /* Push only if don't intersect */
adj_list = MEM_REALLOC(allocator, adj_list,
adjoining_n * sizeof(struct scad_geometry*));
- for(j=0; j<adjoining_n; j++) adj_list[j] = adj[j].envelop;
- ERR(scad_intersect_geometries(NULL, &hole, 1, adj_list, adjoining_n,
- &hole_adjoining_intersect));
+ for(j = 0; j < adjoining_n; j++) adj_list[j] = adj[j].envelop;
+
+ ERR(str_printf(&name, "adj_intersect_%lu", (long unsigned)i));
+ ERR(scad_intersect_geometries(str_cget(&name), &detect, 1, adj_list,
+ adjoining_n, &hole_adjoining_intersect));
+ ERR(scad_geometry_ref_put(detect));
+ detect = NULL;
ERR(scad_geometry_get_count(hole_adjoining_intersect, &count));
ERR(scad_geometry_ref_put(hole_adjoining_intersect));
hole_adjoining_intersect = NULL;
- } else {
- count = 0;
+ if(count) {
+ removed = 1;
+ removed_windows_adj++;
+ }
}
- if (count == 0) {
- ERR(darray_geometries_push_back(&hole_array, &hole));
+ /* Check if the window intersects an unexpected wall of the building:
+ * - the window is too large wrt of external size of the wall (the window's
+ * size is a % of the internal size of the wall that can be larger than
+ * the external size due to angles).
+ * - another wall facing the current one at a too close distance (can be the
+ * prev/next with sharp angle, or not),
+ * - a tiny unwanted wall created by noise at the polygon level (mainly due
+ * to the offseting algorithm). */
+ if(!removed) {
+ /* Use smaller distance than the one used for neighbor detection */
+ hsz = 0.1 + data->wall_thickness + data->internal_insulation_thickness
+ + data->external_insulation_thickness;
+ d3_muld(dir, N, hsz);
+ ERR(str_printf(&name, "detect_self_%lu", (long unsigned)i));
+ ERR(scad_geometry_extrude(surface_, str_cget(&name), dir, &detect));
+ /* Compute intersection between detect and envelop: the number of
+ * components is expected to be 1, or the window is better removed */
+ ERR(str_printf(&name, "self_intersect_%lu", (long unsigned)i));
+ ERR(scad_intersect_geometries(str_cget(&name), &benv, 1, &detect, 1,
+ &problem));
+ ERR(scad_geometry_ref_put(detect));
+ detect = NULL;
+ ERR(scad_geometry_get_count(problem, &count));
+ ERR(scad_geometry_ref_put(problem));
+ problem = NULL;
+ if(count != 1) {
+ removed = 1;
+ removed_windows_self++;
+ }
+ }
- dir[0] = N[0] * 0.024;
- dir[1] = N[1] * 0.024;
- dir[2] = N[2] * 0.024;
- ERR(scad_geometry_extrude(surface, NULL, dir, &glass));
+ if(!removed) {
+ ERR(scad_geometry_dilate(surface, center, scale, NULL, &win_surface));
+ ERR(str_printf(&name, "hole_%lu", (long unsigned)i));
+ ERR(scad_geometry_extrude(win_surface, str_cget(&name), dir, &hole));
+ ERR(darray_geometries_push_back(&hole_array, &hole));
+ ERR(scad_geometry_ref_put(hole));
+ hole = NULL;
+ d3_muld(dir, N, 0.024);
+ ERR(str_printf(&name, "glass_%lu", (long unsigned)i));
+ ERR(scad_geometry_extrude(win_surface, str_cget(&name), dir, &glass));
ERR(darray_geometries_push_back(&glass_array, &glass));
+ ERR(darray_geometries_push_back(current_cad, &glass));
ERR(scad_geometry_ref_put(glass));
glass = NULL;
- } else {
- removed_windows++;
+
+ }
+ ASSERT(hole == NULL);
+ ASSERT(detect == NULL);
+ if(win_surface) {
+ ERR(scad_geometry_ref_put(win_surface));
+ win_surface = NULL;
+ }
+ if(surface) {
+ ERR(scad_geometry_ref_put(surface));
+ surface = NULL;
+ }
+ if(surface_) {
+ ERR(scad_geometry_ref_put(surface_));
+ surface_ = NULL;
}
- ERR(scad_geometry_ref_put(hole));
- hole = NULL;
- ERR(scad_geometry_ref_put(surface));
- surface = NULL;
}
- ASSERT(darray_geometries_size_get(&hole_array)
- == darray_geometries_size_get(&glass_array));
-
+ removed_count = removed_windows_sz + removed_windows_adj + removed_windows_self;
array_n = darray_geometries_size_get(&hole_array);
-
- if(removed_windows) {
- logger_print(logger, LOG_OUTPUT,
- "Building '%s' has %zu/%zu windows removed due to close neighbors.\n",
- prefix, removed_windows, removed_windows+array_n);
+ ASSERT(array_n == darray_geometries_size_get(&glass_array));
+ ASSERT(array_n + removed_hor + removed_count == list_n);
+
+ prefix = str_cget(&data_cad->building->name);
+ if(removed_count != 0) {
+ logger_print(data_cad->building->city->logger, LOG_WARNING,
+ "Building '%s' has %zu/%zu windows removed:\n",
+ prefix, removed_count, removed_count + array_n);
+ if(removed_windows_sz != 0) {
+ logger_print(data_cad->building->city->logger, LOG_WARNING,
+ "- %zu windows removed due to too small size.\n", removed_windows_sz);
+ }
+ if(removed_windows_adj != 0) {
+ logger_print(data_cad->building->city->logger, LOG_WARNING,
+ "- %zu windows removed due to close neighbors.\n", removed_windows_adj);
+ }
+ if(removed_windows_self != 0) {
+ logger_print(data_cad->building->city->logger, LOG_WARNING,
+ "- %zu windows removed due to self conflicts.\n", removed_windows_self);
+ }
+ } else {
+ logger_print(data_cad->building->city->logger, LOG_OUTPUT,
+ "Building '%s' has no window removed (out of %zu).\n", prefix, array_n);
}
if (array_n > 0) {
@@ -994,20 +996,18 @@ build_windows
glass_list = darray_geometries_data_get(&glass_array);
/* wall perforation */
- ERR(scad_cut_geometries(NULL, &data_cad->wall, 1,
- hole_list, array_n, &geom));
- ERR(scad_geometry_swap_names(data_cad->wall, geom));
- ERR(scad_geometry_ref_put(data_cad->wall));
- data_cad->wall = geom;
+ ERR(scad_cut_geometries(NULL, &data_cad->wall, 1, hole_list, array_n, &geom));
+ ERR(scad_geometries_swap(&data_cad->wall, &geom, 1, Scad_swap_geometry));
+ ERR(scad_geometry_ref_put(geom));
geom = NULL;
/* internal insulation perforation */
if (data_cad->internal_insulation) {
ERR(scad_cut_geometries(NULL, &data_cad->internal_insulation, 1,
hole_list, array_n, &geom));
- ERR(scad_geometry_swap_names(data_cad->internal_insulation, geom));
- ERR(scad_geometry_ref_put(data_cad->internal_insulation));
- data_cad->internal_insulation = geom;
+ ERR(scad_geometries_swap(&data_cad->internal_insulation, &geom, 1,
+ Scad_swap_geometry));
+ ERR(scad_geometry_ref_put(geom));
geom = NULL;
}
@@ -1015,38 +1015,37 @@ build_windows
if (data_cad->external_insulation) {
ERR(scad_cut_geometries(NULL, &data_cad->external_insulation, 1,
hole_list, array_n, &geom));
- ERR(scad_geometry_swap_names(data_cad->external_insulation, geom));
- ERR(scad_geometry_ref_put(data_cad->external_insulation));
- data_cad->external_insulation = geom;
+ ERR(scad_geometries_swap(&data_cad->external_insulation, &geom, 1,
+ Scad_swap_geometry));
+ ERR(scad_geometry_ref_put(geom));
geom = NULL;
}
/* build glass */
- if (prefix) {
- str_init(allocator, &gname);
- is_init = 1;
- ERR(str_set(&gname, prefix));
- ERR(str_append(&gname, "_S_glazing"));
- }
-
- ERR(scad_fuse_geometries(str_cget(&gname), glass_list, 1,
- glass_list+1, array_n - 1, &data_cad->glass));
+ ERR(str_set(&name, prefix));
+ ERR(str_append(&name, "_S_glazing"));
+ ERR(scad_fuse_geometries(str_cget(&name), glass_list, 1,
+ glass_list+1, array_n - 1, &data_cad->glazing));
}
exit:
- for (i = 0 ; i < list_n; i++) {
- if(list[i]) SCAD(geometry_ref_put(list[i]));
- }
+ for(i = 0 ; i < list_n; i++) SCAD(geometry_ref_put(list[i]));
darray_geometries_release(&hole_array);
darray_geometries_release(&glass_array);
- if (surface) SCAD(geometry_ref_put(surface));
- if (glass) SCAD(geometry_ref_put(glass));
- if (geom) SCAD(geometry_ref_put(geom));
- if (bcavity) SCAD(geometry_ref_put(bcavity));
- if (hole_adjoining_intersect) SCAD(geometry_ref_put(hole_adjoining_intersect));
+ if(env) SCAD(geometry_ref_put(env));
+ if(benv) SCAD(geometry_ref_put(benv));
+ if(surface) SCAD(geometry_ref_put(surface));
+ if(win_surface) SCAD(geometry_ref_put(win_surface));
+ if(problem) SCAD(geometry_ref_put(problem));
+ if(hole) SCAD(geometry_ref_put(hole));
+ if(detect) SCAD(geometry_ref_put(detect));
+ if(glass) SCAD(geometry_ref_put(glass));
+ if(geom) SCAD(geometry_ref_put(geom));
+ if(bcavity) SCAD(geometry_ref_put(bcavity));
+ if(hole_adjoining_intersect) SCAD(geometry_ref_put(hole_adjoining_intersect));
MEM_RM(allocator, list);
MEM_RM(allocator, adj_list);
- if (is_init) str_release(&gname);
+ str_release(&name);
return res;
error:
goto exit;
@@ -1054,10 +1053,7 @@ error:
static res_T
build_boundary
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
- struct data_cad_cmode_1* data_cad,
+ (struct data_cad_cmode_1* data_cad,
struct darray_adjoining_data* adjoining_data,
struct darray_geometries* boundary)
{
@@ -1067,18 +1063,17 @@ build_boundary
struct scad_geometry* bound = NULL;
char* boundaryname = NULL;
struct str name;
- int is_init = 0;
struct adjoining_data* adj;
size_t adjoining_n, i = 0, count = 0;
- (void)scpr;
+ const char* prefix;
- ASSERT(allocator && prefix && data_cad && adjoining_data && boundary);
+ ASSERT(data_cad && adjoining_data && boundary);
+ prefix = str_cget(&data_cad->building->name);
adjoining_n = darray_adjoining_data_size_get(adjoining_data);
adj = darray_adjoining_data_data_get(adjoining_data);
- darray_geometries_init(allocator, &array);
- str_init(allocator, &name);
- is_init = 1;
+ darray_geometries_init(data_cad->building->city->allocator, &array);
+ str_init(data_cad->building->city->allocator, &name);
/* Ensure enough room for all geometries without error nor mem move */
ERR(darray_geometries_reserve(&array, 14 + adjoining_n));
@@ -1115,11 +1110,13 @@ build_boundary
if (data_cad->crawlspace_cavity) {
ERR(darray_geometries_push_back(&array, &data_cad->crawlspace_cavity));
}
- if (data_cad->glass) {
- ERR(darray_geometries_push_back(&array, &data_cad->glass));
+ if (data_cad->glazing) {
+ ERR(darray_geometries_push_back(&array, &data_cad->glazing));
}
for (i=0; i<adjoining_n; i++) {
- ERR(darray_geometries_push_back(&array, &adj[i].envelop));
+ if(adj[i].really_adjoining) {
+ ERR(darray_geometries_push_back(&array, &adj[i].envelop));
+ }
}
count = darray_geometries_size_get(&array);
@@ -1146,12 +1143,12 @@ build_boundary
ERR(scad_geometry_ref_put(bound));
bound = NULL;
- if (data_cad->glass) {
+ if (data_cad->glazing) {
ERR(str_set(&name, prefix));
ERR(str_append(&name, "_B_glazing"));
boundaryname = str_get(&name);
ERR(scad_geometries_common_boundaries(boundaryname, list, count,
- &data_cad->glass, 1, &bound));
+ &data_cad->glazing, 1, &bound));
ERR(darray_geometries_push_back(boundary, &bound));
ERR(scad_geometry_ref_put(bound));
bound = NULL;
@@ -1185,7 +1182,7 @@ build_boundary
exit:
if(bound) SCAD(geometry_ref_put(bound));
- if (is_init) str_release(&name);
+ str_release(&name);
darray_geometries_release(&array);
return res;
error:
@@ -1194,10 +1191,7 @@ error:
static res_T
build_connection
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
- struct data_cad_cmode_1* data_cad,
+ (struct data_cad_cmode_1* data_cad,
struct darray_geometries* connection)
{
res_T res = RES_OK;
@@ -1205,15 +1199,15 @@ build_connection
size_t count = 0;
char* cname = NULL;
struct str name;
- int is_init = 0;
- (void)scpr;
+ const char* prefix;
- ASSERT(allocator && prefix && data_cad && connection);
+ ASSERT(data_cad && connection);
- str_init(allocator, &name);
- is_init = 1;
+ prefix = str_cget(&data_cad->building->name);
+ str_init(data_cad->building->city->allocator, &name);
-#define CREATE_CONNECT(G1,G2,SUFFIX) ERR(str_set(&name, prefix));\
+#define CREATE_CONNECT(G1,G2,SUFFIX) \
+ ERR(str_set(&name, prefix));\
ERR(str_append(&name, SUFFIX));\
cname = str_get(&name);\
ERR(scad_geometries_common_boundaries(cname, &data_cad->G1, 1,\
@@ -1236,8 +1230,8 @@ build_connection
CREATE_CONNECT(habitable_cavity,wall,"_C_levels_walls");
/* with glass */
- if (data_cad->glass) {
- CREATE_CONNECT(habitable_cavity,glass,"_C_levels_glazing");
+ if (data_cad->glazing) {
+ CREATE_CONNECT(habitable_cavity,glazing,"_C_levels_glazing");
}
/* with internal insulation */
@@ -1296,26 +1290,7 @@ build_connection
#undef CREATE_CONNECT
exit:
- if (is_init) str_release(&name);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-build_footprint
- (struct scpr_polygon* pg,
- struct scad_geometry** footprint)
-{
- res_T res = RES_OK;
- size_t nverts = 0;
-
- ASSERT(pg && footprint);
-
- ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
- ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, footprint));
-
-exit:
+ str_release(&name);
return res;
error:
goto exit;
@@ -1323,11 +1298,9 @@ error:
static res_T
build_fake_ground
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- struct data_cad_cmode_1* cad,
- struct scpr_polygon* pg,
+ (struct data_cad_cmode_1* cad,
const double depth,
+ struct darray_geometries* current_cad,
struct scad_geometry** ground)
{
res_T res = RES_OK;
@@ -1339,9 +1312,9 @@ build_fake_ground
struct scad_geometry* footprint = NULL;
struct scad_geometry* geom = NULL;
- ASSERT(cad && pg && ground );
+ ASSERT(cad && ground );
- darray_geometries_init(allocator, &array);
+ darray_geometries_init(cad->building->city->allocator, &array);
/* Ensure enough room for all geometries without error nor mem move */
ERR(darray_geometries_reserve(&array, 4));
@@ -1361,15 +1334,16 @@ build_fake_ground
count = darray_geometries_size_get(&array);
list = darray_geometries_data_get(&array);
- ERR(scpr_polygon_create_copy(scpr, pg, &pg_offset));
+ ERR(scpr_polygon_create_copy(cad->building->city->scpr, cad->building->pg, &pg_offset));
ERR(scpr_offset_polygon(pg_offset, 0.1, SCPR_JOIN_MITER));
- ERR(build_footprint(pg_offset, &footprint));
+ ERR(build_footprint(pg_offset, 0, &footprint));
dir[2] = -depth*1.1;
ERR(scad_geometry_extrude(footprint, NULL, dir, &geom));
- ERR(scad_cut_geometries(NULL, &geom, 1, list, count, ground));
+ ERR(scad_cut_geometries("fake_ground", &geom, 1, list, count, ground));
+ ERR(darray_geometries_push_back(current_cad, ground));
exit:
if (pg_offset) SCPR(polygon_ref_put(pg_offset));
@@ -1383,29 +1357,24 @@ error:
static res_T
building_ground_connection
- (struct scpr_device* scpr,
- struct mem_allocator* allocator,
- const char* prefix,
- struct data_cad_cmode_1* cad,
+ (struct data_cad_cmode_1* cad,
struct scad_geometry** connection)
{
res_T res = RES_OK;
char* cname = NULL;
struct str name;
- int is_init = 0;
size_t count;
struct darray_geometries array;
struct scad_geometry** list = NULL;
struct scad_geometry* list_boundary = NULL;
struct scad_geometry* footprint = NULL;
+ const char* prefix;
- (void)scpr;
- ASSERT(scpr && allocator && prefix && cad && connection);
-
- darray_geometries_init(allocator, &array);
+ ASSERT(cad && connection);
- str_init(allocator, &name);
- is_init = 1;
+ prefix = str_cget(&cad->building->name);
+ darray_geometries_init(cad->building->city->allocator, &array);
+ str_init(cad->building->city->allocator, &name);
ERR(str_set(&name, prefix));
ERR(str_append(&name, "_C_ground"));
cname = str_get(&name);
@@ -1439,7 +1408,7 @@ building_ground_connection
exit:
darray_geometries_release(&array);
- if (is_init) str_release(&name);
+ str_release(&name);
if (list_boundary) SCAD(geometry_ref_put(list_boundary));
if (footprint) SCAD(geometry_ref_put(footprint));
return res;
@@ -1464,13 +1433,13 @@ init_cmode_1
struct str dataset_name;
int name_initialized = 0;
static struct construction_mode_functors functors_1 = {
- &init_cmode_1,
- &release_cmode_1,
- &build_cad_cmode_1,
- &build_footprint_cmode_1,
- &build_envelop_cmode_1,
- &export_stl_cmode_1,
- &release_cad_cmode_1
+ &init_cmode_1,
+ &release_cmode_1,
+ &build_cad_cmode_1,
+ &build_footprint_cmode_1,
+ &save_ground_connection_triangles_1,
+ &export_stl_cmode_1,
+ &release_cad_cmode_1
};
struct mem_allocator* allocator;
struct logger* logger;
@@ -1519,9 +1488,10 @@ release_cmode_1
res_T
build_cad_cmode_1
(struct building* building,
- int dump_footprints_on_error,
+ int dump_footprints_level,
int keep_running_on_errors,
struct darray_adjoining_data* adjoining_data,
+ struct darray_geometries* current_cad,
void** cad)
{
res_T res = RES_OK;
@@ -1539,16 +1509,18 @@ build_cad_cmode_1
struct htable_polygons polygons;
int polygons_initialized = 0;
double zero = 0;
- struct scpr_device* scpr;
struct mem_allocator* allocator;
struct logger* logger = NULL;
+ size_t i, cad_count;
+ struct scad_geometry** cur_cad = NULL;
+ struct scad_geometry** partitioned = NULL;
if (!building || !cad || !adjoining_data) {
res = RES_BAD_ARG;
goto error;
}
- scpr = building->city->scpr;
+ name = str_cget(&building->name);
allocator = building->city->allocator;
logger = building->city->logger;
data_cad = MEM_CALLOC(allocator, 1, sizeof(struct data_cad_cmode_1));
@@ -1556,15 +1528,17 @@ build_cad_cmode_1
res = RES_MEM_ERR;
goto error;
}
- data_cad->allocator = allocator;
- darray_geometries_init(allocator, &data_cad->boundary);
- darray_geometries_init(allocator, &data_cad->connection);
+ building->data_cad = data_cad;
+ data_cad->building = building;
darray_common_trg_init(allocator, &data_cad->common_trg);
darray_geometries_init(allocator, &data_cad->adj_walls);
+ darray_geometries_init(allocator, &data_cad->boundary);
+ darray_geometries_init(allocator, &data_cad->connection);
+
htable_polygons_init(allocator, &polygons);
polygons_initialized = 1;
- ERR(scpr_intersector_create(scpr, &overlapping_intersector));
+ ERR(scpr_intersector_create(building->city->scpr, &overlapping_intersector));
ERR(scpr_intersector_register_polygon(overlapping_intersector, building->pg));
/* An htable to associate offset polygons to offsets. Not really for
* performance, but to avoid considering the same polygon more than once when
@@ -1577,16 +1551,15 @@ build_cad_cmode_1
- roof
*/
- name = str_cget(&building->name);
- ERR(build_floor(scpr, allocator, logger, &error_msg_printed,
- keep_running_on_errors, name, building->pg, data, overlapping_intersector,
- &polygons, &data_cad->floor));
+ ERR(build_floor(building, &error_msg_printed, data, overlapping_intersector,
+ &polygons, current_cad, &data_cad->floor));
- ERR(build_wall(scpr, allocator, name, "S_walls", building->pg, height, data,
- overlapping_intersector, &polygons, &data_cad->wall));
+ ERR(build_wall(building, &error_msg_printed, 0, "S_walls", height, data,
+ overlapping_intersector, &polygons, current_cad, &data_cad->wall));
- ERR(build_roof(scpr, allocator, name, building->pg, height, data,
- overlapping_intersector, &polygons, &data_cad->roof));
+ ERR(build_roof(building, &error_msg_printed,
+ height, data,
+ overlapping_intersector, &polygons, current_cad, &data_cad->roof));
/* build optionnal elements :
- foundation
@@ -1599,34 +1572,34 @@ build_cad_cmode_1
if (data->foundation_depth > 0) {
depth = -data->foundation_depth;
- ERR(build_wall(scpr, allocator, name, "S_foundation", building->pg, depth, data,
- overlapping_intersector, &polygons, &data_cad->foundation));
+ ERR(build_wall(building, &error_msg_printed, 1, "S_foundation", depth,
+ data, overlapping_intersector, &polygons, current_cad, &data_cad->foundation));
}
if (data->inter_floor_count > 0) {
- ERR(build_inter_floor(scpr, allocator, name, building->pg, height, data,
- overlapping_intersector, &polygons, &data_cad->intermediate_floor));
+ ERR(build_inter_floor(building, &error_msg_printed, height, data,
+ overlapping_intersector, &polygons, current_cad, &data_cad->intermediate_floor));
}
if (data->external_insulation_thickness> 0) {
- ERR(build_ext_insulation(scpr, allocator, name, building->pg, height, data,
- overlapping_intersector, &polygons, &data_cad->external_insulation));
+ ERR(build_ext_insulation(building, &error_msg_printed, height, data,
+ overlapping_intersector, &polygons, current_cad, &data_cad->external_insulation));
}
if (data->internal_insulation_thickness> 0) {
- ERR(build_int_insulation(scpr, allocator, name, building->pg, height, data,
+ ERR(build_int_insulation(building, &error_msg_printed, height, data,
data_cad->intermediate_floor, overlapping_intersector, &polygons,
- &data_cad->internal_insulation));
+ current_cad, &data_cad->internal_insulation));
}
if (data->roof_insulation_thickness > 0) {
- ERR(build_roof_insulation(scpr, allocator, name, building->pg, height, data,
- overlapping_intersector, &polygons, &data_cad->roof_insulation));
+ ERR(build_roof_insulation(building, &error_msg_printed, height, data,
+ overlapping_intersector, &polygons, current_cad, &data_cad->roof_insulation));
}
if (data->floor_insulation_thickness > 0) {
- ERR(build_floor_insulation(scpr, allocator, name, building->pg, data,
- overlapping_intersector, &polygons, &data_cad->floor_insulation));
+ ERR(build_floor_insulation(building, &error_msg_printed, data,
+ overlapping_intersector, &polygons, current_cad, &data_cad->floor_insulation));
}
/* build cavities :
@@ -1636,17 +1609,17 @@ build_cad_cmode_1
*/
if (data->attic_height > 0) {
- ERR(build_attic(scpr, allocator, name, building->pg, height, data,
- overlapping_intersector, &polygons, &data_cad->attic_cavity));
+ ERR(build_attic(building, &error_msg_printed, height, data,
+ overlapping_intersector, &polygons, current_cad, &data_cad->attic_cavity));
}
- ERR(build_habitable(scpr, allocator, name, building->pg, height, data,
+ ERR(build_habitable(building, &error_msg_printed, height, data,
data_cad->intermediate_floor, overlapping_intersector, &polygons,
- &data_cad->habitable_cavity));
+ current_cad, &data_cad->habitable_cavity));
if (data->crawl_height > 0) {
- ERR(build_crawlspace(scpr, allocator, name, building->pg, data,
- overlapping_intersector, &polygons, &data_cad->crawlspace_cavity));
+ ERR(build_crawlspace(building, &error_msg_printed, data,
+ overlapping_intersector, &polygons, current_cad, &data_cad->crawlspace_cavity));
}
/* Check for registered polygons overlapping */
@@ -1655,14 +1628,14 @@ build_cad_cmode_1
ctx.buildings_count = 1;
ctx.intersection_found = &error_occured;
ctx.search_type = OVERLAPPING_PROXIMITY;
- ctx.dump_footprints_on_error = dump_footprints_on_error;
+ ctx.dump_footprints_level = dump_footprints_level;
ctx.keep_running_on_errors = keep_running_on_errors;
callbacks.simple_intersection = simple_intersection;
ERR(scpr_intersector_check(overlapping_intersector, &callbacks, &ctx));
if(error_occured) {
logger_print(logger, LOG_ERROR,
"Internal error building CAD for building '%s'.\n",
- str_cget(&building->name));
+ name);
ERR(darray_pbuilding_push_back(&building->city->removed_buildings, &building));
error_msg_printed = 1;
res = RES_BAD_ARG;
@@ -1672,29 +1645,38 @@ build_cad_cmode_1
/* build adjoining envelop */
adjoining_n = htable_building_size_get(&building->close_buildings);
if (adjoining_n > 0) {
- ERR(build_adjoining(building, adjoining_data));
+ ERR(build_adjoining(building, current_cad, adjoining_data));
ASSERT(adjoining_n == darray_adjoining_data_size_get(adjoining_data));
}
/* windows */
if (data->glass_ratio > 0) {
- ERR(build_windows(scpr, allocator, logger, name, data, data_cad, adjoining_data));
+ ERR(build_windows(data, data_cad, current_cad, adjoining_data));
}
/* fake ground */
depth = MMAX(data->foundation_depth,
data->floor_thickness + data->floor_insulation_thickness + data->crawl_height);
+ ERR(build_fake_ground(data_cad, depth, current_cad, &data_cad->fake_ground));
- ERR(build_fake_ground(scpr, allocator, data_cad, building->pg, depth,
- &data_cad->fake_ground));
-
- ERR(scad_scene_partition());
+ /* Partition CAD */
+ cad_count = darray_geometries_size_get(current_cad);
+ partitioned = MEM_CALLOC(allocator, cad_count, sizeof(*partitioned));
+ if(!partitioned) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ cur_cad = darray_geometries_data_get(current_cad);
+ ERR(scad_geometries_partition(cur_cad, cad_count, 0, partitioned));
+ /* Swap original geometry and partitioned geometry in data_cad (was
+ * accumulated into current_cad) */
+ ERR(scad_geometries_swap(cur_cad, partitioned, cad_count, Scad_swap_geometry));
/* After partitioning, manage common parts with other buildings */
if(adjoining_n > 0) {
size_t a, c;
struct b_pair pair;
- struct darray_double* common_trg;
+ struct darray_double* common;
struct adjoining_data* adjoining
= darray_adjoining_data_data_get(adjoining_data);
struct scad_geometry* extern_most = data_cad->external_insulation
@@ -1704,45 +1686,44 @@ build_cad_cmode_1
ERR(scad_geometries_common_boundaries(NULL, &extern_most, 1,
&adj->envelop, 1, &adj->common_geometry));
ERR(scad_geometry_get_count(adj->common_geometry, &c));
- if(c == 0) {
- /* Not really adjoining */
+ adj->really_adjoining = (c != 0);
+ if(!adj->really_adjoining) {
logger_print(logger, LOG_OUTPUT,
"building '%s': neighbor '%s' not really adjoining.\n",
- str_cget(&building->name),
+ name,
str_cget(&adj->adjoining_building->name));
continue;
}
make_b_pair(&pair, building, adj->adjoining_building);
- common_trg
- = htable_common_triangles_find(&building->city->common_triangles, &pair);
- if(common_trg) {
- /* The common geometry has already been processed when creating a
- * previous building, and the very same mesh must be used for this one.
- * Keep track of the geometry to replace and the mesh to output instead */
- ERR(darray_geometries_push_back(&data_cad->adj_walls,
- &adj->common_geometry));
- ERR(darray_common_trg_push_back(&data_cad->common_trg, &common_trg));
- } else {
+ /* Keep track of the geometry to replace and the mesh to output instead */
+ ERR(darray_geometries_push_back(&data_cad->adj_walls, &adj->common_geometry));
+ ERR(darray_common_trg_push_back(&data_cad->common_trg, &pair));
+ common = htable_common_find(&building->city->common, &pair);
+ if(!common) {
/* The mesh doesn't exist yet and won't be created until a further step.
* We need to store the geometry id so that the mesh can be stored when
* created. */
- adjoining[a].save = 1;
+ adj->save = 1;
}
}
}
/* build ground/building connection */
- ERR(building_ground_connection(scpr, allocator, name, data_cad,
- &data_cad->ground_connection));
+ ERR(building_ground_connection(data_cad, &data_cad->ground_connection));
/* build boundaries */
- ERR(build_boundary(scpr, allocator, name, data_cad, adjoining_data,
- &data_cad->boundary));
+ ERR(build_boundary(data_cad, adjoining_data, &data_cad->boundary));
/* build connections */
- ERR(build_connection(scpr, allocator, name, data_cad, &data_cad->connection));
+ ERR(build_connection(data_cad, &data_cad->connection));
exit:
+ if(partitioned) {
+ for(i = 0; i < cad_count; i++) {
+ if(partitioned[i]) SCAD(geometry_ref_put(partitioned[i]));
+ }
+ MEM_RM(allocator, partitioned);
+ }
if(polygons_initialized) htable_polygons_release(&polygons);
if(overlapping_intersector) SCPR(intersector_ref_put(overlapping_intersector));
if(cad) *(struct data_cad_cmode_1**)cad = data_cad;
@@ -1770,7 +1751,7 @@ build_footprint_cmode_1
goto error;
}
- ERR(build_footprint(building->pg, footprint));
+ ERR(build_footprint(building->pg, 0, footprint));
exit:
return res;
@@ -1778,27 +1759,21 @@ error:
goto exit;
}
-res_T
-build_envelop_cmode_1
- (struct building* building,
- struct scad_geometry** envelop)
+res_T save_ground_connection_triangles_1
+ (void* cad,
+ struct darray_double* triangles)
{
res_T res = RES_OK;
- size_t nverts = 0;
- double height = building->height;
- double d[3] = {0, 0, 0};
- struct scpr_polygon* pg = building->pg;
- struct scad_geometry* footprint = NULL;
+ struct data_cad_cmode_1* data_cad = cad;
- ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
- ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, &footprint));
+ if(!cad || !triangles) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
- /* wall envelop */
- d[2] = height;
- ERR(scad_geometry_extrude(footprint, NULL, d, envelop));
+ ERR(scad_stl_get_data(data_cad->ground_connection, triangles));
exit:
- if (footprint) SCAD(geometry_ref_put(footprint));
return res;
error:
goto exit;
@@ -1811,87 +1786,159 @@ export_stl_cmode_1
{
res_T res = RES_OK;
struct data_cad_cmode_1* data_cad = (struct data_cad_cmode_1 *)cad;
- size_t i = 0;
+ size_t i = 0, j, common_n = 0, coord_count = 0;
+ struct darray_double trg;
+ struct str name;
+ int initialized = 0;
+ struct scad_geometry** list = NULL;
+ struct mem_allocator* allocator = NULL;
if (!cad) {
res = RES_BAD_ARG;
goto error;
}
+ allocator = data_cad->building->city->allocator;
+
/* floor export */
- ERR(scad_stl_export(data_cad->floor, NULL, binary));
+ ERR(scad_stl_export(data_cad->floor, NULL, Scad_force_normals_outward, binary));
+
+ /* roof export */
+ ERR(scad_stl_export(data_cad->roof, NULL, Scad_force_normals_outward, binary));
/* wall export */
- ERR(scad_stl_export(data_cad->wall, NULL, binary));
+ if(darray_geometries_size_get(&data_cad->adj_walls) == 0) {
+ ERR(scad_stl_export(data_cad->wall, NULL, Scad_force_normals_outward, binary));
+ } else {
+ /* There is some adjoining building(s) to manage */
+ size_t common_count = darray_common_trg_size_get(&data_cad->common_trg);
+ const char* tmp;
- /* roof export */
- ERR(scad_stl_export(data_cad->roof, NULL, binary));
+ darray_double_init(allocator, &trg);
+ str_init(allocator, &name);
+ initialized = 1;
+ /* Get the triangles that are not common with adjoining buildings */
+ ERR(scad_stl_get_data_partial(data_cad->wall,
+ darray_geometries_data_get(&data_cad->adj_walls),
+ darray_geometries_size_get(&data_cad->adj_walls), &trg));
+ coord_count = darray_double_size_get(&trg);
+ /* Add the triangles from adjoining buildings */
+ for(i = 0; i < common_count; i++) {
+ size_t sz;
+ struct b_pair* pair = darray_common_trg_data_get(&data_cad->common_trg)+ i;
+ const double *t9;
+ double* tgt;
+ struct city* city = data_cad->building->city;
+ struct darray_double* common = NULL;
+ /* Get triangles */
+ common = htable_common_find(&city->common, pair);
+ if(!common) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ t9 = darray_double_cdata_get(common);
+ /* Add common triangles */
+ sz = darray_double_size_get(common);
+ ASSERT(sz % 9 == 0);
+ ASSERT(coord_count == darray_double_size_get(&trg));
+ ERR(darray_double_resize(&trg, coord_count + sz));
+ tgt = darray_double_data_get(&trg);
+ for(j = 0; j < sz; j++) {
+ tgt[coord_count + j] = t9[j];
+ }
+ coord_count += sz;
+ ASSERT(coord_count % 9 == 0);
+ }
+ ERR(scad_geometry_get_name(data_cad->wall, &tmp));
+ ERR(str_set(&name, tmp));
+ ERR(str_append(&name, ".stl"));
+ ERR(scad_stl_data_write(&trg, str_cget(&name), Scad_force_normals_outward,
+ binary));
+ }
/* foundation export */
if (data_cad->foundation) {
- ERR(scad_stl_export(data_cad->foundation, NULL, binary));
+ ERR(scad_stl_export(data_cad->foundation, NULL, Scad_force_normals_outward,
+ binary));
}
/* glass export */
- if (data_cad->glass) {
- ERR(scad_stl_export(data_cad->glass, NULL, binary));
+ if (data_cad->glazing) {
+ ERR(scad_stl_export(data_cad->glazing, NULL, Scad_force_normals_outward,
+ binary));
}
/* intermediate floor export*/
if (data_cad->intermediate_floor) {
- ERR(scad_stl_export(data_cad->intermediate_floor, NULL, binary));
+ ERR(scad_stl_export(data_cad->intermediate_floor, NULL,
+ Scad_force_normals_outward, binary));
}
/* internal insulation export*/
if (data_cad->internal_insulation) {
- ERR(scad_stl_export(data_cad->internal_insulation, NULL, binary));
+ ERR(scad_stl_export(data_cad->internal_insulation, NULL,
+ Scad_force_normals_outward, binary));
}
/* external insulation export*/
if (data_cad->external_insulation) {
- ERR(scad_stl_export(data_cad->external_insulation, NULL, binary));
+ ERR(scad_stl_export(data_cad->external_insulation, NULL,
+ Scad_force_normals_outward, binary));
}
/* roof insulation export*/
if (data_cad->roof_insulation) {
- ERR(scad_stl_export(data_cad->roof_insulation, NULL, binary));
+ ERR(scad_stl_export(data_cad->roof_insulation, NULL,
+ Scad_force_normals_outward, binary));
}
/* floor insulation export*/
if (data_cad->floor_insulation) {
- ERR(scad_stl_export(data_cad->floor_insulation, NULL, binary));
+ ERR(scad_stl_export(data_cad->floor_insulation, NULL,
+ Scad_force_normals_outward, binary));
}
/* attic cavity export*/
if (data_cad->attic_cavity) {
- ERR(scad_stl_export(data_cad->attic_cavity, NULL, binary));
+ ERR(scad_stl_export(data_cad->attic_cavity, NULL,
+ Scad_force_normals_outward, binary));
}
/* habitable cavity export*/
- ERR(scad_stl_export(data_cad->habitable_cavity, NULL, binary));
+ ERR(scad_stl_export(data_cad->habitable_cavity, NULL,
+ Scad_force_normals_outward, binary));
/* crawlspace cavity export*/
if (data_cad->crawlspace_cavity) {
- ERR(scad_stl_export(data_cad->crawlspace_cavity, NULL, binary));
+ ERR(scad_stl_export(data_cad->crawlspace_cavity, NULL,
+ Scad_force_normals_outward, binary));
}
/* boundary export*/
for(i = 0; i < darray_geometries_size_get(&data_cad->boundary); i++) {
struct scad_geometry* b = darray_geometries_data_get(&data_cad->boundary)[i];
- ERR(scad_stl_export(b, NULL, binary));
+ ERR(scad_stl_export(b, NULL, Scad_keep_normals_unchanged, binary));
}
/* connections export*/
for(i = 0; i < darray_geometries_size_get(&data_cad->connection); i++) {
struct scad_geometry* c = darray_geometries_data_get(&data_cad->connection)[i];
- ERR(scad_stl_export(c, NULL, binary));
+ ERR(scad_stl_export(c, NULL, Scad_keep_normals_unchanged, binary));
}
/* ground/building connection export*/
- ERR(scad_geometry_reverse(data_cad->ground_connection));
- ERR(scad_stl_export(data_cad->ground_connection, NULL, binary));
+ ERR(scad_stl_export(data_cad->ground_connection, NULL,
+ Scad_keep_normals_unchanged, binary));
exit:
+ for(j = 0; j < common_n; j++) {
+ if(list[j]) SCAD(geometry_ref_put(list[j]));
+ }
+ MEM_RM(allocator, list);
+ if(initialized) {
+ darray_double_release(&trg);
+ str_release(&name);
+ }
return res;
error:
goto exit;
@@ -1910,7 +1957,7 @@ release_cad_cmode_1
goto error;
}
- allocator = data_cad->allocator;
+ allocator = data_cad->building->city->allocator;
darray_geometries_release(&data_cad->boundary);
darray_geometries_release(&data_cad->connection);
darray_common_trg_release(&data_cad->common_trg);
@@ -1927,7 +1974,7 @@ release_cad_cmode_1
GDEL(floor);
GDEL(floor_insulation);
GDEL(foundation);
- GDEL(glass);
+ GDEL(glazing);
GDEL(ground_connection);
GDEL(habitable_cavity);
GDEL(intermediate_floor);
diff --git a/src/cg_construction_mode_1.h b/src/cg_construction_mode_1.h
@@ -63,11 +63,11 @@ struct dataset_cmode_1 {
#include <rsys/hash_table.h>
struct data_cad_cmode_1 {
- struct mem_allocator* allocator;
- struct darray_geometries boundary;
- struct darray_geometries connection;
struct darray_common_trg common_trg;
struct darray_geometries adj_walls;
+ struct darray_geometries boundary;
+ struct darray_geometries connection;
+ struct building* building;
struct scad_geometry* wall;
struct scad_geometry* roof;
struct scad_geometry* floor;
@@ -80,7 +80,7 @@ struct data_cad_cmode_1 {
struct scad_geometry* external_insulation; /* can be NULL */
struct scad_geometry* floor_insulation; /* can be NULL */
struct scad_geometry* roof_insulation; /* can be NULL */
- struct scad_geometry* glass;
+ struct scad_geometry* glazing;
struct scad_geometry* fake_ground;/*not exported, used for ground connection*/
struct scad_geometry* ground_connection;
size_t n_connection;
@@ -105,6 +105,7 @@ build_cad_cmode_1
int dump_footprints_on_error,
int keep_running_on_errors,
struct darray_adjoining_data* adjoining_data,
+ struct darray_geometries* current_cad,
void** cad);
res_T
@@ -112,10 +113,9 @@ build_footprint_cmode_1
(struct building* building,
struct scad_geometry** footprint);
-res_T
-build_envelop_cmode_1
- (struct building* building,
- struct scad_geometry** envelop);
+res_T save_ground_connection_triangles_1
+ (void* cad,
+ struct darray_double* triangles);
res_T
export_stl_cmode_1
diff --git a/src/cg_ground.c b/src/cg_ground.c
@@ -18,10 +18,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "cg_ground.h"
+#include "cg_building.h"
#include "cg_city.h"
#include "cg.h"
+#include <rsys/rsys.h>
+#include <rsys/dynamic_array_double.h>
#include <rsys/str.h>
+
#include <star/scad.h>
#define GDEL(Tgt) \
@@ -29,17 +33,17 @@
/* To avoid double delete, set to NULL after deletion */ \
Tgt = NULL
-#define GMV(Idx) \
- ASSERT(ground->boundary[Idx] == NULL); \
- ground->boundary[Idx] = surface; \
- /* To avoid unwanted delete, set to NULL after mv */ \
- surface = NULL
+#define GPUSH(G) \
+ ASSERT(G); \
+ ERR(darray_geometries_push_back(&ground->boundaries, &(G))); \
+ ERR(scad_geometry_ref_put(G)); /* Ownership is transfered to array */ \
+ surface = NULL; \
+ (G) = NULL;
res_T
ground_build_cad
(struct mem_allocator* allocator,
- struct city* city,
- struct ground* ground)
+ struct city* city)
{
res_T res = RES_OK;
double origin[3];
@@ -47,10 +51,13 @@ ground_build_cad
struct scad_geometry* bound = NULL;
struct scad_geometry** list;
struct scad_geometry* surface = NULL;
+ struct scad_geometry* tmp = NULL;
size_t i, count = 0;
+ struct ground* ground;
- ASSERT(city && ground);
+ ASSERT(city);
+ ground = &city->ground;
origin[0] = city->lower[0];
origin[1] = city->lower[1];
origin[2] = -city->ground_depth;
@@ -59,7 +66,7 @@ ground_build_cad
extent[1] = city->upper[1] - city->lower[1];
extent[2] = city->ground_depth;
- if (origin[2] > 0 || extent[0] < 0 || extent[1] < 0 || extent[2] < 0 ) {
+ if(origin[2] > 0 || extent[0] < 0 || extent[1] < 0 || extent[2] < 0 ) {
res = RES_BAD_ARG;
goto error;
}
@@ -68,11 +75,9 @@ ground_build_cad
ERR(scad_geometry_boundary(NULL, &ground->box, 1, &bound));
ERR(scad_geometry_explode(bound, NULL, &list, &count));
- ASSERT(count == 6);
-
- ground->boundary = MEM_CALLOC(allocator, count, sizeof(struct scad_geometry*));
+ ERR(darray_geometries_reserve(&ground->boundaries, count));
- for (i = 0; i < count; i++) {
+ for(i = 0; i < count; i++) {
double center[3];
size_t center_n;
double N[3];
@@ -80,33 +85,41 @@ ground_build_cad
ERR(scad_geometry_get_count(list[i], ¢er_n));
ASSERT(center_n == 1);
ERR(scad_geometry_get_centerofmass(list[i], center));
-
ERR(scad_geometry_normal(list[i], center, N, NULL, &surface));
if (N[0] == 0 && N[1] == 0 && N[2] == -1) {
ERR(scad_geometry_rename(surface, "ground_B_bottom"));
- GMV(0);
+ GPUSH(surface);
}
else if (N[0] == 0 && N[1] == 0 && N[2] == 1) {
- ERR(scad_cut_geometries("ground_B_top", &surface, 1,
- ground->footprints, ground->footprints_count, &ground->boundary[1]));
- GDEL(surface);
+ struct scad_geometry** footprints =
+ darray_geometries_data_get(&ground->footprints);
+ size_t fpcount = darray_geometries_size_get(&ground->footprints);
+ if(fpcount) {
+ ERR(scad_cut_geometries("ground_B_top", &surface, 1, footprints, fpcount,
+ &tmp));
+ GDEL(surface);
+ GPUSH(tmp);
+ } else {
+ ERR(scad_geometry_rename(surface, "ground_B_top"));
+ GPUSH(surface);
+ }
}
else if (N[0] == -1 && N[1] == 0 && N[2] == 0) {
ERR(scad_geometry_rename(surface, "ground_B_lateral_0"));
- GMV(2);
+ GPUSH(surface);
}
else if (N[0] == 1 && N[1] == 0 && N[2] == 0) {
ERR(scad_geometry_rename(surface, "ground_B_lateral_1"));
- GMV(3);
+ GPUSH(surface);
}
else if (N[0] == 0 && N[1] == -1 && N[2] == 0) {
ERR(scad_geometry_rename(surface, "ground_B_lateral_2"));
- GMV(4);
+ GPUSH(surface);
}
else if (N[0] == 0 && N[1] == 1 && N[2] == 0) {
ERR(scad_geometry_rename(surface, "ground_B_lateral_3"));
- GMV(5);
+ GPUSH(surface);
}
else FATAL("Wrong ground box boundary.");
}
@@ -117,22 +130,33 @@ exit:
}
MEM_RM(allocator, list);
GDEL(surface);
+ GDEL(tmp);
GDEL(bound);
return res;
error:
goto exit;
}
-#undef GMV
+#undef GPUSH
res_T
-ground_export_stl(const struct ground* ground, const int binary)
+ground_export_stl
+ (struct ground* ground,
+ const int binary)
{
res_T res = RES_OK;
size_t i = 0;
- for(i = 0; i < 6; i++) {
- ERR(scad_stl_export(ground->boundary[i], NULL, binary));
+ ASSERT(ground);
+
+ for(i = 0; i < darray_geometries_size_get(&ground->boundaries); i++) {
+ struct scad_geometry* b = darray_geometries_data_get(&ground->boundaries)[i];
+ /* Boundary files */
+ ERR(scad_stl_export(b, NULL, Scad_keep_normals_unchanged, binary));
+ /* Collect triangles */
+ ERR(scad_stl_get_data(b, &ground->ground_trg));
}
+ ERR(scad_stl_data_write(&ground->ground_trg, "ground_body.stl",
+ Scad_force_normals_outward, binary));
exit:
return res;
@@ -140,48 +164,25 @@ error:
goto exit;
}
-res_T
+void
ground_init
(struct mem_allocator* allocator,
- struct logger* logger,
- const size_t count,
struct ground* ground)
{
- res_T res = RES_OK;
- (void)logger;
-
ground->box = NULL;
- ground->boundary = NULL;
- ground->footprints_count = count;
- ground->footprints
- = MEM_CALLOC(allocator, ground->footprints_count, sizeof(*ground->footprints));
- if(!ground->footprints) {
- res = RES_MEM_ERR;
- goto error;
- }
-
-exit:
- return res;
-error:
- goto exit;
+ darray_double_init(allocator, &ground->ground_trg);
+ darray_geometries_init(allocator, &ground->footprints);
+ darray_geometries_init(allocator, &ground->boundaries);
}
void
ground_clear
- (struct mem_allocator* allocator,
- struct ground* ground)
+ (struct ground* ground)
{
- size_t i;
GDEL(ground->box);
- for(i = 0; i < 6; i++) {
- GDEL(ground->boundary[i]);
- }
- MEM_RM(allocator, ground->boundary);
-
- for(i = 0; i < ground->footprints_count; i++) {
- GDEL(ground->footprints[i]);
- }
- MEM_RM(allocator, ground->footprints);
+ darray_geometries_release(&ground->footprints);
+ darray_geometries_release(&ground->boundaries);
+ darray_double_release(&ground->ground_trg);
}
#undef GDEL
diff --git a/src/cg_ground.h b/src/cg_ground.h
@@ -20,7 +20,10 @@
#ifndef GROUND_H
#define GROUND_H
+#include "cg_types.h"
+
#include <rsys/rsys.h>
+#include <rsys/dynamic_array_double.h>
struct city;
struct scad_geometry;
@@ -30,33 +33,28 @@ struct logger;
struct ground {
/* cad representation */
struct scad_geometry* box;
- struct scad_geometry** boundary;
- struct scad_geometry** footprints; /* list of building footprint */
- size_t footprints_count; /* number of footprint */
+ struct darray_geometries boundaries;
+ struct darray_geometries footprints;
+ struct darray_double ground_trg;
};
-#define GROUND_NULL__ {NULL, NULL, NULL, 0}
-static const struct ground GROUND_NULL = GROUND_NULL__;
-
res_T
ground_build_cad
(struct mem_allocator* allocator,
- struct city* city,
- struct ground* ground);
+ struct city* city);
res_T
-ground_export_stl(const struct ground* ground, const int binary);
+ground_export_stl
+ (struct ground* ground,
+ const int binary);
-res_T
+void
ground_init
(struct mem_allocator* allocator,
- struct logger* logger,
- const size_t count,
struct ground* ground);
void
ground_clear
- (struct mem_allocator* allocator,
- struct ground* ground);
+ (struct ground* ground);
#endif /* GROUND */
diff --git a/src/cg_main.c b/src/cg_main.c
@@ -24,12 +24,11 @@
#include "cg_city_parsing.h"
#include "cg_catalog.h"
#include "cg_catalog_parsing.h"
-#include "cg_construction_mode_0_parsing_schemas.h"
-#include "cg_construction_mode_1_parsing_schemas.h"
#include <cyaml/cyaml.h>
#include <rsys/rsys.h>
+#include <rsys/clock_time.h>
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
#include <star/scad.h>
@@ -102,7 +101,10 @@ int main
.log_level = CYAML_LOG_WARNING, /* Logging errors and warnings only. */
.flags = CYAML_CFG_DEFAULT,
};
+ struct time t0, dt;
+ char buf[128];
+ time_current(&t0);
/* init allocator and logger */
ERR(mem_init_proxy_allocator(&allocator, &mem_default_allocator));
allocator_initialized = 1;
@@ -166,8 +168,13 @@ int main
exit:
release_city(city);
release_catalog(catalog);
- if(logger_initialized) logger_release(&logger);
if(args) release_args(args);
+ time_sub(&dt, time_current(&dt), &t0);
+ time_dump(&dt, TIME_MIN | TIME_SEC, NULL, buf, sizeof(buf));
+ if(logger_initialized) {
+ logger_print(&logger, LOG_OUTPUT, "Total run time: %s.\n", buf);
+ logger_release(&logger);
+ }
if(allocator_initialized) {
if(check_memory_allocator(&allocator)) err = EXIT_FAILURE;
mem_shutdown_proxy_allocator(&allocator);
@@ -180,7 +187,7 @@ error:
err = EXIT_FAILURE;
if(logger_initialized) {
logger_print(&logger, LOG_ERROR, "City generator failed.\n");
- if(!city->keep_running_on_errors)
+ if(city && !city->keep_running_on_errors)
logger_print(&logger, LOG_ERROR, "Try to re-run with option -k.\n");
}
goto exit;
diff --git a/src/cg_types.c b/src/cg_types.c
@@ -0,0 +1,39 @@
+/* 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_types.h"
+
+#include <rsys/rsys.h>
+#include <star/scad.h>
+
+void
+pgeom_release(struct scad_geometry** data) {
+ ASSERT(data);
+ SCAD(geometry_ref_put(*data));
+}
+
+res_T
+pgeom_copy(struct scad_geometry** dst, struct scad_geometry* const* src) {
+ ASSERT(dst && src);
+ *dst = *src;
+ SCAD(geometry_ref_get(*src));
+ return RES_OK;
+}
+
+
diff --git a/src/cg_types.h b/src/cg_types.h
@@ -0,0 +1,48 @@
+/* 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 TYPES_H
+#define TYPES_H
+
+#include <rsys/rsys.h>
+#include <rsys/dynamic_array_double.h>
+
+struct scad_geometry;
+
+void
+pgeom_release(struct scad_geometry** data);
+res_T
+pgeom_copy(struct scad_geometry** dst, struct scad_geometry* const* src);
+static FINLINE res_T
+pgeom_copy_and_release
+ (struct scad_geometry** dst, struct scad_geometry* const* src)
+{
+ ASSERT(dst && src);
+ *dst = *src;
+ return RES_OK;
+}
+#define DARRAY_NAME geometries
+#define DARRAY_DATA struct scad_geometry*
+#define DARRAY_INIT adjoining_data_init
+#define DARRAY_FUNCTOR_RELEASE pgeom_release
+#define DARRAY_FUNCTOR_COPY pgeom_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE pgeom_copy_and_release
+#include <rsys/dynamic_array.h>
+
+#endif /* TYPES */