htrdr

Solving radiative transfer in heterogeneous media
git clone git://git.meso-star.fr/htrdr.git
Log | Files | Refs | README | LICENSE

commit 162882802f54460443f96134e4be8a49d90b2f2c
parent 6325d4c369e5535ded7ba03319d2519e6c55699d
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 27 Oct 2022 16:15:17 +0200

htrdr-planeto: implement a source's API

Diffstat:
Mcmake/planeto/CMakeLists.txt | 6++++--
Msrc/atmosphere/htrdr_atmosphere_sun.c | 1+
Msrc/planeto/htrdr_planeto_args.c | 46+++++++++++++++++++++++-----------------------
Msrc/planeto/htrdr_planeto_args.h | 4++++
Msrc/planeto/htrdr_planeto_c.h | 2++
Asrc/planeto/htrdr_planeto_source.c | 178+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/planeto/htrdr_planeto_source.h | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 275 insertions(+), 25 deletions(-)

diff --git a/cmake/planeto/CMakeLists.txt b/cmake/planeto/CMakeLists.txt @@ -53,12 +53,14 @@ include_directories( set(HTRDR_PLANETO_FILES_SRC htrdr_planeto.c htrdr_planeto_args.c - htrdr_planeto_main.c) + htrdr_planeto_main.c + htrdr_planeto_source.c) set(HTRDR_PLANETO_FILES_INC htrdr_planeto.h htrdr_planeto_c.h - htrdr_planeto_args.h) + htrdr_planeto_args.h + htrdr_planeto_source.h) # Prepend each file in the `HTRDR_FILES_<SRC|INC>' list by `HTRDR_SOURCE_DIR' rcmake_prepend_path(HTRDR_PLANETO_FILES_SRC ${HTRDR_SOURCE_DIR}/planeto) diff --git a/src/atmosphere/htrdr_atmosphere_sun.c b/src/atmosphere/htrdr_atmosphere_sun.c @@ -74,6 +74,7 @@ htrdr_atmosphere_sun_create goto error; } ref_init(&sun->ref); + sun->half_angle = 4.6524e-3; sun->temperature = 5778; sun->cos_half_angle = cos(sun->half_angle); diff --git a/src/planeto/htrdr_planeto_args.c b/src/planeto/htrdr_planeto_args.c @@ -73,27 +73,6 @@ check_ground_args(const struct htrdr_planeto_ground_args* args) } static INLINE res_T -check_source_args(const struct htrdr_planeto_source_args* args) -{ - if(!args) return RES_BAD_ARG; - - /* Invalid position */ - if(args->latitude <-90 - || args->latitude > 90 - || args->longitude <-180 - || args->longitude > 180 - || args->distance < 0) - return RES_BAD_ARG; - - /* Miscellaneous parameters */ - if(args->radius < 0 - || args->temperature < 0) - return RES_BAD_ARG; - - return RES_OK; -} - -static INLINE res_T check_spectral_args(const struct htrdr_args_spectral* spectral_domain) { if(!spectral_domain) return RES_BAD_ARG; @@ -572,7 +551,7 @@ htrdr_planeto_args_init(struct htrdr_planeto_args* args, int argc, char** argv) fprintf(stderr, "Missing ground definition -- option '-G'\n"); goto error; } - res = check_source_args(&args->source); + res = htrdr_planeto_source_args_check(&args->source); if(res != RES_OK) { fprintf(stderr, "Missing source definition -- option '-S'\n"); goto error; @@ -644,7 +623,7 @@ htrdr_planeto_args_check(const struct htrdr_planeto_args* args) if(res != RES_OK) return res; /* Check the source */ - res = check_source_args(&args->source); + res = htrdr_planeto_source_args_check(&args->source); if(res != RES_OK) return res; /* Check miscalleneous parameters */ @@ -654,3 +633,24 @@ htrdr_planeto_args_check(const struct htrdr_planeto_args* args) return RES_OK; } + +res_T +htrdr_planeto_source_args_check(const struct htrdr_planeto_source_args* args) +{ + if(!args) return RES_BAD_ARG; + + /* Invalid position */ + if(args->latitude <-90 + || args->latitude > 90 + || args->longitude <-180 + || args->longitude > 180 + || args->distance < 0) + return RES_BAD_ARG; + + /* Miscellaneous parameters */ + if(args->radius < 0 + || args->temperature < 0) + return RES_BAD_ARG; + + return RES_OK; +} diff --git a/src/planeto/htrdr_planeto_args.h b/src/planeto/htrdr_planeto_args.h @@ -115,4 +115,8 @@ extern LOCAL_SYM res_T htrdr_planeto_args_check (const struct htrdr_planeto_args* args); +extern LOCAL_SYM res_T +htrdr_planeto_source_args_check + (const struct htrdr_planeto_source_args* args); + #endif /* HTRDR_PLANETO_ARGS_H */ diff --git a/src/planeto/htrdr_planeto_c.h b/src/planeto/htrdr_planeto_c.h @@ -18,6 +18,8 @@ #ifndef HTRDR_PLANETO_C_H #define HTRDR_PLANETO_C_H +#include "planeto/htrdr_planeto_args.h" + #include "core/htrdr_args.h" #include <rsys/ref_count.h> diff --git a/src/planeto/htrdr_planeto_source.c b/src/planeto/htrdr_planeto_source.c @@ -0,0 +1,178 @@ +/* Copyright (C) 2018, 2019, 2020, 2021 |Meso|Star> (contact@meso-star.com) + * Copyright (C) 2018, 2019, 2021 CNRS + * Copyright (C) 2018, 2019, Université Paul Sabatier + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "planeto/htrdr_planeto_c.h" +#include "planeto/htrdr_planeto_source.h" + +#include "core/htrdr.h" +#include "core/htrdr_log.h" + +#include <star/ssp.h> + +#include <rsys/double3.h> +#include <rsys/ref_count.h> + +struct htrdr_planeto_source { + double position[3]; /* In m */ + + double radius; /* In m */ + double temperature; /* In Kelvin */ + + ref_T ref; + struct htrdr* htrdr; +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +release_source(ref_T* ref) +{ + struct htrdr_planeto_source* source; + struct htrdr* htrdr; + ASSERT(ref); + + source = CONTAINER_OF(ref, struct htrdr_planeto_source, ref); + htrdr = source->htrdr; + MEM_RM(htrdr_get_allocator(htrdr), source); + htrdr_ref_put(htrdr); +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +htrdr_planeto_source_create + (struct htrdr_planeto* cmd, + const struct htrdr_planeto_source_args* args, + struct htrdr_planeto_source** out_source) +{ + struct htrdr_planeto_source* src = NULL; + double dst; /* In m */ + double lat; /* In radians */ + double lon; /* In radians */ + res_T res = RES_OK; + ASSERT(cmd && out_source); + ASSERT(htrdr_planeto_source_args_check(args) == RES_OK); + + src = MEM_CALLOC(htrdr_get_allocator(cmd->htrdr), 1, sizeof(*src)); + if(!src) { + htrdr_log_err(cmd->htrdr, "error allocating source\n"); + res = RES_MEM_ERR; + goto error; + } + ref_init(&src->ref); + htrdr_ref_get(cmd->htrdr); + src->htrdr = cmd->htrdr; + src->radius = args->radius * 1e3/*From km to m*/; + src->temperature = args->temperature; + + /* Convert latitude and longitude to radians and distance in m */ + lat = MDEG2RAD(args->latitude); + lon = MDEG2RAD(args->longitude); + dst = args->distance * 1e3/*From km to m*/; + + /* Compute the position of the source */ + src->position[0] = dst * cos(lat) * cos(lon); + src->position[1] = dst * cos(lat) * sin(lon); + src->position[2] = dst * sin(lat); + +exit: + *out_source = src; + return res; +error: + if(src) { htrdr_planeto_source_ref_put(src); src = NULL; } + goto exit; +} + +void +htrdr_planeto_source_ref_get(struct htrdr_planeto_source* source) +{ + ASSERT(source); + ref_get(&source->ref); +} + +void htrdr_planeto_source_ref_put(struct htrdr_planeto_source* source) +{ + ASSERT(source); + ref_put(&source->ref, release_source); +} + +double +htrdr_planeto_source_sample_direction + (const struct htrdr_planeto_source* source, + struct ssp_rng* rng, + const double pos[3], + double dir[3]) +{ + double main_dir[3]; + double half_angle; /* In radians */ + double cos_half_angle; + double dst; /* In m */ + double pdf; + ASSERT(source && rng && pos && dir); + + /* compute the direction of `pos' toward the center of the source */ + d3_sub(main_dir, source->position, pos); + + /* Normalize the direction and keep the distance from `pos' to the center of + * the source */ + dst = d3_normalize(main_dir, main_dir); + CHK(dst > source->radius); + + /* Sample the source according to its solid angle, + * i.e. 2*PI*(1 - cos(half_angle)) */ + half_angle = asin(source->radius/dst); + cos_half_angle = cos(half_angle); + ssp_ran_sphere_cap_uniform(rng, main_dir, cos_half_angle, dir, &pdf); + + return pdf; +} + +double +htrdr_planeto_source_get_radiance + (const struct htrdr_planeto_source* source, + const double wlen) +{ + return htrdr_planck_monochromatic + (wlen*1e-9/*From nm to m*/, source->temperature); +} + +int +htrdr_planeto_source_is_targeted + (const struct htrdr_planeto_source* source, + const double pos[3], + const double dir[3]) +{ + double main_dir[3]; + double half_angle; /* In radians */ + double dst; /* In m */ + ASSERT(source && dir && d3_is_normalized(dir)); + + /* compute the direction of `pos' toward the center of the source */ + d3_sub(main_dir, source->position, pos); + + /* Normalize the direction and keep the distance from `pos' to the center of + * the source */ + dst = d3_normalize(main_dir, main_dir); + CHK(dst > source->radius); + + /* Compute the the half angle of the source as seen from pos */ + half_angle = asin(source->radius/dst); + + return d3_dot(dir, main_dir) >= cos(half_angle); +} diff --git a/src/planeto/htrdr_planeto_source.h b/src/planeto/htrdr_planeto_source.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2018, 2019, 2020, 2021 |Meso|Star> (contact@meso-star.com) + * Copyright (C) 2018, 2019, 2021 CNRS + * Copyright (C) 2018, 2019, Université Paul Sabatier + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef HTRDR_PLANETO_SOURCE_H +#define HTRDR_PLANETO_SOURCE_H + +#include <rsys/rsys.h> + +/* Forward declarations */ +struct htrdr_planeto; +struct htrdr_planeto_source; +struct htrdr_planeto_source_args; +struct ssp_rng; + +extern LOCAL_SYM res_T +htrdr_planeto_source_create + (struct htrdr_planeto* cmd, + const struct htrdr_planeto_source_args* args, + struct htrdr_planeto_source** source); + +extern LOCAL_SYM void +htrdr_planeto_source_ref_get + (struct htrdr_planeto_source* source); + +extern LOCAL_SYM void +htrdr_planeto_source_ref_put + (struct htrdr_planeto_source* source); + +/* Return the pdf of the sampled direction */ +extern LOCAL_SYM double +htrdr_planeto_source_sample_direction + (const struct htrdr_planeto_source* source, + struct ssp_rng* rng, + const double pos[3], /* Position from which direction is sampled */ + double dir[3]); + +extern LOCAL_SYM double /* In W/m²/sr/m */ +htrdr_planeto_source_get_radiance + (const struct htrdr_planeto_source* source, + const double wlen); /* In nanometers */ + +/* Return 1 if the source is targeted by the submitted ray and 0 otherwise */ +extern LOCAL_SYM int +htrdr_planeto_source_is_targeted + (const struct htrdr_planeto_source* source, + const double pos[3], /* Ray origin */ + const double dir[3]);/* Ray direction */ + +#endif /* HTRDR_PLANETO_SOURCE_H */