Bauinformatik Teil 1 - Baustatik-Info-Server
Bauinformatik Teil 1 - Baustatik-Info-Server
Bauinformatik Teil 1 - Baustatik-Info-Server
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