## coordinate-transformation

Joel
Posts: 58
Joined: Fri Jan 15, 2016 1:36 pm
Flag:

### coordinate-transformation

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.
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
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

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

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

GeorgeMcGinn
Posts: 495
Joined: Sat Sep 10, 2016 6:37 am
IMac
Location: Venice, FL
Flag:
Contact:

### Re: coordinate-transformation

Hi Joel,

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

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.
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)
https://www.georgemcginn.com
https://www.cosmologyandspace.blog

Joel
Posts: 58
Joined: Fri Jan 15, 2016 1:36 pm
Flag:

### Re: coordinate-transformation

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 ??
Last edited by Joel on Sat Jan 07, 2017 4:35 pm, edited 1 time in total.

Joel
Posts: 58
Joined: Fri Jan 15, 2016 1:36 pm
Flag:

### Re: coordinate-transformation - pinch-function added

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
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

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

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

GeorgeMcGinn
Posts: 495
Joined: Sat Sep 10, 2016 6:37 am
IMac
Location: Venice, FL
Flag:
Contact:

### Re: coordinate-transformation

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 ??
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)
https://www.georgemcginn.com
https://www.cosmologyandspace.blog

GeorgeMcGinn
Posts: 495
Joined: Sat Sep 10, 2016 6:37 am
IMac
Location: Venice, FL
Flag:
Contact:

### Re: coordinate-transformation

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 ??
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)
https://www.georgemcginn.com
https://www.cosmologyandspace.blog

Joel
Posts: 58
Joined: Fri Jan 15, 2016 1:36 pm
Flag:

### Re: coordinate-transformation

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...)

GeorgeMcGinn
Posts: 495
Joined: Sat Sep 10, 2016 6:37 am
IMac
Location: Venice, FL
Flag:
Contact:

### Re: coordinate-transformation

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...)
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)
https://www.georgemcginn.com
https://www.cosmologyandspace.blog

Joel
Posts: 58
Joined: Fri Jan 15, 2016 1:36 pm
Flag:

### Re: coordinate-transformation

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

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
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=========