LINUX.ORG.RU

Прилипание к точкам сетки

 


0

1

Доброе утро. Пописываю граф. редактор, решил добавить возможность рисовать с «прилипанием» к точкам сетки. Написал вот что:

QPoint QtnpImage::closest_grid_point(QPoint p)
{
double x,y;

if (p.x() > c_x)
x = (p.x()-c_x)/grid_step;
else if (p.x() < c_x)
x = -1*(c_x-p.x())/grid_step;
else
x = 0;

if (p.y() > c_y)
y = -1*(p.y()-c_y)/grid_step;
else if (p.y() < c_y)
y = (c_y-p.y())/grid_step;
else
y = 0;

return get_grid_point_coordinates(QPoint(round(x),round(y)), grid_step);
}
Так вот, он не делает то, что мне нужно. Точнее делает, но не по всему рисунку. Я понимаю что это связано с тем, что в лево от 0 х отрицателен, в верх у отрицателен и наоборот, но мой маленький мозг не может это всё описать >_<

Помогите позязя!

Если кому-то нужена функция в контексте то она лежит тут: https://github.com/Hackeridze/Qtnp/blob/master/QtnpImage.cpp#L456



Последнее исправление: Hackeridze (всего исправлений: 1)

В нашем «корпоративном» редакторе я сделал элементарное «округление» до шага сетки.

т.е. на псевдокоде

var step = 10px; //шаг
var halfStep = step/2;
var cursorPoint = {x,y}; // координаты курсора
return {
  x: (cursorPoint.x + halfStep) % step, //"округленные" координаты
  y: (cursorPoint.y + halfStep) % step,
}

Далее через сей округлятор фильтруются координаты курсора для операций с фигурами (если у вас MVC или нормальная архитектура то это одна единственная точка входа, иногда чуть больше, в swing емнип около 3х)

Deleted
()
Ответ на: комментарий от Deleted

Эм. округление реализуется ф-ей round, она вот:

int QtnpImage::round(double num)
{
// int mul = 10;
// if (num > 0)
// return floor(num * mul + .5) / mul;
// else
// return ceil(num * mul - .5) / mul;
return nearbyint(num);
}

Hackeridze
() автор топика
Ответ на: комментарий от Hackeridze

Даже не знаю что вам посоветовать.

Deleted
()
Ответ на: комментарий от waker

Неа, >в лево от 0 х отрицателен, в верх у отрицателен и наоборот, но мой маленький мозг не может это всё описать >_<

Hackeridze
() автор топика
Ответ на: комментарий от Hackeridze

Неа, >в лево от 0 х отрицателен, в верх у отрицателен и наоборот, но мой маленький мозг не может это всё описать >_<

приведи пример входных и выходных значений которые ты хочешь получить.

waker ★★★★★
()
Ответ на: комментарий от waker

Сетка 40х40, шаг 10 центр в (500,500) реальной картинки Вход (523,521)(это координаты курсора) Выход (2,1)(координаты на сетке) ВХ(407,409) ВЫ(-10,9) ВХ(403,402) ВЫ(-9,10) ВХ(403,702) ВЫ(-9,-20)

Hackeridze
() автор топика
Ответ на: комментарий от Hackeridze

1. на входе координаты мыши (от левого верхнего угла, наращение «вниз»). нужно перевести их в правильную систему координат, в которой ты работаешь

x = x_mouse - x_scroll; // x_scroll -- это насколько у тебя viewport сдвинут от начала координат
y = -(y_mouse - y_scroll); // то же самое, но с переворотом

2. выравниваем по сетке той функцией что я выше написал

float snap_to_grid (float x, float grid_step) {
    return round(x / grid_step) * grid_step;
}
x = snap_to_grid (x, 10);
y = snap_to_grid (y, 10);

3. координаты уже есть, по идее ничего другого не надо — они же у тебя в этой системе координат должны храниться. но если ты не понимаешь как обратно в экранные перевести, то все то же самое в обратку

x += x_scroll;
y = -(y + y_scroll);
waker ★★★★★
()
Последнее исправление: waker (всего исправлений: 1)
Ответ на: комментарий от waker

не работает вообще, ближайший рабочий вариант:

x = round((p.x() - c_x)/grid_step); // x_scroll -- это насколько у тебя viewport сдвинут от начала координат
y = round((-(p.y() - c_y))/grid_step); // то же самое, но с переворотом
	
	qDebug() << x << y;
	return get_grid_point_coordinates(QPoint(x,y), grid_step);
даёт результаты примерно те же что и в нынешнем варианте. =( Не работает по тому, что приведение к сеточным координатам должно быть
if (p.x() > c_x) // проверка будет ли х положителен
	x = (p.x()-c_x)/grid_step;
else if (p.x() < c_x) // если отрицателен
	x = -1*(c_x-p.x())/grid_step;
else 
	x = 0;
if (p.y() > c_y) // если у отрицателен
	y = -1*(p.y()-c_y)/grid_step;
else if (p.y() < c_y) // ели положителен
	y = (c_y-p.y())/grid_step;
else 
		y = 0;

Это, собсна, и есть нынешний вариант. =[

Hackeridze
() автор топика
Ответ на: комментарий от Hackeridze

ты что-то очень конкретно недопонимаешь. удачи в поисках, у меня, к сожалению, нет времени катать тебе пример программы.

waker ★★★★★
()
Ответ на: комментарий от Hackeridze

Ну ты жжошь. Столько кода на пустом месте. Давай разберём:

if (p.x() > c_x) // проверка будет ли х положителен
	x = (p.x() - c_x) / grid_step;

итого в этой ветке x = (p.x() - c_x) / grid_step;.

Далее:

else if (p.x() < c_x) // если отрицателен
	x = -1 * (c_x - p.x()) / grid_step;

видим, что -1 * (c_x - p.x()) / grid_step == (p.x() - c_x) / grid_step

итого в этой ветке x = (p.x() - c_x) / grid_step;.

Третья ветка:

else 
	x = 0;

Третья ветка выполняется, если c_x == p.x(), отсюда (c_x - p.x()) == 0, и выражение по-прежнему можно заменить формулой x = (p.x() - c_x) / grid_step;.

Итого весь твой развесистый if заменяется этим:

x = (p.x() - c_x) / grid_step;

unC0Rr ★★★★★
()
Ответ на: комментарий от unC0Rr

Ёмоё... Я, конечно, знал что я туповат, но не думал что на столько... Благодарю!

Hackeridze
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.