LightRays/LightRays/ObjetsOptiques.cpp
2020-03-04 23:14:44 +01:00

78 lines
3.0 KiB
C++

#include "ObjetsOptiques.h"
#include "sfml_c01.hpp"
#include <cmath>
Objet_MatriceTrsfUnidir::Objet_MatriceTrsfUnidir (point_t centre, float diam, float angv, mat_trsf_t m) : ObjetLigne({0,0}, {0,0}), mat_trsf(m) {
vec_t v = diam/2 * vec_t{ -sinf(angv), cosf(angv) };
a = centre + v;
b = centre + -v;
}
// Dessin d'un Objet_MatriceTrsfUnidir : on rajoute une ligne qui marque le côté sortant
//
void Objet_MatriceTrsfUnidir::dessiner (sf::RenderWindow& window, bool emphasize) const {
ObjetLigne::dessiner(window, emphasize);
point_t o = milieu_2points(a,b);
window.draw(sf::c01::buildLine(o, o + 0.05 * vecteur_u_perp(), sf::Color(100,100,100)));
}
// Objet_MatriceTrsfUnidir : Application de la matrice ABCD sur le rayon intercepté, dans le sens direct uniquement
//
std::vector<Rayon> Objet_MatriceTrsfUnidir::re_emit (const Rayon& ray, std::shared_ptr<void> interception) {
intercept_ligne_t& intercept = *(intercept_ligne_t*)interception.get();
std::vector<Rayon> rays;
if (intercept.sens_reg) {
float diam = !(a-b);
float y = (1 - 2 * intercept.s_incid) * diam/2; // élévation incidente
float yp = tanf(intercept.ang_incid); // pente incidente
float y2 = mat_trsf.A * y + mat_trsf.B * yp; // élévation en sortie
float y2p = mat_trsf.C * y + mat_trsf.D * yp; // pente en sortie
Rayon raytrsf = ray;
raytrsf.orig = milieu_2points(a,b) + y2 * (b-a)/diam;
raytrsf.dir_angle = atanf(y2p);
rays.push_back(std::move(raytrsf));
}
return rays;
}
// Objet_Filtre : filtrage du rayon incident : simple multiplication composante par composante du spectre par le spectre de transmission
//
std::vector<Rayon> Objet_Filtre::re_emit (const Rayon& ray, std::shared_ptr<void> interception) {
intercept_courbe_t& intercept = *(intercept_courbe_t*)interception.get();
Rayon ray_filtre = ray;
ray_filtre.orig = intercept.p_incid;
Specte::for_each_manual([&] (size_t i, float lambda, pola_t pol) -> void {
ray_filtre.spectre.comps[i] *= transm.comps[i];
});
return { std::move(ray_filtre) };
}
// Miroir : simple réflexion par rapport à la normale au point incident
//
std::vector<Rayon> ObjetCourbe_Miroir::re_emit (const Rayon& ray, std::shared_ptr<void> interception) {
intercept_courbe_t& intercept = *(intercept_courbe_t*)interception.get();
std::vector<Rayon> ray_emis;
Rayon ray_refl;
ray_refl.orig = intercept.p_incid;
ray_refl.dir_angle = intercept.ang_normale - intercept.ang_incid; // i_refl = i par rapport à la normale
ray_refl.spectre = ray.spectre;
ray_emis.push_back(std::move(ray_refl));
return ray_emis;
}
// Bilan d'énergie : accumulation des flux entrants et sortants
//
std::vector<Rayon> Objet_BilanEnergie::re_emit (const Rayon& ray, std::shared_ptr<void> interception) {
intercept_courbe_t& intercept = *(intercept_courbe_t*)interception.get();
Rayon rayon = ray;
rayon.orig = intercept.p_incid;
if (intercept.sens_reg) {
n_ray_in += 1;
flux_in += rayon.spectre.intensite_tot();
} else {
n_ray_out += 1;
flux_out += rayon.spectre.intensite_tot();
}
return { std::move(rayon) };
}