\cancel mode verify
! polytube_bent.jnl
! 4/99 *sh* and *jd*
! 10/00 *sh* bug fix to scaling algorithm
! 08/2012 Adapted from polytube by E. D. Cokelet, NOAA/PMEL

! Description: Plot a colored, sgmented tube of variable values along a plotted track.
! Older polytube cuts off the corners, i.e. it draws a single tube between the midpoints of successive trackline points.  
! polytube_bent does not cut off the corners between trackline data points.  Instead it draws 2-segment tube that lies along the trackline and bends around each data point.  The first segment goes from the midpoint before to the trackline point, and the second segment goes from the trackline point to the midpoint after.  Contrary to polytube, no smoothing is employed in polytube_bent.  If desired, the user should smooth the inputs before calling polytube_bent.  
! Missing values:  polytube_bent does not replace missing values via interpolation.  Missing value interpolation is left to the user prior to input to polytube_bent.  polytube_bent requires that "xpts" and "ypts" contain no missing values.  The "values" variable can contain missing values around which no polygon will be drawn.   

! Usage:                            $1         $2   $3   $4      $5
! yes?	GO polytube_bent polygon_command xpts ypts values [scale]
! $1 - the plot command with qualifiers (eg POLYGON/OVER/KEY)
! $2 - X coordinates of track
! $3 - Y coordinates of track
! $4 - variable whose values will be plotted along the track (eg SST)
! $5 - scale the values by this factor in user units per quarter inch (optional, default 1)

! example -- make up a cruise track and data
!	let pi = 4.0*atan(1.0)
!	let npts = 6
!	define axis/t=0:`npts-1`:1/units=days t_ax
!	let tim = t[gt=t_ax]
!	let xpts = 180 + 50*COS(2*pi*tim/(npts-1))
!	let ypts = 15  + 20*SIN(2*pi*tim/(npts-1))
!	let sst  = 35 - ypts + RANDN(ypts)
!	let sst1 = if (l eq 3) then sst/0 else sst	! Test function with missing value that should not plot
!	go basemap x=120:250 Y=25s:65n 20

! Choose with polytube
!	go polytube polygon/over/key/title=sst xpts,ypts,sst
! or with polytube_bent

!	go polytube_bent polygon/over/key/title=sst xpts,ypts,sst
!	plot/vs/over/nolab/line/sym/thick=2 xpts,ypts
!	list xpts, ypts, sst


! argument check

QUERY/IGNORE $1"<usage: yes? GO polytube_bent polygon_command xpts ypts values [scale]"
QUERY/IGNORE $2"<usage: yes? GO polytube_bent polygon_command xpts ypts values [scale]"
QUERY/IGNORE $3"<usage: yes? GO polytube_bent polygon_command xpts ypts values [scale]"


! save the input expressions into simple variable definitions

LET/QUIET TUBEx = ($2)
LET/QUIET TUBEy = ($3)
LET/QUIET TUBEdata = ($4)


! determine the orientation of the data (and check that it is 1D)

DEFINE SYMBOL TUBEax `TUBEx,return=shape`
DEFINE SYMBOL TUBEpoly_ax ($TUBEax"|X>Z|Y>Z|Z>Y|T>Z|<error: data is not a line")


! Scale factors in units/(quarter-inch)

LET/QUIET TUBEdefault_scale =$5"1" *  0.25
LET/QUIET TUBEx_scale = TUBEdefault_scale*((($xaxis_max))-(($xaxis_min)))/($ppl$xlen)
LET/QUIET TUBEy_scale = TUBEdefault_scale*((($yaxis_max))-(($yaxis_min)))/($ppl$ylen)
LET/QUIET TUBEaxscale_factor = TUBEy_scale/TUBEx_scale


! Compute the local normal vector components -- (COS,SIN) --> (-SIN,COS)
! at each trackline point and at the midpoints before and after.
! These will be used to create offsets from track line.
! The missing value logic below takes care of the first (or last) plotted point before (or after) which there is no value.
! If a centered derivative is missing, fill it with a forward one if it exists, or a backward one if not.

LET/QUIET TUBEdx_bef = TUBEx[($TUBEax)=@ddb] * TUBEaxscale_factor
LET/QUIET TUBEdy_bef = TUBEy[($TUBEax)=@ddb]

LET/QUIET TUBEdx_pt = missing( TUBEx[($TUBEax)=@ddc], missing( TUBEx[($TUBEax)=@ddf], TUBEx[($TUBEax)=@ddb]) ) * TUBEaxscale_factor
LET/QUIET TUBEdy_pt = missing( TUBEy[($TUBEax)=@ddc], missing( TUBEy[($TUBEax)=@ddf], TUBEy[($TUBEax)=@ddb]) )

LET/QUIET TUBEdx_aft = TUBEx[($TUBEax)=@ddf] * TUBEaxscale_factor
LET/QUIET TUBEdy_aft = TUBEy[($TUBEax)=@ddf]

LET/QUIET TUBEds_mag_bef = (TUBEdx_bef^2+TUBEdy_bef^2)^0.5 
LET/QUIET TUBExnorm_bef = TUBEx_scale * (-1 *  TUBEdy_bef / TUBEds_mag_bef)
LET/QUIET TUBEynorm_bef = TUBEy_scale * TUBEdx_bef / TUBEds_mag_bef

LET/QUIET TUBEds_mag_pt = (TUBEdx_pt^2+TUBEdy_pt^2)^0.5
LET/QUIET TUBExnorm_pt = TUBEx_scale * (-1 *  TUBEdy_pt / TUBEds_mag_pt)
LET/QUIET TUBEynorm_pt = TUBEy_scale * TUBEdx_pt / TUBEds_mag_pt

LET/QUIET TUBEds_mag_aft = (TUBEdx_aft^2+TUBEdy_aft^2)^0.5
LET/QUIET TUBExnorm_aft = TUBEx_scale * (-1 *  TUBEdy_aft / TUBEds_mag_aft)
LET/QUIET TUBEynorm_aft = TUBEy_scale * TUBEdx_aft / TUBEds_mag_aft


! compute midpoints before and after each trackline point

LET/QUIET TUBExmid_bef = missing( (TUBEx + TUBEx[($TUBEax)=@shf:-1])/2, TUBEx )
LET/QUIET TUBEymid_bef = missing( (TUBEy + TUBEy[($TUBEax)=@shf:-1])/2, TUBEy )

LET/QUIET TUBExmid_aft = missing( (TUBEx + TUBEx[($TUBEax)=@shf:1])/2, TUBEx )
LET/QUIET TUBEymid_aft = missing( (TUBEy + TUBEy[($TUBEax)=@shf:1])/2, TUBEy )


! create the 6 vertices for each 6-sided bent tube centered on each trackline point
! Vertices are numbered counterclockwise beginning in lower, left corner

LET/QUIET TUBE_index = ($TUBEpoly_ax)[($TUBEpoly_ax)=1:6]

let/quiet TUBEx1 = missing( 0*TUBE_index + TUBExmid_bef - TUBExnorm_bef, TUBEx2)
let/quiet TUBEy1 = missing( 0*TUBE_index + TUBEymid_bef - TUBEynorm_bef, TUBEy2)

let/quiet TUBEx2 = 0*TUBE_index + TUBEx - TUBExnorm_pt
let/quiet TUBEy2 = 0*TUBE_index + TUBEy - TUBEynorm_pt

let/quiet TUBEx3 = missing( 0*TUBE_index + TUBExmid_aft - TUBExnorm_aft, TUBEx2) 
let/quiet TUBEy3 = missing( 0*TUBE_index + TUBEymid_aft - TUBEynorm_aft, TUBEy2)
 
let/quiet TUBEx4 = missing( 0*TUBE_index + TUBExmid_aft + TUBExnorm_aft, TUBEx5)
let/quiet TUBEy4 = missing( 0*TUBE_index + TUBEymid_aft + TUBEynorm_aft, TUBEy5)

let/quiet TUBEx5 = 0*TUBE_index + TUBEx + TUBExnorm_pt 
let/quiet TUBEy5 = 0*TUBE_index + TUBEy + TUBEynorm_pt

let/quiet TUBEx6 = missing( 0*TUBE_index + TUBExmid_bef + TUBExnorm_bef, TUBEx5)
let/quiet TUBEy6 = missing( 0*TUBE_index + TUBEymid_bef + TUBEynorm_bef, TUBEy5)

let/quiet TUBEmask1 = if TUBE_index eq 1 then 1 else 0
let/quiet TUBEmask2 = if TUBE_index eq 2 then 1 else 0
let/quiet TUBEmask3 = if TUBE_index eq 3 then 1 else 0
let/quiet TUBEmask4 = if TUBE_index eq 4 then 1 else 0
let/quiet TUBEmask5 = if TUBE_index eq 5 then 1 else 0
let/quiet TUBEmask6 = if TUBE_index eq 6 then 1 else 0

let/quiet TUBEx_plot = TUBEmask1*TUBEx1 + TUBEmask2*TUBEx2 + TUBEmask3*TUBEx3 + TUBEmask4*TUBEx4 + TUBEmask5*TUBEx5 + TUBEmask6*TUBEx6

let/quiet TUBEy_plot = TUBEmask1*TUBEy1 + TUBEmask2*TUBEy2 + TUBEmask3*TUBEy3 + TUBEmask4*TUBEy4 + TUBEmask5*TUBEy5 + TUBEmask6*TUBEy6


! Plot the polygons on the trackline

$1/coord_ax=($TUBEpoly_ax) TUBEx_plot, TUBEy_plot, TUBEdata

cancel symbol TUBE*
cancel variable TUBE*
set mode/last verify



