Thomas Woelfers Baustatik Blog

Baustatik-Software und was sonst des Weges kommt

Bald: Geometrie verschieben, rotieren, spiegeln

Das nächste Update von Baustatik steht demnächst an. Auf die neue Fensterverwaltung, die in diesem Zusammenhang kommen wird, war ich ja schon eingegangen. Ein anderer umfangreicher Punkt - von vielen Anwendern bisher schmerzlich vermisst - ist das verschieben, rotieren und spiegeln der Auswahl. Das wird aber im kommenden Update endilch auch drin sein. Konstrukte wie das aus der Abbildung sind dann also endlich deutlich weniger aufwendig herzustellen.

Leute gibts

Zum Beispiel der Mensch neben mir auf dem Rückflug Düsseldorf -> München. Er hatte auf den 50 Minuten Flug genau 2 Beschäftigungen: Nacktfotos diverser Damen aus einem Magazin bewundern und per Handy SMS abholen. Beide natürlich sehr verstohlen. So verstohlen das eben geht, wenn man Sitz an Sitz sitzt und das Heft A4 Format hat. Als er dann mit den SMS anfing, fing ich an mir Gedanken zu machen: Sagt ich nun was, oder glaube ich weiterhin daran, das das Handy-Verbot in Fliegern in Wirklichkeit keine Sicherheitsgeschichte ist, sondern in Wirklichkein nur eine Lärmbelästigungs-Vermeidungsregel. Ich habe dann nichts gesagt, und der Flieger kam heil runter.

Beweist natürlich gar nichts.

Der Fall mit der langen Berechnungszeit

Heute ist mir eine Datei untergekommen, bei der die Rechenzeit doch eher im unbrauchbaren Bereich lag: Das erzeugen des Netzes alleine brauchte fast 2 Stunden - damit kann man natürlich nicht vernünftig arbeiten. Beim System handelte es sich um eine Bodenplatte von etwa 100 x 30 m, die mit relativ vielen Einzellasten belastet war - außerdem waren ein paar Wände definiert.

Insgesamt gab es etwa 3600 Einzeleinwirkungen auf der Bodenplatte - und nach ein paar näheren Untersuchungen waren die es auch, die sich als das Problem herausstellten: Die Lasten waren als Knotenlasten und nicht als Faltwerkselement-Einzeleinwirkung definiert. Prinzipiell sollte es egal sein, welche der beiden Einwirkungsarten man verwenden - von der Performance her ist es aber so, das die deutlich besser wird, wenn man die Last als Faltwerkselement-Einzeleinwirkung definiert: In diesem Fall ist nämlich die zugehörige Platte schon bekannt und muss nicht erst ermittelt werden.

(Unabhängig davon ist das aktuelle Performance-Verhalten so nicht angebracht: Das werden wir auf jeden Fall nochmal näher untersuchen und verbessern.)

Die Lösung des Performance-Problems lag dann darin, das einfach alle Knoteneinwirkungen und Faltwerkselement-Einwirkungen "umgebaut" werden mussten. Man muss also die eine Einwirkung löschen, und dafür eine andere anlegen. Was kein Problem wäre - würde es sich nicht um 3600 Stück davon handeln. Die Lösung: Das folgende Makro. (Man erkennt schnell die Ähnlichkeit mit dem von gestern...:-) )


   IShell shell = context.TargetDocument.FindObject("NameDerPLatte", typeof(Shell)) as IShell;

   IDocObjectCollection loads = context.TargetDocument.GetObjects(typeof(INodeLoad));

   foreach (INodeLoad load in loads)
   {
      if( load.Lcs == LocalCoordinateSystem.Unit())
      {
         ShellSingleLoad newLoad = ShellSingleLoad.CreateNamed(context.TargetDocument);

         newLoad.ObjectName = load.ObjectName;
         newLoad.Loadcase = load.Loadcase;
         newLoad.LoadType = ShellSingleLoadTypes.Global;
         newLoad.SizeX = load.SizeX;
         newLoad.SizeY = load.SizeY;
         newLoad.SizeZ = load.SizeZ;
         newLoad.SizeXX = load.SizeXX;
         newLoad.SizeYY = load.SizeYY;
         newLoad.SizeZZ = load.SizeZZ;
         newLoad.Comment = load.Comment;
         newLoad.Node = load.Node;
         newLoad.Shell = shell;

         context.TargetDocument.RemoveObject(load);
         context.TargetDocument.AddObject(newLoad);
      }
   }

 

Beispielmakro: Stäbe zu Unterzügen

Vorab:

Makros in Baustatik
Erste Dokumentation für Baustatik-Makros

Es gibt Fälle, in denen man vorhandene Stäbe in Unterzüge umwandeln will - und zumindest zur Zeit liefern wir dafür keine fertige Funktion mit. Als Makro ist die Sache aber relativ einfach zu haben: Hier ein Makro, das genau diese Funktion erfüllt - zusammen mit ein paar Anmerkungen.

using System;
using DIE.Framework.ApplicationModell.Commands;
using DIE.Applications.Faltwerk.Objects.Beams;
using DIE.Applications.Faltwerk.Objects.BindingBeams;
using DIE.Framework.ObjectModell;

namespace MeineMakros
{
    public class stab2unterzug : UserCommandBase
    {
      // Initialisierung des Makrobefehls.
        public stab2unterzug() : base(@"stab2unterzug", @"übersetzt stäbe in unterzüge")
        {
        }
        
        // Einsprungsfunktion des Makros
        public override void Execute(IExecuteCommandContext context)
        {
            // alle balken holen (alternativ könnte man auch nur die
            // holen, die momentan ausgewäht sind.)
            IDocObjectCollection beams = context.TargetDocument.GetObjects( typeof(Beam));
            
            // über alle balken iterieren.
            foreach( IBeam beam in beams)
            {
                // für jeden balken einen neuen unterzug anlegen.
                BindingBeam bindingBeam = new BindingBeam();
                
                // all eigenschaften übertragen. die findet man in der
                // referenz-dokumentation (baustatik.chm) für die Objekte unter
                // http://www.die.de/blog/PermaLink.aspx?guid=d0d11a5f-9a4c-403b-8e48-1176fdf4b57b
                bindingBeam.ObjectName = beam.ObjectName;
                bindingBeam.StartProfile = beam.StartProfile;
                bindingBeam.EndProfile = beam.EndProfile;
                bindingBeam.Material = beam.Material;
                bindingBeam.DesignParameter = beam.DesignParameter;
                bindingBeam.AdditionalProfileRotation = beam.AdditionalProfileRotation;
                bindingBeam.Anfangsknoten = beam.Anfangsknoten;
                bindingBeam.Endknoten = beam.Endknoten;
                bindingBeam.RotLocalX = beam.RotLocalX;
                bindingBeam.StartJoint = beam.StartJoint;
                bindingBeam.EndJoint = beam.EndJoint;
                
                // den nicht mehr benötigten Stab löschen
                context.TargetDocument.RemoveObject( beam);
                
                // den neuen unterzug ins dokument tun
                context.TargetDocument.AddObject( bindingBeam);
            }
        }
    }
}

Wie man sieht: Auch wenn eine bestimmte Funktion nicht von uns mitgeliefert wird - mit wenigen Zeilen kann man sowas leicht selbst nachrüsten. :-)

 

stab2unterzug.cs (1.91 KB)

Eingabeaufforderung hier öffnen

Heute bei Raymond gefunden: Unter Vista enthält das Kontext-Menü im Explorer mehr Befehle, wenn man zusätzlich zum Rechtsklick auch die Shift-Taste drückt.  (Scheint nur auf den rechten Bereich des Explorers zuzutreffen.)

Im Fall von Ordnern gibt es zwei zusätzliche Befehle: "Eingabeaufforderung hier öffnen" - von früher aus den PowerToys unter dem Namen "Command Prompt her" bekannt, und "Als Pfad kopieren". Letzteres kopiert den kompletten Pfad zum Verzeichnis als Text in die Zwischenablage. Sehr praktisch für Skripte und ähnliche Anwendungen.

 

Windows Vista: Rahmen vom Snipping-Tool loswerden

Das Snipping-Tool ist auch so eines der netten Programme, die ich bei Vista schätze: Dabei handelt es sich im Wesentlichen um ein Werkzeug, mit dem man Screenshots machen oder auch einfach nur Teile des Bildschirms in die Zwischenablage bekommt. Ich benutze das eigentlichen dauernd - praktisch alle Bilder, die im Blog in letzter Zeit aufgetaucht sind, habe ich damit gemacht.

Eines hat mich aber gestört: Markiert man einen Bereich, dann hat die Markierung einen Rand (was nicht weiterverwunderlich ist) - aber dieser Rand taucht dann auch im Bild in der Zwischenablage auf. Heute hats dann gereicht und ich habe nachgesehen. Und ja - man kann den Rand ausschalten, auch wenn der Text der zugehörigen Option alles andere als klar ist. Zu finden ist der Schalter unter "Extras -> Optionen", und hat dort den meiner Ansicht nach völlig unverständlichen Namen "Freihand des markierten Bereichs nach dem Ausschneiden anzeigen".

Wie auch immer: Schaltet man die "Freihand" aus, dann gibts keinen Rahmen mehr.

Woran wir mit Baustatik gerade arbeiten ...

... ist nicht mit einem Satz zu beantworten. Eine Sache die mir aber wichtig ist, ist das Problem mit den "vielen Fenstern". Das Hauptproblem dabei ist, das vielen Anwendern der Baustatik gar nicht klar ist, das diese Fenster offen sind. Ich versuchs mal zu erklären....

Jedesmall, wenn man mit der Projektansicht eine Datei öffnet, dann wird ein Fenster geöffnet, in dem die Datei angezeigt wird. Im Normalfall ist das Arbeitsfenster maximiert - und das führt dann dazu, das auch das neue Fenster maximiert wird, und das zuvor bereits offenen Fenster überdeckt: Man sieht also nicht, das dann bereits zwei Fenster offen sind. Öffnet man die nächste Datei, dann sind bereits 3 Fenster offen.

Soweit ist das nicht weiter dramatisch - die Sache, die das zum echten Problem macht, kommt jetzt: Wenn man das Programm beendet, dann merkt es sich alle möglichen Dinge. Auf welchem Monitor das Hauptfenster war. Welche Unterfenster offen waren - und wo sie waren. Wie groß welche Fenster waren. Ob sie maximiert waren oder nicht...

Beim nächsten Start wird dann genau dieser Zustand wieder hergestellt. Resultat: Direkt nach dem Start sind bereits 3 Fenster geöffnet - aber sehen kann man nur eins. Im Laufe der Zeit sammeln sich auf diese Weise jede Menge Fenster an. Ich habe schon Projektdateien gesehen, in denen über 25 Fenster geöffnet waren - und zwar mit 25 unterschiedlichen Dateien darin. Das führt natürlich dazu, das das Programm auch immer langsamer startet, und natürlich auch immer mehr Speicher verbraucht.

Aus diesem Grund wird das nächste Update eine Änderung in der Fensterverwaltung mit sich bringen. (Zumindest hoffe ich das - ansonsten wird es eben erst das übernächste Update... -:)). Dabei werden dann geöffnete Fenster in Reitern angezeigt - man kann also sofort sehen, welche Dateien man in welchen Fenstern geöffnet hat, und die nicht benötigten schliessen. Ich könnte mir gut vorstellen, das das bei vielen Kunden zu deutlich schnelleren Programmstarts führen wird.

Wer die Reiter nicht mag, sondern lieber das alte Verhalten möchte, der kann das natürlich in den Programmoptionen einstellen.

Managed Code: 32bit vs. 64 bit

Ich hatte am Freitag ein paar Worte zu unserer Statiksoftware in Bezug auf 32 und 64bit sowie Multicore Systeme gesagt. Das führte zu einer Rückfrage, ob ich darüber nicht einen Artikel für eine Zeitschrift verfassen wollte. Nun schreibe ich ja in der Tat hin- und wieder mal solche Fachbeiträge - in diesem Fall glaube ich aber, das das Thema einfach nicht genug für einen solchen Text hergibt. Für einen kurzen Blogeintrag ist es aber vielleicht ausreichend... Mal sehen.

Zunächst mal ist die erste Frage: Wodurch wird die Anwendung 32- oder 64bittig? Da gibt es ein paar Fälle... Im Visual Studio kann man unter den Projekteigenschaften bei "Build" eine Platform Target einstellen. Dort gibt es 3 Optionen, und zwar x86, x64 und "Any CPU". Stellt man die Option auf x86, wird Code für x86 generiert: Der läuft dann sowohl auf 32bit als auch auf 64bit Maschinen als 32bit Code. Stellt man die Option auf x64, dann läuft das Resultat als 64bitter nur noch auf 64bit Maschinen. Stellt man die Option hingegen auf "Any CPU", dann läuft das Resultat auf 64bit Maschinen als 64bitter und auf 32bit Systemen als 32bitter.

Wenn zum Projekt mehrere Assemblies gehören, dann legt die ladende Assembly (also die mit dem Eintrittspunkt ins Programm) fest, ob die Sache 32bittig oder 64bittig wird. Im Wesentlichen kann man also immer die Default-Option "Any CPU" eingeschaltet lassen, und hat dann nie Ärger, egal wie die Zielplatform aussieht.

Dazu gibt es eine Ausnahme, und die tritt dann in Kraft, wenn man im Projekt 32bit Code verwenden muss. Dabei ist mit "muss" gemeint: Man hat entweder eine 3rd Party Bibliothek die es nur in 32bit Geschmacksrichtung gibt, oder aber man hat eigenen Code den man noch nicht umstellen kann oder will. In diesem Fall bleibt einem nichts anderes übrig, als den Eintrittspunkt als "x86" zu übersetzen, und damit eine komplett 32bittige Anwendung zu erzeugen.

Warum überhaupt x64? Gute Frage - auf die ich aber leider keine einfache Antwort kenne. Der wesentliche Vorteil von x64 ist der, das man einen deutlich größeren Adressraum hat. Und zwar einen, der in der Theorie 16 Exabyte unterstützt (was ziemlich viel ist), in der Praxis bei Win64 aber nur 16 Terabyte umfasst (was im Vergleich zu den 4GB bei Win32 auch ziemlich viel ist.). Davon hat man aber nur was, wenn man a) diese Speichermenge auch braucht und b) über Hardware verfügt wo man auch tatsächlich mehr als 4GB reinstecken kann.

Dabei gibt es durchaus Anwendungen auf die a) zutrifft - nicht zuletzt kümmere ich mich um so Kram, weil einige unserer Programme gerne auch mal sehr viel Speicher verbrauchen (Handregel: Je größer das Gebäude das berechnet wird, um so mehr Speicher wird dafür benötigt :-)).

b) ist hingegen eine Sache, die sich wohl erst in nächster Zeit entwickeln wird: (Desktop) Motherboards in die tatsächlich mehr als 4 GB reingehen sind selten - und wenn, dann gehen auch nur 8 rein. (Zumindest habe ich keine anderen gefunden.). Das wird sich mittelfristig natürlich ändern, ist aber zumindest zur Zeit der Stand der Dinge.

Man kann auch ganz sicher Performance-Betrachtungen anstellen, bei denen rauskommt, das 64bit Programme schneller sind als 32bit Programm - aber das genaue Gegenteil geht mit Sicherheit auch. Ebenso kann man wohl Messungen machen, bei denen rauskommt das 64bit Programme größer sind als 32bit Programm (schließlich brauchen ja alle Pointer doppelt so viel Platz) - aber in Abhängigkeit vom Programm geht auch hier wohl das Gegenteil.

Im Wesentlichen läuft das für mich auf eines hinaus: Wenn man keine sehr speziellen Anforderungen hat (so wie wir mit dem massiven Speicherbedarf) und auch nicht an "altem" 32bit Code hängt - dann verwendet man am besten die Option "Any CPU" - denn die macht am wenigsten Ärger.

Apropos Ärger: Einen kleinen Haken hat die Sache schon. Wenn man Interop (PInvoke) verwendet, dann muss man sicherstellen, das die meist von Hand gebastelten Interfaces auch _wirklich_ stimmen - ansonsten funktionieren die hinterher nämlich nur auf ein 32bit Platform, aber nicht auf einer 64bit Platform. Oder natürlich umgekehrt. Hint: pinvoke.net ist dabei wirklich hilfreich.

Hilfreich zu lesen: Everything you need to know to start programming 64-bit Windows Systems.