-
У меня есть объект TCircle, который умеет рисоваться на канве в виде окружности. Необходимо уметь перетаскивать этот круг с одного места в другое, перед этим выделив именно его(желательно по клику мышки). Главный вопрос в том, как его выделить? Ведь объект не визуальный. Тупое, муторное решение : подставлять координаты клика (x,y) в уравнение окружности этого объекта, (x-x0)^2+(y-y0)^2<=r^2 - если удовлетворяет, то делаем вывод, что мы кликнули на круг, выделяем его(вручную), и после этого перетаскиваем(тоже вручную, перерисовываем в новое место). Больше ничего в голову не пришло, может у Вас есть идеи?
-
> Тупое, муторное решение
и единственно верное
-
Жаль
-
В качестве варианта для ускорения могу предложить вычислять попадние точки в описанный вокруг круга квадрат. Если попадает в квадрат, то уже проводить вычисления для круга.
-
> boa_kaa © (19.11.07 08:29) [3]
Примерно тоже можно было б предложить про само рисование, т.е., нужен круг, вписанный в квадрат, и квадратная маска с круглой дыркой.
Ну, а сами вычисления ускорятся не намного.
-- Regards, LVT.
-
> Leonid Troyanovsky (19.11.2007 09:09:04) [4]
Или удвоятся, по статистике N*1.41
-
> Anatoly Podgoretsky © (19.11.07 09:15) [5]
Для статистики еще потребуется знать отношение площадей квадрата и формы. Или экрана :)
-- Regards, LVT.
-
> Leonid Troyanovsky (19.11.2007 10:10:06) [6]
Не важно, понятно, что ускорение будет только в случае промаха, а в остальных случаях пенальти.
-
-
> Leonid Troyanovsky © (19.11.07 09:09) [4]
> Anatoly Podgoretsky © (19.11.07 09:15) [5]
В нормальном случае, когда на канве один объект и обрабатывается по клику мышки, можно и не делать так. В случае, если объектов много, или если нужно проводить вычисления при движении, то желательно локализовать область. Самое простое - это описывающий квадрат.
Попадание в него можно проверить с помощью четырех опереций сравнений. Дело ускорится, если ограничивающий квадрат вычислить заранее.
> Или удвоятся, по статистике N*1.41
Анатолий, я могу легко доказать, что это не так. Количество вычислений уменьшится. Причем с уменьшением относительного размера круга, будет только меньше. И даже не в 2 раза.
Просто Вам, видимо, не приходилось, или не достаточно приходилось, иметь дело с графическими алгоритмами, когда на счета каждое лишнее действие. Не сочтите за грубость.
-
> boa_kaa (19.11.2007 10:17:09) [9]
Да не хочу я спорить, только хочу заметить, что на канве нет объектов. А это резко меняет ситуацию.
-
> Anatoly Podgoretsky © (19.11.07 10:23) [10]
Не важно, он все равно меньше, чем канва
-
Не знаю кто меньше, но работа с объектом позволит отойти от сложных расчетов, для формулы круга к сравнению с радиусом.
-
> Anatoly Podgoretsky © (19.11.07 11:01) [12] > Не знаю кто меньше, но работа с объектом позволит отойти > от сложных расчетов, для формулы круга к сравнению с радиусом.
Не совсем понял, о работе с каким объектом идет речь? Если про круг, так я и предлагаю уменьшить ОБЩИЙ объем вычислений.
-
> boa_kaa (19.11.2007 11:07:13) [13]
Откуда круги на канве? Там же только точки. А объект TCircle и видимо есть список объектов, иначе для одного и говорить то практически не о чем.
-
Пока ребенка укачивал, накатал тестирующий модуль :) 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 else
Result := false;
end;
end. Размер канвы выбрал 100x100. Снимаю шляпу и ем :) Разница составила не более 15% для круга любого диаметра. Но все-таки в сторону второго метода :) Та же репка с вещественной арифметикой. Так что заниматься оптимизацией в данном случае нет смысла.
-
Спасибо за предоставленные исследования по оптимизации. )) Вчера я сделал через попадание в круг, а не в квадрат, скорее всего так и оставлю. > А объект 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 наследуются все графические объекты
|