Косяк с математикой в pixilang 3

Pixilang по русски
Post Reply
User avatar
phase
Posts: 17
Joined: Thu Dec 20, 2012 6:16 pm
Location: Хабаровск

Косяк с математикой в pixilang 3

Post by phase » Fri Nov 15, 2013 12:38 pm

Здравствуйте. Я заметил неточности в вычислениях с нечётными числами (особенно в округлении чисел делённых на 3). А также неточности в работе функций:
pixi(), t_translate(), t_rotate() (по моему это взаимосвязано).
Начнём с округления.
Есть программа:

Code: Select all

// периодическая последовательность чисел
fn repeat( $period , $n) //выдаёт от 0 до period - 1
{
$a=$n/$period
$b=$a-floor($a)
ret($period*$b)
}

period=3 
n=0 m=10
printf("period=%f n=%f \n",period,n)
while(n<m)
{
x=repeat(period, n) 
printf("repeat(%f,%f)=%i \n",period,n,x)
n+1
}
При period =3 в консоли появляется это:
Image :(
А должно быть так:
period=3.000000 n=0.000000
repeat(3.000000,0.000000)=0
repeat(3.000000,1.000000)=1
repeat(3.000000,2.000000)=2
repeat(3.000000,3.000000)=0
repeat(3.000000,4.000000)=1
repeat(3.000000,5.000000)=2
repeat(3.000000,6.000000)=0
repeat(3.000000,7.000000)=1
repeat(3.000000,8.000000)=2
repeat(3.000000,9.000000)=0
Если period чётный например 4, то:
Image
Всё нормально. Вообще при любых чётных числах.
А если взять period =6 и m=12 то: Image таже фигня, при всех нечётных :unknown: .
p.s. если добавить к n 0.1 то с всё вычисляется нормально, но то что нужно что-то добавлять - не нормально.
Last edited by phase on Fri Nov 15, 2013 1:02 pm, edited 2 times in total.

User avatar
phase
Posts: 17
Joined: Thu Dec 20, 2012 6:16 pm
Location: Хабаровск

Re: Косяк с математикой в pixilang 3

Post by phase » Fri Nov 15, 2013 12:55 pm

Теперь функции.
pixi() с нечётными коэффициентами масштабирования часть изображения получается смещённой на один пиксель вправо - вниз. Т.е. первый левый столбец и первая верхняя строка строка на один пиксель больше по ширине и высоте.
При чётных коэффициентах масштабирования ничего не смещается.
Пример-доказательство:

Code: Select all

img=new(3,3,PIXEL)
img[0,0]=0 img[1,0]=RED img[2,0]=0
img[0,1]=RED img[1,1]=RED img[2,1]=RED 
img[0,2]=0 img[1,2]=RED img[2,2]=0
pixi(img,0,0,WHITE,3,3)
frame(-1)
Image
Я писал программу где нужно точное совпадение пикселей в масштабированных изображениях. Этот косяк оказался критичным. Пришлось писать свою функцию увеличения с прямым доступом к массиву.
p.s.Кстати при рендере в OpenGL всё нормально.
Last edited by phase on Fri Nov 15, 2013 1:41 pm, edited 1 time in total.

User avatar
phase
Posts: 17
Joined: Thu Dec 20, 2012 6:16 pm
Location: Хабаровск

Re: Косяк с математикой в pixilang 3

Post by phase » Fri Nov 15, 2013 1:17 pm

Теперь трансформация.
t_rotate().
Решил написать на pixilang простой тетрис.
Вот заготовка:

Code: Select all

field_xsize=32
field_ysize=64

field=new(field_xsize,field_ysize)
figures=new(7,INT)
figures[0]=load("fig1.png")
figures[1]=load("fig2.png")
figures[2]=load("fig3.png")
figures[3]=load("fig4.png")
figures[4]=load("fig5.png")
figures[5]=load("fig6.png")
figures[6]=load("fig7.png")
set_key_color(figures[4],BLACK)

zoom=5.5
angle=0.0

x = 0
y = 0

while( 1 )
{
set_screen(field)
t_reset()
clear(GREEN)
t_rotate(angle,x,y,1.0)
pixi(figures[4],x,y,YELLOW)
set_screen(0)
t_reset()
t_scale(zoom,zoom,0)
pixi(field)
frame()

    while( get_event() )
    {
	draw = 0
	if EVT[ EVT_TYPE ] == EVT_BUTTONDOWN 
	{
	    key = EVT[ EVT_KEY ]
	    if key == KEY_UP { y - 1 }
	    if key == KEY_DOWN { y + 1 }
	    if key == KEY_LEFT { x - 1 }
	    if key == KEY_RIGHT { x + 1 }
	    if key == KEY_SPACE { angle + 90}
         //flag = EVT[ EVT_FLAGS ]
	    
	}
	if EVT[ EVT_TYPE ] == EVT_QUIT { halt }
    }
}
Вот фигуры
figures.rar
(1.22 KiB) Downloaded 261 times
.
Вот окно после запуска: Image

А вот попытка повернуть фигуру на 90 гр.
Image
И куда делся прозрачный цвет?
При перемещении фигура еще больше искажается.

User avatar
NightRadio
Site Admin
Posts: 3025
Joined: Fri Jan 23, 2004 12:28 am
Location: Ekaterinburg. Russia
Contact:

Re: Косяк с математикой в pixilang 3

Post by NightRadio » Fri Nov 15, 2013 8:46 pm

Добрый день!

Вы правы, взаимосвязь есть. Не прямая, но следующая из ошибок округления.
Я заметил неточности в вычислениях с нечётными числами (особенно в округлении чисел делённых на 3).
В первом вашем примере неточность из за того, что Pixilang работает с 32битными числами с плавающей точкой стандарта IEEE 754. Чтобы лучше понимать подводные камни этого формата, рекомендую почитать, например, вот эту статью: http://habrahabr.ru/post/112953/
Кроме того, я вижу, что repeat() ни что иное, как остаток от деления. Такая функция уже есть в составе языка - это mod(). Не знаю точно, как она устроена внутри, но работает она очень точно, без описанных ошибок. Поэтому просто пишите x = mod( n, period )
pixi() с нечётными коэффициентами масштабирования часть изображения получается смещённой на один пиксель вправо - вниз.
Да, опять ошибки округления, боязнь нечетных чисел. Я посмотрю на досуге, как это место можно исправить.
Теперь трансформация. t_rotate().
Решил написать на pixilang простой тетрис.
Вы по всей видимости решили, что в t_rotate() нужно указывать центр поворота. Это не так. t_rotate() принимает координаты вектора оси поворота. То есть, нужно писать вот так:
t_translate( x, y, 0 )
t_rotate( angle, 0, 0, 1 )
pixi( figures[4], 0, 0, YELLOW )
Далее. В процессе тестирования вашего примера я обнаружил ошибку в Pixilang. Суть: картинка с альфа-каналом не может одновременно иметь и альфа-канал и key_color. Сейчас я это поправил - в ближайшем обновлении появится. Но вам рекомендую либо сразу сохранять картинки без альфа-канала, либо удалять его после загрузки. В ваших картинках отсутствуют прозрачные цвета, но это не означает, что отсутствует альфа-канал - он присутствует и просто весь заполнен значениями 255.
Далее. Искажения имеют ту же природу, что и во втором вопросе. Буду разбираться.
В качестве временного решения могу предложить два варианта:
1) использовать OpenGL;
2) увеличивать не весь экран целиком, а сами спрайты.

Post Reply