Program Listing for File fast_shadow.cpp#
↰ Return to documentation for file (src/modules/fast_shadow.cpp)
//
// Canadian Hydrological Model - The Canadian Hydrological Model (CHM) is a novel
// modular unstructured mesh based approach for hydrological modelling
// Copyright (C) 2018 Christopher Marsh
//
// This file is part of Canadian Hydrological Model.
//
// Canadian Hydrological Model 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.
//
// Canadian Hydrological Model 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 Canadian Hydrological Model. If not, see
// <http://www.gnu.org/licenses/>.
//
#include "fast_shadow.hpp"
REGISTER_MODULE_CPP(fast_shadow);
fast_shadow::fast_shadow(config_file cfg)
: module_base("fast_shadow", parallel::data, cfg)
{
depends("solar_az");
depends("solar_el");
provides("shadow");
//number of steps along the search vector to check for a higher point
steps = cfg.get("steps",10);
//max distance to search
max_distance = cfg.get("max_distance",1000.0);
//size of the step to take
size_of_step = max_distance / steps;
}
fast_shadow::~fast_shadow()
{
}
void fast_shadow::run(mesh_elem& face)
{
double solar_el = (*face)["solar_el"_s] *M_PI / 180.;
(*face)["shadow"_s]= 0;
//bail early
if (solar_el < 0)
return;
double solar_az = (*face)["solar_az"_s] ;
Point_3 me = face->center();
double phi = 0.;
// search along each azimuth in j step increments to find horizon angle
for (int j = 1; j <= steps; ++j)
{
double distance = j * size_of_step;
auto f = face->find_closest_face(solar_az, distance);
double z_diff = f->center().z() - me.z() ;
if (z_diff > 0)
{
double dist = math::gis::distance(f->center(), me);
phi = std::max(atan(z_diff / dist), phi);
}
//try to bail early if possible
if (phi > solar_el )
{
(*face)["shadow"_s]= 1;
}
}
//try to bail early if possible
if (phi > solar_el )
{
(*face)["shadow"_s]= 1;
}
}