13.01.2015 Aufrufe

Bauinformatik Teil 1 - Baustatik-Info-Server

Bauinformatik Teil 1 - Baustatik-Info-Server

Bauinformatik Teil 1 - Baustatik-Info-Server

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

<strong>Bauinformatik</strong> <strong>Teil</strong> 1<br />

Übungsskript<br />

2011<br />

Universität Duisburg-Essen<br />

Fakultät für Ingenieurwissenschaften<br />

Abteilung Bauwissenschaften<br />

Institut für <strong>Baustatik</strong><br />

Dr. E. Baeck<br />

19.10.2011


INHALTSVERZEICHNIS<br />

Seite iii<br />

Inhaltsverzeichnis<br />

1 Arbeiten mit EXCEL 2<br />

1.1 Bezüge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2<br />

1.2 Fehlermeldungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2<br />

1.3 EXCEL-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3<br />

1.3.1 SUMME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3<br />

1.3.2 ABS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3<br />

1.3.3 MAX, MIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3<br />

1.3.4 WENN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3<br />

1.3.5 SVERWEIS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4<br />

1.4 Aufgabe 1: Summe, Extremwerte und Absolutbetrag . . . . . . . . . . . . . . . 4<br />

1.5 Aufgabe 2: Nachweis eines statisch unbestimmten Trägers . . . . . . . . . . . . 5<br />

2 Zahlensysteme 7<br />

2.1 Motivation und Anwendung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />

2.2 Beispiele zur Konvertierung zwischen Zahlensystemen . . . . . . . . . . . . . . . 8<br />

2.3 Darstellung negativer Zahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />

3 Die VBA-IDE 11<br />

3.1 Oberfläche und Projektbrowser . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11<br />

3.2 Testen eines Programms, Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />

4 VBA-Interface 14<br />

4.1 Beispiel 1 in 6 Schritten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14<br />

4.1.1 Schritt 1: Gestaltung der Oberfläche . . . . . . . . . . . . . . . . . . . . . 14<br />

4.1.2 Schritt 2: Gestaltung der Steuerelemente . . . . . . . . . . . . . . . . . . . 15<br />

4.1.3 Schritt 3: Generieren eines Moduls für Funktion Summe . . . . . . . . . . 16<br />

4.1.4 Schritt 4: Das Programm Summe . . . . . . . . . . . . . . . . . . . . . . . 16<br />

4.1.5 Schritt 5: Programmtests . . . . . . . . . . . . . . . . . . . . . . . . . . . 17<br />

4.1.6 Schritt 6: Das Ziel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18<br />

5 Elementare Algorithmen 19<br />

5.1 Fakultät . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />

5.2 Binomialkoeffizient . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />

5.3 Winkel zwischen 2 Vektoren des R n . . . . . . . . . . . . . . . . . . . . . . . . . 20<br />

5.3.1 Pseudocode für Hauptprogramm . . . . . . . . . . . . . . . . . . . . . . . 20<br />

5.3.2 Pseudocode für Funktion SP rod . . . . . . . . . . . . . . . . . . . . . . . 20<br />

5.4 Reihenentwicklungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />

5.4.1 Entwicklung der Funktion sinus . . . . . . . . . . . . . . . . . . . . . . . 21<br />

5.4.2 Reihenentwicklung weiterer Funktionen . . . . . . . . . . . . . . . . . . . 22<br />

5.5 Newton-Verfahren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22<br />

5.5.1 Der Algorithmus des 1-dimensionalen Falls . . . . . . . . . . . . . . . . . 22<br />

5.5.2 Pseudo-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23<br />

19.10.2011


Seite iv <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

5.5.3 Programmablaufplan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23<br />

5.5.4 Nassi-Schneidermann-Diagramm . . . . . . . . . . . . . . . . . . . . . . . 24<br />

5.5.5 Die Oberfläche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24<br />

5.5.6 Animation des Verfahrens . . . . . . . . . . . . . . . . . . . . . . . . . . . 25<br />

6 Elementare Sortiert-Algorithmen 26<br />

6.1 Select-Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26<br />

6.2 Bubble-Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27<br />

7 Arbeiten mit Dateien 28<br />

7.1 Dateioperationen für sequentiellen Zugriff . . . . . . . . . . . . . . . . . . . . . . 28<br />

7.2 Torsionsträgeheitsmoments nach 2. Brendt’scher Formel . . . . . . . . . . . . . . 29<br />

8 Das Clapeyron-Problem 30<br />

8.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30<br />

8.2 Oberflächenlayout und Eingabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30<br />

8.2.1 Feldbeschreibung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31<br />

8.2.2 Lastbeschreibung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31<br />

8.3 ER-Modell der Datenstruktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32<br />

8.3.1 ER-Modell der Struktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32<br />

8.3.2 ER-Modell der Belastung . . . . . . . . . . . . . . . . . . . . . . . . . . . 33<br />

8.4 Aufbau der Datenstruktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34<br />

8.4.1 Die Datenstruktur des Systems . . . . . . . . . . . . . . . . . . . . . . . . 34<br />

8.4.2 Die Datenstruktur der Belastungen . . . . . . . . . . . . . . . . . . . . . . 35<br />

8.5 Aufbau des Linearen Gleichungssystems . . . . . . . . . . . . . . . . . . . . . . . 37<br />

8.5.1 Aufbau der Koeffizientenmatrix . . . . . . . . . . . . . . . . . . . . . . . . 37<br />

8.5.2 Aufbau der Lastvektoren . . . . . . . . . . . . . . . . . . . . . . . . . . . 38<br />

9 VBA-Objekte 40<br />

9.1 Konstruktor und Destruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40<br />

9.2 Vektoren und Matrizen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41<br />

9.2.1 Methoden des Klassenmoduls Vektor . . . . . . . . . . . . . . . . . . . . . 41<br />

9.2.2 Methoden des Klassenmoduls Matrix . . . . . . . . . . . . . . . . . . . . . 41<br />

9.3 Die Containerklasse Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42<br />

9.4 Datenstruktur eines Stabwerks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44<br />

9.4.1 Die Oberfläche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45<br />

9.4.2 Methoden des Punktes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45<br />

9.4.3 Methoden des Stabes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45<br />

9.5 2-fach verkettete lineare Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46<br />

9.5.1 Beispiel einer 2-fach verketten Liste . . . . . . . . . . . . . . . . . . . . . 47<br />

9.5.2 Einfügen eines Datenknotens . . . . . . . . . . . . . . . . . . . . . . . . . 47<br />

9.5.3 Entfernen eines Datenknotens . . . . . . . . . . . . . . . . . . . . . . . . . 47<br />

9.5.4 Iteratoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48<br />

10 Rekursive Algorithmen 49<br />

10.1 Quick-Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49<br />

E. Baeck


INHALTSVERZEICHNIS<br />

Seite v<br />

A Dreimomentengleichung, Clapeyron 51<br />

A.1 Das Verfahren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51<br />

A.2 Herleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51<br />

B Das ER-Modell 54<br />

C UML-Aspekte 55<br />

D Gauß’scher Algorithmus und Cholesky-Zerlegung 56<br />

D.1 Der Gauß’sche Algorithmus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56<br />

D.2 Interpretation des Gauß’schen Algorithmuses als Dreieckszerlegung . . . . . . . . 58<br />

D.3 Die Cholesky-Zerlegung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60<br />

D.4 Pseudocode für Cholesky-Zerlegung . . . . . . . . . . . . . . . . . . . . . . . . . . 62<br />

D.4.1 Pseudocode der Zerlegung . . . . . . . . . . . . . . . . . . . . . . . . . . . 62<br />

D.4.2 Pseudocode des Vorwärtseinsetzens . . . . . . . . . . . . . . . . . . . . . . 62<br />

D.4.3 Pseudocode des Rückwärtseinsetzens . . . . . . . . . . . . . . . . . . . . . 62<br />

D.5 VBA-Code des Gleichungslösers nach Cholesky . . . . . . . . . . . . . . . . . . . 63<br />

D.5.1 VBA-Code der Cholesky-Zerlegung . . . . . . . . . . . . . . . . . . . . . . 63<br />

D.5.2 VBA-Code des Vorwärtseinsetzens . . . . . . . . . . . . . . . . . . . . . . 64<br />

D.5.3 VBA-Code des Rückwärtseinsetzens . . . . . . . . . . . . . . . . . . . . . 64<br />

E Lösungen zum Abschnitt Elementare Algorithmen 65<br />

E.1 Summe aller Zahlen aus vorgegebenem Intervall . . . . . . . . . . . . . . . . . . . 65<br />

E.2 Berechnung der Fakultät . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66<br />

E.3 Berechnung des Binomialkoeffizienten . . . . . . . . . . . . . . . . . . . . . . . . 67<br />

E.4 Beispiel 4: Winkel zwischen 2 Vektoren im R n . . . . . . . . . . . . . . . . . . . . 68<br />

E.5 Lösung der sinus-Entwicklung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70<br />

E.6 Implementierung des Newton-Verfahrens . . . . . . . . . . . . . . . . . . . . . . . 72<br />

F Lösungen zum Clapeyron-Problem 74<br />

F.1 Aufgabe 8.3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74<br />

F.2 Aufgabe 8.3.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75<br />

F.3 Einlesen der Systemdaten und Aufbau des Datenmodell . . . . . . . . . . . . . . 76<br />

F.4 Einlesen der Belastungsdaten und Aufbau des Datenmodell . . . . . . . . . . . . 77<br />

F.4.1 Aufbau des Lastfall-Indexvektors . . . . . . . . . . . . . . . . . . . . . . . 77<br />

F.4.2 Aufbau des Lastfall-Containers . . . . . . . . . . . . . . . . . . . . . . . . 79<br />

F.4.3 Aufbau der Koeffizientenmatrix . . . . . . . . . . . . . . . . . . . . . . . . 81<br />

F.4.4 Lesen einer kompakt gespeicherten Bandmatrix . . . . . . . . . . . . . . . 82<br />

F.4.5 Das Hauptprogramm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83<br />

G Lösungen zum Abschnitt Vektor- und Matrixobjekte 84<br />

G.1 Deklaration eines Vektor-Klassenmoduls . . . . . . . . . . . . . . . . . . . . . . . 84<br />

G.2 Deklaration eines Matrix-Klassenmoduls . . . . . . . . . . . . . . . . . . . . . . . 86<br />

G.3 Programm Vektor 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88<br />

G.4 Programm Vektor Drehen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89<br />

H Lösungen zum Abschnitt Rahmen und Collection 90<br />

19.10.2011


INHALTSVERZEICHNIS Seite 1<br />

H.1 Deklaration des Stab-Klassenmoduls . . . . . . . . . . . . . . . . . . . . . . . . . 90<br />

H.2 Deklaration des Knoten-Klassenmoduls . . . . . . . . . . . . . . . . . . . . . . . 90<br />

H.3 Implementierung des Anwendungsprogramms . . . . . . . . . . . . . . . . . . . . 91<br />

H.3.1 Die Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91<br />

H.3.2 Die Funktion Einlesen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91<br />

H.3.3 Die Funktion Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93<br />

H.3.4 Die Funktion Verschieben . . . . . . . . . . . . . . . . . . . . . . . . . . . 94<br />

H.3.5 Die Funktion StabAnzahl . . . . . . . . . . . . . . . . . . . . . . . . . . . 94<br />

H.3.6 Die Ereignisfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94<br />

I Lösungen zum Abschnitt 2-fach verkettete Listen 96<br />

I.1 Deklaration des VNode-Klassenmoduls . . . . . . . . . . . . . . . . . . . . . . . . 96<br />

I.2 Deklaration des VListe-Klassenmoduls . . . . . . . . . . . . . . . . . . . . . . . . 96<br />

I.2.1 Daten am Listenkopf einfügen . . . . . . . . . . . . . . . . . . . . . . . . . 97<br />

I.2.2 Daten am Listenende einfügen . . . . . . . . . . . . . . . . . . . . . . . . 97<br />

I.2.3 Vorwärtsiterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98<br />

I.2.4 Einfügen eines Knotens . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99<br />

J Lösungen zu Sortieralgorithmen 100<br />

J.1 Die Ereignisfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101<br />

J.2 Generierung der Zufallszahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101<br />

J.3 Sortieralgorithmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103<br />

J.3.1 Implementierung von SelectSort . . . . . . . . . . . . . . . . . . . . . . . 103<br />

J.3.2 Implementierung von BubbleSort . . . . . . . . . . . . . . . . . . . . . . . 104<br />

J.3.3 Implementierung von QuickSort . . . . . . . . . . . . . . . . . . . . . . . 105<br />

K Lösung zur Brendt’schen Formel 107<br />

K.1 Die Ereignisfunktion zur Festlegung des Dateinamens . . . . . . . . . . . . . . . . 107<br />

K.2 Die Ereignisfunktion zu Datenimport und Berechnung . . . . . . . . . . . . . . . 107<br />

K.3 Die Datenstruktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108<br />

K.4 Einlesen der Daten aus der Profil-Textdatei . . . . . . . . . . . . . . . . . . . . . 108<br />

K.5 Hilfsfunktionen der Berechnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110<br />

K.5.1 Berechnung der mittlerern Blechdicke . . . . . . . . . . . . . . . . . . . . 110<br />

K.5.2 Berechnung des Knotenabstandes . . . . . . . . . . . . . . . . . . . . . . . 110<br />

K.5.3 Berechnung der Polygonfläche . . . . . . . . . . . . . . . . . . . . . . . . . 111<br />

19.10.2011


Seite 2 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

1 Arbeiten mit EXCEL<br />

1.1 Bezüge<br />

Die Adressierung der EXCEL-Tabellenfelder (Bezüge) erfolgt über relative und absolute Bezüge<br />

bzw. über Namen (Bezeichnung eines Bezuges).<br />

• Indizierung<br />

B3<br />

Z3S2<br />

Standardindizierung von Spalte und Zeile<br />

B:⇒ Spalte 2<br />

3:⇒ Zeile 3<br />

Z1S1 -Indizierung von Spalte und Zeile<br />

S2:⇒ Spalte 2<br />

Z3:⇒ Zeile 3<br />

• Relative Bezüge<br />

Beim Kopieren wird auf relative Bezüge die Verschiebung aufaddiert.<br />

Verschiebung 4 Spalten und 3 Zeilen: B3<br />

Z3S2<br />

⇒ F6<br />

⇒ Z(-3)S(-4)<br />

• Absolute Bezüge<br />

$B3 Beim Kopieren wird der Spaltenbezug erhalten.<br />

$B$3<br />

Beim Kopieren wird der Spalten- und Zeilenbezug erhalten.<br />

• Namen<br />

Ein Name ist gleichbedeutende mit einem absoluten Bezug auf ein oder mehrere Tabellenfelder.<br />

1.2 Fehlermeldungen<br />

Fehler Beispiel Beschreibung<br />

### Die Zelle ist für die vorgegebene Ausgabe zu schmal.<br />

#WERT! =Abs(A3:A5) Unzulässiger Funktionswert.<br />

#DIV!<br />

=A2/A3, bei A3=0 Nulldivision.<br />

#NAME =NoName Bezeichnung eines Bezugs oder einer Funktion ist unbekannt.<br />

#ZAHL! =Exp(1000) Zahlendarstellung nicht möglich. Überlauf.<br />

#NV! =SVerweis(...) Gesuchter Wert nicht verfügbar. Verweisfehler.<br />

#BEZUG! =Z(-3)S(-4)<br />

Der Bezug liegt außerhalb des zulässigen Bereichs, d.h. außerhalb der<br />

Tabelle.<br />

E. Baeck


1. ARBEITEN MIT EXCEL Seite 3<br />

1.3 EXCEL-Funktionen<br />

Nachfolgend werden die EXCEL-Funktionen zusammengestellt, die zur Bearbeitung der Übungsbeispiele<br />

herangezogen werden sollten.<br />

1.3.1 SUMME<br />

Summe berechnet die Summe der Zellenwerte eines Bezugs.<br />

Beispiel:<br />

=Summe(A3:G3)<br />

1.3.2 ABS<br />

ABS berechnet den Absolutbetrag eines Zellenwerts.<br />

Beispiel:<br />

=Abs(A3)<br />

1.3.3 MAX, MIN<br />

MAX bzw. MIN ermittelt den maximalen bzw. minimalen Wert innerhalb eines Bezugs.<br />

Beispiel:<br />

=Max(A3:G3)<br />

=Min(A3:G3)<br />

1.3.4 WENN<br />

Mit der Funktion WENN wird in<br />

Abhängigkeit eines boolschen Ausdrucks<br />

ein DANN -Wert oder ein<br />

SONST -Wert zugewiesen.<br />

Beispiel:<br />

=WENN(D13


Seite 4 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

1.3.5 SVERWEIS<br />

Mit der Matrix-Suchfunktion SVER-<br />

WEIS lassen sich Daten aus Datenbanken,<br />

d.h. aus Bezügen in beliebigen<br />

Tabellen, unter Vorgabe eines Suchbegriffs<br />

extrahieren.<br />

Beispiel:<br />

=SVerweis(E3;A3:C5;2;FALSCH)<br />

Abbildung 2: SVERWEIS-Funktion<br />

Parameter Beschreibung<br />

S T<br />

M D<br />

N S<br />

Suchwert: Text, Zahl oder Wahrheitswert.<br />

Datenmatrix. Ein Bezug in einer beliebigen Tabelle.<br />

Spaltenindex der gewünschten Datenspalte.<br />

(Spalte 1 ist Suchspalte).<br />

K S<br />

Sortierkenner: Wahr ⇒ sortiert, Falsch ⇒ unsortiert.<br />

1.4 Aufgabe 1: Summe, Extremwerte und Absolutbetrag<br />

In einem Bezug A1:D5 werden beliebige Zahlen eingetragen. Es sind die folgenden Größen zu<br />

ermitteln (siehe Abbildung 3):<br />

• Die Spalten- und Zeilensummen sowie die Gesamtsumme.<br />

• Maximaler und Minimaler Wert.<br />

• Maximaler Absolutwert.<br />

• Mit einer WENN-Funktion soll ausgegeben werden ob nur negative, nur positive oder<br />

negative und positive Werte gefunden wurden.<br />

Abbildung 3: Auswertung eines Bereichs<br />

E. Baeck


1. ARBEITEN MIT EXCEL Seite 5<br />

1.5 Aufgabe 2: Nachweis eines statisch unbestimmten Trägers<br />

Die Datenfelder sind in Formeln jeweils mit Namen anzusprechen 1<br />

Ein statisch unbestimmter Träger (siehe Abbildung 4) ist für vorgegebene Trägerlänge l und<br />

Steckenlast q für vorgegebenes Material (Stahltabelle) und Profil (Profiltabelle) nachzuweisen.<br />

Der E-Modul E der Stahlsorte sowie das Widerstandsmoment W sind aus einer Tabelle mittels<br />

der Suchfunktion SVERWEIS zu ermitteln (siehe Abbildung 5).<br />

Es ist zunächst zu berechnen, die Gesamtlast P , die beidseitigen Auflagerkräfte A = 3/8 ∗ P<br />

bzw. B = 5/8 ∗ P , das Einspannmoment M B = −1/8 ∗ P ∗ l und die Biegespannung am Lager B<br />

σ = M B /W . Die Eingabefelder der Tabelle sind als solche entsprechend zu kennzeichnen (siehe<br />

Abbildung 4).<br />

Achten Sie auch auf die Anpassung der unterschiedlichen Dimensionen.<br />

Abbildung 4: Nachweis eines statisch unbestimmten Trägers<br />

1 Namen können im Untermenü Einfügen/Namen eingefügt und bearbeitet werden.<br />

19.10.2011


Seite 6 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

Die Datenbanken für Material und Profile sollten in einer zweiten EXCEL-Tabelle der Mappe<br />

angelegt werden.<br />

Abbildung 5: Material- und Querschnittswerte in einer Datenbank<br />

In einem weiteren Schritt ist die Durchbiegung des Trägers y = P ∗x∗(l3 −3∗l∗x 2 +2∗x 3 )<br />

48∗E∗I∗l<br />

in Abhängigkeit<br />

der Längskoordinate x zu ermitteln und mit dem Diagrammassistenten darzustellen. Als<br />

Diagrammtyp ist der Typ Punkt(XY) auszuwählen. Die Balkenlängsrichtung liegt in X-Richtung,<br />

die Durchbiegung in negative Y-Richtung (Faktor -1).<br />

E. Baeck


2. ZAHLENSYSTEME Seite 7<br />

2 Zahlensysteme<br />

Ein Zahlensystem wird zur Darstellung von Zahlen verwendet. Eine Zahl wird dabei nach den<br />

Regeln des jeweiligen Zahlensystems als Folge von Ziffern beziehungsweise Zahlzeichen dargestellt.<br />

In einem Stellenwertsystem (auch polyadisches Zahlensystem) bestimmt die Stelle (Position)<br />

den Wert der jeweiligen Ziffer. Die niederwertigste Position steht dabei im Allgemeinen rechts.<br />

Ein Stellenwertsystem hat eine Basis b (man spricht auch von einem b-adischen Zahlensystem).<br />

Jede Zifferposition hat einen Wert, der einer Potenz der Basis entspricht. Für die n-te Position<br />

hat man einen Wert von b n−1 (wenn die niederwertigste Position mit 1 nummeriert ist).<br />

Die Berechnung des Zahlenwertes erfolgt durch Multiplikation der einzelnen Ziffernwerte z i mit<br />

den zugehörigen Stellenwerten b i und der Addition dieser Produkte:<br />

Zahlenwert = z n · b n + . . . + z i · b i + . . . + z 0 · b 0 . (1)<br />

2.1 Motivation und Anwendung<br />

Im Allgemeinen wird das Zahlensystem zur Basis 10 eingesetzt. Es gibt jedoch Anwendungsfälle,<br />

in denen das Zahlensystem zur Basis 10 ungeeignet ist. Aufgrund des digitalen Aufbaus eines<br />

Computers eignet sich das Zahlensystem zur Basis 10 zur Darstellung der Bit-<strong>Info</strong>rmation in<br />

keinster Weise. Es verschleiert die Zusammenhänge, die mit Anwendung eines Zahlensystems<br />

zur Basis 2 oder zur Basis einer 2er Potenz einfach und klar in Erscheinung treten würden.<br />

Vergleichbar ist dieser Zusammenhang der Anwendung<br />

verschiedener Koordinatensysteme. So ist z.B. die Beschreibung<br />

einer rechteckigen Fläche im 2 dimensionalen<br />

karthesischen Koordinatensystem sehr einfach. Hierbei<br />

entkoppeln die Unterdimensionen Länge und Breite<br />

(siehe Abb. 6). Eine Fläche ist allein durch Vorgabe dieser<br />

Werte möglich. Soll demgegenüber eine Kreisfläche<br />

im 2 dimensionalen karthesischen Koordinatensystem beschrieben<br />

werden, so sind die Unterdimensionen Länge<br />

Abbildung 6: Rechteckfläche<br />

und Breite offensichtlich gekoppelt. Eine Vorgabe dieser Werte allein reicht nicht mehr aus, um<br />

die Fläche zu beschreiben (siehe Abb. 7). Wählt man hingegen ein polares Koordinatensystem<br />

mit den Unterdimensionen Radius und Winkel, so ist es wieder möglich durch Vorgabe zweier<br />

Werte, in diesem Fall Radius und Winkelbereich, eine Kreisfläche zu beschreiben.<br />

Da der Computer aufbauend auf der logischen Elementareinheit Bit (0 und 1 / aus und ein) in<br />

Paketen von zumeist 8 Bits (1 Byte) strukturiert ist, empfiehlt es sich aufgrund der Unübersichtlichkeit<br />

des dualen Zahlensystems Bits zur gruppieren. Werden 3 Bits gruppiert erhält man als<br />

natürliches Zahlensystem das Zahlensystem zur Basis 8 (Oktalsystem). Werden 4 Bits gruppiert<br />

erhält man als natürliches Zahlensystem das Zahlensystem zur Basis 16 (Hexadezimalsystem).<br />

19.10.2011


Seite 8 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

Abbildung 7: Kreisfläche in karthesischen und polaren Koordinaten<br />

2.2 Beispiele zur Konvertierung zwischen Zahlensystemen<br />

Beispiel 1:<br />

Konvertierung von 142 5 in das Zahlensystem zur Basis b = 3.<br />

• Schritt 1:<br />

Konvertierung in das 10-System<br />

142 5 = 1 · 5 2 + 4 · 5 1 + 2 · 5 0<br />

= 25 10 + 20 10 + 2 10<br />

= 47 10<br />

• Schritt 2a:<br />

Konvertierung in das 3-System vollständig über 10-System<br />

47 10 = 1 · 3 3 + 2 · 3 2 + 0 · 3 1 + 2 · 3 0<br />

= 45 10 + 0 10 + 2 10<br />

= 1202 3<br />

• Schritt 2b:<br />

Ziffernweise Konvertierung in das 3-System<br />

142 5 = 1 · 5 2 + 4 · 5 1 + 2 · 5 0<br />

= 25 10 + 20 10 + 2 10<br />

= 221 3 + 202 3 + 2 3<br />

= 1202 3<br />

E. Baeck


2. ZAHLENSYSTEME Seite 9<br />

Beispiel 2:<br />

Konvertierung von 142 10 in das Zahlensystem zur Basis b = 6.<br />

Der Algorithmus zur Konvertierung einer Zahl in das Zahlensystem zur Basis b erfolgt durch<br />

b-Division und aufsammeln der Divisionsreste nach dem folgenden Prinzip (siehe Abb. 8).<br />

142 wird durch 6 dividiert. Dies ergibt 23 Rest 4<br />

23 wird durch 6 dividiert. Dies ergibt 3 Rest 5<br />

3 wird durch 6 dividiert. Dies ergibt 0 Rest 3<br />

Die erhaltenen Reste 4, 5 und 3 werden in die Reihenfolge<br />

von unten nach oben gebracht und von<br />

links nach rechts hin geschrieben. Damit erhalten<br />

wir die Zahl 354 6 .<br />

Abbildung 8: Rechteckfläche<br />

In Abbildung 8 wird die Umrechnung in einer EXCEL-Tabelle implementiert (siehe dazu auch<br />

Abschnitt 1). In A2 wird die zu konvertierende Zahl eingetragen. Der Divisor ist stets b, also<br />

6. Das Ergebnis der ganzzahligen Division erhalten wir mit der Formel =GANZZAHL(A2/B2). Der<br />

Divisionsrest in der grünen Spalte ergibt sich mit der Formel =REST(A2;B2). Das Ergebnis der<br />

ganzzahligen Division orange Felder werden in der folgenden Zeile in die Spalte des Dividenden<br />

eingetragen. Die Formel der ersten Zeile kann in die zweite Zeile eingetragen kopiert werden.<br />

Die Bezüge werden dabei, da relative Adressen verwendet werden, automatisch angepasst. In der<br />

Spalte E werden zur Kontrolle alle Anteile der Ziffern berechnet und in E6 zum Kontrollwert<br />

aufaddiert.<br />

Ein Übungsbeispiel:<br />

In nachfolgendem Übungsbeispiel ist in der Tabelle die in Spalte Zahl gegebene Zahl in die<br />

verschiedenen Zahlensysteme zur Basis b umzurechnen.<br />

Zahl b = 2 b = 5 b = 7 b = 8 b = 10 b = 16<br />

2021 3<br />

453 6<br />

246 7<br />

246 8<br />

33 10<br />

2F 16<br />

Tabelle 1: Zahlensysteme<br />

19.10.2011


Seite 10 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

2.3 Darstellung negativer Zahlen<br />

Negative Zahlen können bei einer endlichen Ziffernbreite so konstruiert werden, dass die Summe<br />

aus positiver und negative Zahl gerade die Zahl ergibt, die im Bereich der Ziffernbreite alle Ziffern<br />

zu Null setzt und einen Übertrag von 1 erzeugt, der aufgrund der beschränkten Ziffernbreite und<br />

eines Überlaufs nicht mehr darstellbar ist. So verbleiben also die ausgenullten Ziffern und die<br />

führende 1 verschwindet. Im Rahmen der vorliegenden Ziffernbreite ist das aber gerade die<br />

Darstellung des Null-Wertes.<br />

Die Konstruktion der negativen Zahl beginnt mit dem sogenannten Stellenkomplement. Das<br />

Stellenkomplement ist die Zahl, deren Ziffern sich ergeben zu b − z − 1, d.h. wir subtrahieren<br />

von der Basis b die gegebenen Ziffer und die 1. Eine Summe aus Stellenkomplement und<br />

gegebener Zahl ergibt demnach eine Ziffernfolge, die nur die größte Ziffer, also b − 1 enthält.<br />

Wenn wir auf diese Ziffernfolge eins aufaddieren wird ein Übertrag erzeugt, der aufgrund der<br />

Begrenzung der Ziffernbreite verschwindet und alle Ziffern werden auf Null gesetzt. Damit ist die<br />

Darstellung der negativen Zahl, das b-Komplement, gegeben durch das um eins inkrementierte<br />

Stellenkomplement.<br />

In der Tabelle 2 sind die Darstellungen der negativen Zahlen im angegebenen b-Komplement<br />

(Zahlensystemkomplement) bei vorgegebener Ziffernbreite einzutragen.<br />

Beispiel:<br />

b-Komplement der Zahl 346 7 bei einer Ziffernbreite von 4.<br />

Anmerkungen<br />

0346 7 zu komplementierende Zahl mit 4 Ziffer<br />

6320 7 Stellenkomplement: Komplementziffer = 6 -Ziffer<br />

+ 1 b-Komplement = Stellenkomplement +1<br />

6321 7 b-Komplement der Zahl<br />

Addition von Zahl und b-Komplement<br />

0346 7 zu komplementierende Zahl<br />

+ 6321 7 b-Komplement<br />

10000 7 Wird der Überlauf abgeschnitten ist das Ergebnis der Addition Null.<br />

Zahl Breite b − Komplement<br />

−2021 3 6<br />

−453 6 6<br />

−246 7 5<br />

−246 8 5<br />

−33 10 4<br />

−2F 16 4<br />

Tabelle 2: b-Komplement<br />

E. Baeck


3. DIE VBA-IDE Seite 11<br />

3 Die VBA-IDE<br />

Die VBA-IDE, (integrierte Entwicklungsumgebung) ist in allen Applikationen verfügbar, die<br />

VBA zur Automation einsetzten (z.B. MS-Office-Programm, AutoCAD, RStab, etc.).<br />

3.1 Oberfläche und Projektbrowser<br />

Die VBA-IDE wird standardmäßig<br />

über Alt-F11 oder<br />

Extras/Makro/Visual-Basic-<br />

Editor gestartet. Sie besteht<br />

aus einem Editor, einem<br />

Code-Generator für Rahmenprogramme<br />

ausgewählter<br />

Eventfunktionen und einem<br />

Programmtestmodul (Debugger)<br />

(siehe Abbildung 9).<br />

Abbildung 9: VBA-IDE<br />

Im Projektbrowser werden die folgenden Ordner angezeigt.<br />

• MS-EXCEL-Objekte<br />

Der Ordner enthält alle Tabellen der EXCEL-Datei (Workbook).<br />

• Modul-Objekte<br />

Der Ordner enthält Modul-Objekte, die ihrerseits die Quellen sequentieller (konventioneller)<br />

Programme enthalten. Module sind optional.<br />

• Userform-Objekte<br />

Der Ordner enthält Userform-Objekte, d.h. Layouts und Event-Quellen der Dialoge. Module<br />

sind optional.<br />

• Klassenmodul-Objekte<br />

Der Ordner enthält Klassenmodule. Ein Klassenmodul ist ein Objekt (mit Abstrichen) im<br />

Sinne der OOP. Module sind optional.<br />

Optionale Ordner werden beim Einfügen (Menü Einfügen oder Rechtsklick in Browserfenster)<br />

der entsprechenden Objekte (Module, Userform und Klassenmodul) angelegt.<br />

19.10.2011


Seite 12 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

3.2 Testen eines Programms, Debugger<br />

Programme können in der IDE<br />

mit dem integrierten Debugger<br />

getestet werden. Dazu geht man<br />

wie folgt vor. Das Programm<br />

wird nach setzen eines Haltepunktes<br />

unterbrochen und kann<br />

im Einzelschrittmodus, d.h. es<br />

wird Programmzeile um Programmzeile<br />

ausgeführt durchlaufen<br />

werden. Die Belegung der lokalen<br />

Variablen oder der Zustand<br />

gewählter Testausdrucke können<br />

ausgegeben werden.<br />

Abbildung 10: VBA-IDE-Debugger<br />

Der Debugger bietet die folgenden Ausführungsoptionen.<br />

• Haltepunkt<br />

An einem Haltepunkt wird das Programm unterbrochen. Der Haltepunkt kann mit F9<br />

oder im Menü Debuggen ein- oder ausgeschaltet werden.<br />

• Einzelschritt<br />

Mit dem Einzelschritt (F8) wird nur eine Programmanweisung ausgeführt. Mit dem Einzelschritt<br />

läuft der Debugger in Unterprogramme.<br />

• Prozedurschritt<br />

Mit dem Prozedurschritt (Shift+F8) wird nur eine Programmanweisung ausgeführt. Mit<br />

dem Prozedurschritt überspringt der Debugger Unterprogramme, d.h. die Unterprogramme<br />

werden ausgeführt ohne dass der Debugger das Programm anhält.<br />

• Cursorposition<br />

Mit der Ausführung bis zur Cursorposition (Strg+F8) kann das Programm bis zur aktuellen<br />

Cursorposition ausgeführt werden, sofern die Cursorposition in einem Programmteil<br />

liegt, der bei Ausführung durchlaufen wird.<br />

Abbildung 10 zeigt den Debugger im Testbetrieb. Haltepunkte werden als braune Punkte am<br />

linken Fensterrand des Editors angezeigt. Die aktuelle Programmposition wird in den Quellen<br />

gelb hinterlegt und zudem am linken Fensterrand durch einen gelben Pfeil markiert.<br />

E. Baeck


3. DIE VBA-IDE Seite 13<br />

Um den Zustand eines Programms prüfen zu können bietet die IDE die folgenden Einblicke.<br />

• Direktbereich<br />

Der Direktbereich ist ein Fenster, in das vom Programm aus mit der Objektfunktion<br />

—debug.print— direkt geschrieben werden kann. In dieses Fenster können Testausdrucke<br />

geschrieben werden, wenn z.B. ein Einzelschritt-Debuggen zu aufwendig wäre (z.B. Test<br />

bei zahlreichem Schleifendurchlauf).<br />

• Lokal<br />

Um die Transparenz mit wenig Aufwand zu gewährleisten, werden im Lokal-Fenster alle<br />

lokalen Variabelen und eventuelle Programmrückgabewerte ausgegeben.<br />

• Überwachungsausdrücke<br />

Ein Überwachungsausdruck ist eine Variabel oder ein Ausdruck mit mehreren Variablen.<br />

Überwachungsausdrücke können zum bedingten Anhalten eines Programmlaufes eingesetzt<br />

werden.<br />

19.10.2011


Seite 14 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

4 VBA-Interface<br />

Der Codegenerator der IDE verbindet Ereignisse (Klicken, Maus schieben, etc.) mit den<br />

gewünschten Programmen. Dazu ist zunächst ein Steuerelement (hier eine Schaltfläche) zu erzeugen.<br />

Die Eigenschaften des Steuerelements sind im Eigenschaftsfenster zu bearbeiten.<br />

Nach Doppelklick auf das Steuerelement<br />

wird ein Rahmen einer<br />

Klick-Ereignisfunktion im entsprechenden<br />

Tabellenordner der<br />

Tabelle, in der das Steuerelement<br />

erzeugt wurde, geschrieben.<br />

Ereignisfunktionen verknüpfen<br />

Ereignisse eines Steuerelements<br />

mit dem zu implementierenden<br />

Programmcode.<br />

4.1 Beispiel 1 in 6 Schritten<br />

Abbildung 11: VBA-IDE<br />

Im folgenden Beispiel 2 wird ein Programm implementiert, dass über eine Schaltfläche gestartet<br />

alle ganzen Zahlen aus einem vorgegebenen Intervall aufsummiert.<br />

4.1.1 Schritt 1: Gestaltung der Oberfläche<br />

In einem ersten Schritt wird die Programmoberfläche<br />

in einer Tabelle zusammengestellt.<br />

Es sind die Felder VON<br />

und BIS anzulegen, die die Intervallgrenzen<br />

enthalten werden. Zudem ist<br />

ein Feld SUM anzulegen, in das das<br />

zu schreibende Programm den Ergebniswert<br />

eintragen wird. Auf die Vergabe<br />

der Namen (hier: VON, BIS und SUM )<br />

Abbildung 12: Beispiel: Schritt 1<br />

sollte nicht verzichtet werden, da das<br />

Programm Felder in einfacher Weise über Namen ansprechen kann und zudem eine Kopplung<br />

2 Das Programm ist als Beispiel1 in der Beispiel-Sammlung zur Veranstaltung enthalten.<br />

E. Baeck


4. VBA-INTERFACE Seite 15<br />

an das Oberflächenlayout ausgeschlossen wird. Die Schaltfläche ist mit der Werkzeugleiste Steuerelemente<br />

zu generieren.<br />

4.1.2 Schritt 2: Gestaltung der Steuerelemente<br />

Nach dem Erzeugen der Schaltfläche (eines<br />

Steuerelements) ist diese zunächst<br />

im Entwurfsmodus, d.h. die Eigenschaften<br />

sind zu bearbeiten, Ereignisfunktionen<br />

werden automatisch durch einen<br />

Doppelklick generiert.<br />

Die Standardbezeichnung einer Schaltfläche<br />

ist CommandButton1. Dies ist<br />

der Objektname unter dem ein Objekt<br />

(hier die Schaltfläche) im Programmcode<br />

angesprochen werden kann.<br />

Die Schaltfläche soll nun ein Ereignis<br />

auslösen. Der Klick auf die Schaltfläche<br />

Abbildung 13: Beispiel: Schritt 2<br />

soll das Programm starten. Dazu ist der<br />

schon automatisch angelegte Rahmen der Ereignisfunktion CommandButton1_Click() mit dem<br />

entsprechenden Programmcode zu füllen.<br />

Die Syntax eines Ereignisfunktionsnamens wird in VBA wie folgt aufgebaut. Der erste <strong>Teil</strong><br />

des Namens (der Text vor dem _) ist der Name des Objekts (hier: CommandButton1). Der<br />

zweite <strong>Teil</strong> des Namens ist der Bezeichner für das Ereignis (hier: Click()). Rahmen für weitere<br />

Ereignisfunktionen werden automatisch nach Auswahl eines Ereignisses aus der Ereignisliste<br />

(siehe Abbildung 13) erzeugt.<br />

Wird z.B. das Ereignis LostFocus ausgewählt, d.h. Verlust des Eingabefokus, dann wird der<br />

Rahmen der Ereignisfunktion CommandButton1_LostFocus() erzeugt. Um die Wirkungsweise<br />

einer Ereignisfunktion zu studieren, kann in diese einfach der Aufruf einer Meldungsbox<br />

MsgBox "Meldungstext" eingetragen werden. Damit wird immer bei Auftreten des Ereignisses<br />

eine Meldungsbox in EXCEL ausgegeben.<br />

19.10.2011


Seite 16 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

4.1.3 Schritt 3: Generieren eines Moduls für Funktion Summe<br />

Mit einem Rechtsklick auf den Objektbrowser<br />

öffnet sich ein Menü mit der<br />

Funktion Einfügen/Modul. In den eingefügten<br />

Modul ist der Programmcode<br />

einzutragen. Der Name des Moduls wird<br />

in den Eigenschaften auf Beispiel1 abgeändert.<br />

Das noch zu implementierende Programm<br />

Summe wird nun aus der<br />

Ereignisfunktion für das Klickereignis<br />

Abbildung 14: Beispiel: Schritt 3<br />

CommandButton1_Click() aufgerufen. Dazu ist die Zeile Beispiel1.Summe in die Ereignisfunktion<br />

einzutragen.<br />

Damit ergibt sich für die Ereignisfunktion folgender Code.<br />

Private Sub CommandButton1_Click()<br />

Beispiel1.Summe<br />

End Sub<br />

4.1.4 Schritt 4: Das Programm Summe<br />

Um das Programm Summe zu implementieren, ist der Modulordner Beispiel1 zu öffnen und der<br />

Programmcode im Editor wie folgt einzugeben.<br />

’ Summation aller ganzer Zahlen aus einem Zahlenintervall<br />

Public Sub Summe()<br />

’ Öffentliches Programm "Public Sub"<br />

Dim ivon As Integer<br />

Dim ibis As Integer<br />

Dim isum As Integer<br />

Dim i As Integer<br />

’ Deklarationen mit Dim<br />

’ Initialisierung<br />

isum = 0<br />

ivon = Range("VON")<br />

ibis = Range("BIS")<br />

’ Schleife über das Intervall<br />

For i = ivon To ibis<br />

isum = isum + i<br />

Next<br />

’ Rückgabe des Summenwerts nach EXCEL-Tabelle<br />

Range("SUM") = isum<br />

End Sub<br />

E. Baeck


4. VBA-INTERFACE Seite 17<br />

In nachfolgender Tabelle werden die Anweisungen des Summe-Programms erläutert.<br />

Schlüssel<br />

Public<br />

Sub<br />

Dim<br />

Integer<br />

Range<br />

For<br />

End Sub<br />

Bemerkung<br />

gibt ein Unterprogramm, eine Funktion oder eine Variable frei für Zugriffe aus anderen<br />

Modulen.<br />

leitet ein Unterprogramm ein.<br />

explizite Deklaration der Variablen.<br />

Ganzzahlige Variable, Länge 2 Byte.<br />

Das Range-Objekt liefert einen Zugriff auf EXCEL-Tabellenfelder. Als Argument ist<br />

die EXCEL-Adresse, z.B. "VON" oder auch "C1", anzugeben. Mit Range wird sowohl<br />

aus einem Tabellenfeld gelesen als auch geschrieben (z.B. a = Range("TEST") und<br />

Range("TEST") = a).<br />

Mit For · · · Next wird eine Schleife implementiert. Die Laufvariable i durchläuft<br />

hierbei den Wertebereich von ivon bis ibis in Schritten von eins.<br />

schließt das Unterprogramm ab.<br />

Tabelle 3: Anmerkungen zum Programm Summe<br />

4.1.5 Schritt 5: Programmtests<br />

Bei einem ersten Programmtest könnte<br />

die in Abbildung 15 dargestellte<br />

Fehlersituation auftreten: Die Methode<br />

Range für das Object _Global ist fehlgeschlagen,<br />

d.h. der Zugriff auf ein Tabellefeld<br />

(Lesen oder Schreiben) konnte<br />

nicht durchgeführt werden. Grund<br />

dafür ist oft die Angabe einer falschen<br />

oder unbekannten Range-Adresse. In<br />

diesem Fall wurde vergessen, die EX-<br />

CEL-Tabellenfelder, auf die zugegriffen<br />

werden soll, mit einem entsprechenden<br />

Namen zu bezeichnen.<br />

Abbildung 15: Beispiel: Schritt 5<br />

19.10.2011


Seite 18 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

Wenn in der Absturzmeldung die Funktion<br />

Debuggen aufgerufen wird, springt<br />

der Programmzeiger in die Zeile des<br />

Quellcodes, in der der Fehler aufgetreten<br />

ist: Gelbe Zeile mit dem Schlüsselwort<br />

Range. Hier führt der Aufruf zum<br />

Programmabsturz. Der Grund kann nur<br />

eine unzulässige EXCEL-Adresse sein.<br />

Lösung: Vergabe der noch fehlenden Bezeichner<br />

in der Tabelle.<br />

Abbildung 16: Beispiel: Schritt 6<br />

4.1.6 Schritt 6: Das Ziel<br />

Um ein Programm zu testen, sind Aufgabenstellungen<br />

mit bekanntem Ergebnis<br />

zu suchen. Ein Programmtest ist<br />

dann erfolgreich, wenn eine hinreichende<br />

Anzahl von Testergebnissen reproduziert<br />

werden kann. Ein absturzfreier<br />

Durchlauf des Programms alleine ist<br />

natürlich als Test nicht ausreichend.<br />

Das Programm Summe berechnet die<br />

Summe der ganzen Zahlen von 1 bis 7<br />

Abbildung 17: Beispiel: Schritt 6<br />

zu 28. Auf der rechten Seite der Tabelle<br />

(siehe Abbildung 17) erfolgt zur Kontrolle eine Berechnung mit der Standard-EXCEL-Funktion<br />

Summe. Die Ergebnisse sind identisch.<br />

E. Baeck


5. ELEMENTARE ALGORITHMEN Seite 19<br />

5 Elementare Algorithmen<br />

Die Implementierung einfacher Algorithmen in VBA erfolgt in einer EXCEL-Tabelle. Die Eingabefelder<br />

(gelb hinterlegt) werden mit einem Namen versehen. Über diesen Namen werden die<br />

Eingabedaten aus den Feldern in den VBA-Code eingelesen (Funktion Range). Die Ergebniswerte<br />

werden ebenfalls mit der Funktion Range oder im Fall der Ausgabe einer Tabelle mit der<br />

Funktion Cells in die Tabelle geschrieben.<br />

Das Programm wird mit einer Schaltfläche gestartet. Es ist darauf zu achten, dass der Programm-<br />

Code in einem Modul und nicht im Tabellenobjekt abgelegt wird.<br />

5.1 Fakultät<br />

Es ist die Faktultät für eine beliebige natürliche Zahl n zu ermitteln. Die Benutzeroberfläche<br />

ist nach Abbildung 18 zu implementieren. Die Zwischenwerte der Produktbildung sind in einer<br />

Tabelle auszugeben. Die Abhängigkeit des realisierbaren Definitionsbereichs vom gewählten<br />

Datentyp (integer, long, etc.) ist zu untersuchen.<br />

n∏<br />

n! = 1 · 2 · · · · · (n − 1) · n = i (2)<br />

i=1<br />

Abbildung 18: Oberfläche zur Fakultät und zu Binomialkoeffizienten<br />

5.2 Binomialkoeffizient<br />

Es ist der Binomialkoeffizient für zwei beliebige natürliche Zahlen n und m zu ermitteln. Die<br />

Benutzeroberfläche ist nach Abbildung 18 zu implementieren. Die Zwischenwerte der Produktbildung<br />

sind in einer Tabelle auszugeben. Die Abhängigkeit des realisierbaren Definitionsbereichs<br />

vom gewählten Datentyp (integer, long, etc.) ist zu untersuchen.<br />

⎛ ⎞<br />

⎝ n ⎠ = n · n − 1 · · · · · n − m + 1 n!<br />

=<br />

m<br />

m!<br />

m! · (n − m)!<br />

(3)<br />

19.10.2011


Seite 20 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

5.3 Winkel zwischen 2 Vektoren des R n<br />

Der Winkel α zwischen 2 Vektoren ⃗a und ⃗ b aus dem R n kann mit Hilfe des Skalarprodukts wie<br />

folgt berechnet werden.<br />

( )<br />

⃗a ·⃗b<br />

α = arccos<br />

||⃗a|| · || ⃗ (4)<br />

b||<br />

Das Skalarprodukt zwischen den Vektoren ⃗a und ⃗ b berechnet sich wie folgt.<br />

⃗a ·⃗b =<br />

n∑<br />

a i · b i (5)<br />

i=1<br />

Die Beträge im Nenner können wie folgt mit dem Skalarprodukt berechnet werde.<br />

||⃗a|| = √ ⃗a · ⃗a (6)<br />

5.3.1 Pseudocode für Hauptprogramm<br />

Der Pseudocode für das Programm könnte wie folgt lauten.<br />

(1) Einlesen der Vektoren aus Tabelle und Prüfung der Dimensionen.<br />

(2) Berechnung des Betrages von ⃗a mit der Funktion a = SP rod(⃗a,⃗a).<br />

(3) Berechnung des Betrages von ⃗ b mit der Funktion b = SP rod( ⃗ b, ⃗ b).<br />

(4) Berechnung des Skalarprodukts von ⃗a mit ⃗ b mit der Funktion x = SP rod(⃗a, ⃗ b).<br />

(5) Winkelberechnung α = arccos( x<br />

a · b )<br />

5.3.2 Pseudocode für Funktion SP rod<br />

Der Pseudocode für die Funktion des Skalarproduktes könnte wie folgt lauten.<br />

(1) Bestimme die Dimension der Vektoren (Muß identisch sein!).<br />

(2) Initialisiere die Summenvariable (s = 0).<br />

(3) Setze Vektorindex auf Startposition (i = 1)<br />

(4) Berechne für die Position i das Produkt p = a(i) ∗ b(i)<br />

(5) Summiere das Produkt auf die Summenvariable s = s + p<br />

(6) Inkrementiere den Vektorindex um 1<br />

(7) Falls i ≤ n gehe zu (4).<br />

(8) Beende die Routine mit der Übergabe des Summenwertes s.<br />

E. Baeck


5. ELEMENTARE ALGORITHMEN Seite 21<br />

5.4 Reihenentwicklungen<br />

Im folgenden wird die Entwicklung der Funktionen sinus, cosinus und der e-Funktion diskutiert.<br />

5.4.1 Entwicklung der Funktion sinus<br />

Es ist ein Programm zu implementieren, das die Funktion sinus mit Hilfe der Potenzreiehenentwicklung<br />

(siehe unten) berechnet. Die Eingabensgrößen sind aus der Tabelle abzugreifen, die<br />

Ergebnisgrößen sind in den Ausgabebereich der Tabelle zu schreiben.<br />

Beachten Sie bei der Umsetzung der Gleichung 7, dass die Fakultäten im Nenner der Terme zu<br />

numerischen Problemen führen können, wenn sie unabhängig vom Zähler berechnet werden.<br />

Zu beachten ist ferner (siehe Tabelle in Abbildung 19):<br />

• Der X-Wert ist aus der Tabelle in [ 0 ] zu übernehmen.<br />

• Die Genauigkeit der Approximation ist aus der Tabelle zu übernehmen.<br />

• Es ist berücksichtigen, dass das Argument der Reihenentwicklung (siehe Gleichung 7)<br />

gegebenenfalls in rad umzurechnen ist.<br />

• In den Ausgabebereich der Tabelle ist der Index des Terms, der Wert des Terms und die<br />

aktuelle Summe zu schreiben.<br />

• Bevor die Ergebniswerte in die Tabelle ausgegeben werden, sind die Zeilen des Ergebenisbereichs<br />

zu löschen.<br />

sin(x) = x − x3<br />

3! + x5<br />

x2n+1<br />

− · · · + (−1)n<br />

5! (2n + 1)! ± . . . (7)<br />

Abbildung 19: EXCEL-Tabelle zur Reihenentwicklung<br />

19.10.2011


Seite 22 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

5.4.2 Reihenentwicklung weiterer Funktionen<br />

Analog zur Entwicklung der sinus-Funktion kann für die Funktion cosinus(x) eine Reihenentwicklung<br />

programmiert werden (siehe Gleichung 8).<br />

cos(x) = 1 − x2<br />

2! + x4<br />

x2n<br />

− · · · + (−1)n/2<br />

4! (2n)! ± . . . (8)<br />

Analog zur Entwicklung der sinus-Funktion kann für die Funktion f(x) = e x eine Reihenentwicklung<br />

programmiert werden (siehe Gleichung 9).<br />

e x = 1 + x 1! + x2<br />

2! + · · · + xn<br />

(n)! . . . (9)<br />

5.5 Newton-Verfahren<br />

5.5.1 Der Algorithmus des 1-dimensionalen Falls<br />

Mit dem Newton-Verfahren kann iterativ eine Nullstelle<br />

einer Funktion f(x) bestimmt werden. Hierfür<br />

sind ein Startwert x 0 , eine Genauigkeit ɛ und eine<br />

maximale Iterationsanzahl n x vorzugeben.<br />

Durch Nullsetzen einer Taylor-Reihenentwicklung<br />

um den Punkt x n kann die Iterationsformel des<br />

Newton-Verfahrens abgeleitet werden.<br />

Abbildung 20: Graphische Darstellung des<br />

Newton-Verfahrens<br />

f(x n+1 ) = f(x n ) + (x n+1 − x n ) · f ′ (x n ) = 0 ⇒ (10)<br />

x n+1 = x n − f(x n)<br />

f ′ (n = 0, 1, 2, . . . ; x 0 gegeben)<br />

(x n )<br />

Die Ableitung der Funktion f(x) kann durch den Differenzenquotienten angenähert werden.<br />

f ′ (x) =<br />

f(x + h/2) − f(x − h/2)<br />

h<br />

z.B. mit h = 0.001 (11)<br />

E. Baeck


5. ELEMENTARE ALGORITHMEN Seite 23<br />

5.5.2 Pseudo-Code<br />

Das Problem kann wie folgt in einem Pseudo-Code (umgangsprachliche Beschreibung) formuliert<br />

werden.<br />

1. Wähle einen Startwert x.<br />

2. Berechne f(x)<br />

3. Falls |f(x)| < ɛ, dann Nullstelle gefunden.<br />

4. Falls maximale Anzahl Iterationen erreicht, Ausgabe Fehlermeldung.<br />

5. Berechne f ′ (x).<br />

6. Falls |f ′ (x)| < ɛ, Ausgabe einer Fehlermeldung.<br />

7. Nächsten x-Wert berechnen: x ⇐ x − f(x)<br />

f ′ (x)<br />

8. Nächster Iterationsschritt mit Punkt 2.<br />

Anmerkung:<br />

Ein Problem tritt auf, wenn die Ableitung der Funktion verschwindet. Geometrisch: es gibt<br />

keinen Schnittpunkt zwischen Tangente und x-Achse.<br />

5.5.3 Programmablaufplan<br />

Das Newtonverfahren geht aus von einem Startwert<br />

x. Dieser wird zunächst eingelesen. Die Iterationsschleife<br />

beginnt mit der Berechnung des Funktionswertes<br />

f(x). Darauf folgt die Nullabfrage. Falls der<br />

Absolutbetrag des Funktionswertes kleiner als die<br />

Genauigkeit ɛ ist, wird die Iterationsschleife abgebrochen<br />

und die Lösung ausgegeben.<br />

Es folgt die Prüfung der zulässigen Iterationsdurchläufe.<br />

Nach der Berechnung der Tangentensteigung f ′ (x)<br />

wird, falls diese nicht verschwindet, ein neuer x-<br />

Wert berechnet und ein neuer Schleifendurchlauf gestartet.<br />

Abbildung 21: Programmablaufplan des<br />

Newton-Verfahrens<br />

19.10.2011


Seite 24 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

5.5.4 Nassi-Schneidermann-Diagramm<br />

Das Nassi-Shneiderman-<br />

Diagramm zeigt den linearen<br />

Fluß des Programms. Es werden<br />

keine Sprünge (Goto) durch<br />

Verbinder nahe gelegt.<br />

Im Fall des Erreichens der maximal<br />

vorgegebenen Iterationsanzahl<br />

und im Fall verschwindender<br />

Tangentensteigung wird das Programm<br />

direkt mit einer entsprechenden<br />

Meldung abgebrochen.<br />

Abbildung 22: NS-Diagramm des Newton-Verfahrens<br />

5.5.5 Die Oberfläche<br />

In den gelb hinterlegten Tabellenfeldern<br />

C3-C5 werden die Eingangsgröße,<br />

der Startwert x, die<br />

maximal zulässige Anzahl der<br />

Iterationen und die gewünschte<br />

Genauigkeit eingegeben. Mit<br />

der Schaltfläche wird das Programm<br />

gestartet. In den Ausgabefeldern<br />

C8-C10 werden die Ergebnisgrößen,<br />

die eventuell gefundene<br />

Nullstelle, der durchlaufenen<br />

Iterationen und eine Kommentierung<br />

des Iterationsverlaufs ausgegeben.<br />

Abbildung 23: EXCEL-Tabelle zum Programm<br />

Im unteren <strong>Teil</strong> der Tabelle werden die Ergebnisse der einzelnen Interationsschritte ausgegeben.<br />

E. Baeck


5. ELEMENTARE ALGORITHMEN Seite 25<br />

5.5.6 Animation des Verfahrens<br />

Die animierte Darstellung des Newtonverfahrens<br />

zeigt die Annäherung an die<br />

Nullstelle durch konsequentes Verfolgen<br />

der Funktione (blaue Linie) entlang<br />

ihrer Tangente (rote Kurve).<br />

Start der Animation durch Anklicken<br />

Abbildung 24: Animation des Newton-Verfahrens.<br />

19.10.2011


Seite 26 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

6 Elementare Sortiert-Algorithmen<br />

Einfache Sortieralgorithmen können problemlos zum Sortieren kleiner Datenmengen eingesetz<br />

werden. Da der Sortieraufwand zumeist in quadratischer Ordnung O(n 2 ) der zu sortierenden<br />

Datensätze anwächst, sind große Datenmengen i.A. mit diesen Algorithmen nicht mehr wirtschaftlich<br />

zu sortieren.<br />

Im folgenden werden zwei der einfachen Sortieralgorithmen dargestellt,<br />

• Select-Sort oder Auswahlsortierung und<br />

• Bubble-Sort<br />

6.1 Select-Sort<br />

Select-Sort wählt aus einer zu sortierenden<br />

Menge das größte Element aus<br />

und tauscht es mit dem Element der<br />

ersten Position. Aus den verbleibenden<br />

Elementen wählt er wiederum das<br />

größte Element aus und tauscht es mit<br />

dem Element der zweiten Position. Dieses<br />

Verfahren wird solange fortgesetzt,<br />

bis die zu durchsuchende Menge auf<br />

ein Element zusammen geschrumpft ist.<br />

Der so implementierte Algorithmus ist<br />

offensicht von quadratischer Ordnung,<br />

d.h. O(n 2 ), da in einer Schleife alle Positionen<br />

neu besetzt werden müssen und<br />

in dieser in einer inneren Schleife der<br />

Datenbestand - zwar nicht zur Gänze -<br />

durchlaufen wird, um das aktuell größte<br />

Element zu bestimmen.<br />

Abbildung 25: SelectSort: SORTIERANGS<br />

In Abbildung 25 wird das Wort SORTIERANGS alphabetisch sortiert. In jedem Schritt wird aus<br />

der aktuellen Sortiermenge der kleinste Buchstabe im Sinne des Alphabets gesucht. Im ersten<br />

Schritt wird das A gefunden und mit dem Buchstaben der ersten Position S getauscht. Der erste<br />

Buchstabe der aktuellen zu durchsuchenden Menge wird fett berandet dargestellt. Der kleinste<br />

Buchstabe wird farbig markiert. In nachfolgenden Zeile wird zum einen der Buchstabentausch<br />

dargestellt, zum anderen wird die neue Suchmenge und ihr kleinster Buchstabe dargestellt. Um<br />

die einzelnen Suchschritte visuell abzusetzen wird für jeden Such- und dazugehörigen Tauschschritt<br />

eine eigene Hintergrund-Farbe gewählt.<br />

E. Baeck


6. ELEMENTARE SORTIERT-ALGORITHMEN Seite 27<br />

6.2 Bubble-Sort<br />

Die Idee des Bubble-Sort-Algorithmuses folgt der Vorstellung von aufsteigenden Luftblasen in<br />

einer Flüssigkeit. Vom letzten Element an wird in einer inneren Schleife vom ersten Element an<br />

bis zum betrachteten dann eine Vetauschung ausgeführt wenn das Element der inneren Schleife<br />

größer (bzw. kleiner) 3 ist als das betrachtete. So steigen die größeren (bzw. kleineren) Element<br />

nach vorne auf wie Luftblasen in einer Flüssigkeit (Bubble-Sort).<br />

Im Vergleich zu SelectSort benötigt BubbleSort einen unnötig hohen Aufwand des Vertauschens.<br />

3 Abhängig von der Sortierrichtung steigt entweder das kleinere oder größere Element auf Richtung Platz 1.<br />

19.10.2011


Seite 28 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

7 Arbeiten mit Dateien<br />

7.1 Dateioperationen für sequentiellen Zugriff<br />

Die Datei wird geöffnet unter Vorgabe des Dateinamens und des Verarbeitungskenners (Input,<br />

Output, Append). Die Zugriffe auf die Datei erfolgen unter Vorgabe der Kanalnummer.<br />

In nachfolgender Tabelle werden wesentliche Dateifunktionen zusammengefaßt.<br />

Funktion Beschreibung Beispiel<br />

Open Öffnen einer Datei. Open "bsp.txt" For Input As #1<br />

Input Einlesen aus einer Datei. Input #1, x, y<br />

Write Schreiben ín eine Datei. Write #1, x, y<br />

Close Schließen der Daten. Close #1<br />

Input Line Einlesen einer Datenzeile aus Textdatei. Input Line #1, s<br />

EOF Dateiende erkennen. Do While Not EOF(1)<br />

Die EXCEL-Anwendung liefert einen Standarddialog zur Suche einer Datei. Der Aufruf dieses<br />

Dialogs wird in nachfolgendem Code dargestellt.<br />

Die im nachfolgenden Beispiel dargestellte Funktion wird als Steuerprogramm zur Berechnung<br />

des Torsionsträgheitsmomentes nach der Brendt’schen Formel eingesetzt (siehe Gleichung 12).<br />

Im 2. Schritt wird die Methode GetOpenFilename des Application-Objekts 4 aufgerufen. Die<br />

Methode startet den allgemeinen Windows-Datei-Öffnen-Dialog. Als Rückgabewert liefert die<br />

Methode den Namen der gewählten Datei. Wird der Dialog vom Anwender abgebrochen, so<br />

wird der String Falsch zurückgegeben. 5<br />

’ Dateinamen ermitteln<br />

Private Sub CommandButton1_Click()<br />

’ 1: Initialisierung<br />

Call Brendt.Init<br />

’ 2: Dateinamen festlegen<br />

datei$ = Application.GetOpenFilename( _<br />

fileFilter:="Textdateien (*.txt),*.txt")<br />

’ 3: Starten der Berechnung<br />

If Not datei$ = "Falsch" Then<br />

Range("Datei") = datei$<br />

’ Einlese der Datei und Berechnung<br />

Call Brendt.ProfilLesen(datei$)<br />

4 Das Objekt Application, siehe auch OOP, stellt alle Objekte der EXCEL-Anwendung zur Verfügung. Objekt<br />

der EXCEL-Anwendung sind z.B. die Listen der Tabellen und Diagramme, sind auch die Range-Objekte, die die<br />

Kommunikation mit den Tabellenfeldern ermöglicht.<br />

5 Mit der Rückgabe Falsch im Fall des Abbruchs ist es unzulässig eine Datei mit dem Namen Falsch anzusprechen,<br />

was i.A. kein Problem sein dürfte.<br />

E. Baeck


7. ARBEITEN MIT DATEIEN Seite 29<br />

Call Brendt.ProfilBerechnen<br />

End If<br />

End Sub<br />

7.2 Torsionsträgeheitsmoments nach 2. Brendt’scher Formel<br />

In einer Datei wird eine beliebige, konvexe Kontur eines Profils durch Punkte auf der Mittelfläche<br />

im üblichen y-z-Koordinatensystem beschrieben (x-Achse ist Profillängsrichtung). Zu<br />

jedem Punkt wird als dritter Wert die Dicke des Profils am Ort des Punktes angegeben.<br />

Das Programm zur Berechnung des Torsionsträgheitsmomentes nach der 2. Brendt’schen Formel<br />

erhält die folgenden Optionen.<br />

• Einlesen und Speichern der Datei in dynamisch angelegten Feldern (Arrays), wobei die<br />

<strong>Info</strong>rmation eines Punktes in einer benutzerdefinierten Strukur (TYPE/END TYPE) gehalten<br />

werden soll. Um eine zyklische Profilbeschreibung zu erleichtern, sind die Daten des<br />

ersten Punktes als zusätzlicher der Punktliste anzuhängen.<br />

• Ausgabe der Daten des Feldes in einer Tabelle. Die Altdaten werden zunächst mit der<br />

Funktion Löschen aus der Tabelle entfernt.<br />

• Ausgabe der Profilkontur in einem Diagramm in Form eines X-Y-Plots.<br />

• Berechnung des Torsionsträgheitsmoments mit Hilfe der 2. Brendt’schen Formel.<br />

I T = (2 · A m) 2<br />

∮ ds<br />

t<br />

(12)<br />

Im Fall dünnwandiger Profile kann die Gleichung 12 wie folgt vereinfacht werden.<br />

1. Zunächst ist das Linienintegral durch die Summe ∑ N L i<br />

i=1<br />

L i = √ (y i − y i+1 ) 2 + (z i − z i+1 ) 2 und t i = 0.5 · (t i + t i+1 ).<br />

t i<br />

zu berechnen, wobei<br />

2. Die Fläche der Kontur kann mit der folgenden Formel zur Bestimmung einer Polgonfläche<br />

ermittelt werden.<br />

A m =<br />

N∑<br />

i=1<br />

y i · z i+1 − z i · y i+1<br />

2<br />

(13)<br />

mit: y N+1 = y 1 , und z N+1 = z 1<br />

19.10.2011


Seite 30 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

8 Das Clapeyron-Problem<br />

Mit der Gleichung nach Clapeyron können die Stützmomente eines n-Feldträgers (Durchlaufträger)<br />

berechnet werden. Die Herleitung der Gleichung 6 aus dem Kraftgrößenverfahren wird in<br />

Abschnitt A dargestellt.<br />

Der Abschnitt zeigt exemplarisch die wesentlichen Schritte der Entwicklung eines Berechnungsprogramms<br />

mit moderner Eingabeoberfläche und entsprechender Datenhaltung.<br />

8.1 Motivation<br />

In diesem Abschnitt wird die Entwicklung eines Programms zur Berechnung der Stützmomente<br />

eines n-Feld-Durchlaufträgers dargestellt. Es werden als Belastungen Streckenlasten, Punktlasten<br />

und Punktmomente vorgesehen, die beliebig auf den Feldern des Trägers positioniert werden<br />

können.<br />

Die Entwicklung erfolgt den Schritten:<br />

1. Gestaltung der Eingabe in einer Benuzteroberfläche.<br />

2. Modellierung der Datenstrukturen und Visualisierung im ER-Modell.<br />

3. Algorithmus zur Generierung der Modell-Datenstrukturen.<br />

4. Algorithmus zum Aufbau des linearen Gleichungssystems (A · x = b).<br />

5. Cholesky-Algorithmus zur Zerlegung der Matrix A = L · L T .<br />

6. Berechnung der Stützmomente durch Vorwärts- Rückwärtseinsetzen.<br />

7. Ausgabe der Ergebnisgrößen in der Benutzeroberfläche.<br />

8.2 Oberflächenlayout und Eingabe<br />

Als Eingabeoberfläche wird eine EXCEL-Tabelle eingesetzt, in der die Felder bzw. die Belastungen<br />

der Felder in Listenform eingetragen werden. Die Eingabetabelle orientiert sich ausschließlich<br />

an den Bedürfnissen des Anwenders und enthält keinerlei Daten, die nur durch die Organisation<br />

der Daten im Programm (Datenstrukturen) betreffen.<br />

Generell sollte sich die Eingabeoberfläche eines Programms nur an der Sicht des Anwenders<br />

orientieren. So sollten keine für die Gestaltung der Datenstruktur wichtigen Parameter als Eingabeparameter<br />

vorgesehen werden, da deren Notwendigkeit dem Anwender kaum vermittelbar<br />

ist.<br />

Die Anzahl der Felder z.B. ergibt sich aus ihrer Beschreibung. Die Vorgabe der Anzahl der<br />

gewünschten Felder wäre somit für den Anwender eine redundante Eingabe. Die Anzahl der<br />

Felder ist für die Dimensionierung der Feldvariabeln erforderlich und ist vom Programm aus<br />

den Eingaben des Anwenders abzuleiten.<br />

6 Die Gleichung von Clapeyron wird auch 3-Momentengleichung genannt.<br />

E. Baeck


8. DAS CLAPEYRON-PROBLEM Seite 31<br />

Im Vorschlag der<br />

Eingabe werden<br />

die Felder von<br />

links nach rechts<br />

eingegeben. Die<br />

Feldnummerierung<br />

ergibt sich automatisch<br />

aus der<br />

Reihenfolge.<br />

Abbildung 26: Eingabe Oberfläche des Programms<br />

8.2.1 Feldbeschreibung<br />

Die Felddaten können in Form einer Liste eingegeben werden. Die Reihenfolge entspricht der<br />

Feldreihenfolge vom Festlager (links) hin zum Gleitlager (rechts), siehe z.B. Abbildung 43. Pro<br />

Feld werden<br />

• die Feldlänge in [cm] und<br />

• das Verhältnis der Flächenträgheit zur Referenzträgheit I c<br />

eingegeben. Das Import-Programm liest die Datensätze von oben nach unten aus der Tabelle<br />

und schreibt die erfassten Daten in ein Feld aus entsprechenden Datenstrukturen. Die Dimensionierung<br />

ergibt sich aus der Anzahl der Datensätze.<br />

8.2.2 Lastbeschreibung<br />

Die Lastdaten können beliebig in Form einer Liste eingegeben werden. Ein Lastdatensatz enthält<br />

die folgenden Daten.<br />

• Die Lastfallnummer, Wahl der rechten Seite (siehe Abschnitt D).<br />

• Die Feldnummer beschreibt den Ort der zu erfassenden Last.<br />

• Der Belastungstyp:<br />

– Typ 1, die Streckenlast<br />

Parameter: Lastordinate q, Abszisse des Lastschwerpunktes a und Lasteinleitungslänge<br />

c.<br />

– Typ 2, die Punktlast<br />

Parameter: Lastordinate P , Abszisse der Lasteinleitung a.<br />

– Typ 3, das Punktmoment<br />

Parameter: Lastordinate M, Abszisse der Lasteinleitung a.<br />

• Lastordinate für Typ 1, q, in [kN/cm], für Typ 2, P , in [kN] und für Type 3 M in [kNcm].<br />

Dieses Eingabefeld und alle weiteren beschreiben die Details der gewünschten Last.<br />

19.10.2011


Seite 32 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

• Der Parameter a beschreibt den Abstand des Lastschwerpunktes vom linken Lager in [cm]<br />

(für alle Typen relevant).<br />

• Der Parameter c beschreibt die Länge der Lasteinleitung in [cm] (nur für Typ 1 relevant).<br />

8.3 ER-Modell der Datenstruktur<br />

Das ER-Modell (nach Chen siehe Abschnitt B) der Datenstruktur des Clapeyron-Problems besteht<br />

aus zwei <strong>Teil</strong>en, dem Datenmodell der Struktur und dem Datenmodell der Belastung.<br />

In den Diagrammen zum Struktur- und Lastdantenmodell des Clapeyron-Problems werden Container-Objekte<br />

kursiv geschrieben. Container-Objekte sind Objekte, die eine beliebige Anzahl<br />

von Objekten aufnehmen können. In diesem Beispiel werden einfache Datenfelder eingesetzt. In<br />

VBA werden diese durch die Vorgabe des Index-Bereiches vereinbart.<br />

Beispiele 1: Statische Deklaration eines Containers für 20 Felder<br />

Dim FA(1 to 20) As Feld<br />

Beispiele 2: Dynamische Deklaration eines Containers für n Felder<br />

Dim FA() As Feld<br />

...<br />

n = ...<br />

Redim FA(1 to n)<br />

8.3.1 ER-Modell der Struktur<br />

Das System des Durchlaufträgers<br />

besteht aus mehreren<br />

Feldern. Diese werden in dem<br />

Objekt Felder zusammen gefaßt.<br />

Die Anzahl der Felder ist<br />

theoretisch Unbeschränkt, somit<br />

eine 1-n-Beziehung. Ein Feld<br />

hat die Attribute Länge und<br />

Trägheit (siehe Abbildung 27).<br />

Abbildung 27: ER-Modell der Struktur<br />

Aufgabe 8.3.1:<br />

Es sind dem ER-Modell entsprechende Datenstrukturen (Schlüsselwort Type ... End Type) in<br />

VBA zu entwickeln.<br />

E. Baeck


8. DAS CLAPEYRON-PROBLEM Seite 33<br />

8.3.2 ER-Modell der Belastung<br />

Das Datenmodell der Belastung<br />

geht aus von einem<br />

Container (Liste oder Feld)<br />

der Lastfälle. Der Container<br />

kann beliebig viele Lastfälle aufnehmen<br />

(1-n-Beziehung). Jeder<br />

Lastfall enthält wiederum drei<br />

Container. Der erste Container<br />

enthält die Streckenlasten,<br />

der zweite die Punktbelastungen<br />

und der dritte die Punktmomente.<br />

Jeder dieser drei Beziehungen<br />

ist eine 1-n-Beziehung,<br />

da jeder Container beliebig viele<br />

Lasten aufnehmen kann.<br />

Ein Lastfall hat das Attribut Nr,<br />

er weiß sozusagen, wie er heißt.<br />

Die Lastarten haben als Attribute<br />

ihre Parameter, Lastordinate,<br />

Lastabszisse und die<br />

Streckenbelastung hat zudem<br />

das Attribut der Lasteinleitungslänge.<br />

Abbildung 28: ER-Modell der Belastung<br />

Aufgabe 8.3.2:<br />

Es sind dem ER-Modell entsprechende Datenstrukturen (Schlüsselwort Type ... End Type) in<br />

VBA zu entwickeln.<br />

19.10.2011


Seite 34 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

8.4 Aufbau der Datenstruktur<br />

In diesem Abschnitt wird ein Algorithmus zum Aufbau der Datenstrukturen für System und<br />

Belastung entwickelt.<br />

8.4.1 Die Datenstruktur des Systems<br />

Die Daten eines Feldes werden in der Struktur<br />

(Type) Feld abgespeichert. Als Container<br />

wird zunächst ein Datenfeld eingesetzt.<br />

Dieses wird dynamisch an die zu speichernde<br />

Datenmenge angepaßt (dynamisches Allokieren).<br />

Da die Anzahl der Felder nicht explizit<br />

festgelegt wird, ist diese zunächst aus den Eintragungen<br />

der Tabelle zu ermitteln. Die ausgefüllten<br />

Tabellenfelder der Spalte Feldlänge<br />

(siehe Abbildung 26) werden im ersten Durchlauf<br />

gezählt, um den Container dimensionieren<br />

zu können.<br />

Wenn die Feldanzahl feststeht, wird der Container<br />

entsprechend dimensioniert. In einem<br />

zweiten Durchlauf über die Tabelle wird die<br />

Feldlänge und das Trägheitsverhältnis eines<br />

Abbildung 29: Aufbau der Strukturdaten<br />

Feldes ausgelesen und in die Feldstruktur eingetragen.<br />

Die Feldstruktur wird in den Container aufgenommen.<br />

Aufgabe:<br />

Es ist ein Programm zu implementieren, dass aus der Tabelle der Abbildung 26 die Daten der<br />

Felder ausliest und diese in einem Container passender Größe abspeichert.<br />

Hinweis:<br />

Der Container wird mit dem Schlüsselwort Dim [Bezeichnung]() As [Type] und<br />

ReDim [Bezeichnung](1 to nFeld) angelegt. Der Zugriff auf die Tabellenfelder erfolgt<br />

mit dem Objekt Cells (i,j), wobei Cells (1,1) der Tabellenadresse A1 entspricht.<br />

E. Baeck


8. DAS CLAPEYRON-PROBLEM Seite 35<br />

8.4.2 Die Datenstruktur der Belastungen<br />

Der Aufbau der Datenstrukturen für die Belastungen<br />

erfolgt in drei Durchläufen. In jedem<br />

Durchlauf werden die Datenfelder neu Eingelesen<br />

und nach anderen Kriterien ausgewertet.<br />

Im ersten Durchlauf werden die extremalen<br />

Lastfallnummern ermittelt (siehe Abbildung<br />

30). Im Intervall zwischen den extremalen<br />

Lastfallnummern wird ein Indexvektor aufgestellt,<br />

der mit der Lastfallnummer indiziert<br />

wird.<br />

Abbildung 30: Ermitteln extremaler Lastfallnummern<br />

Aufbau des Lastfall-Indexvektors<br />

In den Lastfall-Indexvektor ist in einem zweiten<br />

Durchlauf<br />

• die gefundene Lastfallnummer,<br />

• die Anzahl der Streckenlasten zu diesem<br />

Lastfall,<br />

• die Anzahl der Punktlasten zu diesem<br />

Lastfall und<br />

• die Anzahl der Punktmomente zu diesem<br />

Lastfall<br />

einzutragen. Das Eintragen erfolgt durch<br />

schrittweises Hochzählen der gefundenen<br />

Lastdaten (siehe Abbildung 31).<br />

Abbildung 31: Ermitteln der Lastdatenanzahlen<br />

19.10.2011


Seite 36 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

Aufbau der Datenstruktur<br />

Der Lastfall-Container wird im Bereich der<br />

gefundenen Lastfallnummern angelegt, d.h.<br />

ein Lastfall wird direkt über seine Nummer<br />

angesprochen, auf eine kompakte Speicherung<br />

wird hier verzichtet, da die Datenstruktur der<br />

Belastung abgesehen von der Lastfallnummer<br />

zunächst nur leere Container für die Lastdaten<br />

enthält.<br />

Abbildung 32: Aufbau der Last-Datenstruktur<br />

In einer Schleife über den Lastfall-Indexvektor ILF wird für jeden vorhandenen Lastfall<br />

• die Lastfallnummer aus ILF übertragen,<br />

• falls Streckenlasten vorhanden, ein Container ausreichender Größe für diese dimensioniert,<br />

• falls Punktlasten vorhanden, ein Container ausreichender Größe für diese dimensioniert<br />

und<br />

• falls Punktmomente vorhanden, ein Container ausreichender Größe für diese dimensioniert.<br />

Wie viele Streckenlasten, Punktlasten und Punktmomente vorhanden sind, ist dem entsprechenden<br />

Zähler des Lastfall-Indexvektors zu entnehmen (ILF(lf).sl, ILF(lf).pl und ILF(lf).pm).<br />

Einlesen der Lastdaten<br />

Bevor die Lastdatensätze eingelesen werden<br />

können, werden die Lastdatenzähler im<br />

Lastfall-Indexvektor zurück gesetzt (d.h. auf<br />

0 gesetzt). Die Einleseschleife läuft sodann<br />

über alle Lastdatensätze. Es werden zunächst<br />

Lastfallnummer und Lasttyp eingelesen. Der<br />

Zähler des vorliegenden Lastfalls bzw. des<br />

vorliegenden Lasttyps wird inkrementiert, um<br />

ein fortlaufendes Einspeichern der Lastdaten<br />

in den Container zu ermöglichen. Mit diesem<br />

inkrementierten Zähler wird sodann der<br />

Lastdaten-Container (Streckenlast, Punktlast<br />

oder Punktmoment) indiziert. Die Lastdaten<br />

werde aus der Tabelle mit der Funktion Cells<br />

gelesen und in den entsprechenden Container<br />

übertagen (siehe Abbildung 33).<br />

Abbildung 33: Einlesen der Lastdaten<br />

E. Baeck


8. DAS CLAPEYRON-PROBLEM Seite 37<br />

8.5 Aufbau des Linearen Gleichungssystems<br />

In diesem Abschnitt wird aus den Daten der Datenstrukturen der Felder und Lasten (siehe<br />

Abschnitt 8.4) das lineare Gleichungssystem entwickelt.<br />

8.5.1 Aufbau der Koeffizientenmatrix<br />

Die Koeffizienten-Matrix A eines n-Feldträgers (siehe Gleichung 33) hat die Dimension (n−1)⊗<br />

(n − 1) und ist zudem (siehe Gleichung 28)<br />

• symmetrisch mit<br />

• Bandstruktur der Bandweite 1 7 .<br />

Für einen 5-Feldträger der Feldlängen l 1 bis l 5 ergibt sich die folgende Koeffizienten-Matrix.<br />

⎡<br />

⎤<br />

2 · (l 1 + l 2 ) l 2 0 0<br />

l<br />

A =<br />

2 2 · (l 2 + l 3 ) l 3 0<br />

(14)<br />

⎢ 0 l<br />

⎣<br />

3 2 · (l 3 + l 4 ) l 4 ⎥<br />

⎦<br />

0 0 l 4 2 · (l 4 + l 5 )<br />

Da die Symmetrie der Matrix A während der Zerlegung erhalten bleibt (siehe Abschnitt D.3),<br />

kann auf das Abspeichern der oberen Hälfte der Matrix A verzichtet werden.<br />

Im Fall der Clapeyron’schen Gleichung ist zudem nur die erste Nebendiagonale besetzt, d.h.<br />

es ist nur erforderlich, die Diagonale und die erste Nebendiagonale von A zu speichern. Eine<br />

kompakte Speicherung einer symmetrischen Bandmatrix mit Bandbreite m erfordert die folgende<br />

Indexsubstitution.<br />

a i,k → a i,k−i+m+1 (k ≤ i) (15)<br />

Mit der Indexsubstitution (15) folgt für die Matrix (14)<br />

⎡<br />

⎤<br />

0 2 · (l 1 + l 2 )<br />

l<br />

A =<br />

2 2 · (l 2 + l 3 )<br />

⎢ l<br />

⎣ 3 2 · (l 3 + l 4 ) ⎥<br />

⎦<br />

l 4 2 · (l 4 + l 5 )<br />

(16)<br />

7 Die Bandweite einer Matrix ist gegeben durch die Anzahl der besetzten Nebendiagonalen.<br />

19.10.2011


Seite 38 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

Der erforderliche Speicher für die Koeffizientenmatrix<br />

eines n-Feldträger ergibt sich somit<br />

zu (n − 1) · 2 (siehe (16)).<br />

Die Besetzung der Matrix folgt aus (16). In die<br />

erste Spalte werden die Feldlängen geschrieben,<br />

wobei die erste Feldlänge durch 0 erstetzt<br />

wird. In der zweiten Spalte steht die zweifache<br />

Summe aufeinander folgender Felder. Der Algorithmus<br />

des Aufbaus wird in Abbildung 34<br />

Abbildung 34: Aufbau der Koeffizientenmatrix<br />

dargestellt. Die Länge des i-ten Feldes l i , wird<br />

aus dem Feld-Container abgegriffen und mit dem Trägheitsverhältnis skaliert FA(i).L/FA(i).dI<br />

(siehe Abschnitt A)<br />

Durch die kompakte Speicherung der Matrix reduziert sich der erforderliche Speicher wie folgt.<br />

A kompakt 2 · (n − 1)<br />

=<br />

A komplett<br />

(n − 1) 2 = 2<br />

n − 1<br />

(17)<br />

Im betrachteten Beispiel des 5-Feldträgers reduziert sich der erforderliche Speicherplatz auf<br />

2<br />

5−1 = 1 2<br />

2<br />

101−1 = 1<br />

50<br />

= 50%. Im Fall eines 101-Feldträgers beträgt der erforderliche Speicherplatz bereits<br />

= 2% der Gesamtmatrix.<br />

8.5.2 Aufbau der Lastvektoren<br />

Die Lastvektoren werden der Einfachheit halber nicht dicht sondern im Intervall [lf min , lf max ]<br />

angelegt. Ob ein Lastvektor Lasten enthält oder nicht ergibt sich aus der Summe der Lastdatensätze<br />

eines Lastfalls (siehe Lastfall-Indexvektor Abschnitt 8.4.2). Für die drei Lastarten<br />

werden Lastgeneratoren implementiert. Die generierten Lastdaten werden in den Lastvektor<br />

aufsummiert.<br />

Nach [1] ergibt sich für den i-ten Eintrag in den Lastvektor, d.h. für das rechte Stützmoment<br />

des i-ten Feldes 8 .<br />

• für eine Streckenlast aus linksseitigem Feld<br />

b i,l = −R i−1 · l i−1 = −q · a · c<br />

(1 − α 2 − 1 )<br />

4 · γ2 · l i−1 (18)<br />

• für eine Streckenlast aus rechsseitigem Feld<br />

b i,r = −L i · l i = −q · b · c<br />

(1 − β 2 − 1 )<br />

4 · γ2 · l i (19)<br />

8 Es werden die folgenden Abkürzungen verwendet: α = a l , β = b l = l − a<br />

l<br />

und γ = c l<br />

E. Baeck


8. DAS CLAPEYRON-PROBLEM Seite 39<br />

• für eine Punktlast aus linksseitigem Feld 9<br />

b i,l = −R i−1 · l i−1 = −P · a · b (1 − α) (20)<br />

• für eine Punktlast aus rechtsseitigem Feld<br />

b i,r = −L i · l i = −P · a · b (1 − β) (21)<br />

• für ein Punktmoment aus linksseitigem Feld 10<br />

b i,l = −R i−1 · l i−1 = M L · (1<br />

− 3 · α 2) · l i−1 (22)<br />

• für ein Punktmoment aus rechtsseitigem Feld<br />

b i,r = −L i · l i = −M L · (1<br />

− 3 · β 2) · l i (23)<br />

9 Die Feldlängen kürzen sich aus den Termen für Punktlasten.<br />

10 M L ist ein linksdrehendes (mathematisch positives) Moment. Der Vorzeichenwechsel folgt aus der Symmetrie.<br />

19.10.2011


Seite 40 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

9 VBA-Objekte<br />

Objekte oder Klassen im Sinne der OOP (objektorientierten Programmierung) werden in VBA<br />

mit Klassenmodul bezeichnet. Die Klassenbestandteile (siehe UML in Abschnitt C) bestehen<br />

aus den folgenden Komponenten.<br />

• Die Bezeichnung des Klassenmoduls ist die Klassenbezeichnung.<br />

• Globale Variablen eines Klassenmoduls sind die Klassenattribute.<br />

• Die Funktionen und Programme in einem Klassenmodul sind die Methoden der Klasse.<br />

Auf alle Mechanismen der Vererbung von Klassen (Generalisierung, Polymorphismus), die in<br />

den meisten Programmiersprachen der OOP implementiert werden, wird in VBA aus Sicherheitsgründen<br />

verzichtet.<br />

9.1 Konstruktor und Destruktor<br />

Jeder Klassenmodul hat die folgenden Methoden. 11<br />

• Der Konstruktor Class Initialize<br />

Diese Methode wird aufgerufen, wenn eine Instanz des Klassenmoduls mit dem new-<br />

Operator (set s = new Stab) erzeugt wird. Im Beispiel wird das Objekt Stab initialisiert.<br />

Es werden Fläche und E-Modul vorbelegt. Es werden die Instanzen der Knoten-<br />

Klassenmodul für die Stabenden erzeugt.<br />

Private Sub Class_Initialize()<br />

Set Ka = new Knoten<br />

Set Kb = new Knoten<br />

Fl = 0#<br />

Em = 210000#<br />

End Sub<br />

• Der Destruktor Class Terminate<br />

Wenn eine Instanz eines Klassenmoduls zerstört wird, d.h. aus dem Speicher entfernt<br />

wird, wird zunächst diese Methode aufgerufen, um dem Programm die automatisierte<br />

Möglichkeit zu bieten, Aufräumarbeiten auszuführen. Das Zerstören einer Instanz erfolgt<br />

mit dem nothing-Operator (set s = nothing).<br />

Im nachfolgenden Beispiel werden vor dem Entfernen eines Stab-Objekts dessen beide<br />

Knoten-Instanzen entfernt. 12<br />

Private Sub Class_Terminate()<br />

Set Ka = nothing<br />

Set Kb = nothing<br />

End Sub<br />

11 Die Beispiele dieses Abschnitts beziehen sich auf die Objekte Knoten und Stab des Abschnitts 9.4).<br />

12 Da in VBA nur dann ein Objekt vernichtet wird, wenn alle Verweise auf nothing gesetzt werden, können alle<br />

Knoten-Instanzen durch den dargestellten Destruktor vernichtet werden.<br />

E. Baeck


9. VBA-OBJEKTE Seite 41<br />

9.2 Vektoren und Matrizen<br />

Vektoren- und Matrizen können im Sinne der OOP<br />

als Klassenmodule implementiert werden. Abbildung<br />

35 zeigt hierfür ein UML-Klassendiagramm.<br />

Im Konstruktor (Class Initialize) werden Standard-<br />

Dimensionen gesetzt. Im Beispiel des Anhangs wird<br />

mit n = 3 das Feld des Vektors bzw. das Feld der<br />

Matrix x dimensioniert. Der Vektor wird als Einheitsvektor<br />

in x-Richtung initialisiert (1, 0, 0).<br />

Abbildung 35: Vektor- und Matrix-Objekte<br />

9.2.1 Methoden des Klassenmoduls Vektor<br />

Methode Anmerkung<br />

Laenge<br />

Norm<br />

Rot<br />

SP rod<br />

SetX<br />

GetX<br />

Xi<br />

List<br />

Berechnung und Rückgabe der Vektorlänge<br />

Normierung der Vektor-Instanz<br />

Multiplikation des Vektors mit einer Matrix-Instanz<br />

Skalare Multiplikation mit anderer Vektor-Instanz<br />

Belegen der Vektor-Elemente (Übergabe mit Feld)<br />

Lesen der Vektor-Elemente (Übergabe mit Feld)<br />

Lesen einer Vektor-Komponente<br />

Kontrolausgabe der Vektor-Attribute<br />

9.2.2 Methoden des Klassenmoduls Matrix<br />

Methode Anmerkung<br />

SetX<br />

GetX<br />

GetK<br />

List<br />

Belegen der Matrix-Elemente (Übergabe mit Feld)<br />

Lesen der Matrix-Elemente (Übergabe mit Feld)<br />

Lesen eines Matrixelements<br />

Kontrolausgabe der Matrix-Attribute<br />

19.10.2011


Seite 42 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

9.3 Die Containerklasse Collection<br />

Mit dem in VBA implementierten Klassenmodul Collection wird die Möglichkeit geschaffen, auf<br />

einfache Weise Instanzen von Klassenmodulen in Listen-Form abzuspeichern. 13 Die gespeicherte<br />

Instanz kann optional über den Index oder über einen freiwählbaren Schlüssel angesprochen<br />

werden. Die Collection bietet hierbei ein automatisches Speichermanagement, das jederzeit für<br />

ausreichenden Speicher sorgt.<br />

Die Collection bietet die foldenden Methoden. 14<br />

• Add<br />

Mit Add kann eine Instanz einer Klasse in die Liste übernommen werden.<br />

Parameter Anmerkung<br />

Item<br />

Key<br />

Before<br />

After<br />

Zeiger auf Instanz eines Objekts<br />

Objektbezeichnung der Instanz<br />

Objektbezeichnung für Einfügen vor<br />

Objektbezeichnung für Einfügen nach<br />

Beispiel:<br />

Das folgende Beispiel zeigt das Erzeugen zweier Instanzen des Klassenmoduls Knoten. Die<br />

Adressen der Instanzen werden in der Collection unter den Bezeichnungen Knoten 1 und<br />

Knoten 2 abgespeichert.<br />

dim Kn as Knoten<br />

set Kn = new Knoten<br />

Liste.Add item:= Kn key:="Knoten 1"<br />

set Kn = new Knoten<br />

Liste.Add item:= Kn key:="Knoten 2"<br />

• Item<br />

Mit der Methode Item wird die Adresse einer Instanz eines Klassenmoduls aus der Collection<br />

gelesen. Die Methode hat die folgenden Parameter.<br />

Parameter Anmerkung<br />

Index<br />

Index der zu lesenden Instanz oder<br />

dessen Bezeichnung (d.h. key), siehe Add-Methode.<br />

Beispiel:<br />

In nachfolgendem Beispiel wird aus der Collection der Bezeichnung Liste die Adresse der 2.<br />

Instanz gelesen. Hierfür kann optional auf das explizite Notieren der Methodenbezeichnung<br />

Item verzichtet werden (Variante 2). In der 3. Variante wird die Adresse der Instanz<br />

über deren Bezeichnung gelesen. In allen Varianten wird die gelesene Adresse der Objekt-<br />

Variablen Kn mit dem Operator Set zugewiesen. 15<br />

13 Die Beispiele dieses Abschnitts beziehen sich auf die Objekte Knoten und Stab des Abschnitts 9.4).<br />

14 Bedauerlich an der Implementierung der Collection ist, dass auf alle Fehlerprüfungen verzichtet wurde, d.h.<br />

es gibt keine Fehlerkenner in der Rückgabe. Wird z.B. auf ein nicht vorhandenes Element zugegriffen, stürzt das<br />

Programm ab, wenn nicht durch einen Fehlerhandler der Fehler abgefangen wird, was eine für diese Situation<br />

recht aufwendige Mimik erfordert.<br />

15 Kurioserweise wurde bei der Implementierung der Collection auf eine Inquire-Methode verzichtet, mit deren<br />

Hilfe die Existenz einer Instanz in der Collection ermittelt werden könnte.<br />

E. Baeck


9. VBA-OBJEKTE Seite 43<br />

dim Kn as Knoten<br />

set Kn = Liste.Item(2)<br />

set Kn = Liste(2)<br />

set Kn = Liste.Item("Knoten 2")<br />

• Remove<br />

Mit der Methode Remove wird eine in der Collection gespeicherte Instanz-Adresse<br />

gelöscht. Es wird nur der Eintrag der Adresse gelöscht, nicht die Instanz selbst. 16<br />

Parameter Anmerkung<br />

Index<br />

Index der zu löschenden Instanz oder<br />

dessen Bezeichnung (d.h. key), siehe Add-Methode.<br />

Beispiel:<br />

In nachfolgendem Beispiel wird zunächst der 1. Eintrag aus der Collection entfern. Anschließend<br />

wird eine Instanz mit der Bezeichnung Knoten 2 entfernt.<br />

Liste.Remove(1)<br />

Liste.Remove("Knoten 2")<br />

• Count<br />

Mit der Methode Count wird die Anzahl der in der Collection gespeicherten Instanz-<br />

Adressen zurückgegeben.<br />

Beispiel:<br />

In nachfolgendem Beispiel werden in einer Schleife alle Einträge aus einer Collection entfernt.<br />

Dies erfolgt durch n-faches Löschen des ersten Eintrages, da nach Löschen eines<br />

Eintrages die Indizierung lückenlos aktualisiert wird, d.h. der vormals 2. Eintrag der Liste<br />

rückt auf die 1. Stelle vor, nachdem der 1. Eintrag entfernt wurde. Die Anzahl der<br />

gespeicherten Einträge n liefert die Methode Count.<br />

n = Liste.Count<br />

for i=1 to n<br />

Liste.Remove(1)<br />

next<br />

16 Eine Instanz wird dann gelöscht, wenn allen Objektvariablen, die auf diese Instanz verweisen, der Wert<br />

nothing zugewiesen wird.<br />

19.10.2011


Seite 44 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

9.4 Datenstruktur eines Stabwerks<br />

Ein Stabwerk besteht aus n-Stäben. Ein Stab hat die Attribute<br />

E-Modul und Querschnittsfläche (beide double).<br />

Die Geometrie eines Stabes wird beschrieben durch den<br />

Start- und den Endknoten. Als Attribut erhält eine Stab-<br />

Instanz den Verweis (Objektvariable) auf zwei Knoten-<br />

Instanzen, d.h. eine Knoten-Instanz wird i.A. von mehreren<br />

Stab-Instanzen referenziert.<br />

Abbildung 36: Datenstruktur eines<br />

Stabwerks<br />

Der in Abbildung 37 dargestellte<br />

Rahmen ist auf der Grundlage des<br />

in Abbilung 36 dargestellten UML-<br />

Diagrammes zu implementieren. Die<br />

Daten des Rahmens sind aus der in Abbildung<br />

38 dargestellten Tabelle auszulesen.<br />

Nach Aufbau der Datenstruktur<br />

sind die Rahmendaten mit der Funktion<br />

List im Ausgabebereich der Tabelle<br />

anzulisten.<br />

Die Knotendaten sind in der Collection<br />

KListe, die Stäbe in der Collection SListe<br />

abzuspeichern.<br />

Abbildung 37: Rahmenbeispiel<br />

E. Baeck


9. VBA-OBJEKTE Seite 45<br />

9.4.1 Die Oberfläche<br />

Mit der Klassen-Methode Verschieben<br />

ist der Rahmen mit einer zweiten Ereignisfunktion<br />

um den vorgegebenen Verschiebungsvektor<br />

zu verschieben. Das<br />

Ergebnis der Verschiebung ist erneut in<br />

der Tabelle auszugeben.<br />

Zudem ist mit der Stab-Methode Laenge<br />

die Stablänge zu ermitteln und diese<br />

in der entsprechenden Tabellenspalte<br />

einzutragen.<br />

9.4.2 Methoden des Punktes<br />

Abbildung 38: Eingabetabelle<br />

Für das Punkt-Objekt sind die folgenden Methoden zu implementieren.<br />

• Verschieben<br />

Auf die Koordinaten des Knotens wird der Verschiebungsvektor v aufaddiert.<br />

⎛ ⎞ ⎛ ⎞ ⎛ ⎞<br />

⎝ x ⎠ ⇐ ⎝ x ⎠ + ⎝ v x<br />

⎠ (24)<br />

y y v y<br />

• Drehen<br />

Auf den Ortsvektor des Knotens wird die Drehmatrix zum Winkel ϕ aufmultipliziert. 17<br />

⎛ ⎞ ⎛<br />

⎞ ⎛ ⎞<br />

⎝ x ⎠ ⇐ ⎝ + cos(ϕ) − sin(ϕ) ⎠ · ⎝ x ⎠ (25)<br />

y + sin(ϕ) + cos(ϕ) y<br />

• Listen<br />

Die Ausgabe der Knotenattribute x und y in ein Tabellenfeld erfolgt zweckmäßig unter<br />

Vorgabe des Tabellenadressenursprungs (Spalten- und Zeilennummer für die Funktion<br />

Cells).<br />

9.4.3 Methoden des Stabes<br />

Für den Stab sind die folgenden Methoden zu implementieren.<br />

• Länge<br />

l = √ (x a − x b ) 2 + (y a − y b ) 2 (26)<br />

• Verschieben<br />

Es sind nach (24) beide Knoten des Stabes zu verschieben.<br />

17 Generell sind die Winkel in Winkelfunktionen der Programmiersprachen in rad einzusetzen. Die Umrechnung<br />

von ◦ in rad erfolgt unter Ausnutzung der Rechengenauigkeit mit der Skalierung atan(1)/45 ◦ .<br />

19.10.2011


Seite 46 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

• Drehen<br />

Es sind nach (25) beide Knoten des Stabes zu drehen.<br />

• Listen<br />

Die Ausgabe der Stab- und Knotenattribute in eine Tabelle erfolgt zweckmäßig unter Vorgabe<br />

des Tabellenadressenursprungs (Spalten- und Zeilennummer für die Funktion Cells).<br />

9.5 2-fach verkettete lineare Listen<br />

Lineare Listen können als rekursive Datenstrukturen<br />

implementiert werden. Ein Listen-Objekt (hier VNode)<br />

enthält bei 2-facher Verkettung (als Attribute) einen Zeiger<br />

auf das vorhergehende (hier prv)und einen Zeiger auf<br />

das nachfolgende Listen-Objekt (hier nxt). Mit dieser Verkettung<br />

ist es bei vorgegebenem Listen-Objekt möglich,<br />

über die Verkettung einerseits bis zum ersten Listen-<br />

Objekt zurück, andererseits zum letzten Listen-Objekt<br />

vorwärts zu laufen.<br />

Üblicherweise wird die verkettete Liste durch ein spezielles<br />

Objekt eröffnet bzw. abgeschlossen. Diese beiden Objekte<br />

können in einer Listen-Klasse als Attribute geführt werden<br />

(hier VListe), um sowohl über das erste als auch über das<br />

letzte Listen-Objekt in eine Listen-Iteration einzusteigen.<br />

Abbildung 39:<br />

Objekte einer verketteten Liste<br />

Ferner kann über diese Attribute ein neues Objekt sowohl als erstes als auch als letztes Objekt<br />

in die Liste eingefügt werden.<br />

Mit Ausnahme der Start- und Abschluss-Objekte der Liste können Listen-Objekten über einen<br />

Datenzeiger (hier dat) Datenobjekte referenzieren, d.h. sie zeigen auf die Instanzen (beliebiger<br />

Objekte), die in der Liste gespeichert werden sollen.<br />

Die zu implementierende Liste VListe erhält die folgenden für Listen üblichen Methoden. 18<br />

Methode<br />

AddF irst<br />

AddLast<br />

GetF irst<br />

GetNext<br />

GetLast<br />

GetP rev<br />

Insert<br />

Remove<br />

RemoveAll<br />

Anmerkung<br />

Fügt ein Objekt an erster Stelle in die Liste ein.<br />

Fügt ein Objekt an letzter Stelle in die Liste ein.<br />

Liefert einen Zeiger auf das erste Listen-Objekt.<br />

Liefert einen Zeiger auf das nächste Listen-Objekt.<br />

Liefert einen Zeiger auf das letzte Listen-Objekt.<br />

Liefert einen Zeiger auf das vorhergehende Listen-Objekt.<br />

Fügt ein Objekt in die Liste vor einem vorgegebenem ein.<br />

Entfernt ein vorgegebenes Objekt aus der Liste.<br />

Entfernt alle Objekte aus der Liste.<br />

18 Da es z.Z. in VBA nicht möglich ist einen Null-Zeiger abzufragen (nothing), erhält der VKnoten das Attribut<br />

Ken, das die folgenden Werte annehmen kann. Ken=0: Datenknoten, Ken=1: Startknoten und Ken=2: Endknoten.<br />

E. Baeck


9. VBA-OBJEKTE Seite 47<br />

9.5.1 Beispiel einer 2-fach verketten Liste<br />

In Abbildung 40 zeigt die Implementierung<br />

einer 2-fach verketteten Liste, die 3<br />

Zeiger auf Instanzen des Klassenmoduls<br />

Stab enthält. Der 1. Knoten dient als<br />

Einstiegsknoten am Listenanfang (ken<br />

= 1 ), der letzte Knoten dient als Einstiegsknoten<br />

am Listenende (ken=2 ).<br />

Abbildung 40: Verkettete Liste mit 3 Stab-Instanzen<br />

Der Objektzeiger nxt enthält die Adresse des jeweils nächsten Knotens der Liste. Der Objektzeiger<br />

prv enthält die Adresse des jeweils vorhergehenden Knoten der Liste. Der Objektzeiger<br />

dat enthält für Datenknoten Zeiger auf die gespeicherten Datenobjekte (hier Stab-Instanzen).<br />

9.5.2 Einfügen eines Datenknotens<br />

Das Einfügen eines Datenknotens in eine 2-fach verkettete Liste erfordert die Umordnung der<br />

Knotenzeiger in zwei Schritten. Zum einen sind die Knotenzeiger des neuen Knotens zu belegen.<br />

Zum andere sind die Knotenzeiger der bereits gespeicherten Knoten im Umfeld des Einfügens<br />

an D anzupassen.<br />

Abbildung 41 zeigt das Einfügen eines<br />

Knotens in eine 2-fach verkettete Liste.<br />

Die Liste enthält bereits die Knoten mit<br />

den Instanzen Stab1 und Stab3. Es soll<br />

die Instanz Stab2 zwischen die beiden<br />

genannen Instanzen eingefügt werden.<br />

In der Ausgangssituation sind Stab1<br />

und Stab3 mit den blauen Pfeilen verkettet.<br />

Der nxt-Zeiger von Stab1 wird<br />

Abbildung 41: Einfügen bzw. Entfernen eines Knotens<br />

auf auf Stab2 gesetzt. In gleicher Weise wird der prv-Zeiger von Stab3 auf Stab2 gerichtet.<br />

Zusätzlich wird der nxt-Zeiger von Stab2 auf Stab3 und der prv-Zeiger von Stab2 auf Stab1<br />

erzeugt. Nach Einfügen von Stab2 werden die Knoten im Umfeld von Stab2 durch die roten<br />

Pfeile verkettet.<br />

9.5.3 Entfernen eines Datenknotens<br />

Das Entfernen eines Datenknotens aus einer 2-fach verkettete Liste erfordert die Umordnung der<br />

Knotenzeiger in zwei Schritten. Zum einen sind die Knotenzeiger des zu löschenden Knotens zu<br />

entfernen. Zum andere sind die Knoten vor und nach dem zu entfernenden Knoten mit einander<br />

zu verketten.<br />

Abbildung 41 zeigt das Löschen des Datenknotens von Stab2. Zunächst ist Stab2 noch eingebunden<br />

(blaue Pfeile). Es ist der nxt-Zeiger von Stab1 auf Stab3 zu setzen. Der prv-Zeiger von Stab3<br />

ist auf Stab1 zu setzen. Beim Entfernen eines Knotens ist darauf zu achten, dass gelöscht wird,<br />

bevor die Zeiger auf ihn entfernt werden, da eine Instanz ohne Zeiger nicht mehr ansprechbar<br />

ist.<br />

19.10.2011


Seite 48 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

9.5.4 Iteratoren<br />

Der Iterator ist ein Zeiger mit dessen Hilfe eine Liste durchlaufen wird. Startpunkt einer Iteration<br />

ist bei einfach verketteten Listen der Kopf der Liste. Bei zweifach verketteten Listen kann zudem<br />

der das Ende der Liste als Startpunkt der Iteration gewählt werden. Die Iteration erfolgt in<br />

diesem Fall rückwärts über die Rückwärtsverkettung.<br />

Gängigerweise wird eine Iteration durch das Holen des Startzeigers initiiert. Darauf folgend wird<br />

in einer Schleife durch Holen des jeweils nächsten Zeigers die Iteration ausgeführt.<br />

Eine Listeniteration kann somit wie folgt im Pseudocode formuliert werden.<br />

• Hole 1. Zeiger (Kopfzeiger oder Endezeiger)<br />

• Hole nächsten Zeiger bis das Iterationsende erreicht ist. Der nächste Zeiger ist von der<br />

Iterationsrichtung abhängig.<br />

E. Baeck


10. REKURSIVE ALGORITHMEN Seite 49<br />

10 Rekursive Algorithmen<br />

Ein Algorithmus ist dann rekursiv, wenn er sich selbst enthält oder durch sich selbst teilweise<br />

definiert wird.<br />

Einer der bekanntesten und einfachsten rekursiven Algorithmen ist gegeben durch die Berechnung<br />

der Fakultät (siehe auch Abschnitt 5.1).<br />

⎧<br />

⎨ 1<br />

n! =<br />

⎩ (n − 1)!<br />

:n = 0<br />

: sonst<br />

(27)<br />

Wie im Fall der Fakultät (27) bekannt, ist die rekursive Formulierung des Problems im Gegensatz<br />

zur direkten (2) nicht wirtschaftlich.<br />

10.1 Quick-Sort<br />

Das Sortierverfahren QuickSort arbeitet nach der Devise Herrsche und <strong>Teil</strong>e. Der Algorithmus<br />

geht zurück auf C.A.R Hoare 1960.<br />

Das zu sortierende Feld wird zerlegt<br />

in zwei <strong>Teil</strong>felder. Die <strong>Teil</strong>ung erfolgt<br />

durch Wahl eines beliebigen Elements<br />

P. Die Elemente der <strong>Teil</strong>felder werden<br />

so umsortiert, dass im einen <strong>Teil</strong>feild alle<br />

Elemente kleiner P im anderen <strong>Teil</strong>feld<br />

alle Elemente größer P einsortiert<br />

werden.<br />

Die auf diese Weise generierten <strong>Teil</strong>felder<br />

werden erneut in zwei <strong>Teil</strong>felder<br />

durch Wahl eines jeweils neuen <strong>Teil</strong>erelements<br />

P zerlegt. Die Zerlegung eines<br />

<strong>Teil</strong>feldes wird solange fort gesetzt, bis<br />

sich nur noch ein Element im <strong>Teil</strong>feld<br />

befindet.<br />

Reduziert sich die Anzahl der Elemente<br />

alle <strong>Teil</strong>felder auf ein Element, ist die<br />

Sortierung abgeschlossen.<br />

In Abbildung 42 wird das Wort SOR-<br />

TIERANGS alphabetisch sortiert. Das<br />

berandete Feld am rechten Intervallrand<br />

teilt das Intervall. Zum einen läuft<br />

Abbildung 42: QuckSort: SORTIERANGST<br />

ein Zeiger vom linken Intervallrand nach rechts und sucht das erste Zeichen, das größer oder<br />

gleich dem <strong>Teil</strong>er ist, dieses wird türkis eingefärbt. Andererseits läuft ein zweiter Zeiger von rechts<br />

nach links und sucht ein Zeichen, das kleiner oder gleich dem <strong>Teil</strong>er ist. Dieses Zeichen wird gelb<br />

19.10.2011


Seite 50 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

dargestellt. Gelbes und türkises Zeichen werden getauscht. Daraufhin wird die Suche von beiden<br />

Seiten fortgesetzt. Gefundene Zeichen werden getauscht. Dies wird solange fort geführt, bis sich<br />

die beiden Zeiger treffen. Daraufhin wird das Zeichen, auf das der linksseitige Zeiger verweist mit<br />

dem <strong>Teil</strong>erzeichen getauscht. Das <strong>Teil</strong>erzeichen erhält damit seine endgültige Position. In Abbildung<br />

42 werden gefundene Intervallgrenzen durch einen vertikalen roten Strich gekennzeichnet.<br />

Links- bzw. rechsseitiges Intervall (ohne das <strong>Teil</strong>erzeichen) werden erneut nach beschriebener<br />

Art umsortiert. Die Zerlegung in <strong>Teil</strong>intervalle wird solange fort gesetzt, bis die <strong>Teil</strong>intervallen<br />

nur noch ein Zeichen enthalten. Vertauschte Zeichen werden hellgrau gekennzeichnet. Zeichen,<br />

die bereits ihre endgültige Position erhalten haben, werden dunkelgrau gekennzeichnet.<br />

E. Baeck


A. DREIMOMENTENGLEICHUNG, CLAPEYRON Seite 51<br />

A<br />

Dreimomentengleichung, Clapeyron<br />

In diesem Abschnitt wird das Verfahren der Dreimomentengleichung oder Verfahren nach Clapeyron<br />

dargestellt (siehe auch [1]).<br />

A.1 Das Verfahren<br />

Mit der Dreimomentengleichung<br />

werden unter folgender Einschränkungen<br />

die Stützmomente<br />

mehrfeldriger Durchlaufträger<br />

berechnet.<br />

Abbildung 43: Durchlaufträger mit 8 Feldern<br />

Voraussetzungen:<br />

• Stützpunkte sind starr gelagert.<br />

• Auftretende Lasten wirken senkrecht zur Stabachse.<br />

• Die Biegesteifigkeit EI ist feldweise konstant.<br />

Für 2-feldrigen Abschnitt gilt (mit m ∈ [b, h] in Abbildung 43):<br />

M l · l l + 2 · M m · (l l + l r ) + M r · l r = −R l · l l − L r · l r (28)<br />

mit: M l , M m , M r ,<br />

l l , l r ,<br />

R l , L r ,<br />

dem linken, mittleren und rechten Stützmoment<br />

der effektiven linken und rechten Feldweite<br />

dem linken und rechten Belastungsglied (rechte Seite)<br />

Die effektiven Feldweiten l l und l r sind bei unterschiedlichen Steifigkeiten auf ein Vergleichsträgheitsmoment<br />

I c zu beziehen, d.h. l l = Ic<br />

I l<br />

· l l,0 mit l l,0 , der realen Feldweite.<br />

A.2 Herleitung<br />

Vorgehen:<br />

Als statisch bestimmtes Grundsystem<br />

wird ein durch Gelenke<br />

entkoppelter Mehrfeldträger<br />

gewählt. Als statisch Unbestimmte<br />

werden die Stützmo-<br />

Abbildung 44: Statisch Unbestimmte an Zwischenlagern<br />

mente in den Mittenlagern gewählt (Stützmomente an Randlagern verschwinden). Durch<br />

Ansetzen dieser Momente (als äußere Lasten) werden die Verdrehungen ϕ in den Gelenken in<br />

der Weise beeinflußt, dass sich in den Gelenken knicklose Übergänge (C1 stetig) ergeben.<br />

19.10.2011


Seite 52 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

Für den in Abbildung 43 dargestellten Durchlaufträger ergeben sich für die Verdrehwinkel an<br />

den Lagern 1-7 bei Wahl der Stützmomente als statische Unbestimmte die folgenden Verträglichkeitsbedingungen<br />

(knickfreier Übergang zwischen den Feldern!). Aus den Verträglichkeitsbedinungen<br />

folgt ein lineares Gleichungssystem für den gesuchten Momenten-Vektor X ⃗ (X 1 bis<br />

X 7 ).<br />

Gl. X 1 X 2 X 3 X 4 X 5 X 6 X 7<br />

1 δ 11 δ 12 0 0 0 0 0 δ 10 = 0<br />

2 δ 21 δ 22 δ 23 0 0 0 0 δ 20 = 0<br />

3 0 δ 32 δ 33 δ 34 0 0 0 δ 30 = 0<br />

4 0 0 δ 43 δ 44 δ 45 0 0 δ 40 = 0<br />

5 0 0 0 δ 54 δ 55 δ 56 0 δ 50 = 0<br />

6 0 0 0 0 δ 65 δ 66 δ 67 δ 60 = 0<br />

7 0 0 0 0 0 δ 76 δ 77 δ 70 = 0<br />

Tabelle 4: Gleichungssystem zur Ermittlung der Momente X 1 bis X 7<br />

Da die Momentenfläche eines angesetzten 1-<br />

Momente am Lager i jeweils dreieckförmig<br />

zu den benachbarten Lagern i − 1 und i + 1<br />

ausläuft, ergeben sich bei der Integration der<br />

Eigenspannungszustände δ ij nur dann nicht<br />

verschwindende Werte wenn |i − j| ≤ 1.<br />

In Abbildung 45 werden die Momentenflächen<br />

für die ersten 5 Lager dargestellt. Es<br />

ist zu erkennen, dass jeweils zwei zur Mittelachse<br />

symmetrische Dreieckflächen benachbarter<br />

Lagerpunkte zu überlagern sind.<br />

δ ij = ∑ s<br />

∫<br />

1<br />

E · I · M i · M j · dx =<br />

Abbildung 45: Statisch Unbestimmte an Zwischenlagern<br />

l i<br />

6 · E · I , für i > j<br />

δ ii = ∑ s<br />

∫<br />

l i+1<br />

=<br />

6 · E · I , für i < j<br />

1<br />

E · I · M i 2 · dx = l i + l i+1<br />

, für Diagonalterme i = j (29)<br />

3 · E · I<br />

Aus Gleichung 29 und Tabelle 4 folgt:<br />

l i<br />

X i−1 ·<br />

6EI + X i · li + l i+1<br />

+ X i+1 · li+1<br />

3EI<br />

6EI + δ i0 = 0<br />

X i−1 · l i + 2 · X i · (l i + l i+1 ) + X i+1 · l i+1 = −δ i0 · 6 · E · I (30)<br />

E. Baeck


A. DREIMOMENTENGLEICHUNG, CLAPEYRON Seite 53<br />

Die rechte Seite aus Gleichung 30 kann wie folgt umgeformt werden.<br />

δ i0 = ϕ i,r − ϕ i,l<br />

6 · E · I · ϕ i,l = −R i · l i<br />

6 · E · I · ϕ i,r = L i+1 · l i+1 (31)<br />

mit den Stabenddrehwinkeln 19 ϕ i,r und ϕ i,l .<br />

Aus den Gleichungen 30 und 31 folgt die Formel von Clapeyron (siehe Gleichung 28).<br />

Es gibt spezielle Integrationstabellen (siehe z.B. [1] Seite 65) für die die Belastungsglieder L r<br />

und R l der Dreimomentengleichung (siehe Gleichung 28). Diese sind ebenso aus der allgemeinen<br />

Überlagerung der Belastungsmomentenfläche mit den jeweiligen Dreiecks.Momentenflächen des<br />

Einheitsmomentes am betrachteten Lagerpunkt zu erhalten.<br />

δ i0 = ∑ ∑<br />

∫<br />

1<br />

E · I · (M i + M i+1 ) · M 0,l · dx (32)<br />

s<br />

l<br />

mit M i , der linksseitigen, und M i+1 , der rechtsseitigen Momentenfläche am Lager i. M 0,l ist die<br />

Momentenfläche aus einer Belastung l. Bei der Berechnung von δ i0 sind die Momentenflächen<br />

aller l Belastungen zu berücksichtigen.<br />

19 Die Winkel ϕ sind Endwinkel eines Balkens auf zwei Stützen. Dies entspricht dem statisch bestimmten Grundsystems<br />

des Durchlaufträgers<br />

19.10.2011


Seite 54 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

B<br />

Das ER-Modell<br />

Das ER-Modell (Entity-Relationship-<br />

Modell) oder Gegenstands-<br />

Beziehungs-Modell von Peter<br />

Pin-Shan Chen (1976) dient zur<br />

Beschreibung einer Datenstruktur<br />

in einem Modell bestehend aus graphischen<br />

Symbolen (siehe Abbildung<br />

46). Eine ähnliche Visualisierung<br />

der Abhängigkeiten der Objekte des<br />

ER-Modells ist auch in der UML<br />

(Unified Modelling Language) zu finden.<br />

Abbildung 46: ER-Modell nach P.P. Chen<br />

• Entität (Entities):<br />

Objekt der Wirklichkeit, materiell oder abstrakt (zum Beispiel Lastfall oder Feld).<br />

• Beziehung (Relationships):<br />

Semantische Beziehung zwischen zwei Objekten (zum Beispiel Lastfall enthält Lasten)<br />

• Attribut:<br />

Elementarinformation einer Entität oder einer Beziehung (z.B. hat eine Last eine Ordinate<br />

q, ein Feld hat eine Länge l).<br />

• Kardinalität:<br />

Mögliche Anzahl der an einer Beziehung beteiligten Entitäten (z.B. 1 Lastfall enthält 20<br />

Lasten). Die Kardinalität wird optional am Ende einer Beziehungslinie angemerkt.<br />

E. Baeck


C. UML-ASPEKTE Seite 55<br />

C<br />

UML-Aspekte<br />

Die Unified Modeling Language ist eine überwiegend graphische Modellierungssprache für objektorientierte<br />

Entwicklungsansätze. Die UML geht zurück auf Booch, Rumbaugh und Jacobson.<br />

An dieser Stelle werden nur die Klassendiagramme erläutert, die als Erweiterung der ER-<br />

Diagramme betrachtet werden können.<br />

Ein Klassendiagramm stellt die Beziehungen zwischen den einzelnen Klassen (Objekten) des<br />

Systems dar. Das Diagramm besteht aus Klassen, die durch Assoziation und/oder Generalisierung<br />

miteinander verbunden sind. Eine Klasse wird als Rechteck mit den 3 folgenden Bereichen<br />

dargestellt.<br />

• Der obere Bereich enthält den Namen der Klasse.<br />

• Der mittlere Bereich enthält die Liste der Attribute, d.h. die Daten, die eine Klasse umfaßt.<br />

• Der untere Bereich enthält die Methoden der Klasse (Klassen-Funktione).<br />

Assoziationen entsprechen den Relationen<br />

des ER-Modells. Sie werden<br />

durch Kanten dargestellt an deren Enden<br />

die Quantitäten vermerkt werden.<br />

Generalisierungen werden mit einer<br />

Richtung vorgegeben. 20<br />

Beispiel:<br />

Ein Beispiel objektorientierter Modellierung<br />

sind z.B. Geometrieobjekte eines<br />

CAD-Systems. Das Basis-Objekt<br />

der Modellierung ist das Geo-Objekt<br />

(Geometrieobjekt), es liefert die folgenden<br />

Standarddaten und Grundfunktionalität<br />

aller spezialisierten Objekte.<br />

Abbildung 47: UML-Klassendiagramm<br />

Standarddaten<br />

Grundfunktionalität<br />

: Farbe, Layer, Linientyp, Strickstärke.<br />

: Löschen, Verschieben, Rotieren, Spiegeln.<br />

Eine Generalisierung des Geo-Objektes wäre z.B. das Punkt-Objekt. Es geht aus dem Geo-<br />

Objekt hervor und beerbt dessen Attribute und Funktionen. Zudem erhält das Objekt Punkt die<br />

Attribute x, y und z, die die Lage des Punktes im Raum beschreiben. Die Funktionen der Basisklasse<br />

Geo werden überschrieben mit speziellen Funktionen des Punktes. So ist im Gegensatz<br />

zur Linie beispielsweise beim Verschieben eines Punktes nur ein Ortsvektor zu variieren.<br />

20 Generalisierungen wurden in VB nicht vorgesehen. In der aktuellen VB-Version wurde die Generalisierung<br />

implementiert. In VBA unter EXCEL wurde bislang auf Generalisierungen verzichtet.<br />

19.10.2011


Seite 56 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

D<br />

Gauß’scher Algorithmus und Cholesky-Zerlegung<br />

In diesem Abschnitt wird der Gauß’sche Algorithmus zur Lösung des linearen Gleichungssystems<br />

erläutert. Bei den hier betrachteten Problemen ist das folgende symmetrisch-definites<br />

Gleichungssystem zu lösen 2122 .<br />

A · x + b = 0 , mit A T = A und A positiv definit (33)<br />

In Komponentendarstellung erhält man:<br />

⎛<br />

⎞ ⎛<br />

a 1,1 a 1,2 . . . a 1,n<br />

a 2,1 a 2,2 . . . a 2,n<br />

.<br />

⎜ . . .. ·<br />

. ⎟ ⎜<br />

⎝<br />

⎠ ⎝<br />

a n,1 a n,2 . . . a n,n<br />

⎞ ⎛<br />

x 1<br />

x 2<br />

=<br />

. . . ⎟ ⎜<br />

⎠ ⎝<br />

x n<br />

b 1<br />

b 2<br />

. . .<br />

b n<br />

⎞<br />

⎟<br />

⎠<br />

(34)<br />

oder<br />

n∑<br />

a ik · x k + b i = 0 (i = 1, 2, ..., n) (35)<br />

k=1<br />

Zur Lösung der Dreimomentengleichungen (Clapeyron) wären die Einträge der Matrix A die<br />

Längengewichte der Momente. Der Vektor x wäre der Vektor der gesuchten Stützmomente, der<br />

Vektor b, der Vektor der Belastungsglieder.<br />

D.1 Der Gauß’sche Algorithmus<br />

In einem ersten Schritt eliminiert man die erste Unbekannte x 1 aus den Gleichungen 2 bis n, in<br />

dem das (a i1 /a 11 )-fache der ersten Zeile von der i-ten Zeile subtrahiert wird. Damit erhält man<br />

ein reduziertes Gleichungssystem für die Unbekannten x 2 bis x n .<br />

mit<br />

n∑<br />

k=2<br />

a (1)<br />

ik · x k + b (1)<br />

i<br />

= 0 (i = 2, 3, ..., n) (36)<br />

a (1)<br />

ik<br />

= a ik − a i1 · a 1k<br />

a 11<br />

(i, k = 2, 3, ..., n) (37)<br />

b (1)<br />

i<br />

= b i − a i1 · b 1<br />

a 11<br />

(i = 2, 3, ..., n) (38)<br />

es werden die folgenden l-Faktoren eingeführt<br />

l i1 = a i1<br />

a 11<br />

(i = 2, 3, ..., n) (39)<br />

Unter Berücksichtigung von (39) folgt aus (37) und (38) 23<br />

a (1)<br />

ik<br />

= a ik − l i1 · a k1 (40)<br />

b (1)<br />

i<br />

= b i − l i1 · b 1 (i = 2, 3, ..., n; k = 2, 3, ..., i) (41)<br />

21 Weiterführende Erläuterungen und Algorithmen siehe [2].<br />

22 Für eine transponierte Matrix A T gilt: A T i,j = A j,i .<br />

23 Die l i1 können erst nach Abschluss des Reduktionsschrittes in den Speicher der a i1 geschrieben werden.<br />

E. Baeck


D. GAUß’SCHER ALGORITHMUS UND CHOLESKY-ZERLEGUNG Seite 57<br />

In (40) und (41) wurde die Symmetrie der Matrix A berücksichtigt. Zum einen läuft der Index<br />

k nicht mehr bis n, sondern nur noch bis i, d.h. bis zur Diagonalen der Matrix. Zum zweiten<br />

wurde in (40) a 1k durch a k1 ersetzt. Damit kann auf die Matrixeinträge des oberen Dreiecks<br />

verzichtet werden.<br />

Wird die erste Gleichung aus (35) durch a 11 dividiert, so folgt mit (39) die Bestimmungsgleichung<br />

für die Unbekannte x 1 . 24<br />

x 1 = −<br />

n∑<br />

k=2<br />

l k1 · x k − c 1 mit c 1 = b 1<br />

a 11<br />

(42)<br />

Mit dem reduzierten Gleichungssystem der Stufe (1) (Bestimmungsgleichungen für x 2 bis x n<br />

(36)), folgen in analoger Weise die Größen des reduzierten Gleichungssystems der Stufe (2).<br />

Die l-Faktoren ergeben sich zu<br />

l i2 = a(1) i2<br />

a (1)<br />

22<br />

(i = 3, 4, ..., n) (43)<br />

die Koeffizienten der zweiten Stufe ergeben sich zu<br />

a (2)<br />

ik<br />

= a (1)<br />

ik − l i2 · a (1)<br />

k2<br />

(44)<br />

b (2)<br />

i<br />

= b (1)<br />

i<br />

− l i2 · b 2 (i = 2, 3, ..., n; k = 2, 3, ..., i) (45)<br />

und die Bestimmungsgleichung für die Unbekannte x 2 ergibt sich zu<br />

n∑<br />

x 2 = − l k2 · x k − c 2<br />

k=3<br />

mit c 2 = b(1) 2<br />

a (1)<br />

22<br />

(46)<br />

Bei konsequenter Fortführung dieser Reduktion folgt nach n − 1 Schritten die Bestimmungsgleichung<br />

der letzten Unbekannten x n zu<br />

a (n−1)<br />

nn<br />

· x n + b (n−1)<br />

n = 0 (47)<br />

und somit folgt für die letzte Unbekannte x n<br />

x n = −c n<br />

mit c n = b(n−1) n<br />

a (n−1)<br />

nn<br />

(48)<br />

Die Berechnung aller Unbekannten x 1 bis x n erfolgt somit rekursiv, d.h. zur Berechnung der<br />

1. Unbekannten ist die Lösung der 2. erforderlich, zur Berechnung der 2. die 3. usw.. Nach<br />

vollständiger Reduktion des Gleichungssystems (35) zu (48), können sozusagen rückwärts,<br />

deshalb Rückwärtseinsetzen, alle Unbekannten x n−1 , x n−2 bis x 1 ermittelt werden.<br />

24 Die c i Werte werden in den Speicher der b i-Werte geschrieben.<br />

19.10.2011


Seite 58 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

D.2 Interpretation des Gauß’schen Algorithmuses als Dreieckszerlegung<br />

Aus den Gleichungen des Abschnitts D.1 folgen die Lösung des linearen Gleichungssystems<br />

für eine Inhomogenität oder rechte Seite, d.h. einen Vektor b. Da i.A. mehrere Lastfälle zur<br />

Berechnung vorliegen, müßte nach dem besprochenen Algorithmus für jeden Lastfall individuell<br />

eine Lösung berechnet werden.<br />

Mit der Interpretation des Gauß’schen Algorithmuses als Zerlegung einer Matrix A in eine<br />

Linksdreiecksmatrix L mit 1-Werten auf der Diagonalen und eine Rechtsdreiecksmatrix R läßt<br />

sich eine Berechnungsvorschrift ableiten, die den Lösungsalgorithmus in drei Schritte aufspaltet,<br />

wobei der aufwendigste erste Schritt unabhängig von der rechten Seite, d.h. unabhängig vom<br />

Lastvektor durchgeführt werden kann.<br />

⎡<br />

⎤ ⎡<br />

⎤ ⎡<br />

⎤<br />

1 0 0 0 a 11 a 12 a 13 a 14<br />

a 11 a 12 a 13 a 14<br />

l 21 1 0 0<br />

0 a (1)<br />

·<br />

22 a (1)<br />

23 a (1)<br />

24<br />

a ⎢ l<br />

⎣ 31 l 32 1 0 ⎥ ⎢ 0 0 a (2)<br />

⎦ ⎣<br />

33 a (2)<br />

=<br />

21 a 22 a 23 a 24<br />

34<br />

⎥ ⎢ a<br />

⎦ ⎣ 31 a 32 a 33 a 34 ⎥<br />

⎦<br />

l 41 l 42 l 43 1 0 0 0 a (3)<br />

44<br />

a 41 a 42 a 43 a 44<br />

L · R = A<br />

(49)<br />

Die Beziehung (49) 25 läßt sich elementar z.B. durch (44) im Fall des ersten reduzierten Gleichungssystems<br />

zeigen.<br />

Die Rechtsdreiecksmatrix R läßt sich auf die Linksdreiecksmatrix L in folgender Beziehung<br />

zurück führen.<br />

R =<br />

=<br />

⎡<br />

a 11 a 12 a 13 a 14<br />

0 a (1)<br />

22 a (1)<br />

23 a (1)<br />

24<br />

⎢ 0 0 a (2)<br />

⎣<br />

33 a (2)<br />

34<br />

0<br />

⎡<br />

0 0 a (3)<br />

44<br />

a 11 0 0 0<br />

⎢<br />

⎣<br />

= D · L T<br />

0 a (1)<br />

22 0 0<br />

0 0 a (2)<br />

33 0<br />

0 0 0 a (3)<br />

44<br />

⎤<br />

⎥<br />

⎦<br />

⎤ ⎡<br />

⎤<br />

1 l 21 l 31 l 41<br />

0 1 l ·<br />

32 l 42<br />

⎥ ⎢ 0 0 1 l<br />

⎦ ⎣<br />

43 ⎥<br />

⎦<br />

0 0 0 1<br />

(50)<br />

Aus (49) und (50) folgt die Gleichung der Dreieckszerlegung nach Gauß.<br />

A = L · D · L T (51)<br />

Damit folgt für das lineare Gleichungssystem (34)<br />

L · D · L T x + b = 0 (52)<br />

25 Zur Erläuterung der matriziellen Zusammenhänge wird der Fall n = 4 in Komponentenform dargestellt. Die<br />

Verallgemeinerung auf beliebige Dimension erfolgt entsprechend.<br />

E. Baeck


D. GAUß’SCHER ALGORITHMUS UND CHOLESKY-ZERLEGUNG Seite 59<br />

Zur Bestimmung der Unbekannten wird zunächst der Hilfsvektor y wie folgt eingeführt 26 .<br />

y = −D · L T · x (53)<br />

Der Vektor y wird zudem wie folgt in c skaliert.<br />

D · c = y (54)<br />

Somit kann (52) in den folgenden 3 Schritten umformuliert werden.<br />

− L · y + b = 0 (55)<br />

−D · c + y = 0 (56)<br />

L T · x + c = 0 (57)<br />

Die Unbekannten x i für mehrere Lastfälle wird demnach in den folgenden 3 Schritten ermittelt.<br />

• Dreieckszerlegung<br />

Die Matrix A wird nach (51) unabhängig von den rechten Seiten in eine Lingsdreiecksmatrix<br />

und eine Diagonalmatrix zerlegt.<br />

• Vorwärtseinsetzen<br />

Berechnung einer modifizierten rechten Seite c nach (55 und 56).<br />

• Rückwärtseinsetzen<br />

Berechnung aller Unbekannten mit modifizierten rechten Seite c nach (57).<br />

Der Vorteil dieses Verfahrens ist, dass der aufwendigste Schritt, die Dreieckszerlegung der Koeffizientenmatrix<br />

(O(n 3 )), nur einmal für alle Lastfälle (Inhomogenitäten b) durchzuführen ist.<br />

Die Berechnung der Unbekannten durch Vorwärtseinsetzen (O(n 2 )) und Rückwärtseinsetzen<br />

(O(n 2 )) erfolgt dann für jeden Lastfall individuell.<br />

26 Bei Anwendung der Standardvariante des Gauß’schen Algorithmus wird das Gleichungssystem für jede rechte<br />

Seite (Lastfall) individuell gelöst. Ziel der Betrachtung hier ist, den aufwendigen Schritt der Zerlegung im Falle<br />

mehrerer rechter Seiten, d.h. für mehrere Lastfälle, von der Berechnung der Unbekannten zu separieren, sodass<br />

die Zerlegung nur einmal durchgeführt werden muss.<br />

19.10.2011


Seite 60 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

D.3 Die Cholesky-Zerlegung<br />

Zur optimalen Nutzung des Speichers werden die Faktoren l ik an die Stelle der entsprechenden<br />

Matrixelemente der Matrix A gespeichert. Der Gauß’sche Algorithmus wirft das Problem auf,<br />

dass die Faktoren l ik erst dann auf die Matrixelemente abgespeichert werden können, wenn<br />

der Eliminationsschritt vollständig durchgeführt wurde (siehe Gleichung 44). Wird darauf nicht<br />

geachtet, gehen Matrixelemente verloren, die zukünftig noch gebraucht werden.<br />

Durch Cholesky’s Idee einer symmetrischen Zerlegung der Matrix A wird dieses Problem gelöst.<br />

Der Algorithmus wird vereinfacht. Durch die symmetrische Aufspaltung der Matrix A wird aus<br />

den Diagonalelementen die Wurzel gezogen. Dies reduziert die Größenordung der Matrixelemente<br />

auf die Halfte (z.B. √ 100 = 10 und √ 10000 = 100), die Matrixelemente rücken zusammen,<br />

was zu einer besseren Konditionierung der Matrix und dadurch zu einer höheren numerische<br />

Stabilität der Berechnung führt.<br />

Die Zerlegung nach Cholesky ergibt folgende Beziehung.<br />

A = L · L T (58)<br />

Die Diagonalelemente der Gauß’schen Zerlegung, Matrix D (51) werden in der Cholesky-<br />

Zerlegung symmetrisch in die Dreiecksmatrizen L und L T aufgenommen. Damit ergibt sich<br />

die folgende Beziehung.<br />

A = L Chol · L T Chol<br />

, mit L Chol<br />

= L Gaus · D (1/2) (59)<br />

Für die l-Faktoren ergibt sich mit<br />

l i1 =<br />

a i1<br />

√<br />

a11<br />

(i = 2, 3, ..., n) (60)<br />

die symmetrische Form 27<br />

a (1)<br />

ik = a ik − l i1 · l k1 (i = 2, 3, ..., n; k = 2, 3, ..., i) (61)<br />

wobei für die erste Gleichung gilt<br />

l 11 = √ a 11 , und<br />

c 1<br />

c 1 = √ = b 1<br />

(62)<br />

a11 l 11<br />

Mit (60), (61) und (62) folgt für die Bestimmungsgleichung für die erste Unbekannte x 1<br />

[ n∑<br />

]<br />

x 1 = − 1 · l k1 · x k + c 1<br />

l 11<br />

k=2<br />

(63)<br />

für (45) folgt mit (60) und (62)<br />

b (1)<br />

i<br />

= b i − l i1 · c 1 (i = 2, 3, ..., n) (64)<br />

27 Aus (61) folgt, dass unmittelbar nach Berechnung eines neuen Matrixelements, das entsprechend alte nicht<br />

mehr benötigt wird, d.h. das neue kann unmittelbar nach Berechnung auf den Speicherplatz des alten geschrieben<br />

werden.<br />

E. Baeck


D. GAUß’SCHER ALGORITHMUS UND CHOLESKY-ZERLEGUNG Seite 61<br />

Das Aufstellen der reduzierten Gleichungssysteme erfolgt analog zur Gauß’schen Zerlegung. Für<br />

das reduzierte Gleichungssystem der zweiten Stufe ergibt sich folgende Gleichungen.<br />

l 22 =<br />

√<br />

a (1)<br />

22 , l i2 = a(1) i2<br />

(i = 3, 4, ..., n) (65)<br />

l 22<br />

a (2)<br />

ik<br />

= a (1)<br />

ik − l i2 · l k2 (i = 3, 4, ..., n; k = 3, 4, ..., i) (66)<br />

c 2 = b 2<br />

l 22<br />

(67)<br />

b (2)<br />

i<br />

= b (1)<br />

i<br />

− l i2 · c 2 (i = 3, 4, ..., n) (68)<br />

Die Gleichungen (65) und (66) zeigen die symmetrische Zerlegung nach Cholesky, die Gleichungen<br />

(67) und (68) das Vorwärtseinsetzen, die Berechnung des Hilfsvektors zur Ermittlung der<br />

Unbekannten im Rückwärtseinsetzen.<br />

Die Linksdreiecksmatrix nach der Cholesky-Zerlegung (vgl. (58)) hat die folgende Gestalt.<br />

⎡<br />

⎤<br />

l 11 0 0 0<br />

l<br />

L =<br />

21 l 22 0 0<br />

(69)<br />

⎢ l<br />

⎣ 31 l 32 l 33 0 ⎥<br />

⎦<br />

l 41 l 42 l 43 l 44<br />

Im Gegensatz zum Gauß’schen Algorithmus benötigt der Algorithmus nach Cholesky nur einen<br />

Hilfvektor (c = −L T · x) für das Vorwärts-, Rückwärtseinsetzen. Die Skalierung mit der Diagonalmatrix<br />

(siehe (56)) entfällt.<br />

Für das lineare Gleichungssystem (33) folgt mit der Zerlegung (58)<br />

L · L T · x + b = 0 (70)<br />

Der Hilfsvektor der Lastseite c wird durch das Vorwärtseinsetzen (71) berechnet. Die Unbekannten<br />

ergeben sich aus dem Rückwärtseinsetzen (72)mit Hilfe des Vektors c.<br />

− L · c + b = 0 (71)<br />

L T · x + c = 0 (72)<br />

19.10.2011


Seite 62 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

D.4 Pseudocode für Cholesky-Zerlegung<br />

Die Berechnung der Unbekannten aus dem linearen Gleichungssystem (33) werden für mehrere<br />

rechte Seiten, d.h. Lastfälle, sinnvollerweise durch drei getrennte Programmteile (Funktionen)<br />

implementiert,<br />

• die Dreieckszerlegung,<br />

• das Vorwärtseinsetzen und<br />

• das Rückwärtseinsetzen,<br />

wobei die Dreieckszerlegung nur einmal, das Vorwärts- und Rückwärtseinsetzen für jede rechte<br />

Seite b, d.h. für jeden Lastfall erfolgt.<br />

D.4.1<br />

Pseudocode der Zerlegung<br />

Der Prozess der Dreieckszerlegung wird durch den folgenden Pseudocode beschrieben.<br />

für p = 1, 2, ..., n<br />

l pp = √ a pp<br />

für i = p + 1, p + 2, ..., n<br />

l ip = a ip /l pp<br />

für k = p + 1, p + 2, ..., i<br />

für a ik = a ik − l ip · l kp (58’)<br />

D.4.2<br />

Pseudocode des Vorwärtseinsetzens<br />

Der Prozess des Vorwärtseinsetzens wird durch den folgenden Pseudocode beschrieben.<br />

für k = 1, 2, ..., n<br />

s = b k<br />

für i = 1, 2, ..., k − 1<br />

s = s − l ki · c i<br />

c k = s/l kk (71’)<br />

D.4.3<br />

Pseudocode des Rückwärtseinsetzens<br />

Der Prozess des Rückwärtseinsetzens wird durch den folgenden Pseudocode beschrieben.<br />

für k = n, n − 1, ..., 1<br />

s = c k<br />

für i = k + 1, k + 2, ..., n<br />

s = s + l ik · x i<br />

x k = −s/l kk (72’)<br />

E. Baeck


D. GAUß’SCHER ALGORITHMUS UND CHOLESKY-ZERLEGUNG Seite 63<br />

D.5 VBA-Code des Gleichungslösers nach Cholesky<br />

In diesem Abschnitt werden die VBA-Codes für die Dreieckszerlegung nach Cholesky sowie<br />

die Codes des Vorwärts- und Rückwärtseinsetzens gegeben. Der VBA-Code ergibt sich aus der<br />

direkten Umsetzung des Pseudocodes (siehe Abschnitt D.4) in die VBA-Sprache.<br />

D.5.1<br />

VBA-Code der Cholesky-Zerlegung<br />

Option Explicit<br />

’ Zerlegen einer Matrix A(n x n) nach Cholesky<br />

’<br />

’ A = L * L^T<br />

’<br />

’ A: Dim A(1 to n, 1 to n)<br />

Public Function Cholesky(n As Integer, a() As Double) As Integer<br />

Dim P As Integer<br />

Dim i As Integer<br />

Dim k As Integer<br />

’ über die Spalten<br />

For P = 1 To n<br />

’ Matrix nicht zerlegbar<br />

If a(P, P)


Seite 64 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

D.5.2<br />

VBA-Code des Vorwärtseinsetzens<br />

’ Vorwärtseinsetzen<br />

Public Sub Vorwaerts(n As Integer, L() As Double, b() As Double, c() As Double)<br />

Dim k As Integer<br />

Dim i As Integer<br />

Dim s As Double<br />

For k = 1 To n<br />

s = b(k)<br />

For i = 1 To k - 1<br />

s = s - L(k, i) * c(i)<br />

Next<br />

c(k) = s / L(k, k)<br />

Next<br />

End Sub<br />

D.5.3<br />

VBA-Code des Rückwärtseinsetzens<br />

’ Rückwärtseinsetzen<br />

Public Sub Rueckwaerts(n As Integer, L() As Double, c() As Double, x() As Double)<br />

Dim k As Integer<br />

Dim i As Integer<br />

Dim s As Double<br />

For k = n To 1 Step -1<br />

s = -c(k)<br />

’ "-" falls: A*x = b<br />

’ s = +c(k) ’ "+" falls: A*x + b = 0<br />

For i = k + 1 To n<br />

s = s + L(i, k) * x(i)<br />

Next<br />

x(k) = -s / L(k, k)<br />

Next<br />

End Sub<br />

E. Baeck


E. LÖSUNGEN ZUM ABSCHNITT ELEMENTARE ALGORITHMEN Seite 65<br />

E<br />

Lösungen zum Abschnitt Elementare Algorithmen<br />

In diesem Anhang werden Lösungsvorschläge zu den Aufgaben im Abschnitt 5 gegeben. Auf<br />

die Darstellung an die Eventfunktionen wird hierbei verzichtet, da diese bei allen Programmen<br />

ähnlich ist und damit aus der Darstellung des Abschnitts 4.1 prinzipiell entnommen werden<br />

kann.<br />

E.1 Summe aller Zahlen aus vorgegebenem Intervall<br />

’ Summe der ganzen Zahlen von "VON" nach "BIS"<br />

Public Sub Summe()<br />

’ Deklaration<br />

Dim von As Integer<br />

Dim bis As Integer<br />

Dim sum As Integer<br />

Dim i As Integer<br />

Abbildung 48: Eingabefelder und Programstart<br />

’ Initialisierung<br />

sum = 0<br />

’ Hole Daten aus Tabelle<br />

von = Range("VON")<br />

bis = Range("BIS")<br />

’ Berechnung der Summe<br />

For i = von To bis<br />

sum = sum + i<br />

Next<br />

’ Schreibe Ergebnis in Tabelle<br />

Range("SUM") = sum<br />

End Sub<br />

19.10.2011


Seite 66 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

E.2 Berechnung der Fakultät<br />

Aufgabenstellung in Abschnitt 5.1.<br />

’ Berechnung der Fakultät<br />

Public Sub Fakultaet()<br />

Dim n As Integer<br />

Dim i As Integer<br />

Dim f As Double<br />

’ Eingangsgröße<br />

’ Laufvariable<br />

’ Ergebnis: Achtung 8Bytes! erforderlich<br />

’ Initialisierung<br />

f = 1<br />

n = Range("NWERT")<br />

’ Berechnung<br />

For i = 2 To n<br />

f = f * i<br />

Next<br />

Abbildung 49: Eingabefelder und Programstart<br />

’ Ergebnis<br />

Range("NFAKULTAET") = f<br />

End Sub<br />

E. Baeck


E. LÖSUNGEN ZUM ABSCHNITT ELEMENTARE ALGORITHMEN Seite 67<br />

E.3 Berechnung des Binomialkoeffizienten<br />

Aufgabenstellung in Abschnitt 5.2 28<br />

’ Berechnung des Binomialkoeffizienten<br />

Public Sub Binomi()<br />

Dim i As Integer<br />

Dim f As Double<br />

’ Ergebnis kritsch! => 8Bytes!<br />

Dim n As Integer<br />

Dim m As Integer<br />

’ Eingangsgrößen aus Tabelle<br />

n = Range("B_N")<br />

m = Range("B_M")<br />

Abbildung 50: Eingabefelder und Programstart<br />

f = 1<br />

’ Berechnung<br />

For i = 1 To m<br />

f = f * (n - i + 1) / i<br />

Next<br />

’ Ausgabe in Tabelle<br />

Range("W_BIN") = f<br />

End Sub<br />

28 Das Beispiel zeigt die möglichen Kombinationen für die Auswahl von 6 aus 49. Der Kehrwert wäre die<br />

Wahrscheinlichkeit einen 6er im Lotto zu holen. Füllen Sie also 14 Millionen Lottoscheine aus und es wird Ihnen<br />

einmal das große Glück zu winken. Dies allerdings nur, bei hinreichend häufiger Wiederholung!<br />

19.10.2011


Seite 68 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

E.4 Beispiel 4: Winkel zwischen 2 Vektoren im R n<br />

Aufgabenstellung in Abschnitt 5.3<br />

VBA liefert keine Arkuskosinus-Funktion. Arkuskosinus wird wie folgt auf Arkustangens zurück<br />

geführt 29 .<br />

( ) −x<br />

arccos(x) = arctan √ + π (73)<br />

1 − x 2<br />

’ Berechnung des Winkels zwischen 2 Vektoren aus R^n<br />

Public Function Winkel(i0 As Integer, j0 As Integer)<br />

Dim i As Integer<br />

Dim dm As Integer<br />

’ Laufindex<br />

’ Dimension<br />

Dim V1() As Double ’ Vektor 1<br />

Dim V2() As Double ’ Vektor 2<br />

Dim L1 As Double ’ Vektorlänge 1<br />

Dim L2 As Double ’ Vektorlänge 2<br />

Dim L3 As Double ’ Skalarpodukt V1, V2<br />

Dim cs As Double ’ Cosinus-Wert<br />

i = 1<br />

’ Dimension ermitteln<br />

Do While (Cells(i + i0, 1 + j0) "")<br />

i = i + 1<br />

Loop<br />

dm = i - 1<br />

’ Dimensionierung der Vektoren<br />

ReDim V1(1 To dm)<br />

ReDim V2(1 To dm)<br />

’ Einlesen der Vektoren<br />

For i = 1 To dm<br />

V1(i) = Cells(i + i0, 1 + j0)<br />

V2(i) = Cells(i + i0, 2 + j0)<br />

Next<br />

Abbildung 51: Eingabefelder und Programstart<br />

’ Vektorlängen berechnen<br />

L1 = Sqr(SkalProd(V1, V1))<br />

L2 = Sqr(SkalProd(V2, V2))<br />

L3 = SkalProd(V1, V2)<br />

29 Die Umrechnung von Rad in Grad erfolgt durch Skalierung mit Faktor<br />

45<br />

arctan(1)<br />

E. Baeck


E. LÖSUNGEN ZUM ABSCHNITT ELEMENTARE ALGORITHMEN Seite 69<br />

’ Winkelberechnung<br />

cs = L3 / (L1 * L2)<br />

’ Berechnung des Winkels in Grad<br />

Winkel = acos(cs) * 45# / Atn(1#)<br />

End Function<br />

’ arccos - Arcuscosinus<br />

Function acos(x)<br />

acos = Atn(-x / Sqr(-x * x + 1)) + 2 * Atn(1)<br />

End Function<br />

’ Berechnung des Skalarprodukts<br />

Function SkalProd(a() As Double, b() As Double)<br />

Dim nu As Integer<br />

Dim no As Integer<br />

Dim s As Double<br />

nu = LBound(a)<br />

no = UBound(b)<br />

s = 0<br />

’ untere Grenze<br />

’ obere Grenze<br />

’ über alle<br />

For i = nu To no<br />

s = s + a(i) * b(i)<br />

Next<br />

SkalProd = s<br />

End Function<br />

19.10.2011


Seite 70 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

E.5 Lösung der sinus-Entwicklung<br />

Das Programm wird als Eventfunktion zum Click-Ereignis der Schaltfläche in der Tabelle implementiert.<br />

Private Sub SinusStart_Click()<br />

Dim f As Double<br />

Dim x As Double<br />

Dim eps As Double<br />

Dim t As Double<br />

Dim i As Long<br />

Dim j As Long<br />

Dim g As Integer<br />

On Error GoTo Fehler<br />

g = 0<br />

’ Löschen der Ausgabebereiche<br />

Range("sinus_kom") = ""<br />

’ Löschen der Tabelle<br />

i = 10<br />

Do While Cells(i, 2) ""<br />

Cells(i, 2) = ""<br />

Cells(i, 3) = ""<br />

Cells(i, 4) = ""<br />

i = i + 1<br />

Loop<br />

’ Eingabedaten<br />

x = Range("sinus_x")<br />

eps = Range("sinus_eps")<br />

’ Initialisierung<br />

f = 0: g = 1<br />

x = x * Atn(1) / 45<br />

’ Term 1<br />

f = x: t = x<br />

i = 1: j = 1<br />

Cells(9 + i, 2) = i<br />

Cells(9 + i, 3) = t<br />

Cells(9 + i, 4) = f<br />

E. Baeck


E. LÖSUNGEN ZUM ABSCHNITT ELEMENTARE ALGORITHMEN Seite 71<br />

´<br />

’ Summationsschleife<br />

Do While Abs(t) > eps<br />

t = -t * x * x<br />

j = j + 1<br />

t = t / j<br />

j = j + 1<br />

t = t / j<br />

f = f + t<br />

’ Ausgabe in die Tabelle<br />

i = i + 1<br />

Cells(9 + i, 2) = i<br />

Cells(9 + i, 3) = t<br />

Cells(9 + i, 4) = f<br />

Loop<br />

g = 2<br />

Exit Sub<br />

Fehler:<br />

Range("sinus_kom") = "Programmfehler: Überlauf (Code " & g & ")!"<br />

End Sub<br />

19.10.2011


Seite 72 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

E.6 Implementierung des Newton-Verfahrens<br />

Das Verfahren besteht aus drei Programmteilen, dem Unterprogramm newton und den Funktionen<br />

f bzw. fs. In vorliegender Implementierung wird die Ableitung der Funktion numerisch<br />

berechnet. Da es in VBA nicht möglich ist, als Parameter eine Funktion zu übergeben, erhält<br />

die Funktion generell die Bezeichnung f. Die Funktion f ist demzufolge ebenfalls als Programmeingabe<br />

zu verstehen.<br />

Option Explicit<br />

’ alle Variablen deklarieren<br />

’ Funktion<br />

Private Function f(x As Double) As Double<br />

f = x ^ 2 - 1<br />

End Function<br />

’ Numerische Ableitung der Funktion f(x)<br />

Private Function fs(x As Double) As Double<br />

Dim h As Double<br />

h = 0.00001<br />

fs = (f(x + h / 2) - f(x - h / 2)) / h<br />

End Function<br />

’ Newtonalgorithmus<br />

Public Sub newton()<br />

Dim x As Double<br />

Dim eps As Double<br />

Dim nx As Integer<br />

Dim n As Integer<br />

Dim z0 As Integer<br />

Dim s0 As Integer<br />

’ Ursprung der Ausgabetabelle<br />

’ Initialisierung<br />

x = Range("NX0")<br />

eps = Range("NEPS")<br />

nx = Range("NIX")<br />

n = 0<br />

z0 = 13<br />

s0 = 1<br />

’ Zurücksetzen der Ausgabetabelle<br />

’ ... noch ein Geheimnis ...<br />

’ Iterationsschleife<br />

Do<br />

’ Fall 1: Nullstelle gefunden<br />

If Abs(f(x)) < eps Then<br />

E. Baeck


E. LÖSUNGEN ZUM ABSCHNITT ELEMENTARE ALGORITHMEN Seite 73<br />

Range("NXN") = x<br />

Range("NIT") = n<br />

Range("NKOM") = "Nullstelle gefunden!"<br />

Exit Sub<br />

’ Fall 2: Anzahl zulässiger Iterationen erreicht<br />

ElseIf n >= nx Then<br />

Range("NXN") = "---"<br />

Range("NIT") = n<br />

Range("NKOM") = "Keine Nullstelle gefunden!"<br />

Exit Sub<br />

’ Fall 3: Horizontale Tangente<br />

ElseIf Abs(fs(x)) < eps Then<br />

Range("NXN") = "---"<br />

Range("NIT") = n<br />

Range("NKOM") = "Abbruch wegen horizontaler Tangente!"<br />

Exit Sub<br />

End If<br />

’ Iterationsschritt<br />

x = x - f(x) / fs(x)<br />

n = n + 1<br />

’ Protokoll der Iteration<br />

Cells(z0 + n, s0 + 1) = n<br />

Cells(z0 + n, s0 + 2) = x<br />

Cells(z0 + n, s0 + 3) = f(x)<br />

Cells(z0 + n, s0 + 4) = fs(x)<br />

Loop<br />

End Sub<br />

19.10.2011


Seite 74 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

F<br />

Lösungen zum Clapeyron-Problem<br />

In diesem Abschnitt werden Lösungsvorschläge für das Clapeyron-Problem zusammen gestellt.<br />

F.1 Aufgabe 8.3.1<br />

Eine mögliche Datenstrukturen gemäß der ER-Modelle wäre die folgende.<br />

’ Daten eines Feldes<br />

Type Feld<br />

L As Double<br />

i As Double<br />

End Type<br />

’ Feldlänge<br />

’ Trägheitsverhältnis<br />

Der Container für die Felder wird als globale Variabel angelegt, d.h. er ist aus allen Routinen des<br />

Moduls direkt ansprechbar. Zudem wird die Anzahl der Felddaten nFeld als globale Variabel<br />

geführt.<br />

’ Globale Variable<br />

Dim FA() As Feld<br />

’ Container für die Felder<br />

Dim nFeld As Integer<br />

’ Feldanzahl<br />

E. Baeck


F. LÖSUNGEN ZUM CLAPEYRON-PROBLEM Seite 75<br />

F.2 Aufgabe 8.3.2<br />

Eine mögliche Datenstrukturen gemäß der ER-Modelle wären die folgende.<br />

’ Daten einer Streckenlast<br />

Type SLast<br />

nF As Integer<br />

q As Double<br />

a As Double<br />

c As Double<br />

End Type<br />

’ Feldnummer<br />

’ Ordinate<br />

’ Position im Feld<br />

’ Einleitungslänge<br />

’ Daten einer Punktlast<br />

Type PLast<br />

nF As Integer<br />

P As Double<br />

a As Double<br />

End Type<br />

’ Feldnummer<br />

’ Ordinate<br />

’ Position im Feld<br />

’ Daten einer Punktmoment<br />

Type PMoment<br />

nF As Integer<br />

M As Double<br />

a As Double<br />

End Type<br />

’ Feldnummer<br />

’ Ordinate<br />

’ Position im Feld<br />

’ Daten eines Lastfalls<br />

Type Lastfall<br />

Nr As Integer<br />

’ Lastfallnummer<br />

’ Lasten und Momente<br />

SL() As SLast<br />

PL() As PLast<br />

PM() As PMoment<br />

End Type<br />

’ Container der Streckenlasten<br />

’ Container der Punktlasten<br />

’ Container der Punktmomente<br />

’ Index für Lastfall<br />

’ "Strichliste" zum Zählen der Lasten<br />

Type IndLF<br />

Nr As Integer<br />

’ Lastfallnummer<br />

SL As Integer<br />

’ Zähler der Streckenlasten<br />

PL As Integer<br />

’ Zähler der Punktlasten<br />

PM As Integer<br />

’ Zähler der Punktmomente<br />

End Type<br />

19.10.2011


Seite 76 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

F.3 Einlesen der Systemdaten und Aufbau des Datenmodell<br />

Das Programm zählt in einem ersten Schritt die Anzahl der eingegeben Felder, legt dann den<br />

Container in entsprechender Größe an und überträgt dann in einem zweiten Schritt die Daten<br />

aus der Tabelle in das Datenmodell.<br />

’ Einlesen der Strukturdaten<br />

’ Tabellenoffset: i0, j0<br />

’ Rückgabe: Fehlerkenner = 0 (alles ok)<br />

Public Function LeseSystem(i0 As Integer, j0 As Integer) As Integer<br />

’ Schritt 1: Feldanzahl ermitteln<br />

Dim i As Integer ’ Laufindex der Zeilen<br />

Dim j As Integer ’ Laufindex der Spalten<br />

’ Initialisierung<br />

LeseSystem = 0<br />

nFeld = 0<br />

i = i0 + 1<br />

j = j0 + 1<br />

’ 0: alles ok<br />

’ Initialisierung der Feldanzahl<br />

’ 1. Zeile<br />

’ 1. Spalte<br />

’ über alle Zeilen bis leeres Feld gefunden<br />

Do While (Cells(i, j) "")<br />

i = i + 1<br />

Loop<br />

’ Anzahl der Felder: Offset und Leerfeld berücksichtigen<br />

nFeld = i - i0 - 1<br />

’ Wurden Felder eingegeben<br />

If nFeld < 1 Then<br />

LeseSystem = 1<br />

Exit Function<br />

End If<br />

’ Container anlegen<br />

ReDim FA(1 To nFeld)<br />

’ Schritt 2: Daten lesen und speichern<br />

For i = 1 To nFeld<br />

FA(i).L = Cells(i + i0, 1 + j0)<br />

FA(i).i = Cells(i + i0, 2 + j0)<br />

Next<br />

End Function<br />

E. Baeck


F. LÖSUNGEN ZUM CLAPEYRON-PROBLEM Seite 77<br />

F.4 Einlesen der Belastungsdaten und Aufbau des Datenmodell<br />

Das Problem des Aufbaus der Belastungsdaten wird in zwei verschiedene Unterprogramme separiert.<br />

30<br />

• Der Aufbau des Lastfall-Indexvektors.<br />

• Der Aufbau des Lastfall-Containers.<br />

F.4.1<br />

Aufbau des Lastfall-Indexvektors<br />

Der Lastfallindex-Vektor ILF wird wie der Feld-Container als globale Variable deklariert. Zudem<br />

werden die Anzahl der Lastdaten nLast und die extremalen Lastfallnummern lfmin und lfmax<br />

als globale Variabel geführt.<br />

’ Globale Variable<br />

Dim ILF() As IndLF<br />

’ Container der Lastindizes<br />

Dim nLast As Integer<br />

Dim lfmin As Integer<br />

Dim lfmax As Integer<br />

’ Lastdatenanzahl<br />

’ minimale Lastfallnummer<br />

’ maximale Lastfallnummer<br />

In einem ersten Schritt wird der Lastfallnummern-Bereich ermittelt. 3132<br />

’ Aufbau des Lastfall-Indexvektors<br />

’ Tabellenoffset: i0, j0<br />

’ Rückgabe: Fehlerkenner = 0 (alles ok)<br />

Public Function GenLastIndex(i0 As Integer, j0 As Integer) As Integer<br />

’ Schritt 1: Lastfallbereich ermitteln<br />

Dim i As Integer ’ Laufindex der Zeilen<br />

Dim lf As Integer ’ Lastfallnummer aus Tabelle<br />

Dim typ As Integer ’ Lastfalltyp aus Tabelle<br />

’ Initialisierung<br />

GenLastIndex = 0<br />

nLast = 0<br />

i = 1<br />

’ 1. Zeile<br />

’ über alle Zeile<br />

Do While (Cells(i + i0, 1 + j0) "")<br />

lf = Cells(i + i0, 1 + j0) ’ Lastfallnummer lesen<br />

30 Das Zerlegen längerer Programmsequenzen in abgegrenzte Einheiten, Module führt i.A. zu wesentlich übersichtlicheren<br />

und dadurch verständlicheren Programmen. Daumenwert für die maximale Code-Länge sind 1-2<br />

A4-Seiten im Ausdruck.<br />

31 Bei der select case Anweisung im Schritt 2, die in verschiedene Lasttypen verzweigt, wurden in den case-<br />

Zweigen jeweils zwei Code-Zeilen mit dem : aus Gründen der Übersichtlichkeit zusammen gefasst.<br />

32 Wenn in einer if...endif-Klammer nur eine Anweisung ausgeführt werden soll, kann auf die Schlüsselworte<br />

then und endif verzichtet werden.<br />

19.10.2011


Seite 78 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

’ 1. Datensatz => Initialisierung<br />

If i = 1 Then<br />

lfmax = lf<br />

lfmin = lf<br />

’ Extremale Lastfallnummern herausfischen<br />

Else<br />

If lfmax < lf Then lfmax = lf<br />

If lfmin > lf Then lfmin = lf<br />

End If<br />

i = i + 1<br />

Loop<br />

’ Anzahl der Lasten<br />

nLast = i - 1<br />

’ Wurden Lasten eingegeben<br />

If nLast < 1 Then<br />

GenLastIndex = 1<br />

Exit Function<br />

End If<br />

’ Container anlegen<br />

ReDim ILF(lfmin To lfmax)<br />

’ Schritt 2: Lastdaten der Lastfälle zählen<br />

For i = 1 To nLast<br />

lf = Cells(i + i0, 1 + j0)<br />

’ Lastfallnummer<br />

ILF(lf).Nr = lf<br />

’ ... übernehmen<br />

typ = Cells(i + i0, 3 + j0) ’ Lasttyp<br />

’ Welche Last liegt vor<br />

Select Case typ<br />

’ Steckenlast zählen<br />

Case 1: ILF(lf).SL = ILF(lf).SL + 1<br />

’ Punktlast zählen<br />

Case 2: ILF(lf).PL = ILF(lf).PL + 1<br />

’ Punktmoment zählen<br />

Case 3: ILF(lf).PM = ILF(lf).PM + 1<br />

End Select<br />

Next<br />

End Function<br />

E. Baeck


F. LÖSUNGEN ZUM CLAPEYRON-PROBLEM Seite 79<br />

F.4.2<br />

Aufbau des Lastfall-Containers<br />

Der Lastfall-Container LA wird wie der Feld-Container als globale Variable deklariert.<br />

’ Globale Variable<br />

Dim LA() As Lastfall<br />

’ Container der Lastfälle<br />

In einem ersten Schritt wird der Lastfall-Container aus der <strong>Info</strong>rmation des Lastfall-Indexvektors<br />

dimensioniert. Bevor die Lasten in die Container eingelesen werden, werden die Lastenzähler im<br />

Lastfall-Indexvektor zurück gesetzt (=0). Da als Container indizierte Variablen (Felder) eingesetzt<br />

werden, benötigt man einen Füllzeiger, der als Index für den jeweils nächsten Datensatz<br />

eingesetzt wird.<br />

’ Aufbau des Lastfall-Containers und einlesen der Lastdaten<br />

’ Tabellenoffset: i0, j0<br />

’ Rückgabe: Fehlerkenner = 0 (alles ok)<br />

Public Function GenLastdaten(i0 As Integer, j0 As Integer) As Integer<br />

’ Schritt 1: Dimensionierung des Lastfall-Containers<br />

Dim i As Integer ’ Laufindex der Zeilen<br />

Dim lf As Integer ’ Lastfallnummer aus Tabelle<br />

Dim typ As Integer ’ Lastfalltyp aus Tabelle<br />

’ Initialisierung<br />

GenLastdaten = 0<br />

’ Dimensionieren der Lastfälle<br />

ReDim LA(LBound(ILF) To UBound(ILF))<br />

’ über alle Lastfälle<br />

For i = LBound(ILF) To UBound(ILF)<br />

’ für vorhandene Lastfälle werden die<br />

’ Last-Container dimensioniert<br />

If ILF(i).Nr > 0 Then<br />

’ Streckenlasten dimensionieren<br />

If ILF(i).SL > 0 Then ReDim LA(i).SL(1 To ILF(i).SL)<br />

’ Punktlasten dimensionieren<br />

If ILF(i).PL > 0 Then ReDim LA(i).PL(1 To ILF(i).PL)<br />

’ Punktmomente dimensionieren<br />

If ILF(i).PM > 0 Then ReDim LA(i).PM(1 To ILF(i).PM)<br />

End If<br />

Next<br />

’ Schritt 2: Einlesen der Lastdaten<br />

’ - Initialisierung der Lastenzähler<br />

19.10.2011


Seite 80 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

For i = LBound(ILF) To UBound(ILF)<br />

ILF(i).SL = 0<br />

ILF(i).PL = 0<br />

ILF(i).PM = 0<br />

Next<br />

’ - über alle Datensätze<br />

’ Zeiger auf ersten Lastdatensatz setzen<br />

i = 1<br />

Do While (Cells(i + i0, 1 + j0) "")<br />

lf = Cells(i + i0, 1 + j0) ’ Lastfallnummer lesen<br />

typ = Cells(i + i0, 3 + j0) ’ Lasttyp lesen<br />

’ Welche Last liegt vor<br />

Select Case typ<br />

’ Steckenlast lesen<br />

Case 1<br />

ILF(lf).SL = ILF(lf).SL + 1 ’ Zähler inkrementieren<br />

LA(lf).SL(ILF(lf).SL).nF = Cells(i + i0, 2 + j0)<br />

LA(lf).SL(ILF(lf).SL).q = Cells(i + i0, 4 + j0)<br />

LA(lf).SL(ILF(lf).SL).a = Cells(i + i0, 5 + j0)<br />

LA(lf).SL(ILF(lf).SL).c = Cells(i + i0, 6 + j0)<br />

’ Punktlast lesen<br />

Case 2<br />

ILF(lf).PL = ILF(lf).PL + 1 ’ Zähler inkrementieren<br />

LA(lf).PL(ILF(lf).PL).nF = Cells(i + i0, 2 + j0)<br />

LA(lf).PL(ILF(lf).PL).P = Cells(i + i0, 4 + j0)<br />

LA(lf).PL(ILF(lf).PL).a = Cells(i + i0, 5 + j0)<br />

’ Punktmoment lesen<br />

Case 3<br />

ILF(lf).PM = ILF(lf).PM + 1 ’ Zähler inkrementieren<br />

LA(lf).PM(ILF(lf).PM).nF = Cells(i + i0, 2 + j0)<br />

LA(lf).PM(ILF(lf).PM).M = Cells(i + i0, 4 + j0)<br />

LA(lf).PM(ILF(lf).PM).a = Cells(i + i0, 5 + j0)<br />

End Select<br />

i = i + 1<br />

Loop<br />

’ nächste Lastdaten-Zeile<br />

End Function<br />

E. Baeck


F. LÖSUNGEN ZUM CLAPEYRON-PROBLEM Seite 81<br />

F.4.3<br />

Aufbau der Koeffizientenmatrix<br />

Die Koefizientenmatrix wird kompakt unter Ausnutzung von Symmetrie und Bandstruktur aufgebaut.<br />

Die Matrix A wird als globale Variable deklariert.<br />

’ Globale Variable<br />

Dim A() As Double<br />

’ Koeffizientenmatrix<br />

’ Aufbau der Kooeffizentenmatrix A<br />

’ Der Aufbau erfolgt in kompakter Form unter Ausnutzung von<br />

’ Symmetrie und Bandstruktur<br />

’ Rückgabe: Fehlerkenner = 0 (alles ok)<br />

Public Function GenMatA() As Integer<br />

Dim i As Integer<br />

GenMatA = 0<br />

’ Für ein Felder ist Lösung bekannt<br />

If nFeld < 2 Then<br />

GenMatA = 1<br />

Exit Function<br />

End If<br />

’ Anlegen der Matrix<br />

ReDim A(1 To nFeld - 1, 1 To 2)<br />

’ Setzen der Matrixelemente<br />

For i = 1 To nFeld - 1<br />

If i = 1 Then<br />

A(1, 1) = 0<br />

Else<br />

A(i, 1) = FA(i).L / FA(i).i<br />

End If<br />

A(i, 2) = 2 * (FA(i).L / FA(i).i + FA(i + 1).L / FA(i + 1).i)<br />

Next<br />

End Function<br />

19.10.2011


Seite 82 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

F.4.4<br />

Lesen einer kompakt gespeicherten Bandmatrix<br />

In der nachfolgenden Route wird aus der Matrix A das Element A ij gelesen. Das Programm<br />

berücksichtigt zum einen die Symmetrie der Matrix, zum anderen die kompakte Speicherung<br />

der Matrix als symmetrische Bandmatrix (siehe auch Abschnitt 8.5.1).<br />

’ Lesen der Matrixelemente i,j einer globalen Band-Matrix A<br />

Function AIJ(i As Integer, j As Integer) As Double<br />

’ i,j -> i,j-i+m+1 mit m=1<br />

’ i >=j und i-j m Then<br />

AIJ = 0#<br />

Exit Function<br />

End If<br />

’ 1: oberen Dreieck z.B. a(1,2)<br />

If j > i Then<br />

ki = j<br />

kj = i - j + m + 1<br />

’ 2: unteres Dreieck + Hauptdiagonale<br />

Else<br />

ki = i<br />

kj = j - i + m + 1<br />

End If<br />

AIJ = A(ki, kj)<br />

End Function<br />

E. Baeck


F. LÖSUNGEN ZUM CLAPEYRON-PROBLEM Seite 83<br />

F.4.5<br />

Das Hauptprogramm<br />

Die einzelnen <strong>Teil</strong>schritte, die jeweils in eigenen Unterprogrammen codiert wurden, werden nacheinander<br />

in einem Hauptprogramm aufgerufen. Dieses Hauptprogramm liegt (z.Z. noch) in der<br />

Ereignisfunktion zum Click-Event.<br />

Aus der Ereignisfunktion werden die Tabellen-Ursprungskoordinaten den Programmen weiter<br />

gereicht, die aus den Tabellen Eingabedaten entnehmen. Zudem wird nach jedem <strong>Teil</strong>schritt<br />

eine entsprechende Fehlerprüfung durchgeführt, um zu klären, ob eine weiteres Abarbeiten des<br />

Programms noch sinnvoll ist.<br />

’ Starten von "Clapeyron"<br />

Private Sub CommandButton1_Click()<br />

’ Einlesen der Strukturdaten<br />

ierr = MClapeyron.LeseSystem(9, 1)<br />

’ Prüfen der Rückgabe<br />

Select Case ierr<br />

Case 1: MsgBox "Fehler: kein Feld gefunden!": Exit Sub<br />

End Select<br />

’ Einlesen Lastindex<br />

ierr = MClapeyron.GenLastIndex(9, 4)<br />

’ Prüfen der Rückgabe<br />

Select Case ierr<br />

Case 1: MsgBox "Fehler: keine Lasten gefunden!": Exit Sub<br />

End Select<br />

’ Einlesen der Lastdaten<br />

ierr = MClapeyron.GenLastdaten(9, 4)<br />

’ Aufbau der Kooefizientenmatrix<br />

ierr = MClapeyron.GenMatA()<br />

End Sub<br />

19.10.2011


Seite 84 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

G<br />

Lösungen zum Abschnitt Vektor- und Matrixobjekte<br />

In diesem Abschnitt wird das Arbeiten mit Vektoren und Matrizen unter Verwendung von<br />

Klassenmodulen (OOP) an Beispielen erläutert (siehe auch Abschnitt 9.2).<br />

G.1 Deklaration eines Vektor-Klassenmoduls<br />

In VBA ist es nicht möglich auf Feldelemente (Arrays) eines Klassenmoduls als Public zuzugreifen.<br />

Aus diesem Grund werden Zugriffsfunktionen als Methoden implementiert, die die internen<br />

Feldelemente x() belegen oder auslesen.<br />

Dim x() As Double ’ Vektorkomponenten<br />

Public n As Integer ’ Vektordimension<br />

Private Sub Class_Initialize()<br />

Dim i As Integer<br />

n = 3 ’ Vektoren aus R3<br />

ReDim x(1 To n)<br />

For i = 1 To n<br />

x(i) = 0<br />

Next<br />

x(1) = 1<br />

’ Initialisierung mit EV in X-Richtung<br />

End Sub<br />

’ Berechnen der Vektorlänge<br />

Public Function Laenge() As Double<br />

Dim i As Integer<br />

Laenge = 0#<br />

For i = 1 To n<br />

Laenge = Laenge + x(i) * x(i)<br />

Next i<br />

Laenge = Sqr(Laenge)<br />

End Function<br />

’ Vektornormierung<br />

Public Function Norm() As Double<br />

Dim i As Integer<br />

l = Laenge()<br />

For i = 1 To n<br />

x(i) = x(i) / l<br />

Next i<br />

Norm = 1<br />

End Function<br />

’ Vektor belegen<br />

E. Baeck


G. LÖSUNGEN ZUM ABSCHNITT VEKTOR- UND MATRIXOBJEKTE Seite 85<br />

Public Function SetX(dX() As Double) As Integer<br />

Dim ie As Integer<br />

ie = n<br />

If UBound(dX) < n Then ie = UBound(dX)<br />

For i = 1 To ie<br />

x(i) = dX(i)<br />

Next i<br />

SetX = 1<br />

End Function<br />

’ Vektor auslesen<br />

Public Function GetX(dX() As Double) As Integer<br />

Dim ie As Integer<br />

ie = n<br />

If UBound(dX) < n Then ie = UBound(dX)<br />

For i = 1 To ie<br />

dX(i) = x(i)<br />

Next i<br />

GetX = 1<br />

End Function<br />

’ Rotieren eines Vektors mit Drehmatrix "m"<br />

Public Function Rot(m As Matrix) As Integer<br />

Dim s As Double<br />

Dim xs() As Double<br />

ReDim xs(n)<br />

For i = 1 To n<br />

xs(i) = 0#<br />

For j = 1 To n<br />

xs(i) = xs(i) + m.GetK(i, j) * x(j)<br />

Next j<br />

Next i<br />

For i = 1 To n<br />

x(i) = xs(i)<br />

Next i<br />

Rot = 1<br />

End Function<br />

’ Zugriffsfunktion auf Feld x(i)<br />

Public Function xi(i As Integer) As Double<br />

xi = x(i)<br />

End Function<br />

’ Skalarprodukt mit anderem Vektor<br />

19.10.2011


Seite 86 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

Public Function sprod(v As Vektor) As Double<br />

Dim s As Double<br />

’ Skalarprodukt<br />

s = 0<br />

For i = 1 To n<br />

s = s + x(i) * v.xi(i)<br />

Next<br />

sprod = s<br />

End Function<br />

’ Testausgabe<br />

Public Function List() As Integer<br />

Debug.Print "Vektor: " + Format(x(1), "0.0000") + "; " + _<br />

Format(x(2), "0.0000") + "; " + _<br />

Format(x(3), "0.0000") + "; "<br />

List = 1<br />

End Function<br />

G.2 Deklaration eines Matrix-Klassenmoduls<br />

In VBA ist es nicht möglich auf Feldelemente (Arrays) eines Klassenmoduls als Public zuzugreifen.<br />

Aus diesem Grund werden Zugriffsfunktionen als Methoden implementiert, die die internen<br />

Feldelemente x() belegen oder auslesen.<br />

’ Klasse quadratischer n x n-Matrizen<br />

’<br />

Dim x() As Double<br />

Dim n As Integer<br />

Dim i, j As Integer<br />

Private Sub Class_Initialize()<br />

n = 3<br />

ReDim x(1 To n, 1 To n) As Double<br />

For i = 1 To n<br />

For j = 1 To n<br />

x(i, j) = 0#<br />

Next j<br />

Next i<br />

End Sub<br />

’ Belegen der Matrixelemente<br />

Public Function SetX(dX() As Double) As Integer<br />

For i = 1 To n<br />

For j = 1 To n<br />

x(i, j) = dX(i, j)<br />

Next j<br />

E. Baeck


G. LÖSUNGEN ZUM ABSCHNITT VEKTOR- UND MATRIXOBJEKTE Seite 87<br />

Next i<br />

SetX = 1<br />

End Function<br />

’ Lesen der Matrixelemente<br />

Public Function GetX(dX() As Double) As Integer<br />

For i = 1 To n<br />

For j = 1 To n<br />

dX(i, j) = x(i, j)<br />

Next j<br />

Next i<br />

GetX = 1<br />

End Function<br />

’ Lesen eines Matrixelements<br />

Public Function GetK(ByVal i1 As Integer, ByVal i2 As Integer) As Double<br />

GetK = x(i1, i2)<br />

End Function<br />

’ Testausdruck für den Fall n x n<br />

Public Function List() As Integer<br />

Debug.Print "Matrix: " + Format(x(1, 1), "0.0000") + "; " + _<br />

Format(x(1, 2), "0.0000") + "; " + _<br />

Format(x(1, 3), "0.0000") + "; "<br />

Debug.Print " " + Format(x(2, 1), "0.0000") + "; " + _<br />

Format(x(2, 2), "0.0000") + "; " + _<br />

Format(x(2, 3), "0.0000") + "; "<br />

Debug.Print " " + Format(x(3, 1), "0.0000") + "; " + _<br />

Format(x(3, 2), "0.0000") + "; " + _<br />

Format(x(3, 3), "0.0000") + "; "<br />

List = 1<br />

End Function<br />

19.10.2011


Seite 88 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

G.3 Programm Vektor 1<br />

Das Programm Vektor 1 erzeugt eine Instanz des Vektor-Klassemoduls. Der Vektor wird initialisiert.<br />

Es wird die Vektorlänge berechnet. Im zweiten <strong>Teil</strong> des Programms wird der Vektor<br />

normiert und zur Prüfung erneut die Vektorlänge berechnet und ausgegeben.<br />

’ Testprogramm für Klasse Vektor<br />

Sub vektor1()<br />

Dim l As Double<br />

Dim v As Vektor<br />

’ Vektorlänge<br />

’ Zeiger Vektor<br />

Dim x(1 To 3) As Double<br />

x(1) = 2: x(2) = 2: x(3) = 0<br />

Set v = New Vektor ’ Instanz von Vektor anlegen<br />

l = v.Laenge()<br />

Call v.List ’ Vektorausgabe in Direktfenster<br />

Debug.Print "Länge: " + Format(l, "0.000")<br />

r = v.SetX(x) ’ Daten setzen<br />

l = v.Laenge()<br />

Call v.List ’ Vektorausgabe in Direktfenster<br />

Debug.Print "Länge: " + Format(l, "0.000")<br />

Call v.Norm ’ Normierung des Vektors<br />

Call v.List ’ Vektorausgabe in Direktfenster<br />

l = v.Laenge() ’ Vektorlänge berechnen<br />

Debug.Print "Länge: " + Format(l, "0.000")<br />

End Sub<br />

E. Baeck


G. LÖSUNGEN ZUM ABSCHNITT VEKTOR- UND MATRIXOBJEKTE Seite 89<br />

G.4 Programm Vektor Drehen<br />

Das Programm Vektor Drehen erzeugt eine Instanz des Vektor-Klassemoduls v und eines Matrix-<br />

Klassenmoduls D. Der Vektor wird initialisiert. Die Matrix wird mit den Matrixelementen einer<br />

2d-Drehmatrix (Drehen um (0,0) um die z-Achse) belegt. Der Drehoperator wird in Form der<br />

Matrixmultiplikation v ′ = D · v ausgeführt.<br />

’ Vektor- und Matrixobjekte:<br />

’ - 2D-Drehmatrix, Drehen eines Vektors<br />

Sub Vektor_Drehen()<br />

Dim phi, co, si As Double<br />

Dim x(1 To 3, 1 To 3) As Double<br />

Dim y(1 To 3) As Double<br />

’ Drehwinkel<br />

phi = Atn(1#) / 45# * 90#<br />

’ Drehmatrix<br />

Dim m As Matrix<br />

’ Vektor<br />

Dim v As Vektor<br />

’ Initialisierungen<br />

Set m = New Matrix<br />

Set v = New Vektor<br />

co = Cos(phi)<br />

si = Sin(phi)<br />

x(1, 1) = co: x(1, 2) = -si: x(1, 3) = 0#<br />

x(2, 1) = si: x(2, 2) = co: x(2, 3) = 0#<br />

x(3, 1) = 0#: x(3, 2) = 0#: x(3, 3) = 1#<br />

y(1) = 1#: y(2) = 0#: y(3) = 0#<br />

’ Setzen der Objektwerte<br />

n = m.SetX(x)<br />

n = v.SetX(y)<br />

’ Ausgabe der Objekte<br />

n = m.List()<br />

n = v.List()<br />

’ Multiplikation: v := m*v<br />

n = v.Rot(m)<br />

’ Ausgabe des Vektors<br />

n = v.List()<br />

End Sub<br />

19.10.2011


Seite 90 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

H<br />

Lösungen zum Abschnitt Rahmen und Collection<br />

In diesem Abschnitt wird die Implementierung des Speicherkonzepts zum Rahmenbeispiel dargestellt.<br />

Es werden die Klassenmodule Stab und Knoten angelegt (siehe Abschnitt 9.4). Die<br />

Assoziation zwischen Stab und Knoten erfolgt über die Objektzeiger der Knoten-Instanzen.<br />

Stäbe und Knoten werden in den VBA-Listen , den Collections, gespeichert.<br />

H.1 Deklaration des Stab-Klassenmoduls<br />

Ein Stab-Objekt erhält die Attribute Stabnummer (Nr), E-Modul (E) und Querschnittsfläche<br />

(a) sowie die Knoten-Instanz-Zeiger KnA und KnB.<br />

Die Methode Laenge ermittelt die Stablänge über die Koordinatenwerte der assoziierten Knoten-<br />

Instanzen.<br />

Public Nr As Integer<br />

Public E As Double<br />

Public a As Double<br />

Public KnA As Knoten<br />

Public KnB As Knoten<br />

’ Nummer des Stabes<br />

’ E-Modul<br />

’ Fläche<br />

’ Knoten A<br />

’ Knoten B<br />

’ Berechnen der Stablänge<br />

Public Function Laenge() As Double<br />

Laenge = Sqr((KnA.x - KnB.x) ^ 2 + (KnA.y - KnB.y) ^ 2)<br />

End Function<br />

H.2 Deklaration des Knoten-Klassenmoduls<br />

Ein Knoten erhält die Attribute Knotennummer (Nr) und die Knotenkoordinaten (x und y).<br />

Die Methode Verschieben addiert einen Translationsvektor auf den Ortsvektor des Knotens<br />

(Koordindatenwerte).<br />

Public Nr As Integer<br />

Public x As Double<br />

Public y As Double<br />

’ Nummer des Knotens<br />

’ x-Koordinate<br />

’ y-Koordinate<br />

’ Verschieben eines Knotens<br />

Public Sub Verschieben(dx As Double, dy As Double)<br />

x = x + dx<br />

y = y + dy<br />

End Sub<br />

E. Baeck


H. LÖSUNGEN ZUM ABSCHNITT RAHMEN UND COLLECTION Seite 91<br />

H.3 Implementierung des Anwendungsprogramms<br />

Das Anwendungsprogramm besteht aus den folgenden drei <strong>Teil</strong>programmen.<br />

• Einlesen<br />

liest die Daten aus der Tabelle, erzeugt die Instanzen der Stäbe bzw. Knoten und speichert<br />

diese in die Stabliste SL bzw. Knotenliste KL. Als Parameter erwartet das Programm den<br />

Offset (i0,j0) des Eingabebereichs der Tabelle.<br />

• Ausgabe<br />

schreibt die Daten der Stäbe bzw. Knoten, die in den Listen (Collections) gespeichert wurden<br />

in den Ausgabebereich der Tabelle. Zudem wird noch die Länge der Stäbe ausgegeben.<br />

Als Parameter erwartet das Programm den Offset (i0,j0) des Ausgabebereichs der Tabelle.<br />

• Verschieben<br />

addiert den in der Tabelle eingegebenen Verschiebungsvektor auf alle Knotenkoordinaten.<br />

Als Parameter werden die Verschiebungen in x- bzw. y-Richtung erwartet.<br />

• StabAnzahl<br />

ermittelt als Hilfsfunktion die Anzahl der bereits eingegebenen Stäbe. Wurden keine Stäbe<br />

eingelesen, so wird vor dem Ausführen der Verschiebungsfunktion der Datenbestand eingelesen.<br />

H.3.1<br />

Die Listen<br />

Die Listen (Collection) werden als globale Variablen angelegt, damit sie von allen Programmen<br />

des Moduls erreichbar sind.<br />

Dim KL As New Collection<br />

Dim SL As New Collection<br />

’ Anlegen der Knotenliste<br />

’ Anlegen der Stabliste<br />

H.3.2<br />

Die Funktion Einlesen<br />

Es werden zunächst die Listen der Knoten und Stäbe zurückgesetzt, d.h. es werden alle Instanzen<br />

mit der Item-Funktion gelesen und gelöscht (=nothing). Der Indexeintrag der Collection wird<br />

mit der Funktion Remove entfernt. 33 Im nächsten Schritt werden zunächst die Knotendaten<br />

eingelesen und die Knotenliste aufgebaut. Die Knoten werden für den Aufbau der Stabdaten<br />

benötigt. Als letzter Schritt werden die Stabdaten eingelesen, hierbei werden die Knotennummern<br />

in Knotenverweise gewandelt. Diese werden aus der bereits existierenden Knotenliste abgegriffen.<br />

Die Parameter i0 und j0 sind Zeilen- und Spaltenoffset des Eingabebereichs der Tabelle.<br />

33 Da beim Löschen in einer Liste die verbleibenden Einträge zum Listenkopf rücken, wenn vor ihnen ein Eintrag<br />

gelöscht wird, wird mit der Anzahl der in der Liste gespeicherten Elemente immer der Erste Eintrag gelöscht.<br />

19.10.2011


Seite 92 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

’ Einlesen der Daten aus Tabelle<br />

Public Sub Einlesen(i0 As Integer, j0 As Integer)<br />

Dim s As Stab<br />

Dim k As Knoten<br />

’ nur Stabzeiger!<br />

’ Knotenzeiger<br />

’ Liste der Knoten zurücksetzen<br />

N = KL.Count<br />

For i = 1 To N<br />

Set k = KL(1) ’ Zeiger holen<br />

Set k = Nothing ’ Objekt löschen<br />

KL.Remove (1) ’ Index löschen<br />

Next<br />

’ Liste der Stäbe zurücksetzen<br />

N = SL.Count<br />

For i = 1 To N<br />

Set s = SL(1) ’ Zeiger holen<br />

Set s = Nothing ’ Objekt löschen<br />

SL.Remove (1) ’ Index löschen<br />

Next<br />

’ Einlesen der Knoten<br />

iZ = 1 ’ 1. Zeile<br />

Do While (Cells(i0 + iZ, j0 + 7) "")<br />

Set k = New Knoten<br />

’ neus Knotenobjekt anlegen<br />

k.Nr = Cells(i0 + iZ, j0 + 7)<br />

k.x = Cells(i0 + iZ, j0 + 8)<br />

k.y = Cells(i0 + iZ, j0 + 9)<br />

iZ = iZ + 1 ’ nächste Zeile<br />

KL.Add Item:=k, key:="K" & k.Nr<br />

Loop<br />

’ Einlesen der Stäbe<br />

iZ = 1 ’ 1. Zeile<br />

Do While (Cells(i0 + iZ, j0 + 1) "")<br />

Set s = New Stab<br />

’ neues Stabobjekt anlegen<br />

s.Nr = Cells(i0 + iZ, j0 + 1)<br />

s.E = Cells(i0 + iZ, j0 + 2)<br />

s.a = Cells(i0 + iZ, j0 + 3)<br />

nA = Cells(i0 + iZ, j0 + 4)<br />

nB = Cells(i0 + iZ, j0 + 5)<br />

Set s.KnA = KL("K" & nA)<br />

E. Baeck


H. LÖSUNGEN ZUM ABSCHNITT RAHMEN UND COLLECTION Seite 93<br />

Set s.KnB = KL("K" & nB)<br />

iZ = iZ + 1<br />

’ nächste Zeile<br />

SL.Add Item:=s, key:="S" & s.Nr<br />

Loop<br />

End Sub<br />

H.3.3<br />

Die Funktion Ausgabe<br />

In einer Schleife über die Stabliste werden alle Stab-Instanzen aus der Liste abgegriffen. Zunächst<br />

werden Stab-Attribute in den Ausgabebereich der Tabelle geschrieben. Die Knotenkoordinaten<br />

werden über die Verweise aus der assoziierten Knoteninstanz abgegriffen und ausgegeben. Die<br />

Länge des Stabes liefert die Methode Laenge des Stabes, die ihrerseits auf die Knotenkoordinaten<br />

der assoziierten Knoten-Instanzen verweisen (Abschnitt H.1). Die Parameter i0 und j0 sind<br />

Zeilen- und Spaltenoffset des Ausgabebereichs der Tabelle.<br />

’ Ausgabe der Daten in die Tabelle<br />

Public Sub Ausgabe(i0 As Integer, j0 As Integer)<br />

Dim s As Stab<br />

’ nur Stabzeiger!<br />

’ über alle Stäbe<br />

For i = 1 To SL.Count<br />

Set s = SL(i)<br />

’ Stab holen<br />

Cells(i0 + i, j0 + 1) = s.Nr<br />

Cells(i0 + i, j0 + 2) = s.E<br />

Cells(i0 + i, j0 + 3) = s.a<br />

Cells(i0 + i, j0 + 4) = s.KnA.x<br />

Cells(i0 + i, j0 + 5) = s.KnA.y<br />

Cells(i0 + i, j0 + 6) = s.KnB.x<br />

Cells(i0 + i, j0 + 7) = s.KnB.y<br />

Cells(i0 + i, j0 + 8) = s.Laenge()<br />

Next<br />

End Sub<br />

19.10.2011


Seite 94 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

H.3.4<br />

Die Funktion Verschieben<br />

In einer Schleife über die Knotenliste werden alle Knoten-Instanzen aus der Liste abgegriffen.<br />

Für jeder dieser Knoten-Instanzen wird die Knoten-Methode Verschieben aufgerufen (Abschnitt<br />

H.2).<br />

’ Knoten verschieben<br />

Public Sub Verschieben(vx As Double, vy As Double)<br />

Dim k As Knoten<br />

’ über alle Knoten<br />

For i = 1 To KL.Count<br />

Set k = KL(i)<br />

Call k.Verschieben(vx, vy)<br />

’ Knoten holen<br />

’ und verschieben<br />

Next<br />

End Sub<br />

H.3.5<br />

Die Funktion StabAnzahl<br />

Mit der Funktion StabAnzahl ermittelt die Verschieben-Ereignisfunktion, ob bereits Stab-<br />

Instanzen in die Stabliste gespeichert wurden. Hierfür ermittelt StabAnzahl über die Methode<br />

Count die Anzahl der Listenelemente.<br />

’ Anzahl der Stäbe ermitteln<br />

Public Function StabAnzahl() As Integer<br />

StabAnzahl = SL.Count<br />

End Function<br />

H.3.6<br />

Die Ereignisfunktionen<br />

Die erste Ereignisfunktion 34 wird aufgerufen, wenn die Schaltfläche Einlesen der Daten betätigt<br />

wird. Mit Offset (4,0) wird der Eingabebereich der Tabelle ausgelesen. Die Daten werden in<br />

Listen gespeichert und in aufbereiteter Form mit Offeset (22,0) in den Ausgabebereich der<br />

Tabelle eingetragen<br />

Private Sub CommandButton1_Click()<br />

Call Staebe.Einlesen(4, 0)<br />

Call Staebe.Ausgabe(22, 0)<br />

End Sub<br />

34 Die Ereignisfunktionen stehen im Code-Bereich des Tabellenobjekts, im Order Microsoft Excel Objekte.<br />

E. Baeck


H. LÖSUNGEN ZUM ABSCHNITT RAHMEN UND COLLECTION Seite 95<br />

Die zweite Ereignisfunktion wird aufgerufen, wenn die Schaltfläche Verschieben betätigt wird.<br />

Zunächst werden die Daten des Verschiebungsvektors (vx,vy) aus der Tabelle gelesen. Falls keine<br />

Stab-Instanzen in der Stabliste gefunden werden, wird der Eingabebereich der Tabelle eingelesen,<br />

die Datenstrukturen werden aufgebaut. Im zweiten Schritt werden die Knoten verschoben, im<br />

dritten die Daten des verschobenen Rahmens in den Ausgabebereich der Tabelle eingetragen.<br />

Private Sub CommandButton2_Click()<br />

Dim vx As Double<br />

Dim vy As Double<br />

vx = Range("VX")<br />

vy = Range("VY")<br />

’ Verschiebung in x<br />

’ Verschiebung in y<br />

If Staebe.StabAnzahl < 1 Then<br />

Call Staebe.Einlesen(4, 0)<br />

End If<br />

Call Staebe.Verschieben(vx, vy)<br />

Call Staebe.Ausgabe(22, 0)<br />

End Sub<br />

19.10.2011


Seite 96 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

I<br />

Lösungen zum Abschnitt 2-fach verkettete Listen<br />

In diesem Abschnitt wird die Implementierung einer 2-fach verketteten Liste dargestellt. Die<br />

Liste besteht aus zwei Klassenmodulen. Der Klassenmodul VListe ist das Hauptobjekt, das<br />

die einzelnen Listenmethoden enthält. Der Klassenmodul VNode dient als Listenelement, das<br />

zum einen Bestandteil der Listentopologie ist, zum anderen die Zeiger auf die Instanzen der<br />

einzuspeichernden Datenobjekte erhält (siehe Abschnitt 9.5).<br />

I.1 Deklaration des VNode-Klassenmoduls<br />

Der Listenknoten enthält nur eine Methode, die Initialisierung. Alle Zeiger werden auf nothing<br />

gesetzt. Der Knoten ist standardmäßig ein Datenknoten.<br />

Public prv As Object<br />

Public nxt As Object<br />

Public Dat As Object<br />

’ Zeiger auf vorhergehenden Knoten<br />

’ Zeiger auf nachfolgenden Knoten<br />

’ Zeiger auf Daten<br />

Public Ken As Integer<br />

’ 0: Datenknoten<br />

’ 1: Startknoten<br />

’ 2: Endknoten<br />

Private Sub Class_Initialize()<br />

Set prv = Nothing<br />

Set nxt = Nothing<br />

Set Dat = Nothing<br />

Ken = 0<br />

End Sub<br />

I.2 Deklaration des VListe-Klassenmoduls<br />

Der Klassenmodul VListe implementiert die Container-Klasse. In der Instanz-Initialisierung wird<br />

Start- und Endknoten in die Liste aufgenommen. Beide Knoten werden gegenseitig verzeigert.<br />

Public Count As Integer<br />

’ Anzahl der Datenknoten<br />

Public N1 As VNode<br />

Public NL As VNode<br />

’ Startknoten<br />

’ Endknoten<br />

Private Sub Class_Initialize()<br />

Set N1 = New VNode: N1.Ken = 1<br />

Set NL = New VNode: NL.Ken = 2<br />

’ Startknoten setzen<br />

’ Endknoten setzen<br />

Set N1.nxt = NL<br />

Set NL.prv = N1<br />

’ Liste ist leer<br />

’ Start -> Ende<br />

End Sub<br />

E. Baeck


I. LÖSUNGEN ZUM ABSCHNITT 2-FACH VERKETTETE LISTEN Seite 97<br />

I.2.1<br />

Daten am Listenkopf einfügen<br />

Implementierung nach Abschnitt 9.5.2.<br />

’ Objekt am Listenkopf einfügen<br />

Public Function AddFirst(Dat As Object) As Integer<br />

Dim N As New VNode<br />

’ Neuen Knoten erzeugen<br />

Set N1.nxt.prv = N<br />

Set N.nxt = N1.nxt<br />

Set N1.nxt = N<br />

’ ... ist Vorgänger des ehemals ersten<br />

’ ... der Nachfolger ist eben dieser<br />

’ ... der neue Knoten ist nun erster der Liste<br />

Set N.prv = N1<br />

Set N.Dat = Dat<br />

’ ... der Vorgänger des ersten ist der Startknoten<br />

’ ... und dann der Zeiger auf die Daten<br />

Count = Count + 1<br />

AddFirst = Count<br />

’ ... damit Liste um 1 vergrößert<br />

End Function<br />

I.2.2<br />

Daten am Listenende einfügen<br />

Implementierung nach Abschnitt 9.5.2.<br />

’ Objekt am Listenende einfügen<br />

Public Function AddLast(Dat As Object) As Integer<br />

Dim N As New VNode<br />

’ Neuen Knoten erzeugen<br />

Set NL.prv.nxt = N<br />

Set N.prv = NL.prv<br />

Set NL.prv = N<br />

’ ... ist nächster des letzten<br />

’ ... vorhergehender ist vormals letzter<br />

’ ... wird neuer letzter Knoten<br />

Set N.nxt = NL<br />

Set N.Dat = Dat<br />

’ ... Listenende zeigt auf neuen Knoten<br />

’ ... und Datenzeiger setzen<br />

Count = Count + 1<br />

AddLast = Count<br />

’ ... damit Liste um 1 vergrößert<br />

End Function<br />

19.10.2011


Seite 98 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

I.2.3<br />

Vorwärtsiterator<br />

Implementierung nach Abschnitt 9.5.4. Die Implementierung setzt voraus, dass die zurückgegebenen<br />

Listenknoten (Instanz VNode) vom aufrufenden Programm nicht verändert werden.<br />

’ Ersten Knoten holen<br />

Public Function GetFirst(Nd As VNode) As Integer<br />

If N1.nxt.Ken = 2 Then<br />

GetFirst = 0<br />

’ ... Listenende (Kein Datenknoten vorh.)<br />

Else ’ ... 0: Ende<br />

Set Nd = N1.nxt<br />

’ ... ersten Datenknoten holen<br />

GetFirst = 1 ’ ... 1: Daten vorhanden<br />

End If<br />

End Function<br />

’ Nächsten Knoten holen<br />

Public Function GetNext(Nd As VNode) As Integer<br />

If Nd.nxt.Ken = 2 Then<br />

’ ... Listenende (Kein weiterer Datenknoten vorh.)<br />

GetNext = 0 ’ ... 0: Ende<br />

Else<br />

Set Nd = Nd.nxt<br />

’ ... nächsten Datenknoten holen<br />

GetNext = 1 ’ ... 1: Daten vorhanden<br />

End If<br />

End Function<br />

In nachfolgendem Beispiel wird eine Liste mit Stab-Instanzen iteriert.<br />

...<br />

Dim L As new VListe ’ ... Instanz der Liste<br />

Dim Nd As New VNode<br />

’ ... Knoteninstatnz<br />

... Aufbau der Liste ...<br />

’ Liste vorwärts iterieren<br />

nret = L.GetFirst(Nd)<br />

’ ... holen des ersten Knotens<br />

Do While (nret > 0)<br />

’ ... nächsten holen solange das Ende<br />

Debug.Print " Stab: " & Nd.Dat.Nr ’ ... der Liste nicht erreicht ist.<br />

nret = L.GetNext(Nd)<br />

’ ... Zuvor Stabnummer ausgeben<br />

Loop<br />

...<br />

E. Baeck


I. LÖSUNGEN ZUM ABSCHNITT 2-FACH VERKETTETE LISTEN Seite 99<br />

I.2.4<br />

Einfügen eines Knotens<br />

Implementierung nach Abschnitt 9.5.2. Die Implementierung setzt voraus, dass die zurückgegebenen<br />

Listenknoten (Instanz VNode) vom aufrufenden Programm nicht verändert werden.<br />

Ein neuer Listenknoten ist im aufrufenden Programm zu erzeugen und mit den entsprechenden<br />

Daten zu versehen. Das Einfügen des Listenknotens in die Liste über nimmt die Methode Insert.<br />

’ Knoten einfügen vor Referenzknoten<br />

Public Function Insert(Nd As VNode, NdNew As VNode) As Integer<br />

If Nd.Ken = 1 Then<br />

Insert = 0<br />

Exit Function<br />

End If<br />

’ ... Einfügen vor Start nicht möglich<br />

Set Nd.prv.nxt = NdNew<br />

Set NdNew.prv = Nd.prv<br />

Set NdNew.nxt = Nd<br />

Set Nd.prv = NdNew<br />

’ ... prv- von Nd soll auf Ndnew zeigen<br />

’ ... Belegen der Zeiger des neuen Knotens<br />

’ ... NdNew wird vor Nd eingefügt<br />

Count = Count + 1<br />

Insert = 1<br />

’ ... damit Liste um 1 vergrößert<br />

End Function<br />

19.10.2011


Seite 100 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

J<br />

Lösungen zu Sortieralgorithmen<br />

In diesem Abschnitt wird das<br />

Laufzeitverhalten der Sortieralgorithmen<br />

SelectSort, BubbleSort<br />

und QuickSort verglichen.<br />

Mit der Schaltfläche Zufallszahlen<br />

werden Zufallszahlen im Bereich<br />

des vorgegebenen Zahlenintervalls<br />

erzeugt.<br />

Mit den weiteren Schaltflächen<br />

werden die drei verschiedenen<br />

Sortieralgorithmen aufgerufen.<br />

Die generierten Zufallszahlen<br />

werden nach Größe aufsteigend<br />

sortiert. Es wird jeweils die Anzahl<br />

der erfolgten Vertauschungen<br />

ausgegeben.<br />

Der erforderliche Aufwand der<br />

hier betrachteten Sortierverfahren<br />

SelectSort, BubbleSort und<br />

QuickSort ergibt sich zu<br />

Abbildung 52: Vergleich dreier Sortieralgorithmen<br />

• SelectSort benötigt n 2 /2 Vergleiche und n Vertauschungen.<br />

• BubbleSort benötigt im ungünstigsten Fall n 2 /2 Vergleiche und n 2 /2 Vertauschungen.<br />

• Quicksort benötigt im Mittel 2 · n · Ln(n) Vergleiche.<br />

Der Aufwand der Vergleiche bei elementaren Sortierverfahren ist ca. von gleicher Größenordnung.<br />

Dem gegenüber liegt der Aufwand der Vergleiche bei der QuickSort-Sortierung bei Orndung<br />

n · Log(n).<br />

Bei beispielsweise 300 Zufallszahlen 35 aus dem Intervall 1 bis 1000 benötigen SelectSort und<br />

BubbleSort 44850 Vergleiche (siehe Abbildung 52). Demgegenüber benötigt Quicksort 605 Vergleiche.<br />

36<br />

35 Die für die Sortierung erzeugten Reihen von Zufallszahlen sind in den vorliegenden Sortierungen unterschiedlich.<br />

Das Laufzeitverhalten ist jedoch annähernd unabhängig von der gewählten Zufallszahlenreihe.<br />

36 Quicksort benötigt ca. n · Log(n) Vergleiche, die beiden anderen Sortierungen benötigen ca. n 2 /2 Vergleiche.<br />

Bei n = 1000 ergibt sich ein Leistungsquotient von (n · Log(n))/n 2 /2 = 2 · Log(n)/n = 2 · 3/1000 = 0, 6%, d.h.<br />

der Aufwand für Quicksort im Vergleich zu den beiden anderen Sortierverfahren liegt bei 1000 zu sortierenden<br />

Elementen demnach unter 1%.<br />

E. Baeck


J. LÖSUNGEN ZU SORTIERALGORITHMEN Seite 101<br />

J.1 Die Ereignisfunktionen<br />

Die Ereignisfunktionen werden aus dem Modul Sortieren aufgerufen. Als Parameter werden die<br />

Offsets des Bereichs der Tabelle übergeben, in der die Zufallszahlen ausgegeben werden. Zudem<br />

wird die Anzahl der generierten Zufallszahlen aus dem Eingabebereich der Tabelle mit Range<br />

gelesen und übergeben.<br />

Private Sub CommandButton1_Click()<br />

Call Sortieren.Zufallszahlen(9, 0, Range("SORTANZ"))<br />

End Sub<br />

Private Sub CommandButton2_Click()<br />

Call Sortieren.SelectSortieren(9, 0, Range("SORTANZ"))<br />

End Sub<br />

Private Sub CommandButton3_Click()<br />

Call Sortieren.QuickSortieren(9, 0, Range("SORTANZ"))<br />

End Sub<br />

Private Sub CommandButton4_Click()<br />

Call Sortieren.BubbleSortieren(9, 0, Range("SORTANZ"))<br />

End Sub<br />

J.2 Generierung der Zufallszahlen<br />

Die Zufallszahlen können in VBA mit der Funktion Rnd 37 erzeugt werden. Rnd liefert hierfür<br />

eine Zufallszahl 38 .<br />

Die genierten Zufallszahlen werden wie folgt in das vorgegebene Intervall skaliert.<br />

Z = (Z bis − Z von ) · Z rnd + Z von (74)<br />

Das Intervall der Zufallszahlen wird aus der Tabelle über Range abgegriffen. Bevor die Zufallszahlen<br />

generiert und die Tabelle geschrieben werden, wird diese im Ausgabebereich zunächst von<br />

Altdaten befreit, d.h. es wird die Hilfsfunktion Loeschen aufgerufen. Es wird die erste Spalte<br />

nach Einträgen untersucht. Falls ein Eintrag gefunden wird, wird die Anzahl der vorgegebenen<br />

Spalten gelöscht. Falls kein Eintrag gefunden wird, geht das Programm davon aus, dass das<br />

Ende des zu löschenden Bereichs erreicht wurde.<br />

37 Reihen von Zufallszahlen sind dann reproduzierbar, wenn der Zufallszahlengenerator nicht mit einer zufälligen<br />

<strong>Info</strong>rmation vorbesetzt wird. Dies erfolgt durch Aufruf der Routine Randomize<br />

38 Ein Zufallszahlen-Generator erzeugt Pseudo-Zufallszahlen. Pseudo-Zufallszahl bedeutet, dass bei exakt identischen<br />

Eingangsdaten (Zeitwerte etc.) der Zufallszahlen-Generators Zahlen reproduzierbar erzeugt. Da die Eingangsdaten<br />

des Zufallszahlen-Generators kaum reproduzierbar und somit zufällig sind, die Algorithmen jedoch<br />

deterministisch, werden die generierten Zahlen nicht als Zufallszahlen sondern als Pseudo-Zufallszahlen bezeichnet.<br />

Der Einfachheit halber sind hier Zufallszahlen generell als Pseudo-Zufallszahlen zu verstehe.<br />

19.10.2011


Seite 102 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

’ Erzeugen von Zufallszahlen<br />

Sub Zufallszahlen(i0 As Integer, j0 As Integer, nAnz As Integer)<br />

Dim dVon As Double<br />

Dim dBis As Double<br />

dVon = Range("S_VON")<br />

dBis = Range("S_BIS")<br />

’ Tabelle löschen<br />

i = Util.Loeschen(i0, j0, 2)<br />

’ Zufallszahlen generieren<br />

call Randomize<br />

For i = 1 To nAnz<br />

Cells(i0 + i, 1) = i<br />

Cells(i0 + i, 2) = (dBis - dVon) * Rnd + dVon<br />

Next<br />

End Sub<br />

Nachfolgend das Hilfsprogramm Loeschen, dass einen Tabellenbereich löscht unter Vorgabe des<br />

Zeilen- und Spaltenoffset sowie der Spaltenanzahl.<br />

’ Löschen eines Tabellenbereichs<br />

Public Function Loeschen(i0 As Integer, j0 As Integer, nSpalten As Integer) _<br />

As Integer<br />

Dim nZeile As Integer<br />

Dim i As Integer<br />

’ Zeilenzähler<br />

nZeile = 1<br />

’ erste Zeile ’lokal’<br />

’ über alle Zeilen<br />

Do Until Cells(i0 + nZeile, j0 + 1) = ""<br />

’ über die Spalten<br />

For i = 1 To nSpalten<br />

Cells(i0 + nZeile, j0 + i) = ""<br />

Next<br />

nZeile = nZeile + 1<br />

Loop<br />

Loeschen = nZeile<br />

End Function<br />

E. Baeck


J. LÖSUNGEN ZU SORTIERALGORITHMEN Seite 103<br />

J.3 Sortieralgorithmen<br />

In diesem Abschnitt wird eine VBA-Implementierung der Sortieralgorithmen SelectSort (siehe<br />

6.1), BubbleSort (siehe 6.2) und QuickSort (siehe 10.1) dargestellt.<br />

Um die Leistungsfähigkeit der Algorithmen darzustellen werden die globalen Variablen nT ausch<br />

und nV ergleich als Zähler für Vertauschungen und Vergleiche eingeführt. Die Zähler werden<br />

jeweils vor der Sortierung zurückgesetzt. Die Vertauschung der Zufallszahlen erfolgt in folgender<br />

Routine, die von allen implementierten Sortierverfahren aufgerufen wird.<br />

’ Datensätze tauschen<br />

Sub tausche(i, j)<br />

For k = 1 To 2<br />

s = Cells(i, k)<br />

Cells(i, k) = Cells(j, k)<br />

Cells(j, k) = s<br />

Next<br />

nTausch = nTausch + 1<br />

End Sub<br />

J.3.1<br />

Implementierung von SelectSort<br />

’ Hauptprogramm: Selectsort<br />

Sub SelectSortieren(i0 As Integer, j0 As Integer, nAnz As Integer)<br />

nTausch = 0<br />

nVergleich = 0<br />

’ Protokoll<br />

Cells(i0 + 1, j0 + 3) = "Sortierung in Arbeit..."<br />

’ über alle Auswahlpositionen<br />

For i = 1 To nAnz - 1<br />

x = i<br />

’ extremale Größe aus Intervall ermitteln<br />

For j = i + 1 To nAnz<br />

dvj = Cells(i0 + j, 2)<br />

dvx = Cells(i0 + x, 2)<br />

If dvj < dvx Then x = j<br />

nVergleich = nVergleich + 1<br />

Next<br />

’ extremale Größe an aktuelle Spitzenposition tauschen<br />

Call tausche(i0 + i, i0 + x)<br />

Next<br />

19.10.2011


Seite 104 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

’ Protokoll<br />

Cells(i0 + 1, j0 + 3) = Format(nVergleich, "0") + " Vergleiche und " + _<br />

Format(nTausch, "0") + " Vertauschungen (SelectSort)"<br />

End Sub<br />

J.3.2<br />

Implementierung von BubbleSort<br />

’ Hauptprogramm: Bubblesort<br />

Sub BubbleSortieren(i0 As Integer, j0 As Integer, nAnz As Integer)<br />

nTausch = 0<br />

nVergleich = 0<br />

’ Protokoll<br />

Cells(i0 + 2, j0 + 3) = "Sortierung in Arbeit..."<br />

’ über alle Auswahlpositionen<br />

For i = nAnz To 1 Step -1<br />

’ Auswahlgebiet<br />

For j = 2 To i<br />

dV1 = Cells(i0 + j - 1, j0 + 2)<br />

dv2 = Cells(i0 + j, j0 + 2)<br />

nVergleich = nVergleich + 1<br />

If dV1 > dv2 Then<br />

Call tausche(i0 + j - 1, i0 + j)<br />

End If<br />

Next<br />

Next<br />

’ Protokoll<br />

Cells(i0 + 2, j0 + 3) = Format(nVergleich, "0") + " Vergleiche und " + _<br />

Format(nTausch, "0") + " Vertauschungen (BubbleSort)"<br />

End Sub<br />

E. Baeck


J. LÖSUNGEN ZU SORTIERALGORITHMEN Seite 105<br />

J.3.3<br />

Implementierung von QuickSort<br />

’ Hauptprogramm: Quicksort<br />

Sub QuickSortieren(i0 As Integer, j0 As Integer, nAnz As Integer)<br />

nTausch = 0<br />

nVergleich = 0<br />

’ Protokoll<br />

Cells(i0 + 3, j0 + 3) = "Sortierung in Arbeit..."<br />

’ Sortierung<br />

Call qsort(i0 + 1, i0 + nAnz)<br />

’ Protokoll<br />

Cells(i0 + 3, j0 + 3) = Format(nVergleich, "0") + " Vergleiche und " + _<br />

Format(nTausch, "0") + " Vertauschungen (QuickSort)"<br />

End Sub<br />

Im folgenden wird das Programm qsort dargestellt, das rekursiv ein Intervall der zu sortierenden<br />

Menge bezogen auf einen <strong>Teil</strong>er vorsortiert. 39 ausgeschaltet würde.<br />

’ Vorsortierung des Bereichs von l (links) bis r (rechts)<br />

Sub qsort(l, r)<br />

’ <strong>Teil</strong>feld enthält nur ein Element<br />

If r


Seite 106 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

’ mit j von rechts nach links<br />

Do<br />

j = j - 1<br />

w = Cells(j, 2)<br />

nVergleich = nVergleich + 1<br />

Loop While w > v and j > l<br />

’ bereits vorsortiert<br />

If i >= j Then Exit Do<br />

Call tausche(i, j)<br />

Loop<br />

’ Setze r an endgültige Position<br />

Call tausche(i, r)<br />

’ das ganze dann auf <strong>Teil</strong>gebiete anwenden<br />

’ - linkes <strong>Teil</strong>gebiet<br />

Call qsort(l, i - 1)<br />

’ - linkes <strong>Teil</strong>gebiet<br />

Call qsort(i + 1, r)<br />

End Sub<br />

E. Baeck


K. LÖSUNG ZUR BRENDT’SCHEN FORMEL Seite 107<br />

K<br />

Lösung zur Brendt’schen Formel<br />

In diesem Abschnitt eine Implementierung<br />

der Brendt’schen Formel<br />

(Gleichung 12) gegeben.<br />

Mit der ersten Schaltfläche wird<br />

die einzulesende Datei, die die<br />

Profildaten enthält, festgelegt.<br />

Mit der zweiten Schaltfläche wird Abbildung 53: Einlesen einer sequentiellen Datei<br />

das Einlesen der Profildaten aus<br />

der vorgegebenen Datei und die Berechnung des Torsionsträgheitsmomentes nach 2. Brendt’scher<br />

Formel angestoßen.<br />

K.1 Die Ereignisfunktion zur Festlegung des Dateinamens<br />

Um den Dateinamen der einzulesenden Datei festzulegen wird in der Ereignisfunktion die Methode<br />

GetOpenFilename des EXCEL-Application-Objekts eingesetzt.<br />

Private Sub CommandButton1_Click()<br />

datei$ = Application.GetOpenFilename( _<br />

filefilter:="Textdatei (*.txt),*.txt")<br />

If Not datei$ = "Falsch" Then<br />

Range("DNAME") = datei$<br />

Abbildung 54: Dateinamen festlegen<br />

End If<br />

End Sub<br />

K.2 Die Ereignisfunktion zu Datenimport und Berechnung<br />

Wurde der Dateinamen vereinbart, kann die zweite Funktion<br />

Lesen aus dem Modul Brendt gestartet werden.<br />

Sie importiert die Daten aus der vereinbarten Textdatei<br />

und berechnet die gewünschten Größen nach der 2.<br />

Brendt’schen Formel. Im Beispiel der Abbildung 55 wird<br />

ein rechteckiges Kastenprofil mit koinstanter Blechdicke<br />

beschrieben.<br />

Abbildung 55: Eingabedaten<br />

Private Sub CommandButton2_Click()<br />

Call Brendt.Lesen<br />

End Sub<br />

19.10.2011


Seite 108 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

K.3 Die Datenstruktur<br />

Die Konturknoten des Profils, d.h. je ein Datensatz der Datei, werden in Datenstrukturen (Type)<br />

gespeichert. Da mehrere Knoten zu speichern sind, wird ein Feld als globale Variable des Typs<br />

KKNOTEN angelegt. Die Anzahl der Knoten soll dynamisch zur Laufzeit des Programms vereinbart<br />

werden, d.h. der Indexbereich des Feldes wird zunächst leer gelassen (K()).<br />

’ Knoten der Kontur<br />

Type KKNOTEN<br />

y As Double<br />

z As Double<br />

t As Double<br />

End Type<br />

’ Variable der Kontur<br />

Dim K() As KKNOTEN<br />

K.4 Einlesen der Daten aus der Profil-Textdatei<br />

Das Hauptprogramm der Verarbeitung Lesen wird aus dem Modul Brendt gestartet, somit ist<br />

es als Public zu vereinbaren.<br />

1. In einem ersten Schritt wird zunächst die Anzahl der Konturknoten ermittelt. Ein Knoten<br />

wird im Knotenfeld angelegt (Redim K(1 to 1)).<br />

2. In einem zweiten Schritt wird die Datei geöffnet. Es werden die Datensätze, d.h. die Anzahl<br />

der Knoten in der Datei ermittelt. Für diese und den gedoppelten 1. Knoten, da zyklisches<br />

Problem, wird der Speicherplatz angelegt.<br />

3. Im dritten Schritt wird die Datei erneut geöffnet. Nun werden die Daten in die Datenstruktur<br />

gelesen. Nach Ende des Einlesens wird die Datei geschlossen und der erste Knoten als<br />

Kopie in den Speicher des N+1-ten geschrieben.<br />

4. Die Ausgabetabelle wird von Altdaten befreit. Die in der Datenstruktur gespeicherten<br />

Daten werden in die Tabelle geschrieben.<br />

5. Die Berechnung nach der 2. Brendt-schen Formel wird gestartet.<br />

’ Einlesen der Daten<br />

Public Sub Lesen()<br />

Dim datei As String<br />

Dim nAnz As Integer<br />

Dim i As Integer<br />

’ Dateiname<br />

’ Anzahl der Knoten<br />

datei = Range("DNAME")<br />

nAnz = 0<br />

’ Dateinamen aus Tabelle holen<br />

’ Konturknotenanzahl bestimmen<br />

’ Datei öffnen<br />

E. Baeck


K. LÖSUNG ZUR BRENDT’SCHEN FORMEL Seite 109<br />

ReDim K(1 To 1)<br />

Open datei For Input As #1<br />

’ Datei zum Lesen öffnen<br />

’ über alle Datensätze<br />

Do Until EOF(1)<br />

’ Lesen bis zum Dateiende<br />

Input #1, K(1).y, K(1).z, K(1).t<br />

nAnz = nAnz + 1 ’ ... und Datensätze zählen,<br />

Loop<br />

’ Datei schließen<br />

Close #1<br />

’ dann Datei wieder schließen<br />

’ Konturknotendatenstruktur<br />

ReDim K(1 To nAnz + 1)<br />

Open datei For Input As #1<br />

’ Jetzt Speicher für Knoten anlegen<br />

’ und Datei erneut öffnen<br />

’ über alle Datensätze<br />

For i = 1 To nAnz<br />

’ Einlesen und speichern aller Knotendaten<br />

Input #1, K(i).y, K(i).z, K(i).t<br />

Next<br />

K(nAnz + 1) = K(1)<br />

’ Datei schließen<br />

Close #1<br />

’ 1. Knoten als Knoten N+1 doppeln,<br />

’ da zyklisches Problem<br />

’ Ausgaber der Daten in Tabelle<br />

Call Loeschen("KKTAB", 3)<br />

For i = 1 To nAnz + 1<br />

Range("KKTAB")(i, 1) = K(i).y<br />

Range("KKTAB")(i, 2) = K(i).z<br />

Range("KKTAB")(i, 3) = K(i).t<br />

Next<br />

’ Berechnung durchführen und Werte ausgeben<br />

Call Berechnung<br />

’ Starten der Berechnung<br />

End Sub<br />

Das Löschen der Tabelle erfolgte mit folgendem Programm. Der erste Paramter ist die Bezeichnung<br />

des ersten Tabellenfeldes, d.h. des Tabellenfeldes der ersten Zeile und der ersten Spalte.<br />

Der zweite Parameter gibt an, wieviele Spalten gelöscht werden sollen, wenn in der ersten Spalte<br />

der betrachteten <strong>Teil</strong>tabelle kein Leertext gefunden wird. Der Vorgang des Löschens beginnt in<br />

der ersten Tabellenzeile und wird solange in einer nächsten Zeile fortgesetzt, bis in dieser ein<br />

Leertext gefunden wird.<br />

’ Löschen eines Tabellenbereichs<br />

Sub Loeschen(z0 As String, nSpa As Integer)<br />

Dim iz As Integer<br />

19.10.2011


Seite 110 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

Dim j As Integer<br />

iz = 1<br />

Do While Range(z0)(iz, 1) ""<br />

For j = 1 To nSpa<br />

Range(z0)(iz, j) = ""<br />

Next<br />

Loop<br />

End Sub<br />

K.5 Hilfsfunktionen der Berechnung<br />

Um das Berechnungsprogramm übersichtlicher zu gestalten, werden allgemeine Rechenoperationen,<br />

wie die Bestimmung einer mittleren Dicke zwischen zwei Knoten, die Berechnung des<br />

Abstandes zweier Knoten und die Berechnung der Polygonfläche in Unterprogrammen ausgelagert.<br />

K.5.1<br />

Berechnung der mittlerern Blechdicke<br />

Die Funktion berechnet die mittlere Dicke der Verbindung zwischen den Konturknoten i und<br />

i+1.<br />

’ Gestimmt die Dicke<br />

Public Function GetDicke(i As Integer) As Double<br />

GetDicke = (K(i).t + K(i + 1).t) / 2<br />

End Function<br />

K.5.2<br />

Berechnung des Knotenabstandes<br />

Die Funktion berechnet den Abstand zwischen den Knoten i und i+1.<br />

’ Gestimmt die Länge<br />

Public Function GetLaenge(i As Integer) As Double<br />

GetLaenge = Sqr((K(i).y - K(i + 1).y) ^ 2 + (K(i).z - K(i + 1).z) ^ 2)<br />

End Function<br />

E. Baeck


K. LÖSUNG ZUR BRENDT’SCHEN FORMEL Seite 111<br />

K.5.3<br />

Berechnung der Polygonfläche<br />

Die Funktion berechnet den Flächeninhalt der durch die Konturknoten aufgespannten Fläche.<br />

Es wird vorausgesetzt, dass der 1. Konturknoten als n+1 -Knoten in der Knotenliste ergänzt<br />

wurde.<br />

’ Gestimmt die Fläche eines Polygons<br />

Public Function GetFlaeche() As Double<br />

Dim i As Integer<br />

Dim A As Double<br />

A = 0<br />

For i = 1 To UBound(K) - 1 ’ über alle Knoten<br />

A = A + K(i).y * K(i + 1).z - K(i).z * K(i + 1).y<br />

Next<br />

GetFlaeche = A / 2<br />

End Function<br />

19.10.2011


Seite 112 <strong>Bauinformatik</strong> - <strong>Teil</strong> 1 - Übungsskript / 2011<br />

Literatur<br />

[1] H. Rubin, K.-J. Schneider<br />

<strong>Baustatik</strong>, Theorie I. und II. Ordnung<br />

Werner Verlag, 2002<br />

[2] H. R. Schwarz<br />

Methode der finiten Elemente<br />

Teubner Studienbücher Mathematik, B.G. Teubner, Stuttgart 1984<br />

[3] R. Sedgewick<br />

Algorithmen in C++<br />

(auch für VBA-Programmierung als Vorlage zu empfehlen!)<br />

Addison-Wesley, 1992<br />

[4] Peter Fröhlich (Hrsg.)<br />

Berechnungsbibliothek Bauwesen<br />

Vieweg & Sohn Verlagsgesellschaft mbH, Braunschweig/Wiesbaden, 1998<br />

E. Baeck

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!