#!/usr/bin/perl # A sun reflection template # Copyright : https://www.fsf.org/copyleft/gpl.html # Author : Dan Jacobson -- https://www.jidanni.org/ # Created On : Mon May 31 19:31:41 2021 # Last Modified On: Mon May 31 22:03:09 2021 # Update Count : 25 use strict; use warnings FATAL => 'all'; use open qw/:std :encoding(utf8)/; use Math::Trig '/./'; sub NESW { deg2rad( $_[0] ), deg2rad( 90 - $_[1] ) } my $world_radius = 6378137; #meters. Or maybe I should use 6370997: #proj -le: sphere my %location = ( reflector => { longtude => 120.873615, latitude => 24.143174, above_sea_level => 901, #meters azimuth => 324.05, #of perpendicular to plane of reflector vs_horizon => 30 , #0 is e.g., an average window, perpendicular makes 0 degrees angle with horizon }, observer => { longtude => 120.865225, latitude => 24.181802, above_sea_level => 777 } ); my @light; { my @t; for (qw/reflector observer/) { push @t, NESW( @{ $location{$_} }{qw/longtude latitude/} ); } $location{observer}{azimuth} = rad2deg great_circle_direction(@t); $location{observer}{vs_horizon} = rad2deg atan( ( $location{observer}{above_sea_level} - $location{reflector}{above_sea_level} ) / great_circle_distance( @t, $world_radius ) #short distance, assume flat earth ); @t = (); for (qw/reflector observer/) { push @t, NESW( @{ $location{$_} }{qw/azimuth vs_horizon/} ); } @light = great_circle_waypoint( @t, -1 ); } ## Now we start to think using a sphere centered at the reflector. ## Compute the best time of day where the light (sun, moon, etc.) is closest to the ## spot in the sky where it reflects perfectly to the observer. my ( $date, %best ); while (<>) { if (/./) { ( $date, my ( $time, $azimuth, $elevation ) ) = split; my $distance = great_circle_distance( @light, NESW( $azimuth, $elevation ) ); if ( !%best or $distance < $best{distance} ) { $best{time} = $time; $best{distance} = $distance; } } else { printf "%s %s\n", $date, $best{time}; undef %best; } }