Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2015.11.29;
Скачать: [xml.tar.bz2];

Вниз

Как делают вывод подсказок на графиках?   Найти похожие ветки 

 
KSergey ©   (2015-04-02 13:16) [0]

Нарисовал график. И даже 2 графика по каким-то данным.
Как умные люди делают подсказку (разную) в зависимости от положения курсора мыши на графике? Речь не о выводе координат курсора. Речь (в простом варианте) например о вывода названия графика, на который показывает курсор мыши.

Я понимаю, что в общих словах "определить к чему курсор ближе, если до графика менее 5 пикселов - вывести подсказку". Вопрос в том как организовать ту самую проверку технически?

Вижу 2 варианта:

1) Имея формулу графика (ну или данные с неким отсчетом полученные, та же формула по сути) фактически перевычислять точки графика с учетом интерполяции и определять расстояние до точки курсора. Видится крайне затратным и сложным алгоритмически при изменении метода интерполяции и/или метода рисования графика (связная линия / крестики с каким-то шагом и т.п.)

2) Всегда рисовать картинку графика в памяти (т.е. всегда иметь отрисованную и фактически отображаемую сейчас картинку в памяти) и уже по ней определяя цвет точек определять ближайший к курсору график.

Вопрос:

а) Как организовать картинку из п.2 так, чтобы она еще и быстро отрисовывалась (если рисуем именно на картинке) и чтобы на ней был при этом быстрый доступ к пикселям?

б) Может усть более ловкие и умные методы? может Windows сама умеет говорить (и быстро!) цвет фактически отрисованных в WM_PAINT пикселей? (это если вариант, когда в WM_PAINT я просто честно рисую не сохраняя в явном виде картинку в памяти самостоятельно)


 
KSergey ©   (2015-04-02 13:27) [1]

Кстати в варианте 2 еще есть проблема, если 2 графика имеют одинаковый цвет - не различить.
Можно, конечно, делать вторую картинку "техническую", которую не показывать, но на которой все цвета разные, но опять получается двойная работа: отрисуй на экране, отрисуй  на технической картинке.


 
Dimka Maslov ©   (2015-04-02 13:37) [2]

Зная уравнение, я бы сделал график ломанной линией и вычислял расстояния от отрезков до курсора.


 
KSergey ©   (2015-04-02 14:20) [3]

Положим, точек, по которым построена ломанная, 10 тыс (это реальные цифры)
Как-то грустно искать среди них.

Ну реально отображаемых, конечно, меньше, это можно (нужно) учесть. И тем не менее. Даже если предположить график в котором на каждую точку экрана своё значение - это уже 1400...1900 точек перебирать.

Можно еще соптимизировать - зная X координату - через масштаб -пересчитать "где искать"....

но блин, всё это сильно усложняет алгоритм и придётся под каждый вариант отображения графика выдумывать строить свой алгоритм поиска (а график может быть самый разный, да хоть спиралью! или наоборот - вертикальными палками).

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


 
Kerk ©   (2015-04-02 14:40) [4]

В винде есть такая штука - регионы. Вдруг поможет.


 
кгшзх ©   (2015-04-02 15:01) [5]

если бы не в делфи то все намного проще

http://dev.sencha.com/ext/5.1.0/examples/charts-kitchensink/#tip-chart


 
KSergey ©   (2015-04-02 15:44) [6]

Поизучаю, спасибо
Ибо язык - не имеет значения


 
Rouse_ ©   (2015-04-02 16:02) [7]

Типа такого чтоль?
http://rouse.drkb.ru/tmp/hint.avi


 
KSergey ©   (2015-04-02 18:03) [8]

> Rouse_ ©   (02.04.15 16:02) [7]

Тут, если я верно понял, просто на основании координаты Х выдается значение значение Y графика в подсказке. Да? Если так, то это не то.

Речь про то, как например здесь
http://dev.sencha.com/ext/5.1.0/examples/charts-kitchensink/#tip-chart

когда подводишь мышь на график - и он становится жирным. И вопрос в том как определить, что мы к этому графику подвели сейчас мышь. Когда уже понятно о каком графике речь - то там уже можно сделать с ним что угодно; вопрос в том, как определить к какому графику подвели мышь.

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


 
Rouse_ ©   (2015-04-02 18:06) [9]


> KSergey ©   (02.04.15 18:03) [8]

Понял, щас попробую накидать идею.


 
кгшзх ©   (2015-04-02 18:08) [10]

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


 
Rouse_ ©   (2015-04-02 18:12) [11]

Не, так будет сложнее - а можно показать пример отрисовки пары функций (демку накидать) я бы тогда к ней прямо и прикрутил.


 
Кто б сомневался ©   (2015-04-02 18:37) [12]



> 2) Всегда рисовать картинку графика в памяти (т.е. всегда
> иметь отрисованную и фактически отображаемую сейчас картинку
> в памяти) и уже по ней определяя цвет точек определять ближайший
> к курсору график.


>  Может усть более ловкие и умные методы? может Windows сама
> умеет говорить (и быстро!) цвет фактически отрисованных
> в WM_PAINT пикселей?


Что то не пойму, а зачем вообще их по цвету различать? Их же нужно по координатам вычислять, а после высчитать смещение в массиве данных.


 
Кто б сомневался ©   (2015-04-02 18:38) [13]

А вдруг будет 2 прямоугольника (ну или что там) одного цвета?


 
Кто б сомневался ©   (2015-04-02 18:47) [14]


> А вдруг будет 2 прямоугольника (ну или что там) одного цвета?


Любой XY график можно представить как набор прямоугольников с разной шириной и высотой. Каждый пик и яма - новый прямоугольник.
Эта вся хрень может храниться в массиве из TRect - по ним и можно легко вычислить позицию на канве - по X - сумма ширины, по Y ... высоты - ну понятно думаю.
Я так представляю.


 
Rouse_ ©   (2015-04-02 18:56) [15]

Через построение региона на этапе вывода графика имх проще.


 
invis ©   (2015-04-02 19:00) [16]

Я бы скорее выбрал вариант 1. Все кривые сводятся к ломаным, а что ещё есть? Палки и крестики - то есть всего 3 типа графиков, причём для палок и крестиков проверка очень простая. Проверка ломаной на 2000 точек безо всяких оптимизаций занимает всего 50 мкс (2.7 Ггц). Что до масштабирования/сдвига - можно отдельно хранить график в экранных координатах с отсечением невидимых областей.
А в варианте 2 техническую картинку желательно рисовать толстой кистью (чтобы проверялось попадание в определённом радиусе), это медленнее чем обычное рисование, и правка функций рисования всё же понадобится.


 
Rouse_ ©   (2015-04-02 19:10) [17]

Ребят, кгшзх © уже правильное решение предложил. Сложность графика не важна (пусть он хоть из триллиарда точек), важно только то, с чем работает пользователь. А работает он с тем что выведено на экране, где эти триллиарды сольются в несколько тысяч пикселей, от которых и нужно плясать, расширив коридор по радиусу, и скомбинировав все это в один регион.


 
Rouse_ ©   (2015-04-02 19:12) [18]

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


 
Kerk ©   (2015-04-02 19:17) [19]

Вот ведь. Про регионы первым вспомнил я, а оказывается это кгшзх правильное решение предложил. Пойду напьюсь с горя :)


 
Rouse_ ©   (2015-04-02 19:22) [20]

Ну пардоньть Ромч, и ты тоже :)
Кстати, завтра в аську выйди, а ты мне нужен.


 
Кто б сомневался ©   (2015-04-02 19:28) [21]


> Эта вся хрень может храниться в массиве из TRect - по ним
> и можно легко вычислить позицию на канве - по X - сумма
> ширины, по Y ... высоты - ну понятно думаю.

Это дает еще самое нужное - можно добавить типы к каждому участку кривой.
Это и цвет, и жирность и форма и текст что угодно. И все это можно реализовать в методах record"a участка.


 
invis ©   (2015-04-02 19:52) [22]

Регионы через BeginPath/EndPath/PathToRegion что ли? Пробовал - тормозит, 400 мс на той же ломаной из 2000 точек.
А если вручную создавать, то кода там будет не меньше, чем с геометрической проверкой. Скорее больше, стандартной функции создания региона из ломаной нет, нужно как-то изощряться.


 
Sha ©   (2015-04-02 20:01) [23]

Завтра ж пятница, поэтому на все про все для одного графика должно хватить одного массива типа TAreal :)  

type
 TYBounds = record
    YMin, YMax: word;
 end;
 TAreal = array of TYBounds;


 
Inovet ©   (2015-04-02 20:05) [24]

Чёт я не понял про ваши эти регионы. Почему не хранить просчитанные точки в массивах для каждого графика. При наведении мыши переводить экранные координаты в соответсвии с масштабом горизонтальную - в индекс массива и смотреть в окрестостях этого индекса значения - это будут Y тоже с заданным приближением.

С масштабированием отображения, чтобы не пересчитывать всё целиком, можно посложнее придумать структуру и дополнять уже посчитанное.


 
KSergey ©   (2015-04-02 20:45) [25]

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


 
invis ©   (2015-04-02 21:08) [26]

Насчёт тормознутости регионов уточню: 400 мс - это были неудобные данные, ломаная на основе рандомного набора точек. С синусоидой лучше, 25 мс. Но при этом не получается одновременно нарисовать график (StrokePath) и получить регион, то есть два раза рисовать нужно.
Вообще, не люблю я эти мутные системные API: в таком порядке/сочетании вызовы работают, в этаком - нет, логически объяснить невозможно, только запомнить хитрое шаманское движение бубном. Ну нафиг, лучше уж самому посчитать, благо возможность есть.


 
Kerk ©   (2015-04-02 21:46) [27]


>
> Rouse_ ©   (02.04.15 19:22) [20]
>
> Кстати, завтра в аську выйди, а ты мне нужен.

Выйду:)


 
Кто б сомневался ©   (2015-04-02 23:21) [28]


> Чёт я не понял про ваши эти регионы. Почему не хранить просчитанные
> точки в массивах для каждого графика.


Так наверное интереснее, просчитывать точки снова. :)


 
Кто б сомневался ©   (2015-04-02 23:39) [29]


> Ну реально отображаемых, конечно, меньше, это можно (нужно)
> учесть. И тем не менее. Даже если предположить график в
> котором на каждую точку экрана своё значение - это уже 1400.
> ..1900 точек перебирать.
>
> Можно еще соптимизировать - зная X координату - через масштаб
> -пересчитать "где искать"....
>
> но блин, всё это сильно усложняет алгоритм и придётся под
> каждый вариант отображения графика выдумывать строить свой
> алгоритм поиска


Что там его придумывать - обычный бинарный поиск - делим на два и сравниваем 2 числа.


 
Кто б сомневался ©   (2015-04-02 23:45) [30]


> Что там его придумывать - обычный бинарный поиск - делим
> на два и сравниваем 2 числа.


Массив то будет отсортирован по координатам - от 0 - до X.


 
Юрий Зотов ©   (2015-04-03 00:22) [31]

> Windows сама умеет говорить (и быстро!) цвет ... пикселей

GetPixel


 
Andy BitOff ©   (2015-04-03 08:06) [32]

Если использовать GDI+ то там у пути есть нужные методы. Например:

function TForm1.isOver(X, Y: Integer): Boolean;
var
 path: IGPGraphicsPath;
begin
 path := TGPGraphicsPath.Create();
 path.AddBeziers(PointsArr);
 Result := path.IsOutlineVisible(TGPPointF.Create(X, Y), m_theCurrentPen);
end;

Возвращает тру, если координаты находятся на линией n кривых Безье


 
KSergey ©   (2015-04-03 08:23) [33]

> Юрий Зотов ©   (03.04.15 00:22) [31]
> > Windows сама умеет говорить (и быстро!) цвет ... пикселей
> GetPixel

Опасаюсь, что работает крайне медленно эта штука.
Кстати, такой момент: если наложено 2 окна, одно полупрозрачное - какой цвет в итоге вернёт GetPixel?

Блин, что цвет тут верно заметили - разные графики могут быть одного цвета же. Кроме того, один график может быть разных цветов.
Нешта придётся таки выдумывать систему определения назад, через координаты и математику? Грустно.


 
KSergey ©   (2015-04-03 08:24) [34]

> Кто б сомневался ©   (02.04.15 23:45) [30]
> Массив то будет отсортирован по координатам - от 0 - до X.

Еще раз, график может быть, например, спиралью.


 
Andy BitOff ©   (2015-04-03 09:45) [35]


> KSergey ©

Скинь данных попробовать.


 
KSergey ©   (2015-04-03 12:08) [36]

Прикидывая как и что - всё больше склоняюсь к идее, что проще все точки (буквально все видимые) точки линии запоминать в виде массива координат.
но пример накидаю, да. Всё равно придётся на чем-то отрабатывать технологию.
А так хотелось по-простому!


 
Inovet ©   (2015-04-03 12:24) [37]

> [34] KSergey ©   (03.04.15 08:24)
> Еще раз, график может быть, например, спиралью.

Это уже не график


 
Кто б сомневался ©   (2015-04-03 12:30) [38]


> KSergey ©   (03.04.15 08:24) [34]
>
> > Кто б сомневался ©   (02.04.15 23:45) [30]
> > Массив то будет отсортирован по координатам - от 0 - до
> X.
>
> Еще раз, график может быть, например, спиралью.


Как это? Точка назад во времени (влево) чтоли возвращаться может?


 
Pavelnk ©   (2015-04-03 14:20) [39]

Вообще тема интересная, если упростить, то звучит так, как оживить пиксели битмапа. Тут наверное нужен ответ опытного или знающего человека.


 
pavelnk ©   (2015-04-03 14:31) [40]

А если такая идея - анализировать пиксели которые находятся под мышью и принимать решение отталкиваясь от цвета пикселя (ведь графики будут разного цвета).


 
Inovet ©   (2015-04-03 14:47) [41]

> [39] Pavelnk ©   (03.04.15 14:20)
> как оживить пиксели битмапа

Неправильно. Изначально не битмап, а известная закономерность. Как выясняется, она не график функции - другое представление, но тем не менее.


 
Inovet ©   (2015-04-03 14:48) [42]

> [40] pavelnk ©   (03.04.15 14:31)
> А если такая идея - анализировать пиксели которые находятся под мышью

На пиксели надо забить.


 
pavelnk ©   (2015-04-03 14:49) [43]

> Inovet ©   (03.04.15 14:47) [41]
> Неправильно. Изначально не битмап, а известная закономерность.
Но всё равно ж на битмапе, так какая разница?


 
pavelnk ©   (2015-04-03 14:50) [44]

Проще анализировать пиксели, а не закономерность.


 
Inovet ©   (2015-04-03 14:59) [45]

> [44] pavelnk ©   (03.04.15 14:50)
> Проще анализировать пиксели, а не закономерность.

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


 
Pavelnk ©   (2015-04-03 15:26) [46]

Да разве цвет не будет принадлежностью?


 
Andy BitOff ©   (2015-04-03 16:25) [47]

http://s13.postimg.org/f22h10g2f/Rec.gif


 
Юрий Зотов ©   (2015-04-03 16:32) [48]

Очень простой, но неэкономный способ.

Каждая точка - это объект, потомок TCollectionItem. Содержит свои координаты и цвет, а еще имеет свойство Figure, которое тоже есть объект, потомок TGraphicControl. Через метод Paint этого объекта точка умеет сама себя рисовать, а через его же события OnMouseEnter и OnMouseLeave точка знает, когда на нее наведена мышь.

График - это коллекция точек, потомок TCollection. У графика есть строковое свойство Hint (и раз каждая точка через свое свойство Collection знает свой график, то она имеет доступ к его свойству Hint).

Еще график имеет метод PaintCurve. В нем простой цикл - вызвать метод Paint каждой точки, а в результате график отрисован. Теперь если навести курсор на любую его точку, то у нее сработает OnMouseEnter и будет показан Hint графика (или что угодно другое). Соответственно, при уходе мыши срабатывает OnMouseLeave и Hint исчезает.


 
Andy BitOff ©   (2015-04-03 16:36) [49]

Код к моему посту выше


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ComCtrls, ExtCtrls, StdCtrls, Buttons, gdiplus, Generics.Collections;

type
 TArrTypeEnum = (atBeziers, atLines);
 TArrayData = record
   arr: TArray<TGPPointF>;
   ArrType: TArrTypeEnum;
   Caption: string;
   isOver: Boolean;
   PenColor: TGPColor;
   PenWidth: Single;
   SelPenColor: TGPColor;
   SelPenWidth: Single;
 end;

 TForm1 = class(TForm)
   procedure FormCreate(Sender: TObject);
   procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
   procedure FormPaint(Sender: TObject);
 private
   m_theArrayList: TArray<TArrayData>;
   m_Over: boolean;
   m_theCurrentPen: IGPPen;
   m_theHint: THintWindow;
   procedure draw;
   { Private declarations }
 public
   { Public declarations }

 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 m_theCurrentPen := TGPPen.Create(TGPColor.Black);
 m_theHint := THintWindow.Create(self);
 m_theArrayList := TArray<TArrayData>.Create();
 SetLength(m_theArrayList, 3);

 m_theArrayList[0].arr := TArray<TGPPointF>.create(
     TGPPointF.Create(10, 100),
     TGPPointF.Create(100,10),
     TGPPointF.Create(150,150),
     TGPPointF.Create(200,100),
     TGPPointF.Create(300,10),
     TGPPointF.Create(350,150),
     TGPPointF.Create(400,100),
     TGPPointF.Create(500,10),
     TGPPointF.Create(550,150),
     TGPPointF.Create(600,100)
     );
 m_theArrayList[0].ArrType := atBeziers;
 m_theArrayList[0].Caption := "Bezier 1";
 m_theArrayList[0].isOver := false;
 m_theArrayList[0].PenColor := TGPColor.Blue;
 m_theArrayList[0].PenWidth := 1;
 m_theArrayList[0].SelPenColor := TGPColor.Yellow;
 m_theArrayList[0].SelPenWidth := 5;

 m_theArrayList[1].arr := TArray<TGPPointF>.create(
    TGPPointF.Create(110,100),
    TGPPointF.Create(200,10),
    TGPPointF.Create(250,150),
    TGPPointF.Create(300,100),
    TGPPointF.Create(400,10),
    TGPPointF.Create(450,150),
    TGPPointF.Create(500,100),
    TGPPointF.Create(600,10),
    TGPPointF.Create(650,150),
    TGPPointF.Create(700,100)
    );
 m_theArrayList[1].ArrType := atBeziers;
 m_theArrayList[1].Caption := "Bezier 2";
 m_theArrayList[1].isOver := false;
 m_theArrayList[1].PenColor := TGPColor.Red;
 m_theArrayList[1].PenWidth := 2;
 m_theArrayList[1].SelPenColor := TGPColor.Green;
 m_theArrayList[1].SelPenWidth := 5;

 m_theArrayList[2].arr := TArray<TGPPointF>.create(
     TGPPointF.Create(60, 100),
     TGPPointF.Create(150,10),
     TGPPointF.Create(200,150),
     TGPPointF.Create(250,100),
     TGPPointF.Create(350,10),
     TGPPointF.Create(400,150),
     TGPPointF.Create(450,100),
     TGPPointF.Create(550,10),
     TGPPointF.Create(600,150),
     TGPPointF.Create(650,100)
     );
 m_theArrayList[2].ArrType := atLines;
 m_theArrayList[2].Caption := "Lines 1";
 m_theArrayList[2].isOver := false;
 m_theArrayList[2].PenColor := TGPColor.Gray;
 m_theArrayList[2].PenWidth := 3;
 m_theArrayList[2].SelPenColor := TGPColor.Cyan;
 m_theArrayList[2].SelPenWidth := 10;
end;

procedure TForm1.draw;
var
 Graphics: IGPGraphics;
 ArrayDataItem: TArrayData;
begin
 Graphics := TGPGraphics.FromHWnd(Handle);

 Graphics.Clear(TGPColor.White);

 for ArrayDataItem in m_theArrayList do begin
   if ArrayDataItem.isOver then begin
     m_theCurrentPen.Color := ArrayDataItem.SelPenColor;
     m_theCurrentPen.Width := ArrayDataItem.SelPenWidth;
   end
   else begin
     m_theCurrentPen.Color := ArrayDataItem.PenColor;
     m_theCurrentPen.Width := ArrayDataItem.PenWidth;
   end;
   case ArrayDataItem.ArrType of
     atBeziers: Graphics.DrawBeziers(m_theCurrentPen, ArrayDataItem.arr);
     atLines  : Graphics.DrawLines(m_theCurrentPen, ArrayDataItem.arr);
   end;
 end;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
 i: integer;
 oldOver, NeedRedraw: Boolean;
 P: TPoint;
 HintCaption: string;
 pen: IGPPen;
 path: IGPGraphicsPath;

begin
 HintCaption := "";
 NeedRedraw := false;
 for i := 0 to Length(m_theArrayList) - 1 do begin
   oldOver := m_theArrayList[i].isOver;

   pen := TGPPen.Create(TGPColor.Black, 10);
   path := TGPGraphicsPath.Create();
   case m_theArrayList[i].ArrType of
     atBeziers: path.AddBeziers(m_theArrayList[i].arr);
     atLines  : path.AddLines(m_theArrayList[i].arr);
   end;
   m_theArrayList[i].isOver := path.IsOutlineVisible(TGPPointF.Create(X, Y), pen);

   if oldOver <> m_theArrayList[i].isOver then
     NeedRedraw := true;
   if m_theArrayList[i].isOver then
     HintCaption := HintCaption + " " + m_theArrayList[i].Caption;
 end;

 if NeedRedraw then
   Draw;
 if HintCaption <> "" then begin
   p := ClientToScreen(Point(X + 10, Y - 20));
   m_theHint.ActivateHint(Rect(P.X, P.Y, P.X + 100, P.Y + 18), HintCaption);
 end
 else
   m_theHint.ReleaseHandle;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
 draw;
end;

end.


 
Inovet ©   (2015-04-03 16:47) [50]

> [47] Andy BitOff ©   (03.04.15 16:25)
> http://s13.postimg.org/f22h10g2f/Rec.gif

Это нюансы итерфейса. Как опознать, вот в чём вопрос.


 
Inovet ©   (2015-04-03 16:52) [51]

> [48] Юрий Зотов ©   (03.04.15 16:32)

Таки дилема и цимус лоджика - разделять ли данные и их отображение или нет.


 
KSergey ©   (2015-04-03 17:06) [52]

> Andy BitOff ©   (03.04.15 16:36) [49]
> Код к моему посту выше

Человек не слова, но дела!
Восхищён!

Интересен как минимум пример работы с GDI+, ну и более чем по теме.
Спасибо


 
Andy BitOff ©   (2015-04-03 17:12) [53]


> KSergey ©

Я просил у тебя данных, чтобы не вручную вбивать циферки, да и чтобы их было побольше, чтобы нагрузку проверить.

gdi+ брать у Митова - http://www.mitov.com/products/igdi+#overview


 
Кто б сомневался ©   (2015-04-03 17:13) [54]

Как график должен выглядеть, можешь снять скриншот?
И это график чего?


 
Юрий Зотов ©   (2015-04-03 17:27) [55]

> Inovet ©   (03.04.15 16:52) [51]
> разделять ли данные и их отображение или нет.


Если следовать принципам ООП, то не разделять. Инкапсуляция, тудыть ее. Объект содержит и данные, и методы их обработки. Поскольку только ему одному известно, как надо их обрабатывать

Хотя никто не мешает хранить где-то кривую отдельно, в виде массива точек. И передавать этот массив на вход PaintCurve.


 
Юрий Зотов ©   (2015-04-03 17:32) [56]

Если нужны исходники, то вот здесь почти готовый сабж:

http://delphikingdom.com/asp/viewitem.asp?catalogid=215


 
Palladin ©   (2015-04-03 18:00) [57]


> Inovet ©   (03.04.15 16:52) [51]
>
> > [48] Юрий Зотов ©   (03.04.15 16:32)
>
> Таки дилема и цимус лоджика - разделять ли данные и их отображение
> или нет.
>

такой дилеммы не существует
все проблемы от большого ума
от фанатичного следования парадигамам


 
Кто б сомневался ©   (2015-04-03 19:39) [58]


> Юрий Зотов ©   (03.04.15 16:32) [48]
>
> Очень простой, но неэкономный способ.
>
> Каждая точка - это объект, потомок TCollectionItem.


Еще один велосипед :)


 
Inovet ©   (2015-04-03 19:43) [59]

> [55] Юрий Зотов ©   (03.04.15 17:27)
> Объект содержит и данные, и методы их обработки.

> [55] Юрий Зотов ©   (03.04.15 17:27)
> Хотя никто не мешает хранить где-то кривую отдельно, в виде массива точек

Значит, нужен обобщённый объект, который хранит и обрабатывает и то и другое. Я и говорю - не жирно ли это для точки на битмап, не лучше ли отдельно точки и отдельно их диаграммы.


 
Inovet ©   (2015-04-03 19:52) [60]

> [57] Palladin ©   (03.04.15 18:00)
> от фанатичного следования парадигамам

Это чё, наезд на "официальную" науку? Так, у меня не хватает знаний, чтобы ею заниматься. Но иногда знаний хватает для реализации практических подходов.


 
Rouse_ ©   (2015-04-03 21:35) [61]

Ну вот, а мне данные не кинули, хоть и просил :(
А по поводу регионов - они для того и придуманы, чтобы работать максимально быстро :)


 
Palladin ©   (2015-04-04 02:29) [62]


> Это чё, наезд на "официальную" науку?

Ну... я хотел сказать, что реальные посоны, в зависимости от условий, среды исполнения, от данных, и вообще задачи, как таковой, использую разные методы решения. В том числе и гетерогенные. И не кидаются в философские измышления (читай "срачи") вроде: "ООП рулез" или "ассемблер форева". Нет для них этой дилеммы.
А еще в моей практике есть решения адептов квадратно-гнездового способа мышления: это просто клиника. Вроде "я узнал о новой фиче, будем использовать ее везде, она мне понравилась". Через пол года, конечно, чел осознает (в случае наличия хоть какого то признака мозговой деятельности) ущербность пихания этой фичи во все дырки и фича предается анафеме, потому что не решает все проблемы. Но он не осознает ущербности подхода "новая фича во все дырки". И потому заменяется старую фичу на другую фичу. И тд и тп.


 
Юрий Зотов ©   (2015-04-04 07:42) [63]

> Кто б сомневался ©   (03.04.15 19:39) [58]

> Еще один велосипед :)


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

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

> Inovet ©   (03.04.15 19:43) [59]

> нужен обобщённый объект, который хранит и обрабатывает и то и другое.


Коллекция (график) и является таким объектом, если ее элемент (точка) хранит свои данные (координаты, цвет, и т.п.). В этом варианте график и сам хранит свои данные, и сам умеет себя рисовать.

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

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

> не жирно ли это для точки на битмап

Я же сразу так и написал - способ простой, но неэкономный. Единственный его плюс - это простота и скорость реализации. Что важнее - простота или экономичность - это уже решает сам ТС.


 
Кто б сомневался ©   (2015-04-04 13:48) [64]


> Открою страшную тайну: почти каждая написанная Вами, мною,
>  да и кем угодно программа - это еще один велосипед. Или
> даже целый парк новых велосипедов.


Не, ну велосипед еще - это что то не в меру усложненное.


> Но элемент коллекции (точка) хранить свои данные не обязан.


Тогда уже лучше сделать массив из record ов, да работать напрямую с ними без промежуточного класса коллекции.

Имхо самый оптимальный вариант остается [14] [21] и [29], как по производительности, так и по гибкости. Другого пока не вижу.


 
Юрий Зотов ©   (2015-04-04 16:01) [65]

> Кто б сомневался ©   (04.04.15 13:48) [64]

> Не, ну велосипед еще - это что то не в меру усложненное.


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

> Тогда уже лучше сделать массив из record ов, да работать
> напрямую с ними без промежуточного класса коллекции.


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

А что касается гибкости... ну, надеюсь, что человеку, понимающему ООП, даже и объяснять не надо.

===============

Дискуссию заканчиваю. Было предложено несколько вариантов, указаны их плюсы и минусы - выбор за ТС, а обсуждать тут более нечего.


 
Kerk ©   (2015-04-04 16:40) [66]

ЮЗ прав. Как хранить сам список точек - это уже детали. Главное отделить модель от представления. Все эти идеи с GetPixel - полный капец. Нужна модель в памяти, которая умеет себя рисовать.



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2015.11.29;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.67 MB
Время: 0.004 c
15-1428565202
ВладОшин
2015-04-09 10:40
2015.11.29
Чудеса какие то в отладке


15-1427898124
Dimka Maslov
2015-04-01 17:22
2015.11.29
А вот почему?


9-1195943145
Тул
2007-11-25 01:25
2015.11.29
GLScene Как с помощью компонента TGLCustomBitmapFont вывести текс


15-1428569892
Ghost del vonte
2015-04-09 11:58
2015.11.29
Толи лыжи не едут, толи я...


15-1427751002
Юрий
2015-03-31 00:30
2015.11.29
С днем рождения ! 31 марта 2015 вторник





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский