Regenerated the branch

This commit is contained in:
Cercos-Pita J.L
2014-02-18 10:08:12 +01:00
parent a6b734c8ce
commit 1b2d6e53ec
40 changed files with 18514 additions and 5499 deletions

View File

@@ -8,11 +8,6 @@ SET(ShipMain_SRCS
)
SOURCE_GROUP("" FILES ${ShipMain_SRCS})
SET(ShipIcons_SRCS
resources/icons/Ico.xpm
)
SOURCE_GROUP("shipicons" FILES ${ShipIcons_SRCS})
SET(ShipExamples_SRCS
resources/examples/s60.fcstd
resources/examples/s60_katamaran.fcstd
@@ -137,7 +132,7 @@ SET(SimPost_SRCS
)
SOURCE_GROUP("simpost" FILES ${SimPost_SRCS})
SET(all_files ${ShipMain_SRCS} ${ShipIcons_SRCS} ${ShipExamples_SRCS} ${ShipOpenCL_SRCS} ${ShipLoadExample_SRCS} ${ShipCreateShip_SRCS} ${ShipOutlineDraw_SRCS} ${ShipAreasCurve_SRCS} ${ShipHydrostatics_SRCS} ${ShipUtils_SRCS} ${ShipWeights_SRCS} ${ShipCreateTank_SRCS} ${ShipGZ_SRCS} ${SimCreate_SRCS} ${SimRun_SRCS} ${SimPost_SRCS})
SET(all_files ${ShipMain_SRCS} ${ShipExamples_SRCS} ${ShipOpenCL_SRCS} ${ShipLoadExample_SRCS} ${ShipCreateShip_SRCS} ${ShipOutlineDraw_SRCS} ${ShipAreasCurve_SRCS} ${ShipHydrostatics_SRCS} ${ShipUtils_SRCS} ${ShipWeights_SRCS} ${ShipCreateTank_SRCS} ${ShipGZ_SRCS} ${SimCreate_SRCS} ${SimRun_SRCS} ${SimPost_SRCS})
ADD_CUSTOM_TARGET(Ship ALL
SOURCES ${all_files}
@@ -145,12 +140,6 @@ ADD_CUSTOM_TARGET(Ship ALL
fc_copy_sources(Mod/Ship "${CMAKE_BINARY_DIR}/Mod/Ship" ${all_files})
INSTALL(
FILES
${ShipIcons_SRCS}
DESTINATION
Mod/Ship/resources/icons
)
INSTALL(
FILES
${ShipExamples_SRCS}

View File

@@ -1,74 +1,111 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
class ShipWorkbench ( Workbench ):
""" @brief Workbench of Ship design module. Here toolbars & icons are append. """
from PyQt4 import QtCore, QtGui
from shipUtils import Paths
import ShipGui
Icon = "Ico"
MenuText = str(QtCore.QT_TRANSLATE_NOOP("Ship", "Ship"))
ToolTip = str(QtCore.QT_TRANSLATE_NOOP("Ship", "Ship module provides some of the commonly used tool to design ship forms"))
class ShipWorkbench(Workbench):
"""Ships design workbench."""
from shipUtils import Paths
import ShipGui
def Initialize(self):
from PyQt4 import QtCore, QtGui
Icon = "Ship_Module.svg"
MenuText = "Ship"
ToolTip = ("Ship module provides some of the commonly used tool to design"
" ship forms")
def Initialize(self):
from PySide import QtCore, QtGui
try:
import Plot
except ImportError:
msg = QtGui.QApplication.translate(
"ship_console",
"Plot module is disabled, tools cannot graph output curves",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg + '\n')
# ToolBar
shiplist = ["Ship_LoadExample",
"Ship_CreateShip",
"Ship_OutlineDraw",
"Ship_AreasCurve",
"Ship_Hydrostatics"]
weightslist = ["Ship_Weights",
"Ship_CreateTank",
"Ship_GZ"]
self.appendToolbar(
str(QtCore.QT_TRANSLATE_NOOP("Ship", "Ship design")),
shiplist)
self.appendToolbar(
str(QtCore.QT_TRANSLATE_NOOP("Ship", "Weights")),
weightslist)
self.appendMenu(
str(QtCore.QT_TRANSLATE_NOOP("Ship", "Ship design")),
shiplist)
self.appendMenu(
str(QtCore.QT_TRANSLATE_NOOP("Ship", "Weights")),
weightslist)
# Simulation tools will be added only if pyOpenCL & numpy are present
# Simulations are in development, so keep it disabled except for
# development purposes
hasSim = False
if hasSim:
hasOpenCL = True
hasNumpy = True
try:
import pyopencl
except ImportError:
hasOpenCL = False
msg = QtGui.QApplication.translate(
"ship_console",
"pyOpenCL not installed, simulation tools will disabled"
" therefore",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg + '\n')
try:
import numpy
except ImportError:
hasNumpy = False
msg = QtGui.QApplication.translate(
"ship_console",
"numpy not installed, simulation tools will disabled"
" therefore",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg + '\n')
if hasOpenCL and hasNumpy:
simlist = ["Ship_CreateSim",
"Ship_RunSim",
"Ship_StopSim",
"Ship_TrackSim"]
self.appendToolbar(
str(QtCore.QT_TRANSLATE_NOOP("Ship", "Simulation")),
simlist)
self.appendMenu(
str(QtCore.QT_TRANSLATE_NOOP("Ship", "Simulation")),
simlist)
# Print a warning if Plot module can't be used
try:
import Plot
except ImportError:
msg = QtGui.QApplication.translate("ship_console", "Plot module is disabled, tools can't graph output curves",
None,QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg + '\n')
# ToolBar
shiplist = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"]
weightslist = ["Ship_Weights", "Ship_CreateTank", "Ship_GZ"]
self.appendToolbar(str(QtCore.QT_TRANSLATE_NOOP("Ship", "Ship design")),shiplist)
self.appendToolbar(str(QtCore.QT_TRANSLATE_NOOP("Ship", "Weights")),weightslist)
self.appendMenu(str(QtCore.QT_TRANSLATE_NOOP("Ship", "Ship design")),shiplist)
self.appendMenu(str(QtCore.QT_TRANSLATE_NOOP("Ship", "Weights")),weightslist)
# Simulation stuff only if pyOpenCL & numpy are present
hasOpenCL = True
hasNumpy = True
hasSim = False # In development, activate it only for development purposes
try:
import pyopencl
except ImportError:
hasOpenCL = False
msg = QtGui.QApplication.translate("ship_console", "pyOpenCL not installed, simulations stuff will disabled therefore",
None,QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg + '\n')
try:
import numpy
except ImportError:
hasNumpy = False
msg = QtGui.QApplication.translate("ship_console", "numpy not installed, simulations stuff will disabled therefore",
None,QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg + '\n')
if hasOpenCL and hasNumpy and hasSim:
simlist = ["Ship_CreateSim", "Ship_RunSim", "Ship_StopSim", "Ship_TrackSim"]
self.appendToolbar(str(QtCore.QT_TRANSLATE_NOOP("Ship", "Simulation")),simlist)
self.appendMenu(str(QtCore.QT_TRANSLATE_NOOP("Ship", "Simulation")),simlist)
Gui.addWorkbench(ShipWorkbench())

View File

@@ -1,599 +1,264 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
import time
from math import *
# Qt library
from PyQt4 import QtGui,QtCore
# COIN
from PySide import QtGui, QtCore
from pivy.coin import *
from pivy import coin
# FreeCAD
import FreeCAD,FreeCADGui
import FreeCAD
import FreeCADGui
from FreeCAD import Base, Vector
import Part
# Ship design module
from shipUtils import Paths, Math
class Ship:
def __init__(self, obj, solids):
""" Creates a new ship on active document.
@param obj Part::FeaturePython created object.
@param faces Ship solids components.
"""
# Add uniqueness property to identify Ship instances
tooltip = str(QtGui.QApplication.translate("Ship","True if is a valid ship instance",None,QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyBool","IsShip","Ship", tooltip).IsShip=True
# Add main dimensions
tooltip = str(QtGui.QApplication.translate("Ship","True if is a valid ship instance",None,QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyLength","Length","Ship", tooltip).Length=0.0
tooltip = str(QtGui.QApplication.translate("Ship","True if is a valid ship instance",None,QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyLength","Beam","Ship", tooltip).Beam=0.0
tooltip = str(QtGui.QApplication.translate("Ship","True if is a valid ship instance",None,QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyLength","Draft","Ship", tooltip).Draft=0.0
# Add shapes
obj.Shape = Part.makeCompound(solids)
tooltip = str(QtGui.QApplication.translate("Ship","True if is a valid ship instance",None,QtGui.QApplication.UnicodeUTF8))
obj.addProperty("Part::PropertyPartShape","ExternalFaces","Ship", tooltip)
obj.Proxy = self
def __init__(self, obj, solids):
""" Transform a generic object to a ship instance.
def onChanged(self, fp, prop):
""" Called when a ship property is modified
@param fp Part::FeaturePython object.
@param prop Property changed.
"""
if prop == "Length" or prop == "Beam" or prop == "Draft":
pass
Keyword arguments:
obj -- Part::FeaturePython created object which should be transformed
in a ship instance.
solids -- Set of solids which will compound the ship hull.
"""
# Add an unique property to identify the Ship instances
tooltip = str(QtGui.QApplication.translate(
"Ship",
"True if it is a valid ship instance, False otherwise",
None,
QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyBool",
"IsShip",
"Ship",
tooltip).IsShip = True
# Add the main dimensions
tooltip = str(QtGui.QApplication.translate(
"Ship",
"Ship length [m]",
None,
QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyLength",
"Length",
"Ship",
tooltip).Length = 0.0
tooltip = str(QtGui.QApplication.translate(
"Ship",
"Ship breadth [m]",
None,
QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyLength",
"Breadth",
"Ship",
tooltip).Breadth = 0.0
tooltip = str(QtGui.QApplication.translate(
"Ship",
"Ship draft [m]",
None,
QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyLength",
"Draft",
"Ship",
tooltip).Draft = 0.0
# Add the subshapes
obj.Shape = Part.makeCompound(solids)
tooltip = str(QtGui.QApplication.translate(
"Ship",
"Set of external faces of the ship hull",
None,
QtGui.QApplication.UnicodeUTF8))
obj.addProperty("Part::PropertyPartShape",
"ExternalFaces",
"Ship",
tooltip)
obj.Proxy = self
def onChanged(self, fp, prop):
"""Detects the ship data changes.
Keyword arguments:
fp -- Part::FeaturePython object affected.
prop -- Modified property name.
"""
if prop == "Length" or prop == "Breadth" or prop == "Draft":
pass
def execute(self, fp):
"""Detects the entity recomputations.
Keyword arguments:
fp -- Part::FeaturePython object affected.
"""
fp.Shape = Part.makeCompound(fp.Shape.Solids)
def execute(self, fp):
""" Called when a recomputation is needed.
@param fp Part::FeaturePython object.
"""
fp.Shape = Part.makeCompound(fp.Shape.Solids)
class ViewProviderShip:
def __init__(self, obj):
"Set this object to the proxy object of the actual view provider"
obj.Proxy = self
def __init__(self, obj):
"""Add this view provider to the selected object.
def attach(self, obj):
''' Setup the scene sub-graph of the view provider, this method is mandatory '''
return
Keyword arguments:
obj -- Object which must be modified.
"""
obj.Proxy = self
def updateData(self, fp, prop):
''' If a property of the handled feature has changed we have the chance to handle this here '''
return
def attach(self, obj):
"""Setup the scene sub-graph of the view provider, this method is
mandatory.
"""
return
def getDisplayModes(self,obj):
''' Return a list of display modes. '''
modes=[]
return modes
def updateData(self, fp, prop):
"""If a property of the handled feature has changed we have the chance
to handle this here.
def getDefaultDisplayMode(self):
''' Return the name of the default display mode. It must be defined in getDisplayModes. '''
return "Shaded"
Keyword arguments:
fp -- Part::FeaturePython object affected.
prop -- Modified property name.
"""
return
def setDisplayMode(self,mode):
''' Map the display mode defined in attach with those defined in getDisplayModes.
Since they have the same names nothing needs to be done. This method is optinal.
'''
return mode
def getDisplayModes(self, obj):
"""Return a list of display modes.
def onChanged(self, vp, prop):
''' Print the name of the property that has changed '''
# FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n")
Keyword arguments:
obj -- Object associated with the view provider.
"""
modes = []
return modes
def __getstate__(self):
''' When saving the document this object gets stored using Python's cPickle module.
Since we have some un-pickable here -- the Coin stuff -- we must define this method
to return a tuple of all pickable objects or None.
'''
return None
def getDefaultDisplayMode(self):
"""Return the name of the default display mode. It must be defined in
getDisplayModes."""
return "Shaded"
def __setstate__(self,state):
''' When restoring the pickled object from document we have the chance to set some
internals here. Since no data were pickled nothing needs to be done here.
'''
return None
def setDisplayMode(self, mode):
"""Map the display mode defined in attach with those defined in
getDisplayModes. Since they have the same names nothing needs to be
done. This method is optinal.
Keyword arguments:
mode -- Mode to be activated.
"""
return mode
def onChanged(self, vp, prop):
"""Detects the ship view provider data changes.
Keyword arguments:
vp -- View provider object affected.
prop -- Modified property name.
"""
pass
def __getstate__(self):
"""When saving the document this object gets stored using Python's
cPickle module. Since we have some un-pickable here (the Coin stuff)
we must define this method to return a tuple of all pickable objects
or None.
"""
return None
def __setstate__(self, state):
"""When restoring the pickled object from document we have the chance
to set some internals here. Since no data were pickled nothing needs
to be done here.
"""
return None
def getIcon(self):
"""Returns the icon for this kind of objects."""
return ":/icons/Ship_Instance.svg"
def getIcon(self):
return """
/* XPM */
static char * Ship_xpm[] = {
"32 32 396 2",
" c None",
". c #2C2C2C",
"+ c #3A3A3A",
"@ c #585857",
"# c #161616",
"$ c #000000",
"% c #363636",
"& c #333333",
"* c #B3B3B3",
"= c #B4B4B4",
"- c #949494",
"; c #565653",
"> c #141414",
", c #080807",
"' c #585858",
") c #878787",
"! c #9F9E9F",
"~ c #9F9F9E",
"{ c #8F8F90",
"] c #6B6B6B",
"^ c #101010",
"/ c #737373",
"( c #4C4C4C",
"_ c #B1B1B7",
": c #9090C0",
"< c #A7A7B2",
"[ c #87878E",
"} c #4F4F52",
"| c #191919",
"1 c #656565",
"2 c #D1D1D2",
"3 c #D1D1D1",
"4 c #CECECE",
"5 c #CDCCCC",
"6 c #CCCCCC",
"7 c #CCCCCB",
"8 c #CDCECD",
"9 c #BDBDBD",
"0 c #424242",
"a c #373737",
"b c #0A0A0A",
"c c #241414",
"d c #0E0C0C",
"e c #929393",
"f c #383738",
"g c #9B9B9A",
"h c #A0A0AF",
"i c #2929E4",
"j c #2525E5",
"k c #3F3FD7",
"l c #5B5BC8",
"m c #535368",
"n c #686866",
"o c #C8C8C8",
"p c #C8C8C7",
"q c #C7C6C7",
"r c #C6C6C6",
"s c #C5C5C5",
"t c #C4C5C5",
"u c #C3C4C3",
"v c #C3C3C2",
"w c #BCBCBC",
"x c #595959",
"y c #A6A6A6",
"z c #969696",
"A c #0B0B0B",
"B c #0D0707",
"C c #894646",
"D c #1C1A1A",
"E c #525252",
"F c #6C6D6C",
"G c #A3A3A2",
"H c #A3A296",
"I c #8E8F98",
"J c #6F6EA5",
"K c #5354AF",
"L c #373753",
"M c #8D8D8B",
"N c #C5C5C4",
"O c #C2C2C2",
"P c #C1C1C1",
"Q c #C0C0C0",
"R c #C0BFBF",
"S c #BFBFBF",
"T c #BEBEBE",
"U c #B1B2B2",
"V c #404040",
"W c #ABAAAA",
"X c #797979",
"Y c #2A1212",
"Z c #662828",
"` c #3D403F",
" . c #B5B5B5",
".. c #6B6A6B",
"+. c #4A4A4A",
"@. c #9A9A9A",
"#. c #909090",
"$. c #8B8B8A",
"%. c #898A86",
"&. c #84837F",
"*. c #3D3D3C",
"=. c #9E9E9E",
"-. c #BFBFBE",
";. c #BDBEBD",
">. c #BBBBBB",
",. c #BABABA",
"'. c #B9B9B9",
"). c #B8B8B8",
"!. c #999999",
"~. c #BABAB9",
"{. c #ABABAB",
"]. c #292929",
"^. c #381212",
"/. c #4C1514",
"(. c #535656",
"_. c #717171",
":. c #919090",
"<. c #818181",
"[. c #4E4E4E",
"}. c #4B4B4B",
"|. c #B1B1B1",
"1. c #B8B7B8",
"2. c #B6B6B6",
"3. c #B6B5B5",
"4. c #B4B5B4",
"5. c #B2B3B2",
"6. c #5C5D5C",
"7. c #AFAFAF",
"8. c #ADACAC",
"9. c #5B5B5B",
"0. c #410C0C",
"a. c #3E0707",
"b. c #525555",
"c. c #9C9C9C",
"d. c #2D2D2D",
"e. c #757575",
"f. c #474747",
"g. c #484848",
"h. c #9F9F9F",
"i. c #B3B3B4",
"j. c #B2B2B2",
"k. c #B0B0B0",
"l. c #ADAEAD",
"m. c #ADADAD",
"n. c #B0B1B0",
"o. c #1E1E1E",
"p. c #ACABAC",
"q. c #AAA9A9",
"r. c #A8A8A8",
"s. c #5D5D5D",
"t. c #290202",
"u. c #281010",
"v. c #272828",
"w. c #767777",
"x. c #505050",
"y. c #1F1F1F",
"z. c #5E5E5D",
"A. c #A4A5A5",
"B. c #B1B2B1",
"C. c #AEAEAE",
"D. c #AEADAD",
"E. c #ABACAC",
"F. c #AAAAAA",
"G. c #A9A8A8",
"H. c #ABABAC",
"I. c #7B7B7B",
"J. c #2B2B2B",
"K. c #A4A4A4",
"L. c #A6A5A6",
"M. c #888888",
"N. c #0E0E0E",
"O. c #101312",
"P. c #7E8080",
"Q. c #5E5E5E",
"R. c #242424",
"S. c #555555",
"T. c #7F7F7F",
"U. c #A4A3A4",
"V. c #B3B3B2",
"W. c #ACACAC",
"X. c #A9A9A9",
"Y. c #A8A7A7",
"Z. c #A7A6A7",
"`. c #A7A7A7",
" + c #A8A8A7",
".+ c #A5A5A5",
"++ c #A2A2A2",
"@+ c #222122",
"#+ c #7E7E7E",
"$+ c #A3A3A3",
"%+ c #9B9B9B",
"&+ c #050505",
"*+ c #6E6E6E",
"=+ c #A7A7A6",
"-+ c #989898",
";+ c #A5A4A4",
">+ c #A7A7A8",
",+ c #A5A6A7",
"'+ c #979A99",
")+ c #818383",
"!+ c #757878",
"~+ c #757979",
"{+ c #878A8A",
"]+ c #A3A5A5",
"^+ c #828282",
"/+ c #A0A0A0",
"(+ c #232323",
"_+ c #939393",
":+ c #A5A6A5",
"<+ c #A2A3A2",
"[+ c #A2A1A1",
"}+ c #A1A0A1",
"|+ c #939292",
"1+ c #636262",
"2+ c #554D4D",
"3+ c #634C4C",
"4+ c #755555",
"5+ c #936464",
"6+ c #9F6868",
"7+ c #9B6060",
"8+ c #804A4A",
"9+ c #5C3737",
"0+ c #1D1616",
"a+ c #A1A1A1",
"b+ c #010101",
"c+ c #151516",
"d+ c #707070",
"e+ c #9D9E9E",
"f+ c #8C8D8D",
"g+ c #8B8888",
"h+ c #726A6A",
"i+ c #6D5959",
"j+ c #866261",
"k+ c #C18B8B",
"l+ c #D79696",
"m+ c #D18C8C",
"n+ c #CB8180",
"o+ c #C57575",
"p+ c #BF6B6A",
"q+ c #BB6161",
"r+ c #B95958",
"s+ c #9C4544",
"t+ c #2E1212",
"u+ c #6F6C6C",
"v+ c #A0A1A1",
"w+ c #575757",
"x+ c #0C0C0C",
"y+ c #9C9D9D",
"z+ c #7A7272",
"A+ c #876F6F",
"B+ c #977070",
"C+ c #C28C8C",
"D+ c #D59595",
"E+ c #D08A8A",
"F+ c #C67D7D",
"G+ c #C07272",
"H+ c #BC6969",
"I+ c #B85F5F",
"J+ c #B35656",
"K+ c #B04C4C",
"L+ c #AB4243",
"M+ c #A63939",
"N+ c #591B1B",
"O+ c #6A2121",
"P+ c #542323",
"Q+ c #585A5A",
"R+ c #191515",
"S+ c #706262",
"T+ c #A58080",
"U+ c #B58383",
"V+ c #CE8F8F",
"W+ c #CD8989",
"X+ c #C17372",
"Y+ c #B45656",
"Z+ c #AF4C4C",
"`+ c #AB4242",
" @ c #A73A39",
".@ c #A3302F",
"+@ c #9F2626",
"@@ c #8E1A1A",
"#@ c #2C0808",
"$@ c #91191A",
"%@ c #2F0200",
"&@ c #90C6FB",
"*@ c #8BBFFB",
"=@ c #94CBFC",
"-@ c #AFEFFB",
";@ c #7DABA0",
">@ c #3C2521",
",@ c #C88484",
"'@ c #C57C7D",
")@ c #C17273",
"!@ c #B86060",
"~@ c #AB4343",
"{@ c #A73939",
"]@ c #A32F2F",
"^@ c #9B1C1D",
"/@ c #961313",
"(@ c #96090A",
"_@ c #3C0202",
":@ c #4E0202",
"<@ c #300000",
"[@ c #3E5378",
"}@ c #7EABF9",
"|@ c #84B5FC",
"1@ c #96CDFB",
"2@ c #B2F2FA",
"3@ c #C4FFFA",
"4@ c #2E3FFD",
"5@ c #3346FD",
"6@ c #2A3AFD",
"7@ c #161EFE",
"8@ c #1B25FD",
"9@ c #1F25B4",
"0@ c #7C6196",
"a@ c #AA6075",
"b@ c #AC5763",
"c@ c #AD5155",
"d@ c #AD4645",
"e@ c #A83938",
"f@ c #A3302E",
"g@ c #A02624",
"h@ c #9B1C1B",
"i@ c #971311",
"j@ c #930A09",
"k@ c #900300",
"l@ c #900505",
"m@ c #660007",
"n@ c #00000D",
"o@ c #200112",
"p@ c #597F88",
"q@ c #6E97FD",
"r@ c #384CFD",
"s@ c #394EFD",
"t@ c #2D3EFD",
"u@ c #151DFE",
"v@ c #1821FE",
"w@ c #3C52FD",
"x@ c #6388FC",
"y@ c #9CD6FB",
"z@ c #D0FFFA",
"A@ c #AEEEFB",
"B@ c #749FFF",
"C@ c #3F5DFF",
"D@ c #4165FF",
"E@ c #525AE3",
"F@ c #6153C4",
"G@ c #672D8D",
"H@ c #6C1B6A",
"I@ c #722164",
"J@ c #75225E",
"K@ c #731D57",
"L@ c #701653",
"M@ c #690E52",
"N@ c #5F0050",
"O@ c #562086",
"P@ c #11108D",
"Q@ c #2330BE",
"R@ c #344AE1",
"S@ c #4E6BFF",
"T@ c #4E6BFD",
"U@ c #597AFC",
"V@ c #6184FC",
"W@ c #7099FC",
"X@ c #8BBEFB",
"Y@ c #95CCFB",
"Z@ c #5B7CFC",
"`@ c #1C26FD",
" # c #121AFE",
".# c #9ED7FB",
"+# c #81B4FF",
"@# c #6893FF",
"## c #6997FF",
"$# c #6695FF",
"%# c #6390FF",
"&# c #618DFF",
"*# c #608DFF",
"=# c #618EFF",
"-# c #6391FF",
";# c #6898FF",
"># c #6B9AFF",
",# c #5171ED",
"'# c #90C4FF",
")# c #7EABFC",
"!# c #729CFC",
"~# c #6287FC",
"{# c #4761FD",
"]# c #070AFE",
"^# c #6084FC",
"/# c #9AD2FB",
"(# c #A2DDFB",
"_# c #8ABDFB",
":# c #2B3AFD",
"<# c #A9E8FB",
"[# c #B9FCFA",
"}# c #BAFEFA",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" . + @ # $ $ $ $ $ ",
" % & * = - ; > $ $ , ' ) ! ~ { ] & $ $ $ ",
" ^ / ( = _ : < [ } | $ 1 2 3 4 5 6 7 6 8 9 0 a b ",
" c d e f g h i j k l m n 4 o p q r s t u v w x y z A ",
" B C D * E F G H I J K L M N O O P Q R S T 9 U V W O X $ ",
" Y Z ` ...+.@.#.$.%.&.*.=.-.;.w >.>.,.'.).).!.+ ~. .{.]. ",
" ^./.(.y _.f :.) <.[.^ }.|.).1.2.3. .4.* 5. .6.1 4.7.8.9. ",
" 0.a.b.c./ d.e.f.| g.h.9 i.* j.|.k.7.7.l.m.n.o.@.p.q.r.s. ",
" t.u.v.w.x.y.% z.A.).B.C.D.m.E.{.F.F.G.r.H.I.J.k.K.L.M.N. ",
" O.P.Q.R.S.T.U.V.W.q.X.r.Y.Z.`.Y. +`..+++{.@+#+$+++%+y. ",
" &+*+W.=+-+;+X.>+y .+K.K.y y ,+'+)+!+~+{+]+^+].$+/+$+J. ",
" (+_+:+U.$+<+[+}+/+h.=.|+1+2+3+4+5+6+7+8+9+0+_.a+/+0 b+ ",
" c+d+h.a+/+++e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+u+v+w+$ ",
" x+f.- y+w.z+A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+$ ",
" R+S+T+U+V+W+F+X+H+I+Y+Z+`+ @.@+@@@#@$@%@$ ",
"&@*@=@-@;@>@,@'@)@H+!@Y+K+~@{@]@+@^@/@(@_@:@<@[@}@|@1@2@3@ ",
"4@5@6@7@8@9@0@a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@v@w@x@y@",
" z@A@B@C@D@E@F@G@H@I@J@K@L@M@N@O@P@Q@R@S@T@U@V@W@X@Y@Z@`@ #",
" .#+#@###$#%#&#*#=#-#;#>#,#'# )#!#~#{#]#^#/#",
" (#_#:#<#",
" [#}#",
" ",
" ",
" ",
" "};
"""
def weights(obj):
""" Returns Ship weights list. If weights has not been sets,
this tool creates it.
@param obj Ship object
@return Weights list. None if errors
"""
# Test if is a ship instance
props = obj.PropertiesList
try:
props.index("IsShip")
except ValueError:
return None
if not obj.IsShip:
return None
# Test if properties already exist
try:
props.index("WeightNames")
except ValueError:
tooltip = str(QtGui.QApplication.translate("Ship","Ship Weights names",None,QtGui.QApplication.UnicodeUTF8))
lighweight = str(QtGui.QApplication.translate("Ship","Lightweight",None,QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyStringList","WeightNames","Ship", tooltip).WeightNames=[lighweight]
try:
props.index("WeightMass")
except ValueError:
# Compute mass aproximation
from shipHydrostatics import Tools
disp = Tools.displacement(obj,obj.Draft)
tooltip = str(QtGui.QApplication.translate("Ship","Ship Weights masses",None,QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyFloatList","WeightMass","Ship", tooltip).WeightMass=[1000.0 * disp[0]]
try:
props.index("WeightPos")
except ValueError:
# Compute mass aproximation
from shipHydrostatics import Tools
disp = Tools.displacement(obj,obj.Draft)
tooltip = str(QtGui.QApplication.translate("Ship","Ship Weights centers of gravity",None,QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyVectorList","WeightPos","Ship", tooltip).WeightPos=[Vector(disp[1].x,0.0,obj.Draft)]
# Setup list
weights = []
for i in range(0,len(obj.WeightNames)):
weights.append([obj.WeightNames[i], obj.WeightMass[i], obj.WeightPos[i]])
return weights
"""Returns the ship weights list. If weights has not been set this tool
will generate the default ones.
Keyword arguments:
obj -- Ship inmstance object.
"""
# Test if is a ship instance
props = obj.PropertiesList
try:
props.index("IsShip")
except ValueError:
return None
if not obj.IsShip:
return None
# Test if properties already exist
try:
props.index("WeightNames")
except ValueError:
tooltip = str(QtGui.QApplication.translate(
"Ship",
"Ship Weights names",
None,
QtGui.QApplication.UnicodeUTF8))
lighweight = str(QtGui.QApplication.translate(
"Ship",
"Lightweight",
None,
QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyStringList",
"WeightNames",
"Ship",
tooltip).WeightNames = [lighweight]
try:
props.index("WeightMass")
except ValueError:
# Compute a mass aproximation
from shipHydrostatics import Tools
disp = Tools.displacement(obj, obj.Draft)
tooltip = str(QtGui.QApplication.translate(
"Ship",
"Ship Weights masses [tons]",
None,
QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyFloatList",
"WeightMass",
"Ship",
tooltip).WeightMass = [1000.0 * disp[0]]
try:
props.index("WeightPos")
except ValueError:
# Compute a CoG aproximation
from shipHydrostatics import Tools
disp = Tools.displacement(obj, obj.Draft)
tooltip = str(QtGui.QApplication.translate(
"Ship",
"Ship Weights centers of gravity",
None,
QtGui.QApplication.UnicodeUTF8))
obj.addProperty("App::PropertyVectorList",
"WeightPos",
"Ship",
tooltip).WeightPos = [Vector(disp[1].x,
0.0,
obj.Draft)]
# Setup the weights list
weights = []
for i in range(len(obj.WeightNames)):
weights.append([obj.WeightNames[i],
obj.WeightMass[i],
obj.WeightPos[i]])
return weights

View File

@@ -14,7 +14,6 @@ nobase_data_DATA = \
resources/examples/s60_katamaran.fcstd \
resources/examples/wigley.fcstd \
resources/examples/wigley_katamaran.fcstd \
resources/icons/Ico.xpm \
resources/opencl/matrixGen.cl \
resources/opencl/jacobi.cl \
resources/opencl/minres.cl \

View File

@@ -1,7 +1,7 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* 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) *
@@ -21,133 +21,221 @@
#* *
#***************************************************************************
from PyQt4 import QtCore, QtGui
import FreeCAD, FreeCADGui, os
import PySide
from PySide import QtCore, QtGui
import FreeCAD
import FreeCADGui
import os
# Load resources
import Ship_rc
FreeCADGui.addLanguagePath(":/Ship/translations")
FreeCADGui.addIconPath(":/Ship/icons")
class LoadExample:
class LoadExample:
def Activated(self):
import shipLoadExample
shipLoadExample.load()
def GetResources(self):
MenuText = QtCore.QT_TRANSLATE_NOOP('Ship_LoadExample', 'Load an example ship geometry')
ToolTip = QtCore.QT_TRANSLATE_NOOP('Ship_LoadExample', 'Load an example ship geometry able to be converted into a ship.')
return {'Pixmap' : 'LoadIco', 'MenuText': MenuText, 'ToolTip': ToolTip}
MenuText = QtCore.QT_TRANSLATE_NOOP(
'Ship_LoadExample',
'Load an example ship geometry')
ToolTip = QtCore.QT_TRANSLATE_NOOP(
'Ship_LoadExample',
'Load an example ship hull geometry.')
return {'Pixmap': 'Ship_Load',
'MenuText': MenuText,
'ToolTip': ToolTip}
class CreateShip:
class CreateShip:
def Activated(self):
import shipCreateShip
shipCreateShip.load()
def GetResources(self):
MenuText = QtCore.QT_TRANSLATE_NOOP('Ship_CreateShip', 'Create a new ship')
ToolTip = QtCore.QT_TRANSLATE_NOOP('Ship_CreateShip', 'Create a new ship in order to work with them')
return {'Pixmap' : 'Ico', 'MenuText': MenuText, 'ToolTip': ToolTip}
MenuText = QtCore.QT_TRANSLATE_NOOP(
'Ship_CreateShip',
'Create a new ship')
ToolTip = QtCore.QT_TRANSLATE_NOOP(
'Ship_CreateShip',
'Create a new ship instance on top of the hull geometry')
return {'Pixmap': 'Ship_Module',
'MenuText': MenuText,
'ToolTip': ToolTip}
class OutlineDraw:
class OutlineDraw:
def Activated(self):
import shipOutlineDraw
shipOutlineDraw.load()
def GetResources(self):
MenuText = QtCore.QT_TRANSLATE_NOOP('Ship_OutlineDraw', 'Outline draw')
ToolTip = QtCore.QT_TRANSLATE_NOOP('Ship_OutlineDraw', 'Plot ship outline draw')
return {'Pixmap' : 'OutlineDrawIco', 'MenuText': MenuText, 'ToolTip': ToolTip}
MenuText = QtCore.QT_TRANSLATE_NOOP(
'Ship_OutlineDraw',
'Outline draw')
ToolTip = QtCore.QT_TRANSLATE_NOOP(
'Ship_OutlineDraw',
'Plots the ship hull outline draw')
return {'Pixmap': 'Ship_OutlineDraw',
'MenuText': MenuText,
'ToolTip': ToolTip}
class AreasCurve:
class AreasCurve:
def Activated(self):
import shipAreasCurve
shipAreasCurve.load()
def GetResources(self):
MenuText = QtCore.QT_TRANSLATE_NOOP('Ship_AreasCurve', 'Areas curve')
ToolTip = QtCore.QT_TRANSLATE_NOOP('Ship_AreasCurve', 'Plot transversal areas curve')
return {'Pixmap' : 'AreaCurveIco', 'MenuText': MenuText, 'ToolTip': ToolTip}
MenuText = QtCore.QT_TRANSLATE_NOOP(
'Ship_AreasCurve',
'Areas curve')
ToolTip = QtCore.QT_TRANSLATE_NOOP(
'Ship_AreasCurve',
'Plot the transversal areas curve')
return {'Pixmap': 'Ship_AreaCurve',
'MenuText': MenuText,
'ToolTip': ToolTip}
class Hydrostatics:
class Hydrostatics:
def Activated(self):
import shipHydrostatics
shipHydrostatics.load()
def GetResources(self):
MenuText = QtCore.QT_TRANSLATE_NOOP('Ship_Hydrostatics', 'Hydrostatics')
ToolTip = QtCore.QT_TRANSLATE_NOOP('Ship_Hydrostatics', 'Plot ship hydrostatics')
return {'Pixmap' : 'HydrostaticsIco', 'MenuText': MenuText, 'ToolTip': ToolTip}
class SetWeights:
MenuText = QtCore.QT_TRANSLATE_NOOP(
'Ship_Hydrostatics',
'Hydrostatics')
ToolTip = QtCore.QT_TRANSLATE_NOOP(
'Ship_Hydrostatics',
'Plot the ship hydrostatics')
return {'Pixmap': 'HydrostaticsIco',
'MenuText': MenuText,
'ToolTip': ToolTip}
class SetWeights:
def Activated(self):
import tankWeights
tankWeights.load()
def GetResources(self):
MenuText = QtCore.QT_TRANSLATE_NOOP('Ship_Weights', 'Set ship weights')
ToolTip = QtCore.QT_TRANSLATE_NOOP('Ship_Weights', 'Set ship weights, tanks must be added later')
return {'Pixmap' : 'Weight', 'MenuText': MenuText, 'ToolTip': ToolTip}
MenuText = QtCore.QT_TRANSLATE_NOOP(
'Ship_Weights',
'Set ship weights')
ToolTip = QtCore.QT_TRANSLATE_NOOP(
'Ship_Weights',
'Set the ship weights (tanks must be added later)')
return {'Pixmap': 'Weight',
'MenuText': MenuText,
'ToolTip': ToolTip}
class CreateTank:
class CreateTank:
def Activated(self):
import tankCreateTank
tankCreateTank.load()
def GetResources(self):
MenuText = QtCore.QT_TRANSLATE_NOOP('Ship_CreateTank', 'Create a new tank')
ToolTip = QtCore.QT_TRANSLATE_NOOP('Ship_CreateTank', 'Create a new ship tank')
return {'Pixmap' : 'Tank', 'MenuText': MenuText, 'ToolTip': ToolTip}
MenuText = QtCore.QT_TRANSLATE_NOOP(
'Ship_CreateTank',
'Create a new tank')
ToolTip = QtCore.QT_TRANSLATE_NOOP(
'Ship_CreateTank',
'Create a new ship tank')
return {'Pixmap': 'Tank',
'MenuText': MenuText,
'ToolTip': ToolTip}
class GZ:
class GZ:
def Activated(self):
import tankGZ
tankGZ.load()
def GetResources(self):
MenuText = QtCore.QT_TRANSLATE_NOOP('Ship_GZ', 'GZ curve')
ToolTip = QtCore.QT_TRANSLATE_NOOP('Ship_GZ', 'Transversal stability GZ curve computation')
return {'Pixmap' : 'HydrostaticsIco', 'MenuText': MenuText, 'ToolTip': ToolTip}
MenuText = QtCore.QT_TRANSLATE_NOOP(
'Ship_GZ',
'GZ curve')
ToolTip = QtCore.QT_TRANSLATE_NOOP(
'Ship_GZ',
'Transversal stability GZ curve computation')
return {'Pixmap': 'HydrostaticsIco',
'MenuText': MenuText,
'ToolTip': ToolTip}
class CreateSim:
class CreateSim:
def Activated(self):
import simCreate
simCreate.load()
def GetResources(self):
MenuText = QtCore.QT_TRANSLATE_NOOP('Ship_CreateSim', 'Create a new simulation')
ToolTip = QtCore.QT_TRANSLATE_NOOP('Ship_CreateSim', 'Create a new simulation in order to process later')
return {'Pixmap' : 'SimCreateIco', 'MenuText': MenuText, 'ToolTip': ToolTip}
MenuText = QtCore.QT_TRANSLATE_NOOP(
'Ship_CreateSim',
'Create a new simulation')
ToolTip = QtCore.QT_TRANSLATE_NOOP(
'Ship_CreateSim',
'Create a new simulation in order to process later')
return {'Pixmap': 'SimCreateIco',
'MenuText': MenuText,
'ToolTip': ToolTip}
class RunSim:
class RunSim:
def Activated(self):
import simRun
simRun.load()
def GetResources(self):
MenuText = QtCore.QT_TRANSLATE_NOOP('Ship_RunSim', 'Run a simulation')
ToolTip = QtCore.QT_TRANSLATE_NOOP('Ship_RunSim', 'Run a simulation')
return {'Pixmap' : 'SimRunIco', 'MenuText': MenuText, 'ToolTip': ToolTip}
MenuText = QtCore.QT_TRANSLATE_NOOP(
'Ship_RunSim',
'Run a simulation')
ToolTip = QtCore.QT_TRANSLATE_NOOP(
'Ship_RunSim',
'Run a simulation')
return {'Pixmap': 'SimRunIco',
'MenuText': MenuText,
'ToolTip': ToolTip}
class StopSim:
class StopSim:
def Activated(self):
import simRun
simRun.stop()
def GetResources(self):
MenuText = QtCore.QT_TRANSLATE_NOOP('Ship_StopSim', 'Stop active simulation')
ToolTip = QtCore.QT_TRANSLATE_NOOP('Ship_StopSim', 'Stop active simulation')
return {'Pixmap' : 'SimStopIco', 'MenuText': MenuText, 'ToolTip': ToolTip}
MenuText = QtCore.QT_TRANSLATE_NOOP(
'Ship_StopSim',
'Stop active simulation')
ToolTip = QtCore.QT_TRANSLATE_NOOP(
'Ship_StopSim',
'Stop active simulation')
return {'Pixmap': 'SimStopIco',
'MenuText': MenuText,
'ToolTip': ToolTip}
class TrackSim:
class TrackSim:
def Activated(self):
import simPost
simPost.load()
def GetResources(self):
MenuText = QtCore.QT_TRANSLATE_NOOP('Ship_TrackSim', 'Track simulation')
ToolTip = QtCore.QT_TRANSLATE_NOOP('Ship_TrackSim', 'Track simulation')
return {'Pixmap' : 'SimPostIco', 'MenuText': MenuText, 'ToolTip': ToolTip}
MenuText = QtCore.QT_TRANSLATE_NOOP(
'Ship_TrackSim',
'Track simulation')
ToolTip = QtCore.QT_TRANSLATE_NOOP(
'Ship_TrackSim',
'Track simulation')
return {'Pixmap': 'SimPostIco',
'MenuText': MenuText,
'ToolTip': ToolTip}
FreeCADGui.addCommand('Ship_LoadExample', LoadExample())

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,12 @@
<RCC>
<qresource prefix="Ship">
<file>icons/AreaCurveIco.png</file>
<qresource>
<file>icons/Ship_AreaCurve.svg</file>
<file>icons/Ship_Instance.svg</file>
<file>icons/Ship_Load.svg</file>
<file>icons/Ship_Logo.svg</file>
<file>icons/Ship_Module.svg</file>
<file>icons/Ship_OutlineDraw.svg</file>
<file>icons/HydrostaticsIco.png</file>
<file>icons/Ico.png</file>
<file>icons/LoadIco.png</file>
<file>icons/OutlineDrawIco.png</file>
<file>icons/SimCreateIco.png</file>
<file>icons/SimPostIco.png</file>
<file>icons/SimRunIco.png</file>

View File

@@ -0,0 +1,400 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2985"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Ship_AreaCurve.svg">
<defs
id="defs2987">
<linearGradient
id="linearGradient4722">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop4724" />
<stop
style="stop-color:#bebebe;stop-opacity:1;"
offset="1"
id="stop4726" />
</linearGradient>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;">
<path
id="path3873"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lend"
style="overflow:visible;">
<path
id="path3867"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.8) rotate(180) translate(12.5,0)" />
</marker>
<linearGradient
id="linearGradient3937">
<stop
style="stop-color:#be7328;stop-opacity:1;"
offset="0"
id="stop3939" />
<stop
style="stop-color:#dc962d;stop-opacity:1;"
offset="1"
id="stop3941" />
</linearGradient>
<linearGradient
id="linearGradient3929">
<stop
id="stop3931"
offset="0"
style="stop-color:#c88c3c;stop-opacity:1;" />
<stop
id="stop3933"
offset="1"
style="stop-color:#ffff96;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3893">
<stop
style="stop-color:#505050;stop-opacity:1;"
offset="0"
id="stop3895" />
<stop
style="stop-color:#aaaaaa;stop-opacity:1;"
offset="1"
id="stop3897" />
</linearGradient>
<linearGradient
id="linearGradient3873">
<stop
style="stop-color:#f0be6e;stop-opacity:1;"
offset="0"
id="stop3875" />
<stop
style="stop-color:#c88228;stop-opacity:1;"
offset="1"
id="stop3877" />
</linearGradient>
<linearGradient
id="linearGradient3863">
<stop
id="stop3865"
offset="0"
style="stop-color:#6e4b18;stop-opacity:1;" />
<stop
id="stop3867"
offset="1"
style="stop-color:#c88228;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3979">
<stop
id="stop3981"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3983"
offset="1"
style="stop-color:#ff9600;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3971">
<stop
id="stop3973"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3975"
offset="1"
style="stop-color:#be7300;stop-opacity:1;" />
</linearGradient>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;">
<path
id="path4031"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Send"
style="overflow:visible;">
<path
id="path4049"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.3) rotate(180) translate(-2.3,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Sstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Sstart"
style="overflow:visible">
<path
id="path4046"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.3) translate(-2.3,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Mstart"
style="overflow:visible">
<path
id="path4040"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.6) translate(0,0)" />
</marker>
<linearGradient
id="linearGradient3900">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3902" />
<stop
style="stop-color:#a0a0a0;stop-opacity:1;"
offset="1"
id="stop3904" />
</linearGradient>
<linearGradient
id="linearGradient3882">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3884" />
<stop
style="stop-color:#960000;stop-opacity:1;"
offset="1"
id="stop3886" />
</linearGradient>
<linearGradient
id="linearGradient3860">
<stop
style="stop-color:#1e76e3;stop-opacity:1;"
offset="0"
id="stop3862" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3864" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3860-6"
id="linearGradient3866-5"
x1="31.125395"
y1="61.410763"
x2="30.113636"
y2="12.160761"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3860-6">
<stop
style="stop-color:#5a9ff5;stop-opacity:1;"
offset="0"
id="stop3862-4" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3864-4" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient3871"
gradientUnits="userSpaceOnUse"
x1="38.907837"
y1="51.470051"
x2="45.302406"
y2="54.091148" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3863"
id="linearGradient3891"
gradientUnits="userSpaceOnUse"
x1="51.657837"
y1="34.470051"
x2="45.427406"
y2="32.216148" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3893"
id="linearGradient3899"
gradientUnits="userSpaceOnUse"
x1="51.657837"
y1="34.470051"
x2="45.427406"
y2="32.216148" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3903"
cx="53.748837"
cy="4.9173141"
fx="53.748837"
fy="4.9173141"
r="3.2874005"
gradientTransform="matrix(2.3303929,-1.4921636,1.0936999,1.7080907,-77.643882,78.644487)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3929"
id="radialGradient3927"
cx="15.125"
cy="48.035076"
fx="15.125"
fy="48.035076"
r="18.875"
gradientTransform="matrix(2.7636523,-0.71644256,0.733044,2.8276918,-61.887066,-71.992203)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3937"
id="radialGradient3943"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.40097726,-0.37931652,0.11734116,0.12404187,14.422507,4.6205505)"
cx="-14.308363"
cy="14.910047"
fx="-14.308363"
fy="14.910047"
r="18.875" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3929"
id="radialGradient3949"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.7636523,-0.71644256,0.733044,2.8276918,-61.887066,-71.992203)"
cx="15.125"
cy="48.035076"
fx="15.125"
fy="48.035076"
r="18.875" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3937"
id="radialGradient3951"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.40097726,-0.37931652,0.11734116,0.12404187,14.422507,4.6205505)"
cx="-14.308363"
cy="14.910047"
fx="-14.308363"
fy="14.910047"
r="18.875" />
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend-3"
style="overflow:visible">
<path
inkscape:connector-curvature="0"
id="path3873-0"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
</marker>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4722"
id="radialGradient4730"
cx="22.399223"
cy="27.920977"
fx="22.399223"
fy="27.920977"
r="25.5625"
gradientTransform="matrix(0.61346721,-0.22517965,0.21191717,0.57733561,2.1543769,16.986575)"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6568543"
inkscape:cx="47.014405"
inkscape:cy="15.321975"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1366"
inkscape:window-height="722"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
style="fill:url(#radialGradient4730);fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 4,59.875 c 3.4375,0 6.125,-43.375 24,-43.375 17.875,0 16.875,43.25 26.625,43.25"
id="path4720"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csc" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
d="m 4.25,61 0,-58.375"
id="path3066"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
d="m 3,59.75 58.375,0"
id="path3066-6"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,319 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2985"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Ship_Module.svg">
<defs
id="defs2987">
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;">
<path
id="path4031"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Send"
style="overflow:visible;">
<path
id="path4049"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.3) rotate(180) translate(-2.3,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Sstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Sstart"
style="overflow:visible">
<path
id="path4046"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.3) translate(-2.3,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Mstart"
style="overflow:visible">
<path
id="path4040"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.6) translate(0,0)" />
</marker>
<linearGradient
id="linearGradient3900">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3902" />
<stop
style="stop-color:#a0a0a0;stop-opacity:1;"
offset="1"
id="stop3904" />
</linearGradient>
<linearGradient
id="linearGradient3882">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3884" />
<stop
style="stop-color:#960000;stop-opacity:1;"
offset="1"
id="stop3886" />
</linearGradient>
<linearGradient
id="linearGradient3860">
<stop
style="stop-color:#1e76e3;stop-opacity:1;"
offset="0"
id="stop3862" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3864" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3860-6"
id="linearGradient3866-5"
x1="31.125395"
y1="61.410763"
x2="30.113636"
y2="12.160761"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3860-6">
<stop
style="stop-color:#5a9ff5;stop-opacity:1;"
offset="0"
id="stop3862-4" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3864-4" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3890"
cx="25.629292"
cy="38.444794"
fx="25.629292"
fy="38.444794"
r="11.769514"
gradientTransform="matrix(1.7159608,-0.59513916,0.29226939,0.84269877,-28.848719,13.387411)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3898"
cx="31.803391"
cy="31.659325"
fx="31.803391"
fy="31.659325"
r="3.417994"
gradientTransform="matrix(4.734087,-1.1798961,0.73145851,2.9348253,-139.28906,-25.817159)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3906"
cx="20.211554"
cy="12.140632"
fx="20.211554"
fy="12.140632"
r="15.992805"
gradientTransform="matrix(1.6937502,-0.50833021,0.26447657,0.88123273,-17.232683,18.826666)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3914"
cx="44.852757"
cy="22.63999"
fx="44.852757"
fy="22.63999"
r="5.0740972"
gradientTransform="matrix(1,0,0,1.5705123,0,-16.367411)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3926"
cx="18.050617"
cy="25.765184"
fx="18.050617"
fy="25.765184"
r="2.4997866"
gradientTransform="matrix(1.1875159,0.30002561,-0.66139805,2.6178455,13.656265,-48.87061)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3930"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1875159,0.30002561,-0.66139805,2.6178455,13.656265,-48.87061)"
cx="17.915045"
cy="24.185383"
fx="17.915045"
fy="24.185383"
r="2.4997866" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3936"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.980826,0.90111766,-0.59612552,2.6334762,-39.306292,-60.304205)"
cx="18.420965"
cy="23.089165"
fx="18.420965"
fy="23.089165"
r="2.4997866" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3946"
cx="16.274988"
cy="23.718588"
fx="16.274988"
fy="23.718588"
r="3.6819806"
gradientTransform="matrix(1.1622967,-0.42417542,0.71241125,1.9521011,-19.727075,-16.498215)"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4"
inkscape:cx="-6.1454977"
inkscape:cy="13.674344"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1366"
inkscape:window-height="722"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3977"
transform="matrix(1.6428611,0,0,1.6428611,-22.221039,-15.973411)">
<g
id="g3968">
<g
id="g3953">
<path
inkscape:connector-curvature="0"
id="path3938"
d="m 16.528621,30.942758 0.707107,-7.778175 c 0,0 0.795495,-1.767767 2.563262,-1.767767 1.767767,0 2.032932,1.06066 2.032932,1.06066 l 1.06066,8.220117 z"
style="fill:url(#radialGradient3946);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<g
id="g3948">
<path
style="fill:url(#radialGradient3926);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 18.73833,21.286331 1.657281,-0.729204 c 0,0 2.342292,1.546796 2.342292,3.601825 0,2.055029 0,7.159456 0,7.159456 l -3.987549,1.738087 0.05427,-7.748495 1.06066,-2.231805 c 0,0 -0.0221,-1.126952 -1.126951,-1.789864 z"
id="path3918"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsccccc" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path3928"
d="m 18.73833,21.286331 1.657281,-0.729204 0.06629,-2.209709 -1.723573,0.618718 z"
style="fill:url(#radialGradient3930);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
<path
sodipodi:nodetypes="cscc"
inkscape:connector-curvature="0"
id="path3932"
d="m 22.737903,31.318408 c 0,0 0,-5.104427 0,-7.159456 0,-2.055029 -2.342292,-3.601825 -2.342292,-3.601825 0,-0.927244 0.06629,-2.209709 0.06629,-2.209709 l 15.055864,4.034207 0,2.108783 c 0,0 -1.930193,-0.176776 -1.930193,1.502602 0,1.679379 0,7.51301 0,7.51301 z"
style="fill:url(#radialGradient3936);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
</g>
</g>
<path
style="fill:none;stroke:#0000ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 23.776465,21.927147 32.15231,24.26278"
id="path3966"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
<g
id="g3960">
<path
style="fill:url(#radialGradient3890);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 42.02866,32.97569 c 0,0 -1.237437,-1.149049 -4.596194,-1.149049 -3.358758,0 -9.678525,1.723573 -11.136932,2.165515 -1.458408,0.441941 -6.805903,2.872621 -6.805903,2.872621 0,0 1.458408,1.016466 1.767767,1.325825 0.309359,0.309359 1.281631,1.325825 1.281631,1.325825 0,0 5.170718,1.37002 7.51301,1.37002 2.342291,0 7.73398,-0.751301 7.73398,-0.751301 0,0 3.756505,-4.375223 4.242641,-7.159456 z"
id="path3870"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path3874"
d="m 37.786019,40.135146 c 0,0 3.756505,-4.375223 4.242641,-7.159456 1.723573,3.270369 1.59099,3.18198 1.59099,3.18198 0,0 -3.049398,3.402952 -5.833631,3.977476 z"
style="fill:url(#radialGradient3898);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="ccccc"
style="fill:url(#radialGradient3914);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 45.829359,21.220039 c 0,4.065864 -3.800699,11.755651 -3.800699,11.755651 1.723573,3.270369 1.59099,3.18198 1.59099,3.18198 2.695845,-1.325825 7.557204,-8.529475 7.557204,-8.529475 0,0 -1.944544,-6.142991 -5.347495,-6.408156"
id="path3876"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path3878"
d="m 14.84375,33.46875 c 0.18566,-1.505743 3.84375,-4.625 3.84375,-4.625 L 20.34375,30.5 c 0,0 2.21875,-1.5 4.15625,-2.28125 C 26.4375,27.4375 30.53125,26.25 30.53125,26.25 l 0.9375,-4.4375 c 0,0 5.471217,-3.903672 14.360609,-0.592461 0,4.065864 -3.800699,11.755651 -3.800699,11.755651 0,0 -1.237437,-1.149049 -4.596194,-1.149049 -3.358758,0 -9.678525,1.723573 -11.136932,2.165515 -1.458408,0.441941 -6.805903,2.872621 -6.805903,2.872621 0,0 -3.770881,-3.083527 -4.645881,-3.396027"
style="fill:url(#radialGradient3906);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
sodipodi:nodetypes="cccsccccsscc" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,452 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2985"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Ship_Load.svg">
<defs
id="defs2987">
<linearGradient
id="linearGradient3979">
<stop
id="stop3981"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3983"
offset="1"
style="stop-color:#ff9600;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3971">
<stop
id="stop3973"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3975"
offset="1"
style="stop-color:#be7300;stop-opacity:1;" />
</linearGradient>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;">
<path
id="path4031"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Send"
style="overflow:visible;">
<path
id="path4049"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.3) rotate(180) translate(-2.3,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Sstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Sstart"
style="overflow:visible">
<path
id="path4046"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.3) translate(-2.3,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Mstart"
style="overflow:visible">
<path
id="path4040"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.6) translate(0,0)" />
</marker>
<linearGradient
id="linearGradient3900">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3902" />
<stop
style="stop-color:#a0a0a0;stop-opacity:1;"
offset="1"
id="stop3904" />
</linearGradient>
<linearGradient
id="linearGradient3882">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3884" />
<stop
style="stop-color:#960000;stop-opacity:1;"
offset="1"
id="stop3886" />
</linearGradient>
<linearGradient
id="linearGradient3860">
<stop
style="stop-color:#1e76e3;stop-opacity:1;"
offset="0"
id="stop3862" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3864" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3860-6"
id="linearGradient3866-5"
x1="31.125395"
y1="61.410763"
x2="30.113636"
y2="12.160761"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3860-6">
<stop
style="stop-color:#5a9ff5;stop-opacity:1;"
offset="0"
id="stop3862-4" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3864-4" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3979"
id="radialGradient3964"
cx="-5.6195011"
cy="1.8141681"
fx="-5.6195011"
fy="1.8141681"
r="26.25"
gradientTransform="matrix(1.8486536,-0.93638191,0.67849884,1.3395274,0.15759963,2.6203733)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3971"
id="radialGradient3977"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.8486536,-0.93638191,0.67849884,1.3395274,0.15759963,2.6203733)"
cx="14.92104"
cy="5.9079928"
fx="14.92104"
fy="5.9079928"
r="26.25" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient4009"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1622967,-0.42417542,0.71241125,1.9521011,-19.727075,-16.498215)"
cx="16.274988"
cy="23.718588"
fx="16.274988"
fy="23.718588"
r="3.6819806" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient4011"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1875159,0.30002561,-0.66139805,2.6178455,13.656265,-48.87061)"
cx="18.050617"
cy="25.765184"
fx="18.050617"
fy="25.765184"
r="2.4997866" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient4013"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1875159,0.30002561,-0.66139805,2.6178455,13.656265,-48.87061)"
cx="17.915045"
cy="24.185383"
fx="17.915045"
fy="24.185383"
r="2.4997866" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient4015"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.980826,0.90111766,-0.59612552,2.6334762,-39.306292,-60.304205)"
cx="18.420965"
cy="23.089165"
fx="18.420965"
fy="23.089165"
r="2.4997866" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient4017"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.7159608,-0.59513916,0.29226939,0.84269877,-28.848719,13.387411)"
cx="25.629292"
cy="38.444794"
fx="25.629292"
fy="38.444794"
r="11.769514" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient4019"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(4.734087,-1.1798961,0.73145851,2.9348253,-139.28906,-25.817159)"
cx="31.803391"
cy="31.659325"
fx="31.803391"
fy="31.659325"
r="3.417994" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient4021"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.5705123,0,-16.367411)"
cx="44.852757"
cy="22.63999"
fx="44.852757"
fy="22.63999"
r="5.0740972" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient4023"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.6937502,-0.50833021,0.26447657,0.88123273,-17.232683,18.826666)"
cx="20.211554"
cy="12.140632"
fx="20.211554"
fy="12.140632"
r="15.992805" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4"
inkscape:cx="-23.757069"
inkscape:cy="20.751227"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1366"
inkscape:window-height="722"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
inkscape:connector-curvature="0"
id="path3967"
d="M 19.5,24.25 14.125,57 l 38.625,0 4.625,-32.75 -24.3125,0 -0.8125,-4.625 -9,0 z"
style="fill:url(#radialGradient3977);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
sodipodi:nodetypes="ccccc" />
<g
id="g3985"
transform="translate(105.5,-0.75)">
<path
inkscape:connector-curvature="0"
id="path3856"
d="m -55.356078,30.695806 c 0,0 1.811961,-1.281631 6.054602,-1.281631 4.24264,0 5.656854,1.502602 5.656854,1.502602"
style="fill:none;stroke:#afffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path3860"
d="m -103.0625,28.4375 c 0,0 0.9375,-0.9375 3.375,-0.9375 2.4375,0 5.25,1 5.25,1"
style="fill:none;stroke:#afffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path3864"
d="m -49.831806,29.458369 c 0,0 -3.623923,-1.679378 -10.208855,-1.679378 -6.584932,0 -10.606602,2.474873 -10.606602,2.474873"
style="fill:none;stroke:#afffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m -49.831806,29.458369 c 0,0 -3.623923,-1.679378 -10.208855,-1.679378 -6.584932,0 -10.606602,2.474873 -10.606602,2.474873"
id="path3866"
inkscape:connector-curvature="0" />
<g
transform="translate(-104.5,-10.5)"
id="g3977">
<g
id="g3968">
<g
id="g3953">
<path
style="fill:url(#radialGradient4009);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 16.528621,30.942758 0.707107,-7.778175 c 0,0 0.795495,-1.767767 2.563262,-1.767767 1.767767,0 2.032932,1.06066 2.032932,1.06066 l 1.06066,8.220117 z"
id="path3938"
inkscape:connector-curvature="0" />
<g
id="g3948">
<path
sodipodi:nodetypes="ccsccccc"
inkscape:connector-curvature="0"
id="path3918"
d="m 18.73833,21.286331 1.657281,-0.729204 c 0,0 2.342292,1.546796 2.342292,3.601825 0,2.055029 0,7.159456 0,7.159456 l -3.987549,1.738087 0.05427,-7.748495 1.06066,-2.231805 c 0,0 -0.0221,-1.126952 -1.126951,-1.789864 z"
style="fill:url(#radialGradient4011);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
<path
style="fill:url(#radialGradient4013);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 18.73833,21.286331 1.657281,-0.729204 0.06629,-2.209709 -1.723573,0.618718 z"
id="path3928"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="fill:url(#radialGradient4015);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 22.737903,31.318408 c 0,0 0,-5.104427 0,-7.159456 0,-2.055029 -2.342292,-3.601825 -2.342292,-3.601825 0,-0.927244 0.06629,-2.209709 0.06629,-2.209709 l 15.055864,4.034207 0,2.108783 c 0,0 -1.930193,-0.176776 -1.930193,1.502602 0,1.679379 0,7.51301 0,7.51301 z"
id="path3932"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscc" />
</g>
</g>
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path3966"
d="M 23.776465,21.927147 32.15231,24.26278"
style="fill:none;stroke:#0000ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
<g
id="g3960">
<path
inkscape:connector-curvature="0"
id="path3870"
d="m 42.02866,32.97569 c 0,0 -1.237437,-1.149049 -4.596194,-1.149049 -3.358758,0 -9.678525,1.723573 -11.136932,2.165515 -1.458408,0.441941 -6.805903,2.872621 -6.805903,2.872621 0,0 1.458408,1.016466 1.767767,1.325825 0.309359,0.309359 1.281631,1.325825 1.281631,1.325825 0,0 5.170718,1.37002 7.51301,1.37002 2.342291,0 7.73398,-0.751301 7.73398,-0.751301 0,0 3.756505,-4.375223 4.242641,-7.159456 z"
style="fill:url(#radialGradient4017);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
style="fill:url(#radialGradient4019);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 37.786019,40.135146 c 0,0 3.756505,-4.375223 4.242641,-7.159456 1.723573,3.270369 1.59099,3.18198 1.59099,3.18198 0,0 -3.049398,3.402952 -5.833631,3.977476 z"
id="path3874"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path3876"
d="m 45.829359,21.220039 c 0,4.065864 -3.800699,11.755651 -3.800699,11.755651 1.723573,3.270369 1.59099,3.18198 1.59099,3.18198 2.695845,-1.325825 7.557204,-8.529475 7.557204,-8.529475 0,0 -1.944544,-6.142991 -5.347495,-6.408156"
style="fill:url(#radialGradient4021);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
sodipodi:nodetypes="ccccc" />
<path
sodipodi:nodetypes="cccsccccsscc"
style="fill:url(#radialGradient4023);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 14.84375,33.46875 c 0.18566,-1.505743 3.84375,-4.625 3.84375,-4.625 L 20.34375,30.5 c 0,0 2.21875,-1.5 4.15625,-2.28125 C 26.4375,27.4375 30.53125,26.25 30.53125,26.25 l 0.9375,-4.4375 c 0,0 5.471217,-3.903672 14.360609,-0.592461 0,4.065864 -3.800699,11.755651 -3.800699,11.755651 0,0 -1.237437,-1.149049 -4.596194,-1.149049 -3.358758,0 -9.678525,1.723573 -11.136932,2.165515 -1.458408,0.441941 -6.805903,2.872621 -6.805903,2.872621 0,0 -3.770881,-3.083527 -4.645881,-3.396027"
id="path3878"
inkscape:connector-curvature="0" />
</g>
</g>
<path
inkscape:connector-curvature="0"
id="path3082"
d="m -98.8125,30.25 c 0,0 3.9375,-2.4375 9.5,-2.4375 5.5625,0 8.75,2.5625 15.8125,2.5625 7.0625,0 5.4375,-1.125 11.0625,-1.125 5.625,0 10.125001,3 10.125001,3"
style="fill:none;stroke:#afffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m -98.8125,30.25 c 0,0 3.9375,-2.4375 9.5,-2.4375 5.5625,0 8.75,2.5625 15.8125,2.5625 7.0625,0 5.4375,-1.125 11.0625,-1.125 5.625,0 10.125001,3 10.125001,3"
id="path3852"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m -55.356078,30.695806 c 0,0 1.811961,-1.281631 6.054602,-1.281631 4.24264,0 5.656854,1.502602 5.656854,1.502602"
id="path3858"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m -103.0625,28.4375 c 0,0 0.9375,-0.9375 3.375,-0.9375 2.4375,0 5.25,1 5.25,1"
id="path3862"
inkscape:connector-curvature="0" />
</g>
<path
style="fill:url(#radialGradient3964);stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1.0"
d="m 14.125,57 38.625,0 -13.125,-32.875 -24.25,0 -4.75,-4.75 -7.5,0 -1.875,4.875 z"
id="path3164"
inkscape:connector-curvature="0" />
<g
id="g5774"
transform="matrix(0.99136339,-0.13114354,0.13114354,0.99136339,-15.325656,-9.4612023)">
<path
d="m 34.604037,49.371727 c 0,1.000719 -0.811242,1.811961 -1.811961,1.811961 -1.000718,0 -1.811961,-0.811242 -1.811961,-1.811961 0,-1.000719 0.811243,-1.811961 1.811961,-1.811961 1.000719,0 1.811961,0.811242 1.811961,1.811961 z"
sodipodi:ry="1.8119612"
sodipodi:rx="1.8119612"
sodipodi:cy="49.371727"
sodipodi:cx="32.792076"
id="path4004"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4006"
d="M 30.756005,53.250092 30.49874,52.450731 36.391621,50.871738 36.160297,50.008422"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4008"
d="m 33.375,51.71875 2.385247,8.901862"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4010"
d="m 29.40625,60.125 c 1.8125,0.9375 4.631882,0.963181 6.59375,0.4375 1.961869,-0.525681 4.116517,-2.098648 4.78125,-3.25"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)" />
<path
inkscape:connector-curvature="0"
id="path5772"
d="m 34.125,61.03125 0,-1.34375 2.53125,-0.96875 L 37.5625,60 37.125,61.03125 35.34375,61.625 z"
style="fill:#000000;fill-opacity:1;stroke:none" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,524 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="256"
height="256"
id="svg2985"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Ship_Module.svg">
<defs
id="defs2987">
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0"
refX="0"
id="Arrow1Send"
style="overflow:visible">
<path
id="path4031"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Send"
orient="auto"
refY="0"
refX="0"
id="Arrow2Send"
style="overflow:visible">
<path
id="path4049"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-0.3,0,0,-0.3,0.69,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Sstart"
orient="auto"
refY="0"
refX="0"
id="Arrow2Sstart"
style="overflow:visible">
<path
id="path4046"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(0.3,0,0,0.3,-0.69,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow2Mstart"
style="overflow:visible">
<path
id="path4040"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(0.6,0.6)"
inkscape:connector-curvature="0" />
</marker>
<linearGradient
id="linearGradient3900">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3902" />
<stop
style="stop-color:#a0a0a0;stop-opacity:1;"
offset="1"
id="stop3904" />
</linearGradient>
<linearGradient
id="linearGradient3882">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3884" />
<stop
style="stop-color:#960000;stop-opacity:1;"
offset="1"
id="stop3886" />
</linearGradient>
<linearGradient
id="linearGradient3860">
<stop
style="stop-color:#1e76e3;stop-opacity:1;"
offset="0"
id="stop3862" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3864" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3860-6"
id="linearGradient3866-5"
x1="31.125395"
y1="61.410763"
x2="30.113636"
y2="12.160761"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3860-6">
<stop
style="stop-color:#5a9ff5;stop-opacity:1;"
offset="0"
id="stop3862-4" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3864-4" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3890"
cx="25.629292"
cy="38.444794"
fx="25.629292"
fy="38.444794"
r="11.769514"
gradientTransform="matrix(1.7159608,-0.59513916,0.29226939,0.84269877,-28.848719,13.387411)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3898"
cx="31.803391"
cy="31.659325"
fx="31.803391"
fy="31.659325"
r="3.417994"
gradientTransform="matrix(4.734087,-1.1798961,0.73145851,2.9348253,-139.28906,-25.817159)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3906"
cx="20.211554"
cy="12.140632"
fx="20.211554"
fy="12.140632"
r="15.992805"
gradientTransform="matrix(1.6937502,-0.50833021,0.26447657,0.88123273,-17.232683,18.826666)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3914"
cx="44.852757"
cy="22.63999"
fx="44.852757"
fy="22.63999"
r="5.0740972"
gradientTransform="matrix(1,0,0,1.5705123,0,-16.367411)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3926"
cx="18.050617"
cy="25.765184"
fx="18.050617"
fy="25.765184"
r="2.4997866"
gradientTransform="matrix(1.1875159,0.30002561,-0.66139805,2.6178455,13.656265,-48.87061)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3930"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1875159,0.30002561,-0.66139805,2.6178455,13.656265,-48.87061)"
cx="17.915045"
cy="24.185383"
fx="17.915045"
fy="24.185383"
r="2.4997866" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3936"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.980826,0.90111766,-0.59612552,2.6334762,-39.306292,-60.304205)"
cx="18.420965"
cy="23.089165"
fx="18.420965"
fy="23.089165"
r="2.4997866" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3946"
cx="16.274988"
cy="23.718588"
fx="16.274988"
fy="23.718588"
r="3.6819806"
gradientTransform="matrix(1.1622967,-0.42417542,0.71241125,1.9521011,-19.727075,-16.498215)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3081"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1622967,-0.42417542,0.71241125,1.9521011,-19.727075,-16.498215)"
cx="16.274988"
cy="23.718588"
fx="16.274988"
fy="23.718588"
r="3.6819806" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3083"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1875159,0.30002561,-0.66139805,2.6178455,13.656265,-48.87061)"
cx="18.050617"
cy="25.765184"
fx="18.050617"
fy="25.765184"
r="2.4997866" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3085"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1875159,0.30002561,-0.66139805,2.6178455,13.656265,-48.87061)"
cx="17.915045"
cy="24.185383"
fx="17.915045"
fy="24.185383"
r="2.4997866" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3087"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.980826,0.90111766,-0.59612552,2.6334762,-39.306292,-60.304205)"
cx="18.420965"
cy="23.089165"
fx="18.420965"
fy="23.089165"
r="2.4997866" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3089"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.7159608,-0.59513916,0.29226939,0.84269877,-28.848719,13.387411)"
cx="25.629292"
cy="38.444794"
fx="25.629292"
fy="38.444794"
r="11.769514" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3091"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(4.734087,-1.1798961,0.73145851,2.9348253,-139.28906,-25.817159)"
cx="31.803391"
cy="31.659325"
fx="31.803391"
fy="31.659325"
r="3.417994" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3093"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.5705123,0,-16.367411)"
cx="44.852757"
cy="22.63999"
fx="44.852757"
fy="22.63999"
r="5.0740972" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3095"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.6937502,-0.50833021,0.26447657,0.88123273,-17.232683,18.826666)"
cx="20.211554"
cy="12.140632"
fx="20.211554"
fy="12.140632"
r="15.992805" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4142136"
inkscape:cx="-38.366"
inkscape:cy="88.055386"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1366"
inkscape:window-height="722"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,192)">
<g
id="g3045"
transform="matrix(4.1291004,0,0,4.1291004,-0.58670633,-198.26865)">
<text
sodipodi:linespacing="125%"
id="text3992"
y="13.75"
x="3.25"
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
xml:space="preserve"><tspan
style="font-size:14px"
y="13.75"
x="3.25"
id="tspan3994"
sodipodi:role="line">FreeCAD</tspan></text>
<path
inkscape:connector-curvature="0"
id="path3856"
d="m 49.143922,41.195806 c 0,0 1.811961,-1.281631 6.054602,-1.281631 4.24264,0 5.656854,1.502602 5.656854,1.502602"
style="fill:none;stroke:#afffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path3860"
d="m 1.4375,38.9375 c 0,0 0.9375,-0.9375 3.375,-0.9375 2.4375001,0 5.25,1 5.25,1"
style="fill:none;stroke:#afffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path3864"
d="m 54.668194,39.958369 c 0,0 -3.623923,-1.679378 -10.208855,-1.679378 -6.584932,0 -10.606602,2.474873 -10.606602,2.474873"
style="fill:none;stroke:#afffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 54.668194,39.958369 c 0,0 -3.623923,-1.679378 -10.208855,-1.679378 -6.584932,0 -10.606602,2.474873 -10.606602,2.474873"
id="path3866"
inkscape:connector-curvature="0" />
<g
id="g3977">
<g
id="g3968">
<g
id="g3953">
<path
style="fill:url(#radialGradient3081);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 16.528621,30.942758 0.707107,-7.778175 c 0,0 0.795495,-1.767767 2.563262,-1.767767 1.767767,0 2.032932,1.06066 2.032932,1.06066 l 1.06066,8.220117 z"
id="path3938"
inkscape:connector-curvature="0" />
<g
id="g3948">
<path
sodipodi:nodetypes="ccsccccc"
inkscape:connector-curvature="0"
id="path3918"
d="m 18.73833,21.286331 1.657281,-0.729204 c 0,0 2.342292,1.546796 2.342292,3.601825 0,2.055029 0,7.159456 0,7.159456 l -3.987549,1.738087 0.05427,-7.748495 1.06066,-2.231805 c 0,0 -0.0221,-1.126952 -1.126951,-1.789864 z"
style="fill:url(#radialGradient3083);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
<path
style="fill:url(#radialGradient3085);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 18.73833,21.286331 1.657281,-0.729204 0.06629,-2.209709 -1.723573,0.618718 z"
id="path3928"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="fill:url(#radialGradient3087);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 22.737903,31.318408 c 0,0 0,-5.104427 0,-7.159456 0,-2.055029 -2.342292,-3.601825 -2.342292,-3.601825 0,-0.927244 0.06629,-2.209709 0.06629,-2.209709 l 15.055864,4.034207 0,2.108783 c 0,0 -1.930193,-0.176776 -1.930193,1.502602 0,1.679379 0,7.51301 0,7.51301 z"
id="path3932"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscc" />
</g>
</g>
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path3966"
d="M 23.776465,21.927147 32.15231,24.26278"
style="fill:none;stroke:#0000ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
<g
id="g3960">
<path
inkscape:connector-curvature="0"
id="path3870"
d="m 42.02866,32.97569 c 0,0 -1.237437,-1.149049 -4.596194,-1.149049 -3.358758,0 -9.678525,1.723573 -11.136932,2.165515 -1.458408,0.441941 -6.805903,2.872621 -6.805903,2.872621 0,0 1.458408,1.016466 1.767767,1.325825 0.309359,0.309359 1.281631,1.325825 1.281631,1.325825 0,0 5.170718,1.37002 7.51301,1.37002 2.342291,0 7.73398,-0.751301 7.73398,-0.751301 0,0 3.756505,-4.375223 4.242641,-7.159456 z"
style="fill:url(#radialGradient3089);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
style="fill:url(#radialGradient3091);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 37.786019,40.135146 c 0,0 3.756505,-4.375223 4.242641,-7.159456 1.723573,3.270369 1.59099,3.18198 1.59099,3.18198 0,0 -3.049398,3.402952 -5.833631,3.977476 z"
id="path3874"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path3876"
d="m 45.829359,21.220039 c 0,4.065864 -3.800699,11.755651 -3.800699,11.755651 1.723573,3.270369 1.59099,3.18198 1.59099,3.18198 2.695845,-1.325825 7.557204,-8.529475 7.557204,-8.529475 0,0 -1.944544,-6.142991 -5.347495,-6.408156"
style="fill:url(#radialGradient3093);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
sodipodi:nodetypes="ccccc" />
<path
sodipodi:nodetypes="cccsccccsscc"
style="fill:url(#radialGradient3095);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 14.84375,33.46875 c 0.18566,-1.505743 3.84375,-4.625 3.84375,-4.625 L 20.34375,30.5 c 0,0 2.21875,-1.5 4.15625,-2.28125 C 26.4375,27.4375 30.53125,26.25 30.53125,26.25 l 0.9375,-4.4375 c 0,0 5.471217,-3.903672 14.360609,-0.592461 0,4.065864 -3.800699,11.755651 -3.800699,11.755651 0,0 -1.237437,-1.149049 -4.596194,-1.149049 -3.358758,0 -9.678525,1.723573 -11.136932,2.165515 -1.458408,0.441941 -6.805903,2.872621 -6.805903,2.872621 0,0 -3.770881,-3.083527 -4.645881,-3.396027"
id="path3878"
inkscape:connector-curvature="0" />
</g>
</g>
<path
inkscape:connector-curvature="0"
id="path3082"
d="m 5.6875001,40.75 c 0,0 3.9375,-2.4375 9.4999999,-2.4375 5.5625,0 8.75,2.5625 15.8125,2.5625 7.0625,0 5.4375,-1.125 11.0625,-1.125 5.625,0 10.125001,3 10.125001,3"
style="fill:none;stroke:#afffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 5.6875001,40.75 c 0,0 3.9375,-2.4375 9.4999999,-2.4375 5.5625,0 8.75,2.5625 15.8125,2.5625 7.0625,0 5.4375,-1.125 11.0625,-1.125 5.625,0 10.125001,3 10.125001,3"
id="path3852"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 49.143922,41.195806 c 0,0 1.811961,-1.281631 6.054602,-1.281631 4.24264,0 5.656854,1.502602 5.656854,1.502602"
id="path3858"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 1.4375,38.9375 c 0,0 0.9375,-0.9375 3.375,-0.9375 2.4375001,0 5.25,1 5.25,1"
id="path3862"
inkscape:connector-curvature="0" />
<text
sodipodi:linespacing="125%"
id="text3996"
y="59.75"
x="11.375"
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
xml:space="preserve"><tspan
style="font-size:14px"
y="59.75"
x="11.375"
id="tspan3998"
sodipodi:role="line">Sh</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4000"
y="59.125"
x="42.75"
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
xml:space="preserve"><tspan
y="59.125"
x="42.75"
id="tspan4002"
sodipodi:role="line">p</tspan></text>
<g
transform="translate(0.53033009,0)"
id="g5774">
<path
sodipodi:type="arc"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path4004"
sodipodi:cx="32.792076"
sodipodi:cy="49.371727"
sodipodi:rx="1.8119612"
sodipodi:ry="1.8119612"
d="m 34.604037,49.371727 c 0,1.000719 -0.811242,1.811961 -1.811961,1.811961 -1.000718,0 -1.811961,-0.811242 -1.811961,-1.811961 0,-1.000719 0.811243,-1.811961 1.811961,-1.811961 1.000719,0 1.811961,0.811242 1.811961,1.811961 z" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="M 30.756005,53.250092 30.49874,52.450731 36.391621,50.871738 36.160297,50.008422"
id="path4006"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 33.375,51.71875 2.385247,8.901862"
id="path4008"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"
d="m 29.40625,60.125 c 1.8125,0.9375 4.631882,0.963181 6.59375,0.4375 1.961869,-0.525681 4.116517,-2.098648 4.78125,-3.25"
id="path4010"
inkscape:connector-curvature="0" />
<path
style="fill:#000000;fill-opacity:1;stroke:none"
d="m 34.125,61.03125 0,-1.34375 2.53125,-0.96875 L 37.5625,60 37.125,61.03125 35.34375,61.625 z"
id="path5772"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,427 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2985"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Ship_Module.svg">
<defs
id="defs2987">
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;">
<path
id="path4031"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Send"
style="overflow:visible;">
<path
id="path4049"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.3) rotate(180) translate(-2.3,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Sstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Sstart"
style="overflow:visible">
<path
id="path4046"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.3) translate(-2.3,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Mstart"
style="overflow:visible">
<path
id="path4040"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.6) translate(0,0)" />
</marker>
<linearGradient
id="linearGradient3900">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3902" />
<stop
style="stop-color:#a0a0a0;stop-opacity:1;"
offset="1"
id="stop3904" />
</linearGradient>
<linearGradient
id="linearGradient3882">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3884" />
<stop
style="stop-color:#960000;stop-opacity:1;"
offset="1"
id="stop3886" />
</linearGradient>
<linearGradient
id="linearGradient3860">
<stop
style="stop-color:#1e76e3;stop-opacity:1;"
offset="0"
id="stop3862" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3864" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3860-6"
id="linearGradient3866-5"
x1="31.125395"
y1="61.410763"
x2="30.113636"
y2="12.160761"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3860-6">
<stop
style="stop-color:#5a9ff5;stop-opacity:1;"
offset="0"
id="stop3862-4" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3864-4" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3890"
cx="25.629292"
cy="38.444794"
fx="25.629292"
fy="38.444794"
r="11.769514"
gradientTransform="matrix(1.7159608,-0.59513916,0.29226939,0.84269877,-28.848719,13.387411)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3898"
cx="31.803391"
cy="31.659325"
fx="31.803391"
fy="31.659325"
r="3.417994"
gradientTransform="matrix(4.734087,-1.1798961,0.73145851,2.9348253,-139.28906,-25.817159)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3906"
cx="20.211554"
cy="12.140632"
fx="20.211554"
fy="12.140632"
r="15.992805"
gradientTransform="matrix(1.6937502,-0.50833021,0.26447657,0.88123273,-17.232683,18.826666)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3914"
cx="44.852757"
cy="22.63999"
fx="44.852757"
fy="22.63999"
r="5.0740972"
gradientTransform="matrix(1,0,0,1.5705123,0,-16.367411)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3926"
cx="18.050617"
cy="25.765184"
fx="18.050617"
fy="25.765184"
r="2.4997866"
gradientTransform="matrix(1.1875159,0.30002561,-0.66139805,2.6178455,13.656265,-48.87061)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3930"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1875159,0.30002561,-0.66139805,2.6178455,13.656265,-48.87061)"
cx="17.915045"
cy="24.185383"
fx="17.915045"
fy="24.185383"
r="2.4997866" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3900"
id="radialGradient3936"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.980826,0.90111766,-0.59612552,2.6334762,-39.306292,-60.304205)"
cx="18.420965"
cy="23.089165"
fx="18.420965"
fy="23.089165"
r="2.4997866" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3946"
cx="16.274988"
cy="23.718588"
fx="16.274988"
fy="23.718588"
r="3.6819806"
gradientTransform="matrix(1.1622967,-0.42417542,0.71241125,1.9521011,-19.727075,-16.498215)"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4"
inkscape:cx="-6.1454977"
inkscape:cy="13.674344"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1366"
inkscape:window-height="722"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
x="3.25"
y="13.75"
id="text3992"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3994"
x="3.25"
y="13.75"
style="font-size:14px">FreeCAD</tspan></text>
<path
style="fill:none;stroke:#afffff;stroke-width:2.50000000000000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d="m 49.143922,41.195806 c 0,0 1.811961,-1.281631 6.054602,-1.281631 4.24264,0 5.656854,1.502602 5.656854,1.502602"
id="path3856"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#afffff;stroke-width:2.50000000000000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d="m 1.4375,38.9375 c 0,0 0.9375,-0.9375 3.375,-0.9375 2.4375001,0 5.25,1 5.25,1"
id="path3860"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#afffff;stroke-width:2.50000000000000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d="m 54.668194,39.958369 c 0,0 -3.623923,-1.679378 -10.208855,-1.679378 -6.584932,0 -10.606602,2.474873 -10.606602,2.474873"
id="path3864"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path3866"
d="m 54.668194,39.958369 c 0,0 -3.623923,-1.679378 -10.208855,-1.679378 -6.584932,0 -10.606602,2.474873 -10.606602,2.474873"
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g3977">
<g
id="g3968">
<g
id="g3953">
<path
inkscape:connector-curvature="0"
id="path3938"
d="m 16.528621,30.942758 0.707107,-7.778175 c 0,0 0.795495,-1.767767 2.563262,-1.767767 1.767767,0 2.032932,1.06066 2.032932,1.06066 l 1.06066,8.220117 z"
style="fill:url(#radialGradient3946);stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />
<g
id="g3948">
<path
style="fill:url(#radialGradient3926);stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
d="m 18.73833,21.286331 1.657281,-0.729204 c 0,0 2.342292,1.546796 2.342292,3.601825 0,2.055029 0,7.159456 0,7.159456 l -3.987549,1.738087 0.05427,-7.748495 1.06066,-2.231805 c 0,0 -0.0221,-1.126952 -1.126951,-1.789864 z"
id="path3918"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsccccc" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path3928"
d="m 18.73833,21.286331 1.657281,-0.729204 0.06629,-2.209709 -1.723573,0.618718 z"
style="fill:url(#radialGradient3930);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
<path
sodipodi:nodetypes="cscc"
inkscape:connector-curvature="0"
id="path3932"
d="m 22.737903,31.318408 c 0,0 0,-5.104427 0,-7.159456 0,-2.055029 -2.342292,-3.601825 -2.342292,-3.601825 0,-0.927244 0.06629,-2.209709 0.06629,-2.209709 l 15.055864,4.034207 0,2.108783 c 0,0 -1.930193,-0.176776 -1.930193,1.502602 0,1.679379 0,7.51301 0,7.51301 z"
style="fill:url(#radialGradient3936);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
</g>
</g>
<path
style="fill:none;stroke:#0000ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 23.776465,21.927147 32.15231,24.26278"
id="path3966"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
<g
id="g3960">
<path
style="fill:url(#radialGradient3890);stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
d="m 42.02866,32.97569 c 0,0 -1.237437,-1.149049 -4.596194,-1.149049 -3.358758,0 -9.678525,1.723573 -11.136932,2.165515 -1.458408,0.441941 -6.805903,2.872621 -6.805903,2.872621 0,0 1.458408,1.016466 1.767767,1.325825 0.309359,0.309359 1.281631,1.325825 1.281631,1.325825 0,0 5.170718,1.37002 7.51301,1.37002 2.342291,0 7.73398,-0.751301 7.73398,-0.751301 0,0 3.756505,-4.375223 4.242641,-7.159456 z"
id="path3870"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path3874"
d="m 37.786019,40.135146 c 0,0 3.756505,-4.375223 4.242641,-7.159456 1.723573,3.270369 1.59099,3.18198 1.59099,3.18198 0,0 -3.049398,3.402952 -5.833631,3.977476 z"
style="fill:url(#radialGradient3898);stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="ccccc"
style="fill:url(#radialGradient3914);stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
d="m 45.829359,21.220039 c 0,4.065864 -3.800699,11.755651 -3.800699,11.755651 1.723573,3.270369 1.59099,3.18198 1.59099,3.18198 2.695845,-1.325825 7.557204,-8.529475 7.557204,-8.529475 0,0 -1.944544,-6.142991 -5.347495,-6.408156"
id="path3876"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path3878"
d="m 14.84375,33.46875 c 0.18566,-1.505743 3.84375,-4.625 3.84375,-4.625 L 20.34375,30.5 c 0,0 2.21875,-1.5 4.15625,-2.28125 C 26.4375,27.4375 30.53125,26.25 30.53125,26.25 l 0.9375,-4.4375 c 0,0 5.471217,-3.903672 14.360609,-0.592461 0,4.065864 -3.800699,11.755651 -3.800699,11.755651 0,0 -1.237437,-1.149049 -4.596194,-1.149049 -3.358758,0 -9.678525,1.723573 -11.136932,2.165515 -1.458408,0.441941 -6.805903,2.872621 -6.805903,2.872621 0,0 -3.770881,-3.083527 -4.645881,-3.396027"
style="fill:url(#radialGradient3906);stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
sodipodi:nodetypes="cccsccccsscc" />
</g>
</g>
<path
style="fill:none;stroke:#afffff;stroke-width:2.50000000000000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d="m 5.6875001,40.75 c 0,0 3.9375,-2.4375 9.4999999,-2.4375 5.5625,0 8.75,2.5625 15.8125,2.5625 7.0625,0 5.4375,-1.125 11.0625,-1.125 5.625,0 10.125001,3 10.125001,3"
id="path3082"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path3852"
d="m 5.6875001,40.75 c 0,0 3.9375,-2.4375 9.4999999,-2.4375 5.5625,0 8.75,2.5625 15.8125,2.5625 7.0625,0 5.4375,-1.125 11.0625,-1.125 5.625,0 10.125001,3 10.125001,3"
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path3858"
d="m 49.143922,41.195806 c 0,0 1.811961,-1.281631 6.054602,-1.281631 4.24264,0 5.656854,1.502602 5.656854,1.502602"
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path3862"
d="m 1.4375,38.9375 c 0,0 0.9375,-0.9375 3.375,-0.9375 2.4375001,0 5.25,1 5.25,1"
style="fill:none;stroke:#0000ff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
x="11.375"
y="59.75"
id="text3996"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3998"
x="11.375"
y="59.75"
style="font-size:14px">Sh</tspan></text>
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
x="42.75"
y="59.125"
id="text4000"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4002"
x="42.75"
y="59.125">p</tspan></text>
<g
id="g5774"
transform="translate(0.53033009,0)">
<path
d="m 34.604037,49.371727 c 0,1.000719 -0.811242,1.811961 -1.811961,1.811961 -1.000718,0 -1.811961,-0.811242 -1.811961,-1.811961 0,-1.000719 0.811243,-1.811961 1.811961,-1.811961 1.000719,0 1.811961,0.811242 1.811961,1.811961 z"
sodipodi:ry="1.8119612"
sodipodi:rx="1.8119612"
sodipodi:cy="49.371727"
sodipodi:cx="32.792076"
id="path4004"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4006"
d="M 30.756005,53.250092 30.49874,52.450731 36.391621,50.871738 36.160297,50.008422"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4008"
d="m 33.375,51.71875 2.385247,8.901862"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4010"
d="m 29.40625,60.125 c 1.8125,0.9375 4.631882,0.963181 6.59375,0.4375 1.961869,-0.525681 4.116517,-2.098648 4.78125,-3.25"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)" />
<path
inkscape:connector-curvature="0"
id="path5772"
d="m 34.125,61.03125 0,-1.34375 2.53125,-0.96875 L 37.5625,60 37.125,61.03125 35.34375,61.625 z"
style="fill:#000000;fill-opacity:1;stroke:none" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -0,0 +1,399 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2985"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Ship_Load.svg">
<defs
id="defs2987">
<linearGradient
id="linearGradient3937">
<stop
style="stop-color:#be7328;stop-opacity:1;"
offset="0"
id="stop3939" />
<stop
style="stop-color:#dc962d;stop-opacity:1;"
offset="1"
id="stop3941" />
</linearGradient>
<linearGradient
id="linearGradient3929">
<stop
id="stop3931"
offset="0"
style="stop-color:#c88c3c;stop-opacity:1;" />
<stop
id="stop3933"
offset="1"
style="stop-color:#ffff96;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3893">
<stop
style="stop-color:#505050;stop-opacity:1;"
offset="0"
id="stop3895" />
<stop
style="stop-color:#aaaaaa;stop-opacity:1;"
offset="1"
id="stop3897" />
</linearGradient>
<linearGradient
id="linearGradient3873">
<stop
style="stop-color:#f0be6e;stop-opacity:1;"
offset="0"
id="stop3875" />
<stop
style="stop-color:#c88228;stop-opacity:1;"
offset="1"
id="stop3877" />
</linearGradient>
<linearGradient
id="linearGradient3863">
<stop
id="stop3865"
offset="0"
style="stop-color:#6e4b18;stop-opacity:1;" />
<stop
id="stop3867"
offset="1"
style="stop-color:#c88228;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3979">
<stop
id="stop3981"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3983"
offset="1"
style="stop-color:#ff9600;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3971">
<stop
id="stop3973"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3975"
offset="1"
style="stop-color:#be7300;stop-opacity:1;" />
</linearGradient>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;">
<path
id="path4031"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Send"
style="overflow:visible;">
<path
id="path4049"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.3) rotate(180) translate(-2.3,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Sstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Sstart"
style="overflow:visible">
<path
id="path4046"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.3) translate(-2.3,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Mstart"
style="overflow:visible">
<path
id="path4040"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.6) translate(0,0)" />
</marker>
<linearGradient
id="linearGradient3900">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3902" />
<stop
style="stop-color:#a0a0a0;stop-opacity:1;"
offset="1"
id="stop3904" />
</linearGradient>
<linearGradient
id="linearGradient3882">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3884" />
<stop
style="stop-color:#960000;stop-opacity:1;"
offset="1"
id="stop3886" />
</linearGradient>
<linearGradient
id="linearGradient3860">
<stop
style="stop-color:#1e76e3;stop-opacity:1;"
offset="0"
id="stop3862" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3864" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3860-6"
id="linearGradient3866-5"
x1="31.125395"
y1="61.410763"
x2="30.113636"
y2="12.160761"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3860-6">
<stop
style="stop-color:#5a9ff5;stop-opacity:1;"
offset="0"
id="stop3862-4" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3864-4" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient3871"
gradientUnits="userSpaceOnUse"
x1="38.907837"
y1="51.470051"
x2="45.302406"
y2="54.091148" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3863"
id="linearGradient3891"
gradientUnits="userSpaceOnUse"
x1="51.657837"
y1="34.470051"
x2="45.427406"
y2="32.216148" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3893"
id="linearGradient3899"
gradientUnits="userSpaceOnUse"
x1="51.657837"
y1="34.470051"
x2="45.427406"
y2="32.216148" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3882"
id="radialGradient3903"
cx="53.748837"
cy="4.9173141"
fx="53.748837"
fy="4.9173141"
r="3.2874005"
gradientTransform="matrix(2.3303929,-1.4921636,1.0936999,1.7080907,-77.643882,78.644487)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3929"
id="radialGradient3927"
cx="15.125"
cy="48.035076"
fx="15.125"
fy="48.035076"
r="18.875"
gradientTransform="matrix(2.7636523,-0.71644256,0.733044,2.8276918,-61.887066,-71.992203)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3937"
id="radialGradient3943"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.40097726,-0.37931652,0.11734116,0.12404187,14.422507,4.6205505)"
cx="-14.308363"
cy="14.910047"
fx="-14.308363"
fy="14.910047"
r="18.875" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3929"
id="radialGradient3949"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.7636523,-0.71644256,0.733044,2.8276918,-61.887066,-71.992203)"
cx="15.125"
cy="48.035076"
fx="15.125"
fy="48.035076"
r="18.875" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3937"
id="radialGradient3951"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.40097726,-0.37931652,0.11734116,0.12404187,14.422507,4.6205505)"
cx="-14.308363"
cy="14.910047"
fx="-14.308363"
fy="14.910047"
r="18.875" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="43.350917"
inkscape:cy="32.886977"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1366"
inkscape:window-height="722"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3945">
<path
sodipodi:nodetypes="csccscscsc"
inkscape:connector-curvature="0"
id="path3919"
d="m 15.125,55.375 c 0,0 -7.75,-4.125 -7.75,-28.5 0,-9.375 2.125,-12.5 2.125,-12.5 L 15.375,8 c 0,0 4.125,-0.625 10.75,-0.625 6.625,0 15.625,1.25 15.625,1.25 0,0 -1.5,8.75 -1.5,18.625 0,9.875 3.875,21.125 3.875,21.125 0,0 -7.375,-0.25 -14.875,1.75 -7.5,2 -14.125,5.25 -14.125,5.25 z"
style="fill:url(#radialGradient3949);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
style="fill:url(#radialGradient3951);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="M 16.875,16.9375 C 14.5625,9.5625 9.5,14.375 9.5,14.375 L 15.375,8 c 0,0 3.3125,-1.375 1.5,8.9375"
id="path3935"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
<g
id="g3961"
transform="translate(1.25,0.5)"
style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none">
<path
sodipodi:nodetypes="ccssccsc"
inkscape:connector-curvature="0"
id="path3953"
d="m 17.5,14.5 0.375,17.125 c 0,0 1.75,11.25 5.875,10.875 4.125,-0.375 -0.625,-3.25 3,-3.125 3.625,0.125 5.375,6.5 10.375,6.875 m 0,0 C 36.125,42 35.465045,38.810263 34.625,33.875 33.625,28 32.5,11.75 32.5,11.75"
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
sodipodi:nodetypes="csc"
inkscape:connector-curvature="0"
id="path3957"
d="m 19.625,14.125 c 0,0 0.370838,11.000136 0.5,14.875 0.125,3.75 7.437825,10.194757 15.437825,10.194757"
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
sodipodi:nodetypes="csc"
inkscape:connector-curvature="0"
id="path3959"
d="m 21.743534,13.618642 c 0,0 0.884343,12.431507 1.06112,14.906381 0.176776,2.474873 2.828427,6.010407 11.932427,6.010407"
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
<g
id="g3910">
<g
id="g3881">
<path
sodipodi:nodetypes="cscscsc"
inkscape:connector-curvature="0"
id="path3869"
d="m 39.125,51.4375 c 0,0 0.546875,-1.15625 1.203125,-0.78125 0.65625,0.375 0.546875,1.9375 0.546875,1.9375 0,0 0.625,-1.328125 1.5625,-0.921875 0.9375,0.40625 0.640625,1.828125 0.640625,1.828125 0,0 0.578125,-1.71875 1.453125,-1.34375 0.875,0.375 0.84375,1.28125 0.84375,1.28125 l -3.987156,4.839354 -1.988738,-0.574524 z"
style="fill:url(#linearGradient3871);fill-opacity:1;stroke:#000000;stroke-width:0.10000000000000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.10000000000000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 41.387844,58.276854 -1.988738,-0.574524 0.353553,2.253903 z"
id="path3879"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
<g
id="g3905">
<path
style="fill:url(#linearGradient3891);fill-opacity:1;stroke:#000000;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 39.125,51.4375 c 0,0 0.546875,-1.15625 1.203125,-0.78125 0.65625,0.375 0.546875,1.9375 0.546875,1.9375 0,0 0.625,-1.328125 1.5625,-0.921875 0.9375,0.40625 0.640625,1.828125 0.640625,1.828125 0,0 0.578125,-1.71875 1.453125,-1.34375 0.875,0.375 0.84375,1.28125 0.84375,1.28125 l 12.1875,-37.375 c 0,0 -1.53125,-0.90625 -2.6875,-1.375 -1.15625,-0.46875 -3.25,-0.75 -3.25,-0.75 z"
id="path3061"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscscsccscc" />
<path
sodipodi:nodetypes="csccscc"
inkscape:connector-curvature="0"
id="path3885"
d="m 57.5625,16.0625 c 0,0 -1.53125,-0.90625 -2.6875,-1.375 -1.15625,-0.46875 -3.25,-0.75 -3.25,-0.75 l 0.394091,-1.162722 c 0,0 2.244178,0.26484 3.322303,0.73359 1.078125,0.46875 2.565641,1.368987 2.565641,1.368987 z"
style="fill:url(#linearGradient3899);fill-opacity:1;stroke:#000000;stroke-width:0.10000000000000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
style="fill:url(#radialGradient3903);fill-opacity:1;stroke:#000000;stroke-width:0.10000000000000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 52.019091,12.774778 c 0,0 2.244178,0.26484 3.322303,0.73359 1.078125,0.46875 2.565641,1.368987 2.565641,1.368987 l 0.561857,-1.568072 c 0,0 -0.665164,-1.448399 -2.342291,-2.099224 -1.480505,-0.574524 -3.469243,-0.132582 -3.469243,-0.132582 z"
id="path3901"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csccscc" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,4 +1,5 @@
/*
/***************************************************************************
* *
* Copyright (c) 2011, 2012 *
* Jose Luis Cercos Pita <jlcercos@gmail.com> *
* *
@@ -17,43 +18,8 @@
* License along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
* USA *
*/
/** Get matrix column.
* @param A Linear system matrix.
* @param v Column vector (output).
* @param col Column index.
* @param n Linear system dimension.
*/
__kernel void column(__global float* A,
__global float* v,
unsigned int col,
unsigned int n)
{
// find position in global arrays
unsigned int i = get_global_id(0);
if(i >= n)
return;
v[i] = A[i + col*n];
}
/** Performs matrix column product by a constant.
* @param A Linear system matrix.
* @param c Constant.
* @param col Column index.
* @param n Linear system dimension.
*/
__kernel void prod_c_column(__global float* A,
float c,
unsigned int col,
unsigned int n)
{
// find position in global arrays
unsigned int i = get_global_id(0);
if(i >= n)
return;
A[i + col*n] *= c;
}
* *
***************************************************************************/
/** Compute residuals of the solution stimator for a linear system.
* @param A Linear system matrix.

View File

@@ -1,185 +1,207 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
import os
# Qt library
from PyQt4 import QtGui,QtCore
# FreeCAD modules
import FreeCAD,FreeCADGui
from PySide import QtGui, QtCore
import FreeCAD
import FreeCADGui
from FreeCAD import Base
import Image, ImageGui
# FreeCADShip modules
from shipUtils import Paths
header = """ #################################################################
##### #### ### #### ##### # # ### ####
# # # # # # # # # # # #
# ## #### #### # # # # # # # # # # #
#### # # # # # # # ##### # # ## ## ##### # ####
# # #### #### # # # # # # # # # #
# # # # # # # # # # # # # #
# # #### #### ### # # #### ##### # # ### #
##### #### ### #### ##### # # ### ####
# # # # # # # # # # # #
# ## #### #### # # # # # # # # # # #
#### # # # # # # # ##### # # ## ## ##### # ####
# # #### #### # # # # # # # # # #
# # # # # # # # # # # # # #
# # #### #### ### # # #### ##### # # ### #
#################################################################
"""
class Plot(object):
def __init__(self, x, y, disp, xcb, ship):
""" Constructor. performs plot and show it.
@param x X coordinates.
@param y Transversal areas.
@param disp Ship displacement.
@param xcb Bouyancy center length.
@param ship Active ship instance.
"""
# Try to plot
self.plot(x,y,disp,xcb,ship)
# Save data
if self.createDirectory():
return
if self.saveData(x,y,ship):
return
def __init__(self, x, y, disp, xcb, ship):
""" Constructor. performs the plot and shows it.
@param x X coordinates.
@param y Transversal computed areas.
@param disp Ship displacement.
@param xcb Bouyancy center length.
@param ship Active ship instance.
"""
self.plot(x, y, disp, xcb, ship)
if self.createDirectory():
return
if self.saveData(x, y, ship):
return
def plot(self, x, y, disp, xcb, ship):
""" Perform areas curve plot.
@param x X coordinates.
@param y Transversal areas.
@param disp Ship displacement.
@param xcb Bouyancy center length.
@param ship Active ship instance.
@return True if error happens.
"""
# Create plot
try:
import Plot
plt = Plot.figure('Areas curve')
except ImportError:
msg = QtGui.QApplication.translate("ship_console", "Plot module is disabled, can't perform plot",
None,QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintWarning(msg + '\n')
return True
# Plot areas curve
areas = Plot.plot(x,y,r'Transversal areas')
areas.line.set_linestyle('-')
areas.line.set_linewidth(2.0)
areas.line.set_color((0.0, 0.0, 0.0))
# Get perpendiculars data
Lpp = ship.Length
FPx = 0.5*Lpp
APx = -0.5*Lpp
maxArea = max(y)
# Plot perpendiculars
FP = Plot.plot([FPx,FPx], [0.0,maxArea])
FP.line.set_linestyle('-')
FP.line.set_linewidth(1.0)
FP.line.set_color((0.0, 0.0, 0.0))
AP = Plot.plot([APx,APx], [0.0,maxArea])
AP.line.set_linestyle('-')
AP.line.set_linewidth(1.0)
AP.line.set_color((0.0, 0.0, 0.0))
# Add annotations for prependiculars
ax = Plot.axes()
ax.annotate('AP', xy=(APx+0.01*Lpp, 0.01*maxArea), size=15)
ax.annotate('AP', xy=(APx+0.01*Lpp, 0.95*maxArea), size=15)
ax.annotate('FP', xy=(FPx+0.01*Lpp, 0.01*maxArea), size=15)
ax.annotate('FP', xy=(FPx+0.01*Lpp, 0.95*maxArea), size=15)
# Add some additional data
addInfo = r"""$XCB = %g \; \mathrm{m}$
$Area_{max} = %g \; \mathrm{m}^2$
$\bigtriangleup = %g \; \mathrm{tons}$""" % (xcb,maxArea,disp)
ax.text(0.0, 0.01*maxArea, addInfo,
verticalalignment='bottom',horizontalalignment='center', fontsize=20)
# Write axes titles
Plot.xlabel(r'$x \; \mathrm{m}$')
Plot.ylabel(r'$Area \; \mathrm{m}^2$')
ax.xaxis.label.set_fontsize(20)
ax.yaxis.label.set_fontsize(20)
# Show grid
Plot.grid(True)
# End
plt.update()
return False
def plot(self, x, y, disp, xcb, ship):
""" Perform the areas curve plot.
@param x X coordinates.
@param y Transversal areas.
@param disp Ship displacement.
@param xcb Bouyancy center length.
@param ship Active ship instance.
@return True if error happens.
"""
try:
import Plot
plt = Plot.figure('Areas curve')
except ImportError:
msg = QtGui.QApplication.translate(
"ship_console",
"Plot module is disabled, so I cannot perform the plot",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintWarning(msg + '\n')
return True
# Plot areas curve
areas = Plot.plot(x, y, 'Transversal areas')
areas.line.set_linestyle('-')
areas.line.set_linewidth(2.0)
areas.line.set_color((0.0, 0.0, 0.0))
# Get perpendiculars data
Lpp = ship.Length
FPx = 0.5 * Lpp
APx = -0.5 * Lpp
maxArea = max(y)
# Plot perpendiculars
FP = Plot.plot([FPx, FPx], [0.0, maxArea])
FP.line.set_linestyle('-')
FP.line.set_linewidth(1.0)
FP.line.set_color((0.0, 0.0, 0.0))
AP = Plot.plot([APx, APx], [0.0, maxArea])
AP.line.set_linestyle('-')
AP.line.set_linewidth(1.0)
AP.line.set_color((0.0, 0.0, 0.0))
# Add annotations for prependiculars
ax = Plot.axes()
ax.annotate('AP', xy=(APx + 0.01 * Lpp, 0.01 * maxArea), size=15)
ax.annotate('AP', xy=(APx + 0.01 * Lpp, 0.95 * maxArea), size=15)
ax.annotate('FP', xy=(FPx + 0.01 * Lpp, 0.01 * maxArea), size=15)
ax.annotate('FP', xy=(FPx + 0.01 * Lpp, 0.95 * maxArea), size=15)
# Add some additional data
addInfo = ("$XCB = {0} \\; \\mathrm{{m}}$\n"
"$Area_{{max}} = {1} \\; \\mathrm{{m}}^2$\n"
"$\\bigtriangleup = {2} \\; \\mathrm{{tons}}$".format(
xcb,
maxArea,
disp))
ax.text(0.0,
0.01 * maxArea,
addInfo,
verticalalignment='bottom',
horizontalalignment='center',
fontsize=20)
# Write axes titles
Plot.xlabel(r'$x \; \mathrm{m}$')
Plot.ylabel(r'$Area \; \mathrm{m}^2$')
ax.xaxis.label.set_fontsize(20)
ax.yaxis.label.set_fontsize(20)
# Show grid
Plot.grid(True)
# End
plt.update()
return False
def createDirectory(self):
""" Create needed folder to write data.
@return True if error happens.
"""
self.path = FreeCAD.ConfigGet("UserAppData") + "ShipOutput/"
if not os.path.exists(self.path):
os.makedirs(self.path)
if not os.path.exists(self.path):
msg = QtGui.QApplication.translate("ship_console", "Can't create folder",
None,QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintError(msg + ':\n\t' + "\'"+ self.path + "\'\n")
return True
return False
def saveData(self,x,y,ship):
""" Write data file.
@param x X coordinates.
@param y Transversal areas.
@param ship Active ship instance.
@return True if error happens.
"""
# Open the file
filename = self.path + 'areas.dat'
try:
Output = open(filename, "w")
except IOError:
msg = QtGui.QApplication.translate("ship_console", "Can't write to file",
None,QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintError(msg + ':\n\t' + "\'"+ filename + "\'\n")
return True
# Print header
Output.write(header)
Output.write(" #\n")
Output.write(" # File automatically exported by FreeCAD-Ship\n")
Output.write(" # This file contains transversal areas data, filled with following columns:\n")
Output.write(" # 1: X coordiante [m]\n")
Output.write(" # 2: Transversal area [m2]\n")
Output.write(" # 3: X FP coordinate [m]\n")
Output.write(" # 4: Y FP coordinate (bounds in order to draw it)\n")
Output.write(" # 3: X AP coordinate [m]\n")
Output.write(" # 4: Y AP coordinate (bounds in order to draw it)\n")
Output.write(" #\n")
Output.write(" #################################################################\n")
# Get perpendiculars data
Lpp = ship.Length
FPx = 0.5*Lpp
APx = -0.5*Lpp
maxArea = max(y)
# Print data
string = "%f %f %f %f %f %f\n" % (x[0], y[0], FPx, 0.0, APx, 0.0)
Output.write(string)
for i in range(1, len(x)):
string = "%f %f %f %f %f %f\n" % (x[i], y[i], FPx, maxArea, APx, maxArea)
Output.write(string)
# Close file
Output.close()
self.dataFile = filename
msg = QtGui.QApplication.translate("ship_console", "Data saved",
None,QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg + ':\n\t' + "\'"+ self.dataFile + "\'\n")
return False
def createDirectory(self):
""" Create the needed folder to write the output data.
@return True if error happens.
"""
self.path = FreeCAD.ConfigGet("UserAppData") + "ShipOutput/"
if not os.path.exists(self.path):
os.makedirs(self.path)
if not os.path.exists(self.path):
msg = QtGui.QApplication.translate(
"ship_console",
"Failure creating the folder",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintError(msg + ":\n\t'" + self.path + "'\n")
return True
return False
def saveData(self, x, y, ship):
""" Write the output data file.
@param x X coordinates.
@param y Transversal areas.
@param ship Active ship instance.
@return True if error happens.
"""
filename = self.path + 'areas.dat'
try:
Output = open(filename, "w")
except IOError:
msg = QtGui.QApplication.translate(
"ship_console",
"Failure writing to file",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintError(msg + ":\n\t'" + filename + "'\n")
return True
# Print the header
Output.write(header)
Output.write(" #\n")
Output.write(" # File automatically exported by FreeCAD-Ship\n")
Output.write(" # This file contains transversal areas data, filled"
" with following columns:\n")
Output.write(" # 1: X coordiante [m]\n")
Output.write(" # 2: Transversal area [m2]\n")
Output.write(" # 3: X FP coordinate [m]\n")
Output.write(" # 4: Y FP coordinate (bounds in order to draw it)\n")
Output.write(" # 3: X AP coordinate [m]\n")
Output.write(" # 4: Y AP coordinate (bounds in order to draw it)\n")
Output.write(" #\n")
Output.write(" ######################################################"
"###########\n")
# Get perpendiculars data
Lpp = ship.Length
FPx = 0.5 * Lpp
APx = -0.5 * Lpp
maxArea = max(y)
# Print the data
string = "{0} {1} {2} {3} {4} {5}\n".format(x[0],
y[0],
FPx,
0.0,
APx,
0.0)
Output.write(string)
for i in range(1, len(x)):
string = "{0} {1} {2} {3} {4} {5}\n".format(x[i],
y[i],
FPx,
maxArea,
APx,
maxArea)
Output.write(string)
Output.close()
self.dataFile = filename
msg = QtGui.QApplication.translate("ship_console",
"Data saved",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg + ":\n\t'" + self.dataFile + "'\n")
return False

View File

@@ -1,78 +1,72 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD,FreeCADGui
import FreeCAD
import FreeCADGui
from FreeCAD import Base
import Part
# FreeCADShip modules
import Units
from shipUtils import Paths
class Preview(object):
def __init__(self):
""" Constructor.
"""
self.reinit()
def __init__(self):
""" Constructor. """
self.reinit()
def reinit(self):
""" Reinitializate drawer.
"""
self.obj = None
self.clean()
def reinit(self):
""" Reinitializate the drawer. """
self.obj = None
self.clean()
def update(self, draft, trim, ship):
""" Update free surface 3D view
@param traft Draft.
@param trim Trim in degrees.
"""
# Destroy old object if exist
self.clean()
# Set free surface bounds
bbox = ship.Shape.BoundBox
L = 1.5 * bbox.XLength
B = 3.0 * bbox.YLength
# Create plane
x = - 0.5 * L
y = - 0.5 * B
point = Base.Vector(x,y,0.0)
plane = Part.makePlane(L,B, point, Base.Vector(0,0,1))
# Set position
plane.rotate(Base.Vector(0,0,0), Base.Vector(0,1,0), trim)
plane.translate(Base.Vector(0,0,draft))
# Create the FreeCAD object
Part.show(plane)
objs = FreeCAD.ActiveDocument.Objects
self.obj = objs[len(objs)-1]
self.obj.Label = 'FreeSurface'
# Set properties of object
guiObj = FreeCADGui.ActiveDocument.getObject(self.obj.Name)
guiObj.ShapeColor = (0.4,0.8,0.85)
guiObj.Transparency = 50
def update(self, draft, trim, ship):
""" Update the free surface 3D view
@param draft Draft.
@param trim Trim in degrees.
"""
self.clean()
# Set free surface bounds
bbox = ship.Shape.BoundBox
L = 1.5 * bbox.XLength
B = 3.0 * bbox.YLength
# Create the plane
x = -0.5 * L
y = -0.5 * B
point = Base.Vector(x, y, 0.0)
plane = Part.makePlane(L, B, point, Base.Vector(0, 0, 1))
plane.rotate(Base.Vector(0, 0, 0), Base.Vector(0, 1, 0), trim)
plane.translate(Base.Vector(0, 0, draft * Units.Metre.Value))
Part.show(plane)
objs = FreeCAD.ActiveDocument.Objects
self.obj = objs[len(objs) - 1]
self.obj.Label = 'FreeSurface'
guiObj = FreeCADGui.ActiveDocument.getObject(self.obj.Name)
guiObj.ShapeColor = (0.4, 0.8, 0.85)
guiObj.Transparency = 50
def clean(self):
""" Erase all annotations from screen.
"""
if not self.obj:
return
FreeCAD.ActiveDocument.removeObject(self.obj.Name)
self.obj=None
def clean(self):
""" Erase all the annotations from the 3D view. """
if not self.obj:
return
FreeCAD.ActiveDocument.removeObject(self.obj.Name)
self.obj = None

View File

@@ -1,245 +1,322 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
import math
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Qt library
from PyQt4 import QtGui,QtCore
# Module
import Preview, PlotAux
import Units
from PySide import QtGui, QtCore
import Preview
import PlotAux
import Instance
from shipUtils import Paths
from shipHydrostatics import Tools as Hydrostatics
class TaskPanel:
def __init__(self):
self.ui = Paths.modulePath() + "/shipAreasCurve/TaskPanel.ui"
self.preview = Preview.Preview()
self.ship = None
def __init__(self):
self.ui = Paths.modulePath() + "/shipAreasCurve/TaskPanel.ui"
self.preview = Preview.Preview()
self.ship = None
def accept(self):
if not self.ship:
return False
self.save()
# Plot data
data = Hydrostatics.displacement(self.ship,self.form.draft.value(),0.0,self.form.trim.value())
disp = data[0]
xcb = data[1].x
data = Hydrostatics.areas(self.ship,self.form.draft.value(),0.0,self.form.trim.value())
x = []
y = []
for i in range(0,len(data)):
x.append(data[i][0])
y.append(data[i][1])
PlotAux.Plot(x,y,disp,xcb, self.ship)
self.preview.clean()
return True
def accept(self):
if not self.ship:
return False
self.save()
# Plot data
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.draft = self.widget(QtGui.QDoubleSpinBox, "Draft")
form.trim = self.widget(QtGui.QDoubleSpinBox, "Trim")
data = Hydrostatics.displacement(self.ship,
form.draft.value(),
0.0,
form.trim.value())
disp = data[0]
xcb = data[1].x
data = Hydrostatics.areas(self.ship,
form.draft.value(),
0.0,
form.trim.value())
x = []
y = []
for i in range(0, len(data)):
x.append(data[i][0])
y.append(data[i][1])
PlotAux.Plot(x, y, disp, xcb, self.ship)
self.preview.clean()
return True
def reject(self):
self.preview.clean()
return True
def reject(self):
self.preview.clean()
return True
def clicked(self, index):
pass
def clicked(self, index):
pass
def open(self):
pass
def open(self):
pass
def needsFullSpace(self):
return True
def needsFullSpace(self):
return True
def isAllowedAlterSelection(self):
return False
def isAllowedAlterSelection(self):
return False
def isAllowedAlterView(self):
return True
def isAllowedAlterView(self):
return True
def isAllowedAlterDocument(self):
return False
def isAllowedAlterDocument(self):
return False
def helpRequested(self):
pass
def helpRequested(self):
pass
def setupUi(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.draft = form.findChild(QtGui.QDoubleSpinBox, "Draft")
form.trim = form.findChild(QtGui.QDoubleSpinBox, "Trim")
form.output = form.findChild(QtGui.QTextEdit, "OutputData")
form.doc = QtGui.QTextDocument(form.output)
self.form = form
# Initial values
if self.initValues():
return True
self.retranslateUi()
# Connect Signals and Slots
QtCore.QObject.connect(form.draft, QtCore.SIGNAL("valueChanged(double)"), self.onData)
QtCore.QObject.connect(form.trim, QtCore.SIGNAL("valueChanged(double)"), self.onData)
def setupUi(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.draft = self.widget(QtGui.QDoubleSpinBox, "Draft")
form.trim = self.widget(QtGui.QDoubleSpinBox, "Trim")
form.output = self.widget(QtGui.QTextEdit, "OutputData")
form.doc = QtGui.QTextDocument(form.output)
self.form = form
if self.initValues():
return True
self.retranslateUi()
QtCore.QObject.connect(form.draft,
QtCore.SIGNAL("valueChanged(double)"),
self.onData)
QtCore.QObject.connect(form.trim,
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 getMainWindow(self):
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 = QtGui.QApplication.translate("ship_console", "Ship instance must be selected (no object selected)",
None,QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
return True
for i in range(0,len(selObjs)):
obj = selObjs[i]
# Test if is a ship instance
props = obj.PropertiesList
try:
props.index("IsShip")
except ValueError:
continue
if obj.IsShip:
# Test if another ship already selected
if self.ship:
msg = QtGui.QApplication.translate("ship_console", "More than one ship selected (extra ships will be neglected)",
None,QtGui.QApplication.UnicodeUTF8)
App.Console.PrintWarning(msg + '\n')
break
self.ship = obj
# Test if any valid ship was selected
if not self.ship:
msg = QtGui.QApplication.translate("ship_console",
"Ship instance must be selected (no valid ship found at selected objects)",
None,QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
return True
# Get bounds
bbox = self.ship.Shape.BoundBox
self.form.draft.setMaximum(bbox.ZMax)
self.form.draft.setMinimum(bbox.ZMin)
self.form.draft.setValue(self.ship.Draft)
# Try to use saved values
props = self.ship.PropertiesList
flag = True
try:
props.index("AreaCurveDraft")
except ValueError:
flag = False
if flag:
self.form.draft.setValue(self.ship.AreaCurveDraft)
flag = True
try:
props.index("AreaCurveTrim")
except ValueError:
flag = False
if flag:
self.form.trim.setValue(self.ship.AreaCurveTrim)
# Update GUI
self.preview.update(self.form.draft.value(), self.form.trim.value(), self.ship)
self.onUpdate()
return False
def widget(self, class_id, name):
"""Return the selected widget.
def retranslateUi(self):
""" Set user interface locale strings.
"""
self.form.setWindowTitle(QtGui.QApplication.translate("ship_areas","Plot transversal areas curve",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QLabel, "DraftLabel").setText(QtGui.QApplication.translate("ship_areas","Draft",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QLabel, "TrimLabel").setText(QtGui.QApplication.translate("ship_areas","Trim",
None,QtGui.QApplication.UnicodeUTF8))
Keyword arguments:
class_id -- Class identifier
name -- Name of the widget
"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
return form.findChild(class_id, name)
def onData(self, value):
""" Method called when input data is changed.
@param value Changed value.
"""
if not self.ship:
return
self.onUpdate()
self.preview.update(self.form.draft.value(), self.form.trim.value(), self.ship)
def initValues(self):
""" Set initial values for fields
"""
selObjs = Gui.Selection.getSelection()
if not selObjs:
msg = QtGui.QApplication.translate(
"ship_console",
"A ship instance must be selected before using this tool (no"
" objects selected)",
None,
QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
return True
for i in range(0, len(selObjs)):
obj = selObjs[i]
props = obj.PropertiesList
try:
props.index("IsShip")
except ValueError:
continue
if obj.IsShip:
if self.ship:
msg = QtGui.QApplication.translate(
"ship_console",
"More than one ship have been selected (the extra"
" ships will be ignored)",
None,
QtGui.QApplication.UnicodeUTF8)
App.Console.PrintWarning(msg + '\n')
break
self.ship = obj
if not self.ship:
msg = QtGui.QApplication.translate(
"ship_console",
"A ship instance must be selected before using this tool (no"
" valid ship found at the selected objects)",
None,
QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
return True
# Get the bounds for the tools
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.draft = self.widget(QtGui.QDoubleSpinBox, "Draft")
form.trim = self.widget(QtGui.QDoubleSpinBox, "Trim")
bbox = self.ship.Shape.BoundBox
form.draft.setMaximum(bbox.ZMax / Units.Metre.Value)
form.draft.setMinimum(bbox.ZMin / Units.Metre.Value)
form.draft.setValue(self.ship.Draft)
# Try to use saved values
props = self.ship.PropertiesList
flag = True
try:
props.index("AreaCurveDraft")
except ValueError:
flag = False
if flag:
form.draft.setValue(self.ship.AreaCurveDraft)
flag = True
try:
props.index("AreaCurveTrim")
except ValueError:
flag = False
if flag:
form.trim.setValue(self.ship.AreaCurveTrim)
# Update GUI
self.preview.update(form.draft.value(), form.trim.value(), self.ship)
self.onUpdate()
return False
def onUpdate(self):
""" Method called when update data request.
"""
if not self.ship:
return
# Calculate drafts
angle = math.radians(self.form.trim.value())
L = self.ship.Length
draftAP = self.form.draft.value() + 0.5*L*math.tan(angle)
if draftAP < 0.0:
draftAP = 0.0
draftFP = self.form.draft.value() - 0.5*L*math.tan(angle)
if draftFP < 0.0:
draftFP = 0.0
# Calculate hydrostatics involved
data = Hydrostatics.displacement(self.ship,self.form.draft.value(),0.0,self.form.trim.value())
# Prepare the string in html format
string = 'L = %g [m]<BR>' % (self.ship.Length)
string = string + 'B = %g [m]<BR>' % (self.ship.Beam)
string = string + 'T = %g [m]<HR>' % (self.form.draft.value())
string = string + 'Trim = %g [degrees]<BR>' % (self.form.trim.value())
string = string + 'T<sub>AP</sub> = %g [m]<BR>' % (draftAP)
string = string + 'T<sub>FP</sub> = %g [m]<HR>' % (draftFP)
dispText = QtGui.QApplication.translate("ship_areas",'Displacement',
None,QtGui.QApplication.UnicodeUTF8)
string = string + dispText + ' = %g [ton]<BR>' % (data[0])
string = string + 'XCB = %g [m]' % (data[1].x)
# Set the document
self.form.output.setHtml(string)
def retranslateUi(self):
""" Set user interface locale strings. """
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.setWindowTitle(QtGui.QApplication.translate(
"ship_areas",
"Plot the transversal areas curve",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QLabel, "DraftLabel").setText(
QtGui.QApplication.translate(
"ship_areas",
"Draft",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QLabel, "TrimLabel").setText(
QtGui.QApplication.translate(
"ship_areas",
"Trim",
None,
QtGui.QApplication.UnicodeUTF8))
def onData(self, value):
""" Method called when the tool input data is touched.
@param value Changed value.
"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.draft = self.widget(QtGui.QDoubleSpinBox, "Draft")
form.trim = self.widget(QtGui.QDoubleSpinBox, "Trim")
if not self.ship:
return
self.onUpdate()
self.preview.update(form.draft.value(), form.trim.value(), self.ship)
def onUpdate(self):
""" Method called when the data update is requested. """
if not self.ship:
return
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.draft = self.widget(QtGui.QDoubleSpinBox, "Draft")
form.trim = self.widget(QtGui.QDoubleSpinBox, "Trim")
form.output = self.widget(QtGui.QTextEdit, "OutputData")
# Calculate the drafts at each perpendicular
angle = math.radians(form.trim.value())
L = self.ship.Length
draftAP = form.draft.value() + 0.5 * L * math.tan(angle)
if draftAP < 0.0:
draftAP = 0.0
draftFP = form.draft.value() - 0.5 * L * math.tan(angle)
if draftFP < 0.0:
draftFP = 0.0
# Calculate the involved hydrostatics
data = Hydrostatics.displacement(self.ship,
form.draft.value(),
0.0,
form.trim.value())
# Setup the html string
string = 'L = {0} [m]<BR>'.format(self.ship.Length)
string = string + 'B = {0} [m]<BR>'.format(self.ship.Breadth)
string = string + 'T = {0} [m]<HR>'.format(form.draft.value())
string = string + 'Trim = {0} [degrees]<BR>'.format(form.trim.value())
string = string + 'T<sub>AP</sub> = {0} [m]<BR>'.format(draftAP)
string = string + 'T<sub>FP</sub> = {0} [m]<HR>'.format(draftFP)
dispText = QtGui.QApplication.translate(
"ship_areas",
'Displacement',
None,
QtGui.QApplication.UnicodeUTF8)
string = string + dispText + ' = {0} [ton]<BR>'.format(data[0])
string = string + 'XCB = {0} [m]'.format(data[1].x)
form.output.setHtml(string)
def save(self):
""" Saves the data into ship instance. """
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.draft = self.widget(QtGui.QDoubleSpinBox, "Draft")
form.trim = self.widget(QtGui.QDoubleSpinBox, "Trim")
props = self.ship.PropertiesList
try:
props.index("AreaCurveDraft")
except ValueError:
try:
tooltip = str(QtGui.QApplication.translate(
"ship_areas",
"Areas curve tool draft selected [m]",
None,
QtGui.QApplication.UnicodeUTF8))
except:
tooltip = "Areas curve tool draft selected [m]"
self.ship.addProperty("App::PropertyFloat",
"AreaCurveDraft",
"Ship",
tooltip)
self.ship.AreaCurveDraft = form.draft.value()
try:
props.index("AreaCurveTrim")
except ValueError:
try:
tooltip = str(QtGui.QApplication.translate(
"ship_areas",
"Areas curve tool trim selected [deg]",
None,
QtGui.QApplication.UnicodeUTF8))
except:
tooltip = "Areas curve tool trim selected [deg]"
self.ship.addProperty("App::PropertyFloat",
"AreaCurveTrim",
"Ship",
tooltip)
self.ship.AreaCurveTrim = form.trim.value()
def save(self):
""" Saves data into ship instance.
"""
props = self.ship.PropertiesList
try:
props.index("AreaCurveDraft")
except ValueError:
tooltip = str(QtGui.QApplication.translate("ship_areas","Areas curve tool draft selected [m]",
None,QtGui.QApplication.UnicodeUTF8))
self.ship.addProperty("App::PropertyFloat","AreaCurveDraft","Ship", tooltip)
self.ship.AreaCurveDraft = self.form.draft.value()
try:
props.index("AreaCurveTrim")
except ValueError:
tooltip = str(QtGui.QApplication.translate("ship_areas","Areas curve tool trim selected",
None,QtGui.QApplication.UnicodeUTF8))
self.ship.addProperty("App::PropertyFloat","AreaCurveTrim","Ship", tooltip)
self.ship.AreaCurveTrim = self.form.trim.value()
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel

View File

@@ -1,36 +1,29 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* 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()
""" Loads the tool """
TaskPanel.createTask()

View File

@@ -1,142 +1,195 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD,FreeCADGui
import FreeCAD
import FreeCADGui
from FreeCAD import Base
import Part
# Qt library
from PyQt4 import QtGui,QtCore
# FreeCADShip modules
import Units
from PySide import QtGui, QtCore
from shipUtils import Paths
class Preview(object):
def __init__(self):
""" Constructor.
"""
self.baseLine = None
self.baseLineLabel = None
self.reinit()
def __init__(self):
"""Constructor."""
self.baseLine = None
self.baseLineLabel = None
self.reinit()
def reinit(self):
""" Reinitializate drawer.
"""
self.clean()
def reinit(self):
"""Reinitializate drawer, removing all the previous annotations"""
self.clean()
def update(self, L, B, T):
""" Update the 3D view printing annotations.
@param L Ship length.
@param B Ship beam.
@param T Ship draft.
"""
# Destroy all previous entities
self.clean()
# Draw base line
xStart = -0.6*L;
xEnd = 0.6*L;
baseLine = Part.makeLine((xStart,0,0),(xEnd,0,0))
Part.show(baseLine)
objs = FreeCAD.ActiveDocument.Objects
self.baseLine = objs[len(objs)-1]
self.baseLine.Label = 'BaseLine'
text = str(QtGui.QApplication.translate("ship_create","Base line",
None,QtGui.QApplication.UnicodeUTF8))
self.baseLineLabel = DrawText('BaseLineText', text, Base.Vector(xEnd,0,0))
# Draw free surface
fsLine = Part.makeLine((xStart,0,T),(xEnd,0,T))
Part.show(fsLine)
objs = FreeCAD.ActiveDocument.Objects
self.fsLine = objs[len(objs)-1]
self.fsLine.Label = 'FreeSurface'
text = str(QtGui.QApplication.translate("ship_create","Free surface",
None,QtGui.QApplication.UnicodeUTF8))
self.fsLineLabel = DrawText('FSText', text, Base.Vector(xEnd,0,T))
# Draw forward perpendicular
zStart = -0.1*T
zEnd = 1.1*T
fpLine = Part.makeLine((0.5*L,0,zStart),(0.5*L,0,zEnd))
Part.show(fpLine)
objs = FreeCAD.ActiveDocument.Objects
self.fpLine = objs[len(objs)-1]
self.fpLine.Label = 'ForwardPerpendicular'
text = str(QtGui.QApplication.translate("ship_create","Forward perpendicular",
None,QtGui.QApplication.UnicodeUTF8))
self.fpLineLabel = DrawText('FPText', text, Base.Vector(0.5*L,0,zEnd))
# Draw after perpendicular
apLine = Part.makeLine((-0.5*L,0,zStart),(-0.5*L,0,zEnd))
Part.show(apLine)
objs = FreeCAD.ActiveDocument.Objects
self.apLine = objs[len(objs)-1]
self.apLine.Label = 'AfterPerpendicular'
text = str(QtGui.QApplication.translate("ship_create","After perpendicular",
None,QtGui.QApplication.UnicodeUTF8))
self.apLineLabel = DrawText('APText', text, Base.Vector(-0.5*L,0,zEnd))
# Draw amin frame
amLine = Part.makeLine((0,-0.5*B,zStart),(0,-0.5*B,zEnd))
Part.show(amLine)
objs = FreeCAD.ActiveDocument.Objects
self.amLine = objs[len(objs)-1]
self.amLine.Label = 'AminFrame'
text = str(QtGui.QApplication.translate("ship_create","Main frame",
None,QtGui.QApplication.UnicodeUTF8))
self.amLineLabel = DrawText('AMText', text, Base.Vector(0,-0.5*B,zEnd))
def clean(self):
""" Erase all annotations from screen.
"""
if not self.baseLine:
return
FreeCAD.ActiveDocument.removeObject(self.baseLine.Name)
FreeCAD.ActiveDocument.removeObject(self.baseLineLabel.Name)
FreeCAD.ActiveDocument.removeObject(self.fsLine.Name)
FreeCAD.ActiveDocument.removeObject(self.fsLineLabel.Name)
FreeCAD.ActiveDocument.removeObject(self.fpLine.Name)
FreeCAD.ActiveDocument.removeObject(self.fpLineLabel.Name)
FreeCAD.ActiveDocument.removeObject(self.apLine.Name)
FreeCAD.ActiveDocument.removeObject(self.apLineLabel.Name)
FreeCAD.ActiveDocument.removeObject(self.amLine.Name)
FreeCAD.ActiveDocument.removeObject(self.amLineLabel.Name)
def update(self, L, B, T):
"""Update the 3D view printing the annotations.
def DrawText(name, string, position, displayMode="Screen", angle=0.0, justification="Left", colour=(0.00,0.00,0.00), size=12):
""" Draws a text in a desired position.
@param name Name of the object
@param string Text to draw (recommended format u'')
@param position Point to draw the text
@param angle Counter clockwise rotation of text
@param justification Alignement of the text ("Left", "Right" or "Center")
@param colour Colour of the text
@param size Font size
@return FreeCAD annotation object
"""
# Create the object
text = FreeCAD.ActiveDocument.addObject("App::Annotation",name)
# Set the text
text.LabelText = [string, u'']
# Set the options
text.Position = position
FreeCADGui.ActiveDocument.getObject(text.Name).Rotation = angle
FreeCADGui.ActiveDocument.getObject(text.Name).Justification = justification
FreeCADGui.ActiveDocument.getObject(text.Name).FontSize = size
FreeCADGui.ActiveDocument.getObject(text.Name).TextColor = colour
FreeCADGui.ActiveDocument.getObject(text.Name).DisplayMode = displayMode
return FreeCAD.ActiveDocument.getObject(text.Name)
Keyword arguments:
L -- Selected ship length.
B -- Selected ship breadth.
T -- Selected ship draft.
"""
self.clean()
# Move to the international system units
L *= Units.Metre.Value
B *= Units.Metre.Value
T *= Units.Metre.Value
# Draw the base line
xStart = -0.6 * L
xEnd = 0.6 * L
baseLine = Part.makeLine((xStart, 0, 0), (xEnd, 0, 0))
Part.show(baseLine)
objs = FreeCAD.ActiveDocument.Objects
self.baseLine = objs[len(objs) - 1]
self.baseLine.Label = 'BaseLine'
try:
text = str(QtGui.QApplication.translate(
"ship_create",
"Base line",
None,
QtGui.QApplication.UnicodeUTF8))
except:
text = "Base line"
self.baseLineLabel = DrawText('BaseLineText',
text,
Base.Vector(xEnd, 0, 0))
# Draw the free surface line
fsLine = Part.makeLine((xStart, 0, T), (xEnd, 0, T))
Part.show(fsLine)
objs = FreeCAD.ActiveDocument.Objects
self.fsLine = objs[len(objs) - 1]
self.fsLine.Label = 'FreeSurface'
try:
text = str(QtGui.QApplication.translate(
"ship_create",
"Free surface",
None,
QtGui.QApplication.UnicodeUTF8))
except:
text = "Free surface"
self.fsLineLabel = DrawText('FSText', text, Base.Vector(xEnd, 0, T))
# Draw the forward perpendicular
zStart = -0.1 * T
zEnd = 1.1 * T
fpLine = Part.makeLine((0.5 * L, 0, zStart), (0.5 * L, 0, zEnd))
Part.show(fpLine)
objs = FreeCAD.ActiveDocument.Objects
self.fpLine = objs[len(objs) - 1]
self.fpLine.Label = 'ForwardPerpendicular'
try:
text = str(QtGui.QApplication.translate(
"ship_create",
"Forward perpendicular",
None,
QtGui.QApplication.UnicodeUTF8))
except:
text = "Forward perpendicular"
self.fpLineLabel = DrawText('FPText',
text,
Base.Vector(0.5 * L, 0, zEnd))
# Draw the after perpendicular
apLine = Part.makeLine((-0.5 * L, 0, zStart), (-0.5 * L, 0, zEnd))
Part.show(apLine)
objs = FreeCAD.ActiveDocument.Objects
self.apLine = objs[len(objs) - 1]
self.apLine.Label = 'AfterPerpendicular'
try:
text = str(QtGui.QApplication.translate(
"ship_create",
"After perpendicular",
None,
QtGui.QApplication.UnicodeUTF8))
except:
text = "After perpendicular"
self.apLineLabel = DrawText('APText',
text,
Base.Vector(-0.5 * L, 0, zEnd))
# Draw the amin frame
amLine = Part.makeLine((0, -0.5 * B, zStart), (0, -0.5 * B, zEnd))
Part.show(amLine)
objs = FreeCAD.ActiveDocument.Objects
self.amLine = objs[len(objs) - 1]
self.amLine.Label = 'AminFrame'
try:
text = str(QtGui.QApplication.translate(
"ship_create",
"Main frame",
None,
QtGui.QApplication.UnicodeUTF8))
except:
text = "Main frame"
self.amLineLabel = DrawText('AMText',
text,
Base.Vector(0, -0.5 * B, zEnd))
def clean(self):
"""Remove all previous annotations from screen."""
if not self.baseLine:
return
FreeCAD.ActiveDocument.removeObject(self.baseLine.Name)
FreeCAD.ActiveDocument.removeObject(self.baseLineLabel.Name)
FreeCAD.ActiveDocument.removeObject(self.fsLine.Name)
FreeCAD.ActiveDocument.removeObject(self.fsLineLabel.Name)
FreeCAD.ActiveDocument.removeObject(self.fpLine.Name)
FreeCAD.ActiveDocument.removeObject(self.fpLineLabel.Name)
FreeCAD.ActiveDocument.removeObject(self.apLine.Name)
FreeCAD.ActiveDocument.removeObject(self.apLineLabel.Name)
FreeCAD.ActiveDocument.removeObject(self.amLine.Name)
FreeCAD.ActiveDocument.removeObject(self.amLineLabel.Name)
def DrawText(name,
string,
position,
displayMode="Screen",
angle=0.0,
justification="Left",
colour=(0.0, 0.0, 0.0),
size=12):
"""Draw a text in the screen.
Keyword arguments:
name -- Name (label) of the object to generate.
string -- Text to draw (it is strongly recommended to use format u'').
position -- Point to draw the text.
angle -- Counter clockwise rotation of text.
justification -- Alignement of the text ("Left", "Right" or "Center").
colour -- Colour of the text.
size -- Font size (in points pt).
Returns:
A FreeCAD annotation object
"""
# Create the object
text = FreeCAD.ActiveDocument.addObject("App::Annotation", name)
# Set the text
text.LabelText = [string, u'']
# Set the options
text.Position = position
doc = FreeCADGui.ActiveDocument
doc.getObject(text.Name).Rotation = angle
doc.getObject(text.Name).Justification = justification
doc.getObject(text.Name).FontSize = size
doc.getObject(text.Name).TextColor = colour
doc.getObject(text.Name).DisplayMode = displayMode
return FreeCAD.ActiveDocument.getObject(text.Name)

View File

@@ -1,230 +1,291 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Qt library
from PyQt4 import QtGui,QtCore
# Module
import Units
from PySide import QtGui, QtCore
import Preview
import Instance
from shipUtils import Paths
class TaskPanel:
def __init__(self):
self.ui = Paths.modulePath() + "/shipCreateShip/TaskPanel.ui"
self.preview = Preview.Preview()
def __init__(self):
"""Constructor"""
self.ui = Paths.modulePath() + "/shipCreateShip/TaskPanel.ui"
self.preview = Preview.Preview()
def accept(self):
self.preview.clean()
# Create new ship instance
obj = App.ActiveDocument.addObject("Part::FeaturePython","Ship")
ship = Instance.Ship(obj, self.solids)
Instance.ViewProviderShip(obj.ViewObject)
# Set main dimensions
obj.Length = self.form.length.value()
obj.Beam = self.form.beam.value()
obj.Draft = self.form.draft.value()
# Discretize it
App.ActiveDocument.recompute()
return True
def accept(self):
"""Create the ship instance"""
self.preview.clean()
obj = App.ActiveDocument.addObject("Part::FeaturePython", "Ship")
ship = Instance.Ship(obj, self.solids)
Instance.ViewProviderShip(obj.ViewObject)
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.length = self.widget(QtGui.QDoubleSpinBox, "Length")
form.breadth = self.widget(QtGui.QDoubleSpinBox, "Breadth")
form.draft = self.widget(QtGui.QDoubleSpinBox, "Draft")
obj.Length = form.length.value()
obj.Breadth = form.breadth.value()
obj.Draft = form.draft.value()
App.ActiveDocument.recompute()
return True
def reject(self):
self.preview.clean()
return True
def reject(self):
"""Cancel the job"""
self.preview.clean()
return True
def clicked(self, index):
pass
def clicked(self, index):
pass
def open(self):
pass
def open(self):
pass
def needsFullSpace(self):
return True
def needsFullSpace(self):
return True
def isAllowedAlterSelection(self):
return False
def isAllowedAlterSelection(self):
return False
def isAllowedAlterView(self):
return True
def isAllowedAlterView(self):
return True
def isAllowedAlterDocument(self):
return False
def isAllowedAlterDocument(self):
return False
def helpRequested(self):
pass
def helpRequested(self):
pass
def setupUi(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.length = form.findChild(QtGui.QDoubleSpinBox, "Length")
form.beam = form.findChild(QtGui.QDoubleSpinBox, "Beam")
form.draft = form.findChild(QtGui.QDoubleSpinBox, "Draft")
form.mainLogo = form.findChild(QtGui.QLabel, "MainLogo")
iconPath = Paths.iconsPath() + "/Ico.xpm"
form.mainLogo.setPixmap(QtGui.QPixmap(iconPath))
self.form = form
# Initial values
if self.initValues():
return True
self.retranslateUi()
self.preview.update(self.L, self.B, self.T)
# Connect Signals and Slots
QtCore.QObject.connect(form.length, QtCore.SIGNAL("valueChanged(double)"), self.onData)
QtCore.QObject.connect(form.beam, QtCore.SIGNAL("valueChanged(double)"), self.onData)
QtCore.QObject.connect(form.draft, QtCore.SIGNAL("valueChanged(double)"), self.onData)
def setupUi(self):
"""Create and configurate the user interface"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.length = self.widget(QtGui.QDoubleSpinBox, "Length")
form.breadth = self.widget(QtGui.QDoubleSpinBox, "Breadth")
form.draft = self.widget(QtGui.QDoubleSpinBox, "Draft")
form.mainLogo = self.widget(QtGui.QLabel, "MainLogo")
form.mainLogo.setPixmap(QtGui.QPixmap(":/icons/Ship_Logo.svg"))
self.form = form
if self.initValues():
return True
self.retranslateUi()
self.preview.update(self.L, self.B, self.T)
QtCore.QObject.connect(
form.length,
QtCore.SIGNAL("valueChanged(double)"),
self.onData)
QtCore.QObject.connect(
form.breadth,
QtCore.SIGNAL("valueChanged(double)"),
self.onData)
QtCore.QObject.connect(
form.draft,
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 getMainWindow(self):
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
self.solids = None
selObjs = Gui.Selection.getSelection()
if not selObjs:
msg = QtGui.QApplication.translate("ship_console",
"Ship objects can only be created on top of hull geometry (any object selected)",
None,QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
msg = QtGui.QApplication.translate("ship_console",
"Please create or load a ship hull geometry before using this tool",
None,QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
return True
self.solids = []
for i in range(0, len(selObjs)):
solids = self.getSolids(selObjs[i])
for j in range(0, len(solids)):
self.solids.append(solids[j])
if not self.solids:
msg = QtGui.QApplication.translate("ship_console",
"Ship objects can only be created on top of hull geometry (no solid found at selected objects)",
None,QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
msg = QtGui.QApplication.translate("ship_console",
"Please create or load a ship hull geometry before using this tool",
None,QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
return True
# Get bounds
bounds = [0.0, 0.0, 0.0]
bbox = self.solids[0].BoundBox
minX = bbox.XMin
maxX = bbox.XMax
minY = bbox.YMin
maxY = bbox.YMax
minZ = bbox.ZMin
maxZ = bbox.ZMax
for i in range(1,len(self.solids)):
bbox = self.solids[i].BoundBox
if minX > bbox.XMin:
minX = bbox.XMin
if maxX < bbox.XMax:
maxX = bbox.XMax
if minY > bbox.YMin:
minY = bbox.YMin
if maxY < bbox.YMax:
maxY = bbox.YMax
if minZ > bbox.ZMin:
minZ = bbox.ZMin
if maxZ < bbox.ZMax:
maxZ = bbox.ZMax
bounds[0] = maxX - minX
bounds[1] = max(maxY - minY, abs(maxY), abs(minY))
bounds[2] = maxZ - minZ
# Set UI fields
self.form.length.setMaximum(bounds[0])
self.form.length.setMinimum(0.001)
self.form.length.setValue(bounds[0])
self.L = bounds[0]
self.form.beam.setMaximum(bounds[1])
self.form.beam.setMinimum(0.001)
self.form.beam.setValue(bounds[1])
self.B = bounds[1]
self.form.draft.setMaximum(bounds[2])
self.form.draft.setMinimum(0.001)
self.form.draft.setValue(0.5*bounds[2])
self.T = 0.5*bounds[2]
return False
def widget(self, class_id, name):
"""Return the selected widget.
def retranslateUi(self):
""" Set user interface locale strings.
"""
self.form.setWindowTitle(QtGui.QApplication.translate("ship_create","Create a new ship",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QLabel, "LengthLabel").setText(QtGui.QApplication.translate("ship_create","Length",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QLabel, "BeamLabel").setText(QtGui.QApplication.translate("ship_create","Breadth",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QLabel, "DraftLabel").setText(QtGui.QApplication.translate("ship_create","Draft",
None,QtGui.QApplication.UnicodeUTF8))
Keyword arguments:
class_id -- Class identifier
name -- Name of the widget
"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
return form.findChild(class_id, name)
def onData(self, value):
""" Method called when ship data is changed.
Annotations must be showed.
@param value Changed value.
"""
self.L = self.form.length.value()
self.B = self.form.beam.value()
self.T = self.form.draft.value()
self.preview.update(self.L, self.B, self.T)
def initValues(self):
"""Setup the initial values"""
self.solids = None
selObjs = Gui.Selection.getSelection()
if not selObjs:
msg = QtGui.QApplication.translate(
"ship_console",
"Ship objects can only be created on top of hull geometry"
" (no objects selected)",
None,
QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
msg = QtGui.QApplication.translate(
"ship_console",
"Please create or load a ship hull geometry before using"
" this tool",
None,
QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
return True
self.solids = []
for i in range(0, len(selObjs)):
solids = self.getSolids(selObjs[i])
for j in range(0, len(solids)):
self.solids.append(solids[j])
if not self.solids:
msg = QtGui.QApplication.translate(
"ship_console",
"Ship objects can only be created on top of hull geometry"
" (no solid found at selected objects)",
None,
QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
msg = QtGui.QApplication.translate(
"ship_console",
"Please create or load a ship hull geometry before using"
" this tool",
None,
QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
return True
# Get the ship bounds. The ship instance can not have dimensions
# out of these values.
bounds = [0.0, 0.0, 0.0]
bbox = self.solids[0].BoundBox
minX = bbox.XMin
maxX = bbox.XMax
minY = bbox.YMin
maxY = bbox.YMax
minZ = bbox.ZMin
maxZ = bbox.ZMax
for i in range(1, len(self.solids)):
bbox = self.solids[i].BoundBox
if minX > bbox.XMin:
minX = bbox.XMin
if maxX < bbox.XMax:
maxX = bbox.XMax
if minY > bbox.YMin:
minY = bbox.YMin
if maxY < bbox.YMax:
maxY = bbox.YMax
if minZ > bbox.ZMin:
minZ = bbox.ZMin
if maxZ < bbox.ZMax:
maxZ = bbox.ZMax
bounds[0] = maxX - minX
bounds[1] = max(maxY - minY, abs(maxY), abs(minY))
bounds[2] = maxZ - minZ
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.length = self.widget(QtGui.QDoubleSpinBox, "Length")
form.breadth = self.widget(QtGui.QDoubleSpinBox, "Breadth")
form.draft = self.widget(QtGui.QDoubleSpinBox, "Draft")
form.length.setMaximum(bounds[0] / Units.Metre.Value)
form.length.setMinimum(0.001)
form.length.setValue(bounds[0] / Units.Metre.Value)
self.L = bounds[0] / Units.Metre.Value
form.breadth.setMaximum(bounds[1] / Units.Metre.Value)
form.breadth.setMinimum(0.001)
form.breadth.setValue(bounds[1] / Units.Metre.Value)
self.B = bounds[1] / Units.Metre.Value
form.draft.setMaximum(bounds[2] / Units.Metre.Value)
form.draft.setMinimum(0.001)
form.draft.setValue(0.5 * bounds[2] / Units.Metre.Value)
self.T = 0.5 * bounds[2] / Units.Metre.Value
return False
def retranslateUi(self):
"""Set the user interface locale strings."""
self.form.setWindowTitle(QtGui.QApplication.translate(
"ship_create",
"Create a new ship",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QLabel, "LengthLabel").setText(
QtGui.QApplication.translate(
"ship_create",
"Length",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QLabel, "BreadthLabel").setText(
QtGui.QApplication.translate(
"ship_create",
"Breadth",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QLabel, "DraftLabel").setText(
QtGui.QApplication.translate(
"ship_create",
"Draft",
None,
QtGui.QApplication.UnicodeUTF8))
def onData(self, value):
"""Updates the 3D preview on data changes.
Keyword arguments:
value -- Edited value. This parameter is required in order to use this
method as a callback function, but it is unuseful.
"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.length = self.widget(QtGui.QDoubleSpinBox, "Length")
form.breadth = self.widget(QtGui.QDoubleSpinBox, "Breadth")
form.draft = self.widget(QtGui.QDoubleSpinBox, "Draft")
self.L = form.length.value()
self.B = form.breadth.value()
self.T = form.draft.value()
self.preview.update(self.L, self.B, self.T)
def getSolids(self, obj):
"""Returns the solid entities from an object
Keyword arguments:
obj -- FreeCAD object to extract the solids from.
Returns:
The solid entities, None if no solid have been found.
"""
if not obj:
return None
if obj.isDerivedFrom('Part::Feature'):
# get shape
shape = obj.Shape
if not shape:
return None
obj = shape
if not obj.isDerivedFrom('Part::TopoShape'):
return None
# get face
solids = obj.Solids
if not solids:
return None
return solids
def getSolids(self, obj):
""" Returns object solids (list of them)
@param obj Object to extract solids.
@return Solids. None if errors happens
"""
if not obj:
return None
if obj.isDerivedFrom('Part::Feature'):
# get shape
shape = obj.Shape
if not shape:
return None
obj = shape
if not obj.isDerivedFrom('Part::TopoShape'):
return None
# get face
solids = obj.Solids
if not solids:
return None
return solids
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel

View File

@@ -111,6 +111,19 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="LengthUnits">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>m</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@@ -128,14 +141,14 @@
<number>0</number>
</property>
<item>
<widget class="QLabel" name="BeamLabel">
<widget class="QLabel" name="BreadthLabel">
<property name="text">
<string>Beam</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="Beam">
<widget class="QDoubleSpinBox" name="Breadth">
<property name="decimals">
<number>3</number>
</property>
@@ -144,6 +157,19 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="BreadthUnits">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>m</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@@ -177,6 +203,19 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="DraftUnits">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>m</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View File

@@ -1,36 +1,29 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* 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()
"""Loads the tool in the task panel"""
TaskPanel.createTask()

View File

@@ -1,35 +1,32 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
import math
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
from FreeCAD import Base, Vector
import Part
# Qt library
from PyQt4 import QtGui,QtCore
# Module
import PlotAux
import Instance
from shipUtils import Paths

View File

@@ -1,38 +1,37 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
import math
# FreeCAD modules
from FreeCAD import Vector
import Part
import Units
import FreeCAD as App
import FreeCADGui as Gui
# Module
import Instance
from shipUtils import Math
def areas(ship, draft, roll=0.0, trim=0.0, yaw=0.0, n=30):
""" Compute ship transversal areas.
""" Compute the ship transversal areas.
@param ship Ship instance.
@param draft Ship draft.
@param roll Ship roll angle.
@@ -45,38 +44,42 @@ def areas(ship, draft, roll=0.0, trim=0.0, yaw=0.0, n=30):
"""
if n < 2:
return []
# We will take a duplicate of ship shape in order to place it
# We will take a duplicate of ship shape in order to conviniently place it
shape = ship.Shape.copy()
shape.translate(Vector(0.0,0.0,-draft))
shape.translate(Vector(0.0,0.0,-draft*Units.Metre.Value))
# Rotations composition is Roll->Trim->Yaw
shape.rotate(Vector(0.0,0.0,0.0), Vector(1.0,0.0,0.0), roll)
shape.rotate(Vector(0.0,0.0,0.0), Vector(0.0,-1.0,0.0), trim)
shape.rotate(Vector(0.0,0.0,0.0), Vector(0.0,0.0,1.0), yaw)
# Now we need to know the x range of values
# Now we need to know the x range of values to perform the sections
bbox = shape.BoundBox
xmin = bbox.XMin
xmax = bbox.XMax
dx = (xmax - xmin) / (n-1.0)
# First area is equal to zero.
areas = [[xmin, 0.0]]
# Since we need face entities, in order to compute sections we will
# create boxes with front face at transversal area position,
# compute solid common, divide by faces, and preserve only desired
# ones.
# Since we are computing in the total length (not in the perpendiculars one),
# we can grant that the starting and ending sections are null
areas = [[xmin/Units.Metre.Value, 0.0]]
# And since we need only face entities, in order to compute sections we will
# create boxes with front face at the desired transversal area position,
# computing the common solid part, dividing it by faces, and getting only
# the desired ones.
App.Console.PrintMessage("Computing transversal areas...\n")
App.Console.PrintMessage("Some Inventor representation errors can be shown, ignore it please.\n")
App.Console.PrintMessage("Some Inventor representation errors can be shown, please ignore it.\n")
for i in range(1,n-1):
App.Console.PrintMessage("%d / %d\n" % (i, n-2))
App.Console.PrintMessage("{0} / {1}\n".format(i, n-2))
x = xmin + i*dx
area = 0.0
# Create the box
L = xmax - xmin
B = bbox.YMax - bbox.YMin
p = Vector(-1.5*L, -1.5*B, bbox.ZMin - 1.0)
box = Part.makeBox(1.5*L + x, 3.0*B, - bbox.ZMin + 1.0, p)
# Compute common part with ship
p = Vector(-1.5*L, -1.5*B, bbox.ZMin)
try:
box = Part.makeBox(1.5*L + x, 3.0*B, - bbox.ZMin, p)
except:
areas.append([x, area])
continue
# Compute the common part with ship
for s in shape.Solids:
# Get solids intersection
try:
common = box.common(s)
except:
@@ -89,7 +92,7 @@ def areas(ship, draft, roll=0.0, trim=0.0, yaw=0.0, n=30):
Part.show(common)
except:
continue
# Divide by faces and compute only section placed ones
# Divide the solid by faces and compute only the well placed ones
faces = common.Faces
for f in faces:
faceBounds = f.BoundBox
@@ -99,19 +102,18 @@ def areas(ship, draft, roll=0.0, trim=0.0, yaw=0.0, n=30):
# Place filter
if abs(faceBounds.XMax - x) > 0.00001:
continue
# Valid face, compute area
area = area + f.Area
# Destroy last object generated
# It is a valid face, so we can add this area
area = area + f.Area/Units.Metre.Value**2
# Destroy the last generated object
App.ActiveDocument.removeObject(App.ActiveDocument.Objects[-1].Name)
# Append transversal area
areas.append([x, area])
# Last area is equal to zero
areas.append([xmax, 0.0])
areas.append([x/Units.Metre.Value, area])
# Last area is equal to zero (see some lines above)
areas.append([xmax/Units.Metre.Value, 0.0])
App.Console.PrintMessage("Done!\n")
return areas
def displacement(ship, draft, roll=0.0, trim=0.0, yaw=0.0):
""" Compute ship displacement.
""" Compute the ship displacement.
@param ship Ship instance.
@param draft Ship draft.
@param roll Ship roll angle.
@@ -119,15 +121,15 @@ def displacement(ship, draft, roll=0.0, trim=0.0, yaw=0.0):
@param yaw Ship yaw angle. Ussually you don't want to use this
value.
@return [disp, B, Cb], \n
disp = Ship displacement [ton].
B = Bouyance center [m].
Cb = Block coefficient.
@note Bouyance center will returned as FreeCAD.Vector class.
@note Returned Bouyance center is in non modified ship coordinates
- disp = Ship displacement [ton].
- B = Bouyance center [m].
- Cb = Block coefficient.
@note Bouyance center will returned as a FreeCAD.Vector instance.
@note Returned Bouyance center is in the non modified ship coordinates
"""
# We will take a duplicate of ship shape in order to place it
# We will take a duplicate of ship shape in order to conviniently place it
shape = ship.Shape.copy()
shape.translate(Vector(0.0,0.0,-draft))
shape.translate(Vector(0.0,0.0,-draft*Units.Metre.Value))
# Rotations composition is Roll->Trim->Yaw
shape.rotate(Vector(0.0,0.0,0.0), Vector(1.0,0.0,0.0), roll)
shape.rotate(Vector(0.0,0.0,0.0), Vector(0.0,-1.0,0.0), trim)
@@ -139,27 +141,30 @@ def displacement(ship, draft, roll=0.0, trim=0.0, yaw=0.0):
# Create the box
L = xmax - xmin
B = bbox.YMax - bbox.YMin
p = Vector(-1.5*L, -1.5*B, bbox.ZMin - 1.0)
box = Part.makeBox(3.0*L, 3.0*B, -bbox.ZMin + 1.0, p)
p = Vector(-1.5*L, -1.5*B, bbox.ZMin)
try:
box = Part.makeBox(3.0*L, 3.0*B, - bbox.ZMin, p)
except:
return [0.0, Vector(), 0.0]
vol = 0.0
cog = Vector()
for solid in shape.Solids:
# Compute common part with ship
# Compute the common part with the ship
try:
common = box.common(solid)
except:
continue
# Get data
vol = vol + common.Volume
# Get the data
vol = vol + common.Volume/Units.Metre.Value**3
for s in common.Solids:
sCoG = s.CenterOfMass
cog.x = cog.x + sCoG.x*s.Volume
cog.y = cog.y + sCoG.y*s.Volume
cog.z = cog.z + sCoG.z*s.Volume
cog.x = cog.x + sCoG.x*s.Volume/Units.Metre.Value**4
cog.y = cog.y + sCoG.y*s.Volume/Units.Metre.Value**4
cog.z = cog.z + sCoG.z*s.Volume/Units.Metre.Value**4
cog.x = cog.x / vol
cog.y = cog.y / vol
cog.z = cog.z / vol
Vol = L*B*abs(bbox.ZMin)
Vol = L*B*abs(bbox.ZMin)/Units.Metre.Value**3
# Undo transformations
B = Vector()
B.x = cog.x*math.cos(math.radians(-yaw)) - cog.y*math.sin(math.radians(-yaw))

View File

@@ -1,35 +1,29 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD
import FreeCADGui
# Qt libraries
from PyQt4 import QtGui,QtCore
# Main object
import TaskPanel
def load():

View File

@@ -1,108 +1,124 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Qt library
from PyQt4 import QtGui,QtCore
# Module
from PySide import QtGui, QtCore
from shipUtils import Paths
class TaskPanel:
def __init__(self):
self.ui = Paths.modulePath() + "/shipLoadExample/TaskPanel.ui"
def __init__(self):
"""Constructor."""
self.ui = Paths.modulePath() + "/shipLoadExample/TaskPanel.ui"
def accept(self):
path = Paths.modulePath() + "/resources/examples/"
if(self.form.ship.currentIndex() == 0): # s60 from Iowa University
App.open(path + "s60.fcstd")
elif(self.form.ship.currentIndex() == 1): # Wigley canonical ship
App.open(path + "wigley.fcstd")
elif(self.form.ship.currentIndex() == 2): # s60 (Katamaran)
App.open(path + "s60_katamaran.fcstd")
elif(self.form.ship.currentIndex() == 2): # Wigley (Katamaran)
App.open(path + "wigley_katamaran.fcstd")
return True
def accept(self):
"""Load the selected hull example."""
path = Paths.modulePath() + "/resources/examples/"
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.ship = self.widget(QtGui.QComboBox, "Ship")
if(form.ship.currentIndex() == 0): # s60 from Iowa University
App.open(path + "s60.fcstd")
elif(form.ship.currentIndex() == 1): # Wigley canonical ship
App.open(path + "wigley.fcstd")
elif(form.ship.currentIndex() == 2): # s60 (Katamaran)
App.open(path + "s60_katamaran.fcstd")
elif(form.ship.currentIndex() == 2): # Wigley (Katamaran)
App.open(path + "wigley_katamaran.fcstd")
return True
def reject(self):
return True
def reject(self):
"""Cancel the job"""
return True
def clicked(self, index):
pass
def clicked(self, index):
pass
def open(self):
pass
def open(self):
pass
def needsFullSpace(self):
return True
def needsFullSpace(self):
return True
def isAllowedAlterSelection(self):
return False
def isAllowedAlterSelection(self):
return False
def isAllowedAlterView(self):
return True
def isAllowedAlterView(self):
return True
def isAllowedAlterDocument(self):
return False
def isAllowedAlterDocument(self):
return False
def helpRequested(self):
pass
def helpRequested(self):
pass
def setupUi(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.ship = form.findChild(QtGui.QComboBox, "Ship")
form.mainLogo = form.findChild(QtGui.QLabel, "MainLogo")
iconPath = Paths.iconsPath() + "/Ico.xpm"
form.mainLogo.setPixmap(QtGui.QPixmap(iconPath))
self.form = form
self.retranslateUi()
def setupUi(self):
"""Setup the task panel user interface."""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.ship = self.widget(QtGui.QComboBox, "Ship")
form.mainLogo = self.widget(QtGui.QLabel, "MainLogo")
form.mainLogo.setPixmap(QtGui.QPixmap(":/icons/Ship_Logo.svg"))
self.form = form
self.retranslateUi()
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 getMainWindow(self):
toplevel = QtGui.qApp.topLevelWidgets()
for i in toplevel:
if i.metaObject().className() == "Gui::MainWindow":
return i
raise Exception("No main window found")
def widget(self, class_id, name):
"""Return the selected widget.
Keyword arguments:
class_id -- Class identifier
name -- Name of the widget
"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
return form.findChild(class_id, name)
def retranslateUi(self):
"""Set the user interface locale strings."""
self.form.setWindowTitle(QtGui.QApplication.translate(
"ship_load",
"Load example ship",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QGroupBox, "ShipSelectionBox").setTitle(
QtGui.QApplication.translate("ship_load",
"Select ship example geometry",
None,
QtGui.QApplication.UnicodeUTF8))
def retranslateUi(self):
""" Set user interface locale strings.
"""
self.form.setWindowTitle(QtGui.QApplication.translate("ship_load","Load example ship",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QGroupBox, "ShipSelectionBox").setTitle(QtGui.QApplication.translate("ship_load",
"Select ship example geometry",
None,QtGui.QApplication.UnicodeUTF8))
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel

View File

@@ -1,36 +1,29 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* 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()
"""Load the examples importing tool"""
TaskPanel.createTask()

View File

@@ -1,127 +1,145 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
# Qt library
from PyQt4 import QtGui,QtCore
# FreeCAD modules
import FreeCAD,FreeCADGui
from PySide import QtGui, QtCore
import FreeCAD
import FreeCADGui
from FreeCAD import Base, Vector
import Part
# FreeCADShip modules
import Units
from shipUtils import Paths
def Plot(scale, sections, shape):
""" Creates the outline draw.
@param scale Plane scale (format 1:scale)
@param sections Sections computed.
@param shape Ship surfaces shell
@return plotted object (DocumentObject)
"""
msg = QtGui.QApplication.translate("ship_console", "Performing plot",
None,QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg + ' (1:%d)...\n' % (scale))
scale = 1000.0 / scale
# Take positions
bounds = [0.0, 0.0, 0.0]
bbox = shape.BoundBox
bounds[0] = bbox.XLength
bounds[1] = bbox.YLength
bounds[2] = bbox.ZLength
xTot = scale*bounds[1] + 32.0 + scale*bounds[0]
yTot = scale*bounds[2] + 32.0 + scale*bounds[1]
xMid = 210.0
yMid = 185.0
x0 = xMid - 0.5*xTot
y0 = 297.0 - yMid - 0.5*yTot # 297 = A3_width
# Get border
edges = getEdges([shape])
border = edges[0]
for i in range(0,len(edges)):
border = border.oldFuse(edges[i]) # Only group objects, don't try to build more complex entities
border = border.oldFuse(edges[i].mirror(Vector(0.0, 0.0, 0.0),Vector(0.0, 1.0, 0.0)))
# Fuse sections & borders
# obj = sections.oldFuse(border)
obj = border.oldFuse(sections)
# Send to 3D view
Part.show(obj)
objs = FreeCAD.ActiveDocument.Objects
obj = objs[len(objs)-1]
# Create a new plane
FreeCAD.ActiveDocument.addObject('Drawing::FeaturePage','OutlineDrawPlot')
FreeCAD.ActiveDocument.OutlineDrawPlot.Template = FreeCAD.getResourceDir()+'Mod/Drawing/Templates/A3_Landscape.svg'
# Side view
FreeCAD.ActiveDocument.addObject('Drawing::FeatureViewPart','OutlineDrawSideView')
FreeCAD.ActiveDocument.OutlineDrawSideView.Source = obj
FreeCAD.ActiveDocument.OutlineDrawSideView.Direction = (1.0,0.0,0.0)
FreeCAD.ActiveDocument.OutlineDrawSideView.Rotation = -90.0
FreeCAD.ActiveDocument.OutlineDrawSideView.Scale = scale
FreeCAD.ActiveDocument.OutlineDrawSideView.X = 420.0 - x0 - 0.5*scale*bounds[1] # 420 = A3_height
FreeCAD.ActiveDocument.OutlineDrawSideView.Y = y0 + 0.5*scale*bounds[2]
FreeCAD.ActiveDocument.OutlineDrawPlot.addObject(FreeCAD.ActiveDocument.OutlineDrawSideView)
# Front view
FreeCAD.ActiveDocument.addObject('Drawing::FeatureViewPart','OutlineDrawFrontView')
FreeCAD.ActiveDocument.OutlineDrawFrontView.Source = obj
FreeCAD.ActiveDocument.OutlineDrawFrontView.Direction = (0.0,1.0,0.0)
FreeCAD.ActiveDocument.OutlineDrawFrontView.Rotation = -90.0
FreeCAD.ActiveDocument.OutlineDrawFrontView.Scale = scale
FreeCAD.ActiveDocument.OutlineDrawFrontView.X = 420.0 - x0 - scale*bounds[1] - 32 - 0.5*scale*bounds[0]
FreeCAD.ActiveDocument.OutlineDrawFrontView.Y = y0 + 0.5*scale*bounds[2]
FreeCAD.ActiveDocument.OutlineDrawPlot.addObject(FreeCAD.ActiveDocument.OutlineDrawFrontView)
# Up view
FreeCAD.ActiveDocument.addObject('Drawing::FeatureViewPart','OutlineDrawUpView')
FreeCAD.ActiveDocument.OutlineDrawUpView.Source = obj
FreeCAD.ActiveDocument.OutlineDrawUpView.Direction = (0.0,0.0,1.0)
FreeCAD.ActiveDocument.OutlineDrawUpView.Scale = scale
FreeCAD.ActiveDocument.OutlineDrawUpView.X = 420.0 - x0 - scale*bounds[1] - 32 - 0.5*scale*bounds[0]
FreeCAD.ActiveDocument.OutlineDrawUpView.Y = y0 + scale*bounds[2] + 32
FreeCAD.ActiveDocument.OutlineDrawPlot.addObject(FreeCAD.ActiveDocument.OutlineDrawUpView)
FreeCAD.ActiveDocument.recompute()
return obj
""" Creates the outline draw.
@param scale Plane scale (format 1:scale)
@param sections Computed sections.
@param shape Ship surfaces
@return plotted object (DocumentObject)
"""
msg = QtGui.QApplication.translate(
"ship_console",
"Performing plot",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg + ' (1:{0})...\n'.format(scale))
scale = 1.0 / scale
# Take positions
bounds = [0.0, 0.0, 0.0]
bbox = shape.BoundBox
bounds[0] = bbox.XLength
bounds[1] = bbox.YLength
bounds[2] = bbox.ZLength
xTot = scale * bounds[1] + 32.0 + scale * bounds[0]
yTot = scale * bounds[2] + 32.0 + scale * bounds[1]
xMid = 210.0
yMid = 185.0
x0 = xMid - 0.5 * xTot
y0 = 297.0 - yMid - 0.5 * yTot # 297 = A3_width
# Get border
edges = getEdges([shape])
border = edges[0]
for i in range(0, len(edges)):
border = border.oldFuse(edges[i])
border = border.oldFuse(edges[i].mirror(Vector(0.0, 0.0, 0.0),
Vector(0.0, 1.0, 0.0)))
# Fuse sections & borders
obj = border.oldFuse(sections)
# Send to 3D view
Part.show(obj)
objs = FreeCAD.ActiveDocument.Objects
obj = objs[len(objs) - 1]
# Create a new plane
FreeCAD.ActiveDocument.addObject('Drawing::FeaturePage',
'OutlineDrawPlot')
FreeCAD.ActiveDocument.OutlineDrawPlot.Template = (
FreeCAD.getResourceDir() + 'Mod/Drawing/Templates/A3_Landscape.svg')
# Side view
FreeCAD.ActiveDocument.addObject('Drawing::FeatureViewPart',
'OutlineDrawSideView')
FreeCAD.ActiveDocument.OutlineDrawSideView.Source = obj
FreeCAD.ActiveDocument.OutlineDrawSideView.Direction = (1.0, 0.0, 0.0)
FreeCAD.ActiveDocument.OutlineDrawSideView.Rotation = -90.0
FreeCAD.ActiveDocument.OutlineDrawSideView.Scale = scale
FreeCAD.ActiveDocument.OutlineDrawSideView.X = (
420.0 - x0 - 0.5 * scale * bounds[1]) # 420 = A3_height
FreeCAD.ActiveDocument.OutlineDrawSideView.Y = (
y0 + 0.5 * scale * bounds[2])
FreeCAD.ActiveDocument.OutlineDrawPlot.addObject(
FreeCAD.ActiveDocument.OutlineDrawSideView)
# Front view
FreeCAD.ActiveDocument.addObject('Drawing::FeatureViewPart',
'OutlineDrawFrontView')
FreeCAD.ActiveDocument.OutlineDrawFrontView.Source = obj
FreeCAD.ActiveDocument.OutlineDrawFrontView.Direction = (0.0, 1.0, 0.0)
FreeCAD.ActiveDocument.OutlineDrawFrontView.Rotation = -90.0
FreeCAD.ActiveDocument.OutlineDrawFrontView.Scale = scale
FreeCAD.ActiveDocument.OutlineDrawFrontView.X = (
420.0 - x0 - scale * bounds[1] - 32 - 0.5 * scale * bounds[0])
FreeCAD.ActiveDocument.OutlineDrawFrontView.Y = (
y0 + 0.5 * scale * bounds[2])
FreeCAD.ActiveDocument.OutlineDrawPlot.addObject(
FreeCAD.ActiveDocument.OutlineDrawFrontView)
# Up view
FreeCAD.ActiveDocument.addObject('Drawing::FeatureViewPart',
'OutlineDrawUpView')
FreeCAD.ActiveDocument.OutlineDrawUpView.Source = obj
FreeCAD.ActiveDocument.OutlineDrawUpView.Direction = (0.0, 0.0, 1.0)
FreeCAD.ActiveDocument.OutlineDrawUpView.Scale = scale
FreeCAD.ActiveDocument.OutlineDrawUpView.X = (
420.0 - x0 - scale * bounds[1] - 32 - 0.5 * scale * bounds[0])
FreeCAD.ActiveDocument.OutlineDrawUpView.Y = (
y0 + scale * bounds[2] + 32)
FreeCAD.ActiveDocument.OutlineDrawPlot.addObject(
FreeCAD.ActiveDocument.OutlineDrawUpView)
FreeCAD.ActiveDocument.recompute()
return obj
def getEdges(objs=None):
""" Returns object edges (list of them)
@param objs Object to get the faces, none if selected
object may used.
@return Selected edges. None if errors happens
"""
edges = []
if not objs:
objs = FreeCADGui.Selection.getSelection()
if not objs:
return None
for i in range(0, len(objs)):
obj = objs[i]
if obj.isDerivedFrom('Part::Feature'):
# get shape
shape = obj.Shape
if not shape:
return None
obj = shape
if not obj.isDerivedFrom('Part::TopoShape'):
return None
objEdges = obj.Edges
if not objEdges:
continue
for j in range(0, len(objEdges)):
edges.append(objEdges[j])
return edges
""" Returns object edges (a list of them)
@param objs Object to get the faces, none if the selected object may be
used.
@return Selected edges. None if errors happened
"""
edges = []
if not objs:
objs = FreeCADGui.Selection.getSelection()
if not objs:
return None
for i in range(0, len(objs)):
obj = objs[i]
if obj.isDerivedFrom('Part::Feature'):
# get shape
shape = obj.Shape
if not shape:
return None
obj = shape
if not obj.isDerivedFrom('Part::TopoShape'):
return None
objEdges = obj.Edges
if not objEdges:
continue
for j in range(0, len(objEdges)):
edges.append(objEdges[j])
return edges

View File

@@ -1,151 +1,151 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
# Qt library
from PyQt4 import QtGui,QtCore
# FreeCAD modules
import FreeCAD,FreeCADGui
from PySide import QtGui, QtCore
import FreeCAD
import FreeCADGui
from FreeCAD import Base, Vector
import Part
# FreeCADShip modules
import Units
from shipUtils import Paths
class Preview(object):
def __init__(self):
""" Constructor.
"""
self.obj = None
self.reinit()
def __init__(self):
""" Constructor. """
self.obj = None
self.reinit()
def reinit(self):
""" Reinitializate drawer.
"""
self.clean()
def reinit(self):
""" Reinitializate the drawer. """
self.clean()
def update(self, L, B, T, sectionsL, sectionsB, sectionsT, shape):
""" Update the 3D view printing annotations.
@param L Ship Lpp.
@param B Ship beam.
@param T Ship draft.
@param sectionsL Transversal sections.
@param sectionsB Longitudinal sections.
@param sectionsT Water lines.
@param shape Ship surfaces shell
@return Sections object. None if errors happens.
"""
msg = QtGui.QApplication.translate("ship_console", "Computing sections",
None,QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg + '...\n')
# Destroy all previous entities
self.clean()
# Receive data
nL = len(sectionsL)
nB = len(sectionsB)
nT = len(sectionsT)
if not (nL or nB or nT):
return None
# Found sections
sections = []
for i in range(0,nL):
pos = sectionsL[i]
# Cut ship
section = shape.slice(Vector(1.0,0.0,0.0), pos)
for j in range(0,len(section)):
edges = section[j].Edges
# We have 3 cases,
# * when section is before midship, then only starboard section will be considered
# * When section is midship, then all section must be preserved
# * When section is after midship, then only board will be considered
if pos > 0.01:
# Look for edges at the wrong side and delete it
for k in range(len(edges)-1,-1,-1):
edge = edges[k]
bbox = edge.BoundBox
if bbox.YMin < -0.001:
del edges[k]
elif pos < -0.01:
# Look for edges at the wrong side and delete it
for k in range(len(edges)-1,-1,-1):
edge = edges[k]
bbox = edge.BoundBox
if bbox.YMax > 0.001:
del edges[k]
sections.extend(edges)
for i in range(0,nB):
pos = sectionsB[i]
section = shape.slice(Vector(0.0,1.0,0.0), pos)
for j in range(0,len(section)):
edges = section[j].Edges
# Longitudinal sections will preserve board and starboard ever. Since we take from one side,
# we nned to mirror it.
section[j] = section[j].mirror(Vector(0.0, 0.0, 0.0),Vector(0.0, 1.0, 0.0))
edges2 = section[j].Edges
sections.extend(edges)
sections.extend(edges2)
for i in range(0,nT):
pos = sectionsT[i]
section = shape.slice(Vector(0.0,0.0,1.0), pos)
for j in range(0,len(section)):
edges = section[j].Edges
# We have 3 cases,
# * when section is below draft, then only board section will be considered
# * When section is draft, then all section must be preserved
# * When section is above draft, then only starboard will be considered
if pos > T + 0.01:
# Look for edges at the wrong side and delete it
for k in range(len(edges)-1,-1,-1):
edge = edges[k]
bbox = edge.BoundBox
if bbox.YMax > 0.001:
del edges[k]
elif pos < T - 0.01:
# Look for edges at the wrong side and delete it
for k in range(len(edges)-1,-1,-1):
edge = edges[k]
bbox = edge.BoundBox
if bbox.YMin < -0.001:
del edges[k]
sections.extend(edges)
# Convert all BSplines into a shape
if not sections:
msg = QtGui.QApplication.translate("ship_console", "Any valid ship section found",
None,QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintWarning(msg + '\n')
return
obj = sections[0]
for i in range(1,len(sections)):
obj = obj.oldFuse(sections[i]) # Only group the edges, don't try to build more complex entities
# Create the representable object
Part.show(obj)
objs = FreeCAD.ActiveDocument.Objects
self.obj = objs[len(objs)-1]
self.obj.Label = 'OutlineDraw'
return self.obj
def clean(self):
""" Erase all annotations from screen.
"""
if not self.obj:
return
FreeCAD.ActiveDocument.removeObject(self.obj.Name)
self.obj = None
def update(self, L, B, T, sectionsL, sectionsB, sectionsT, shape):
""" Update the 3D view annotations.
@param L Ship Lpp.
@param B Ship beam.
@param T Ship draft.
@param sectionsL Transversal sections.
@param sectionsB Longitudinal sections.
@param sectionsT Water lines.
@param shape Ship surfaces shell
@return Sections object. None if errors happens.
"""
msg = QtGui.QApplication.translate(
"ship_console",
"Computing sections",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg + '...\n')
# Destroy all previous entities
self.clean()
# Receive data
nL = len(sectionsL)
nB = len(sectionsB)
nT = len(sectionsT)
if not (nL or nB or nT):
return None
# Found sections
sections = []
for i in range(0, nL):
pos = sectionsL[i] * Units.Metre.Value
# Cut ship
section = shape.slice(Vector(1.0, 0.0, 0.0), pos)
for j in range(0, len(section)):
edges = section[j].Edges
# We have 3 cases,
# * when the section is before midship (starboard side drawn)
# * When the section is midship (both sides drawn)
# * When the section is after midship (board side drawn)
if pos > 0.01 * L * Units.Metre.Value:
for k in range(len(edges) - 1, -1, -1):
edge = edges[k]
bbox = edge.BoundBox
if bbox.YMin < -0.01 * B * Units.Metre.Value:
del edges[k]
elif pos < -0.01 * L * Units.Metre.Value:
for k in range(len(edges) - 1, -1, -1):
edge = edges[k]
bbox = edge.BoundBox
if bbox.YMax > 0.01 * B * Units.Metre.Value:
del edges[k]
sections.extend(edges)
for i in range(0, nB):
pos = sectionsB[i] * Units.Metre.Value
section = shape.slice(Vector(0.0, 1.0, 0.0), pos)
for j in range(0, len(section)):
edges = section[j].Edges
# The longitudinal sections are printed in both sides.
section[j] = section[j].mirror(Vector(0.0, 0.0, 0.0),
Vector(0.0, 1.0, 0.0))
edges2 = section[j].Edges
sections.extend(edges)
sections.extend(edges2)
for i in range(0, nT):
pos = sectionsT[i] * Units.Metre.Value
section = shape.slice(Vector(0.0, 0.0, 1.0), pos)
for j in range(0, len(section)):
edges = section[j].Edges
# We have 3 cases,
# * when the section is below draft (starboard side drawn)
# * When the section is draft (both sides drawn)
# * When the section is above draft (starboard side drawn)
if pos > T * 1.01 * Units.Metre.Value:
for k in range(len(edges) - 1, -1, -1):
edge = edges[k]
bbox = edge.BoundBox
if bbox.YMax > 0.01 * B * Units.Metre.Value:
del edges[k]
elif pos < T * 0.99 * Units.Metre.Value:
for k in range(len(edges) - 1, -1, -1):
edge = edges[k]
bbox = edge.BoundBox
if bbox.YMin < -0.01 * B * Units.Metre.Value:
del edges[k]
sections.extend(edges)
# Trabform and join all the BSplines into a shape
if not sections:
msg = QtGui.QApplication.translate(
"ship_console",
"Any valid ship section found",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintWarning(msg + '\n')
return
obj = sections[0]
for i in range(1, len(sections)):
# Just create a group of edges
obj = obj.oldFuse(sections[i])
Part.show(obj)
objs = FreeCAD.ActiveDocument.Objects
self.obj = objs[len(objs) - 1]
self.obj.Label = 'OutlineDraw'
return self.obj
def clean(self):
""" Erase all the annotations from the screen.
"""
if not self.obj:
return
FreeCAD.ActiveDocument.removeObject(self.obj.Name)
self.obj = None

View File

@@ -1,373 +1,504 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
# Qt library
from PyQt4 import QtGui,QtCore
# Module
import Preview, Plot
from PySide import QtGui, QtCore
import Preview
import Plot
import Instance
from shipUtils import Paths
class TaskPanel:
def __init__(self):
self.ui = Paths.modulePath() + "/shipOutlineDraw/TaskPanel.ui"
self.ship = None
self.skip = False
self.LSections = []
self.BSections = []
self.TSections = []
self.obj = None
self.preview = Preview.Preview()
def __init__(self):
self.ui = Paths.modulePath() + "/shipOutlineDraw/TaskPanel.ui"
self.ship = None
self.skip = False
self.LSections = []
self.BSections = []
self.TSections = []
self.obj = None
self.preview = Preview.Preview()
def accept(self):
self.saveSections()
self.obj = Plot.Plot(self.form.scale.value(), self.obj.Shape, self.ship.Shape)
self.preview.clean()
self.obj.Label = 'OutlineDraw'
return True
def accept(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.scale = self.widget(QtGui.QSpinBox, "Scale")
def reject(self):
self.preview.clean()
return True
self.saveSections()
self.obj = Plot.Plot(form.scale.value(),
self.obj.Shape,
self.ship.Shape)
self.preview.clean()
self.obj.Label = 'OutlineDraw'
return True
def clicked(self, index):
pass
def reject(self):
self.preview.clean()
return True
def open(self):
pass
def clicked(self, index):
pass
def needsFullSpace(self):
return True
def open(self):
pass
def isAllowedAlterSelection(self):
return False
def needsFullSpace(self):
return True
def isAllowedAlterView(self):
return True
def isAllowedAlterSelection(self):
return False
def isAllowedAlterDocument(self):
return False
def isAllowedAlterView(self):
return True
def helpRequested(self):
pass
def isAllowedAlterDocument(self):
return False
def setupUi(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.sections = form.findChild(QtGui.QTableWidget, "Sections")
try:
form.sections.setInputMethodHints(QtCore.Qt.ImhFormattedNumbersOnly)
hasImhFormattedNumbersOnly = True
except:
hasImhFormattedNumbersOnly = False
form.sectionType = form.findChild(QtGui.QComboBox, "SectionType")
form.deleteButton = form.findChild(QtGui.QPushButton, "DeleteButton")
form.nSections = form.findChild(QtGui.QSpinBox, "NSections")
form.createButton = form.findChild(QtGui.QPushButton, "CreateButton")
form.scale = form.findChild(QtGui.QSpinBox, "Scale")
self.form = form
# Initial values
if self.initValues():
return True
self.retranslateUi()
self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
# Connect Signals and Slots
QtCore.QObject.connect(form.sectionType,QtCore.SIGNAL("activated(QString)"),self.onSectionType)
QtCore.QObject.connect(form.sections,QtCore.SIGNAL("cellChanged(int,int)"),self.onTableItem);
QtCore.QObject.connect(form.deleteButton,QtCore.SIGNAL("pressed()"),self.onDeleteButton)
QtCore.QObject.connect(form.createButton,QtCore.SIGNAL("pressed()"),self.onCreateButton)
def helpRequested(self):
pass
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 setupUi(self):
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.sections = self.widget(QtGui.QTableWidget, "Sections")
try:
form.sections.setInputMethodHints(
QtCore.Qt.ImhFormattedNumbersOnly)
hasImhFormattedNumbersOnly = True
except:
hasImhFormattedNumbersOnly = False
form.sectionType = self.widget(QtGui.QComboBox, "SectionType")
form.deleteButton = self.widget(QtGui.QPushButton, "DeleteButton")
form.nSections = self.widget(QtGui.QSpinBox, "NSections")
form.createButton = self.widget(QtGui.QPushButton, "CreateButton")
form.scale = self.widget(QtGui.QSpinBox, "Scale")
self.form = form
# Initial values
if self.initValues():
return True
self.retranslateUi()
self.obj = self.preview.update(self.ship.Length,
self.ship.Breadth,
self.ship.Draft,
self.LSections,
self.BSections,
self.TSections,
self.ship.Shape)
# Connect Signals and Slots
QtCore.QObject.connect(
form.sectionType,
QtCore.SIGNAL("activated(QString)"),
self.onSectionType)
QtCore.QObject.connect(
form.sections,
QtCore.SIGNAL("cellChanged(int,int)"),
self.onTableItem)
QtCore.QObject.connect(
form.deleteButton,
QtCore.SIGNAL("pressed()"),
self.onDeleteButton)
QtCore.QObject.connect(
form.createButton,
QtCore.SIGNAL("pressed()"),
self.onCreateButton)
def initValues(self):
""" Set initial values for fields
"""
# Get selected objects
selObjs = Gui.Selection.getSelection()
if not selObjs:
msg = QtGui.QApplication.translate("ship_console",
"Ship instance must be selected (no object selected)",
None,QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
return True
for i in range(0,len(selObjs)):
obj = selObjs[i]
# Test if is a ship instance
props = obj.PropertiesList
try:
props.index("IsShip")
except ValueError:
continue
if obj.IsShip:
# Test if another ship already selected
if self.ship:
msg = QtGui.QApplication.translate("ship_console",
"More than one ship selected (extra ships will be neglected)",
None,QtGui.QApplication.UnicodeUTF8)
App.Console.PrintWarning(msg + '\n')
break
self.ship = obj
# Test if any valid ship was selected
if not self.ship:
msg = QtGui.QApplication.translate("ship_console",
"Ship instance must be selected (no valid ship found at selected objects)",
None,QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
return True
# Load sections (if exist)
self.loadSections()
return False
def getMainWindow(self):
toplevel = QtGui.qApp.topLevelWidgets()
for i in toplevel:
if i.metaObject().className() == "Gui::MainWindow":
return i
raise Exception("No main window found")
def retranslateUi(self):
""" Set user interface locale strings.
"""
self.form.setWindowTitle(QtGui.QApplication.translate("ship_outline","Outline draw",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QGroupBox, "AutoCreateBox").setTitle(QtGui.QApplication.translate("ship_outline","Auto create",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QGroupBox, "ScaleBox").setTitle(QtGui.QApplication.translate("ship_outline","Scale",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QPushButton, "DeleteButton").setText(QtGui.QApplication.translate("ship_outline",
"Delete all sections",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QPushButton, "CreateButton").setText(QtGui.QApplication.translate("ship_outline",
"Create sections",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(0, QtGui.QApplication.translate("ship_outline",
"Transversal",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(1, QtGui.QApplication.translate("ship_outline",
"Longitudinal",
None,QtGui.QApplication.UnicodeUTF8))
self.form.findChild(QtGui.QComboBox, "SectionType").setItemText(2, QtGui.QApplication.translate("ship_outline",
"Water lines",
None,QtGui.QApplication.UnicodeUTF8))
def widget(self, class_id, name):
"""Return the selected widget.
def onSectionType(self):
""" Function called when the section type is changed.
"""
# Search section type
ID = self.form.sectionType.currentIndex()
self.setSectionType(ID)
Keyword arguments:
class_id -- Class identifier
name -- Name of the widget
"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
return form.findChild(class_id, name)
def setSectionType(self, ID):
""" Function that set the type section related table.
@param ID Id of the section to set: \n
0 = Transversal sections \n
1 = Longitudinal sections \n
2 = Water lines
"""
SectionList = []
if ID == 0:
SectionList = self.LSections[:]
elif ID == 1:
SectionList = self.BSections[:]
elif ID == 2:
SectionList = self.TSections[:]
nRow = len(SectionList)
self.form.sections.clearContents()
self.form.sections.setRowCount(nRow+1)
if not nRow:
self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
return
self.skip = True # Avoid recursive call to OnItem
for i in range(0,nRow):
if i == nRow-1:
self.skip = False
string = '%f' % (SectionList[i])
item = QtGui.QTableWidgetItem(string)
self.form.sections.setItem(i,0,item)
def initValues(self):
""" Set initial values for fields
"""
# Get selected objects
selObjs = Gui.Selection.getSelection()
if not selObjs:
msg = QtGui.QApplication.translate(
"ship_console",
"A ship instance must be selected before use this tool (no"
" objects selected)",
None,
QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
return True
for i in range(0, len(selObjs)):
obj = selObjs[i]
# Test if is a ship instance
props = obj.PropertiesList
try:
props.index("IsShip")
except ValueError:
continue
if obj.IsShip:
# Test if another ship already selected
if self.ship:
msg = QtGui.QApplication.translate(
"ship_console",
"More than one ship has been selected (just the first"
" one will be used)",
None,
QtGui.QApplication.UnicodeUTF8)
App.Console.PrintWarning(msg + '\n')
break
self.ship = obj
# Test if any valid ship was selected
if not self.ship:
msg = QtGui.QApplication.translate(
"ship_console",
"A ship instance must be selected before use this tool (no"
"valid ships found in the selected objects)",
None,
QtGui.QApplication.UnicodeUTF8)
App.Console.PrintError(msg + '\n')
return True
# Load sections (if exist)
self.loadSections()
return False
def onTableItem(self, row, column):
""" Function called when an item of table is changed.
@param row Changed item row
@param column Changed item column
"""
if self.skip:
return
# Ensure that exist one empty item at least
nRow = self.form.sections.rowCount()
item = self.form.sections.item(nRow-1,0)
if item :
if(item.text() != ''):
self.form.sections.setRowCount(nRow+1)
# Ensure that new item is a number
ID = self.form.sectionType.currentIndex()
if ID == 0:
SectionList = self.LSections[:]
elif ID == 1:
SectionList = self.BSections[:]
elif ID == 2:
SectionList = self.TSections[:]
item = self.form.sections.item(row,column)
(number,flag) = item.text().toFloat()
if not flag:
if len(SectionList) > nRow-1:
number = SectionList[nRow-1]
else:
number = 0.0
string = '%f' % (number)
item.setText(string)
# Regenerate the list
SectionList = []
for i in range(0,nRow):
item = self.form.sections.item(i,0)
if item:
(number,flag) = item.text().toFloat()
SectionList.append(number)
# Paste it into the class list
ID = self.form.sectionType.currentIndex()
if ID == 0:
self.LSections = SectionList[:]
elif ID == 1:
self.BSections = SectionList[:]
elif ID == 2:
self.TSections = SectionList[:]
self.obj = self.preview.update(self.ship.Length, self.ship.Beam, self.ship.Draft, self.LSections,self.BSections,self.TSections, self.ship.Shape)
def onDeleteButton(self):
""" Function called when the delete button is pressed.
All sections mustt be erased
"""
self.form.sections.clearContents()
self.form.sections.setRowCount(1)
# Clear active list
ID = self.form.sectionType.currentIndex()
if ID == 0:
self.LSections = []
elif ID == 1:
self.BSections = []
elif ID == 2:
self.TSections = []
self.setSectionType(ID)
def onCreateButton(self):
""" Function called when create button is pressed.
Several sections must be added to list
"""
# Recolect data
nSections = self.form.nSections.value()
SectionList = []
L = 0.0
ID = self.form.sectionType.currentIndex()
if ID == 0:
L = self.ship.Length
d = L / (nSections-1) # Distance between sections
start = - L/2.0 # Ship must have 0.0 at coordinates origin
elif ID == 1:
L = -0.5*self.ship.Beam # Ship must be in y<0.0
d = L / (nSections+1.0) # Distance between sections
start = d
elif ID == 2:
L = self.ship.Draft
d = L / (nSections) # Distance between sections
start = d
# Calculate sections
for i in range(0,nSections):
sec = i*d + start
SectionList.append(sec)
# Paste into class table
if ID == 0:
self.LSections = SectionList[:]
elif ID == 1:
self.BSections = SectionList[:]
elif ID == 2:
self.TSections = SectionList[:]
# Print the table
self.setSectionType(ID)
def retranslateUi(self):
"""Set the user interface locale strings."""
self.form.setWindowTitle(QtGui.QApplication.translate(
"ship_outline",
"Outline draw",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QGroupBox, "AutoCreateBox").setTitle(
QtGui.QApplication.translate(
"ship_outline",
"Auto create",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QGroupBox, "ScaleBox").setTitle(
QtGui.QApplication.translate(
"ship_outline",
"Scale",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QPushButton, "DeleteButton").setText(
QtGui.QApplication.translate(
"ship_outline",
"Delete all sections",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QPushButton, "CreateButton").setText(
QtGui.QApplication.translate(
"ship_outline",
"Create sections",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QComboBox, "SectionType").setItemText(
0,
QtGui.QApplication.translate(
"ship_outline",
"Transversal",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QComboBox, "SectionType").setItemText(
1,
QtGui.QApplication.translate(
"ship_outline",
"Longitudinal",
None,
QtGui.QApplication.UnicodeUTF8))
self.widget(QtGui.QComboBox, "SectionType").setItemText(
2,
QtGui.QApplication.translate(
"ship_outline",
"Water lines",
None,
QtGui.QApplication.UnicodeUTF8))
def loadSections(self):
""" Loads from ship object previously selected sections.
"""
# Load sections
props = self.ship.PropertiesList
flag=True
try:
props.index("LSections")
except ValueError:
flag=False
if flag:
self.LSections = self.ship.LSections[:]
self.BSections = self.ship.BSections[:]
self.TSections = self.ship.TSections[:]
# Load scale too
flag=True
try:
props.index("PlotScale")
except ValueError:
flag=False
if flag:
self.form.scale.setValue(self.ship.PlotScale)
# Set UI
self.setSectionType(self.form.sectionType.currentIndex())
def onSectionType(self):
""" Function called when the section type is changed.
"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.sectionType = self.widget(QtGui.QComboBox, "SectionType")
ID = form.sectionType.currentIndex()
self.setSectionType(ID)
def setSectionType(self, ID):
""" Set the table depending on the selected section type.
@param ID Id of the section type to set:
- 0 = Transversal sections
- 1 = Longitudinal sections
- 2 = Water lines
"""
SectionList = []
if ID == 0:
SectionList = self.LSections[:]
elif ID == 1:
SectionList = self.BSections[:]
elif ID == 2:
SectionList = self.TSections[:]
nRow = len(SectionList)
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.sections = self.widget(QtGui.QTableWidget, "Sections")
form.sections.clearContents()
form.sections.setRowCount(nRow + 1)
self.skip = True
for i in range(0, nRow):
string = '{0}'.format(SectionList[i])
item = QtGui.QTableWidgetItem(string)
form.sections.setItem(i, 0, item)
self.skip = False
self.obj = self.preview.update(self.ship.Length,
self.ship.Breadth,
self.ship.Draft,
self.LSections,
self.BSections,
self.TSections,
self.ship.Shape)
def onTableItem(self, row, column):
""" Function called when an item of the table is touched.
@param row Changed item row
@param column Changed item column
"""
if self.skip:
return
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.sections = self.widget(QtGui.QTableWidget, "Sections")
form.sectionType = self.widget(QtGui.QComboBox, "SectionType")
nRow = form.sections.rowCount()
item = form.sections.item(nRow - 1, 0)
if item:
if(item.text() != ''):
form.sections.setRowCount(nRow + 1)
# Ensure that the new introduced item is a number
ID = form.sectionType.currentIndex()
if ID == 0:
SectionList = self.LSections[:]
elif ID == 1:
SectionList = self.BSections[:]
elif ID == 2:
SectionList = self.TSections[:]
item = form.sections.item(row, column)
(number, flag) = item.text().toFloat()
if not flag:
if len(SectionList) > nRow - 1:
number = SectionList[nRow - 1]
else:
number = 0.0
string = '{0}'.format(number)
item.setText(string)
# Regenerate the list
SectionList = []
for i in range(0, nRow):
item = form.sections.item(i, 0)
if item:
(number, flag) = item.text().toFloat()
SectionList.append(number)
# Paste it into the section type list
ID = form.sectionType.currentIndex()
if ID == 0:
self.LSections = SectionList[:]
elif ID == 1:
self.BSections = SectionList[:]
elif ID == 2:
self.TSections = SectionList[:]
self.obj = self.preview.update(self.ship.Length,
self.ship.Breadth,
self.ship.Draft,
self.LSections,
self.BSections,
self.TSections,
self.ship.Shape)
def onDeleteButton(self):
""" Function called when the delete button is pressed.
All the sections of the active type must be erased therefore.
"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.sections = self.widget(QtGui.QTableWidget, "Sections")
form.sectionType = self.widget(QtGui.QComboBox, "SectionType")
form.sections.clearContents()
form.sections.setRowCount(1)
ID = form.sectionType.currentIndex()
if ID == 0:
self.LSections = []
elif ID == 1:
self.BSections = []
elif ID == 2:
self.TSections = []
self.setSectionType(ID)
def onCreateButton(self):
""" Function called when automatic creating button is pressed.
Several sections must be added to the active sections list
"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.sectionType = self.widget(QtGui.QComboBox, "SectionType")
form.nSections = self.widget(QtGui.QSpinBox, "NSections")
# Recolect data
nSections = form.nSections.value()
SectionList = []
L = 0.0
ID = form.sectionType.currentIndex()
if ID == 0:
L = self.ship.Length
d = L / (nSections - 1)
start = - L / 2.0
elif ID == 1:
L = -0.5 * self.ship.Breadth
d = L / (nSections + 1)
start = d
elif ID == 2:
L = self.ship.Draft
d = L / (nSections)
start = d
# Compute the sections positions
for i in range(0, nSections):
sec = i * d + start
SectionList.append(sec)
# Paste it into the corresponding section list
if ID == 0:
self.LSections = SectionList[:]
elif ID == 1:
self.BSections = SectionList[:]
elif ID == 2:
self.TSections = SectionList[:]
self.setSectionType(ID)
def loadSections(self):
""" Loads from the ship object all the previously selected sections.
"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.sectionType = self.widget(QtGui.QComboBox, "SectionType")
form.scale = self.widget(QtGui.QSpinBox, "Scale")
# Load sections
props = self.ship.PropertiesList
flag = True
try:
props.index("LSections")
except ValueError:
flag = False
if flag:
self.LSections = self.ship.LSections[:]
self.BSections = self.ship.BSections[:]
self.TSections = self.ship.TSections[:]
# Load scale too
flag = True
try:
props.index("PlotScale")
except ValueError:
flag = False
if flag:
form.scale.setValue(self.ship.PlotScale)
# Set UI
self.setSectionType(form.sectionType.currentIndex())
def saveSections(self):
""" Save the selected sections into ship object.
"""
mw = self.getMainWindow()
form = mw.findChild(QtGui.QWidget, "TaskPanel")
form.scale = self.widget(QtGui.QSpinBox, "Scale")
props = self.ship.PropertiesList
try:
props.index("LSections")
except ValueError:
tooltip = str(QtGui.QApplication.translate(
"ship_outline",
"Transversal section positions [m]",
None,
QtGui.QApplication.UnicodeUTF8))
self.ship.addProperty("App::PropertyFloatList",
"LSections",
"Ship",
tooltip).LSections = []
tooltip = str(QtGui.QApplication.translate(
"ship_outline",
"Longitudinal section positions [m]",
None,
QtGui.QApplication.UnicodeUTF8))
self.ship.addProperty("App::PropertyFloatList",
"BSections",
"Ship",
tooltip).BSections = []
tooltip = str(QtGui.QApplication.translate(
"ship_outline",
"Water line positions [m]",
None,
QtGui.QApplication.UnicodeUTF8))
self.ship.addProperty("App::PropertyFloatList",
"TSections",
"Ship",
tooltip).TSections = []
# Save the sections
self.ship.LSections = self.LSections[:]
self.ship.BSections = self.BSections[:]
self.ship.TSections = self.TSections[:]
# Save the scale as well
try:
props.index("PlotScale")
except ValueError:
tooltip = str(QtGui.QApplication.translate(
"ship_outline",
"Plot scale (1:scale format)",
None,
QtGui.QApplication.UnicodeUTF8))
self.ship.addProperty("App::PropertyInteger",
"PlotScale",
"Ship",
tooltip).PlotScale = 250
self.ship.PlotScale = form.scale.value()
def saveSections(self):
""" Save selected sections into ship object.
"""
# Test if previous section have been created
props = self.ship.PropertiesList
try:
props.index("LSections")
except ValueError:
# Create new sections list
tooltip = str(QtGui.QApplication.translate("ship_outline","Transversal sections position [m]",
None,QtGui.QApplication.UnicodeUTF8))
self.ship.addProperty("App::PropertyFloatList","LSections","Ship", tooltip).LSections=[]
tooltip = str(QtGui.QApplication.translate("ship_outline","Longitudinal sections position [m]",
None,QtGui.QApplication.UnicodeUTF8))
self.ship.addProperty("App::PropertyFloatList","BSections","Ship", tooltip).BSections=[]
tooltip = str(QtGui.QApplication.translate("ship_outline","Water lines position [m]",
None,QtGui.QApplication.UnicodeUTF8))
self.ship.addProperty("App::PropertyFloatList","TSections","Ship", tooltip).TSections=[]
# Save sections
self.ship.LSections = self.LSections[:]
self.ship.BSections = self.BSections[:]
self.ship.TSections = self.TSections[:]
# Save also scale
try:
props.index("PlotScale")
except ValueError:
tooltip = str(QtGui.QApplication.translate("ship_outline","Plot scale (1:scale format)",
None,QtGui.QApplication.UnicodeUTF8))
self.ship.addProperty("App::PropertyInteger","PlotScale","Ship", tooltip).PlotScale=250
self.ship.PlotScale = self.form.scale.value()
def createTask():
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel
panel = TaskPanel()
Gui.Control.showDialog(panel)
if panel.setupUi():
Gui.Control.closeDialog(panel)
return None
return panel

View File

@@ -1,36 +1,29 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* 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()
""" Loads the tool """
TaskPanel.createTask()

View File

@@ -36,7 +36,7 @@ def modulePath():
def iconsPath():
"""returns the current Ship design module icons path
@return Icons path"""
path = modulePath() + "/resources/icons"
path = modulePath() + "/Resources/icons"
return path
def getPathFromFile(fileName):

View File

@@ -75,8 +75,8 @@ class TaskPanel:
App.Console.PrintMessage(msg + "...\n")
# Build simulation thread
simulator = Sim(device, endTime, output, self.sim, FSMesh, FSData, waves, SeaNx, SeaNy)
simulator.start() # Activate me for final release
# simulator.run() # Activate me for development (i will show python fails)
# simulator.start() # Activate me for final release
simulator.run() # Activate me for development (I will show python fails)
msg = QtGui.QApplication.translate("ship_console","Done",
None,QtGui.QApplication.UnicodeUTF8)
App.Console.PrintMessage(msg + "!\n")

View File

@@ -45,8 +45,8 @@ class simBEMSolver_cl:
potentials for the other ones).
@param bem Boundary Element Method instance.
"""
"""
[bem['gradp'], r, iters] = self.solver.solve(bem['A'], bem['B'], bem['gradp'])
# Take care, LSQR expects that x0 = 0
[bem['gradp'], r, iters] = self.solver.solve(bem['A'], bem['B'])
if(iters >= 300):
FreeCAD.Console.PrintError("\t\t[Sim]: Solving velocity potentials.\n")
FreeCAD.Console.PrintError("\t\t\tSolutions seems don't convergs after 300 iterations (%g residual)\n" % (r))
@@ -58,4 +58,4 @@ class simBEMSolver_cl:
if(rank < bem['N']):
FreeCAD.Console.PrintError("\t\t[Sim]: Solving velocity potentials.\n")
FreeCAD.Console.PrintError("\t\t\tEffective rank of linear system matrix is {0} (N = {1})\n".format(rank, bem['N']))
"""

View File

@@ -48,11 +48,29 @@ class jacobi:
self.B = None
self.X0 = None
self.X = None
self.R = None
self.x = None
self.n = 0
# Create dot operator
self.dot = ReductionKernel(context, np.float32, neutral="0",
reduce_expr="a+b", map_expr="x[i]*y[i]",
arguments="__global float *x, __global float *y")
# self.dot = ReductionKernel(context, np.float32, neutral="0",
# reduce_expr="a+b", map_expr="x[i]*y[i]",
# arguments="__global float *x, __global float *y")
def rnorm2(self, X):
""" Compute the norm square of the residuals.
@param X Result of the last iteration (pyopencl.array object).
@return norm square of the residuals.
"""
n = np.uint32(self.n)
gSize = (clUtils.globalSize(n),)
kernelargs = (self.A,
self.B.data,
X.data,
self.R.data,
n)
# Test if the final result has been reached
self.program.r(self.queue, gSize, None, *(kernelargs))
return cl_array.dot(self.R,self.R).get()
def solve(self, A, B, x0=None, tol=10e-6, iters=300, w=1.0):
r""" Solve linear system of equations by a Jacobi
@@ -64,7 +82,8 @@ class jacobi:
\$ \vert\vert B - A \, x \vert \vert_\infty /
\vert\vert B \vert \vert_\infty \$
@param iters Maximum number of iterations.
@param w Relaxation factor
@param w Relaxation factor (could be autoupdated
if the method diverges)
"""
# Create/set OpenCL buffers
w = np.float32(w)
@@ -73,47 +92,47 @@ class jacobi:
n = np.uint32(len(B))
gSize = (clUtils.globalSize(n),)
# Get a norm to can compare later for valid result
B_cl = cl_array.to_device(self.context,self.queue,B)
bnorm2 = self.dot(B_cl,B_cl).get()
w = w / bnorm2
bnorm2 = cl_array.dot(self.B,self.B).get()
FreeCAD.Console.PrintMessage(bnorm2)
FreeCAD.Console.PrintMessage("\n")
rnorm2 = 0.
# Iterate while the result converges or maximum number
# of iterations is reached.
for i in range(0,iters):
kernelargs = (self.A,
self.B,
self.X0,
self.X,
n)
# Test if the final result has been reached
self.program.r(self.queue, gSize, None, *(kernelargs))
cl.enqueue_read_buffer(self.queue, self.X, self.x).wait()
x_cl = cl_array.to_device(self.context,self.queue,self.x)
rnorm2 = self.dot(x_cl,x_cl).get()
rnorm2 = self.rnorm2(self.X0)
FreeCAD.Console.PrintMessage("\t")
FreeCAD.Console.PrintMessage(rnorm2)
FreeCAD.Console.PrintMessage(" -> ")
FreeCAD.Console.PrintMessage(rnorm2 / bnorm2)
FreeCAD.Console.PrintMessage("\n")
if np.sqrt(rnorm2 / bnorm2) <= tol:
break
# Iterate
kernelargs = (self.A,
self.B,
self.X0,
self.X,
self.B.data,
self.X0.data,
self.X.data,
w,
n)
self.program.jacobi(self.queue, gSize, None, *(kernelargs))
# Test if the result is diverging
temp_rnorm2 = self.rnorm2(self.X)
if(temp_rnorm2 > rnorm2):
FreeCAD.Console.PrintMessage("\t\tDivergence found...\n\t\tw = ")
w = w * rnorm2 / temp_rnorm2
FreeCAD.Console.PrintMessage(w)
FreeCAD.Console.PrintMessage("\n")
# Discard the result
continue
kernelargs = (self.A,
self.B,
self.X,
self.X0,
self.B.data,
self.X.data,
self.X0.data,
w,
n)
self.program.jacobi(self.queue, gSize, None, *(kernelargs))
# Return result computed
cl.enqueue_read_buffer(self.queue, self.X0, self.x).wait()
cl.enqueue_read_buffer(self.queue, self.X0.data, self.x).wait()
return (np.copy(self.x), np.sqrt(rnorm2 / bnorm2), i)
def setBuffers(self, A,B,x0):
@@ -141,15 +160,17 @@ class jacobi:
if not self.A:
mf = cl.mem_flags
self.A = cl.Buffer( self.context, mf.READ_ONLY, size = n*n * np.dtype('float32').itemsize )
self.B = cl.Buffer( self.context, mf.READ_ONLY, size = n * np.dtype('float32').itemsize )
self.X0 = cl.Buffer( self.context, mf.READ_WRITE, size = n * np.dtype('float32').itemsize )
self.X = cl.Buffer( self.context, mf.READ_WRITE, size = n * np.dtype('float32').itemsize )
self.B = cl_array.zeros(self.context,self.queue, (n), np.float32)
self.X0 = cl_array.zeros(self.context,self.queue, (n), np.float32)
self.X = cl_array.zeros(self.context,self.queue, (n), np.float32)
self.R = cl_array.zeros(self.context,self.queue, (n), np.float32)
self.x = np.zeros((n), dtype=np.float32)
self.n = n
# Transfer data to buffers
events = []
events.append(cl.enqueue_write_buffer(self.queue, self.A, A.reshape((n*n)) ))
events.append(cl.enqueue_write_buffer(self.queue, self.B, B))
events.append(cl.enqueue_write_buffer(self.queue, self.X0, x0))
events.append(cl.enqueue_write_buffer(self.queue, self.B.data, B))
events.append(cl.enqueue_write_buffer(self.queue, self.X0.data, x0))
for e in events:
e.wait()

View File

@@ -1,24 +1,24 @@
#***************************************************************************
#* *
#* Copyright (c) 2011, 2012 *
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
#* *
#* *
#* 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 *
#* 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 *
#* *
#* USA *
#* *
#***************************************************************************
# numpy
@@ -46,14 +46,11 @@ class lsqr:
# Create OpenCL objects as null objects, that we will generate
# at the first iteration
self.A = None
self.B = None
self.X0 = None
self.X = None
self.R = None
# Create dot operator
self.dot = ReductionKernel(context, np.float32, neutral="0",
reduce_expr="a+b", map_expr="x[i]*y[i]",
arguments="__global float *x, __global float *y")
self.b = None
self.x0 = None
self.x = None
self.r = None
# Create some useful operators
self.dot_c_vec = ElementwiseKernel(context,
"float c, float *v",
"v[i] *= c")
@@ -66,42 +63,66 @@ class lsqr:
"float b, float *y",
"z[i] = a*x[i] + b*y[i]")
self.prod = ElementwiseKernel(context,
"float* z,"
"float *z,"
"float *x, float *y",
"z[i] = x[i]*y[i]")
def solve(self, A, B, x0=None, tol=10e-6, iters=300):
def symOrtho(self, a, b):
""" Computes the radius, cosine, and sine for the
orthogonal transformation.
@param a x vector.
@param b y vector.
@return [c,s,r]. Cosine value, Sine value, and the radius.
"""
s = 0
c = 0
r = 0
if not b:
r = np.abs(a)
c = np.copysign(1,0,a)
elif not a:
r = np.abs(b)
s = np.copysign(1,0,b)
elif np.abs(b) > np.abs(a):
t = a / b
s = np.copysign(1.0,b) / np.sqrt(1.0 + t**2)
c = s * t
r = b / s
else:
t = b / a
c = np.copysign(1.0,a) / np.sqrt(1.0 + t**2)
s = c * t
r = a / c
return [c,s,r]
def solve(self, A, b, x0=None, tol=10e-5, iters=300):
r""" Solve linear system of equations by a Jacobi
iterative method.
@param A Linear system matrix.
@param B Linear system independent term.
@param b Linear system independent term.
@param x0 Initial aproximation of the solution.
@param tol Relative error tolerance: \n
\$ \vert\vert B - A \, x \vert \vert_\infty /
\vert\vert B \vert \vert_\infty \$
\$ \vert\vert b - A \, x \vert \vert_\infty /
\vert\vert b \vert \vert_\infty \$
@param iters Maximum number of iterations.
"""
# Create/set OpenCL buffers
self.setBuffers(A,B,x0)
self.setBuffers(A,b,x0)
# Get dimensions for OpenCL execution
n = np.uint32(len(B))
n = np.uint32(len(b))
gSize = (clUtils.globalSize(n),)
# Preconditionate matrix
self.precondition(n)
# Get a norm to can compare later for valid result
bnorm = np.sqrt(self.dot(self.b,self.b).get())
FreeCAD.Console.PrintMessage(bnorm)
FreeCAD.Console.PrintMessage("\n")
bnorm = np.sqrt(cl_array.dot(self.b,self.b).get())
# Initialize the problem
beta = bnorm
self.dot_c_vec(1.0/beta, self.u)
kernelargs = (self.A,self.u.data,self.v.data,n)
self.program.dot_matT_vec(self.queue, gSize, None, *(kernelargs))
alpha = np.sqrt(self.dot(self.v,self.v).get())
alpha = np.sqrt(cl_array.dot(self.v,self.v).get())
self.dot_c_vec(1.0/alpha, self.v)
self.copy_vec(self.w, self.v)
rhobar = alpha
phibar = beta
rhobar = alpha
# Iterate while the result converges or maximum number
# of iterations is reached.
for i in range(0,iters):
@@ -112,50 +133,41 @@ class lsqr:
self.r.data,
n)
self.program.r(self.queue, gSize, None, *(kernelargs))
rnorm = np.sqrt(self.dot(self.r,self.r).get())
FreeCAD.Console.PrintMessage("\t")
FreeCAD.Console.PrintMessage(rnorm)
FreeCAD.Console.PrintMessage("\n")
rnorm = np.sqrt(cl_array.dot(self.r,self.r).get())
# Test if the final result has been reached
if rnorm / bnorm <= tol:
break
# Compute next alpha, beta, u, v
kernelargs = (self.A,self.u.data,self.v.data,self.u.data,alpha,n)
self.program.u(self.queue, gSize, None, *(kernelargs))
beta = np.sqrt(self.dot(self.u,self.u).get())
FreeCAD.Console.PrintMessage("\t beta=")
FreeCAD.Console.PrintMessage(beta)
FreeCAD.Console.PrintMessage("\n")
beta = np.sqrt(cl_array.dot(self.u,self.u).get())
if not beta:
break
self.dot_c_vec(1.0/beta, self.u)
kernelargs = (self.A,self.u.data,self.v.data,self.v.data,beta,n)
self.program.v(self.queue, gSize, None, *(kernelargs))
alpha = np.sqrt(self.dot(self.v,self.v).get())
FreeCAD.Console.PrintMessage("\t alpha=")
FreeCAD.Console.PrintMessage(alpha)
FreeCAD.Console.PrintMessage("\n")
alpha = np.sqrt(cl_array.dot(self.v,self.v).get())
if not alpha:
break
self.dot_c_vec(1.0/alpha, self.v)
# Apply the orthogonal transformation
rho = np.sqrt(rhobar*rhobar + beta*beta)
c = rhobar/rho
s = beta*rho
theta = s*alpha
rhobar = -c*alpha
phi = c*phibar
phibar = s*phibar
c,s,rho = self.symOrtho(rhobar,beta)
theta = s * alpha
rhobar = -c * alpha
phi = c * phibar
phibar = s * phibar
# Update x and w
self.linear_comb(self.x, 1, self.x, phi/rho, self.w)
self.linear_comb(self.w, 1, self.v, theta/rho, self.w)
# Correct returned result due to the precoditioning
self.prod(self.x, self.xf, self.x)
self.linear_comb(self.x, 1.0, self.x, phi/rho, self.w)
self.linear_comb(self.w, 1.0, self.v, -theta/rho, self.w)
# Return result computed
x = np.zeros((n), dtype=np.float32)
cl.enqueue_read_buffer(self.queue, self.x.data, x).wait()
return (x, rnorm / bnorm, i)
return (x, rnorm / bnorm, i+1)
def setBuffers(self, A,B,x0):
def setBuffers(self, A,b,x0):
""" Create/set OpenCL required buffers.
@param A Linear system matrix.
@param B Independent linear term.
@param b Independent linear term.
@param x0 Initial solution estimator.
"""
# Get dimensions
@@ -164,22 +176,20 @@ class lsqr:
raise ValueError, 'Matrix A must be 2 dimensional array'
if shape[0] != shape[1]:
raise ValueError, 'Square linear system matrix expected'
if len(B) != shape[0]:
raise ValueError, 'Matrix and independet term dimensions does not match'
n = len(B)
if len(b) != shape[0]:
raise ValueError, 'Matrix and independet term dimensions must match'
n = len(b)
# Set x0 if not provided
if x0 != None:
if len(x0) != n:
raise ValueError, 'Initial solution estimator length does not match with linear system dimensions'
if x0 == None:
x0 = B
x0 = np.zeros((n), dtype=np.float32)
if len(x0) != n:
raise ValueError, 'Initial solution estimator length does not match with linear system dimensions'
# Create OpenCL objects if not already generated
if not self.A:
mf = cl.mem_flags
self.A = cl.Buffer( self.context, mf.READ_WRITE, size = n*n * np.dtype('float32').itemsize )
self.b = cl_array.zeros(self.context,self.queue, (n), np.float32)
self.x = cl_array.zeros(self.context,self.queue, (n), np.float32)
self.xf = cl_array.zeros(self.context,self.queue, (n), np.float32)
self.r = cl_array.zeros(self.context,self.queue, (n), np.float32)
self.u = cl_array.zeros(self.context,self.queue, (n), np.float32)
self.v = cl_array.zeros(self.context,self.queue, (n), np.float32)
@@ -187,43 +197,9 @@ class lsqr:
# Transfer data to buffers
events = []
events.append(cl.enqueue_write_buffer(self.queue, self.A, A.reshape((n*n)) ))
self.b.set(B)
self.b.set(b)
self.x.set(x0)
self.u.set(B)
self.u.set(b)
for e in events:
e.wait()
def precondition(self, n):
""" Preconditionate matrix, ensuring that all linear system
matrix columns has an acceptable norm. Of course, final
solution vector must be corrected conveniently.
@param n Linear system dimension.
"""
gSize = (clUtils.globalSize(n),)
xf = np.ones((n), dtype=np.float32)
for i in range(0,n):
col = np.uint32(i)
# Compute column norm
# We can use v as column vector because has not been used yet
kernelargs = (self.A,
self.v.data,
col,
n)
self.program.column(self.queue, gSize, None, *(kernelargs))
norm = np.sqrt(self.dot(self.v,self.v).get())
FreeCAD.Console.PrintMessage("col ")
FreeCAD.Console.PrintMessage(i)
FreeCAD.Console.PrintMessage(", norm=")
FreeCAD.Console.PrintMessage(norm)
FreeCAD.Console.PrintMessage("\n")
if norm < 1.0:
continue
fact = np.float32(1.0/norm)
xf[i] = fact
kernelargs = (self.A,
fact,
col,
n)
self.program.prod_c_column(self.queue, gSize, None, *(kernelargs))
self.x.set(xf)

View File

@@ -45,7 +45,7 @@ def path():
""" Gets the OpenCL kernels path
@return OpenCL kernels path
"""
path = Paths.modulePath() + "/resources/opencl"
path = Paths.modulePath() + "/Resources/opencl"
return path
def globalSize(n):

View File

@@ -67,22 +67,23 @@ class simEvolution_cl:
bem['dpdt'][i*ny+j] = - 0.5 * gradp**2.0 - 9.81*z
fs['vel'][i,j,2] = gradp
# Since the inverse method returns significant errors near
# to the free surface borders, we will modify 3 area
# to the free surface borders, we will modify "nBC" area
# elements of the border such that the last one will be
# exactly the analytic solution. Also we will use it as
# numerical beach in order to disipate waves generated
# inside the domain (that will be refelceted otherwise)
nBC = 10
# 1.- Corners
for i in range(0,4)+range(nx-4,nx):
if i in range(0,4):
fx = 1. - i/4.
for i in range(0,nBC)+range(nx-nBC,nx):
if i in range(0,nBC):
fx = 1. - i/float(nBC)
else:
fx = (i - nx + 5) / 4.
for j in range(0,4)+range(ny-4,ny):
if j in range(0,4):
fy = 1. - j/4.
fx = (i - nx + nBC+1.) / nBC
for j in range(0,nBC)+range(ny-nBC,ny):
if j in range(0,nBC):
fy = 1. - j/float(nBC)
else:
fy = (j - ny + 5) / 4.
fy = (j - ny + nBC+1.) / nBC
factor = max(fx,fy)
pos = fs['pos'][i,j]
dpdt = 0.
@@ -103,12 +104,12 @@ class simEvolution_cl:
bem['dpdt'][i*ny+j] = factor*dpdt + (1.-factor)*bem['dpdt'][i*ny+j]
fs['vel'][i,j,2] = factor*vel + (1.-factor)*fs['vel'][i,j,2]
# 2.- rows
for i in range(0,4)+range(nx-4,nx):
if i in range(0,4):
factor = 1. - i/4.
for i in range(0,nBC)+range(nx-nBC,nx):
if i in range(0,nBC):
factor = 1. - i/float(nBC)
else:
factor = (i - nx + 5) / 4.
for j in range(4, ny-4):
factor = (i - nx + nBC+1.) / nBC
for j in range(nBC, ny-nBC):
pos = fs['pos'][i,j]
dpdt = 0.
vel = 0.
@@ -128,12 +129,12 @@ class simEvolution_cl:
bem['dpdt'][i*ny+j] = factor*dpdt + (1.-factor)*bem['dpdt'][i*ny+j]
fs['vel'][i,j,2] = factor*vel + (1.-factor)*fs['vel'][i,j,2]
# 3.- columns
for j in range(0,4)+range(ny-4,ny):
if j in range(0,4):
factor = 1. - j/4.
for j in range(0,nBC)+range(ny-nBC,ny):
if j in range(0,nBC):
factor = 1. - j/float(nBC)
else:
factor = (j - ny + 5) / 4.
for i in range(4, nx-4):
factor = (j - ny + nBC+1.) / nBC
for i in range(nBC, nx-nBC):
pos = fs['pos'][i,j]
dpdt = 0.
vel = 0.
@@ -169,22 +170,23 @@ class simEvolution_cl:
bem['p'][i*ny+j] = bem['p'][i*ny+j] + dt * bem['dpdt'][i*ny+j]
fs['pos'][i,j,2] = fs['pos'][i,j,2] + dt * fs['vel'][i,j,2]
# Since the inverse method returns significant errors near
# to the free surface borders, we will modify 3 area
# to the free surface borders, we will modify "nBC" area
# elements of the border such that the last one will be
# exactly the analytic solution. Also we will use it as
# numerical beach in order to disipate waves generated
# inside the domain (that will be refelceted otherwise)
nBC = 10
# 1.- Corners
for i in range(0,4)+range(nx-4,nx):
if i in range(0,4):
fx = 1. - i/4.
for i in range(0,nBC)+range(nx-nBC,nx):
if i in range(0,nBC):
fx = 1. - i/float(nBC)
else:
fx = (i - nx + 5) / 4.
for j in range(0,4)+range(ny-4,ny):
if j in range(0,4):
fy = 1. - j/4.
fx = (i - nx + nBC+1.) / nBC
for j in range(0,nBC)+range(ny-nBC,ny):
if j in range(0,nBC):
fy = 1. - j/float(nBC)
else:
fy = (j - ny + 5) / 4.
fy = (j - ny + nBC+1.) / nBC
factor = max(fx,fy)
pos = fs['pos'][i,j]
phi = 0.
@@ -205,12 +207,12 @@ class simEvolution_cl:
bem['p'][i*ny+j] = factor*phi + (1.-factor)*bem['p'][i*ny+j]
fs['pos'][i,j,2] = factor*z + (1.-factor)*fs['pos'][i,j,2]
# 2.- rows
for i in range(0,4)+range(nx-4,nx):
if i in range(0,4):
factor = 1. - i/4.
for i in range(0,nBC)+range(nx-nBC,nx):
if i in range(0,nBC):
factor = 1. - i/float(nBC)
else:
factor = (i - nx + 5) / 4.
for j in range(4, ny-4):
factor = (i - nx + nBC+1.) / nBC
for j in range(nBC, ny-nBC):
pos = fs['pos'][i,j]
phi = 0.
z = 0.
@@ -230,12 +232,12 @@ class simEvolution_cl:
bem['p'][i*ny+j] = factor*phi + (1.-factor)*bem['p'][i*ny+j]
fs['pos'][i,j,2] = factor*z + (1.-factor)*fs['pos'][i,j,2]
# 3.- columns
for j in range(0,4)+range(ny-4,ny):
if j in range(0,4):
factor = 1. - j/4.
for j in range(0,nBC)+range(ny-nBC,ny):
if j in range(0,nBC):
factor = 1. - j/float(nBC)
else:
factor = (j - ny + 5) / 4.
for i in range(4, nx-4):
factor = (j - ny + nBC+1.) / nBC
for i in range(nBC, nx-nBC):
pos = fs['pos'][i,j]
phi = 0.
z = 0.

Binary file not shown.