File config_input.hpp
File List > config_input > config_input.hpp
Go to the documentation of this file
#pragma once
#include <cmath>
#include <iostream>
#include <optional>
#include <set>
#include <vector>
#include "isom/colors.hpp"
#include "utilities/filesystem.hpp"
#include "utilities/resources.hpp"
struct GridConfig {
double bin_resolution;
unsigned int downsample_factor;
};
#define SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \
template <typename BasicJsonType> \
inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) { \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool { \
return ej_pair.first == e; \
}); \
if (it == std::end(m)) throw std::invalid_argument("unknown enum value"); \
j = it->second; \
} \
template <typename BasicJsonType> \
inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) { \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool { \
return ej_pair.second == j; \
}); \
if (it == std::end(m)) throw std::invalid_argument("unknown json value: " + std::string(j)); \
e = it->first; \
}
struct GroundConfig {
double outlier_removal_height_diff;
int min_ground_intensity;
int max_ground_intensity;
};
struct ContourConfig {
double interval;
unsigned int min_points;
ColorVariant color;
double width;
};
struct CanopyConfig {
double min_height;
double max_height;
double blocking_threshold;
};
struct BlockingThresholdColorPair {
double blocking_threshold;
ColorVariant color;
};
struct VegeHeightConfig {
std::string name;
double min_height;
double max_height;
std::vector<BlockingThresholdColorPair> colors;
std::optional<ColorVariant> pick_from_blocked_proportion(double bp) const {
std::optional<ColorVariant> color;
for (const BlockingThresholdColorPair& btc : colors) {
if (bp >= btc.blocking_threshold) {
color = btc.color;
}
}
return color;
}
};
struct VegeConfig {
ColorVariant background_color;
std::vector<VegeHeightConfig> height_configs;
};
struct RenderConfig {
double scale;
double dpi;
};
struct WaterConfig {
double catchment;
ColorVariant color;
double width;
};
struct WaterConfigs {
std::map<std::string, WaterConfig> configs;
const WaterConfig& config_from_catchment(double catchment) const {
const WaterConfig* max_valid_config = nullptr;
for (const auto& [_, config] : configs) {
if (config.catchment <= catchment &&
(max_valid_config == nullptr || config.catchment > max_valid_config->catchment))
max_valid_config = &config;
}
return *max_valid_config;
}
double minimum_catchment() const {
double min_catchment = std::numeric_limits<double>::max();
for (const auto& [_, config] : configs) {
min_catchment = std::min(config.catchment, min_catchment);
}
return min_catchment;
}
};
struct ContourConfigs {
std::map<std::string, ContourConfig> configs;
double min_interval;
static double minimum_interval(const std::map<std::string, ContourConfig>& configs) {
double min_interval = std::numeric_limits<double>::max();
for (const auto& [_, config] : configs) {
min_interval = std::min(min_interval, config.interval);
}
return min_interval;
}
ContourConfigs() : min_interval(std::numeric_limits<double>::max()) {}
explicit ContourConfigs(std::map<std::string, ContourConfig> in_configs)
: configs(std::move(in_configs)), min_interval(minimum_interval(configs)) {}
const ContourConfig& operator[](const std::string& key) const { return configs.at(key); }
const ContourConfig& pick_from_height(double height) const {
auto max_valid_interval = std::numeric_limits<double>::min();
const ContourConfig* config_to_return = nullptr;
for (const auto& [_, config] : configs) {
if (config.interval > max_valid_interval &&
std::fmod(std::abs(height), config.interval) < 1e-8) {
max_valid_interval = config.interval;
config_to_return = &config;
}
}
return *config_to_return;
}
std::string layer_name_from_height(double height) const {
auto max_valid_interval = std::numeric_limits<double>::min();
std::string layer_name = "Contour";
for (const auto& [name, config] : configs) {
if (config.interval > max_valid_interval &&
std::fmod(std::abs(height), config.interval) < 1e-8) {
if (name == "form_line") {
layer_name = "103_Form_Line";
} else if (name == "index") {
layer_name = "102_Index_Contour";
} else if (name == "normal") {
layer_name = "101_Contour";
}
max_valid_interval = config.interval;
}
}
return layer_name;
}
};
struct BuildingsConfig {
ColorVariant color;
};
enum class ProcessingStep {
Tiles,
Combine,
};
std::ostream& operator<<(std::ostream& os, const ProcessingStep& step);
struct Config {
GridConfig grid;
GroundConfig ground;
ContourConfigs contours;
WaterConfigs water;
VegeConfig vege;
RenderConfig render;
BuildingsConfig buildings;
std::vector<fs::path> las_files;
std::set<ProcessingStep> processing_steps;
fs::path output_directory;
double border_width;
fs::path relative_path_to_config;
void set_output_directory(const fs::path& output_dir) { output_directory = output_dir; }
fs::path output_path() const {
if (output_directory.is_absolute()) {
return output_directory;
}
return relative_path_to_config / output_directory;
}
std::vector<fs::path> las_filepaths() const {
std::vector<fs::path> las_filepaths;
for (const fs::path& las_file : las_files) {
if (las_file.is_absolute()) {
las_filepaths.push_back(las_file);
} else {
las_filepaths.push_back(relative_path_to_config / las_file);
}
}
return las_filepaths;
}
std::vector<fs::path> get_las_files(const fs::path& las_path) const {
std::vector<fs::path> file_list;
fs::path actual_path = las_path.is_absolute() ? las_path : relative_path_to_config / las_path;
if (fs::exists(actual_path)) {
if (fs::is_directory(actual_path)) {
for (const fs::directory_entry& entry : fs::directory_iterator(actual_path)) {
if (entry.path().extension() == ".las" || entry.path().extension() == ".laz") {
file_list.push_back(entry.path());
}
}
} else if (actual_path.extension() == ".las" || actual_path.extension() == ".laz") {
file_list.push_back(actual_path);
}
}
return file_list;
}
static Config FromFile(const fs::path& filename);
void write_to_file(const fs::path& filename) const;
static Config Default() { return FromFile(AssetRetriever::get_asset("default_config.json")); }
Config& operator=(const Config& config) = default;
Config(const Config& config) = delete;
Config(Config&& config) = default;
Config() = default;
friend std::ostream& operator<<(std::ostream& os, const Config& config);
};