Programutveckling för Tekniska Tillämpningar Arbetsblad 5 I detta arbetsblad innehåller följande moment: 1. Skapa metod för att spara indata till fil. 2. Skapa användargränssnitt för noder, linjer, föreskrivna variabler och laster. 3. Lägg till komponent för visualisering av nodvärden. Skapa en metod för att spara indata till fil Vi har sedan tidigare en metod för inläsning av indata från en fil. En användare måste också kunna ändra och sedan spara indata till en fil igen. Skriv en metod, writetofile(), i modellklassen som skriver geometridefinitionen, laster och föreskrivna värden till en fil. Formatet skall vara samma som definierats för metoden, readfromfile(). I pycalfem_utils finns 4 metoder, writesinglefloat(), writesingleint(), writefloatlist() och writeint List() för att skriva värden och listor till fil. Nedan visas ett kort exempel på hur dessa används: outputfile = open(self.filename, 'w') # Skriv koordinater writesingleint(outputfile, self.vertices.shape[0]) for row in self.vertices: writefloatlist(outputfile, row) Meny för indata För att kunna hantera indata i programmet skapas en meny, Indata, med följande innehåll: Menynamn Beskrivning Metod Konstanter Visar fönster med generella parametrar onshowkonstants() för problemet. Noder Visar fönster för redigering av noder. onshownodewindow() Linjer Visar fönster för redigering av linjer. onshowlinewindow() Laster Visar fönster för redigering av laster. onshowloadwindow() Föreskrivna variabler Visar fönster för redigering av föreskrivna variabler. onshowbcwindow()
Fönster för inmatning av koordinater Koordinaterna för geometrin skall hanteras av ett speciellt fönster. Fönstret kan se ut som i följande bild: Hierarkin i wxglade visas i följande figur: Figur 1 Koordinatredigeringsfönster Figur 2 Objekthierarki för koordinatredigeringsfönstret Tabellen nedan visar viktiga egenskaper för olika objekt i fönsterklassen, NodeWindow. Objekt Egenskap Värde nodewindow Class NodeWindow mainpanel Proportion 1 Border 0 wxall Alignment wxexpand verticeslistbox Size 371, 201 Border 5 wxall Alignment wxexpand Style wxlb_single
EVT_LISTBOX onselect hsizevertices Proportion Alignment wxexpand xlabel Border 5 wxleft, wxright, wxbottom Label x (m) ylabel Border 5 wxleft, wxright, wxbottom Label y (m) xvalue Border 5 wxbottom yvalue Border 5 wxbottom hsizerbuttons Proportion 0 Alignment wxalign_center_horizontal addbutton Border 5 wxall EVT_BUTTON onadd removebutton Border 5 wxall EVT_BUTTON onremove changebutton Border 5 wxall EVT_BUTTON onchange closebutton Border 5 wxall EVT_BUTTON onclose För att hantera initieringen av fönstret skapas en metod, _initwindow(), som anropas från klassens initieringsmetod. I metoden definierar vi variabeln, self.vertices, som tilldelas motsvarande variabel i modell klassen. class NodeWindow(wx.Frame): def init (self, *args, **kwds): # begin wxglade: NodeWindow. init # < Bortklippt kod > self.bind(wx.evt_button, self.on, self.changebutton) self.bind(wx.evt_button, self.onclose, self.closebutton) # end wxglade self._initwindow() def _initwindow(self): self.model = None Innan fönstret visas måste listboxen uppdateras med verkliga värden. Skapa en metod, filllistbox(), som fyller listboxen med värden ur self.model. Använda metoden Append() för listbox instansen för att lägga till strängar till listboxen. För att skapa NodeWindow från huvudfönstret läggs följande import direktiv till i MainWindow klassen: from model import * from ReportWindow import * from NodeWindow import *
Fönstret visas sedan från händelsemetoden onshownodewindow(). def onshownodewindow(self, event): # wxglade: MainWindow.<event_handler> self._nodewindow = NodeWindow(self, 1) self._nodewindow.model = self._model self._nodewindow.filllistbox() self._nodewindow.show() Implementera sedan händelsemetoderna, onadd, onremove, onchange och onclose, för knapparna i fönstret. Nyttiga metoder: {listbox}.getselection() {listbox}.clear() {listbox}.append({sträng}) {textkontroll}.getvalue() {textkontroll}.setvalue() append(arr, values, axis) Returnerar index för markerat alternativ i listbox. Rensar allt i listboxen. Lägger till en sträng till listboxen. Returnerar aktuell textsträng i textkontrollen. Tilldelar textkontrollen en sträng. Returnerar en ny matris utökad med values. Axis=0 lägger till rad på slutet, axis=1 lägger till kolumn. a = zeros([20,2], float) newrow = array([1,2],float).reshape(1,2) a = append(a, newrow, 0) delete(arr, index, axis) Lägger till en rad med värdena [1,2] på slutet av a. Returnerar ny matris när raden/kolumnen index har tagits bort Metoderna append och delete är numpy metoder och kräver att man lägger till from numpy import * i början av modulen. Fönster för inmatning av linjetopologi Fönstret för inmatning av linjetopologi implementeras på samma sätt koordinatfönstret med skillnaden att istället för textrutor för x och y anges nu topologin för varje element i 2 textutor och randmarkören i en textruta. Fönster för inmatning av laster Lastinmatningsfönstret skall visa en listbox med alla laster definierade på strukturen. Textrutorna skall innehålla: randmarkör, lastvärde. För plan spänning anges lastvärdet som två komponenter i x och y riktning.
Fönster för inmatning av föreskrivna värden Fönstret för föreskrivna variabler skall innehålla en listbox med alla föreskrivna variabler. Fönstret skall också ha textrutor för definition av randmarkör, föreskrivet värde. Fönstret måste också innehålla kryssrutekontroller för att kunna ange vilka riktningar som skall föreskrivas. Uppritning av nodvariabler och förskjutningar med ElementView Pycalfem_classes innehåller en speciell uppritningsklass, ElementView, som skall användas för att visa förskjutningar och nodvariabler. För att använda klassen importeras den i MainWindow modulen: from model import * from ReportWindow import * from NodeWindow import * from pycalfem_classes import ElementView Visning av fönstret görs sedan i händelsemetoden, onshownodalvalues. def onviewnodalvalues(self, event): # wxglade: MainWindow.<event_handler> self._elementview = ElementView(self, 1) self._elementview.ex = self._model.ex self._elementview.ey = self._model.ey self._elementview.ed = self._model.ed self._elementview.show() Vad som skall visas styrs med ett antal egenskaper: ex ey ed dofspernode magnfac showmesh shownodalvalues showdisplacements x koordinater för element. y koordinater för element. Elementförskjutningar. Antal frihetsgrader per nod. Förstoringsfaktor. True = visar elementnät True = visar nodvariabler True = visar förskjutningar Det går också att komplettera diagrammen med textannoteringar och extra uppritning genom att tilldela ElementView en metod för detta: def onviewnodalvalues(self, event): # wxglade: MainWindow.<event_handler> self._elementview = ElementView(self, 1) self._elementview.ex = self._model.ex self._elementview.ey = self._model.ey self._elementview.ed = self._model.ed self._elementview.drawannotations = self.drawannotations self._elementview.show() self.drawannotation är en metod som kan definieras i MainWindow klassen på följande sätt: def drawannotations(self, view, width, height): view.drawstroketext("hello", 50, 50, 50)
view är den aktuella ElementView instansen. Width och height är bredden och höjden på fönstret. För uppritning av text finns metoden view.drawstroketext som kan användas för att rita vektorbaserad text i fönstret. Syntax för metoden är: def drawstroketext(self, text, x=0.0, y=0.0, fontsize=1.0, color=[0.0, 0.0, 0.0], font=glut_stroke_roman) All uppritning måste ske med hjälp av OpenGL uppritningskommando. Tidigare wxpython baserade ritkommandon fungerar inte i ElementView. Konvertering till skärmkoordinater kan göras med metoden view.worldtoscreen(x, y) vilken returnerar x, y i skärmkoordinater (för ElementView fönstret.) För temperatur och grundvattenströmning implementeras en färgskala för nodvariabelplotten. För plan spänning implemteras en skalpil för förskjutningarna. Redovisning Redovisningen av uppgiften skall innehålla: Programlista Skärmdumpar (Alt+Print Screen)