#Metview Macro

# **************************** LICENSE START ***********************************
#
# Copyright 2017 ECMWF. This software is distributed under the terms
# of the Apache License version 2.0. In applying this license, ECMWF does not
# waive the privileges and immunities granted to it by virtue of its status as
# an Intergovernmental Organization or submit itself to any jurisdiction.
#
# ***************************** LICENSE END ************************************

# **************************************************************************
# Function      : mvl_geocircle
#
# Syntax        : definition mvl_geocircle (lat : number, lon : number,
#                                          radius : number, resolution : number)
#
# Category      : VISUAL
#
# OneLineDesc   : Returns a curve marking the circle with the given radius around the given centre
#
# Description   : Returns a plot definintion for drawing a circle with the given radius
#                 around the given centre. This circle is projection-independent.
#
# Parameters    : lat,lon - coordinates of the centre of the circle
#                 radius  - the radius of the circle in km
#                 resolution     - the number of point used to make up the circle 
#                           
# Return Value  : an Input Visualiser that may be used in a plot() command
#
# Example Usage : 
#
#                   lat  = 51
#                   lon  = -1                  
#                   radius = 100
#                   resolution = 100
#
#                   my_circle = mvl_geocircle(lat,lon,radius,resolution)
#
#                   plot ( display_window, data, my_circle, mgraph())
#
# **************************************************************************

function mvl_geocircle (lat : number, lon : number,
                      radius : number, resolution : number)
                 
    resolution=int(resolution)
    
    #Some checks
    if lon < -180. or lon > 180. then
        fail("lon=",lon," is out of range!")
    end if
    
    if lat < -90. or lat > 90. then
        fail("lat=",lat," is out of range!")
    end if        
    
    if radius <=0 or radius > 45000 then
        fail("radius=",radius," is out of range!")
    end if   
    
    if resolution <=0 then
        fail("resolution=",resolution," must be non-negative!")
    end if   
    
    if resolution > 500 then
        resolution=500
    end if    
      
    #Define contants  
    R=6371 #km, Radius of Earth
    PI=acos(-1)
    
    #First we compute the circle coordinates as if the north pole
    #was the centre then rotate the pole to the real centre
    
    
    
    
    #Distance from the pole in radians
    radDist=radius/R
    
    #Define some rotation parameters
    
        theta=(PI/2-PI*lat/180.)
    
    cosTheta=cos(theta)
    sinTheta=sin(theta)
    
    #The resulting lists
    latOut=nil
    lonOut=nil

    #Loop for the circle points
    for i=0 to resolution do
        
        #Angle east from Greenwich in radians            
        lonVal=i*2*PI/resolution
        
        #Angle from the north pole in radians
        latVal=PI/2-radDist
           
        #print("------ latVal=",latVal," lonVal=",lonVal)
           
        #transform to xyz
        x = cos(lonVal)*cos(latVal)
        y = sin(lonVal)*cos(latVal)
        z = sin(latVal)  
         
        #print("x=",x," y=",y," z=",z)   
         
        #Rotate around the y axis by theta angle  
        xr = cosTheta*x + sinTheta*z
        yr = y
        zr = -sinTheta*x + cosTheta*z  
        
        #print("xr=",xr," yr=",yr," zr=",zr)
        
        #Back to lat-lon (in degrees)
        latVal = asin(zr)*180./PI       
        lonVal = mvl_atan2(xr,yr)*180./PI
      
        #print("latVal=",latVal," lonVal=",lonVal)
      
        #Rotate the lon  
        lonVal=lonVal+lon
         
        #print("latVal=",latVal," lonVal=",lonVal)
         
        lonOut=lonOut & [lonVal]
        latOut=latOut & [latVal]
        
    end for
    
    # set up a curve with suitable vis def
    geocircle_curve = input_visualiser
    (
        input_plot_type        :    "geo_points",
        input_longitude_values :    lonOut,
        input_latitude_values  :    latOut
     )

	return geocircle_curve


end  mvl_geocircle

function mvl_atan2(x,y)

    PI=acos(-1)
   
    if y = 0 then
        if x <= 0 then
            return -PI
        else
            return 0    
        end if
    end if

    if x = 0 then
        if y >= 0 then
            return PI/2.
        else
            return -PI/2.
        end if
    end if   
      
    v=atan(y/x)                  
    if x < 0 and y > 0 then
        return v+PI
    else if x < 0 and y < 0 then
        return v-PI
    else 
        return v      
    end if
     
    if x = 0 then
        if y >=0 then
            return PI/2.
        else
            return -PI/2.
        end if
    end if    
                    
    return 0             
            
end mvl_atan2