Справка по интерпретатору Painter(v)


Painter(v) (или просто Painter) - это интерпретатор DaqScript, интегрированный в окна мнемосхем пакета CRW-DAQ. Окна мнемосхем являются одним из основных средств отображения графического интерфейса пользователя (GUI - graphical user interface) пакета CRW-DAQ. Мнемосхемы содержат статическое поле основного изображения (GeneralMap), на котором располагаются сенсоры (Sensor), т.е. чувствительные элементы, которые могут отображать состояние подключенных данных (кривых, тегов базы данных DAQ-системы) и откликаться на действия пользователя. Сенсоры могут быть простыми (основанными на статических изображениях) или программируемыми, т.е. содержащими в себе формулы или пользовательские сценарии на интерпретаторе Painter, влияющие на их вид и поведение.

Интерпретатор Painter(v) может использоваться для расчета отображаемого состояния сенсора или для рисования на сенсоре:

  1. TagEval(v) - задает формулу для расчета тега изображения (идентификатора картинки) по значению данных v, взятых из подключенной кривой/тега базы данных DAQ-системы. Здесь уместно сделать примечание. Не следует путать тег изображения (т.е. идентификатор фоновой картинки сенсора) и тег данных (т.е. подключенный к сенсору тег базы данных DAQ-системы). У простых сенсоров (без формул), не имеющих циферблата (т.е. цифровой надписи) при LED = 0, значение тега изображения определяется значением данных, взятых из подключенной кривой/тега базы данных DAQ-системы, что эквивалентно заданию формулы TagEval(v) = v. Если же простой (не формульный) сенсор имеет цифровую надпись, то значение тега изображения не меняется. Задание непустого значения TagEval(v) приводит к тому, что значение тега изображения (идентификатора картинки) определяется явно заданной формулой в обоих случаях (при наличии надписи или без неё). Это позволяет, например, менять фон надписи в зависимости от величины подключенной кривой/тега базы данных DAQ-системы.

  2. LedEval(v) - задает формулу для расчета циферблата (цифровой надписи) по значению v подключенной кривой/тега базы данных DAQ-системы. Эта формула используется только в случае использования циферблата (цифровой надписи), т.е. при задании параметра LED > 0. Название циферблата LED взялось, вероятно, от названия старых светящихся светодиодных циферблатов (light emission display). У простых (без формул) циферблатных сенсоров вид отображаемой надписи определяется значением подключенной кривой/тега базы данных DAQ-системы, что эквивалентно заданию формулы LedEval(v) = v. Задание непустого значения LedEval(v) приводит к тому, что циферблат (цифровая надпись) определяется явно заданной формулой, позволяя отображать заданную функцию исходных данных.

  3. Painter(v) - задает пользовательский сценарий рисования сенсора по значению v подключенной кривой/тега базы данных DAQ-системы. При рисовании сенсора сначала вычисляется тег изображения и рисуется соответствующая фоновая картинка. Затем выполняется пользовательский сценарий рисования Painter(v), если он указан. Затем на него накладывается циферблат (цифровая надпись), если задан LED > 0. Параметр Painter(v) в описании сенсора задает [имя секции], в которой находится сам сценарий. Сценарий Painter(v) выполняет заданные пользователем действия по рисованию, используя функции рисования, перечисленные ниже. Из соображений производительности сценарий Painter(v) следует использовать только в случае, когда простые сенсоры не могут выполнить требуемые функции отображения. Не используйте сценарии без необходимости.

Для облегчения создания мнемосхем и унификации их внешнего вида созданы следующие библиотеки графических элементов Painter:
1) GuiLib - общепринятые элементы GUI, такие как кнопки, радиокнопки, кнопки выбора, рамки и т.д.
2) GostLib - элементы GUI, стандартизованные по ГОСТ, ЕСКД или другим опубликованным стандартам.
3) DaqLib - элементы GUI, созданные специально для DAQ-систем, но не обязательно по ГОСТ.

См. также справку и памятку по общим и графическим функциям, цветовым константам Painter(v).
См. также справку по графическим библиотекам GuiLib, DaqLib, GostLib.
См. также договоренности, правила и советы по сценариям Painter(v).
См. также ДЕМО конфигурацию DEMO_PAINT для примера.


Например:

    [Circuit]
    Name = DemoPaint                         ; Set window name
    GeneralMap = .\DemoPaint.bmp             ; Set background picture
    StartupScript = [Circuit.StartupScript]  ; Set startup script section
    []

    [ConfigFileList] ; Include standard definitions
    ConfigFile = ~~\Resource\DaqSite\Default\Painter.crc
    []

    [Circuit.StartupScript] ; Run on startup
    alarm1=30               ; Set alarm1 level
    alarm2=60               ; Set alarm2 level
    []

    [SensorList]
    Sensor = Led1
    [Led1]                                                     ; Display with variable background
    Pos = 10, 10                                               ; Set sensor position
    LED = 7, 0, 3, %7.3f, [LedFont]                            ; Set display format
    TagEval(v) = gt(v,alarm1)+gt(v,alarm2)                     ; Background depends on v
    Tag#1 = 0, ~~\Resource\DaqSite\StdLib\Bitmaps\_LED07C.BMP  ; Background if v <= alarm1
    Tag#2 = 1, ~~\Resource\DaqSite\StdLib\Bitmaps\_LED07Y.BMP  ; Background if alarm1 < v <= alarm2
    Tag#3 = 2, ~~\Resource\DaqSite\StdLib\Bitmaps\_LED07R.BMP  ; Background if v > alarm2
    []

    [SensorList]
    Sensor = Bar1
    [Bar1]                                                                            ; Sensor with script painting
    Pos = 10 40                                                                       ; Set sensor position
    Tag#1 = 0, BAR.BMP                                                                ; Set background picture
    Painter(v) = [Bar1.Painter(v)]                                                    ; Set script to paint sensor
    []
    [Bar1.Painter(v)]                                                                 ; Draw a line script
    sw=sensorWidth()                                                                  ; Get sensor width
    sh=sensorHeight()                                                                 ; Get sensor height
    x1=2                                                                              ; Calculate coordinates of line
    y1=sh-2-v*(sh-4)/100                                                              ;
    x2=sw-2                                                                           ;
    y2=y1                                                                             ;
    color=clAqua*le(v,alarm1)+clYellow*gt(v,alarm1)*le(v,alarm2)+clRed*gt(v,alarm2)   ; Calculate color to draw
    setPen(color,psSolid,pmCopy,4)+drawLine(x1,y1,x2,y2)                              ; Set pen style and draw a line
    setBrush(clWhite,bsClear)                                                         ; Set brush style for text
    fh=-round(1.33*16)                                                                ; Find height of font 16 pt
    @font charset 204                                                                 ; Set font Charset Russian
    @font style 1                                                                     ; Set font Style Bold
    @font color %clBlue                                                               ; Set font Color
    @font height %fh                                                                  ; Set font Height
    @font name Courier New                                                            ; Set font Name
    tw=@textwidth %7.3f%v                                                             ; Get text width
    th=@textheight %7.3f%v                                                            ; Get text height
    setCursor(sw/2-tw/2,max(5,min(y2+2-(th+4)*gt(y2,sh/2),sh-th-5)))                  ; Set text cursor
    @print %7.3f%v                                                                    ; Print v value with format %7.3f
    []
  


Справка по общим функциям интерпретатора Painter(v)


Каждое окно мнемосхем имеет встроенный в него экземпляр интепретатора DaqScript, который мы будем именовать Painter или Painter(v), поскольку он используется для рисования сенсора с текущим значением пользовательских данных v (от слова value), взятых из подключенной кривой/тега базы данных DAQ-системы. В пакете CRW-DAQ вообще работает много экземпляров интерпретатора DaqScript. Свой экземпляр интерпретатора имеет Главная Консоль, Калькулятор, каждая программа DaqPascal и программа DaqScript. Все интерпретаторы имеют общий синтаксический анализатор и минимальный базовый набор функций, но могут отличаться расширенным набором функций, специфичным для каждого экземпляра интерпретатора. В данном случае специфичными для интерпретатора Painter(v) является набор графических функций для рисования на сенсоре.

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

    Список констант:

    _inf        = INF
    _minusinf   = -INF
    _nan        = NAN
    e           = 2.71828182845905
    false       = 0
    macheps     = 2.22044604925031E-16
    maxbyte     = 255
    maxdouble   = 1.7E308
    maxdword    = 4294967295
    maxint      = 2147483647
    maxlongint  = 2147483647
    maxlongword = 4294967295
    maxshortint = 127
    maxsingle   = 3.4E38
    maxsmallint = 32767
    maxword     = 65535
    mindouble   = 4.94065645841247E-324
    minint      = -2147483648
    minlongint  = -2147483648
    minshortint = -128
    minsingle   = 1.5E-45
    minsmallint = -32768
    pi          = 3.14159265358979
    true        = 1

    Список функций:

    abs(a)            модуль
    acos(a)           обратный косинус
    and(a,b)          логическое и
    asin(a)           обратный синус
    atan(a)           обратный тангенс
    bitand(a,b)       побитное и
    bitnot(a)         побитная инверсия
    bitor(a,b)        побитное неисключающее или
    bitxor(a,b)       побитное исключающее или
    ceil(a)           округление в сторону inf
    cga2rgb(a)        rgb цвет cga(a)
    cos(a)            косинус
    cosh(a)           косинус гиперболический
    cpu_clock()       счетчик CPU от вызова cpu_start
    cpu_count()       счетчик числа процессоров
    cpu_start()       начать измерение счетчика CPU
    deg(a)            перевод радиан в градусы
    eq(a,b)           1 если a=b или 0
    exp(a)            натуральная экспонента
    floor(a)          округление в сторону 0
    frac(a)           дробная часть числа
    gamma(a)          гамма-функция: gamma(a)=(a-1)!
    ge(a,b)           1 если a>=b или 0
    getbitmask(a)     число 2^a
    getclockres(a)    узнать разрешение таймера в ms
    getpid()          идентификатор текущего процесса
    getppid()         идентификатор родительского процесса
    getticks()        время bios в тиках
    gt(a,b)           1 если a>b или 0
    hypot(a,b)        sqrt(a^2+b^2)
    int(a)            округление в сторону 0
    isbit(a,b)        1 если в a есть бит b или 0
    isinf(a)          1 если а=inf или 0
    isnan(a)          1 если а=nan или 0
    le(a,b)           1 если a<=b или 0
    ln(a)             натуральный логарифм
    log(a,b)          логарифм b по основанию a
    lt(a,b)           1 если a<b или 0
    max(a,b)          максимальное из a,b
    min(a,b)          минимальное из a,b
    mksecnow()        время в микросек. от старта
    msecnow()         время в миллисек. от р.х.
    ne(a,b)           1 если a<>b или 0
    not(a)            логическая инверсия
    or(a,b)           логическое неисключающее или
    pidaffinity(a,b)  задать привязку процесса к CPU
    rad(a)            перевод градусов в радианы
    rand()            случайное число от 0 до 1
    random(a,b)       случайное число от a до b
    rgb(a,b,c)        вычислить цвет (r,g,b)=(a,b,c)
    round(a)          округление до ближайшего целого
    secnow()          время в сек. от р.х.
    setclockres(a)    задать разрешение таймера в ms
    sign(a)           функция знака: -1,0,1
    sin(a)            синус
    sinh(a)           синус гиперболический
    sqrt(a)           корень
    tan(a)            тангенс
    tanh(a)           тангенс гиперболический
    trunc(a)          округление в сторону 0
    xor(a,b)          логическое исключающее или

    Список акций:

    @async    - выполнить команду асинхронно (в очередь).
    @echo     - вывод сообщения в консоль
    @global   - выполнение выражения в системном калькуляторе
    @mmtimer  - чтение\установка периода мулитимедийного таймера, [ms].
    @system   - выполнение выражения в системном калькуляторе
    @voice    - проигрывание звуковых wav файлов
    
С арифметическими функциями (abs, acos, asin, atan, ceil, cos, cosh, deg, floor, frac, gamma, hypot, int, isinf, isnan, ln, log, max, min, rad, rand, random, round, sign,sin, sinh, sqrt, tan, tanh, trunc) всё должно быть понятно, т.к. они работают обычным образом и не имеют особенностей.

Специальное замечание надо сделать относительно логических функций (and, eq, ge, gt, le, lt, ne, not, or, xor). Эти функции любое ненулевое значение аргументов воспринимают как логическую единицу (true=1), и возвращают логическое значение результата (false=0 или true=1). В сочетании с арифметическими операциями это позволяет реализовать в формульном виде многие вычисления, которые в обычном подходе требовали бы сложной логики. Например:
     вместо

     if x>b then y=c else if x>a then y=d else y=e

     можно написать

     x=gt(x,b)*c+le(x,b)*gt(x,a)*d+le(x,a)*e
    
Надо также сделать замечания относительно битовых функций (bitand, bitnot, bitor, bitxor, isbit, getbitmask). Эти функции преобразуют аргументы к типу LongInt путем округления (round), а затем выполняяют целочисленные операции. Это поведение надо учитывать при программировании. Например:
    bitand(v,255)    - округляет и выделяет биты 0..7
    bitand(v/256,7)  - выделяет биты 8..10 округленного числа v
    


Справка по графическим функциям интерпретатора Painter(v)


Перечисленные ниже функции служат для рисования на сенсорах в сценариях Painter(v).
Рисование происходит на фоне текущего изображения сенсора, которое задается тегом изображения (идентификатором картинки). Особое внимание следует обратить на то, что рисование происходит на текущем фоновом изображении сенсора, в частности границы рисования определяет размер картинки, а битность фонового изображения определяет битность рисуемого цвета. Отсюда следует, что для рисования в полном цвете необходимо использовать для сенсоров 24-битные изображения, т.к. при использовании 4 или 8-битных изображений RGB цвет будет "округляться" до ближайшего цвета палитры текущего фонового изображения.
Сверху накладывается циферблат (цифровая надпись), если указана ненулевая ширина LED.


Краткая сводка функций


     Sensor Painter routines
     sensorwidth()                                      - get sensor width
     sensorheight()                                     - get sensor height
     linkedvalue()                                      - linked tag/curve value, must be equal to v
     linkedcurve()                                      - linked curve reference
     linkedtag()                                        - linked tag reference
     linkedtagcolor()                                   - linked tag color, GetTagColor(linkedtag)
     linkedtagparam()                                   - linked tag param, GetTagParam(linkedtag)
     linkedtagtimer()                                   - linked tag timer, GetTagTimer(linkedtag)
     bookmark()                                         - sensor bookmark, i.e. current picture tag
     ledwidth()                                         - LED field width
     leddigit()                                         - LED digits after dot
     moveled(dx,dy)                                     - move LED to (dx,dy) px
     setcursor(x,y)                                     - set text cursor position
     setpen(pencolor,penstyle,penmode,penwidth)         - set pen style to draw lines
     setbrush(brushcolor,brushstyle)                    - set brush style to fill bars
     drawpoint(x1,y1,pointcolor,pointstyle)             - draw a point with given marker
     drawline(x1,y1,x2,y2)                              - draw a line with current pen
     drawarrow(x1,y1,x2,y2,d1,d2)                       - draw a line with arraw ends d1,d2
     drawrect(x1,y1,x2,y2)                              - draw a rect (filled rectangle)
     drawbox(x1,y1,x2,y2)                               - draw a box  (filled rectangle)
     drawbar(x1,y1,x2,y2)                               - draw a bar  (filled rectangle)
     drawroundrect(x1,y1,x2,y2,rx,ry)                   - draw a rounded rect (filled rounded rectangle)
     drawroundbox(x1,y1,x2,y2,rx,ry)                    - draw a rounded rect (filled rounded rectangle)
     drawroundbar(x1,y1,x2,y2,rx,ry)                    - draw a rounded rect (filled rounded rectangle)
     drawellipse(x1,y1,x2,y2)                           - draw a filled ellipse
     drawpie(x1,y1,x2,y2,x3,y3,x4,y4)                   - draw a filled ellipse pie
     drawarc(x1,y1,x2,y2,x3,y3,x4,y4)                   - draw a ellipse arc
     drawchord(x1,y1,x2,y2,x3,y3,x4,y4)                 - draw a filled ellipse chord
     drawpoly(x,y,pl)                                   - draw polygonal figure of (x,y) array, pl is operation
     setsimulation(m)                                   - set simulation mode m=0/1=normal/simulation (just for testing)
     setdebugflags(f)                                   - set DebugFlags (just for debug):
                                                          bit 0/1/2/3: echo on Startup/TagEval/LedEval/Painter errors
                                                          bit 4/5/6/7: log to Temp\Debug.out file on Startup/TagEval/LedEval/Painter errors
     @print msg                                         - draw a text (msg) at cursor
     @textwidth msg                                     - return text width
     @textheight msg                                    - return text height
     @font charset/color/height/size/name/pitch/style value  - assign value to font property like @font name PT Mono
     where:
      color=[R,G,B]=[clBlack,clMaroon,clGreen,clOlive,clNavy,clPurple,clTeal,clGray,clSilver,clRed,clLime,clYellow,clBlue,clFuchsia,clAqua,clLtGray,clDkGray,clWhite]
      penstyle=[0..6]=[psSolid,psDash,psDot,psDashDot,psDashDotDot,psClear,psInsideFrame]
      penmode=[0..15]=[pmBlack,pmWhite,pmNop,pmNot,pmCopy,pmNotCopy,pmMergePenNot,pmMaskPenNot,pmMergeNotPen,pmMaskNotPen,pmMerge,pmNotMerge,pmMask,pmNotMask,pmXor,pmNotXor]
      penwidth=line width
      barcolor=color of bar filling
      barstyle=[0..7]=[bsSolid,bsClear,bsHorizontal,bsVertical,bsFDiagonal,bsBDiagonal,bsCross,bsDiagCross]
      charset=[ANSI_CHARSET, DEFAULT_CHARSET, SYMBOL_CHARSET, MAC_CHARSET, SHIFTJIS_CHARSET, HANGEUL_CHARSET,
               JOHAB_CHARSET, GB2312_CHARSET, CHINESEBIG5_CHARSET, GREEK_CHARSET, TURKISH_CHARSET, HEBREW_CHARSET,
               ARABIC_CHARSET, BALTIC_CHARSET, RUSSIAN_CHARSET, THAI_CHARSET, EASTEUROPE_CHARSET, OEM_CHARSET]
      font style=[0..15]=4 bits [fsBold,fsItalic,fsUnderline,fsStrikeOut]
      font pitch=[0..2]=[fpDefault,fpVariable,fpFixed]
      pl=[0..5]=plNone,plClear,plAddPoint,plPolyLine,plPolygon,plPolyBezier
  


Подробное описание функций


sensorWidth() - возвращает ширину сенсора в пикселях.
sensorHeight() - возвращает высоту сенсора в пикселях.
Функции используются для расчета графических координат рисуемых объектов.
Графические координаты отсчитываются от точки (0,0) верхнего левого угла сенсора.
Координата X идет слева направо, а Y сверху вниз.


linkedValue() - возвращает значение подключенной к сенсору кривой/тега. Должно быть равно v.
linkedCurve() - возвращает ссылку подключенной к сенсору кривой.
linkedTag() - возвращает ссылку подключенного к сенсору тега.
linkedTagColor() - возвращает атрибут цвета (color) подключенного к сенсору тега. Прикладная программа может задать цвет тега вызовом SetTagColor(tag,color).
linkedTagParam() - возвращает атрибут пользовательского параметра (param) подключенного к сенсору тега. Прикладная программа может задать пользовательский параметр тега вызовом SetTagParam(tag,param).
linkedTagTimer() - возвращает атрибут метки времени (timer) подключенного к сенсору тега. Прикладная программа может задать метку времени тега вызовом SetTagTimer(tag,timer).
bookmark() - возвращает идентификатор текущей картинки изображения сенсора.
ledWidth() - возвращает ширину числового поля LED.
ledDigit() - возвращает точность LED (число знаков после запятой).
Функции используются для определения параметров сенсора.


moveLed(dx,dy) - сдвигает циферблат (цифровую надпись - LED) относительно обычного положения. Обычное положение надписи - по центру сенсора. Сдвиг позволяет смещать надпись относительного этого положения. Применяется, например, для имитации нажатия кнопок.


setCursor(x,y) - задает координаты текстового курсора.
Курсор задается перед вызовом функции @print для указания места печати.
Курсор определяет координату верхнего левого угла выводимого текста.


setPen(penColor,penStyle,penMode,penWidth) - задает "перо" (pen), т.е. стиль рисования линий.
Перо используется при рисовании любых линейных объектов - линий, контуров прямоугольников и эллипсов и т.д.
Перо должно быть задано перед рисованием интересующей фигуры.

Параметр penColor задает цвет линий. Для указания цвета можно использовать числовые значения RGB, например, $0AFF88. Можно также использовать константы для распространенных цветов:
 clBlack   ,  clMaroon  ,  clGreen   ,  clOlive   ,  clNavy    ,  clPurple  ,  clTeal   ,  clGray    ,  clDkGray ,
 clWhite   .  clRed     ,  clLime    ,  clYellow  ,  clBlue    ,  clFuchsia ,  clAqua   ,  clLtGray  ,  clSilver ,
Подробнее о цветах см. справку по цветовым константам Painter(v).
Особое внимание следует обратить на то, что рисование происходит на текущем фоновом изображении сенсора, в частности битность фонового изображения сенсора определяет битность рисуемого цвета. Отсюда следует, что для рисования в полном цвете необходимо использовать для сенсоров 24-битные изображения, т.к. при использовании 4 или 8-битных изображений RGB цвет будет "округляться" до ближайшего цвета палитры текущего фонового изображения.

Параметр penStyle задает стиль линий. Это набор констант psSolid (сплошная), psDash (штрих), psDot (пунктир), psDashDot (штрих пунктир), psDashDotDot (двойной штрих пунктир), psClear (пустая, т.е. не рисовать), psInsideFrame. Обычно используется стиль psSolid для сплошных линий. Стиль psClear используется, чтобы избежать рисования контуров фигур.

Параметр penMode задает режим рисования линий. Это набор констант pmBlack, pmWhite, pmNop, pmNot, pmCopy, pmNotCopy, pmMergePenNot, pmMaskPenNot, pmMergeNotPen, pmMaskNotPen, pmMerge, pmNotMerge, pmMask, pmNotMask, pmXor, pmNotXor. Обычно используется режим pmCopy для рисования указанным цветом. Другие режимы позволяют рисовать, например, с инверсией цвета, наложением цветовой маски и т.д.

Параметр penWidth задает толщину рисуемых линий в пикселях.


setBrush(brushColor,brushStyle) - задает "Кисть" (brush), т.е. стиль заполнения рисуемых фигур. Кисть используется при рисовании любых объемных (имеющих площадь) объектов - прямоугольников, эллипсов и т.д. Кисть должна быть задана перед рисованием интересующей фигуры.

Параметр brushColor задает цвет заполнения. Он может принимать такие же значения, как параметр penColor.

Параметр brushStyle задает стиль заполнения. Это набор констант bsSolid (сплошное заполнение), bsClear (нет заполнения), bsHorizontal (горизонтальная штриховка), bsVertical (вертикальная штриховка), bsFDiagonal (косая штриховка вперед), bsBDiagonal (косая штриховка назад), bsCross (прямая клетка), bsDiagCross (наклонная клетка). Обычно используется режим bsSolid для рисования заполненных фигур. Режим bsClear используется если надо рисовать только контур фигур без заполнения.


drawPoint(x,y,pointColor,pointStyle) - рисует точечный маркер.

Параметры x,y задают координаты маркера.

Параметр pointColor задает цвет маркера.

Параметр pointStyle задает стиль маркера (такой же как на кривых). Нулевой стиль соответствует отдельному пикселю.


drawLine(x1,y1,x2,y2) - рисует отрезок прямой (line).
drawArrow(x1,y1,x2,y2,d1,d2) - рисует отрезок со стрелкой на конце (arrow).

Параметры x1,y1 задают координаты начала отрезка.

Параметры x2,y2 задают координаты конца отрезка.

Параметры d1,d2 задают размеры стрелки на конце отрезка (длину и раствор стрелки).

При рисовании отрезков и стрелок используется ранее заданное перо.


drawRect(x1,y1,x2,y2) - рисует прямоугольник (rect).
drawBox(x1,y1,x2,y2) - рисует прямоугольник (box).
drawBar(x1,y1,x2,y2) - рисует прямоугольник (bar).
Функции являются синонимами (так сложилось исторически).

Параметры x1,y1 задают координаты верхнего левого угла прямоугольника.

Параметры x2,y2 задают координаты нижнего правого угла прямоугольника.

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


drawRoundRect(x1,y1,x2,y2,rx,ry) - рисует скругленный прямоугольник (rect).
drawRoundBox(x1,y1,x2,y2,rx,ry) - рисует скругленный прямоугольник (box).
drawRoundBar(x1,y1,x2,y2,rx,ry) - рисует скругленный прямоугольник (bar).
Функции являются синонимами (так сложилось исторически).

Параметры x1,y1 задают координаты верхнего левого угла прямоугольника.

Параметры x2,y2 задают координаты нижнего правого угла прямоугольника.

Параметры rx,ry задают размеры скругления углов прямоугольника.

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


drawEllipse(x1,y1,x2,y2) - рисует эллипс (ellipse).

Параметры x1,y1,x2,y2 задают координаты прямоугольника, в который вписан эллипс.

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


drawPie(x1,y1,x2,y2,x3,y3,x4,y4) - рисует сегмент (pie) эллипса.

Параметры x1,y1,x2,y2 задают координаты прямоугольника, в который вписан эллипс.

Параметры x3,y3,x4,y4 задают координаты сегмента (pie) эллипса.

Используйте drawPie, чтобы нарисовать клинообразный сегмент эллипса. Клин определяется эллипсом, ограниченным прямоугольником, определенным точками (X1, Y1) и (X2, Y2). Рисуемое сечение определяется двумя линиями, идущими от центра эллипса через точки (X3, Y3) и (X4, Y4).

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


drawArc(x1,y1,x2,y2,x3,y3,x4,y4) - рисует дугу (arc) эллипса.

Параметры x1,y1,x2,y2 задают координаты прямоугольника, в который вписан эллипс.

Параметры x3,y3,x4,y4 задают координаты дуги (арки) эллипса.

Дуга пересекает периметр эллипса,который ограничен точками (X1,Y1) и (X2, Y2). Дуга рисуется по периметру эллипса, против часовой стрелки от начальной точки до конечной точки. Начальная точка определяется пересечением эллипса и линией,определенной центром эллипса и (X3, Y3). Конечная точка определяется пересечением эллипса и линией, определенной центром эллипса и (X4, Y4).

При рисовании дуги эллипса используется ранее заданное перо.


drawChord(x1,y1,x2,y2,x3,y3,x4,y4) - рисует хорду (chord) эллипса.
Рисует замкнутую фигуру, представленную пересечением линии и эллипса.

Параметры x1,y1,x2,y2 задают координаты прямоугольника, в который вписан эллипс.

Параметры x3,y3,x4,y4 задают координаты хорды (chord) эллипса.

Используйте drawChord для рисования хорды - фигуры, определенной дугой эллипса и линией, соединяющей конечные точки дуги. Хорда состоит из части эллипса,которая ограничена точками (X1,Y1) и (X2, Y2). Эллипс делится на линии,которая проходит между точками (X3,Y3) и (X4, Y4). По периметру хорда проходит против часовой стрелки от (X3,Y3), против часовой стрелки вдоль эллипса до (X4,Y4), и прямо обратно (X3, Y3). Если (X3, Y3) и (X4, Y4) не находятся на поверхности эллипса, то соответствующие углы хорды являются ближайшими точками по периметру, пересекающим линию.

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


drawPoly(x,y,pl) - рисует полигональные (многоугольные) фигуры.

Параметры x,y задают координаты точек полигональной фигуры.

Параметр pl задает операцию над полигональной фигурой:

  1. plNone - Не делает ничего. Служит для обхода исполнения оператора по каким-то условиям. В этом случае параметры (x,y) не используются.
  2. plClear - очищает массив точек полигональной фигуры. В этом случае параметры (x,y) не используются.
  3. plAddPoint - добавляет в массив точек полигональной фигуры еще одну точку (x,y). Вызывается многократно для накопления массива точек.
  4. plPolyLine - рисует незаполненную линейную полигональную фигуру, используя ранее накопленный массив точек (x,y). В этом случае параметры (x,y) не используются. Точки соединяяются линейными отрезками, используя текущее перо. Массив должен содержать не менее 2 точек.
  5. plPolygon - рисует заполненную линейную полигональную фигуру, используя ранее накопленный массив точек (x,y). В этом случае параметры (x,y) не используются. Точки соединяяются линейными отрезками, используя текущее перо. Затем внутренность фигуры заполняется, используя текущую кисть. Массив должен содержать не менее 3 точек.
  6. plPolyBezier - рисует незаполненную сплайновую фигуру, используя ранее накопленный массив точек (x,y). В этом случае параметры (x,y) не используются. Точки соединяяются отрезками кубического сплайна Безье (Bezier), используя текущее перо. Массив должен содержать не менее 4 точек.
Например, так можно рисовать звёздочки с числом вершин от 2 до 8:
    (sw=sensorWidth())+(sh=sensorHeight())
    ;=====================================================================================
    ; Polygonal figure (nv-vertex Star) drawing example, may draw up to nv=8 vertices.
    ; (cx,cy)=center, nv=number of vertices, r1/r2=outer/inner radius, fi=start angle.
    ;=====================================================================================
    setPen(clBlue,psSolid,pmCopy,1)+setBrush(clYellow,bsSolid)           ; Set pen/brush to draw
    (cx=sw/2)+(cy=sh/2)+(nv=5)+(r1=20)+(r2=7)+(fi=pi/2*3)                ; Init (cx,cy,nv,r1,r2,fi)
    drawPoly(0,0,plClear)+(rt=fi)+(st=pi/nv)                             ; Init vertex points
    drawPoly(cx+cos(rt)*r1,cy+sin(rt)*r1,plAddPoint*ge(nv,1))+(rt=rt+st) ; Vertex 1 (outer)
    drawPoly(cx+cos(rt)*r2,cy+sin(rt)*r2,plAddPoint*ge(nv,1))+(rt=rt+st) ; Vertex 1 (inner)
    drawPoly(cx+cos(rt)*r1,cy+sin(rt)*r1,plAddPoint*ge(nv,2))+(rt=rt+st) ; Vertex 2 (outer)
    drawPoly(cx+cos(rt)*r2,cy+sin(rt)*r2,plAddPoint*ge(nv,2))+(rt=rt+st) ; Vertex 2 (inner)
    drawPoly(cx+cos(rt)*r1,cy+sin(rt)*r1,plAddPoint*ge(nv,3))+(rt=rt+st) ; Vertex 3 (outer)
    drawPoly(cx+cos(rt)*r2,cy+sin(rt)*r2,plAddPoint*ge(nv,3))+(rt=rt+st) ; Vertex 3 (inner)
    drawPoly(cx+cos(rt)*r1,cy+sin(rt)*r1,plAddPoint*ge(nv,4))+(rt=rt+st) ; Vertex 4 (outer)
    drawPoly(cx+cos(rt)*r2,cy+sin(rt)*r2,plAddPoint*ge(nv,4))+(rt=rt+st) ; Vertex 4 (inner)
    drawPoly(cx+cos(rt)*r1,cy+sin(rt)*r1,plAddPoint*ge(nv,5))+(rt=rt+st) ; Vertex 5 (outer)
    drawPoly(cx+cos(rt)*r2,cy+sin(rt)*r2,plAddPoint*ge(nv,5))+(rt=rt+st) ; Vertex 5 (inner)
    drawPoly(cx+cos(rt)*r1,cy+sin(rt)*r1,plAddPoint*ge(nv,6))+(rt=rt+st) ; Vertex 6 (outer)
    drawPoly(cx+cos(rt)*r2,cy+sin(rt)*r2,plAddPoint*ge(nv,6))+(rt=rt+st) ; Vertex 6 (inner)
    drawPoly(cx+cos(rt)*r1,cy+sin(rt)*r1,plAddPoint*ge(nv,7))+(rt=rt+st) ; Vertex 7 (outer)
    drawPoly(cx+cos(rt)*r2,cy+sin(rt)*r2,plAddPoint*ge(nv,7))+(rt=rt+st) ; Vertex 7 (inner)
    drawPoly(cx+cos(rt)*r1,cy+sin(rt)*r1,plAddPoint*ge(nv,8))+(rt=rt+st) ; Vertex 8 (outer)
    drawPoly(cx+cos(rt)*r2,cy+sin(rt)*r2,plAddPoint*ge(nv,8))+(rt=rt+st) ; Vertex 8 (inner)
    drawPoly(cx+cos(fi)*r1,cy+sin(fi)*r1,plAddPoint)                     ; Finalize points
    drawPoly(0,0,plPolygon)+drawPoly(0,0,plClear)                        ; Draw + Cleanup
  


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


setSimulation(m) - задает режим симуляции m = 0 или 1. Возвращает предыдущее состояние симуляции.
Функция используется для отладки и проверки производительности графического интерпретатора Painter(v). В нормальном состоянии (m=0) при вызове функций Painter(v) идет прорисовка графических элементов. В состоянии симуляции (m=1) при вызове функций Painter(v) все прорисовки игнорируются, что позволяет оценить производительность интерпретатора самого по себе и графической системы отдельно.


setDebugFlags(f) - задает флаги отладки f. Возвращает предыдущее состояние флагов отладки.
Функция используется для отладки и управления отладочным выводом интерпретатора Painter(v) при ошибках. Биты флагов f означают следующее:

Вызов функции рекомендуется делать в начале секции [Circuit.StartupScript], чтобы включить отладку как можно раньше. Например:
   [Circuit.StartupScript] ; секция Startup сценария
   setDebugFlags(15*16)    ; включить отладочный вывод в файл Temp\Debug.out
   ...                     ; теперь при ошибках можно увидеть диагностику в файле
  
Следует подчеркнуть, что отладочный вывод делается только при возникновении ошибок при выполнении сценариев [Circuit.StartupScript], TagEval(v), LedEval(v), Painter(v). Нормальное выполение сценариев Painter(v) происходит "молча".

Заметим, что злоупотреблять отладочным выводом не следует из соображений производительности. После успешной отладки весь отладочный вывод следует отключать, убрав вызов setdebugflags, либо задав нулевое значение флагов setdebugflags(0).


@print msg - рисует текст сообщения (msg) в позиции, заданной курсором.

Параметр msg задает выводимый текст.

В тексте можно использовать подстановки переменных типа %v (подстановка переменной v).
Если перед подстановкой используется формат, то подстановка делается с использованием формата.
Например, подстановка @print %7.3f%v выведет значение переменной v в формате %7.3f.

Цвет и стиль фона определяет ранее заданная кисть - setBrush.
Положение надписи определяет ранее заданный курсор - setCursor.
Фонт (имя, стиль, цвет) задается функцией @font.


@textWidth msg - возвращает ширину текста (msg) в пикселях.

Параметр msg задает текст, ширину которого надо определить.

Возвращается ширина текста msg при текущем фонте, заданном функцией @font.
Функция обычно используется для расчета координат текстового курсора.


@textHeight msg - возвращает высоту текста (msg) в пикселях.

Параметр msg задает текст, высоту которого надо определить.

Возвращается высота текста msg при текущем фонте, заданном функцией @font.
Функция обычно используется для расчета координат текстового курсора.


@font id value - задает свойства текущего фонта.
Функция @font используется для задания фонта перед выводом сообщений функцией @print.

Параметр id задает идентификатор свойства - Charset, Color, Height, Size, Name, Pitch, Style.

Параметр value задает значение свойства - id. Если value не указано, то значение свойства не меняется.

Функция возвращает значение свойства id перед вызовом функции. Это позволяет узнавать и восстанавливать предыдущее значение.

Свойство Charset задает язык и принимает значения ANSI_CHARSET, DEFAULT_CHARSET, SYMBOL_CHARSET, MAC_CHARSET, SHIFTJIS_CHARSET, HANGEUL_CHARSET, JOHAB_CHARSET, GB2312_CHARSET, CHINESEBIG5_CHARSET, GREEK_CHARSET, TURKISH_CHARSET, HEBREW_CHARSET, ARABIC_CHARSET, BALTIC_CHARSET, RUSSIAN_CHARSET, THAI_CHARSET, EASTEUROPE_CHARSET, OEM_CHARSET.
Обычно используется RUSSIAN_CHARSET=204.

Свойство Color задает цвет шрифта.

Свойство Size задает размер шрифта в пунктах (pt). Размер шрифта в пунктах обычно указывается в диалогах выбора шрифта. Высота шрифта в пикселях (px) определяется по формуле Height=Size*4/3.

Свойство Height задает высоту шрифта в пикселях (px), взятую со знаком минус. Оно расчитывается по формуле Height=-round(1.33*Size), где Size - размер шрифта к пунктах (pt). Например, фонт с размером Size=10pt имеет Height=-13.

Свойство Name задает имя шрифта.

Свойство Pitch задает ширину шрифта и принимает значения fpDefault, fpVariable, fpFixed.

Свойство Style имеет 4 бита - fsBold, fsItalic, fsUnderline, fsStrikeOut. Например, для задания жирного (bold) шрифта указывается Style=1.

Для передачи значений переменных используются подстановки (например переменная v передается как %v).
Например: @font color %clRed задает цвет фонта clRed.
Пример задания фонта и печати:

   @font size 12       ; set font size 12 pt
   fh=-round(1.33*12)  ; get height of font 12 pt
   @font height %fh    ; set font height
   @font color %clBlue ; set font color Blue
   @font charset 204   ; set russian charset
   @font style 3       ; set font Bold Italic
   @font name PT Mono  ; set font name PT Mono
   setCursor(5,10)     ; set text cursor position
   @print %7.3f%v      ; print v value with format %7.3f
  


Графические библиотеки GuiLib, DaqLib, GostLib для Painter(v)


Для облегчения использования сценариев Painter(v) созданы библиотеки графических элементов GuiLib, DaqLib, GostLib. При использовании графических элементов используются описанные здесь договоренности, правила и рекомендации.


Полезные советы по сценариям Painter(v)


Несколько полезных примечаний по написанию сценариев Painter(v).

  1. Сценарии Painter(v) и формулы TagEval(v), LedEval(v) пишутся на языке DaqScript, поэтому используемые там формулы можно (частично) проверять в Калькуляторе или в Главной Консоли. Все интерпретаторы имеют один синтаксический анализатор, отличаются только наборы доступных функций.

  2. Для отладки скриптов Painter(v) можно использовать @echo для печати отладочного вывода в Главной Консоли. После отладки эти сообщения удаляются из сценария.

  3. При написании сценариев Painter(v) следует учитывать, что все сенсоры данного окна мнемосхемы работают в одном интерпретаторе, а поэтому имеют общее пространство переменных. Это создает как полезные возможности (например, совместное использование общих констант), так и возможные проблемы (один сценарий может влиять на работу другого). Чтобы избежать трудно обнаружимых ошибок, следует минимизировать связи между сценариями по общим переменным и не надеяться на то, что переменные будут сохранять свои значения между вызовами, т.к. их значения могут измениться в другом скрипте. В общем, надо быть внимательным и на предмет взаимного влияния сценариев.

  4. Из соображений производительности желательно, чтобы сценарии Painter(v) были простыми, т.е. чтобы они не содержали управляющих операторов if.. then, goto, gosub .. return, exit. Простые сценарии Painter(v) выполняются существенно быстрее. Поэтому по возможности следует избегать использования перечисленных операторов и заменять их эквивалентными простыми выражениями. Например:
        Выражение
    
         if le(a,b) then c=0
    
        можно заменить на эквивалентное
    
         c=c*le(a,b)
    
        это выражение обнуляет c если a <= b
    
        Другой пример - расчет цвета для индикатора уровня:
    
        Условные выражения
    
         color=clGreen
         if gt(v,alarm1) then color=clYellow
         if gt(v,alarm2) then color=clRed
    
        можно заменить на эквивалентное простое выражение
    
         color=clGreen*le(v,alarm1)+clYellow*gt(v,alarm1)*le(v,alarm2)+clRed*gt(v,alarm2)
        
    Использование только простых выражений позволяет сделать сценарии существенно быстрее.

  5. Для задания параметров скриптов Painter(v) из программ DaqPascal можно использовать функцию WinDraw('WindowName|Fast|Eval=...').
    Например:
         Вызов
    
          bNul(WinDraw('DemoPaint|Fast|Eval=(alarm1=10)+(alarm2=20)'));
    
         задает переменные alarm1=10, alarm2=20
    
         Фактически вызов означает, что интерпретатору окна
         передается для исполнения выражение
    
          (alarm1=10)+(alarm2=20)
    
         Здесь используются скобки для присвоения сразу двух параметров.
        
    Это позволяет динамически управлять поведением сенсоров из программ DaqPascal.

  6. С помощью скобок можно делать несколько присвоений переменных в одной строке, например:
        (x=10)+(y=20) - задает x=10 и y=20
        
    Это позволяет сделать сценарии компактнее и быстрее.

  7. Можно совмещать вызовы задания пера, кисти и рисования, например:
         setPen(clRed,psSolid,pmCopy,1)+drawLine(10,10,70,80)
         setPen(clBlack,psSolid,pmCopy,1)+setBrush(clBlue,bsSolid)+drawBar(5,10,15,20)
        
    При этом задание пера и кисти должно предшествовать рисованию.


Памятка по функциям Painter(v)


Имеется памятка для использования функций Painter(v):


Успешного использования Painter(v)!