Рано или поздно появляется необходимость во всевозможных структурах хранения объектов – списках и т.п. Все те немногочисленные статьи, что до сегодняшнего момента мне попадались. Сводились к подключению сторонних библиотек. На мой же взгляд решение гораздо проще и всё это время, буквально лежало перед глазами. Адекватный перегружаемый интерфейс класса-контейнера с иерархической структурой предоставляет нам трёхмерная квази-модель полностью построенная на пивотах. Сама работа с контейнером сводится в таком случае к командам:
Для организации структуры и работы с ней -
- CreatePivot ( [parent] )
- FreeEntity EntityHandle
- EntityParent entity,parent[,global]
- GetParent ( entity )
- CountChildren ( entity )
- GetChild (entity,index)
Для доступа к информационным полям элемента структуры -
- NameEntity entity,name$
- EntityName$ ( entity )
- Object
- Handle
Прочие команды.
Рассмотрим пример создания древа. Пример весьма «корявый», но богатый на применение различных функций работы со структурой.
Graphics3D 800,600,32
SetBuffer BackBuffer()
Local root=CreatePivot()
NameEntity root,"директор"
For i=1 To 3
NameEntity CreatePivot(root),"руководитель"+Str(i)
For j=1 To Rand(1,4)
NameEntity CreatePivot(FindChild(root,"руководитель"+Str(i))),"работник"+Str(j)
Next
Next
Local a
Local b
Print EntityName(root)
For i=1 To CountChildren(root)
a=GetChild(root,i)
Print "->"+EntityName(a)
For j=1 To CountChildren(a)
b=GetChild(a,j)
Print "-->"+EntityName(b)
Next
Next
WaitKey()
End
Как дополнительные внутренние поля элементов структуры вы можете использовать иные типовые характеристики Entity: позицию по 3 координатам (3 х 4 байта) и углы вращения (3 переменных со значением от -180 до 180 [весьма проблематичным может оказаться автоматическая коррекция границы]). Их удобно использовать для предварительной идентификации листка древа.
Саму же работу со структурой легко реализовать при помощи рекурсивных функций, что упростит работу с ними и повысит наглядность.
Вот как это может выглядеть:
Graphics3D 800,600,32
SetBuffer BackBuffer()
Local a
Local b
Local root=CreatePivot()
NameEntity root,"директор"
PositionEntity root,24*5,24*5*500,0
For i=1 To 3
a=CreatePivot(root)
NameEntity a,"руководитель"+Str(i)
PositionEntity a,24*Rnd(6,8),24*Rnd(6,8)*200,0
For j=1 To Rand(1,4)
b=CreatePivot(a)
NameEntity b,"работник"+Str(j)
PositionEntity b,24*Rnd(8,12),24*Rnd(8,12)*100,0
Next
Next
Function W(r%,prefix$)
Print prefix$+EntityName(r)
Print prefix$+" часов работы "+EntityX(r)+"; зарплата "+EntityY(r)
Print ""
prefix$=prefix$+"-"
For i=1 To CountChildren(r)
W(GetChild(r,i),prefix)
Next
End Function
W(root,"")
WaitKey()
End
Для хранения структур вы можете воспользоваться командами Object\Handle – сохраняя\загружая квази-адрес структуры в поле имени пивота.
Минусов подобной организации я нашёл только два:
Необходимость инициализации 3D-режима графики. Это, в общем-то, не так болезненно (никто вас не принуждает создавать камеры и рендерить сцену). Кроме того уже само название среды – Blitz3D – подразумевает, что вы пишете программу работы с 3х-мерной графикой, таким образом – для большинства программ применение таких структур не меняет режим графики.
Дополнительные расходы на память. Что есть – то есть. Однако подумайте об удобстве, которое вы на мой взгляд получаете.