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_main.c (6569B)


      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_args.h"
     22 #include "cg_building.h"
     23 #include "cg_city.h"
     24 #include "cg_city_parsing.h"
     25 #include "cg_catalog.h"
     26 #include "cg_catalog_parsing.h"
     27 #include "cg_vertex_denoiser.h"
     28 #include "cg_cyaml.h"
     29 
     30 #include <rsys/rsys.h>
     31 #include <rsys/clock_time.h>
     32 #include <rsys/logger.h>
     33 #include <rsys/mem_allocator.h>
     34 #include <star/scad.h>
     35 
     36 static int
     37 check_memory_allocator(struct mem_allocator* allocator) {
     38   if(MEM_ALLOCATED_SIZE(allocator)) {
     39     char dump[4096];
     40     MEM_DUMP(allocator, dump, sizeof(dump)/sizeof(char));
     41     fprintf(stderr, "%s\n", dump);
     42     fprintf(stderr, "Memory leaks.\n");
     43     return 1;
     44   }
     45   return 0;
     46 }
     47 
     48 static void cg_log
     49   (enum cyaml_log_e level,
     50    void *_ctx,
     51    const char *fmt,
     52    va_list args)
     53 {
     54   struct logger* logger = (struct logger*)_ctx;
     55   enum log_type type;
     56   ASSERT(logger && fmt);
     57 
     58   switch(level) {
     59     case CYAML_LOG_ERROR: type = LOG_ERROR; break;
     60     case CYAML_LOG_WARNING: type = LOG_WARNING; break;
     61     case CYAML_LOG_NOTICE: type = LOG_OUTPUT; break;
     62     default: return; /* Do not log this level of messages */
     63   }
     64   logger_vprint(logger, type, fmt, args);
     65 }
     66 
     67 static void* cg_mem
     68   (void *ctx,
     69    void *ptr,
     70    size_t size)
     71 {
     72   struct mem_allocator* allocator = (struct mem_allocator*)ctx;
     73   ASSERT(allocator);
     74   if(size == 0) {
     75     /* free() request */
     76     MEM_RM(allocator, ptr);
     77     return NULL;
     78   } else {
     79     return MEM_REALLOC(allocator, ptr, size);
     80   }
     81 }
     82 
     83 int main
     84   (int argc, char** argv)
     85 {
     86   int err = EXIT_SUCCESS;
     87   res_T res = RES_OK;
     88   struct args* args = NULL;
     89   struct city* city = NULL;
     90   struct logger logger;
     91   struct mem_allocator allocator;
     92   struct parsed_city* parsed_city = NULL;
     93   struct parsed_catalog* parsed_catalog = NULL;
     94   struct catalog* catalog = NULL;
     95   int logger_initialized = 0, allocator_initialized = 0;
     96   const struct cyaml_config config = {
     97     .log_fn = cg_log,
     98     .log_ctx = &logger,
     99     .mem_fn = cg_mem,
    100     .mem_ctx = &allocator,
    101     .log_level = CYAML_LOG_WARNING, /* Logging errors and warnings only. */
    102     .flags = CYAML_CFG_DEFAULT,
    103   };
    104   struct time t0, dt;
    105   char buf[128];
    106 
    107   time_current(&t0);
    108   /* init allocator and logger */
    109   ERR(mem_init_proxy_allocator(&allocator, &mem_default_allocator));
    110   allocator_initialized = 1;
    111   ERR(logger_init(&allocator, &logger));
    112   logger_initialized = 1;
    113 
    114   /* Active logging for args parsing */
    115   logger_set_stream(&logger, LOG_OUTPUT, log_prt_fn, NULL);
    116   logger_set_stream(&logger, LOG_WARNING, log_warn_fn, NULL);
    117   logger_set_stream(&logger, LOG_ERROR, log_err_fn, NULL);
    118 
    119   /* parse command line */
    120   ERR(parse_args(&allocator, &logger, argc, argv, &args));
    121   if(args->print_help) {
    122     short_help();
    123     goto exit;
    124   }
    125   else if(args->print_version) {
    126     print_version();
    127     goto exit;
    128   }
    129 
    130   /* Deactivate some logging according to the -V arg */
    131   if(args->verbosity_level < 1)
    132     logger_set_stream(&logger, LOG_ERROR, NULL, NULL);
    133   if(args->verbosity_level < 2)
    134     logger_set_stream(&logger, LOG_WARNING, NULL, NULL);
    135   if(args->verbosity_level < 3)
    136     logger_set_stream(&logger, LOG_OUTPUT, NULL, NULL);
    137 
    138 #ifndef NDEBUG
    139   if(args->verbosity_level == 3) {
    140     logger_print(&logger, LOG_WARNING,
    141         "Running debug binary with increased verbosity.\n");
    142   } else {
    143     logger_print(&logger, LOG_WARNING,
    144         "Running debug binary.\n");
    145   }
    146 #endif
    147 
    148   /* Parse catalog.
    149    * No semantic validation is done at this stage */
    150   ERR(parse_catalog(&args->catalog_files, &allocator, &logger, &config,
    151         &parsed_catalog));
    152 
    153   /* Create catalog from parsed data.
    154    * Semantic validation is done along the process as well as the emission of
    155    * informative logs */
    156   ERR(create_catalog(&allocator, &logger, parsed_catalog, &catalog));
    157   release_parsed_catalog(&config, parsed_catalog);
    158   parsed_catalog = NULL;
    159 
    160   /* Parse city description.
    161    * No semantic validation is done at this stage */
    162   ERR(parse_city(args->city_filename, &allocator, &logger, &config, &parsed_city));
    163 
    164   /* Create city with parsed data.
    165    * Semantic validation is done along the process as well as the emission of
    166    * informative logs */
    167   ERR(create_city(&allocator, &logger, args, parsed_city, catalog, &city));
    168   release_parsed_city(&config, parsed_city);
    169   parsed_city = NULL;
    170   release_args(args);
    171   args = NULL;
    172 
    173   ERR(city_cad_build(city));
    174   /* As buildings can be removed at the CAD generation step, ground CAD must be
    175    * generated after buildings CAD */
    176   ERR(city_ground_build(city));
    177 
    178 exit:
    179   if(logger_initialized && city) {
    180     size_t count, denoised_count;
    181     count = vertex_denoiser_get_count(city->denoiser);
    182     denoised_count = vertex_denoiser_get_denoised_count(city->denoiser);
    183     if(denoised_count > 0) {
    184       logger_print(&logger, LOG_OUTPUT, "Denoised %lu / %lu vertices.\n",
    185           denoised_count, count);
    186     }
    187     time_sub(&dt, time_current(&dt), &t0);
    188     time_dump(&dt, TIME_MIN | TIME_SEC, NULL, buf, sizeof(buf));
    189     logger_print(&logger, LOG_OUTPUT, "Total run time: %s.\n", buf);
    190   }
    191   release_city(city);
    192   release_catalog(catalog);
    193   if(args) release_args(args);
    194   if(logger_initialized) logger_release(&logger);
    195   if(allocator_initialized) {
    196     if(check_memory_allocator(&allocator)) err = EXIT_FAILURE;
    197     mem_shutdown_proxy_allocator(&allocator);
    198     CHK(mem_allocated_size() == 0);
    199   }
    200   return err;
    201 error:
    202   release_parsed_catalog(&config, parsed_catalog);
    203   release_parsed_city(&config, parsed_city);
    204   err = EXIT_FAILURE;
    205   if(logger_initialized) {
    206     logger_print(&logger, LOG_ERROR, "City generator failed.\n");
    207     if(city && !city->keep_running_on_errors)
    208       logger_print(&logger, LOG_ERROR, "Try to re-run with option -k.\n");
    209   }
    210   goto exit;
    211 }