Рисование с перетаскиванием фигур в VB.NET

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

SkyBars
Начинающий
Начинающий
 
Сообщения: 6
Зарегистрирован: 22.05.2006 (Пн) 15:32

Рисование с перетаскиванием фигур в VB.NET

Сообщение SkyBars » 25.05.2006 (Чт) 20:44

У меня такая проблема. Существует нарисованная ломаная линия на PictureBox'е, задаваемая по MouseClick'у координатами своих вершин. Далее после завершения рисования ломаной требуется создать точку, не лежащую на ней, и определить расстояния от нее до ближайшего отрезка ломаной. Вот тут начинаются ужасы:

1. Удаленная точка должна быть перетаскиваема: как это реалиховать? Ну то есть в идеале я беру ее MouseUp'ом, опускаю на новое положение MouseDown'ом, а что же с MouseMove? От точки должен оставаться шлейф, то есть ее приходится заново каждый раз перерисовывать, но так как на PBox уже есть ломаная, Refresh здесь не подойдет.

2. Точка должна быть хорошо видима, то есть скорее всего - закрашенная фигура, например, кружок. Так вот, как мне определить, что указатель мыши находится именно над кругом, когда это даже не объект а просто место на PBox'е? Может по цвету круга? Посоветуйте, пожалуйста.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 26.05.2006 (Пт) 7:00

По первому вопросу, точку надо перерисовывать XOR пером. Сделать это в .NET несколько затруднительно (хотя может быть в версии 2005 что-то изменилось). Но этот вопрос на форуме поднимался, стоит поискать.

По второму вопросу, координата точки у тебя есть. Радиус (или диаметр) круга имитирующего точку тоже есть. Остается проверить попадание координат курсора в круг. Это достаточно элементарно.
Весь мир матрица, а мы в нем потоки байтов!

SkyBars
Начинающий
Начинающий
 
Сообщения: 6
Зарегистрирован: 22.05.2006 (Пн) 15:32

Сообщение SkyBars » 26.05.2006 (Пт) 7:55

Ммм, про попадание курсора в круг... Он у меня рисуется по контуру Rectangle'а - так что попадание к прямоугольник я сделал. А как быть со "срезанными" краями круга? Понятно, что при маленьких размерах точки это несущественно, а если вдруг понадобится перемещать большие объекты? Разница будет очень заметна! :?

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 26.05.2006 (Пт) 7:59

Допустим Xc и Yc у тебя центр круга, R - его радиус, X и Y координаты курсора. Проверяешь условие^

Sqr((X^2 - Xc^2) + (Y^2 - yc^2))<=R

если выполнилось, значит курсор в круге, если нет, то за его пределами
Весь мир матрица, а мы в нем потоки байтов!

SkyBars
Начинающий
Начинающий
 
Сообщения: 6
Зарегистрирован: 22.05.2006 (Пн) 15:32

Сообщение SkyBars » 26.05.2006 (Пт) 8:38

Хм, точно... Спасибо, а то я и не догадался. И если можно еще поподробнее про это XOR перо, а то я толком ничего не нашел... Где-то есть топик с предложением введения "левого" bitmap'а в качестве своеобразного буфера для рисования, но к своей задаче это я приспособить не смог :( Из той же темы: как например создавать "тянущуюся" за курсором линию, которая рисуется ни при Move'е, а при Click'е?

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 26.05.2006 (Пт) 9:15

Насчет XOR пера. Тема тщательно жевалась около года назад. Автор темы если не ошибаюсь RomanCoff (могу чуть напутать с ником, заранее извиняюсь). Стоит поискать основываясь на этом.

Насчет рисования за кликом алгоритм следующий.

1. Запомнили координаты при первом клике (X0,Y0). Лучше делать это в обработчиках событий MouseUp или MouseDown.
2. Запомнили координаты при следующем клике (X1,Y1).
3. Провели линию из X0,Y0 в X1,Y1.
4. Присвоили X0=X1 и Y0=Y1
5. И пошли в пункт 2.

Добавлено

Таки нашел ссылки насчет XOR пера:

http://bbs.vbstreets.ru/viewtopic.php?t=17239&highlight=xor
http://bbs.vbstreets.ru/viewtopic.php?t=17151&highlight=xor
http://bbs.vbstreets.ru/viewtopic.php?t=4834&highlight=xor
Последний раз редактировалось Viper 27.05.2006 (Сб) 11:35, всего редактировалось 1 раз.
Весь мир матрица, а мы в нем потоки байтов!

SkyBars
Начинающий
Начинающий
 
Сообщения: 6
Зарегистрирован: 22.05.2006 (Пн) 15:32

Сообщение SkyBars » 26.05.2006 (Пт) 9:41

Угу. Ясно, покопаем. И последнее, наверное. Ну вот у меня есть точка и отрезки ломаной, и нужно найти самый ближний отрезок. То есть, как я понимаю, рассчитать расстояние от точки до всех отрезков и сравнить. Но ну есть одно но: расстоянием может служить и перпендикуляр, опущенный на отрезок, и путь от точки до вершины отрезка. Я нашел примерно вот такой код:

Код: Выделить всё

  if((q.x-p.x1)*(p.x2-p.x1)+(q.y-p.y1)*(p.y2-p.y1))*_
    ((q.x-p.x2)*(p.x2-p.x1)+(q.y-p.y2)*(p.y2-p.y1))>-eps then

    t= sqr(q.x-p.x1)+sqr(q.y-p.y1)
    w= sqr(q.x-p.x2)+sqr(q.y-p.y2)
    if w<t then t= w
else
    t= sqr((q.x-p.x1)*(p.y2-p.y1)-(q.y-p.y1)*(p.x2-p.x1))/_
             (sqr(p.x2-p.x1)+sqr(p.y2-p.y1))
  distance2piece= sqrt(t)
end if


(q-удаленная точка, две p - концы отрезка)

Все бы ничего, да меня смущает странное eps В описании (http://faqs.org.ru/science/geometry_faq.htm) сказано, что это какая-то примерная маленькая величина. Я понимаю, что код ПОЧТИ рабочий, но что делать с этой est - ума не приложу. Может кто знает где тут исправить пару цифер?
Последний раз редактировалось SkyBars 26.05.2006 (Пт) 14:15, всего редактировалось 1 раз.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 26.05.2006 (Пт) 10:50

Во-первых заключи код в теги, а то он нечитаем (есть такая кнопка VB в форме ответа).

Теперь насчет величины eps. Особенности чисел с плавающей запятой требуют при их сравнении между собой или с нулем использования достаточно малого числа, обеспечивающего необходимую точность вычислений. Например если задать eps = 0.000001, то такова и будет точность. Величина выбирается в зависимости от требуемой точности. Соответственно сравниваются числ следующим образом.

Вместо d1 > d2 следует использовать Abs(d1 - d2) < eps
Вместо d = 0.0 следует использовать Abs(d) <= eps и так далее...
Весь мир матрица, а мы в нем потоки байтов!

SkyBars
Начинающий
Начинающий
 
Сообщения: 6
Зарегистрирован: 22.05.2006 (Пн) 15:32

Сообщение SkyBars » 26.05.2006 (Пт) 12:22

Ага, !Viper!, спасибо огромное :D Ну, думаю, это все, пойду наконец добью прогу до конца!!! Надеюсь, больше надоедать этим не буду )))))))))))


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот и гости: 82

    TopList  
cron