#
# Copyright (c) 2012-2016, USC/ISI
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met: 
# 
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer. 
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution. 
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# 

# hsl2rgb($h, $s, $l): convert from HSL to RGB
# $h in [0..360]
# $s in [0..1]
# $l in [0..1]
sub hsl2rgb($$$) {
    my ($h,$s,$l) = @_;
    my $c  =(1. - abs(2*$l-1))*$s;
    my $hh = $h/60.;
    my $x  = $c*(1. - abs($hh - 2*int($hh/2.) - 1.));
    my @rgb;
    @rgb = ($c, $x, 0)
	if 0<=$hh && $hh<1;
    @rgb = ($x, $c, 0)
        if 1<=$hh && $hh<2;
    @rgb = (0, $c, $x)
	if 2<=$hh && $hh<3;
    @rgb = (0, $x, $c)
	if 3<=$hh && $hh<4;
    @rgb = ($x, 0, $c)
	if 4<=$hh && $hh<5;
    @rgb = ($c, 0, $x)
	if 5<=$hh && $hh<6;
    my $m = $l-$c/2.;
    @rgb = map { $_ = int(255*($_+$m)) } @rgb;
    return @rgb;
}


# lonlat2rgb($lon, $lat): convert coordinates to RGB triplet
# input:  latitude  in [ -90;  90]
# input:  longitude in [-180; 180]
# output: @rgb
use POSIX qw(fmod);
sub lonlat2rgb($$) {
   my ($lon, $lat) =  @_;
   $lat = -$lat; #north should be dark
   $lon = fmod($lon+3600, 360);
   my ($LATL, $LATH) = (-115, 80); # L[0,1] is spread over this range of flipped lats
   $lat = $LATH if $lat > $LATH;
   $lat = $LATL if $lat < $LATL;
   my @rgb = hsl2rgb($lon, 1, ($lat - $LATL)/($LATH-$LATL));
   return @rgb;
}



sub lonlat2rgb_test {
    my(@tests) = (
	{ city => 'honolulu', lat => 21.3069, lon => -157.8583, color => "009af5", },
	{ city => 'anchorage', lat => 61.2180, lon => -149.9003, color => "00468c", },
	{ city => 'los angeles', lat => 34.0522, lon => -118.2437, color => "0600d3", },
	{ city => 'mexico city', lat => 19.4326, lon => -99.1332, color => "5600f9", },
	{ city => 'new york city', lat => 40.712784, lon => -74.0059, color => "9400c2", },
	{ city => 'buenos aires', lat => -34.6037, lon => -58.3816, color => "ff88fb" },
	{ city => 'london', lat => 51.5074, lon => -0.1278, color => "a60000" },
	{ city => 'cape town', lat => -33.9249, lon => 18.4241, color => "ffab86" },
	{ city => 'cairo', lat => 30.0444, lon => 31.2357, color => "de7300" },
	{ city => 'tehran', lat => 35.6892, lon => 51.3890, color => "cfb100" },
	{ city => 'new delhi', lat => 28.6139, lon => 77.2090, color => "a1e100" },
	{ city => 'beijing', lat => 39.9042, lon => 116.4074, color => "0bc400" },
	{ city => 'tokyo', lat => 35.6895, lon => 139.6917, color => "00cf44" },
	{ city => 'sidney', lat => -33.8688, lon => 151.2093, color => "86ffc5" },
	{ city => 'wellington', lat => -41.2864, lon => 174.7762, color => "99fff6" },
	);
    print "#fsdb -F t city lat lon color\n";
    foreach my $test (@tests) {
	my(@rgb) = lonlat2rgb($test->{lon}, $test->{lat});
	my($rgb_str) = sprintf("%02x%02x%02x", @rgb);
	print join("\t", $test->{city}, $test->{lat}, $test->{lon}, $rgb_str, ($rgb_str eq $test->{color} ? "ok" : "MISMATCH")) . "\n";
    };
}
# uncomment next line to run tests
# lonlat2rgb_test();
