\cancel mode verify
! polytube.jnl
! 4/99 *sh* and *jd*
! 10/00 *sh* bug fix to scaling algorithm
! 04/2019 Extend axis references to allow E or F axis

! Description: Plot a colored tube of variable values along a plotted track

! Usage:                  $1         $2   $3   $4      $5       $6
! yes?	GO polytube polygon_command xpts ypts values [scale] [smooth]
! $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 (optional, default 1)
! $6 - smooth the track to be plotted with SBX:$6 (optional, default 3)
!      The "smooth" parameter is given in units of the number of points over
!      which a running mean filter will be applied to the normal vectors. It 
!      is effective only in special cases. For "rough" paths, best results are
!      obtained by smoothing the position data that is passed to this script. 

! example -- make up a cruise track and data
!	yes? let xpts = 180 + 50*COS(2*3.14*I[I=1:50]/60)
!	yes? let ypts = 15  + 20*SIN(2*3.14*I[I=1:50]/60)
!	yes? let sst = 25 - ypts + RANDN(ypts)
!	yes? go basemap x=120:250 Y=25s:65n 20
!
!	yes? go polytube polygon/over/key/title=sst xpts,ypts,sst
!
!	yes? plot/vs/over/nolab/line/sym xpts,ypts

! argument check
QUERY/IGNORE $1"<usage: yes? GO polytube polygon_command xpts ypts values [scale] [smooth]"
QUERY/IGNORE $2"<usage: yes? GO polytube polygon_command xpts ypts values [scale] [smooth]"
QUERY/IGNORE $3"<usage: yes? GO polytube polygon_command xpts ypts values [scale] [smooth]"

! 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|E>Z|F>Z|<error: data is not a line")

! units/inch scale factors
LET/QUIET TUBEdefault_scale =$5"1" *  0.25
LET/QUIET TUBEx_correction = TUBEdefault_scale*((($xaxis_max))-(($xaxis_min)))/($ppl$xlen)
LET/QUIET TUBEy_correction = TUBEdefault_scale*((($yaxis_max))-(($yaxis_min)))/($ppl$ylen)
LET/QUIET TUBEaxscale_factor = TUBEy_correction/TUBEx_correction

! compute the local normal vector components -- (COS,SIN) --> (-SIN,COS)
! this will be used to create offsets from track line
! @DDF and @DDB fill in derivative values at endpoints and missing pts
LET/QUIET TUBEdx0 = MISSING(TUBEx[($TUBEax)=@ddc],MISSING(TUBEx[($TUBEax)=@ddf],TUBEx[($TUBEax)=@ddb])) * TUBEaxscale_factor

LET/QUIET TUBEdy0 = MISSING(TUBEy[($TUBEax)=@ddc],MISSING(TUBEy[($TUBEax)=@ddf],TUBEy[($TUBEax)=@ddb]))

LET/QUIET TUBEds_mag = (TUBEdx0^2+TUBEdy0^2)^0.5
LET/QUIET TUBExnorm0 = TUBEx_correction * (-1 *  TUBEdy0 / TUBEds_mag)
LET/QUIET TUBEynorm0 = TUBEy_correction * TUBEdx0 / TUBEds_mag

! smooth the normal vectors ...
LET/QUIET TUBExnorm = MISSING(TUBExnorm0[($TUBEax)=@sbx:$6"3"],TUBExnorm0)
LET/QUIET TUBEynorm = MISSING(TUBEynorm0[($TUBEax)=@sbx:$6"3"],TUBEynorm0)

! compute midpoints -- base points to which the polygon deltas are added 
! use MISSING to capture the very last 1/2 sized quadralateral
LET/QUIET TUBExmid = MISSING( (TUBEx + TUBEx[($TUBEax)=@shf])/2, TUBEx )
LET/QUIET TUBEymid = MISSING( (TUBEy + TUBEy[($TUBEax)=@shf])/2, TUBEy )

! at each midpoint, assemble the vertices above and below
!LET/QUIET TUBExup  = TUBExmid + TUBExnorm
!LET/QUIET TUBEyup  = TUBEymid + TUBEynorm
!LET/QUIET TUBExdn  = TUBExmid - TUBExnorm
!LET/QUIET TUBEydn  = TUBEymid - TUBEynorm

! create the 4 vertices for each quadrlateral of the tube
LET/QUIET TUBEpindex = _($TUBEpoly_ax)[($TUBEpoly_ax)=1:4]
LET/QUIET TUBEx4_0 = IF TUBEpindex EQ 1 OR TUBEpindex EQ 4 then TUBExmid-TUBExnorm ELSE TUBExmid+TUBExnorm
LET/QUIET TUBEy4_0 = IF TUBEpindex EQ 1 OR TUBEpindex EQ 4 then TUBEymid-TUBEynorm ELSE TUBEymid+TUBEynorm

! x4p1,y4p1 just to capture the very first 1/2 sized quadralateral
LET/QUIET TUBEx4p1 = IF TUBEpindex EQ 1 OR TUBEpindex EQ 4 then TUBEx-TUBExnorm ELSE TUBEx+TUBExnorm
LET/QUIET TUBEy4p1 = IF TUBEpindex EQ 1 OR TUBEpindex EQ 4 then TUBEy-TUBEynorm ELSE TUBEy+TUBEynorm

LET/QUIET TUBEx4_1 = IF TUBEpindex LE 2 then TUBEx4_0 ELSE MISSING( TUBEx4_0[($TUBEax)=@shf:-1], TUBEx4p1 )
LET/QUIET TUBEy4_1 = IF TUBEpindex LE 2 then TUBEy4_0 ELSE MISSING( TUBEy4_0[($TUBEax)=@shf:-1], TUBEy4p1 )

$1/coord_ax=($TUBEpoly_ax)  TUBEx4_1,TUBEy4_1,TUBEdata

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