Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

GDI - Выбрать мышкой нарисованную фигуру

17K
23 декабря 2013 года
Uranium-238
17 / / 06.08.2007
Есть функция Contains для проверки попадания в область Rectangle.
Короче нужно нечто аналогичное для нарисованной фигуры (например линии)

Например на форме нарисованно 5 линий, мне нужно мышкой выделить вторую чтоб удалить.
Все линии сидят в массиве.
Получается нужно проверить каждый пиксель всех линий? А если учесть что линия шириной 1 пиксель
то в нее трудновато попасть мышкой... такую линию нужно проверять и по соседним пикселам.
Хорошо если это линия или окружность, а если кривая - где брать формулу по которой GDI её нарисовал?
Может кто сталкивался с такой фигней и знает более простой подход ?... поделитесь идеей если не сталкивались!
78K
23 декабря 2013 года
albeoris
20 / / 17.05.2013
С линией всё просто подставляешь свою координаты в уравнение прямой, решаешь уравнение (знаю, что для программиста это звучит жутко, но по ссылке на пальцах показано - как) и сравниваешь результат с 0 (+- допуск).

С произольной кривой всё сложнее. Тут недурно было бы спросить на gamedev'е - они такими глупостями любят заниматься. Я бы разбил всё пространство на квадраты, каждый квадрат ещё на квадраты и так далее, пока размерз этого квадрата не будет равен допуску. И проверял бы 9 соседних квадратов в районе клика мыши. К сожалению, индексы в этом случае всё равно придётся где-то хранить, тоесть в грубом приближении, каждый мелкий квадратик содержит в себе список прямых, которые через него проходят.

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

Думаю, что когда встаёт задача аналогичная твоей, строятся дополнительные, невидимые прямые отрезки, загрублённой формы, на основе которых и осуществляется проверка. Так, например, при столкновении двух 3D объектов просчитываются столкновения кубов или сфер, вписанных в них, а не каждого полигона этой модели. :)
27K
26 декабря 2013 года
mnanorn
78 / / 01.12.2013
Здравствуйте!

Как-то все очень сложно. Линии рисуются по характеристикам. Стереть линию - это значит нарисовать ее цветом фона. У каждого элемента должен быть ID, изначально заданный в неком массиве, например. Определить, попадает ли точка на линию в определениях растровой графики весьма проблематично. Поэтому все Ваше рисование изначально должно реализовывать идеологию векторов.
27K
26 декабря 2013 года
mnanorn
78 / / 01.12.2013
Цитата: albeoris
Думаю, что когда встаёт задача аналогичная твоей, строятся дополнительные, невидимые прямые отрезки, загрублённой формы, на основе которых и осуществляется проверка. Так, например, при столкновении двух 3D объектов просчитываются столкновения кубов или сфер, вписанных в них, а не каждого полигона этой модели. :)



Совершенно верно. Т.н. "апроксимация сложной поверхности". Задача, на самом деле, выходит за уровень "hello world". А для каких целей Вам это нужно, если не секрет?

17K
26 декабря 2013 года
Uranium-238
17 / / 06.08.2007
Код конечно требует доработки, но работает!!!

Код:
Public Class Form1
    Dim _Lines(9) As s_Line
    Private Structure s_Line
        Dim P As Pen
        Dim X1 As Single
        Dim X2 As Single
        Dim Y1 As Single
        Dim Y2 As Single
    End Structure

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim R As New Random()
        For i As Byte = 0 To _Lines.Length - 1
            With _Lines(i)
                .P = New Pen(Color.Green, 1)
                .X1 = R.Next(0, 500)
                .X2 = R.Next(0, 500)
                .Y1 = R.Next(0, 500)
                .Y2 = R.Next(0, 500)
            End With
        Next
    End Sub

    Private Sub Form1_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
        For i As Byte = 0 To _Lines.Length - 1
            With _Lines(i)
                .P = Pens.Green
                ' вычисляем формулу линии
               Dim m, b As Single
                m = (.Y2 - .Y1) / (.X2 - .X1)
                b = .Y1 - (m * .X1)
                If Math.Max(CInt(e.X * m + b), e.Y) - Math.Min(CInt(e.X * m + b), e.Y) < 10 Then .P = Pens.Red
            End With
        Next
        Me.Invalidate()
    End Sub

    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
        For i As Byte = 0 To _Lines.Length - 1
            With _Lines(i)
                e.Graphics.DrawLine(.P, .X1, .Y1, .X2, .Y2)
            End With
        Next
    End Sub
End Class
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог