Page 1 of 1

coordinate-transformation

Posted: Thu Jan 05, 2017 1:17 pm
by Joel
Hi Folks,
having appreciated so much the work of Henko, that one can barely keep up with ;-), here my modest first contribution to the library.
It's about coordinate-transformation.
The functions help to transform coordinates from a user-defined coordinate-system to the ipad screen & vice versa - simple but efficient.

Please note that the code contains three sections.
1. section contains a description of all functions
2. section includes a snippet which demonstrates most of the functions - just remove the /*...*/
3. section includes the functions themselves

Hope it is helpful for you...bye, Joel

Code: Select all

/*
'c'-description
'y'-testing
'b'-definitions
''
'c'
returns the "x"- and "y"-coordinate of a point on the ipad-screen. Basis is a user-defined coordinate-system given by xmin, xmax, ymin, ymax 

===========
global Variables
===========
xmin:smallest number of x-range within new coordinate system
xmax:biggest number of x-range
ymin:smallest number of y-range
ymax:biggest number of y-range

by omitting one pair (e.g.:ymin,ymax) those values are then calculated with respect to screen ratio
==========
functions
==========

tc_x(x):

transforms "x"-user-coordinate into "x"-coordinate of ipad-screen. usable with DRAW LINE etc. 
When using PIXEL then call function as:2*tc_x(x) etc.
"sizes" within user-defined system like "width" or "height" must be treated like : 
SIZE tc_x(10)-tc_x(0) which corresponds to SIZE 10 

x: "x"-coordinate within user-defined coordinate-system
----------

btc_x(x):

inverse function of tc_x(x).
returns the "x"-coordinate of the user-defined coordinate-system. Basis is the corresponding point on ipad-screen. e.g. usable when transforming touch-information into user-defined -coordinates
x: x-value of the screen
----------

tc_y(y):

analogue
----------

btc_y(y):

analogue
----------

draw_sys():

draws the two axis of the user-defined coordinate-system
----------

draw_ticks(tick_x,tick_y):

draws ticks in a user-defined coordinate-system
tick_x: x-value of interval for each tick
tick_y: analogue
----------

draw_grid(dx,dy):

draws a grid in a defined coordinate-system
dx: x-value of interval
dy: analogue
----------

get_unit_x():

returns the smallest element on x-scale in respect of displayable points and params xmin, xmax 
(note: DRAW-command etc. NOT PIXEL-command
----------
 
get_unit_y():

analogue
----------

get_ratio():

returns ratio: dy/dx
''
*/

/*
'y'
'testing
sw=SCREEN_WIDTH() ! sh=SCREEN_HEIGHT()
pi=3.14159
OPTION ANGLE RADIANS
GRAPHICS CLEAR 1,1,1
GRAPHICS

'define boundaries of coordinate-system via global variables
xmin=-pi
xmax=pi
ymin=-50
ymax=50

'draw grid
DRAW COLOR 0.9,0.8,1
DRAW SIZE 1
draw_grid(pi/4,10)

'draw axis
DRAW SIZE 3
DRAW DASH 10
DRAW COLOR 0,0,0
draw_sys

'graph
DRAW SIZE 5
DRAW COLOR 1,0,0
DRAW TO tc_x(xmin),tc_y(0)

FOR phi= xmin TO xmax STEP .1
 DRAW LINE TO tc_x(phi),tc_y(10*SIN(phi))
NEXT phi
draw_ticks(pi/2,10)

'set up touch output field
FIELD "touch_output" TEXT "touch x:= "&CHR$(10)&"touch y:= " AT sw*0,sh*0.9 SIZE sw,sh*.1  ML

'touch
LOOP:
SLOWDOWN
GET TOUCH o AS touchx, touchy

'transform ipad-coordinates into user-defined coordinates
bt_touchx=btc_x(touchx) ! bt_touchy=btc_y(touchy)

'output back-transformed touch-coordinates 
IF touchx>0 AND touchy>0 AND bt_touchx>=0 THEN FIELD "touch_output" TEXT "touch x:= "&LEFT$(STR$(bt_touchx/3.1415),4)&"*"&CHR$(960)&CHR$(10) & "touch y:= "&bt_touchy

IF touchx>0 AND touchy>0 AND bt_touchx<0 THEN FIELD "touch_output" TEXT "touch x:= "&LEFT$(STR$(bt_touchx/3.1415),5)&"*"&CHR$(960)&CHR$(10) & "touch y:= "&bt_touchy
GOTO LOOP
''
*/

'b'
DEF tc_x(x)
 'calculate min& max values when those are left to zero respecting screen-ratio 
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 
 'calculate gradient, linear transormation function  
 mx=SCREEN_WIDTH() /(.xmax-.xmin)
 x0=(-1)*.xmin*mx
 tc_x=x*mx+x0
END DEF
'=================
DEF tc_y(y)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 my=SCREEN_HEIGHT() / (.ymin-.ymax)
 y0=(-1)*.ymax*my
 tc_y=y*my+y0
END DEF
'=================
DEF btc_x(x)
 'back-transformation
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 mx=SCREEN_WIDTH() /(.xmax-.xmin)
 x0=(-1)*.xmin*mx
 btc_x=(x-x0)/mx
END DEF 
'=================
DEF btc_y(y)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 my=SCREEN_HEIGHT() / (.ymin-.ymax)
 y0=(-1)*.ymax*my
 btc_y=(y-y0)/my
END DEF
'=================
DEF draw_sys()
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 DRAW LINE tc_x(.xmin),tc_y(0) TO  tc_x(.xmax),tc_y(0)
 DRAW LINE tc_x(0),tc_y(.ymin) TO tc_x(0),tc_y(.ymax)
END DEF 
'================= 
DEF draw_ticks(tick_x,tick_y)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 FOR n=tick_x TO .xmax STEP tick_x
  DRAW LINE tc_x(n),tc_y(0)-5 TO tc_x(n), tc_y(0)+5
 NEXT n
 
 FOR n= -tick_x TO .xmin STEP -tick_x
  DRAW LINE tc_x(n),tc_y(0)-5 TO tc_x(n), tc_y(0)+5 
 NEXT n
 
 
 FOR n=tick_y TO .yMAX STEP tick_y 
  DRAW LINE tc_x(0)-5,tc_y(n) TO tc_x(0)+5, tc_y(n)
 NEXT n
 
 FOR n=-tick_y TO .ymin STEP -tick_y
  DRAW LINE tc_x(0)-5,tc_y(n) TO tc_x(0)+5, tc_y(n)
 NEXT n
END DEF 
'=================
DEF draw_grid(d_x, d_y)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 
 FOR x=d_x TO .xmax STEP d_x
  DRAW LINE tc_x(x),tc_y(.ymin) TO tc_x(x), tc_y(.ymax)
 NEXT x 
 
 FOR x=d_x TO .xmin STEP -d_x
  DRAW LINE tc_x(x),tc_y(.ymin) TO tc_x(x), tc_y(.ymax)
 NEXT x
 
 FOR y=d_y TO .ymax STEP d_y
  DRAW LINE tc_x(.xmin),tc_y(y) TO tc_x(.xmax),tc_y(y)
 NEXT y 
 
 FOR y=d_y TO .ymin STEP -d_y
  DRAW LINE tc_x(.xmin),tc_y(y) TO tc_x(.xmax),tc_y(y)
 NEXT y 
 
END DEF
'=================
DEF get_unit_x
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 get_unit_x= (.xmax-.xmin)/SCREEN_WIDTH() 
END DEF
'=================
DEF get_unit_y
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 get_unit_y= (.ymax-.ymin)/SCREEN_HEIGHT()
END DEF 
'=================
DEF get_ratio
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 get_ratio= (.ymax-.ymin)/(.xmax-.xmin)
END DEF
 

Re: coordinate-transformation

Posted: Sat Jan 07, 2017 5:56 am
by GeorgeMcGinn
Hi Joel,

Thanks for the program, and I am probably asking a silly question (I just ate crow, so I am entitled :D

Anyway, how did you get around the fact that the distance between two GPS coordinates deal with a spherical surface and the screen of an iPad/iPhone is flat?

Playing around with your code may answer my question, but I figured I would ask for all the non-math majors out there.

George.

Re: coordinate-transformation

Posted: Sat Jan 07, 2017 10:07 am
by Joel
Hi George,
thanks for your question which is not silly at all.
Normally you would use some kind of projection to display spherical geometry on a flat surface.
Mercator projection would be used a lot, besides the simplier Lambert conic projection which is still used in some aviation-charts (vfr but also ifr near 45 degrees with true angles...).

Would be fun to extend my libs to that calculation.

Actually that lib doesn't make a lot, but linear transforming the coordinates from one system to the other...

Bye, Joel

N.B. So.. you guys in Florida are eating crows ?? ;-)

Re: coordinate-transformation - pinch-function added

Posted: Sat Jan 07, 2017 11:21 am
by Joel
Added a two-finger-pinch-and-drag function.
For use as a lib just remove the yellow demo-section

Code: Select all


/*
'c'-description
'y'-testing
'b'-definitions
''
'c'
returns the "x"- and "y"-coordinate of a point on the ipad-screen. Basis is a user-defined coordinate-system given by xmin, xmax, ymin, ymax 

===========
global Variables
===========
xmin:smallest number of x-range within new coordinate system
xmax:biggest number of x-range
ymin:smallest number of y-range
ymax:biggest number of y-range

by omitting one pair (e.g.:ymin,ymax) those values are then calculated with respect to screen ratio
==========
functions
==========

tc_x(x):

transforms "x"-user-coordinate into "x"-coordinate of ipad-screen. usable with DRAW LINE etc. 
When using PIXEL then call function as:2*tc_x(x) etc.
"sizes" within user-defined system like "width" or "height" must be treated like : 
SIZE tc_x(10)-tc_x(0) which corresponds to SIZE 10 

x: "x"-coordinate within user-defined coordinate-system
----------

btc_x(x):

inverse function of tc_x(x).
returns the "x"-coordinate of the user-defined coordinate-system. Basis is the corresponding point on ipad-screen. e.g. usable when transforming touch-information into user-defined -coordinates
x: x-value of the screen
----------

tc_y(y):

analogue
----------

btc_y(y):

analogue
----------

draw_sys():

draws the two axis of the user-defined coordinate-system
----------

draw_ticks(tick_x,tick_y):

draws ticks in a user-defined coordinate-system
tick_x: x-value of interval for each tick
tick_y: analogue
----------

draw_grid(dx,dy):

draws a grid in a defined coordinate-system
dx: x-value of interval
dy: analogue
----------

get_unit_x():

returns the smallest element on x-scale in respect of displayable points and params xmin, xmax 
(note: DRAW-command etc. NOT PIXEL-command
----------
 
get_unit_y():

analogue
----------

get_ratio():

returns ratio: dy/dx
''
*/


'y'
'testing
sw=SCREEN_WIDTH() ! sh=SCREEN_HEIGHT()
pi=3.14159
OPTION ANGLE RADIANS
GRAPHICS CLEAR 1,1,1
GRAPHICS

'define boundaries of coordinate-system via global variables
xmin=-pi
xmax=pi
ymin=-50
ymax=50

paint:
'draw grid
DRAW COLOR 0.9,0.8,1
DRAW SIZE 1
draw_grid(pi/4,10)

'draw axis
DRAW SIZE 3
'DRAW DASH 10
DRAW COLOR 0,0,0
draw_sys

'graph
DRAW SIZE 5
DRAW COLOR 1,0,0
DRAW TO tc_x(xmin),tc_y(0)

FOR phi= xmin TO xmax STEP .1
 DRAW LINE TO tc_x(phi),tc_y(10*SIN(phi))
NEXT phi

DRAW TO tc_x(xmin),tc_y(0)
FOR phi= xmin TO xmax STEP .1
 DRAW LINE TO tc_x(phi),tc_y((phi^3))
NEXT phi

draw_ticks(pi/2,10)

'set up touch output field
FIELD "touch_output" TEXT "touch x:= "&CHR$(10)&"touch y:= " AT sw*0,sh*0.9 SIZE sw,sh*.1  ML

'touch
LOOP:
SLOWDOWN
GET TOUCH 0 AS touchx, touchy
GET TOUCH 1 AS touch1_x,touch1_y

IF pinch(touchx,touchy,touch1_x,touch1_y) =1 THEN
 GRAPHICS CLEAR 1,1,1
 GOTO paint
ENDIF 

'transform ipad-coordinates into user-defined coordinates
bt_touchx=btc_x(touchx) ! bt_touchy=btc_y(touchy)

'output back-transformed touch-coordinates 
IF touchx>0 AND touchy>0 AND bt_touchx>=0 THEN FIELD "touch_output" TEXT "touch x:= "&LEFT$(STR$(bt_touchx/3.1415),4)&"*"&CHR$(960)&CHR$(10) & "touch y:= "&bt_touchy

IF touchx>0 AND touchy>0 AND bt_touchx<0 THEN FIELD "touch_output" TEXT "touch x:= "&LEFT$(STR$(bt_touchx/3.1415),5)&"*"&CHR$(960)&CHR$(10) & "touch y:= "&bt_touchy
GOTO LOOP
''

'b'

DEF pinch(t0_x,t0_y,t1_x,t1_y)
  IF old_pinch=0 AND t1_x>0 THEN 'new touch with 2 fingers?
   old_pinch=1
   xmin=.xmin ! xmax=.xmax ! ymin=.ymin ! ymax=.ymax
   t0_x_first=btc_x2(t0_x) ! t0_y_first=btc_y2(t0_y) ! t1_x_first=btc_x2(t1_x) ! t1_y_first=btc_y2(t1_y)
  ENDIF
  
  IF t1_x<0 OR t0_x<0 THEN 'finger released? 
   old_pinch=0
   RETURN -1
  ENDIF
  
  t0_x_last=btc_x2(t0_x) ! t0_y_last=btc_y2(t0_y) ! t1_x_last=btc_x2(t1_x) ! t1_y_last=btc_y2(t1_y)
 
 .xmin=xmin+(MIN(t0_x_first,t1_x_first)-MIN(t0_x_last,t1_x_last)) 
 .xmax=xmax+(MAX(t0_x_first,t1_x_first)-MAX(t0_x_last,t1_x_last))
 .ymax=ymax+(MAX(t0_y_first,t1_y_first)-MAX(t0_y_last,t1_y_last))
 .ymin=ymin+(MIN(t0_y_first,t1_y_first)-MIN(t0_y_last,t1_y_last))

RETURN 1
END DEF
'=================
DEF tc_x(x)
 'calculate min& max values when those are left to zero respecting screen-ratio 
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 
 'calculate gradient, linear transormation function  
 mx=SCREEN_WIDTH() /(.xmax-.xmin)
 x0=(-1)*.xmin*mx
 tc_x=x*mx+x0
END DEF
'=================
DEF tc_y(y)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 my=SCREEN_HEIGHT() / (.ymin-.ymax)
 y0=(-1)*.ymax*my
 tc_y=y*my+y0
END DEF
'=================
DEF btc_x(x)
 'back-transformation
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 mx=SCREEN_WIDTH() /(.xmax-.xmin)
 x0=(-1)*.xmin*mx
 btc_x=(x-x0)/mx
END DEF 
'=================
DEF btc_y(y)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 my=SCREEN_HEIGHT() / (.ymin-.ymax)
 y0=(-1)*.ymax*my
 btc_y=(y-y0)/my
END DEF
'=================
DEF btc_x2(x)
 'back-transformation
 mx=SCREEN_WIDTH() /(pinch.xmax-pinch.xmin)
 x0=(-1)*pinch.xmin*mx
 btc_x2=(x-x0)/mx
END DEF 
'=================
DEF btc_y2(y)
 my=SCREEN_HEIGHT() / (pinch.ymin-pinch.ymax)
 y0=(-1)*pinch.ymax*my
 btc_y2=(y-y0)/my
END DEF
'=================

DEF draw_sys()
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 DRAW LINE tc_x(.xmin),tc_y(0) TO  tc_x(.xmax),tc_y(0)
 DRAW LINE tc_x(0),tc_y(.ymin) TO tc_x(0),tc_y(.ymax)
END DEF 
'================= 
DEF draw_ticks(tick_x,tick_y)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 FOR n=tick_x TO .xmax STEP tick_x
  DRAW LINE tc_x(n),tc_y(0)-5 TO tc_x(n), tc_y(0)+5
 NEXT n
 
 FOR n= -tick_x TO .xmin STEP -tick_x
  DRAW LINE tc_x(n),tc_y(0)-5 TO tc_x(n), tc_y(0)+5 
 NEXT n
 
 
 FOR n=tick_y TO .yMAX STEP tick_y 
  DRAW LINE tc_x(0)-5,tc_y(n) TO tc_x(0)+5, tc_y(n)
 NEXT n
 
 FOR n=-tick_y TO .ymin STEP -tick_y
  DRAW LINE tc_x(0)-5,tc_y(n) TO tc_x(0)+5, tc_y(n)
 NEXT n
END DEF 
'=================
DEF draw_grid(d_x, d_y)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 
 FOR x=d_x TO .xmax STEP d_x
  DRAW LINE tc_x(x),tc_y(.ymin) TO tc_x(x), tc_y(.ymax)
 NEXT x 
 
 FOR x=d_x TO .xmin STEP -d_x
  DRAW LINE tc_x(x),tc_y(.ymin) TO tc_x(x), tc_y(.ymax)
 NEXT x
 
 FOR y=d_y TO .ymax STEP d_y
  DRAW LINE tc_x(.xmin),tc_y(y) TO tc_x(.xmax),tc_y(y)
 NEXT y 
 
 FOR y=d_y TO .ymin STEP -d_y
  DRAW LINE tc_x(.xmin),tc_y(y) TO tc_x(.xmax),tc_y(y)
 NEXT y 
 
END DEF
'=================
DEF get_unit_x
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 get_unit_x= (.xmax-.xmin)/SCREEN_WIDTH() 
END DEF
'=================
DEF get_unit_y
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 get_unit_y= (.ymax-.ymin)/SCREEN_HEIGHT()
END DEF 
'=================
DEF get_ratio
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 get_ratio= (.ymax-.ymin)/(.xmax-.xmin)
END DEF
 

Re: coordinate-transformation

Posted: Wed Jan 11, 2017 4:48 am
by GeorgeMcGinn
Originally from upstate NY.

But we eat crow when we step in it without thinking :?
Joel wrote:
Sat Jan 07, 2017 10:07 am
Hi George,
thanks for your question which is not silly at all.
Normally you would use some kind of projection to display spherical geometry on a flat surface.
Mercator projection would be used a lot, besides the simplier Lambert conic projection which is still used in some aviation-charts (vfr but also ifr near 45 degrees with true angles...).

Would be fun to extend my libs to that calculation.

Actually that lib doesn't make a lot, but linear transforming the coordinates from one system to the other...

Bye, Joel

N.B. So.. you guys in Florida are eating crows ?? ;-)

Re: coordinate-transformation

Posted: Wed Jan 11, 2017 4:49 am
by GeorgeMcGinn
Along with aviation charts, nautical charts probably use the same projection.

George.
Joel wrote:
Sat Jan 07, 2017 10:07 am
Hi George,
thanks for your question which is not silly at all.
Normally you would use some kind of projection to display spherical geometry on a flat surface.
Mercator projection would be used a lot, besides the simplier Lambert conic projection which is still used in some aviation-charts (vfr but also ifr near 45 degrees with true angles...).

Would be fun to extend my libs to that calculation.

Actually that lib doesn't make a lot, but linear transforming the coordinates from one system to the other...

Bye, Joel

N.B. So.. you guys in Florida are eating crows ?? ;-)

Re: coordinate-transformation

Posted: Wed Jan 11, 2017 10:08 am
by Joel
Same problem here...so many crows!! But in my experience, down there you'll find more intelligence than in some upper spheres...

btw.:In facts of projection and displaying maps on ipad: I would strongly recommend to have a look to the extraordinary work of Dutchman. (Just sort the threads by number of replies and you'll see Mercator as a cue...)

Re: coordinate-transformation

Posted: Thu Jan 12, 2017 6:03 am
by GeorgeMcGinn
Thanks.

I downloaded his Mercator programs and he did an excellent job. However, I messed it up and forgot to make a backup and my copy doesn't work. (I sometimes like to break things, not on purpose. But to learn) and he's got such great coding in it.

George.
Joel wrote:
Wed Jan 11, 2017 10:08 am
Same problem here...so many crows!! But in my experience, down there you'll find more intelligence than in some upper spheres...

btw.:In facts of projection and displaying maps on ipad: I would strongly recommend to have a look to the extraordinary work of Dutchman. (Just sort the threads by number of replies and you'll see Mercator as a cue...)

Re: coordinate-transformation

Posted: Thu Jan 12, 2017 4:25 pm
by Joel
added rotation to the lib. just turn the device a little bit...and don't forget to check this out: pinch and two-finger-drag-function

(included maths-lib this time-so it works without further including libs)

ciao, joel.

Code: Select all

/*
'c'-description
'y'-testing
'b'-definitions
''
'c'
returns the "x"- and "y"-coordinate of a point on the ipad-screen. Basis is a user-defined coordinate-system given by xmin, xmax, ymin, ymax 

===========
global Variables
===========
xmin:smallest number of x-range within new coordinate system
xmax:biggest number of x-range
ymin:smallest number of y-range
ymax:biggest number of y-range

by omitting one pair (e.g.:ymin,ymax) those values are then calculated with respect to screen ratio
==========
functions
==========

tc_x(x):

transforms "x"-user-coordinate into "x"-coordinate of ipad-screen. usable with DRAW LINE etc. 
When using PIXEL then call function as:2*tc_x(x) etc.
"sizes" within user-defined system like "width" or "height" must be treated like : 
SIZE tc_x(10)-tc_x(0) which corresponds to SIZE 10 

x: "x"-coordinate within user-defined coordinate-system
----------

btc_x(x):

inverse function of tc_x(x).
returns the "x"-coordinate of the user-defined coordinate-system. Basis is the corresponding point on ipad-screen. e.g. usable when transforming touch-information into user-defined -coordinates
x: x-value of the screen
----------

tc_y(y):

analogue
----------

btc_y(y):

analogue
----------

draw_sys():

draws the two axis of the user-defined coordinate-system
----------

draw_ticks(tick_x,tick_y):

draws ticks in a user-defined coordinate-system
tick_x: x-value of interval for each tick
tick_y: analogue
----------

draw_grid(dx,dy):

draws a grid in a defined coordinate-system
dx: x-value of interval
dy: analogue
----------

get_unit_x():

returns the smallest element on x-scale in respect of displayable points and params xmin, xmax 
(note: DRAW-command etc. NOT PIXEL-command
----------
 
get_unit_y():

analogue
----------

get_ratio():

returns ratio: dy/dx
----------

pinch(touch0_x,touch0_y,touch1_x,touch1_y)

to use with:
GET TOUCH 0 AS touch0_x, touch0_y
GET TOUCH 1 AS touch1_x, touch1_y
in the main-program (for time-efficiency)

returns -1 if at least one finger has been released
returns 1 if both fingers on screen
changes the global variables: xmin,xmax,ymin,ymax
''
*/

'y'
test2:
GRAPHICS
REFRESH OFF
GET ORIENTATION p
SET ORIENTATION p

xmin=-5
xmax=5
'ymin=-5
'ymax=5

OPTION ANGLE DEGREES
DRAW SIZE 2

'r'
test2loop:
'y'

tau=-(ATAN2(ACCEL_Y(),ACCEL_X())-ATAN2(1,0))

GET TOUCH 0 AS touch0_x, touch0_y
GET TOUCH 1 AS touch1_x, touch1_y
pinch(touch0_x,touch0_y,touch1_x,touch1_y)

GRAPHICS CLEAR .5,.5,.5
DRAW COLOR 1,1,1
draw_sysr(tau)
draw_ticksr(1,1,tau)
'DRAW LINE tc_x(0),tc_y(0) TO tc_x(1),tc_y(0)
DRAW COLOR 1,0,0
DRAW LINE tcr_x(0,0,tau),tcr_y(0,0,tau) TO tcr_x(3,1,tau),tcr_y(3,1,tau)
REFRESH
GOTO test2loop
RETURN 'of test2
''

'b'

DEF tcr_x(x,y,tau)
 RETURN tc_x(rot_x(x,y,tau))
END DEF
'=================
DEF tcr_y(x,y,tau)
 RETURN tc_y(rot_y(x,y,tau))
END DEF
'=================
DEF rot_x(x,y,tau)
 phi=ATAN2(y,x)
 r=SQR(x*x+y*y)
 RETURN r*COS(phi+tau)
END DEF
'=================
DEF rot_y(x,y,tau)
 phi=ATAN2(y,x)
 r=SQR(x*x+y*y)
 RETURN r*SIN(phi+tau)
END DEF
'=================
DEF tc_x(x)
 'calculate min& max values when those are left to zero respecting screen-ratio 
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 
 'calculate gradient, linear transormation function  
 mx=SCREEN_WIDTH() /(.xmax-.xmin)
 x0=(-1)*.xmin*mx
 tc_x=x*mx+x0
END DEF
'=================
DEF tc_y(y)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 my=SCREEN_HEIGHT() / (.ymin-.ymax)
 y0=(-1)*.ymax*my
 tc_y=y*my+y0
END DEF
'=================
DEF btc_x(x)
 'back-transformation
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 mx=SCREEN_WIDTH() /(.xmax-.xmin)
 x0=(-1)*.xmin*mx
 btc_x=(x-x0)/mx
END DEF 
'=================
DEF btc_y(y)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 my=SCREEN_HEIGHT() / (.ymin-.ymax)
 y0=(-1)*.ymax*my
 btc_y=(y-y0)/my
END DEF
'=================
DEF btc_x2(x)
 'back-transformation
 mx=SCREEN_WIDTH() /(pinch.xmax-pinch.xmin)
 x0=(-1)*pinch.xmin*mx
 btc_x2=(x-x0)/mx
END DEF 
'=================
DEF btc_y2(y)
 my=SCREEN_HEIGHT() / (pinch.ymin-pinch.ymax)
 y0=(-1)*pinch.ymax*my
 btc_y2=(y-y0)/my
END DEF
'=================
DEF draw_sysr(tau)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 DRAW LINE tcr_x(.xmin,0,tau),tcr_y(.xmin,0,tau) TO  tcr_x(.xmax,0,tau),tcr_y(.xmax,0,tau)
 DRAW LINE tcr_x(0,.ymin,tau),tcr_y(0,.ymin,tau) TO tcr_x(0,.ymax,tau),tcr_y(0,.ymax,tau)
END DEF
'=================
DEF draw_sys()
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 DRAW LINE tc_x(.xmin),tc_y(0) TO  tc_x(.xmax),tc_y(0)
 DRAW LINE tc_x(0),tc_y(.ymin) TO tc_x(0),tc_y(.ymax)
END DEF 
'================= 
DEF draw_ticks(tick_x,tick_y)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 FOR n=tick_x TO .xmax STEP tick_x
  DRAW LINE tc_x(n),tc_y(0)-5 TO tc_x(n), tc_y(0)+5
 NEXT n
 
 FOR n= -tick_x TO .xmin STEP -tick_x
  DRAW LINE tc_x(n),tc_y(0)-5 TO tc_x(n), tc_y(0)+5 
 NEXT n
 
 
 FOR n=tick_y TO .yMAX STEP tick_y 
  DRAW LINE tc_x(0)-5,tc_y(n) TO tc_x(0)+5, tc_y(n)
 NEXT n
 
 FOR n=-tick_y TO .ymin STEP -tick_y
  DRAW LINE tc_x(0)-5,tc_y(n) TO tc_x(0)+5, tc_y(n)
 NEXT n
END DEF 
'=================
DEF draw_ticksr(tick_x,tick_y,tau)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 
 FOR n=tick_x TO .xmax STEP tick_x
  DRAW LINE tcr_x(n,-5*get_unit_y,tau),tcr_y(n,-5*get_unit_y,tau) TO tcr_x(n,5*get_unit_y,tau), tcr_y(n,5*get_unit_y,tau)
 NEXT n
 
 FOR n= -tick_x TO .xmin STEP -tick_x
  DRAW LINE tcr_x(n,-5*get_unit_y,tau),tcr_y(n,-5*get_unit_y,tau) TO tcr_x(n,5*get_unit_y,tau), tcr_y(n,5*get_unit_y,tau) 
 NEXT n
 
 
 FOR n=tick_y TO .yMAX STEP tick_y 
  DRAW LINE tcr_x(-5*get_unit_x,n,tau),tcr_y(-5*get_unit_x,n,tau) TO tcr_x(5*get_unit_x,n,tau), tcr_y(5*get_unit_x,n,tau)
 NEXT n
 
 FOR n=-tick_y TO .ymin STEP -tick_y
  DRAW LINE tcr_x(-5*get_unit_x,n,tau),tcr_y(-5*get_unit_x,n,tau) TO tcr_x(5*get_unit_x,n,tau), tcr_y(5*get_unit_x,n,tau)
 NEXT n
END DEF
'=================
DEF draw_grid(d_x, d_y)
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF
 
 FOR x=d_x TO .xmax STEP d_x
  DRAW LINE tc_x(x),tc_y(.ymin) TO tc_x(x), tc_y(.ymax)
 NEXT x 
 
 FOR x=d_x TO .xmin STEP -d_x
  DRAW LINE tc_x(x),tc_y(.ymin) TO tc_x(x), tc_y(.ymax)
 NEXT x
 
 FOR y=d_y TO .ymax STEP d_y
  DRAW LINE tc_x(.xmin),tc_y(y) TO tc_x(.xmax),tc_y(y)
 NEXT y 
 
 FOR y=d_y TO .ymin STEP -d_y
  DRAW LINE tc_x(.xmin),tc_y(y) TO tc_x(.xmax),tc_y(y)
 NEXT y 
 
END DEF
'=================
DEF get_unit_x
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 get_unit_x= (.xmax-.xmin)/SCREEN_WIDTH() 
END DEF
'=================
DEF get_unit_y
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 get_unit_y= (.ymax-.ymin)/SCREEN_HEIGHT()
END DEF 
'=================
DEF get_ratio
 IF .ymin=0 AND .ymax=0 THEN 
  .ymin=.xmin*SCREEN_HEIGHT()/SCREEN_WIDTH() ! .ymax=.xmax*SCREEN_HEIGHT()/SCREEN_WIDTH()
 ENDIF
 IF .xmin=0 AND .xmax=0 THEN 
  .xmin=.ymin*SCREEN_WIDTH()/SCREEN_HEIGHT() ! .xmax=.ymax*SCREEN_WIDTH()/SCREEN_HEIGHT()
 ENDIF 
 get_ratio= (.ymax-.ymin)/(.xmax-.xmin)
END DEF
'================= 
DEF pinch(t0_x,t0_y,t1_x,t1_y)
  IF old_pinch=0 AND t1_x>0 THEN 'new touch with 2 fingers?
   old_pinch=1
   xmin=.xmin ! xmax=.xmax ! ymin=.ymin ! ymax=.ymax
   t0_x_first=btc_x2(t0_x) ! t0_y_first=btc_y2(t0_y) ! t1_x_first=btc_x2(t1_x) ! t1_y_first=btc_y2(t1_y)
  ENDIF
  
  IF t1_x<0 OR t0_x<0 THEN 'finger released? 
   old_pinch=0
   RETURN -1
  ENDIF
  
  t0_x_last=btc_x2(t0_x) ! t0_y_last=btc_y2(t0_y) ! t1_x_last=btc_x2(t1_x) ! t1_y_last=btc_y2(t1_y)
 
 .xmin=xmin+(MIN(t0_x_first,t1_x_first)-MIN(t0_x_last,t1_x_last)) 
 .xmax=xmax+(MAX(t0_x_first,t1_x_first)-MAX(t0_x_last,t1_x_last))
 .ymax=ymax+(MAX(t0_y_first,t1_y_first)-MAX(t0_y_last,t1_y_last))
 .ymin=ymin+(MIN(t0_y_first,t1_y_first)-MIN(t0_y_last,t1_y_last))

RETURN 1
END DEF
'=================
/*
DEF follow_c(z(),v(),alph_max,z1) 'returns complex number of position
 index=OPTION_BASE()
 
 v_bearing=
END DEF  
*/


'===========included maths=============

'returns a string of length L with random letters from a...z
DEF str_rnd$(L)
 letter$=""
 FOR n=1 TO l
  letter$= letter$&CHR$(i_rnd(ASC("a"),ASC("z")))
 NEXT n
 RETURN letter$
END DEF

'returns a random number between [a...b] only once by calling the function until all numbers have been returned
'returns -1 when all numbers have been returned 
'control = 1: creates tupple of numbers [a...b] 
'control=0: returns randomly a number of above created tupples and removes it 
DEF t_rnd(a,b,control)
 OPTION SORT DESCENDING
 optionbase=OPTION_BASE()
 
 IF control=1 THEN 'new
  num_elements=b-a+1
  DIM m(num_elements)
  n=0
  WHILE n<num_elements
   m(n+optionbase)=a
   a=a+1
   n=n+1
  END WHILE
 ENDIF
 
 IF control=0 THEN 'return rnd and reduce
  IF num_elements=0 THEN RETURN -1
  SORT m
  random=RND(num_elements)+optionbase
  number=m(random)
  m(random)=0
  num_elements=num_elements-1
  
  'DEBUG PAUSE
  RETURN number
 ENDIF
END DEF
'==========
DEF i_rnd(a,b) 'returns random integer between two given numbers [a,b]
 i_rnd=FLOOR((b+1-a) *RND(1)+a)
END DEF
'==========
DEF  r_rnd(a,b) 'returns random real number between two given real numbers (a,b) 
 r_rnd=(b-a)*RND(1)+a
END DEF
'==========
DEF phi_vector(x1,y1,x2,y2) 'angle phi of a vector defined by two points 
 delta_y=y2-y1 ! delta_x=x2-x1
 phi_vector=ATAN2(delta_y,delta_x)
END DEF
'==========
DEF phi_vectors(v1x1,v1y1,v1x2,v1y2,v2x1,v2y1,v2x2,v2y2) 'v1 to v2 in mathematical sense
 phi_vectors=phi_vector(v2x1,v2y1,v2x2,v2y2)-phi_vector(v1x1,v1y1,v1x2,v1y2)
END DEF
'==========
'returns the distance to the nearest number (grid*n+anchor) of a where n is a natural number. (e.g. glueing-to-grid-function of a with c as anchor and b as the gridsize around that anchored point.
DEF nearest(a,grid,anchor) 
 grid=ABS(grid)
 IF grid-(ABS(a-anchor)%grid)>(ABS(a-anchor)%grid) THEN 
  'ifthen=1
  nearest=-1*SIGN(a-anchor)*(ABS(a-anchor)%grid) 
 ELSE 
  'ifthen=2
  nearest=SIGN(a-anchor)*(grid-(ABS(a-anchor)%grid))
 ENDIF
 'IF b-((a-anchor)%b)>((a-anchor)%b) THEN nearest=-1*((a-anchor)%b) ELSE nearest=b-((a-anchor)%b)
END DEF
'===========
'returns the nearest number to a with a grid and its anchor
DEF nearest2(a,grid,anchor) 
 grid=ABS(grid)
 IF grid-(ABS(a-anchor)%grid)>(ABS(a-anchor)%grid) THEN  
  'ifthen=1
  nearest2=-1*SIGN(a-anchor)*(ABS(a-anchor)%grid)+a
 ELSE 
  'ifthen=2
  nearest2=SIGN(a-anchor)*(grid-(ABS(a-anchor)%grid))+a
 ENDIF
END DEF
'==========
'returns the gridposition of a within the grid anchored in anchor. gridpos of anchor = 0
'difference to nearest2(...): this function counts the "gridlines" to 'a' while nearest2 returns the distance 
DEF gridpos(a,grid,anchor)
  grid=ABS(grid)
  IF grid-(ABS(a-anchor)%grid)>(ABS(a-anchor)%grid) THEN  
   m_nearest=-1*SIGN(a-anchor)*(ABS(a-anchor)%grid)+a
  ELSE 
   m_nearest=SIGN(a-anchor)*(grid-(ABS(a-anchor)%grid))+a
  ENDIF
 gridpos=(m_nearest-anchor)/grid
END DEF
'==========
'returns the number related to gridposition n dependent on gridsize (grid) and anchor. complementary of nearest2.
DEF nextn(n,grid,anchor)
 n=INT(n)
 nextn=anchor+grid*n
END DEF
'==========
'returns the nth value of a line with length starting in anchor and divided in a number of sections num_section 
DEF divide(anchor,length,num_section,n)
 length_section=length/num_section
 divide= length_section*n+anchor 
END DEF
'==========
DEF point_on_orthog(px,py,lpx1,lpy1,lpx2,lpy2)
 IF (lpx1=lpx2 AND lpy1<>lpy2) OR (lpx1<>lpx2 AND lpy1=lpy2) THEN
  'orthogonal and no point instead of line
  IF lpx1=lpx2 THEN
   'senkrechte
   IF px=lpx1 AND py>=MIN(lpy1,lpy2) AND py<=MAX(lpy1,lpy2) THEN RETURN (py-lpy1)/(lpy2-lpy1)
  ELSE
   'waagrechte
   IF py=lpy1 AND px>=MIN(lpx1,lpx2) AND px<=MAX(lpx1,lpx2) THEN RETURN (px-lpx1)/(lpx2-lpx1)
  ENDIF 
  RETURN -1
 ELSE 'not orthogonal
  RETURN -1
 ENDIF     
END DEF
'==========
'returns -1 if point is off line. otherweise returns a value between [0,1] equivalent to the relation to the length of the line  
DEF point_on_line(px,py,lpx1,lpy1,lpx2,lpy2)
 d_ly=lpy2-lpy1 ! d_lx=lpx2-lpx1
 m=(d_ly)/(d_lx) 'gradient of the line
 IF px-lpx1<>0 THEN 'check division by zero
  IF m<>(py-lpy1)/(px-lpx1) THEN 
   RETURN -1
  ELSE
   point_line_relation=(py-lpy1)/d_ly 'actual calculation of relation
   RETURN point_line_relation 
  ENDIF
 ELSE 'divisor = 0
  IF py-lpy1=0 THEN RETURN 0 'd_x and d_y=0 so point is in the origin of the line
 ENDIF 
END DEF
'============
DEF length_line(lpx1,lpy1,lpx2,lpy2)
 d_y=lpy2-lpy1 ! d_x=lpx2-lpx1
 length=SQR(d_y*d_y+d_x*d_x)
 RETURN length
END DEF
'============
'returns point on the line px with distance lambda from origin of line (lpx1,lpy1). lambda=1 is length of line.  
DEF px_to_line(lambda,lpx1,lpy1,lpx2,lpy2)
 d_x=lpx2-lpx1
 px=d_x*lambda+lpx1
 RETURN px
END DEF
'============
'analogue
DEF py_to_line(lambda,lpx1,lpy1,lpx2,lpy2)
 d_y=lpy2-lpy1
 py=d_y*lambda+lpy1
 RETURN py
END DEF
'============
'counts the occurrances of a sub$ within a string$
'"xx" in "xxxx" will be counted as 2
DEF count_instr(string$,SUB$)
 _base_=OPTION_BASE()
 result=INSTR(string$,SUB$)
 IF result=-1 THEN  RETURN 0
 IF result=LEN(string$)-LEN(SUB$)+_base_ THEN RETURN 1 
 RETURN 1+ count_instr(MID$(string$,result+LEN(SUB$)),SUB$)
END DEF
'============
'returns the number of data separated by separator$
'";" will be counted as 2 (";" is separator)
'"asd" will be counted as 1 (";" is separator)
DEF lensepstr(string$,separator$)
 RETURN count_instr(string$,separator$)+1    
END DEF
'============
'returns a substring within a given string$ with trenn$ as separator and thus dividing the string in sections
DEF insepstr$(section,s1$,S2$)
 IF MAX(LEN(s1$),LEN(s2$))=LEN(s1$) THEN 's1 the longest?
  separator$=s2$ ! string$=s1$ 'shortest is separator
 ELSE
  string$=s2$ ! separator$=s1$
 ENDIF
  
 IF string$="" THEN RETURN "ERROR" '-1 problematisch bei der auswertung. Stoppzeichen definieren und übergeben?
 'insepstr$(2,",","123,4567,890") -> 4567
 option_base_=OPTION_BASE()
 OPTION BASE 1
 length=LEN(string$)
 IF INSTR(string$,separator$,1)=-1 AND section=1 THEN RETURN string$ '-1 'trennzeichen nicht vorhanden
 pos2=0
 FOR n= 1 TO section
  pos1=pos2+1 
  IF pos1<=LEN(string$) THEN pos2=INSTR(string$,separator$,pos1) ELSE RETURN "ERROR" '-1
  IF pos2 = -1 THEN BREAK 'letztes komma fehlt
 NEXT n
  IF n=section AND pos1<=length THEN pos2=length+1 'letzte komma fehlt
  IF n<section THEN RETURN "ERROR" '-1 'weniger sections als erwartet
  '(n=section und noch zeichen übrig: letztes komma fehlt, sonst zuwenig sections
  
  RETURN MID$(string$,pos1,pos2-pos1)
 OPTION BASE option_base_
END DEF
'===========
'returns x-coordinate of x-ing point of to orthogonal lines.returns -1e30 if no intersection
DEF orthog_cross_x(L1x1,L1y1,L1x2,L1y2,L2x1,L2y1,L2x2,L2y2)
 L1(1,1)=L1x1
 L1(1,2)=L1y1
 L1(2,1)=L1x2
 L1(2,2)=L1y2
 
 L2(1,1)=L2x1
 L2(1,2)=L2y1
 L2(2,1)=L2x2
 L2(2,2)=L2y2
 
 IF L1(1,1)=L1(2,1) THEN bool(1)=1
 IF L1(1,2)=L1(2,2) THEN bool(2)=1
 IF L2(1,1)=L2(2,1) THEN bool(3)=1
 IF L2(1,2)=L2(2,2) THEN bool(4)=1
 
 IF (bool(1)=0 AND bool(2)=1 AND bool(3)=1 AND bool(4)=0) OR (bool(1)=1 AND bool(2)=0 AND bool(3)=0 AND bool(4)=1) THEN
  'orthogonal
  IF bool(1)=1  THEN 
   x=L1(1,1) ! y=L2(1,2)
  ELSE
   x=L2(1,1) ! y=L1(1,2)
  ENDIF
 'now check if point is on one line
 IF point_on_orthog(x,y,L1x1,L1y1,L1x2,L1y2)>0 AND point_on_orthog(x,y,L2x1,L2y1,L2x2,L2y2)>0 THEN RETURN x
 ELSE 'not orthogonal
  RETURN -1e308
 ENDIF   
END DEF
'===========
'returns x-coordinate of x-ing point of to orthogonal lines.returns -1e30 if no intersection
DEF orthog_cross_y(L1x1,L1y1,L1x2,L1y2,L2x1,L2y1,L2x2,L2y2)
 L1(1,1)=L1x1
 L1(1,2)=L1y1
 L1(2,1)=L1x2
 L1(2,2)=L1y2
 
 L2(1,1)=L2x1
 L2(1,2)=L2y1
 L2(2,1)=L2x2
 L2(2,2)=L2y2
 
 IF L1(1,1)=L1(2,1) THEN bool(1)=1
 IF L1(1,2)=L1(2,2) THEN bool(2)=1
 IF L2(1,1)=L2(2,1) THEN bool(3)=1
 IF L2(1,2)=L2(2,2) THEN bool(4)=1
 
 IF (bool(1)=0 AND bool(2)=1 AND bool(3)=1 AND bool(4)=0) OR (bool(1)=1 AND bool(2)=0 AND bool(3)=0 AND bool(4)=1) THEN
  'orthogonal
  IF bool(1)=1  THEN 
   x=L1(1,1) ! y=L2(1,2)
  ELSE
   x=L2(1,1) ! y=L1(1,2)
  ENDIF
 'now check if point is on one line
 IF point_on_orthog(x,y,L1x1,L1y1,L1x2,L1y2)>0 AND point_on_orthog(x,y,L2x1,L2y1,L2x2,L2y2)>0 THEN RETURN y   
 ELSE 'not orthogonal
  RETURN -1e308
 ENDIF   
END DEF
'==========
DEF dist_to_horizontal(px,py,lpx1,lpy1,lpx2,lpy2)
 IF lpx1<>lpx2 AND lpy1=lpy2 THEN
  'horizontal
  IF px>=MIN(lpx1,lpx2) AND px<=MAX(lpx1,lpx2) THEN RETURN py-lpy1 ELSE RETURN -1 'pos if point overhead else neg.
 ELSE
  'not horizontal
  RETURN -1
 ENDIF 
END DEF
'==========
'remark. generalisation of this problem: turn line(lp2) and point (p) around lp1 then perp_to_orthog
DEF dist_to_vertical(px,py,lpx1,lpy1,lpx2,lpy2)
 IF lpy1<>lpy2 AND lpx1=lpx2 THEN
  'vertical
  IF py>=MIN(lpy1,lpy2) AND py<=MAX(lpy1,lpy2) THEN RETURN px-lpx1 ELSE RETURN -1 'pos if point right else neg.
 ELSE
  'not horizontal
  RETURN -1
 ENDIF 
END DEF
'==========
DEF base2base$(num$,from_base,to_base,s$)
 RETURN dec2base$(base2dec(num$,from_base,s$),to_base,s$)
END DEF
'==========
DEF base2dec(num$,from_base,s$)
IF s$=""THEN s$="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#%"
IF LEN(s$)<from_base THEN RETURN -1
 n=INSTR(s$,MID$(num$,OPTION_BASE(),1))-OPTION_BASE()
 IF LEN(num$)=1 THEN
  RETURN n
 ELSE 
  RETURN n*(from_base^(LEN(num$)-1)) + base2dec(RIGHT$(num$,LEN(num$)-1),from_base,s$)
 ENDIF  
END DEF
'==========
DEF dec2base$(n,to_base,s$)
 IF s$="" THEN s$="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#%"
 IF LEN(s$)<to_base THEN RETURN -1
 IF n<to_base THEN 
  RETURN MID$(s$,n+OPTION_BASE(),1)
 ELSE 
  RETURN dec2base$(FLOOR(n/to_base),to_base, s$) & MID$(s$,(n%to_base)+OPTION_BASE(),1)
 ENDIF
END DEF
'==========


'=============includemaths-end=========