Объект "Plan Marker"


Доброго Времени Суток!

Сегодня разбор очередного GDL-объекта с изощренной 2D начинкой, в виде кучки АС(Активные споты - для редактирования объекта в окне(2D,3D)) и организации их поведения. На примере данного объекта будет показано как организовать  интерактивное редактирование объекта на плане. Т.е. сделать так, чтобы каждый раз не лезть в диалог установки параметров, что IMHO лишний раз делать не хочется, даже если там супер-пупер разукрашенная вкладка интерфейса.



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

INTRO:

объект представляет собой "компоновку" из трех различных по назначению маркеров:

1. Первый маркер - это позиция детали на КМД (не обязательно) чертеже, выглядит маркер как кружок с линией-выноской, внутри которого текст - номер позиции детали.
Логическая нагрузка:
1.1 интерактивный выбор номера позиции(АС-1, углового типа);
1.2 число линий выносок от 0 до 10, задается в меню объекта;
1.3 редактирование положения выноски, выноска начинается в АС-2 и заканчивается на контуре круга маркера;
1.4 правильная отрисовка при изменении масштаба окна. Сомнительная необходимость, тем не менее реализовано.
1.5 в меню задаются остальные моменты оформления маркера - размер, перья, штриховка.
1.6 данные для обработки интерактивным каталогом(количество, ед.изм., наименование); реализовано в следующих целях - в соответствии с ГОСТ 21.501 рабочая документация по большому счету состоит из схем расположения и спецификаций к ним. При этом на схемах расположения учитываемые конструкции  изображаются условно, в соответствии с принятыми условными обозначениями. Например балка изображается линией, план перекрестных балок - набор линий, не замкнутых друг на друга , т.е. я хочу сказать что используя технологию BIM, необходимо будет потратить время на приведение автоматически сгенерированных планов/разрезов к ГОСТ. IMHO, в данном случае модель избыточна, достаточно нарисовать подобную схему 2Д примитивами, и используя параметры  (количество, ед.изм., наименование) предусмотренные в данном маркере обсчитать схему при помощи ИК.

 Скрин 1. Маркер "Позиция".

2. Маркер для указания типа полов в помещении. В виде равностороннего треугольника с номером типа пола. Т.е. в рабочем проекте существует экспликация полов, в которой эта нумерация типов полов и отражается. Речь идет о таблице ГОСТ 21.501.
Тут стоит сказать пару слов. Вообще этот маркер  не является ГОСТовским изображением, ГОСТ не дает указаний относительно вида маркера полов. Как правило, план полов отдельно не выполняется, и типы полов соответственно приводятся в экспликации полов, т.е. в строке по каждому типу приводится список номеров помещений в которых предусматривается данный вид полов. (В общем все в курсе, я просто решил помять клавиши...) Тем не менее этот маркер достаточно "закрепился" в оформлении рабочих чертежей АС. И потому добавлен в компоновку объекта. Также моей вольностью было добавить возможность этому маркеру иметь линии-выноски, с целью маркировать полы в мелких при данном масштабе помещениях.
Логическая нагрузка:
По аналогии с маркером "номер позиции"+селектор - привязка линий выносок, 2 варианта:
-к ближайшей вершине маркера;
-к указанной вершине маркера, т.е возможна привязка к 3 точкам, указывается спотом(скрин 2.2) ;
 Параметр "размер маркера" в случае "треугольника" задает диаметр описанной, на котором и нужно искать АС-1.


 Скрин 2.1. Маркер "Тип пола".
Привязка линий-выносок к ближайшей вершине.

 Скрин 2.2. Маркер "Тип пола".
Привязка линий-выносок к указанной вершине.

3. Маркер измененного участка чертежа. Этот маркер регламентируется ГОСТ 21.1101. В нормативе приведены все сведения - как где и когда  применять этот маркер.
Логическая нагрузка:
По аналогии с маркером "номер позиции"+регламентированная ГОСТ 21.1101 функциональность;
- так как заранее нельзя знать какой размер шрифта будет  использован, то вся свистопляска относительно размеров параллелограма, положению АС-4, основана на выбираемом размере шрифта;
- привязка линий выносок, возможна к 4-м точкам - узлам параллелограма, указывается спотом АС-4;
- при горизонтальном отзеркаливании параллелограм должен сохранять свою "ориентацию", т.е. сам контур маркера не должен разворачиваться при операции отзеркаливания(см.видео);
- параметры для ИК(интерактивный каталог) здесь не нужны;

 Скрин 3.1. Маркер "Измененный участок".
 Редактирование текста.
 
Скрин 3.2. Маркер "Измененный участок". 
Редактирование привязки выносок.

Скрин 3.3. Маркер "Измененный участок". 
Редактирование положения маркера.



Назад, к баранам:
Решающим моментом, по включению в один объект этих трех маркеров послужило то, что все они являются элементами оформления чертежа. Как правило, все они существуют в одном проекте и будет правильно и удобно не ползать в библиотеку чтобы найти и выбрать один из них. А в конкретном проекте, на конкретном листе копировать один из размещенных, например маркеров "позиция детали" и, изменив ему тип, на "участок изменений" настроить его нужным образом, т.е. обойтись без поиска по библиотеке, что согласитесь УДОБНО.
Но есть и другая сторона - почему бы не включить в сборку кучу других маркеров? Например маркеры разрезов, узлов? Первое -  эти маркеры есть в составе инструментов Арчика. Разумеется свой объект всегда будет удобнее чем предлагаемый, потому лишь что свои вещи как правило и являются результатом "ленивого труда", т.е. день за днем что-то все время неустраивает, нервирует, и рано или поздно настает момент действий - написание своего. А второе - это момент, который с условной натяжкой - все таки GDL, довольно специфический синтаксис, чтобы применять к нему общепринятые абстракции - закон возрастающей сложности кода, здесь это неплохо изложено:
"Вам кажется, что имея в два раза больше кода, ваша программа будет только вдвое сложнее. На самом деле, каждый раз, когда вы увеличиваете объем кода, сложность программы возрастает экспоненциально. Каждое маленькое дополнение, каждое изменение, каждая взаимозависимость и каждое предпочтение имеют каскадный эффект. Продолжайте безбоязненно добавлять код, и вы получите страшный Большой Ком Грязи — до того, как это заметите.
Как бороться с этой сложностью — уменьшением объема программы. Уменьшение объема программы значит меньше функций, меньше кода, меньше отходов."
http://www.libma.ru/delovaja_literatura/getting_real/p11.php

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

- примочка арчика - AddOn(C++, *.apx), 

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

- Любой внешний проект(еще более общий случай), с интерфейсной частью и логикой, результатом работы которого является "выхлоп", в одном из форматов, которые может читать GDL-скрипт - txt, csv, bin, xml. Этот вариант интересен, в первую очередь тем, что полностью развязывает руки разработчику - нет необходимости регистрироваться в качестве разработчика, нет необходимости ковырять на мой взгляд не самый аппетитный Graphisoft API. Полная свобода инструментов. Обратная сторона - нет некоторых возможностей обусловленный именно родным API, но таких необходимости таких случаев скорее меньше, если не сказать что это вообще специфика. Меньше вероятность ошибок. Хотя есть и существенные моменты,  об этом в  "О целесообразности написания своего объекта, и его проектировании". См. в конце статьи.

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

1. ПАРАМЕТРЫ 

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



 Скрин 4. Параметры.


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

Относительно конкретных параметров:

FSC - нужен для пересчета размеров маркера при изменении масштаба окна(плана/разреза/фасада); такое бывает не часто, тем не менее реализовано. Обычная практика - в макете указать масштаб вьюпорта, там проблем ни с одним объектом быть не может, работает Арч. (IMHO).

AX,BX - поправки отвечающие за "пузатость" контура параллелограма(чтобы текст не залезал на контур маркера)

XC - массив АС - координат окончаний линий-выносок. Поэтому, переключая типы выносок если вновь выбранный маркер может иметь выноски - они останутся на своих местах, разумеется, если были ранее расставлены. Не может иметь выносок маркер 3, параллелограм в случае если объект символизирует участок-дополнение, тут автоматом скрипт параметров выставит значение NN в ноль.
 Скрин 5. Маркер "Измененный участок.Дополнение".

sAng - с юзернэймом "первый разряд", это параметр завязанный на АС-угол, в маркере "Позиция детали", по его значению вычисляется текст размещаемый в маркере.
rAng1,rAng2 - аналогично, текст номера и участка изменения в маркере 3
dAng - текст маркера "тип пола";

rad1,rad2 - параметры размера маркера, задаются пользователем в меню, в конечных единицах, в мм(или какие установлены у вас в Арче в качестве единиц длины);

rad1s,rad2s -тоже, внутренние, пересчитанные в масштабе окна; пользователю недоуступны;

параметры из раздела "установки"(3шт) - задают пределы изменения числовых значений
отображаемых в маркерах (соответственно названию).  

- параметры с индексом SM... - смета, для ИК.

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

2. СКРИПТ ПАРАМЕТРОВ

Итак, смотрим как реализована требуемая логика:

!X1,Y1 - центр маркера, для всех типов маркера в этой точке отрисовывается текст.

!  - получаем массив установленных шрифтов;
dim fontNames[]

n = request("FONTNAMES_LIST", "", fontNames)
values "F"  fontNames, custom

 !  - размер шрифта не менее 1мм;
values "FS" range[1,)

!  - число линий-выносок;
values "NN" 0,1,2,3,4,5,6,7,8,9,10

! FSC Искать в основном скрипте

!  - описана логика вычисления точек привязки линий-выносок к углам контура в маркере "параллелограм";
 
values "X2" X1-AX*FSC,X1+AX*FSC,X1-BX*FSC,X1+BX*FSC
IF (X2=X1-AX*FSC) or (X2=X1+BX*FSC) then
values "Y2" Y1+FSC
endif

IF (X2=X1+AX*FSC) or (X2=X1-BX*FSC) then
values "Y2" Y1-FSC
endif

!  - значения иксов для привязок линий-выносок треугольника, X1,Y1 - центр маркера;
! - и соответствуюшие иксам игреки.

values "X3" x1, x1-rad1*cos(30),x1+rad1*cos(30)

IF (X3=x1-rad1*cos(30)) or (X3=x1+rad1*cos(30)) then
values "Y3" y1-rad1*cos(60)
endif

IF (X3=x1) then
values "Y3" y1+rad1
endif

! - без коментов
values "type"  "Круг", "Треугольник", "Параллелограм"
values "remark_type" "Просто измененный участок","См.лист","Взамен перечеркнутого на листе","Дополнение","Аннулировано"

values "snap_type"  "К ближайшей вершине", "К указанной вершине"

!=============================================

! - используем программный стек для хранения значений углового параметра 

if type="Круг" then
               xx=pos_max
               For x=1 to xx
               PUT INT(360/xx)*x
               NEXT x
 ! - назначаем параметру sAng все вычисленные и сохраненные в стеке параметры; команда GET очищает стек.

                values "sAng" GET(NSP)
endif

if type="Параллелограм" then
xx=izm_max
               For x=1 to xx
               PUT INT(360/xx)*x
               NEXT x

 ! - назначаем параметрам rAng1,2 все вычисленные и сохраненные в стеке параметры; команда USE НЕ-очищает стек. Поэтому параметр rAng2 получит данные аналогичные rAng1

values "rAng1" USE(NSP)
values "rAng2" USE(NSP)
endif

 ! - аналогично, в соответствии с установкой pol_max заполняем список возможных значений для dAng, передаем его параметру из стека,очищаем стек.
 
if type="Треугольник" then
               xx=pol_max
               For x=1 to xx
               PUT INT(360/xx)*x
               NEXT x
               values "dAng" GET(NSP)
endif


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

       3. ОСНОВНОЙ СКРИПТ

 ! - необходимость пользовательского текста(т.е. в маркере можно нарисовать и букву и использовать его как маркер оси %)
if IsCustomText=0 Then
HIDEPARAMETER "CustomText"
Endif


 ! - необходимость штриховки, обратите внимание как повешены друг на друга параметры перья и тип штриховки(на вкладке параметры и в основном скрипте), таким образом пользователь получает для ввода только те параметры которые подразумеваются его выбором, т.е. выбрал "штриховать" - появился тип штриховки и аттрибуты штриховки, это полезно с точки зрения распределения внимания. Бывает откроешь менюху объекта а там 200 параметров!!! куда смотреть, за что цепляться? IMHO - если уж заставляешь пользователя лезть в меню  - "приберись" там.
if IsFill=0 Then
HIDEPARAMETER "Fill_type"
Endif

! прячем ненужные для круга параметры
if type="Круг" then
HIDEPARAMETER "remark_type" ,"listref", "snap_type", "sm_area", "sm_floor_type"
               if IsCustomText=0 Then

 ! - забираем для сметы
               PARAMETERS Sm_poz=atext
               else
               PARAMETERS Sm_poz=CustomText
               endif
              
               endif

Endif

! прячем ненужные для параллелограма параметры
if type="Параллелограм" then
HIDEPARAMETER "rad1s", "rad2s", "snap_type", "spsp"

if remark_type="Дополнение" or remark_type="Аннулировано" or remark_type="Просто измененный участок" Then
HIDEPARAMETER "ListRef"

! для участка типа "дополнение" число выносок ставим в ноль.
if remark_type="Дополнение" Then
PARAMETERS XC=0, nn=0
Endif

Endif

Endif

! прячем ненужные для треугольника параметры
if type="Треугольник" then
HIDEPARAMETER "remark_type" ,"listref", "sm_poz", "sm_oboz", "sm_naim", "sm_edizm", "sm_kolvo"
 ! - забираем для сметы
if IsCustomText=0 Then
               PARAMETERS Sm_floor_type=dtext
               else
               PARAMETERS Sm_floor_type=CustomText
               endif
              
               endif


Endif

 ! - задаем точность вычисления положения угловых АС
             
EPS = 0.0001

 ! - кратность угловых параметров в соответствии с разделом параметров "установки"
alfa = INT(360/pos_max)
beta = INT(360/izm_max)
gama = INT(360/pol_max)


! step x6 angle

!!! ---------- Text Selection Angle 1 ----------
 ! - если последним измененным параметром был sAng, то смотрим сколько градусов было выставлено, устанавливаем текущее положение углового АС, передаем текстовому параметру atext  "меру кратности", т.е номер позиции в маркере.

              if GLOB_MODPAR_NAME = "sAng" then
      for x=1 to pos_max
                               if abs (sAng-alfa* x) < EPS then
                                               PARAMETERS atext=str(x,1,0)
                               endif
                 next x

               endif
! таже петрушка для параллелограмма
!!! ---------- Text Selection Angle 2 ----------
               if GLOB_MODPAR_NAME = "rAng1" then
      for x=1 to izm_max
                               if abs (rAng1-beta* x) < EPS then
                                               parameters btext=str(x,1,0)
                               endif
                 next x
               endif

!!! ---------- Text Selection Angle 3 ----------
               if GLOB_MODPAR_NAME = "rAng2" then
      for x=1 to izm_max
                               if abs (rAng2-beta* x) < EPS then
                                               parameters ctext=str(x,1,0)
                               endif
                 next x
               endif
! таже петрушка для треугольника
!!! ---------- Text Selection Angle 4 ----------
               if GLOB_MODPAR_NAME = "dAng" then
      for x=1 to pol_max
                               if abs (dAng-gama* x) < EPS then
                                               parameters dtext=str(x,1,0)
                               endif
                 next x
               endif

!!! ---------- SCALING  ----------
! Масштабирование, отрисовка всех трех маркеров связана с заданными размерами, т.е. с параметрами rad1, rad2;  GLOB_SCALE  - глобальная переменная-константа, т.е. определена до начала интерпретации GDL-скрипта

               sc=GLOB_SCALE
               PARAMETERS RAD1=RAD1s*sc, RAD2=RAD2s*sc, FSC=FS/(1000)*sc


=======================================================================
=======================================================================
    4. 2D СКРИПТ
!/SABRUS 2012

! два текстовых стиля, "по центру"-для текста в маркере, с привязкой "слева" - для текстовок в параллелограме.

DEFINE STYLE "TST" F, FS,5,0
DEFINE STYLE "DST" F, FS,7,0
SET STYLE "TST"

! номера меток, на которые будем переходить после рисования общей части.
Krug=10
Parall=20
Triangle=30
Finish=40

!=================== штриховка,если нужна
IF isfill then
SET FILL Fill_type
endif


!=======точка центр, она же печъъка.


! АС-3(согласно скринам вначале), центр маркера X1,Y1.

HOTSPOT2 X1,0,3,Y1,1+128
HOTSPOT2 X1,-1,4,Y1,3
HOTSPOT2 X1,Y1,5,Y1,2

HOTSPOT2 0,Y1,6,X1,1+128
HOTSPOT2 -1,Y1,7,X1,3
HOTSPOT2 X1,Y1,8,X1,2


!=========дальше по типу выноски ============

UnID=15


!==Указательный камень ==============

if type="Круг" then goto Krug

if type="Параллелограм" then goto Parall

if type="Треугольник" then goto Triangle

!=============================================

10:
! Маркер "позиция детали"

!========текстовка ==============

pen pen3
if not(IsCustomText) then
text2 x1,y1, atext
else
text2 x1,y1, CustomText
Endif

!======== линии-выноски ==========

for x=1 to nn
! АС-2
HOTSPOT2 xc[x][1],       0,                            UnID+1,              xc[x][2],1+128
HOTSPOT2 xc[x][1],       -1,                          UnID+2, xc[x][2],3
HOTSPOT2 xc[x][1],       xc[x][2],UnID+3, xc[x][2],2

HOTSPOT2 0,                                    xc[x][2],              UnID+4,              xc[x][1],1+128
HOTSPOT2 -1,                   xc[x][2],              UnID+5,              xc[x][1],3
HOTSPOT2 xc[x][1],       xc[x][2],              UnID+6,              xc[x][1],2

!================================================================
! Смотрим в каких четвертях обретается конец данной линии-выноски

alpha=ATN((xc[x][2]-Y1)/(xc[x][1]-X1+0.0001))

dx=Rad1*COS(alpha)
dy=Rad1*SIN(alpha)

ch1=(XC[x][1]>X1)& (XC[x][2]>Y1)
ch2=(XC[x][1]<=X1)&(XC[x][2]>Y1)
ch3=(XC[x][1]<X1)& (XC[x][2]<=Y1)
ch4=(XC[x][1]>=X1)&(XC[x][2]<Y1)

if ch1 then
chx=1:chy=1
endif

if ch2 then
chx=-1:chy=-1
endif

if ch3 then
chx=-1:chy=-1
endif

if ch4 then
chx=1:chy=1
endif

pen pen4
! вот он отрезок заканчивающийся на контуре маркера
line2 x1+chx*dx,y1+chy*dy,xc[x][1],xc[x][2]

!================================================================
UnID=UnId+6

pen pen2
circle2 XC[x][1],XC[x][2], rad2



next x

!================================================================
!v1: Text Edit hotspot
! АС-1 угловой спот повешенный на параметр sAng
add2 x1,y1
               
!!! ---------- Selector ----------    
                uid = UnID+1
                hotspot2 0, 0, uid : uid = uid+1    ! centre
               
                xx = rad1*cos(sAng)
                yy = rad1*sin(sAng)

                hotspot2 0,         0, uid, sAng, 6         : uid = uid+1    ! centre
                hotspot2 rad1,   0, uid, sAng, 4+128     : uid = uid+1    ! base
                hotspot2 xx  ,  yy, uid, sAng, 5, atext  : uid = uid+1    ! moving

del 1
!=======================================

pen pen1
circle2 x1,y1,rad1

!======штрихуем
If IsFill then
! статус коды команды есть в руководстве по GDL, без них ничего не заштриховать.
POLY2_B 2,2, pen5, pen6,
                               x1,y1, 900,
                               Rad1, 360, 4000
endif
!йохоу, один есть.
Goto Finish


!============Выноска- параллелограм
20:

! эти строчки делают параллелограм "незеркальным"
IF SYMB_MIRRORED then
mul2 -1, 1
ENDIF
!========текстовка ==============
pen pen3
if not(IsCustomText) then
text2 x1,y1, btext+"."+ctext
else
text2 x1,y1, CustomText
Endif

!=======точка привязка линий-выносок, по углам параллелограма.

HOTSPOT2 X2,0, UnID+1,Y2,1+128                          : UnID=UnID+1
HOTSPOT2 X2,-1,UnID+1,Y2,3                                   : UnID=UnID+1
HOTSPOT2 X2,Y2,UnID+1,Y2,2                                  : UnID=UnID+1

HOTSPOT2 0,Y2, UnID+1,X2,1+128                          : UnID=UnID+1
HOTSPOT2 -1,Y2,UnID+1,X2,3                                   : UnID=UnID+1
HOTSPOT2 X2,Y2,UnID+1,X2,2                                  : UnID=UnID+1


!==============  разлиновка параллелограма

pen pen1
FSC=FS/(1000)*A_

LINE2 X1-BX*FSC,Y1-FSC,X1-AX*FSC,Y1+FSC
LINE2 X1-AX*FSC,Y1+FSC,X1+BX*FSC,Y1+FSC
LINE2 X1+BX*FSC,Y1+FSC,X1+AX*FSC,Y1-FSC
LINE2 X1+AX*FSC,Y1-FSC,X1-BX*FSC,Y1-FSC

!======штрихуем
If IsFill then
POLY2_B 4,6, pen5, pen6,
                               X1-BX*FSC,Y1-FSC,600,
                               X1-AX*FSC,Y1+FSC,0,
                               X1+BX*FSC,Y1+FSC,0,
                               X1+AX*FSC,Y1-FSC,0
                              

endif

! рисование текстов по ГОСТ

SET STYLE "DST"

if remark_type="См.лист" or remark_type="Взамен перечеркнутого на листе" then
pen pen3
text2 X1+BX*FSC,Y1-FSC,remark_type+" "+ListRef
pen pen4
line2 X1+AX*FSC,Y1-FSC,X1+(STW((remark_type)+"WWW"+ListRef)/1000*GLOB_SCALE), Y1-FSC
endif

if remark_type="Дополнение" or remark_type="Аннулировано" then
pen pen3
text2 X1+BX*FSC,Y1-FSC,remark_type+" "
pen pen4
line2 X1+AX*FSC,Y1-FSC,X1+(STW((remark_type)+"WWW")/1000*GLOB_SCALE), Y1-FSC
endif

!======== линии-выноски ==========

for x=1 to nn

HOTSPOT2 xc[x][1],       0,                            UnID+1,              xc[x][2],1+128
HOTSPOT2 xc[x][1],       -1,                          UnID+2, xc[x][2],3
HOTSPOT2 xc[x][1],       xc[x][2],UnID+3, xc[x][2],2

HOTSPOT2 0,                                    xc[x][2],              UnID+4,              xc[x][1],1+128
HOTSPOT2 -1,                   xc[x][2],              UnID+5,              xc[x][1],3
HOTSPOT2 xc[x][1],       xc[x][2],              UnID+6,              xc[x][1],2

pen pen4
line2 x2,y2,xc[x][1],xc[x][2]

!================================================================
UnID=UnId+6


next x

!================================================================
add2 x1,y1
! эти два угловых АС, ответственных за композитную строку: 
Номер изменения+"."+участок    
        
!!! ---------- Selector "Изменение" ----------     
                uid = UnID+1
                hotspot2 0, 0, uid : uid = uid+1    ! centre
               
                xx = rad1*cos(rAng1)                   
                yy = rad1*sin(rAng1)

                hotspot2 0,         0, uid, rAng1, 6         : uid = uid+1    ! centre
                hotspot2 rad1,   0, uid, rAng1, 4+128     : uid = uid+1    ! base
                hotspot2 xx  ,  yy, uid, rAng1, 5, btext  : uid = uid+1    ! moving

!!! ---------- Selector "Участок" ----------              
                uid = UnID+1
                hotspot2 0, 0, uid : uid = uid+1    ! centre
               
                xxx = 1.2*rad1*cos(rAng2)                       
                yyy = 1.2*rad1*sin(rAng2)

                hotspot2 0,         0, uid, rAng2, 6                : uid = uid+1    ! centre
                hotspot2 1.2*rad1,   0, uid, rAng2, 4+128   : uid = uid+1    ! base
                hotspot2 xxx  ,  yyy, uid, rAng2, 5, ctext  : uid = uid+1    ! moving
! удаляем не зеркальность
IF SYMB_MIRRORED then
del 1
ENDIF
! удаляем смещение add2 x1,y1
del 1

! второй маркер готов

Goto Finish


!============Выноска-треугольник
30:
! почему то закончить хотелось на треугольнике )
!========текстовка ==============

pen pen3
if not(IsCustomText) then
text2 x1,y1, dtext
else
text2 x1,y1, CustomText
Endif

!=======точка привязка линий-выносок, по углам треугольника.
If snap_type="К указанной вершине" then
HOTSPOT2 X3,0, UnID+1,Y3,1+128                          : UnID=UnID+1
HOTSPOT2 X3,-1,UnID+1,Y3,3                                   : UnID=UnID+1
HOTSPOT2 X3,Y3,UnID+1,Y3,2                                  : UnID=UnID+1

HOTSPOT2 0,Y3, UnID+1,X3,1+128                          : UnID=UnID+1
HOTSPOT2 -1,Y3,UnID+1,X3,3                                   : UnID=UnID+1
HOTSPOT2 X3,Y3,UnID+1,X3,2                                  : UnID=UnID+1
endif
!======== линии-выноски ==========
for x=1 to nn
HOTSPOT2 xc[x][1],       0,                            UnID+1,              xc[x][2],1+128
HOTSPOT2 xc[x][1],       -1,                          UnID+2, xc[x][2],3
HOTSPOT2 xc[x][1],       xc[x][2],UnID+3, xc[x][2],2

HOTSPOT2 0,                                    xc[x][2],              UnID+4,              xc[x][1],1+128
HOTSPOT2 -1,                   xc[x][2],              UnID+5,              xc[x][1],3
HOTSPOT2 xc[x][1],       xc[x][2],              UnID+6,              xc[x][1],2

!================================================================
! Оцениваем расстояния от конца линии выноски до вершин, извлекать корень не обязательно, найти ближайшую вершину можно и по оценке суммы квадратов.
rst1=(xc[x][1]-(x1-rad1*cos(30)))^2+(xc[x][2]-(y1-rad1*cos(60)))^2
rst2=(xc[x][1]-(x1+rad1*cos(30)))^2+(xc[x][2]-(y1-rad1*cos(60)))^2
rst3=(xc[x][1]-x1)^2+(xc[x][2]-(y1+rad1))^2

rst=min(rst1, rst2,rst3)

if RST=RST1 then
fx=x1-rad1*cos(30)
fy=y1-rad1*cos(60)
endif

if RST=RST2 then
fx=x1+rad1*cos(30)
fy=y1-rad1*cos(60)
endif

if RST=RST3 then
fx=x1
fy=y1+rad1
endif

pen pen4

If not(snap_type="К указанной вершине") then
line2 fx,fy,xc[x][1],xc[x][2]
else
line2 x3,y3,xc[x][1],xc[x][2]
endif

pen pen2
circle2 XC[x][1],XC[x][2], rad2

!================================================================
UnID=UnId+6

next x

!================================================================
!v1: Text Edit hotspot
add2 x1,y1         
!!! ---------- Selector ----------    
                uid = UnID+1
                hotspot2 0, 0, uid : uid = uid+1    ! centre            
                xx = rad1*cos(dAng)                    
                yy = rad1*sin(dAng)
                hotspot2 0,         0, uid, dAng, 6         : uid = uid+1    ! centre
                hotspot2 rad1,   0, uid, dAng, 4+128         : uid = uid+1    ! base
                hotspot2 xx  ,  yy, uid, dAng, 5, dtext  : uid = uid+1    ! moving
                pen pen1

! рисуем сам треугольник
 
                line2 0, rad1,-rad1*cos(30),-rad1*cos(60)
                line2 -rad1*cos(30),-rad1*cos(60),rad1*cos(30),-rad1*cos(60)
                line2  rad1*cos(30),-rad1*cos(60),0,rad1
                !======штрихуем
                If IsFill then
                POLY2_B 3,6, pen5, pen6,
                                                               0, rad1, 600,
                                                               -rad1*cos(30),-rad1*cos(60), 0,
                                                               rad1*cos(30),-rad1*cos(60),0

endif
!=======================================
del 1
Goto Finish
!===тпрруууу
40:
! Del 1
End

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

ИТАК, в данном объекте показаны следующие моменты:

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

if GLOB_MODPAR_NAME = "sAng" then
      for x=1 to pos_max
                               if abs (sAng-alfa* x) < EPS then
                                               PARAMETERS atext=MyStringEnumerationArray[x]
                               endif
       next x
 endif

здесь MyStringEnumerationArray[x] - массив значений, которые нужно перебирать при помощи АС.

2. Описание допустимых для 2D АС значений. Для треугольника и параллелограмма были описаны зависимости двух координат, такие что АС был вынужден попадать только в вершины контура. Такие условия должны описываться в скрипте параметров, в 2Д скрипте необходимо пользоваться уже готовыми, требуемыми по логике значениями координат, строк, углов, массивов и т.д. Попробуйте поставить комменты на синие части строки и посмотреть как поведут себя АС.

values "X2" X1-AX*FSC,X1+AX*FSC,X1-BX*FSC,X1+BX*FSC
IF (X2=X1-AX*FSC) or (X2=X1+BX*FSC) then
values "Y2" Y1+FSC
endif

IF (X2=X1+AX*FSC) or (X2=X1-BX*FSC) then
values "Y2" Y1-FSC
endif

Extended 2: чтобы сделать перебор активным спотом произвольного заданного набора точек, необходимо в цикле проверять расстояние от АС до каждой  точки набора, при заданной точности конечно, и менять координаты АС, только при попадании в "магнитную"(<E) область одной из точек. 

3. Самый важный пожалуй здесь момент - использование следующего синтаксиса:
    if GLOB_MODPAR_NAME = "sAng" then...
переменная GLOB_MODPAR_NAME - один из 3-х китов интерактивности GDL.
 Данная строка позволяет скрипту "откликаться" на действия пользователя как через меню    так и при редактировании на плане/в 3Д, посредством активных спотов, связанных с параметрами. GLOB_MODPAR_NAME - имя глобальной переменной, которая содержит имя последнего измененного пользователем параметра. Используя вышеуказанную строку GDL-скрипт позволяет писать по сути обработчики событий (в терминологии ООП). Используя связку из условий:

if GLOB_MODPAR_NAME = "имя_параметра" then...
 if имя_параметра=значение_1 then...
 endif

if имя_параметра=значение_2 then...
 endif


endif

реализуется практически любое поведение объекта, его логика. На этом принципе построены различные GDL-объекты, с интерактивной логической нагрузкой - игра-пятнашки, и др. 

4. Скрипт спецификаций. В данном объекте скрипт не разрабатывался, объект не представляет собой 3d объект, который можно осмечивать, не имеет компонентного состава(не состоит из других измеримых объектов - материалов, деталей). Но специфика объекта такова, что он должен как раз "закрывать" случай когда 3Д модель не будет построена(писал в INTRO п1.6.),
поэтому объект имеет параметры для правильного специфицирования с помощью ИК. Скрипт параметров при помощи условных выражений предоставит пользователю параметры ИК относящиеся только к выбранному типу маркера, таким образом, исключая возможность неправильного ввода:

! прячем ненужные для параллелограма параметры
if type="Параллелограм" then
HIDEPARAMETER "rad1s", "rad2s", "snap_type", "spsp"



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

На этом все, скачать архив этой статьи, демо-видео и сам объект(версия для AC16) можно здесь: http://arch-grafika.rusfolder.net/files/34554085


следующая GDL тема: 
 "О целесообразности написания своего объекта, и его проектировании", или есть другие предложения?

Комментарии

  1. К сожалению не удалось скачать по ссылке((

    ОтветитьУдалить
    Ответы
    1. ув. dimdiad,
      файлы размещены на файлообменном сервисе rusfolder, ссылка рабочая,
      для скачивания файла необходимо просмотреть в течение 30 секунд рекламу спонсоров, по одной из ссылок, это мой спортивный интерес(понять и простить). Возможно проблема в том что у вас запрещены всплывающие окна.
      Если это не решит проблему, советую погуглить по: не могу скачать с русфолдер...

      Удалить
    2. http://arch-grafika.rusfolder.net/files/faq

      Удалить
  2. Несмотря на размер поста и позднее время суток всё же осилил. Интересный момент с графическим редактированием массива MyStringEnumerationArray[x]. Буду пробовать. Хотелось бы отработать простой универсальный макрос с функцией селектора:
    -ввод>массив значений
    -вывод>выбранное значение

    Спасибо за детальное изложение.Вижу, что Вы хотели чуть разбавить текст `неофициальными`
    комментами, но всё же пойду чуть отойду с кофе на кухне)))

    ОтветитьУдалить
  3. Оч.классный объект в смысле уровня. Еще раз спасибо.

    ОтветитьУдалить
    Ответы
    1. Спасибо. Остался еще один момент описанный в Extended2, если не забуду в одном из след. постов напишу его реализацию.

      Удалить
  4. Привет, у меня есть вопросы по GDL.
    как можно с Вами связаться?
    напишите мне пжлста письмо
    moitilifon собака gmail.c0m
    буду очень признателен.

    ОтветитьУдалить

Отправить комментарий

Популярные сообщения из этого блога

GDL. Объект для моделей из "оцилиндрованного бревна"

График функции в полярных координатах?! Легко!