where : ibrtses delphi

Delphi - snap and grid

disclaimer

the source code of this page may not appear correctly in certain browsers
due to special characters. Have a look at the source of this HTML page
with notepad instead

Objective

Scaled and/or scalable graphic, mainly vector graphic, can lead to uneven
coordinate numbers. The preferable even numbers can be achieved with the
implementation of a snap.
Examples for
uneven numbers	even numbers instead
0.00001278	0
0.200142	0.2
0.399786	0.4
0.499121	0.5
related : Mapping world and screen

Pixelsnap

The inter pixel distance may not become just any number, but has to be
restricted to even numbers :
0.1 x 10^N	(1/10 based)
0.125 x 10^N	(1/8 based)
0.1667 x 10^N	(1/6 based)
0.2 x 10^N	(1/5 based)
0.25 x 10^N	(1/4 based)
0.333 x 10^N	(1/3 based)
0.4 x 10^N	(1/2.5 based)
0.5 x 10^N	(1/2 based)
0.6667 x 10^N	(2/3 based)
or similar, whereas N is integer

For a given drawing the interpixel snap is given :
Var pixelsnap:float;
then each number to be displayed or stored is rounded to the nearest
multiple of the pixelsnap.
function snappixel(x:float):float;
var i:integer;
begin
 i:=round(x/pixelsnap);
 result:=i*pixelsnap;
end;

Object snap

Faster operation of the drawing application can be achieved when the
objects cannot be moved or placed at each pixel but only at a multiple
of a pixel. Values may be every 6th, 8th, 10th, 12th, 20th or so pixel.
The user has to concentrate less, the bigger the object snap. The pixel
snap and the object snap have to be adjusted for sensible numbers.

Grid

drawing a grid poses the same problems as the snap does. Grid lines
should have a certain gap between them. The grid could be placed at
the object snap or a multiple.

finding sensible numbers

after introducing the snap, the numbers are considered even at the small scale.
Still some care has to be taken when drawing a grid or ruler.
examples with 0.2 and 0.002 distance :
-0.05	-0.1	-0.2	|	0.995	0.994
0.15	0.1	0.0	|	0.997	0.996
0.35	0.3	0.2	|	0.999	0.998
0.55	0.5	0.4	|	1.001	1.000
0.75	0.7	0.6	|	1.003	1.002
0.95	0.9	0.8	|	1.005	1.004
1.15	1.1	1.0	|	1.007	1.006
As can be seen, if zero is part of the range, it has to part of the grid.
It is therefore advisable to draw a grid top-down with decreasing distance

to get a grid with about 10 lines on a range -0.1 .. 1.1, use :

findsnap(1.2,10);	//which gives 0.1

uses math;

function findsnap(range:float;divisions:integer):float;
var i,exponent:integer;
    m,u,mantissa:extended;
begin
 u:=abs(range/divisions);
 // split mantissa and exponent but in decimal notation
 exponent:=ceil(log10(u));
 mantissa:=u/intpower(10,exponent);  // 0.1< mantissa <= 1.0
 // now adjust the snap as case
 if (mantissa<0.14) then m:=0.1;
 if (mantissa>=0.14)and(mantissa<0.18) then m:=1/6;
 if (mantissa>=0.18)and(mantissa<0.23)then m:=1/5;
 if (mantissa>=0.23)and(mantissa<0.27)then m:=1/4;
 if (mantissa>=0.27)and(mantissa<0.4)then m:=1/3;
 if (mantissa>=0.4)and(mantissa<0.6)then m:=1/2;
 if (mantissa>=0.6)then m:=1;
 result:=m*intpower(10,exponent);
end;

Application

assume a field of x:=0 .. pi and y:= -1.1 .. 1.1 has to be mapped
onto an image of 400x400 pixels.
the pixels have to be square, meaning the snap for x and y is the same.
 var range, gridsnap,x,y:extended;
     i:integer;
     xlow,xhigh,ylow,yhigh:extended;  // the boundary

 range:=max(2.2,pi);
 gridsnap:=findsnap(range,20);
 // make the field at least as big as requested
 // lower x
 i:=floor(0/gridsnap);
 xlow:=i*gridsnap;
 // upper x
 i:=ceil(pi/gridsnap);
 xhigh:=i*gridsnap;
 // lower y
 i:=floor(-1.1/gridsnap);
 ylow:=i*gridsnap;
 // upper y
 i:=ceil(1.1/gridsnap);
 yhigh:=i*gridsnap;
 // draw the lines, map them to integer first
 x:=xlow;
 repeat
  xs:=map(x);				//map them to integer
  line(xs,0,xs,image.height-1);
  x:=x+gridsnap;
 until abs(x-xhigh)<0.001;
 x:=ylow;
 repeat
  ys:=map(y);				//map them to integer
  line(0,ys,image.width-1,ys);
  y:=y+gridsnap;
 until abs(y-yhigh)<0.001;
 

findings





Feedback is welcome




sponsored links




Delphi
home

last updated: 24.july.99

Copyright (99,2000) Ing.Büro R.Tschaggelar