Link

GDL

GDL, die Geometric Description Language, ist eine BASIC-ähliche Programmiersprache und wird in Archicad verwendet um die Elemente der Bibliothek zu erstellen.

Die wichtigsten Ressourcen für das Erlernen und den Umgang sind SelfGDL und Graphisofts GDL center. Unter Hilfe > Handbücher befindet sich auch das GDL Referenzhandbuch als PDF für die jeweilige Archicadversion.
Ein Klassiker der GDL Literatur ist David Nichelson-Coles GDL Cookbook und Object Making with ArchiCAD – GDL for Beginners, welche beide jedoch schon älteren Datums sind. Die meisten Grundlagen haben sich allerdings nicht geändert; daher sind diese Bücher immer noch empfehlenswert. Neueren Datums ist das GDL Handbook – A Comprehensive Guide von Andrew Watson (ursprünglich zu beziehen bei Cadimage, mittlerweile in Central Innovation, der Reseller in Australien/Neuseeland, aufgegangen).

Da das Programmieren im GDL Editor selbst recht mühsam ist, und moderne Annehmlichkeiten vermissen lässt, haben sich Alternativen etabliert:


Ausgewähle Tricks

Schnelle Ergebnisse

Wenn das Überlegen und händische Scripten einer Form zu anstrengend und langwierig ist, und besonders, wenn keine Parametrik vonnöten ist, so ist folgendes eine geeignete Alternative: Dabei wird die Form mithilfe einer Polylinie am oder um den Ursprung gezeichnet, und dann als Objekt abgespeichert. (Es ist auch möglich Elemente aus dem Grundriss/3D-Fenster in das jeweilige Skriptfenster zu ziehen. Dazu müssen die Tabs aber abgedockt werden.)
Dadurch schreibt uns Archicad automatisch ein poly2_b{5}. Das ist von der Logik in den meisten Fällen gar nicht vonnöten – der Autor selbst wandelt die Kommando noch in ein normales poly2_b um. Wichtig sind ohnehin die Koordinaten, und diese lassen sich sehr einfach auch für die gängigen prism Befehle im 3D nutzen! Zu beachten ist dort dann jedoch noch das Setzen der richtigen Flags.

Relevantes Geschoss korrekt

Um eine korrekte Anzeige bei In relevanten Geschossen anzeigen zu erhalten, müssen die Parameter ac_bottomlevel und ac_toplevel logisch belegt sein (Das obere Level kann nicht unter dem unteren liegen).

! parameter script
bottom = GLOB_HSTORY_ELEV + GLOB_ELEVATION
parameters ac_bottomlevel = bottom
parameters ac_toplevel = bottom + ZZYZX

Schriftartauswahl

Für eine automatische Auswahlliste aller auf dem System installieren Schriftarten in den Objekt-Einstellungen. Dabei ist in diesem Beispiel ein Textparameter namens myFontFace anzulegen (kann beliebig benannt werden).

! param script
dim fontNames[]
n = request("FONTNAMES_LIST", "", fontNames)
values "myFontFace" fontNames, CUSTOM

Relative Abhängigkeit von Parametern

Manchmal kommt es vor, dass man Parameter in Relation zueinander setzen muss: Wenn Basis doppelt so groß ist, soll Rel_Param auch doppelt so groß sein (Beispiel). Dazu braucht es lediglich einen neuen Parameter Basis_alt, der den vorherigen Wert von Basis speichert. Das kann über GLOB_MODPAR_NAME realisiert werden.

!'--- param script ---'!
if GLOB_MODPAR_NAME = "Basis" then
	rr = Basis / Basis_alt
	Rel_Param = Rel_Param * rr
	Basis_alt = Basis
endif

parameters  Rel_Param = Rel_Param,
			Basis_alt = Basis_alt

Präzision

Aufgrund der Natur von Floating Point Berechnungen kann es passieren, dass der Vergleich von 2 reellen Zahlen nicht das Ergebnis gibt, was man erwartet hätte. Sobald man folgendes im GDL versucht if reell_a = reell_b …, bekommt man eine scharfe Mahnung zurückgeliefert.
Das dient allerdings lediglich als Hinweis, dass man sich mit so einem Konstrukt auf dünnem Eis bewegt. Um Fehler zu vermeiden, sollte man stattdessen die zu vergleichenden Zahlen von einander subtrahieren und dann prüfen, ob dieses Ergebnis größer ist, als ein zuvor definiertes Epsilon, quasi eine Toleranz.
Das Epsilon findet sich häufig als eps = 0.0001 im GDL Code, z.B. von den mitgelieferten Objekten.
Ein besonders detailliertes Konstrukt wäre z.B.:

dict EPS
EPS.length	= 0.0001				!' 1/10 mm
EPS.square	= EPS.length**2
EPS.scalar	= EPS.square
EPS.angle 	= acs(1 - EPS.scalar)	!' 0.0081°

! Ein Vergleich wäre dann:
if abs(real_a - real_b) < EPS.length then [...] 

Werte aus einem Array löschen

Es gibt leider keine Möglichkeit nativ Werte zu popen, aber mit einem bisschen Geschiebe ist auch das möglich:

dim arr[]
!' init w/ some values
arr[1] = 0.1
arr[2] = 0.2
arr[3] = 0.3

!' the item index you want to delete
todelete = 2

dim new_arr[]
check = 0
for i = 1 to vardim1(arr)-1
	if i = todelete then check = 1
	new_arr[i] = arr[i+check]
next i

arr = new_arr

print arr   !' prints:  0.1  0.3

Etikettplatzierung

Um ein Etikett da zu platzieren, wo der User geklickt hat:

if not(LABEL_HAS_POINTER) then
	add2  LABEL_POSITION [2][1]	+ LABEL_POSITION [3][1],
		  LABEL_POSITION [2][2]	+ LABEL_POSITION [3][2]
endif

Text in Umfassungsbox

Natürlich ließe sich dafür richtext2 verwenden, aber hiermit kommt man auch zum Ziel:

! Bounding-Box
line2 0, 0,  0, B
line2 0, 0,  A, 0
line2 A, B,  0, B
line2 A, 0,  A, B

mst = 1/1000 * GLOB_SCALE 	! Zeichnungsmaßstab

font_size = 5
font = "Arial"
txt_display = "Ein bisschen Text"

gosub "getStyle"    ! definiert einen passenden Textstil

text2 a/2, b/2, txt_display

END !--- END --- END --- END --- END --- END ---!

!-----------------------------------------------!
"getStyle":
    ! Dummystil definieren
    define style "dummy" font, A*mst, font_size, 0
    style "dummy"

    width_A = stw(txt_display)  ! Textbreite mit Dummystil ermitteln
    ratio_A = A/width_A 	    ! Verhältnis von Dummy-Textbreite zu A
    
    define style "dummyA" font, A*ratio_A, font_size, 0
    style "dummyA"
    r = request("Height_of_style", "dummyA", text_height)
    text_height = text_height * mst
    
    if text_height > B then
        ratio_B = text_height / B
        define style "dummyB" font, A*ratio_A/ratio_B, font_size, 0
        style "dummyB"
    endif
return

Strichlinien in 3D

Zwar kann man auch Linien im 3D zeichnen, allerdings stehen dafür keine verschiedenen Linienarten wie im 2D zur Verfügung.

! 3D script

!convert paper lengths to model
dashLen = dashLen * GLOB_SCALE
gapLen = gapLen * GLOB_SCALE

dashStart = 0   ! where the first dash starts
dashQ = 0       ! counter for dashes
flag = 0        ! stopper for while loop


! count dashes
while flag = 0 do
	! add a dash to the count
	dashQ = dashQ + 1
	! advance to the next dash start
	dashStart = dashStart + dashLen + gapLen
	! if that's beyond the end, stop
	if dashStart > lineLen then flag = 1
endwhile

! start of final dash
dashStart = dashStart - dashLen - gapLen

! is the last dash trimmed by the end of the object
if dashStart + dashLen > lineLen then
	bTrimDash = 1
	trimLen = lineLen - dashStart   ! special length for last dash
else
	bTrimDash = 0   ! object ends with gap, no special dash
endif

! normal dashes, omit last if trimmed
for k = 1 to dashQ - bTrimDash
	lin_ 0, 0, 0,  dashLen, 0, 0
		addx dashLen + gapLen
next k

! special trimmed last dash if needed
if bTrimDash then lin_ 0, 0, 0,  trimLen, 0, 0
	del dashQ - bTrimDash

Built-in Parameter

Um z.B. den Umbaustatus eines Objekts zu erfragen, verwendet man n = APPLICATION_QUERY ("OwnCustomParameters", "GetParameter(Renovation.RenovationStatus)", parValue).
parValue hält nun den Status als lokalisierten (!) String.

Alle eingebauten Parameter: (Ausgabe im 2D)

DIM folderNamesArray[]
n = APPLICATION_QUERY ("OwnCustomParameters", "GetParameterFolderNames()", folderNamesArray)

for i = 1 to vardim1(folderNamesArray) step 3

    DIM parNamesArray[]
    querystring = "GetParameterNames(" + folderNamesArray[i] + ")"
    n = APPLICATION_QUERY ("OwnCustomParameters", querystring, parNamesArray)
    text2 0, 0, querystring
    add2 1, -1

    _nLines = 1
    for j = 1 to vardim1(parNamesArray) step 3

        parValue = ""
        querystring = "GetParameter(" + parNamesArray[j] + ")"
        n = APPLICATION_QUERY ("OwnCustomParameters", querystring, parValue)
        text2 0, 0, querystring + ": " + parValue
        add2 0, -1
        _nLines = _nLines + 1

    next j

    del _nLines
    add2 0, -_nLines

next i