Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как перетащить круг в Canvas'е [D7, WinXP]


ice-hammer ©   (2007-11-18 20:54:00) 

У меня есть объект TCircle, который умеет рисоваться на канве в виде окружности.
Необходимо уметь перетаскивать этот круг с одного места в другое, перед этим выделив именно его(желательно по клику мышки). Главный вопрос в том, как его выделить? Ведь объект не визуальный.
Тупое, муторное решение : подставлять координаты клика (x,y) в уравнение окружности этого объекта, (x-x0)^2+(y-y0)^2<=r^2 - если удовлетворяет, то делаем вывод, что мы кликнули на круг, выделяем его(вручную), и после этого перетаскиваем(тоже вручную, перерисовываем в новое место). Больше ничего в голову не пришло, может у Вас есть идеи?


ice-hammer   (2007-11-19 22:10:00) [1]

Спасибо за предоставленные исследования по оптимизации. ))
Вчера я сделал через попадание в круг, а не в квадрат, скорее всего так и оставлю.

> А объект TCircle и видимо есть список объектов

ТCircle у меня класс, отвечающий за один объект круга. Объектов у меня может быть много, они хранятся в списке, который является контейнером.

> Да не хочу я спорить, только хочу заметить, что на канве
> нет объектов.

Нету, они только рисуются, выделяются, стираются и переносятся на канве

Вот код:

TCircle=Class(Telement)
     pnt:Tpoint;
     image:TImage;
     index:word;
     R:TRect;
     Procedure Draw;
     Constructor Create(pnt0:Tpoint;image0:TImage;index0:word);
     Destructor Destroy;
     Function Select(move_point0:Tpoint):boolean;
     Procedure Allocation;
    end;

От ТElement наследуются все графические объекты


boa_kaa   (2007-11-19 12:10:00) [2]

Пока ребенка укачивал, накатал тестирующий модуль :)

unit Circle;

interface

uses Windows;

type

TCircle = class
private
 SqrR: Integer;
 Bounds: TRect;
public
 // не будет усложнять все свойствами
 X0: Integer;
 Y0: Integer;
 R: Integer;

 constructor Create(AX, AY, AR: Integer);
 function PointInCircle1(AX, AY: Integer): Boolean;
 function PointInCircle2(AX, AY: Integer): Boolean;
end;

implementation

uses Types;

constructor TCircle.Create(AX, AY, AR: Integer);
var
 r2: Integer;
begin
 X0:=AX;
 Y0:=AY;
 R:= AR;
 SqrR := R * R;
 r2 := Trunc(R/2) + 1;
 Bounds.Left := X0 - r2;
 Bounds.Right := X0 + r2;
 Bounds.Top := Y0 - r2;
 Bounds.Bottom := Y0 + r2;
end;

// вычисляем напрямик
function TCircle.PointInCircle1(AX, AY: Integer): Boolean;
begin
 Result := Sqr(AX-X0)+Sqr(AY-Y0) <= SqrR;
end;

function TCircle.PointInCircle2(AX, AY: Integer): Boolean;
begin
 if ((Bounds.Left <= AX) and (AX <= Bounds.Right) and
     (Bounds.Top <= AY) and (AY <= Bounds.Bottom)) then
    // можно попробовать и так и так
    Result := Sqr(AX-X0)+Sqr(AY-Y0) <= SqrR //PointInCircle1(AX, AY)
 else
   Result := false;
end;

end.


Размер канвы выбрал 100x100.

Снимаю шляпу и ем :) Разница составила не более 15% для круга любого диаметра. Но все-таки в сторону второго метода :) Та же репка с вещественной арифметикой.

Так что заниматься оптимизацией в данном случае нет смысла.


Anatoly Podgoretsky   (2007-11-19 11:27:00) [3]

> boa_kaa  (19.11.2007 11:07:13)  [13]

Откуда круги на канве? Там же только точки. А объект TCircle и видимо есть список объектов, иначе для одного и говорить то практически не о чем.


boa_kaa   (2007-11-19 11:07:00) [4]


> Anatoly Podgoretsky ©   (19.11.07 11:01) [12]
> Не знаю кто меньше, но работа с объектом позволит отойти
> от сложных расчетов, для формулы круга к сравнению с радиусом.

Не совсем понял, о работе с каким объектом идет речь? Если про круг, так я и предлагаю уменьшить ОБЩИЙ объем вычислений.


Anatoly Podgoretsky   (2007-11-19 11:01:00) [5]

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


boa_kaa   (2007-11-19 10:55:00) [6]


> Anatoly Podgoretsky ©   (19.11.07 10:23) [10]

Не важно, он все равно меньше, чем канва


Anatoly Podgoretsky   (2007-11-19 10:23:00) [7]

> boa_kaa  (19.11.2007 10:17:09)  [9]

Да не хочу я спорить, только хочу заметить, что на канве нет объектов.
А это резко меняет ситуацию.


boa_kaa   (2007-11-19 10:17:00) [8]


> Leonid Troyanovsky ©   (19.11.07 09:09) [4]

> Anatoly Podgoretsky ©   (19.11.07 09:15) [5]

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

Попадание в него можно проверить с помощью четырех опереций сравнений. Дело ускорится, если ограничивающий квадрат вычислить заранее.

> Или удвоятся, по статистике N*1.41

Анатолий, я могу легко доказать, что это не так. Количество вычислений уменьшится. Причем с уменьшением относительного  размера круга, будет только меньше. И даже не в 2 раза.

Просто Вам, видимо, не приходилось, или не достаточно приходилось, иметь дело с графическими алгоритмами, когда на счета каждое лишнее действие. Не сочтите за грубость.


easy   (2007-11-19 10:16:00) [9]

http://www.dfc.com.ru/?sid=2&id=18&itemid=44


Anatoly Podgoretsky   (2007-11-19 10:13:00) [10]

> Leonid Troyanovsky  (19.11.2007 10:10:06)  [6]

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


Leonid Troyanovsky   (2007-11-19 10:10:00) [11]


> Anatoly Podgoretsky ©   (19.11.07 09:15) [5]

Для статистики еще потребуется знать отношение
площадей квадрата и формы. Или экрана :)

--
Regards, LVT.


Anatoly Podgoretsky   (2007-11-19 09:15:00) [12]

> Leonid Troyanovsky  (19.11.2007 09:09:04)  [4]

Или удвоятся, по статистике N*1.41


Leonid Troyanovsky   (2007-11-19 09:09:00) [13]


> boa_kaa ©   (19.11.07 08:29) [3]

Примерно тоже можно было б предложить про само рисование,
т.е., нужен круг, вписанный в квадрат, и квадратная маска
с круглой дыркой.

Ну, а сами вычисления ускорятся не намного.

--
Regards, LVT.


boa_kaa   (2007-11-19 08:29:00) [14]

В качестве варианта для ускорения могу предложить вычислять попадние точки в описанный вокруг круга квадрат. Если попадает в квадрат, то уже проводить вычисления для круга.


ice-hammer   (2007-11-18 21:23:00) [15]

Жаль


boa_kaa   (2007-11-18 21:05:00) [16]


> Тупое, муторное решение

и единственно верное


Наверх

Титульная страница Поиск, карта сайта Написать письмо