purebasic.info

PureBasic forum
Текущее время: Пн дек 10, 2018 7:05 pm

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 28 ]  На страницу Пред.  1, 2
Автор Сообщение
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Ср ноя 14, 2018 12:50 pm 
Не в сети
профессор

Зарегистрирован: Чт фев 09, 2017 10:37 am
Сообщений: 239
Благодарил (а): 22 раз.
Поблагодарили: 33 раз.
Пункты репутации: 0
Kuzmat писал(а):
Там вроде под GDI+ сделано, разве он в Линуксе есть?
Я в Windows примеры делал. Тут в качестве идей - оформление в виде библиотеки функций и набор входных параметров, а также идеи с демонстрационными примерами.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Ср ноя 14, 2018 2:06 pm 
Не в сети
профессор

Зарегистрирован: Вс авг 31, 2014 12:11 am
Сообщений: 457
Благодарил (а): 51 раз.
Поблагодарили: 20 раз.
Пункты репутации: 10
Kuzmat
Цитата:
1) Min-Max - задаются при вызове (авто-масштаб по Y не нужен).
2) подписи по Y из массива. (а как привязаться к размерам по вертикали?)
3) сетку двигать вместе с данными, что-бы метки по X не менялись.
Все верно?

1 - Да. Авто-масштаб по Y не нужен.
2 - Да, подписи(значения) и интервал(шаг последовательности значений) задаёт сам пользователь (грубо). По-поводу размера по вертикали: можно внести ещё одну константу, которая бы определяла сколько засечек будет по Y, чтобы можно было хоть как-то регулировать их количество. Хоть и разово/единожды. А там пользователь пусть уже сам "укладывается". Например, если заведомо известно что некая величина изменяется в некоторых пределах, то количеством засечек по Y можно задать приемлемую для этой величины точность (разрешающую способность если хотите).
3 - И да и нет. Сетку двигать вместе с данными? - ДА!
Но... как можно двигать сетку при этом не сдвигая саму шкалу x, не понял. Единственное - это когда увеличиваем масштаб, то добавляются секции самой сетки. Появляется некая детализация по времени (вплоть до 1-ой минуты). Сам график же при этом "растягивается" только по оси x. Y трогать не надо ;)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Ср ноя 14, 2018 5:53 pm 
Не в сети
профессор

Зарегистрирован: Чт фев 09, 2017 10:37 am
Сообщений: 239
Благодарил (а): 22 раз.
Поблагодарили: 33 раз.
Пункты репутации: 0
Kuzmat
Чтоб визуально посмотреть без установки AutoIt3, вот
Изображение


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Ср ноя 14, 2018 8:39 pm 
Не в сети
профессор

Зарегистрирован: Чт сен 22, 2011 6:21 pm
Сообщений: 278
Благодарил (а): 37 раз.
Поблагодарили: 28 раз.
Пункты репутации: 0
AZJIO Ну что вам сказать уважаемый, да, очень красивые графики,(без сарказма) прекрасная работа.
Но у меня стояли другие задачи. Я изначально лепил что-то вроде графического Debug (максимально независимый и быстро вызываемый инструмент), для массива с кучей данных (оценить на глаз максимальные всплески и средний джит).
Потом модуль начал обрастать подробностями, и стало возможным его выложить для публики.
Образно выражаясь, у вас "швейцарский нож" (с кучей рюшечек), у меня "молоток" для "быстро подключить и глянуть".
Возможно со временем мой код разрастется (в смысле возможностей), но задачу создать что-то академическое,
я не ставлю. В идеале - удобный, простой, быстро-встраиваемый, для посмотреть на данные, и не более...


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Чт ноя 15, 2018 11:46 am 
Не в сети
профессор

Зарегистрирован: Чт сен 22, 2011 6:21 pm
Сообщений: 278
Благодарил (а): 37 раз.
Поблагодарили: 28 раз.
Пункты репутации: 0
Код в 1 посте обновлен, теперь сетка привязана к данным а не к окну (подсказка knower),
всплывающее окошко с детальной информацией. (Долго пытался приспособить стандартный GadgetToolTip,
но он работает как-то странно, то всплывает, то нет, да и очень долго, пришлось рисовать самому)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Чт ноя 15, 2018 5:47 pm 
Не в сети
профессор

Зарегистрирован: Вс авг 31, 2014 12:11 am
Сообщений: 457
Благодарил (а): 51 раз.
Поблагодарили: 20 раз.
Пункты репутации: 10
Kuzmat, спасибо за работу. Серьёзные подвижки.

Докладываю: при выборе масштаба 1:1 и прокрутке графика время больше не "плывёт", но теперь эта "детская болезнь" перекинулась на масштабы, отличные от 1:1. В остальном всё выдержано чётко. Сейчас насчёт соотношений говорю (масштаба ко времени):

x=1 step=30
x=2 step=15
x=3 step=10
x=5 step=6
x=6 step=5
x=10 step=3
x=15 step=2
x=30 step=1

Также "артефакты" замечены/проявляются если при масштабе 1:1 сдвинуть график/фазу и затем увеличить масштаб. Например, после запуска(имеем x=1/1) сдвинем график на 90 гр., чтобы в точке отсчёта время было равным 1:30. Но только установить эту метку не в ноль (0, 0), а сдвинуть скажем на один пиксель. Вот тут-то всё и начинается. Получаем минуты уже не 00,15,30,45(как ожидалось) , а 59,14,29,44. Получается что всё таки привязка к окну (началу координат) осталась. Ведь не важно какой участок графика в данный момент просматривается. Иначе получается, что прежде чем изменить масштаб нужно прицелиться и установить/позиционировать одну из рисок точно в (0, 0) и только после этого уже изменять масштаб. Это несколько неудобно.

при x, равном или более 10 график перемещается уже не так "охотно" (как будто подтормаживает/лагает). Справедливо только для протягивания мышкой. При x>=15 сюда же добавляется колесо мышки. Стрелки клавиатуры работают нормально вплоть до x=30. При x=30 и они перестают спасать. График как-будто "замерзает".

По всплывающей подсказке - здорово! Только не успел её ещё как следует протестировать (сверить то что она показывает с тем что нарисовано).

Извиняюсь, если много тут написал, но это то что, как говорится, бросилось в глаза. Надеюсь, что саму суть объяснить всё-таки удалось.

Ещё раз большое спасибо, что не сворачиваете проект. Думаю, что через некоторое время многие будут Вам благодарны за него.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Пт ноя 16, 2018 7:29 am 
Не в сети
профессор

Зарегистрирован: Чт сен 22, 2011 6:21 pm
Сообщений: 278
Благодарил (а): 37 раз.
Поблагодарили: 28 раз.
Пункты репутации: 0
Да, то я поторопился, исправлено. (код в 1 посте обновлен)
Дополнительно: для "любителей прекрасного", вынес константы цветов в шапку, и сразу вопрос?
Можно (легким движением руки) преобразовать их в переменные, и засунуть в параметры вызова графика.
При этом строка вызова будет ниэпического размера, или лучше оставить так?


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Пт ноя 16, 2018 10:12 am 
Не в сети
профессор

Зарегистрирован: Вс авг 31, 2014 12:11 am
Сообщений: 457
Благодарил (а): 51 раз.
Поблагодарили: 20 раз.
Пункты репутации: 10
Kuzmat, отличная работа!
Мелкие недочёты, о которых говорил в предыдущем сообщении устранены. В целом данный модуль всё больше и больше становится похожим на правду :D
Kuzmat, похоже что шкала x уже выверена и в корректировках более не нуждается. Но пожалуйста не оставьте без внимания также и шкалу Y. Её тоже нужно проградуировать. Пусть пользователь сам решит сколько отметок ему нужно по Y (возвращаясь к вопросу о размерах вертикальной шкалы). Допустим заказано 20 штук (может даже не вводить дополнительную константу, а посчитать кол-во элементов списка ListSize(), в котором и будут храниться надписи.). Умножаем это число на #HeightGrid(вертикальный шаг сетки) и получаем размер шкалы Y.

Немного забегая вперёд.
Пожалуй наиболее сложная и важная часть задачи. Как обеспечить так называемые "пропуски" точек на графике? Сейчас постараюсь объяснить. Смотрите... у нас наименьшая кратная часть времени(шкалы x) - это 1 минута, правильно? И сейчас этих пропусков просто нет (расписана каждая минутка). То есть размер массива задан точно(поминутно) для целых суток/для всей шкалы x (в строке 555: #MinOfDay = 24 * 60). Соответственно синусоида и косинусоида сейчас выглядят ровненько.
Так вот... Как бы теперь привязаться ко времени? Допустим... читаю данные из файла-архива(за одни сутки), а там следующее развитие событий: первый замер за время 0:00, второй замер - ну пусть будет за 0:01. Пока всё идёт по-плану(нормально). А вот третий - уже, скажем за 0:15(некий скачок). Ну и так далее... примерно. И вот как теперь обеспечить/отобразить этот разрыв между точками В и С? Ведь если сейчас буду заполнять массив такими данными, то текущий код "шлёпнет" данные за 0:15 в точку 0:02. А это неправильно.
Подводя итог по работе текущего кода можно сказать так: 24 * 60 = 1440. Действительно это кол-во минут в одних сутках. Да... там -1 ещё значится, так как 23:59, но не суть. И сейчас подразумевается, что координаты каждой из этих точек будут непременно заданы. Иначе график будет считаться неполным (с неполными данными) и соответственно не будет дорисован/"уложен" по всей шкале x. А все точки будут сдвинуты так, что отрезок времени между любой парой этих точек будет равен всё той же одной минуте.
Просто идеальным вариантом был бы структурированный список, где координаты каждой точки описываются так: A(0, 0); B(1, 0); C(15, 1); D(85, 1); ... и т.д. Координата x точки D равна 1:25(время на шкале). По Y таким же образом изменять. Не стал писать в примере "левых" значений для Y, чтобы не сбивать с толку, да и для текущих графиков пределы как известно от -1 до +1.

Вот такая глобальная/непростая задача стоит на повестке дня. Но без её решения... увы никак обойтись нельзя. Так как не представляется возможным подсовывать/скармливать коду произвольные данные и соответственно рисовать произвольный график.

Опять же извиняюсь за "много букв", но старался как можно точнее описать задачу. Может где-то излишне детально(подробно) и лишний раз повторился.

P.S. как бы в оправдание. Увидел как-то одно высказывание, понравилось: "без внятного TЗ, результат ХЗ".


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Пт ноя 16, 2018 10:23 am 
Не в сети
профессор

Зарегистрирован: Вс авг 31, 2014 12:11 am
Сообщений: 457
Благодарил (а): 51 раз.
Поблагодарили: 20 раз.
Пункты репутации: 10
Пока писал ответ, сообщение Kuzmat уже дополнилось. Не стал дополнять своё, чтобы не склеивать во едино разные вопросы. А также потому, что то предыдущее и без того вышло объёмным.
Kuzmat писал(а):
При этом строка вызова будет ниэпического размера, или лучше оставить так?

Извини пожалуйста, но про цвета пока даже не заморачивался. Может в будущем, когда будет готов основной механизм. Хотя идея очень даже хорошая. Наглядно показать/выделить предельное значение, например красным цветом. Может кто другой в теме подскажет. Наверняка интерес к теме есть. Иначе не было бы столько просмотров.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Пт ноя 23, 2018 7:25 am 
Не в сети
профессор

Зарегистрирован: Чт сен 22, 2011 6:21 pm
Сообщений: 278
Благодарил (а): 37 раз.
Поблагодарили: 28 раз.
Пункты репутации: 0
knower извиняюсь, был занят, подумал над вашей задачей, и имхо вам просто не подходит линейный график.
гляньте такой вариант: (гистограмма)
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
;*********************************
; Module:   CHART
; Author:   void
; Compiler: PB546
; Ver:      016
;
; столбиковый график с авто-масштабом на несколько линий.
;*********************************
DeclareModule CHART
  EnableExplicit
  Enumeration LabelXIsTime
    #XIdxNum    ;X - номера индексов
    #XTimeSec   ;X - время в секундах
    #XTimeMin   ;X - время в минутах
  EndEnumeration
  #NotValue    = 0.0
  ;Открыть график в отдельном, модальном окне.
  ;Параметры: Заголовок, Ширина, Высота, Массив_Значений, Массив_Цветов, Флаг_глобального_масштаба(масштаб по всему диапозону),
  ;LabelXIsTime - Отображение шкалы по X.
  Declare Open(Title$, Width, Height, Array Values.d(2), Array Colors.l(2), GlobLoc = #False, LabelXIsTime = #XIdxNum)
  ;Открыть график в своем окне в виде гаджета.
  Declare OpenChild(Windows, X, Y, Width, Height, Array Values.d(2), Array Colors.l(2), GlobLoc = #False, LabelXIsTime = #XIdxNum)
  ;Обновить данные присоединенного графика.
  Declare Update(Windows, Chart, Array Values.d(2), Array Colors.l(2))
  ;Удалить присоединенный график.
  Declare FreeChild(Windows, Chart)
 
EndDeclareModule
 
Module CHART
  EnableExplicit
  #FontName$    = "Lucida Console" ;шрифт для меток, должен быть ТТ и моноширинный
  #FontSize     = 8                ;размер шрифта
  #GridColor    = $E0E0E0          ;цвет сетки
  #BarColorEven = $FF0000
  #BarColorOdd  = $808000
  #BackColor    = #White
  #FrameColor   = #Black
  #LabelXColor  = #Black
  #LabelYColor  = #Black
  #LabelSColor  = #Black
  #BackTTColor  = #White           ;ToolTip цвет фона
  #LabelTTColor = #Black           ;ToolTip цвет текста
  #MouseWheelX  = 100              ;чувствительность колеса мыши (за 1 шаг)
  #WidthGrid    = 30               ;горизонтальный шаг сетки
  #HeightGrid   = 30               ;вертикальный шаг сетки
  #DashSize     = 4                ;размер "засечек" к меткам
  #DigitsY      = 3                ;количество значащих цифр в метках Y
  #ToolTipDelay = 10               ;задержка всплывающей подсказки в десятых долях секунды
 
  Structure ChartContext
    HWnd.i
    Canvas.i
    Drawed.i
    CurY.i
    CurX.i
    OldX.i
    LknDwn.i
    DeltaX.i
    StartIdx.i
    GlobMinMax.i
    LabelXMode.i
    ScaleXMul.i
    ScaleXDiv.i
    IsFirstStep.i
    ToolTipSet.i
    GMax.d
    GMin.d
    Array d.d(0,0)
    Array c.l(0,0)
  EndStructure
 
  Global NewList Context.ChartContext(), LastCanvas, Timer, TimerCount, CanvasCount, Font
 
  Procedure Max(a, b)
    If a > b
      ProcedureReturn a
    EndIf
    ProcedureReturn b
  EndProcedure
 
  Procedure SetContextG()
    With Context()  
      ForEach(Context())
        If \Canvas = LastCanvas
          ProcedureReturn
        EndIf
      Next
    EndWith
  EndProcedure  
 
  Procedure SetContextWG(Windows, Gadget)
    With Context()
      ForEach(Context())
        If \HWnd = Windows And \Canvas = Gadget
          ProcedureReturn #True
        EndIf
      Next
    EndWith
  EndProcedure  
 
  Procedure SetContext()
    SetContextWG(EventWindow(), EventGadget())
  EndProcedure  
 
  Procedure DrawGraph(ToolTip = #False)
    Protected   Width, Height, WidthBorder, HeightBorder, TxtWidthX, TxtWidthY, TxtHeight, RoundHeight
    Protected.d Max, Min, Multipler, Shifter, Y1, Y2, LabelY
    Protected   s$, i, j, EndIdx, DigitsX, LenY, LabelX, WorkBorder, BarColor
    #MinDouble  = -1e308
    #MaxDouble  = 1e308
    With Context()
     
      StartDrawing(CanvasOutput(\Canvas))
      DrawingFont(FontID(Font))
     
      ;вычисляем размеры подписей и из них, размеры бордюров
      s$ =  LSet("", #DigitsY, "0")  + " +. "       ;длина правой подписи +знак +точка +2 пробела по бокам
      LenY          = Len(s$)                       ;полная длина меток по Y в символах
      TxtWidthY     = TextWidth(s$)                 ;размер меток по Y
      TxtHeight     = TextHeight(s$)                ;вертикальный размер меток (для центровки)
      WidthBorder   = TxtWidthY + #DashSize         ;размер правого бордюра с учетом "засечек"
      Select \LabelXMode
        Case #XTimeSec
          s$ = "00:00:00"                           ;временная метка в секундах
        Case #XTimeMin
          s$ = "00:00"                              ;временная метка в минутах
        Default;#XIdxNum
          s$ = Str(ArraySize(\d(),2))               ;X - номера индексов
      EndSelect
      DigitsX       = Len(s$)                       ;максимальная длина меток по X в символах
      TxtWidthX     = TextWidth(s$ + "  ")          ;размер меток по X (с учетом отступов в 2 пробела)
      HeightBorder  = TxtWidthX + #DashSize         ;размер нижнего бордюра с учетом "засечек"
      Width         = OutputWidth()  - WidthBorder  ;ширина рабочей зоны
      Height        = OutputHeight() - HeightBorder ;высота рабочей зоны
      RoundHeight   = Height - Height % #HeightGrid ;высота рабочей зоны округленная до полных ячеек
     
      ;если отступ до нижней границы меньше удвойнной высоты подписи - сокращаем масштаб на 1 шаг сетки
      If Height - RoundHeight < TxtHeight * 2: RoundHeight - #HeightGrid: EndIf
     
      ;отступы сверху и снизу
      WorkBorder = (Height - RoundHeight) / 2
     
      ;рисуем экран и рамку
      Box(0, 0, OutputWidth(), OutputHeight(), #BackColor)
      LineXY(0, 0, OutputWidth() - 1, 0, #FrameColor)
      LineXY(0, 0, 0, OutputHeight() - 1, #FrameColor)
      LineXY(Width, Height, Width, 0, #FrameColor)
      LineXY(Width, Height, 0, Height, #FrameColor)
      LineXY(0, OutputHeight() - 1, OutputWidth() - 1, OutputHeight() - 1, #FrameColor)
      LineXY(OutputWidth() - 1, 0, OutputWidth() - 1, OutputHeight() - 1, #FrameColor)
     
      ;корректируем начальный индекс, на выход из диапазона
      If \StartIdx > ArraySize(\d(),2) - Width * \ScaleXDiv / \ScaleXMul
        \StartIdx = ArraySize(\d(),2) - Width * \ScaleXDiv / \ScaleXMul
      EndIf
      If \StartIdx < 0: \StartIdx = 0: EndIf
     
      ;глобальные экстремумы вычисляем по всему массиву 1 раз
      If \IsFirstStep
        \GMax = #MinDouble: \GMin = #MaxDouble
        For j = 0 To ArraySize(\d(),1)
          For i = 0 To ArraySize(\d(),2)
            If \d(j,i) <> #NotValue
              If \GMax < \d(j,i): \GMax = \d(j,i): EndIf
              If \GMin > \d(j,i): \GMin = \d(j,i): EndIf
            EndIf
          Next
        Next    
      EndIf
     
      ;ищем минимальное и максимальное значение
      ;если масштаб локальный - ищем по видимому диапозону
      If \GlobMinMax
        Max = \GMax: Min = \Gmin
      Else
        EndIdx = \StartIdx + Width * \ScaleXDiv / \ScaleXMul
        If EndIdx > ArraySize(\d(),2): EndIdx = ArraySize(\d(),2): EndIf    
        Max = #MinDouble: Min = #MaxDouble
        For j = 0 To ArraySize(\d(),1)
          For i = \StartIdx To EndIdx
            If \d(j,i) <> #NotValue
              If Max < \d(j,i): Max = \d(j,i): EndIf
              If Min > \d(j,i): Min = \d(j,i): EndIf
            EndIf
          Next    
        Next      
      EndIf
     
      ;вычисляем текущий масштаб для вписывания в окно по Y
      If Min <> Max
        Multipler = RoundHeight / (Max - Min)
      Else
        Multipler = RoundHeight
      EndIf
      Shifter = Min * Multipler + RoundHeight + WorkBorder    
     
      ;рисуем вертикальные линии сетки
      i = #WidthGrid - (\StartIdx * \ScaleXMul / \ScaleXDiv) % #WidthGrid
      While i < Width
        LineXY(i, 1, i, Height - 1, #GridColor)
        i + #WidthGrid
      Wend
 
      ;рисуем горизонтальные линии сетки
      i = WorkBorder
      While i < Height  
        LineXY(1, i, Width - 1, i, #GridColor)
        i + #HeightGrid
      Wend
     
      ;рисуем засечки и подписи снизу
      i = #WidthGrid - (\StartIdx * \ScaleXMul / \ScaleXDiv) % #WidthGrid
      While i <= Width
        LineXY(i, Height, i, Height + #DashSize, #FrameColor)  ;засечка
        LabelX = \StartIdx + i * \ScaleXDiv / \ScaleXMul
        Select \LabelXMode
          Case #XTimeSec
            s$ = FormatDate(" %hh:%ii:%ss" , LabelX)           ;представляем в виде времени в секундах
          Case #XTimeMin
            s$ = FormatDate(" %hh:%ii" , LabelX * 60)          ;представляем в виде времени в минутах
          Default                                              ;#XIdxNum
            s$ = RSet(Str(LabelX), DigitsX + 1)                ;добиваем пробелами слева
        EndSelect
        DrawRotatedText(i - TxtHeight / 2, Height + HeightBorder, s$, 90, #LabelXColor)
        i + #WidthGrid
      Wend
     
      ;рисуем засечки и подписи справа
      i = WorkBorder
      While i < Height  
        LineXY(Width, i, Width + #DashSize, i, #FrameColor) ;засечка
        LabelY = (Shifter - i) / Multipler
        If LabelY < 0
          s$ = " " + Left(StrD(LabelY, #DigitsY - 1), #DigitsY + 2)
        Else
          s$ = " +" + Left(StrD(LabelY, #DigitsY - 1), #DigitsY + 1)
        EndIf
        DrawText(Width + #DashSize, i - TxtHeight / 2, s$, #LabelYColor, #BackColor)
        i + #HeightGrid
      Wend
     
      ;информация по масштабу в нижнем правом углу
      If LenY > 7
        If \ScaleXMul > 1
          s$ = " X:" + Str(\ScaleXMul)
        Else
          s$ = " X:1/" + Str(\ScaleXDiv)
        EndIf
        DrawText(Width + #DashSize, Height + #DashSize, s$, #LabelSColor, #BackColor)
        If \GlobMinMax
          s$ = " Y:Glob"
        Else
          s$ = " Y:Loc"
        EndIf
        DrawText(Width + #DashSize, Height + #DashSize + TxtHeight + TxtHeight / 2, s$, #LabelSColor, #BackColor)
      EndIf
     
      ;если данных меньше ширины окна
      EndIdx = Width * \ScaleXDiv / \ScaleXMul - 1
      If EndIdx > ArraySize(\d(),2) - 1
        EndIdx = ArraySize(\d(),2) - 1
      EndIf
     
      ;рисуем сам график
      For j = 0 To ArraySize(\d(),1)
        For i = 0 To EndIdx
          If \d(j, \StartIdx + i) <> #NotValue
            Y1 = Shifter - \d(j, \StartIdx + i) * Multipler
            If \c(j, \StartIdx + i)
              BarColor = \c(j, \StartIdx + i)
            ElseIf i & 1
              BarColor = #BarColorEven
            Else
              BarColor = #BarColorOdd
            EndIf
            Box(i * \ScaleXMul / \ScaleXDiv, Y1, Max(1, \ScaleXMul / \ScaleXDiv), Height - Y1, BarColor)
          EndIf
        Next
      Next
     
      ;Рисуем ToolTip
      Protected TTLeft, TTTop, TTHeight, TTWidth
      TTWidth = Max(TxtWidthX, TxtWidthY) + TextWidth("X2:")
      If ToolTip And \CurX >= 0 And \CurX <= Width And \CurY > 0 And \CurY < Height And
         (\StartIdx + \CurX * \ScaleXDiv / \ScaleXMul) <= ArraySize(\d(),2)
        TTHeight = (TxtHeight + #DashSize) * (ArraySize(\d(),1) + 2) + #DashSize
        If \CurX < Width / 2  ;курср левее середины
          TTLeft = \CurX + 10
        Else
          TTLeft = \CurX - TTWidth - 10
        EndIf
        If \CurY < Height / 2 ;курсор выше середины
          TTTop = \CurY + 10
        Else
          TTTop = \CurY - TTHeight - 10
        EndIf
        Box(TTLeft, TTTop, TTWidth, TTHeight, #BackTTColor)
        LineXY(TTLeft, TTTop, TTLeft + TTWidth, TTTop, #FrameColor)
        LineXY(TTLeft + TTWidth, TTTop, TTLeft + TTWidth, TTTop + TTHeight, #FrameColor)
        LineXY(TTLeft + TTWidth, TTTop + TTHeight, TTLeft, TTTop + TTHeight, #FrameColor)
        LineXY(TTLeft, TTTop + TTHeight, TTLeft, TTTop, #FrameColor)
        LabelX = \StartIdx + \CurX * \ScaleXDiv / \ScaleXMul
        Select \LabelXMode
          Case #XTimeSec
            s$ = FormatDate("%hh:%ii:%ss" , LabelX)           ;представляем в виде времени в секундах
          Case #XTimeMin
            s$ = FormatDate("%hh:%ii" , LabelX * 60)          ;представляем в виде времени в минутах
          Default ;#XIdxNum
            s$ = Str(LabelX)                                  ;в виде номера индекса
        EndSelect
        DrawText(TTLeft + #DashSize, TTTop + #DashSize, "X : " + s$, #LabelTTColor, #BackTTColor)
       
        For i = 0 To ArraySize(\d(),1)
          LabelY = \d(i, \StartIdx + \CurX * \ScaleXDiv / \ScaleXMul)
          If LabelY = #NotValue
            s$="Y: NA"
          ElseIf LabelY < 0
            s$ = "Y" + Str(i + 1) + ":" + Left(StrD(LabelY, #DigitsY - 1), #DigitsY + 2)
          Else
            s$ = "Y" + Str(i + 1) + ":+" + Left(StrD(LabelY, #DigitsY - 1), #DigitsY + 1)
          EndIf          
          DrawText(TTLeft + #DashSize, TTTop + #DashSize + (#DashSize + TxtHeight) * (i + 1), s$, #LabelTTColor, #BackTTColor)
        Next
      EndIf
     
      StopDrawing()
      ProcedureReturn \StartIdx
    EndWith
  EndProcedure
 
  Procedure CheckDraw()
    With Context()
      If \LknDwn And \OldX <> \CurX
        \DeltaX + \OldX - \CurX: \OldX = \CurX
      EndIf
      If \DeltaX * \ScaleXDiv / \ScaleXMul
        \StartIdx + \DeltaX * \ScaleXDiv / \ScaleXMul
        \DeltaX = 0: \Drawed = #False
      EndIf
      If Not \Drawed
        \StartIdx = DrawGraph()
        \IsFirstStep = #False: \Drawed = #True
      EndIf
    EndWith
  EndProcedure  
 
  Procedure IsResizedWindows()
    SetContext()
    With Context()
      ResizeGadget(\Canvas, 0, 0, WindowWidth(\HWnd), WindowHeight(\HWnd))
      \Drawed = #False: CheckDraw()
    EndWith
  EndProcedure
 
  Procedure IsLkMouseDown()
    SetContext()
    With Context()
      \OldX = GetGadgetAttribute(\Canvas, #PB_Canvas_MouseX)
      \LknDwn = #True: CheckDraw()
    EndWith
  EndProcedure
 
  Procedure IsLkMouseUp()
    SetContext()
    With Context()
      \LknDwn = #False
    EndWith
  EndProcedure
 
  Procedure IsMouseMove()
    SetContext()
    With Context()
      \CurX = GetGadgetAttribute(\Canvas, #PB_Canvas_MouseX)
      \CurY = GetGadgetAttribute(\Canvas, #PB_Canvas_MouseY)
      CheckDraw()
      TimerCount = 0
      If \ToolTipSet
        DrawGraph()
        \ToolTipSet = #False
      EndIf
    EndWith
  EndProcedure
 
  Procedure IsMouseEnter()
    SetContext()
    With Context()
      SetActiveGadget(\Canvas)
      LastCanvas = \Canvas
    EndWith
  EndProcedure
 
  Procedure IsWindowsTimer()
    SetContextG()
    With Context()
      TimerCount + 1
      If TimerCount = #ToolTipDelay And Not \ToolTipSet
        DrawGraph(#True)
        \ToolTipSet = #True
      EndIf
    EndWith
  EndProcedure
 
  Procedure IsMouseWheel()
    SetContext()
    With Context()
      \DeltaX + GetGadgetAttribute(\Canvas, #PB_Canvas_WheelDelta) * #MouseWheelX * \ScaleXMul / \ScaleXDiv
      CheckDraw()
    EndWith
  EndProcedure
 
  Procedure IsKeyDown()
    SetContext()
    With Context()
      Select GetGadgetAttribute(\Canvas, #PB_Canvas_Key)
        Case #PB_Shortcut_Left
          \DeltaX - #WidthGrid; * \ScaleXMul / \ScaleXDiv
        Case #PB_Shortcut_Right  
          \DeltaX + #WidthGrid; * \ScaleXMul / \ScaleXDiv
        Case #PB_Shortcut_Up
          \DeltaX - GadgetWidth(\Canvas) / 2
        Case #PB_Shortcut_Down
          \DeltaX + GadgetWidth(\Canvas) / 2
        Case #PB_Shortcut_Add, #VK_OEM_PLUS
          If \ScaleXDiv = 1
            \ScaleXMul + 1
            ;не больше шага сетки
            If \ScaleXMul > #WidthGrid: \ScaleXMul = #WidthGrid: EndIf  
            ;подгонка под ближайшее кратное
            While #WidthGrid % \ScaleXMul: \ScaleXMul + 1: Wend    
          Else
            \ScaleXDiv / 2
          EndIf
          \Drawed = #False
        Case #PB_Shortcut_Subtract, #VK_OEM_MINUS
          If \ScaleXMul > 1
            \ScaleXMul - 1
            ;подгонка под ближайшее кратное
            While #WidthGrid % \ScaleXMul: \ScaleXMul - 1: Wend
          Else
            ;если отображение больше окна - можно сжимать еще
            If ArraySize(\d(),2) / \ScaleXDiv > GadgetWidth(\Canvas): \ScaleXDiv * 2: EndIf
          EndIf
          \Drawed = #False
        Case #PB_Shortcut_0, #PB_Shortcut_Insert
          \ScaleXMul = 1: \ScaleXDiv = 1: \Drawed = #False
        Case #PB_Shortcut_Multiply, #PB_Shortcut_8
          \GlobMinMax = 1 - Bool(\GlobMinMax)
          \Drawed = #False
      EndSelect
      CheckDraw()
    EndWith
  EndProcedure  
 
  Procedure Update(Windows, Chart, Array Values.d(2), Array Colors.l(2))
    SetContextWG(Windows, Chart)
    With Context()
      CopyArray(Values(),\d()): CopyArray(Colors(),\c())
      \ScaleXMul = 1: \ScaleXDiv = 1: \IsFirstStep = #True: \Drawed = #False
      CheckDraw()
    EndWith
  EndProcedure  
 
  Procedure OpenChild(Windows, X, Y, Width, Height, Array Values.d(2), Array Colors.l(2), GlobLoc = #False, LabelXIsTime = #XIdxNum)
    With Context()
      AddElement(Context())
      CanvasCount + 1
      \HWnd = Windows
      \Canvas = CanvasGadget(#PB_Any, X, Y, Width, Height, #PB_Canvas_Keyboard);|#PB_Canvas_DrawFocus)
      SetGadgetAttribute(\Canvas, #PB_Canvas_Cursor, #PB_Cursor_Cross)
      If Not Font
        Font = LoadFont(#PB_Any, #FontName$, #FontSize)
        If Not IsFont(Font)
          MessageRequester("ERROR!", "Unable to load the " + #DQUOTE$ + #FontName$ + #DQUOTE$ + " font!", #MB_ICONERROR)
          End
        EndIf
      EndIf
      SetActiveGadget(\Canvas)
      CopyArray(Values(),\d()): CopyArray(Colors(),\c()): \GlobMinMax = GlobLoc: \LabelXMode = LabelXIsTime
      \ScaleXMul = 1: \ScaleXDiv = 1: \IsFirstStep = #True: \Drawed = #False: CheckDraw()
      BindEvent(#PB_Event_Gadget, @IsLkMouseDown(), \HWnd, \Canvas, #PB_EventType_LeftButtonDown)
      BindEvent(#PB_Event_Gadget, @IsLkMouseUp(), \HWnd, \Canvas, #PB_EventType_LeftButtonUp)
      BindEvent(#PB_Event_Gadget, @IsMouseMove(), \HWnd, \Canvas, #PB_EventType_MouseMove)
      BindEvent(#PB_Event_Gadget, @IsMouseEnter(), \HWnd, \Canvas, #PB_EventType_MouseEnter)
      BindEvent(#PB_Event_Gadget, @IsMouseWheel(), \HWnd, \Canvas, #PB_EventType_MouseWheel)
      BindEvent(#PB_Event_Gadget, @IsKeyDown(), \HWnd, \Canvas, #PB_EventType_KeyDown)
      If Not Timer
        Timer = \HWnd
        AddWindowTimer(\HWnd, Timer, 100)
        BindEvent(#PB_Event_Timer, @IsWindowsTimer(), \HWnd, Timer)
      EndIf
      ProcedureReturn \Canvas
    EndWith
  EndProcedure
 
  Procedure Open(Title$, Width, Height, Array Values.d(2), Array Colors.l(2), GlobLoc = #False, LabelXIsTime = #XIdxNum)
    With Context()
      Protected HWnd, Chart
      ;AddElement(Context()): CanvasCount + 1
      HWnd = OpenWindow(#PB_Any, 0, 0, Width, Height, Title$ +
                        " (Navigate: Up, Down, MouseDrag, Wheel | ScaleXMul: +, -, 0 | ScaleY Global/Local: *)",
                        #PB_Window_SizeGadget|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|
                        #PB_Window_MaximizeGadget|#PB_Window_ScreenCentered)
      Chart = OpenChild(HWnd, 0, 0, WindowWidth(HWnd), WindowHeight(HWnd), Values(), Colors(), GlobLoc, LabelXIsTime)
      BindEvent(#PB_Event_SizeWindow, @IsResizedWindows(), HWnd)
     
      Repeat: Until WaitWindowEvent() = #PB_Event_CloseWindow
     
      UnbindEvent(#PB_Event_SizeWindow, @IsResizedWindows(), HWnd)
      FreeChild(HWnd, Chart)
      CloseWindow(HWnd)
    EndWith
  EndProcedure
 
  Procedure FreeChild(Windows, Chart)
    If SetContextWG(Windows, Chart)
      With Context()
        UnbindEvent(#PB_Event_Gadget, @IsLkMouseDown(), \HWnd, \Canvas, #PB_EventType_LeftButtonDown)
        UnbindEvent(#PB_Event_Gadget, @IsLkMouseUp(), \HWnd, \Canvas, #PB_EventType_LeftButtonUp)
        UnbindEvent(#PB_Event_Gadget, @IsMouseMove(), \HWnd, \Canvas, #PB_EventType_MouseMove)
        UnbindEvent(#PB_Event_Gadget, @IsMouseEnter(), \HWnd, \Canvas, #PB_EventType_MouseEnter)
        UnbindEvent(#PB_Event_Gadget, @IsMouseWheel(), \HWnd, \Canvas, #PB_EventType_MouseWheel)
        UnbindEvent(#PB_Event_Gadget, @IsKeyDown(), \HWnd, \Canvas, #PB_EventType_KeyDown)
        CanvasCount - 1
        If Not CanvasCount ;если графиков больше нет - таймер и фонт не нужны
          UnbindEvent(#PB_Event_Timer, @IsWindowsTimer(), \HWnd, Timer)
          RemoveWindowTimer(\HWnd , Timer): Timer = 0
          FreeFont(Font): Font = 0
        EndIf
        Dim \d(0,0): Dim \c(0,0)
        FreeGadget(\Canvas)
        DeleteElement(Context())
      EndWith
    EndIf
  EndProcedure
 
EndModule
 
 
;Test Module
CompilerIf #PB_Compiler_IsMainFile
  EnableExplicit
 
  #MinVal = 1
  #MaxVal = 15
 
  Procedure Dolled(Array d.d(2), Array c.l(2))
    Protected i
    For i = 0 To ArraySize(d(),2)
     
      ;генерирует рандомные данные с рандомными пропусками
      If Random(#MaxVal,#MinVal) > 10
        d(0,i) = Random(#MaxVal,#MinVal)
      EndIf
     
      ;отмечаем экстремумы
      If d(0,i) = #MaxVal
        c(0,i) = #Red
      EndIf
      If d(0,i) = #MinVal
        c(0,i) = #Green
      EndIf
 
    Next    
  EndProcedure  
 
  #MinOfDay = 24 * 60 * 30
 
  Dim d.d(0, #MinOfDay - 1)
  Dim c.l(0, #MinOfDay - 1)
 
  Dolled(d(), c())
 
  CHART::Open("Single Modal Windows", 800, 620, d(), c(), #True, CHART::#XTimeMin)
 
CompilerEndIf
 


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


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Пт ноя 23, 2018 6:08 pm 
Не в сети
профессор

Зарегистрирован: Вс авг 31, 2014 12:11 am
Сообщений: 457
Благодарил (а): 51 раз.
Поблагодарили: 20 раз.
Пункты репутации: 10
Kuzmat, не стоит извиняться. Рад что тема ожила и связь снова восстановлена.
Что ж... пусть будет гистограмма. В принципе, при увеличении вполне читабельно (можно рассмотреть тенденцию).
Цитата:
кастомных надписей пока нет, если подойдет - добавить не сложно.

Тут дело не только в надписях (или вернее сказать не столько). Поэтапно выдавал информацию, чтобы не нагромождать и конкретно до этого этапа обсуждение ещё не дошло. Видимо пришла пора его озвучить. Сразу скажу, что не так тут всё просто, как может показаться на первый взгляд. Сформулировать бы правильно, не говоря уж о реализации. Всё же попытаюсь объяснить.

На счёт размера шкалы Y говорил выше как вычислить (количество засечек(задано пользователем) * шаг сетки). Но это совсем не главное. И теперь осмелюсь просить сделать прокрутку для Y-ка (не масштабирование). Зачем? Потому что на современных wide-мониторах просто не уместить всю шкалу.

Переходим к главному.
Есть такая метеорологическая величина, как МДВ (далее просто видимость). Допустим для неё требуется построить гистограмму. Нас интересуют все значения менее 3 км., но и то что выше тоже нужно отобразить. Вижу это так (как разметить шкалу Y):
0; 500; 1000; 2000; 3000; 5000; 7000; 12000 при шаге сетки = 100, чтобы добиться приемлемой точности. Таким образом в промежутке от 0 до 500 получаем разрешение в 5 метров. Ровно как и в промежутке от 500 до 1000, так как (1000-500)/100. В промежутке от 1000 до 2000 разрешение уже = 10 метров. и т.д. Не столь значащие/не критичные/визуальных наблюдений значения - это всё, что более 3 км. Там можно и вовсе дать стандартные несколько делений/засечек шкалы Y, такие как 5км; 7км; 12км. Отсюда рождается вопрос: а можно ли для шкалы Y задавать, как бы это сказать, "динамический" шаг сетки? Ну зачем мне 100 отсчётов отводить под промежуток, скажем от 5000 до 7000(получать разрешение в 20 метров), когда заведомо известно, что таких "полумер" как например 5120 или 6920("взять с потолка") и т.д. никогда не встретится. В крайнем случае можно для всего, что выше 3000 задать шаг сетки, скажем 20, ну и проградуировать ...3000; 4000; 5000; 6000; 7000; 10000; 12000 (хотя это и несколько избыточно). Вобщем нужно как-то с очередной надписью передавать шаг сетки. Ну или заранее заполнять структурированный список с полями надпись; шаг сетки.

Вооот... но и это ещё не самое страшное. Тревожит один момент. А именно: что делать если вдруг попадётся значение видимости, скажем равное 81 метр(хотя и маловероятно)? Ведь сетка разлинована следующим образом: ...70;75;80;85... то есть такого значения(координаты Y) просто нет. Здесь вижу только такое решение: найти ближайший отсчёт и соответственно округлить в ту или иную сторону. Ведь график нам нужен только для наглядности(оценить тенденцию) и такой точности (до метра) совсем не надо. В итоге получается, что не вписывающееся значение 81 округлится до 80.
Это конечно экзотический случай, но тем не менее может иметь место быть. Так или иначе думаю, что округление будет совсем не лишним. Это в данном случае рассмотрен довольно мелкий шаг отсчётов, а если у кого-то он будет больше? И попадётся значение аккурат между отсчётами?

Аргументировать же необходимость иметь возможность создания динамической сетки по Y могу также следующим, более наглядным, примером: допустим нужно построить гистограмму для показаний флюгера. Понятно, что тут без вариантов: от 0 до 360 гр. с шагом отсчётов/разрешением в 1 гр. Вот и получаются следующие наноски: 0;100;200;300... (при постоянном шаге сетки = 100) следующую надпись вынужден записать как 400. Но такого же нет в природе (сейчас не говорю про полный оборот + 40гр).

Цитата:
пропущенные значения (не значащие) пока константой, если надо - можно переменной при открытии.

Извиняюсь, недопонял. Про это #NotValue речь? Если да, то без разницы. Ведь в подсказке оно всё равно отображается как "NA". Надо так понимать "not accessible", то есть "не доступный" или "нет данных".
Десятые же могут потребоваться только лишь для температуры; давления. Остальное всё целочисленное.

По цветам.
Наверное буду использовать максимум 3 цвета. Красный, синий и тёмно-зелёный. И не совсем по назначению. То есть не по зависимости цвета от значений (превышающим max-min), а просто для наглядности как разделительные линии. Основные сроки: 0:00; 3:00; 6:00; 9:00; 12:00; 15:00; 18:00; 21:00 - только красным. Все получасовые, не попадающие под условия основных сроков - допустим синим цветом. Всё остальное (промежуточные) - зелёным.

По замечаниям.
Выставил шаг сетки Y = 100 и первая от нуля засечка ни как не равна 100, а всё также на уровне ~ 30. Следующие по 100.
Что-то с цветами творится неладное. При прокрутке графика синий с зелёным поочерёдно меняются местами. Неизменными остаются только экстремумы.
Прокрутка по шкале X много больше одних суток (23:59).

Спасибо большое за ещё один вариант (гистограмму).


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Вт ноя 27, 2018 6:06 am 
Не в сети
профессор

Зарегистрирован: Чт сен 22, 2011 6:21 pm
Сообщений: 278
Благодарил (а): 37 раз.
Поблагодарили: 28 раз.
Пункты репутации: 0
knower Приветствую.
Попробую резюмировать:
1)
Цитата:
0; 500; 1000; 2000; 3000; 5000; 7000; 12000 при шаге сетки = 100, чтобы добиться приемлемой точности. Таким образом в промежутке от 0 до 500 получаем разрешение в 5 метров. Ровно как и в промежутке от 500 до 1000, так как (1000-500)/100. В промежутке от 1000 до 2000 разрешение уже = 10 метров. и т.д.
Назовем это дискретно-логарифмической шкалой, формула масштабирования видимо будет звездецовая, но попробую, поскольку интересно.
2)
Цитата:
Тревожит один момент. А именно: что делать если вдруг попадётся значение видимости, скажем равное 81 метр(хотя и маловероятно)? Ведь сетка разлинована следующим образом: ...70;75;80;85... то есть такого значения(координаты Y) просто нет.
ничего страшного не вижу, при масштабировании будет либо на пиксель выше чем 80, либо сольется с 80 (округлится до ближайшего пикселя), во всплывающем окне - покажет истинное значение.
3)
Цитата:
допустим нужно построить гистограмму для показаний флюгера. Понятно, что тут без вариантов: от 0 до 360 гр. с шагом отсчётов/разрешением в 1 гр. Вот и получаются следующие наноски: 0;100;200;300... (при постоянном шаге сетки = 100)
логично будет в данном конкретном случае взять сетку кратную 360 (10,20,30,60), зачем 100.
4)
Цитата:
Про это #NotValue речь?
Это значение которое график будет понимать как "нет данных", должно быть вне рабочего диапазона.

5) По цветам - сейчас сделано так:
a) если данный бар имеет цвет (в массиве цветов - не 0) то он закрашивается цветом из массива.
б) (если в массиве цветов - 0) то цвета чередуются, четный-нечетный из #BarColorEven, #BarColorOdd.
это нужно что-бы соседние бары не сливались в сплошной массив (да, цвета сейчас подобраны плохо)

зы. как будут готово что-то приемлемое, выложу...


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Линейный график
СообщениеДобавлено: Вт ноя 27, 2018 12:25 pm 
Не в сети
профессор

Зарегистрирован: Вс авг 31, 2014 12:11 am
Сообщений: 457
Благодарил (а): 51 раз.
Поблагодарили: 20 раз.
Пункты репутации: 10
Kuzmat, здравствуйте!
1)
Замысел был таков: задавая отметки по Y-ку программа сама определяет шаг отсчётов в каждой конкретной клетке сетки. Который вычисляется как: текущая отметка по Y-ку минус предыдущая и всё это поделённое на шаг сетки.

2)
Цитата:
ничего страшного не вижу, при масштабировании будет либо на пиксель выше чем 80, либо сольется с 80 (округлится до ближайшего пикселя), во всплывающем окне - покажет истинное значение.

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

3)
Цитата:
логично будет в данном конкретном случае взять сетку кратную 360

Да, здесь я погорячился (не удачный пример взял). Хотелось привести основание для динамического шага сетки по Y. То есть не нужна детализация по всему диапазону, а только до определённого уровня. Хорошо... Скажем так... Может будет яснее...
Весь диапазон от 0 до 12.000 (сейчас конкретно по видимости) можно поделить на данные, полученные инструментально(от датчика) и визуальные наблюдения оператора (полученные, опираясь на искусственные/промышленные ориентиры). Да, данные от датчика продолжают поступать и при значениях видимости более 3 км., но достоверность таких данных мала (велика погрешность). Поэтому принято ориентироваться на него только при V менее 3км. А всё что выше - забивает ручками оператор (приоритет за ним). Что вбил, то и ушло в сводку. Отсюда становится понятно, что тут ни о каких промежуточных отсчётах таких как 5783 или 8233 и т.д.(что может выкинуть датчик) не может быть и речи. Увидел он(оператор) значит трубу котельной на удалении 7 км., всё... значит видимость = 7км. Увидел вышки ЛЭП на 12 км - вбил 12000 и т.д. Нам же важно посмотреть(при листании архива), например: сел туман(отмечено явление), а как там видимость провалилась/просела в этот момент?
Вот и получается, что детализированный участок (до 3 км.) - шаг сетки Y по 100 пикселей, свыше трёх можно рисовать линию сетки(с засечкой) через каждые, скажем 20 пикселей.

4)
Цитата:
это нужно что-бы соседние бары не сливались в сплошной массив

Да и пусть сливаются. Ориентироваться всё-равно по пикам. То что они сечас так чередуются - наоборот ещё больше сбивает с толку(мельтешат). Это только моё мнение, может кому-то выгодней как сейчас. Не знаю.
Впрочем, как уже говорил, цвета - это дело десятое.

Цитата:
как будут готово что-то приемлемое, выложу...

Не нужно спешить/торопиться. Даже если всё заморозится на неопределённый срок, то пойму. Будет конечно жаль, но без никаких претензий.
Уже есть рабочее изделие по просмотру архива. Если его дополнить ещё и графиком, то будет ещё лучше.

И конечно же спасибо за интерес к вопросу.


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 28 ]  На страницу Пред.  1, 2

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group (блог о phpBB)
Сборка создана CMSart Studio
Русская поддержка phpBB