Built simulations run interface (threaded)

This commit is contained in:
Jose Luis Cercós pita 2012-07-06 12:42:19 +02:00 committed by Yorik van Havre
parent 70a4cf0e1b
commit a933c93269
16 changed files with 4150 additions and 862 deletions

View File

@ -40,8 +40,9 @@ SET(ShipIcons_SRCS
Icons/SimIco.xcf
Icons/Sim.xpm
Icons/SimCreateIco.png
Icons/SimCreateIco.xcf
Icons/SimCreateIco.xpm
Icons/SimRunIco.png
Icons/SimRunIco.xpm
Icons/Tank.png
Icons/Tank.xcf
Icons/Tank.xpm
@ -136,7 +137,15 @@ SET(SimCreate_SRCS
)
SOURCE_GROUP("simcreate" FILES ${SimCreate_SRCS})
SET(all_files ${ShipMain_SRCS} ${ShipIcons_SRCS} ${ShipExamples_SRCS} ${ShipLoadExample_SRCS} ${ShipCreateShip_SRCS} ${ShipOutlineDraw_SRCS} ${ShipAreasCurve_SRCS} ${ShipHydrostatics_SRCS} ${ShipUtils_SRCS} ${ShipWeights_SRCS} ${ShipCreateTank_SRCS} ${ShipGZ_SRCS} ${SimCreate_SRCS})
SET(SimRun_SRCS
simRun/__init__.py
simRun/Simulation.py
simRun/TaskPanel.py
simRun/TaskPanel.ui
)
SOURCE_GROUP("simrun" FILES ${SimRun_SRCS})
SET(all_files ${ShipMain_SRCS} ${ShipIcons_SRCS} ${ShipExamples_SRCS} ${ShipLoadExample_SRCS} ${ShipCreateShip_SRCS} ${ShipOutlineDraw_SRCS} ${ShipAreasCurve_SRCS} ${ShipHydrostatics_SRCS} ${ShipUtils_SRCS} ${ShipWeights_SRCS} ${ShipCreateTank_SRCS} ${ShipGZ_SRCS} ${SimCreate_SRCS} ${SimRun_SRCS})
ADD_CUSTOM_TARGET(Ship ALL
SOURCES ${all_files}
@ -216,6 +225,12 @@ INSTALL(
DESTINATION
Mod/Ship/simCreate
)
INSTALL(
FILES
${SimRun_SRCS}
DESTINATION
Mod/Ship/simRun
)
INSTALL(
FILES
${ShipMain_SRCS}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,7 @@ class ShipWorkbench ( Workbench ):
self.appendToolbar("Ship design",list)
list = ["Ship_Weights", "Ship_CreateTank", "Ship_GZ"]
self.appendToolbar("Weights",list)
list = ["Ship_CreateSim"]
list = ["Ship_CreateSim", "Ship_RunSim"]
self.appendToolbar("Simulation",list)
# Menu
@ -44,7 +44,7 @@ class ShipWorkbench ( Workbench ):
self.appendMenu("Ship design",list)
list = ["Ship_Weights", "Ship_CreateTank", "Ship_GZ"]
self.appendToolbar("Weights",list)
list = ["Ship_CreateSim"]
list = ["Ship_CreateSim", "Ship_RunSim"]
self.appendToolbar("Simulation",list)
Gui.addWorkbench(ShipWorkbench())

View File

@ -41,8 +41,9 @@ nobase_data_DATA = \
Icons/SimIco.xcf \
Icons/Sim.xpm \
Icons/SimCreateIco.png \
Icons/SimCreateIco.xcf \
Icons/SimCreateIco.xpm \
Icons/SimRunIco.png \
Icons/SimRunIco.xpm \
Icons/Tank.png \
Icons/Tank.xcf \
Icons/Tank.xpm \
@ -86,10 +87,14 @@ nobase_data_DATA = \
tankGZ/__init__.py \
tankGZ/Plot.py \
tankGZ/TaskPanel.py \
tankGZ/TaskPanel.ui
tankGZ/TaskPanel.ui \
simCreate/__init__.py \
simCreate/TaskPanel.py \
simCreate/TaskPanel.ui
simCreate/TaskPanel.ui \
simRun/__init__.py \
simRun/Simulation.py \
simRun/TaskPanel.py \
simRun/TaskPanel.ui
CLEANFILES = $(BUILT_SOURCES)

View File

@ -132,6 +132,18 @@ class CreateSim:
ToolTip = str(Translator.translate('Create a new simulation in order to process later'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
class RunSim:
def Activated(self):
import simRun
simRun.load()
def GetResources(self):
from shipUtils import Paths, Translator
IconPath = Paths.iconsPath() + "/SimRunIco.png"
MenuText = str(Translator.translate('Run a simulation'))
ToolTip = str(Translator.translate('Run a simulation'))
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
FreeCADGui.addCommand('Ship_LoadExample', LoadExample())
FreeCADGui.addCommand('Ship_CreateShip', CreateShip())
FreeCADGui.addCommand('Ship_OutlineDraw', OutlineDraw())
@ -141,3 +153,4 @@ FreeCADGui.addCommand('Ship_Weights', SetWeights())
FreeCADGui.addCommand('Ship_CreateTank', CreateTank())
FreeCADGui.addCommand('Ship_GZ', GZ())
FreeCADGui.addCommand('Ship_CreateSim', CreateSim())
FreeCADGui.addCommand('Ship_RunSim', RunSim())

View File

@ -23,6 +23,7 @@
import time
from math import *
import threading
# COIN
from pivy.coin import *
@ -40,24 +41,45 @@ class FreeSurfaceFace:
""" Face storage.
@param pos Face position.
@param normal Face normal.
@param Element length (distance between elements at x direction)
@param Element beam (distance between elements at y direction)
@param l Element length (distance between elements at x direction)
@param b Element beam (distance between elements at y direction)
"""
self.pos = pos
self.normal = normal
self.area = l*b
def __init__(self, pos, normal, area):
""" Face storage.
@param pos Face position.
@param normal Face normal.
@param area Element area
"""
self.pos = pos
self.normal = normal
self.area = area
class ShipSimulation:
def __init__(self, obj, fsMeshData):
def __init__(self, obj, fsMeshData, waves):
""" Creates a new simulation instance on active document.
@param obj Created Part::FeaturePython object.
@param fsMeshData [L,B,N] Free surface mesh data, with lenght
(x), Beam (y) and desired number of points.
@param waves [[A,T,phi,heading],] Waves involved
"""
# Add uniqueness property to identify Tank instances
obj.addProperty("App::PropertyBool","IsShipSimulation","ShipSimulation", str(Translator.translate("True if is a valid ship simulation instance"))).IsShipSimulation=True
# Compute free surface mesh
self.createFSMesh(obj,fsMeshData)
# Store waves
obj.addProperty("App::PropertyVectorList","Waves","ShipSimulation", str(Translator.translate("Waves (Amplitude,period,phase)"))).Waves=[]
obj.addProperty("App::PropertyFloatList","Waves_Dir","ShipSimulation", str(Translator.translate("Waves direction (0 deg to stern waves)"))).Waves_Dir=[]
w = []
d = []
for i in range(0,len(waves)):
w.append(Vector(waves[i][0], waves[i][1], waves[i][2]))
d.append(waves[i][3])
obj.Waves = w
obj.Waves_Dir = d
# Add shapes
shape = self.computeShape(obj)
if not shape:
@ -103,7 +125,6 @@ class ShipSimulation:
b = sqrt(area)
nx = int(round(L / l))
ny = int(round(B / b))
print(l,b,nx,ny)
# Start data fields if not already exist
props = obj.PropertiesList
try:
@ -141,87 +162,27 @@ class ShipSimulation:
obj.FS_Area = areas[:]
obj.FS_Normal = normal[:]
def FSMesh(self, obj):
""" Get free surface mesh in matrix mode.
@param obj Created Part::FeaturePython object.
@return Faces matrix
@note areas and normals will recomputed.
"""
nx = obj.FS_Nx
ny = obj.FS_Ny
# Transform positions into a mesh
pos = []
for i in range(0,nx):
pos.append([])
for j in range(0,ny):
pos[i].append(obj.FS_Position[j + i*ny])
# Recompute normals and dimensions
normal = []
l = []
b = []
for i in range(0,nx):
normal.append([])
l.append([])
b.append([])
for j in range(0,ny):
i0 = i-1
i1 = i+1
fi = 1.0
j0 = j-1
j1 = j+1
fj = 1.0
if i == 0:
i0 = i
i1 = i+1
fi = 2.0
if i == nx-1:
i0 = i-1
i1 = i
fi = 2.0
if j == 0:
j0 = j
j1 = j+1
fj = 2.0
if j == ny-1:
j0 = j-1
j1 = j
fj = 2.0
l[i].append(fi*(obj.FS_Position[j + i1*ny].x - obj.FS_Position[j + i0*ny].x))
b[i].append(fj*(obj.FS_Position[j1 + i*ny].y - obj.FS_Position[j0 + i*ny].y))
xvec = Vector(obj.FS_Position[j + i1*ny].x - obj.FS_Position[j + i0*ny].x,
obj.FS_Position[j + i1*ny].y - obj.FS_Position[j + i0*ny].y,
obj.FS_Position[j + i1*ny].z - obj.FS_Position[j + i0*ny].z)
yvec = Vector(obj.FS_Position[j1 + i*ny].x - obj.FS_Position[j0 + i*ny].x,
obj.FS_Position[j1 + i*ny].y - obj.FS_Position[j0 + i*ny].y,
obj.FS_Position[j1 + i*ny].z - obj.FS_Position[j0 + i*ny].z)
n = Vector(xvec.cross(yvec)) # Z positive
normal[i].append(n.normalize())
# Create faces
faces = []
for i in range(0,nx):
faces.append([])
for j in range(0,ny):
faces[i].append(FreeSurfaceFace(pos[i][j], normal[i][j], l[i][j], b[i][j]))
# Reconstruct mesh data
for i in range(0,nx):
for j in range(0,ny):
obj.FS_Position[j + i*ny] = faces[i][j].pos
obj.FS_Normal[j + i*ny] = faces[i][j].normal
obj.FS_Area[j + i*ny] = faces[i][j].area
return faces
def computeShape(self, obj):
""" Computes simulation involved shapes.
@param obj Created Part::FeaturePython object.
@return Shape
"""
print("[ShipSimulation] Computing mesh shape...")
nx = obj.FS_Nx
ny = obj.FS_Ny
mesh = self.FSMesh(obj)
mesh = FSMesh(obj)
planes = []
# Create planes
Percentage = 0
Count = 0
print("0%")
for i in range(1,nx-1):
for j in range(1,ny-1):
Count = Count+1
done = int(round(100 * Count / ((nx-2)*(ny-2))))
if done != Percentage:
Percentage = done
print("%i%%" % (done))
v0 = (mesh[i][j].pos + mesh[i-1][j].pos + mesh[i][j-1].pos + mesh[i-1][j-1].pos).multiply(0.25)
v1 = (mesh[i][j].pos + mesh[i+1][j].pos + mesh[i][j-1].pos + mesh[i+1][j-1].pos).multiply(0.25)
v2 = (mesh[i][j].pos + mesh[i+1][j].pos + mesh[i][j+1].pos + mesh[i+1][j+1].pos).multiply(0.25)
@ -615,3 +576,81 @@ class ViewProviderShipSimulation:
" ",
" "};
"""
def FSMesh(obj, recompute=False):
""" Get free surface mesh in matrix mode.
@param obj Created Part::FeaturePython object.
@param recompute True if mesh must be recomputed, False otherwise.
@return Faces matrix
"""
nx = obj.FS_Nx
ny = obj.FS_Ny
if not recompute:
faces = []
for i in range(0,nx):
faces.append([])
for j in range(0,ny):
faces[i].append(FreeSurfaceFace(obj.FS_Position[j + i*ny],
obj.FS_Normal[j + i*ny],
obj.FS_Area[j + i*ny]))
return faces
# Transform positions into a mesh
pos = []
for i in range(0,nx):
pos.append([])
for j in range(0,ny):
pos[i].append(obj.FS_Position[j + i*ny])
# Recompute normals and dimensions
normal = []
l = []
b = []
for i in range(0,nx):
normal.append([])
l.append([])
b.append([])
for j in range(0,ny):
i0 = i-1
i1 = i+1
fi = 1.0
j0 = j-1
j1 = j+1
fj = 1.0
if i == 0:
i0 = i
i1 = i+1
fi = 2.0
if i == nx-1:
i0 = i-1
i1 = i
fi = 2.0
if j == 0:
j0 = j
j1 = j+1
fj = 2.0
if j == ny-1:
j0 = j-1
j1 = j
fj = 2.0
l[i].append(fi*(obj.FS_Position[j + i1*ny].x - obj.FS_Position[j + i0*ny].x))
b[i].append(fj*(obj.FS_Position[j1 + i*ny].y - obj.FS_Position[j0 + i*ny].y))
xvec = Vector(obj.FS_Position[j + i1*ny].x - obj.FS_Position[j + i0*ny].x,
obj.FS_Position[j + i1*ny].y - obj.FS_Position[j + i0*ny].y,
obj.FS_Position[j + i1*ny].z - obj.FS_Position[j + i0*ny].z)
yvec = Vector(obj.FS_Position[j1 + i*ny].x - obj.FS_Position[j0 + i*ny].x,
obj.FS_Position[j1 + i*ny].y - obj.FS_Position[j0 + i*ny].y,
obj.FS_Position[j1 + i*ny].z - obj.FS_Position[j0 + i*ny].z)
n = Vector(xvec.cross(yvec)) # Z positive
normal[i].append(n.normalize())
# Create faces
faces = []
for i in range(0,nx):
faces.append([])
for j in range(0,ny):
faces[i].append(FreeSurfaceFace(pos[i][j], normal[i][j], l[i][j], b[i][j]))
# Reconstruct mesh data
for i in range(0,nx):
for j in range(0,ny):
obj.FS_Position[j + i*ny] = faces[i][j].pos
obj.FS_Normal[j + i*ny] = faces[i][j].normal
obj.FS_Area[j + i*ny] = faces[i][j].area
return faces

View File

@ -36,9 +36,22 @@ class TaskPanel:
def accept(self):
form = self.form
# Read waves data
w = []
for i in range(0,form.waves.rowCount() - 1):
item = form.waves.item(i,0)
A = item.text().toFloat()[0]
item = form.waves.item(i,1)
T = item.text().toFloat()[0]
item = form.waves.item(i,2)
phi = item.text().toFloat()[0]
item = form.waves.item(i,3)
head = item.text().toFloat()[0]
w.append([A,T,phi,head])
obj = App.ActiveDocument.addObject("Part::FeaturePython","ShipSimulation")
sim = SimInstance.ShipSimulation(obj,
[form.length.value(), form.beam.value(), form.n.value()])
[form.length.value(), form.beam.value(), form.n.value()],
w)
SimInstance.ViewProviderShipSimulation(obj.ViewObject)
return True
@ -72,6 +85,7 @@ class TaskPanel:
form.length = form.findChild(QtGui.QDoubleSpinBox, "Length")
form.beam = form.findChild(QtGui.QDoubleSpinBox, "Beam")
form.n = form.findChild(QtGui.QSpinBox, "N")
form.waves = form.findChild(QtGui.QTableWidget, "Waves")
self.form = form
# Initial values
if self.initValues():
@ -81,6 +95,7 @@ class TaskPanel:
QtCore.QObject.connect(form.length, QtCore.SIGNAL("valueChanged(double)"), self.onFS)
QtCore.QObject.connect(form.beam, QtCore.SIGNAL("valueChanged(double)"), self.onFS)
QtCore.QObject.connect(form.n, QtCore.SIGNAL("valueChanged(int)"), self.onFS)
QtCore.QObject.connect(form.waves,QtCore.SIGNAL("cellChanged(int,int)"),self.onWaves);
def getMainWindow(self):
"returns the main window"
@ -108,14 +123,48 @@ class TaskPanel:
self.form.findChild(QtGui.QLabel, "LengthLabel").setText(Translator.translate("Length"))
self.form.findChild(QtGui.QLabel, "BeamLabel").setText(Translator.translate("Beam"))
self.form.findChild(QtGui.QLabel, "NLabel").setText(Translator.translate("Number of points"))
self.form.findChild(QtGui.QGroupBox, "WavesDataBox").setTitle(Translator.translate("Waves"))
labels = []
labels.append(Translator.translate("Amplitude") + " [m]")
labels.append(Translator.translate("Period") + " [s]")
labels.append(Translator.translate("Phase") + " [rad]")
labels.append(Translator.translate("Heading") + " [deg]")
self.form.waves.setHorizontalHeaderLabels(labels)
def onFS(self, value):
""" Method called when ship data is changed.
Annotations must be showed.
""" Method called when free surface data is changed.
@param value Changed value.
"""
pass
def onWaves(self, row, column):
""" Method called when waves data is changed.
@param row Affected row.
@param col Affected column.
"""
item = self.form.waves.item(row,column)
# Row deletion
if column == 0:
if not item.text():
self.form.waves.removeRow(row)
# Ensure that exist one empty item at the end
nRow = self.form.waves.rowCount()
last = self.form.waves.item(nRow-1,0)
if last:
if(last.text() != ''):
self.form.waves.setRowCount(nRow+1)
# Fields must be numbers
for i in range(0,self.form.waves.rowCount()-1): # Avoid last row
for j in range(0,self.form.waves.columnCount()): # Avoid name column
item = self.form.waves.item(i,j)
if not item:
item = QtGui.QTableWidgetItem('0.0')
self.form.waves.setItem(i,j,item)
continue
(number,flag) = item.text().toFloat()
if not flag:
item.setText('0.0')
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)

View File

@ -6,14 +6,20 @@
<rect>
<x>0</x>
<y>0</y>
<width>260</width>
<height>180</height>
<width>269</width>
<height>384</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>180</height>
<height>384</height>
</size>
</property>
<property name="windowTitle">
@ -22,155 +28,236 @@
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item>
<widget class="QGroupBox" name="FSDataBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>240</width>
<height>160</height>
<width>0</width>
<height>128</height>
</size>
</property>
<property name="title">
<string>Free surface</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="flat">
<bool>false</bool>
</property>
<widget class="QWidget" name="verticalLayoutWidget_2">
<property name="geometry">
<rect>
<x>0</x>
<y>20</y>
<width>241</width>
<height>141</height>
</rect>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0,0">
<property name="spacing">
<number>6</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="LengthLabel">
<property name="text">
<string>Length</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="Length">
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
<property name="singleStep">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="BeamLabel">
<property name="text">
<string>Beam</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="Beam">
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
<property name="singleStep">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="NLabel">
<property name="text">
<string>Number of points</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="N">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000000000</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="WavesDataBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>2</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Waves</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="0">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QTableWidget" name="Waves">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="rowCount">
<number>1</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
<row/>
<column>
<property name="text">
<string>Amplitude [m]</string>
</property>
<property name="leftMargin">
<number>10</number>
</column>
<column>
<property name="text">
<string>Period [s]</string>
</property>
<property name="topMargin">
<number>0</number>
</column>
<column>
<property name="text">
<string>Phase [rad]</string>
</property>
<property name="rightMargin">
<number>10</number>
</column>
<column>
<property name="text">
<string>Heading [deg]</string>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="LengthLabel">
<property name="text">
<string>Length</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="Length">
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
<property name="singleStep">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="BeamLabel">
<property name="text">
<string>Beam</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="Beam">
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
<property name="singleStep">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="NLabel">
<property name="text">
<string>Number of points</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="N">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000000000</number>
</property>
<property name="value">
<number>10000</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</column>
</widget>
</item>
</layout>
</widget>
</item>
</layout>

View File

@ -0,0 +1,56 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import time
from math import *
import threading
# FreeCAD
import FreeCAD,FreeCADGui
from FreeCAD import Part, Base, Vector
# Ship design module
from shipUtils import Paths, Translator, Math
class FreeCADShipSimulation(threading.Thread):
def __init__ (self, endTime, output, FSmesh, waves):
""" Thread constructor.
@param endTime Maximum simulation time.
@param output [Rate,Type] Output rate, Type=0 if FPS, 1 if IPF.
@param FSmesh Free surface mesh faces.
@param waves Waves parameters (A,T,phi,heading)
"""
threading.Thread.__init__(self)
self.endTime = endTime
self.output = output
self.FSmesh = FSmesh
self.waves = waves
def run(self):
""" Runs the simulation.
"""
# Perform work here
print("Im thread, Im running...")
time.sleep(2)
# ...
print("Im thread, I end!")

View File

@ -0,0 +1,160 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Qt library
from PyQt4 import QtGui,QtCore
# Module
import SimInstance
from shipUtils import Paths, Translator
from Simulation import FreeCADShipSimulation as Sim
class TaskPanel:
def __init__(self):
self.ui = Paths.modulePath() + "/simRun/TaskPanel.ui"
self.sim = False
def accept(self):
if not self.sim:
return False
msg = Translator.translate("Building data...\n")
App.Console.PrintMessage(msg)
# Get GUI data
endTime = self.form.time.value()
output = []
output.append(self.form.output.value())
output.append(self.form.outputType.currentIndex())
# Get free surfaces data
FSMesh = SimInstance.FSMesh(self.sim)
wData = self.sim.Waves
wDir = self.sim.Waves_Dir
waves = []
for i in range(0,len(wData)):
waves.append([wData[i].x, wData[i].y, wData[i].z, wDir[i]])
msg = Translator.translate("Launching simulation...\n")
App.Console.PrintMessage(msg)
# Build simulation thread
t = Sim(endTime, output, FSMesh, waves)
t.start()
msg = Translator.translate("Done!\n")
App.Console.PrintMessage(msg)
return True
def reject(self):
return True
def clicked(self, index):
pass
def open(self):
pass
def needsFullSpace(self):
return True
def isAllowedAlterSelection(self):
return False
def isAllowedAlterView(self):
return True
def isAllowedAlterDocument(self):
return False
def helpRequested(self):
pass
def setupUi(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.time = form.findChild(QtGui.QDoubleSpinBox, "SimTime")
form.output = form.findChild(QtGui.QDoubleSpinBox, "Output")
form.outputType = form.findChild(QtGui.QComboBox, "OutputType")
self.form = form
# Initial values
if self.initValues():
return True
self.retranslateUi()
# Connect Signals and Slots
# QtCore.QObject.connect(form.time, QtCore.SIGNAL("valueChanged(double)"), self.onData)
def getMainWindow(self):
"returns the main window"
# using QtGui.qApp.activeWindow() isn't very reliable because if another
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
# returned
toplevel = QtGui.qApp.topLevelWidgets()
for i in toplevel:
if i.metaObject().className() == "Gui::MainWindow":
return i
raise Exception("No main window found")
def initValues(self):
""" Set initial values for fields
"""
# Get objects
selObjs = Gui.Selection.getSelection()
if not selObjs:
msg = Translator.translate("Ship simulation instance must be selected (no object selected)\n")
App.Console.PrintError(msg)
return True
for i in range(0,len(selObjs)):
obj = selObjs[i]
# Test if is a ship instance
props = obj.PropertiesList
try:
props.index("IsShipSimulation")
except ValueError:
continue
if obj.IsShipSimulation:
# Test if another ship already selected
if self.sim:
msg = Translator.translate("More than one ship simulation selected (extra simulations will be neglected)\n")
App.Console.PrintWarning(msg)
break
self.sim = obj
# Test if any valid ship was selected
if not self.sim:
msg = Translator.translate("Ship simulation instance must be selected (no valid simulation found at selected objects)\n")
App.Console.PrintError(msg)
return True
msg = Translator.translate("Ready to work\n")
App.Console.PrintMessage(msg)
return False
def retranslateUi(self):
""" Set user interface locale strings.
"""
self.form.setWindowTitle(Translator.translate("Run the simulation"))
self.form.findChild(QtGui.QLabel, "SimTimeLabel").setText(Translator.translate("Simulation time"))
self.form.findChild(QtGui.QLabel, "OutputLabel").setText(Translator.translate("Output"))
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel

View File

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskPanel</class>
<widget class="QWidget" name="TaskPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>292</width>
<height>72</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>72</height>
</size>
</property>
<property name="windowTitle">
<string>Create new simulation</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="SimTimeLabel">
<property name="text">
<string>Simulation time</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="SimTime">
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>10000000.000000000000000</double>
</property>
<property name="singleStep">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>3600.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="SimTimeUnitsLabel">
<property name="maximumSize">
<size>
<width>16</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>s</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="OutputLabel">
<property name="text">
<string>Output</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="Output">
<property name="maximum">
<double>10000.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="OutputType">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>56</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string comment="FPS = Frames per second, IPF = Iterations per frame"/>
</property>
<item>
<property name="text">
<string>FPS</string>
</property>
</item>
<item>
<property name="text">
<string>IPF</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,36 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD
import FreeCADGui
# Qt libraries
from PyQt4 import QtGui,QtCore
# Main object
import TaskPanel
def load():
""" Loads the tool """
TaskPanel.createTask()