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_construction_mode.c (4380B)


      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_default.h"
     22 #include "cg_building.h"
     23 #include "cg_city.h"
     24 #include "cg_city_parsing_schemas.h"
     25 #include "cg_construction_mode.h"
     26 
     27 #include <rsys/rsys.h>
     28 #include <rsys/str.h>
     29 #include <rsys/logger.h>
     30 #include <rsys/double2.h>
     31 
     32 #include <star/scad.h>
     33 #include <star/scpr.h>
     34 
     35 void
     36 get_nverts(const size_t icomp, size_t* nverts, void* context)
     37 {
     38   struct parsed_city_building* parsed_data = context;
     39   ASSERT(icomp == 0); (void)icomp;
     40   *nverts = parsed_data->vertice_count;
     41 }
     42 
     43 void
     44 get_pos(const size_t icomp, const size_t ivert, double pos[2], void* context)
     45 {
     46   struct parsed_city_building* parsed_data = context;
     47   ASSERT(icomp == 0); (void)icomp;
     48   pos[0] = parsed_data->vertice[ivert*2 + 0];
     49   pos[1] = parsed_data->vertice[ivert*2 + 1];
     50 }
     51 
     52 res_T
     53 init_building_base
     54   (struct building* building,
     55    struct city* city,
     56    struct parsed_city_building* parsed_data)
     57 {
     58   int inside, cw;
     59   size_t count;
     60   double l[2], u[2], t[2];
     61   res_T res = RES_OK;
     62 
     63   ASSERT(city && building && parsed_data);
     64 
     65   building->city = city;
     66   str_init(city->allocator, &building->name);
     67   str_init(city->allocator, &building->dataset_name);
     68   str_init(city->allocator, &building->external_layer_name);
     69   htable_building_init(city->allocator, &building->close_buildings);
     70   darray_double_init(city->allocator, &building->levels_height);
     71   building->structs_initialized = 1;
     72 
     73   ERR(str_set(&building->name, parsed_data->name));
     74   ERR(str_set(&building->dataset_name, parsed_data->dataset_name));
     75   ERR(scpr_polygon_create(city->scpr, &building->pg));
     76   ERR(scpr_polygon_setup_indexed_vertices(building->pg, 1, get_nverts, get_pos,
     77         parsed_data));
     78   ERR(scpr_polygon_get_vertices_count(building->pg, 0, &count));
     79   if(parsed_data->vertice_count != count) {
     80     logger_print(city->logger, LOG_WARNING,
     81         "Building '%s' had quasi-identical or aligned vertices that have been removed.\n",
     82         str_cget(&building->name));
     83   }
     84   /* First try with a slightly decreased bbox as buildings are not allowed to
     85    * reach the bbox limit */
     86   d2(t, CG2_MIN_DISTANCE_TO_MAP_LIMITS, CG2_MIN_DISTANCE_TO_MAP_LIMITS);
     87   d2_add(l, city->lower, t);
     88   d2_sub(u, city->upper, t);
     89   ERR(scpr_polygon_in_bbox(building->pg, l, u, &inside));
     90   if(!inside) {
     91     ERR(scpr_polygon_in_bbox(building->pg, city->lower, city->upper, &inside));
     92     logger_print(city->logger,
     93         (city->keep_running_on_errors ? LOG_WARNING : LOG_ERROR),
     94         (inside
     95          ? "Building '%s' is too close to the map limits.\n"
     96          : "Building '%s' is out of the ground extent.\n"),
     97         str_cget(&building->name));
     98     building->event_flags
     99       |= (inside ? BUILDING_TOO_CLOSE_TO_BORDER : BUILDING_OUT_OF_GROUND_EXTENT);
    100     res = RES_BAD_ARG;
    101     goto error;
    102   }
    103   /* Force orientation so that pg's normal is upward */
    104   ERR(scpr_polygon_is_component_cw(building->pg, 0, &cw));
    105   if(!cw) {
    106     ERR(scpr_polygon_reverse_component(building->pg, 0));
    107   }
    108 
    109 exit:
    110   return res;
    111 error:
    112   goto exit;
    113 }
    114 
    115 res_T
    116 release_building_base
    117   (struct building* building)
    118 {
    119   res_T res = RES_OK;
    120 
    121   ASSERT(building);
    122 
    123   if(building->structs_initialized) {
    124     str_release(&building->name);
    125     str_release(&building->dataset_name);
    126     str_release(&building->external_layer_name);
    127     htable_building_release(&building->close_buildings);
    128     darray_double_release(&building->levels_height);
    129   }
    130   if(building->pg) {
    131     ERR(scpr_polygon_ref_put(building->pg));
    132   }
    133 
    134 exit:
    135   return res;
    136 error:
    137   goto exit;
    138 }