Конференция "Основная" » Как перетащить круг в Canvas'е [D7, WinXP]
 
  • ice-hammer (18.11.07 20:54) [0]
    У меня есть объект TCircle, который умеет рисоваться на канве в виде окружности.
    Необходимо уметь перетаскивать этот круг с одного места в другое, перед этим выделив именно его(желательно по клику мышки). Главный вопрос в том, как его выделить? Ведь объект не визуальный.
    Тупое, муторное решение : подставлять координаты клика (x,y) в уравнение окружности этого объекта, (x-x0)^2+(y-y0)^2<=r^2 - если удовлетворяет, то делаем вывод, что мы кликнули на круг, выделяем его(вручную), и после этого перетаскиваем(тоже вручную, перерисовываем в новое место). Больше ничего в голову не пришло, может у Вас есть идеи?
  • boa_kaa © (18.11.07 21:05) [1]

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

    и единственно верное
  • ice-hammer (18.11.07 21:23) [2]
    Жаль
  • boa_kaa © (19.11.07 08:29) [3]
    В качестве варианта для ускорения могу предложить вычислять попадние точки в описанный вокруг круга квадрат. Если попадает в квадрат, то уже проводить вычисления для круга.
  • Leonid Troyanovsky © (19.11.07 09:09) [4]

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

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

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

    --
    Regards, LVT.
  • Anatoly Podgoretsky © (19.11.07 09:15) [5]
    > Leonid Troyanovsky  (19.11.2007 09:09:04)  [4]

    Или удвоятся, по статистике N*1.41
  • Leonid Troyanovsky © (19.11.07 10:10) [6]

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

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

    --
    Regards, LVT.
  • Anatoly Podgoretsky © (19.11.07 10:13) [7]
    > Leonid Troyanovsky  (19.11.2007 10:10:06)  [6]

    Не важно, понятно, что ускорение будет только в случае промаха, а в остальных случаях пенальти.
  • easy © (19.11.07 10:16) [8]
  • boa_kaa © (19.11.07 10:17) [9]

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

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

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

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

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

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

    Просто Вам, видимо, не приходилось, или не достаточно приходилось, иметь дело с графическими алгоритмами, когда на счета каждое лишнее действие. Не сочтите за грубость.
  • Anatoly Podgoretsky © (19.11.07 10:23) [10]
    > boa_kaa  (19.11.2007 10:17:09)  [9]

    Да не хочу я спорить, только хочу заметить, что на канве нет объектов.
    А это резко меняет ситуацию.
  • boa_kaa © (19.11.07 10:55) [11]

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

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

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

    Не совсем понял, о работе с каким объектом идет речь? Если про круг, так я и предлагаю уменьшить ОБЩИЙ объем вычислений.
  • Anatoly Podgoretsky © (19.11.07 11:27) [14]
    > boa_kaa  (19.11.2007 11:07:13)  [13]

    Откуда круги на канве? Там же только точки. А объект TCircle и видимо есть список объектов, иначе для одного и говорить то практически не о чем.
  • boa_kaa © (19.11.07 12:10) [15]
    Пока ребенка укачивал, накатал тестирующий модуль :)

    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% для круга любого диаметра. Но все-таки в сторону второго метода :) Та же репка с вещественной арифметикой.

    Так что заниматься оптимизацией в данном случае нет смысла.
  • ice-hammer (19.11.07 22:10) [16]
    Спасибо за предоставленные исследования по оптимизации. ))
    Вчера я сделал через попадание в круг, а не в квадрат, скорее всего так и оставлю.

    > А объект 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 наследуются все графические объекты
 
Конференция "Основная" » Как перетащить круг в Canvas'е [D7, WinXP]
Есть новые Нет новых   [134479   +11][b:0][p:0.002]