From 892b5b9494486ad4058d5935949f9be334002b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Sun, 29 Jan 2012 18:17:37 +0100 Subject: [PATCH] Created transversal areas curve plot tool --- src/Mod/Ship/CMakeLists.txt | 1 + src/Mod/Ship/Makefile.am | 1 + src/Mod/Ship/shipAreasCurve/Plot.py | 211 +++++++++++++++++++++++ src/Mod/Ship/shipAreasCurve/TaskPanel.py | 9 +- 4 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 src/Mod/Ship/shipAreasCurve/Plot.py diff --git a/src/Mod/Ship/CMakeLists.txt b/src/Mod/Ship/CMakeLists.txt index 9f86e5e4af..7d5794e624 100644 --- a/src/Mod/Ship/CMakeLists.txt +++ b/src/Mod/Ship/CMakeLists.txt @@ -51,6 +51,7 @@ SOURCE_GROUP("shipoutlinedraw" FILES ${ShipOutlineDraw_SRCS}) SET(ShipAreasCurve_SRCS shipAreasCurve/__init__.py + shipAreasCurve/Plot.py shipAreasCurve/Preview.py shipAreasCurve/TaskPanel.py shipAreasCurve/TaskPanel.ui diff --git a/src/Mod/Ship/Makefile.am b/src/Mod/Ship/Makefile.am index ed2efda8dc..113b0f04f6 100644 --- a/src/Mod/Ship/Makefile.am +++ b/src/Mod/Ship/Makefile.am @@ -40,6 +40,7 @@ nobase_data_DATA = \ shipOutlineDraw/TaskPanel.py \ shipOutlineDraw/TaskPanel.ui \ shipAreasCurve/__init__.py \ + shipAreasCurve/Plot.py \ shipAreasCurve/Preview.py \ shipAreasCurve/TaskPanel.py \ shipAreasCurve/TaskPanel.ui \ diff --git a/src/Mod/Ship/shipAreasCurve/Plot.py b/src/Mod/Ship/shipAreasCurve/Plot.py new file mode 100644 index 0000000000..6e0fdb5362 --- /dev/null +++ b/src/Mod/Ship/shipAreasCurve/Plot.py @@ -0,0 +1,211 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2011, 2012 * +#* Jose Luis Cercos Pita * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* This program is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Library General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with this program; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#*************************************************************************** + +import os +# FreeCAD modules +import FreeCAD,FreeCADGui +from FreeCAD import Part, Base +from FreeCAD import Image, ImageGui +# FreeCADShip modules +from shipUtils import Paths, Translator + +header = """ ################################################################# + + ##### #### ### #### ##### # # ### #### + # # # # # # # # # # # # + # ## #### #### # # # # # # # # # # # + #### # # # # # # # ##### # # ## ## ##### # #### + # # #### #### # # # # # # # # # # + # # # # # # # # # # # # # # + # # #### #### ### # # #### ##### # # ### # + + ################################################################# +""" + +class Plot(object): + def __init__(self, x, y, disp, xcb, ship): + """ Constructor. performs plot and show it (Using pyxplot). + @param x X coordinates. + @param y Transversal areas. + @param disp Ship displacement. + @param xcb Bouyancy center length. + @param ship Active ship instance. + """ + if self.createDirectory(): + return + if self.saveData(x,y,ship): + return + if self.saveLayout(x,y,disp,xcb,ship): + return + if self.execute(): + return + ImageGui.open(self.path + 'areas.png') + + def createDirectory(self): + """ Create needed folder to write data and scripts. + @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 = Translator.translate("Can't create '" + self.path + "' folder.\n") + FreeCAD.Console.PrintError(msg) + 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 = Translator.translate("Can't write '" + filename + "' file.\n") + FreeCAD.Console.PrintError(msg) + 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 + if len(x) < 2: + msg = Translator.translate("Not enough data to plot.\n") + FreeCAD.Console.PrintError(msg) + 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 = Translator.translate("Data saved at '" + self.dataFile + "'.\n") + FreeCAD.Console.PrintMessage(msg) + return False + + def saveLayout(self, x, y, disp, xcb, ship): + """ Prints the data output. + @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. + """ + filename = self.path + 'areas.pyxplot' + # Open the file + try: + Output = open(filename, "w") + except IOError: + msg = Translator.translate("Can't write '" + filename + "' file.\n") + FreeCAD.Console.PrintError(msg) + return True + # Write header + Output.write(header) + Output.write(" #\n") + Output.write(" # File automatically exported by FreeCAD-Ship\n") + Output.write(" # This file contains a script to plot transversal areas curve.\n") + Output.write(" # To use it execute:\n") + Output.write(" #\n") + Output.write(" # pyxplot %s\n" % (filename)) + Output.write(" #\n") + Output.write(" #################################################################\n") + # Write general options for hydrostatics + Output.write("set numeric display latex\n") + Output.write("set output '%s'\n" % (self.path + 'areas.eps')) + Output.write("set nokey\n") + Output.write("set grid\n") + Output.write("# X axis\n") + Output.write("set xlabel 'x / $m$'\n") + Output.write("set xtic\n") + Output.write("# Y axis\n") + Output.write("set ylabel 'Area / $m^2$'\n") + Output.write("set ytic\n") + Output.write("# Line styles\n") + Output.write("set style 1 line linetype 1 linewidth 1 colour rgb (0):(0):(0)\n") + Output.write("set style 2 line linetype 1 linewidth 2 colour rgb (0):(0):(0)\n") + # Get perpendiculars data + Lpp = ship.Length + FPx = 0.5*Lpp + APx = -0.5*Lpp + maxArea = max(y) + # Perpendicular labels + Output.write("# Perpendiculars labels\n") + Output.write("set label (1) AP %f,%f\n" % (APx+0.01*Lpp, 0.01*maxArea)) + Output.write("set label (2) AP %f,%f\n" % (APx+0.01*Lpp, 0.95*maxArea)) + Output.write("set label (3) FP %f,%f\n" % (FPx+0.01*Lpp, 0.01*maxArea)) + Output.write("set label (4) FP %f,%f\n" % (FPx+0.01*Lpp, 0.95*maxArea)) + # Additional data + Output.write("# Additional data\n") + Output.write("set label (5) 'XCB = %g m' %f,%f\n" % (xcb, -0.25*Lpp, 0.25*maxArea)) + Output.write("set label (6) 'Maximum area = %g m2' %f,%f\n" % (maxArea, -0.25*Lpp, 0.15*maxArea)) + Output.write("set label (7) 'Displacement = %g tons' %f,%f\n" % (disp, -0.25*Lpp, 0.05*maxArea)) + # Write plot call + Output.write("# Plot\n") + Output.write("plot '%s' using 1:2 title 'Transversal areas' axes x1y1 with lines style 1, \\\n" % (self.dataFile)) + Output.write(" '%s' using 3:4 title 'FP' axes x1y1 with lines style 2, \\\n" % (self.dataFile)) + Output.write(" '%s' using 5:6 title 'AP' axes x1y1 with lines style 2\n" % (self.dataFile)) + # Close file + self.layoutFile = filename + Output.close() + return False + + def execute(self): + """ Calls pyxplot in order to plot an save an image. + @return True if error happens. + """ + filename = self.path + 'areas' + comm = "pyxplot %s" % (self.layoutFile) + if os.system(comm): + msg = Translator.translate("Can't execute pyxplot. Maybe is not installed?\n") + FreeCAD.Console.PrintError(msg) + msg = Translator.translate("Plot will not generated\n") + FreeCAD.Console.PrintError(msg) + return True + comm = "gs -r300 -dEPSCrop -dTextAlphaBits=4 -sDEVICE=png16m -sOutputFile=%s.png -dBATCH -dNOPAUSE %s.eps" % (filename,filename) + if os.system(comm): + msg = Translator.translate("Can't execute ghostscript. Maybe is not installed?\n") + FreeCAD.Console.PrintError(msg) + msg = Translator.translate("Generated image will not converted to png\n") + FreeCAD.Console.PrintError(msg) + return True + return False diff --git a/src/Mod/Ship/shipAreasCurve/TaskPanel.py b/src/Mod/Ship/shipAreasCurve/TaskPanel.py index 3a5dab2fc9..af4764e124 100644 --- a/src/Mod/Ship/shipAreasCurve/TaskPanel.py +++ b/src/Mod/Ship/shipAreasCurve/TaskPanel.py @@ -28,7 +28,7 @@ import FreeCADGui as Gui # Qt library from PyQt4 import QtGui,QtCore # Module -import Preview +import Preview, Plot import Instance from shipUtils import Paths, Translator from surfUtils import Geometry @@ -44,6 +44,13 @@ class TaskPanel: if not self.ship: return False self.save() + # Plot data + data = Hydrostatics.Displacement(self.ship,self.form.draft.value(),self.form.trim.value()) + x = self.ship.xSection[:] + y = data[0] + disp = data[1] + xcb = data[2] + Plot.Plot(x,y,disp,xcb, self.ship) self.preview.clean() return True