city_generator2

Generated conformal 3D meshes representing a city
git clone git://git.meso-star.fr/city_generator2.git
Log | Files | Refs | README | LICENSE

cg_building.c (5168B)


      1 /* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA
      2  * Copyright (C) 2022 CNRS
      3  * Copyright (C) 2022 Sorbonne Université
      4  * Copyright (C) 2022 Université Paul Sabatier
      5  * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
      6  *
      7  * This program is free software: you can redistribute it and/or modify
      8  * it under the terms of the GNU General Public License as published by
      9  * the Free Software Foundation, either version 3 of the License, or
     10  * (at your option) any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     15  * GNU General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU General Public License
     18  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     19 
     20 #include "cg.h"
     21 #include "cg_city.h"
     22 #include "cg_building.h"
     23 
     24 #include <rsys/str.h>
     25 #include <rsys/mem_allocator.h>
     26 #include <rsys/logger.h>
     27 
     28 #include <star/scad.h>
     29 
     30 void
     31 adjoining_data_release(struct adjoining_data* data)
     32 {
     33   ASSERT(data);
     34   if(data->envelop) {
     35     SCAD(geometry_ref_put(data->envelop));
     36     data->envelop = NULL;
     37   }
     38   if(data->common_geometry) {
     39     SCAD(geometry_ref_put(data->common_geometry));
     40     data->common_geometry = NULL;
     41   }
     42 }
     43 
     44 res_T
     45 adjoining_data_copy
     46   (struct adjoining_data* dst, const struct adjoining_data* src)
     47 {
     48   ASSERT(dst && src);
     49   dst->adjoining_building = src->adjoining_building;
     50   dst->main_building = src->main_building;
     51   dst->common_geometry = src->common_geometry;
     52   if(dst->common_geometry) SCAD(geometry_ref_get(dst->common_geometry));
     53   dst->envelop = src->envelop;
     54   if(dst->envelop) SCAD(geometry_ref_get(dst->envelop));
     55   dst->save = src->save;
     56   return RES_OK;
     57 }
     58 
     59 res_T
     60 adjoining_data_copy_and_release
     61   (struct adjoining_data* dst, const struct adjoining_data* src)
     62 {
     63   ASSERT(dst && src);
     64   dst->adjoining_building = src->adjoining_building;
     65   dst->main_building = src->main_building;
     66   dst->common_geometry = src->common_geometry;
     67   dst->envelop = src->envelop;
     68   dst->save = src->save;
     69   return RES_OK;
     70 }
     71 
     72 void get_position_pg
     73   (const size_t ivert, double pos[2], void* ctx)
     74 {
     75   struct scpr_polygon* pg = ctx;
     76   ASSERT(pos && pg);
     77   CHK(scpr_polygon_get_position(pg, 0, ivert, pos) == RES_OK);
     78 }
     79 
     80 res_T
     81 build_envelop
     82   (struct building* building,
     83    struct scad_geometry** envelop)
     84 {
     85   res_T res = RES_OK;
     86   size_t nverts = 0;
     87   double height = building->total_height;
     88   double d[3] = {0, 0, 0};
     89   struct scpr_polygon* pg = building->pg;
     90   struct scad_geometry* footprint = NULL;
     91   struct str name;
     92 
     93   str_init(building->city->allocator, &name);
     94 
     95   ERR(scpr_polygon_get_vertices_count(pg, 0, &nverts));
     96   ERR(scad_add_polygon(NULL, get_position_pg, pg, 0, nverts, &footprint));
     97 
     98   /* wall envelop */
     99   d[2] = height;
    100   ERR(str_printf(&name, "%s_envelop", str_cget(&building->name)));
    101   ERR(scad_geometry_extrude(footprint, str_cget(&name), d, envelop));
    102 
    103 exit:
    104   str_release(&name);
    105   if (footprint) SCAD(geometry_ref_put(footprint));
    106   return res;
    107 error:
    108   goto exit;
    109 }
    110 
    111 res_T
    112 build_adjoining
    113   (struct building* building,
    114    const int silent,
    115    struct darray_geometries* current_cad,
    116    struct darray_adjoining_data* adjoining)
    117 {
    118   res_T res = RES_OK;
    119   size_t count, prev, i = 0;
    120   struct htable_building_iterator it, end;
    121   struct htable_building* close_buildings;
    122   struct str msg;
    123   struct mem_allocator* allocator;
    124   struct logger* logger;
    125 
    126   ASSERT(building && current_cad && adjoining);
    127 
    128   allocator = building->city->allocator;
    129   logger = building->city->logger;
    130   close_buildings = &building->close_buildings;
    131   count = htable_building_size_get(close_buildings);
    132 
    133   if(!silent) {
    134     str_init(allocator, &msg);
    135     ERR(str_printf(&msg,
    136           "Building '%s' considering close neighbor(s) when creating CAD:",
    137           str_cget(&building->name)));
    138   }
    139 
    140   /* iterate over adjoining building */
    141   htable_building_begin(close_buildings, &it);
    142   htable_building_end(close_buildings, &end);
    143   prev = darray_adjoining_data_size_get(adjoining);
    144   ERR(darray_adjoining_data_reserve(adjoining, prev + count));
    145   while(!htable_building_iterator_eq(&it, &end)) {
    146     struct building* close_building = *htable_building_iterator_key_get(&it);
    147     struct adjoining_data adj;
    148     htable_building_iterator_next(&it);
    149     if(close_building->event_flags & BUILDING_REMOVED_EARLY)
    150       continue;
    151     adjoining_data_init(allocator, &adj);
    152     ERR(build_envelop(close_building, &adj.envelop));
    153     ERR(darray_geometries_push_back(current_cad, &adj.envelop));
    154     ERR(scad_geometry_ref_put(adj.envelop)); /* Ownership transfer */
    155     adj.main_building = building;
    156     adj.adjoining_building = close_building;
    157     if(!silent) {
    158       ERR(str_append_printf(&msg, (i ? ", '%s'" : " '%s'"),
    159             str_cget(&close_building->name)));
    160     }
    161     ERR(darray_adjoining_data_push_back(adjoining, &adj));
    162     i++;
    163   }
    164 
    165   if(!silent) {
    166     logger_print(logger, LOG_OUTPUT, "%s.\n", str_cget(&msg));
    167   }
    168 
    169 exit:
    170   if(!silent) str_release(&msg);
    171   return res;
    172 error:
    173   darray_adjoining_data_clear(adjoining);
    174   goto exit;
    175 }