#!/perl -w
# NAME: sgutil.pl
# AIM: some SG services
my $SG_BUCKET_SPAN = 0.125;
my $SG_EPSILON = 0.0000001;

#* Generate the unique scenery tile index for this bucket
#* The index is constructed as follows:
#* 9 bits - to represent 360 degrees of longitude (-180 to 179)
#* 8 bits - to represent 180 degrees of latitude (-90 to 89)
#* Each 1 degree by 1 degree tile is further broken down into an 8x8
#* grid.  So we also need:
#* 3 bits - to represent x (0 to 7)
#* 3 bits - to represent y (0 to 7)
#inline long int gen_index() const { return ((lon + 180) << 14) + ((lat + 90) << 6) + (y << 3) + x; }
sub gen_index {
	my ($lon, $lat, $y, $x) = @_;
	###prt( "gen_index from lon $lon, lat $lat, y $y, x $x \n" );
	return (($lon + 180) << 14) + (($lat + 90) << 6) + ($y << 3) + $x;
}

##my ($dlon, $dlat) = llxy_2_dll( $lon, $lat, $y, $x );
sub llxy_2_dll {	
	my ( $lon, $lat, $y, $x ) = @_;
	my $span = sg_bucket_span( $lat );
	return ( ($lon + ($x * $span)), ($lat + (($y * 8) / 60)) );
}

#SGBucket::SGBucket(const long int bindex) {
sub conv_bucket_index {
	my ($ind) = shift;
	my $index = $ind;
	my $lon = $ind >> 14;
	$ind -= $lon << 14;
	$lon -= 180;
	my $lat = $ind >> 6;
	$ind -= $lat << 6;
	$lat -= 90;
	my $y = $ind >> 3;
	$ind -= $y << 3;
	my $x = $ind;
	prt( "index $index equal lon $lon, lat $lat, y $y, x $x ...\n" );
	return ($lon, $lat, $y, $x);
}

#// return the horizontal tile span factor based on latitude
#static double sg_bucket_span( double l ) {
sub sg_bucket_span {
	my ($l) = shift;
    if ( $l >= 89.0 ) {
		return 360.0;
    } elsif ( $l >= 88.0 ) {
		return 8.0;
    } elsif ( $l >= 86.0 ) {
		return 4.0;
    } elsif ( $l >= 83.0 ) {
		return 2.0;
    } elsif ( $l >= 76.0 ) {
		return 1.0;
    } elsif ( $l >= 62.0 ) {
		return 0.5;
    } elsif ( $l >= 22.0 ) {
		return 0.25;
    } elsif ( $l >= -22.0 ) {
		return 0.125;
    } elsif ( $l >= -62.0 ) {
		return 0.25;
    } elsif ( $l >= -76.0 ) {
		return 0.5;
    } elsif ( $l >= -83.0 ) {
		return 1.0;
    } elsif ( $l >= -86.0 ) {
		return 2.0;
    } elsif ( $l >= -88.0 ) {
		return 4.0;
    } elsif ( $l >= -89.0 ) {
		return 8.0;
    }
	return 360.0;
}


#// Set the bucket params for the specified lat and lon
sub lon_lat_to_index {
# void SGBucket::set_bucket( double dlon, double dlat ) {
# // latitude first
	my ($dlon, $dlat) = @_;
	my ($lon, $lat, $y, $x);
# double span = sg_bucket_span( dlat );
	my $span = sg_bucket_span( $dlat );
#  double diff = dlon - (double)(int)dlon;
	my $diff = $dlon - int($dlon);
	###prt( "ll2ind: lon $dlon, lat $dlat, span $span, diff $diff ...\n" );
    #// cout << "diff = " << diff << "  span = " << span << endl;
    #if ( (dlon >= 0) || (fabs(diff) < SG_EPSILON) ) {
    if ( ($dlon >= 0) || (abs($diff) < $SG_EPSILON) ) {
		$lon = int($dlon);
    } else {
		$lon = int($dlon - 1);
    }
	###prt( "int lon = $lon ...\n" );
    #// find subdivision or super lon if needed
    # if ( span < SG_EPSILON ) { // polar cap
    if ( $span < $SG_EPSILON ) {
		$lon = 0;
		$x = 0;
    # } else if ( span <= 1.0 ) {
    } elsif ( $span <= 1.0 ) {
		###my $dx = (($dlon - $lon) / $span);
		$x = int(($dlon - $lon) / $span);
		###prt( "span LT 1.0 so x = $x ... dx = $dx \n" );
    } else {
		#if ( (dlon >= 0) || (fabs(diff) < SG_EPSILON) ) {
		if ( ($dlon >= 0) || (abs($diff) < $SG_EPSILON) ) {
			$lon = int( int($lon / $span) * $span);
		} else {
			#// cout << " lon = " << lon 
			#//  << "  tmp = " << (int)((lon-1) / span) << endl;
			$lon = int( int(($lon + 1) / $span) * $span - $span);
			if ( $lon < -180 ) {
				$lon = -180;
			}
		}
		$x = 0;
    }

    #// then latitude
    $diff = $dlat - int($dlat);
    if ( ($dlat >= 0) || (abs($diff) < $SG_EPSILON) ) {
		$lat = int($dlat);
    } else {
		$lat = int($dlat - 1);
    }
    $y = int(($dlat - $lat) * 8);
	return gen_index($lon, $lat, $y, $x);
}

1;	# includes MUST return TRUE!!!
# eof - sgutil.pl
