|
Post by 2ndtrickop on Jan 7, 2019 22:32:12 GMT
First off, thanks to Rod, B+, and tsh for getting me started a few months ago; my routing-model project is firming up nicely.
Now I have a question on converting the slope of a line (representing one or more legs(segments) of a trip into eight, or possibly sixteen. directions on a compass.
The first algorimtm tried below converts the slope (negative for eastward movements and positive for westbound) into a direction expressed as a string variable; this can then be compared to the direction from the original point of origin or destination …..
as formulated below (where Jslp = the slope of the leg/segment and Jdir$ = the direction expressed as a string.
if ((Jslp<1) and (Jslp>.875)) then (Jdir$="S")
if ((Jslp<.875) and (Jslp>.625)) then (Jdir$="SW")
if ((Jslp<.625) and (Jslp>.375)) then (Jdir$="W")
if ((Jslp<.375) and (Jslp>.125)) then (Jdir$="NW")
if ((Jslp<.125) and (Jslp>-.125)) then (Jdir$="N")
if ((Jslp<-.125) and (Jslp>-.375)) then (Jdir$="NE")
if ((Jslp<-.375) and (Jslp>-.625)) then (Jdir$="E")
if ((Jslp<-.625) and (Jslp>-.875)) then (Jdir$="SE")
if ((Jslp<-.875) and (Jslp>-1)) then (Jdir$="S")
I'm trying to avoid eight (let alone sixteen) separate branching statements in this manner; Thanks, as before!
|
|
|
Post by B+ on Jan 8, 2019 0:24:41 GMT
What if you were given a formula to find the angle one point is to another?
The input would be the (x1, y1) coordinate of one place and the (x2, y2) coordinate of the 2nd.
The output would be the exact measure in degrees 0 to 360 in degrees or 0 to 2*pi in radians. PLUS you can have the same data return the distance as bonus information!
|
|
|
Post by 2ndtrickop on Jan 8, 2019 1:01:58 GMT
Thanks! --- that should work well as I currently use a 360-degree field for departures from points not used enough to justify a static table of mileages.
A couple of years ago, using the same hang-bells-and-whistles-until-it-overloads system, I came up with a program to simulate the actions of a rail dispatcher on single track.
It helps an aging introvert get through a dull winter.
|
|
|
Post by B+ on Jan 8, 2019 2:31:40 GMT
OK not a formula, nor even a function, here is a sub (angleAndDistance) that returns both angle and distance given the x, y coordinates of two points on a map. The main code is testing all the major compass directions for accuracy:
'atan2 and distance.txt B+ 2019-01-07
'the subs need the follwing global constants global pi, d2r, r2d pi = acs(-1) d2r = pi/180 'convert degree angle units to radians r2d = 180/pi 'convert radian angle units to degrees
' ' N ' NW | NE ' \ / ' W - - E ' / \ ' SW | SE ' S
'test standard compass directions with these simple map coordinates ox = 0: oy = 0 'Origin Nx = 0: Ny = -1 'North of Origin NEx = 1: NEy = -1 'NE Ex = 1: Ey = 0 'East of Origin SEx = 1: SEy = 1 'SE Sx = 0: Sy = 1 'South of Origin SWx = -1: SWy = 1 'SW Wx = -1: Wy = 0 'West of Origin NWx = -1: NWy = -1 'NW
'going around the world print "Test North of origin:" call angleAndDistance ox, oy, Nx, Ny, ang, dist print ang;" degrees", dist;" distance units" print print "Test North-East of origin:" call angleAndDistance ox, oy, NEx, NEy, ang, dist print ang;" degrees", dist;" distance units" print print "Test East of origin:" call angleAndDistance ox, oy, Ex, Ey, ang, dist print ang;" degrees", dist;" distance units" print print "Test South-East of origin:" call angleAndDistance ox, oy, SEx, SEy, ang, dist print ang;" degrees", dist;" distance units" print print "Test South of origin:" call angleAndDistance ox, oy, Sx, Sy, ang, dist print ang;" degrees", dist;" distance units" print print "Test South-West of origin:" call angleAndDistance ox, oy, SWx, SWy, ang, dist print ang;" degrees", dist;" distance units" print print "Test West of origin:" call angleAndDistance ox, oy, Wx, Wy, ang, dist print ang;" degrees", dist;" distance units" print print "Test North-West of origin:" call angleAndDistance ox, oy, NWx, NWy, ang, dist print ang;" degrees", dist;" distance units"
'this sub needs Atan2(y, x) Function and r2d gobal constant to convert radians to degrees sub angleAndDistance x1, y1, x2, y2, byref angle, byref distance angle = r2d * Atan2(y2 - y1, x2 - x1) if angle < 0 then angle = angle + 360 distance = sqr((x2 - x1)^2 + (y2 - y1)^2) end sub
' this sub needs global constants pi and d2r for converting degrees to radians Function Atan2(y, x) 'Atan2 is a function which determines the angle between points 'x1, y1 and x2, y2. The angle returned is in radians 'The angle returned is always in the range of '-PI to PI radians (-180 to 180 degrees) '============================================================== 'NOTE the position of Y and X arguments 'This keeps Atan2 function same as other language versions '============================================================== If x = 0 Then If y < 0 Then Atan2 = -1.5707963267948967 Else Atan2 = 1.5707963267948967 End If Else chk = atn(y/x) If x < 0 Then If y < 0 Then chk = chk - 3.1415926535897932 Else chk = chk + 3.1415926535897932 End If End If Atan2 = chk End If 'thanks Andy Amaya
'make the angle 0 degrees (or radians) due North to match maps and compass readings Atan2 = Atan2 - 270 * d2r
'normalize angle between 0 and 2*pi if Atan2 < 0 then Atan2 = Atan2 + 2 * pi End Function
Yeah, same here!
|
|
|
Post by B+ on Jan 8, 2019 15:32:17 GMT
Dang! I just realized, maps probably have y, vertical values, increase from bottom to top, not top to bottom.
Well, this could be fixed for such maps...
|
|
|
Post by Rod on Jan 8, 2019 18:50:06 GMT
Vector maths? point x,y point x1,y1 deltaX, deltaY, distance sqr(abs(dx^2+dy^2)) A practical example of the problem would save a lot of guessing.
|
|
|
Post by B+ on Jan 8, 2019 23:11:47 GMT
OK fixed the sub for y values increasing going up on map, just flip y values from + to - and vice versa!
Here is 10 random cities with their angle and distance calculated from the center (origin) of a map running 500 units East and 500 units West, 300 Units North and 300 units South.
'city map.txt for JB v2.0 B+ 2019-01-08
global pi, d2r, r2d, Directions$ pi = acs(-1) d2r = pi/180 'convert degree angle units to radians r2d = 180/pi 'convert radian angle units to degrees Directions$ = "N NE E SE S SW W NW"
randomize 12 'get same random results
nCities = 10 xmax = 500 xmin = -500 ymax = 300 ymin = -300 centerx = 0 centery = 0
dim cityx(nCities), cityy(nCities) Print "From the map center (0, 0):" print "city X", "city Y", "angle", "distance", "~ direction" for i = 1 to nCities cityx(i) = rand(xmin, xmax) cityy(i) = rand(ymin, ymax) call angleAndDistance 0, 0, cityx(i), cityy(i), a, d d$ = Direction$(a) print cityx(i), cityy(i), a, d, d$ next
function Direction$(degreeAngle) for i = 1 to 8 if i = 1 then if degreeAngle < 27.5 or degreeAngle >= 315 + 27.5 then Direction$ = word$(Directions$, i) : exit function else if degreeAngle < 45 * (i - 1) + 27.5 then Direction$ = word$(Directions$, i) : exit function end if next end function
'this sub needs Atan2(y, x) Function and r2d gobal constant to convert radians to degrees sub angleAndDistance x1, y1, x2, y2, byref angle, byref distance angle = r2d * Atan2(y2 - y1, x2 - x1) if angle < 0 then angle = angle + 360 if angle >= 360 then angle = angle - 360 distance = sqr((x2 - x1)^2 + (y2 - y1)^2) end sub
' this sub needs global constants pi and d2r for converting degrees to radians Function Atan2(y, x) 'Atan2 is a function which determines the angle between points 'x1, y1 and x2, y2. The angle returned is in radians 'The angle returned is always in the range of '-PI to PI radians (-180 to 180 degrees) '============================================================== 'NOTE the position of Y and X arguments 'This keeps Atan2 function same as other language versions '==============================================================
'OK to reverse direction on y to fix increasing y values going from bottom to top of a map y = -1 * y
If x = 0 Then If y < 0 Then Atan2 = -1.5707963267948967 Else Atan2 = 1.5707963267948967 End If Else chk = atn(y/x) If x < 0 Then If y < 0 Then chk = chk - 3.1415926535897932 Else chk = chk + 3.1415926535897932 End If End If Atan2 = chk End If 'thanks Andy Amaya
'make the angle 0 degrees (or radians) due North to match maps and compass readings Atan2 = Atan2 - 270 * d2r
'normalize angle between 0 and 2*pi if Atan2 < 0 then Atan2 = Atan2 + 2 * pi End Function
function rand(lo, hi) rand = int((hi - lo + 1) * rnd(0)) + lo end function
output:
From the map center (0, 0): city X city Y angle distance ~ direction -54 -122 203.875281 133.416641 S -426 -65 261.324598 430.930389 W 108 182 30.6851731 211.631756 NE 153 166 42.6663536 225.754291 NE -242 97 291.842218 260.716321 W -469 -292 238.093554 552.471719 SW 187 166 48.4045183 250.049995 NE 358 42 83.3087356 360.455268 E -193 -42 257.722902 197.517088 W -268 -208 232.184267 339.246223 SW
|
|
|
Post by 2ndtrickop on Jan 9, 2019 2:44:35 GMT
Thanks again, gentlemen ....... we'll have some fun tinkering with this.
|
|
|
Post by bluatigro on Jan 29, 2019 11:37:14 GMT
somthing like this can be useful to
for i = 0 to 360 step 10 print compas$( i ) next i end function compas$( deg ) q$ = "N NNW NW WNW W WZW ZW ZZW Z ZZE ZE EZE E ENE NE NNE N" d = int( deg * 16 / 360 + 1.5 ) compas$ = word$( q$ , d ) end function
|
|