316 lines
12 KiB
Python
316 lines
12 KiB
Python
#***************************************************************************
|
|
#* *
|
|
#* Copyright (c) 2011, 2012 *
|
|
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
|
#* *
|
|
#* This program is free software; you can redistribute it and/or modify *
|
|
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
|
#* as published by the Free Software Foundation; either version 2 of *
|
|
#* the License, or (at your option) any later version. *
|
|
#* for detail see the LICENCE text file. *
|
|
#* *
|
|
#* This program is distributed in the hope that it will be useful, *
|
|
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
#* GNU Library General Public License for more details. *
|
|
#* *
|
|
#* You should have received a copy of the GNU Library General Public *
|
|
#* License along with this program; if not, write to the Free Software *
|
|
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
|
#* USA *
|
|
#* *
|
|
#***************************************************************************
|
|
|
|
import FreeCAD as App
|
|
import FreeCADGui as Gui
|
|
import Units
|
|
from PySide import QtGui, QtCore
|
|
import Preview
|
|
import Tools
|
|
import Instance
|
|
from shipUtils import Paths
|
|
import shipUtils.Units as USys
|
|
import shipUtils.Locale as Locale
|
|
|
|
class TaskPanel:
|
|
def __init__(self):
|
|
"""Constructor"""
|
|
self.ui = Paths.modulePath() + "/shipCreateShip/TaskPanel.ui"
|
|
self.preview = Preview.Preview()
|
|
|
|
def accept(self):
|
|
"""Create the ship instance"""
|
|
self.preview.clean()
|
|
mw = self.getMainWindow()
|
|
form = mw.findChild(QtGui.QWidget, "TaskPanel")
|
|
form.length = self.widget(QtGui.QLineEdit, "Length")
|
|
form.breadth = self.widget(QtGui.QLineEdit, "Breadth")
|
|
form.draft = self.widget(QtGui.QLineEdit, "Draft")
|
|
|
|
Tools.createShip(self.solids,
|
|
Locale.fromString(form.length.text()),
|
|
Locale.fromString(form.breadth.text()),
|
|
Locale.fromString(form.draft.text()))
|
|
return True
|
|
|
|
def reject(self):
|
|
"""Cancel the job"""
|
|
self.preview.clean()
|
|
return True
|
|
|
|
def clicked(self, index):
|
|
pass
|
|
|
|
def open(self):
|
|
pass
|
|
|
|
def needsFullSpace(self):
|
|
return True
|
|
|
|
def isAllowedAlterSelection(self):
|
|
return False
|
|
|
|
def isAllowedAlterView(self):
|
|
return True
|
|
|
|
def isAllowedAlterDocument(self):
|
|
return False
|
|
|
|
def helpRequested(self):
|
|
pass
|
|
|
|
def setupUi(self):
|
|
"""Create and configurate the user interface"""
|
|
mw = self.getMainWindow()
|
|
form = mw.findChild(QtGui.QWidget, "TaskPanel")
|
|
form.length = self.widget(QtGui.QLineEdit, "Length")
|
|
form.breadth = self.widget(QtGui.QLineEdit, "Breadth")
|
|
form.draft = self.widget(QtGui.QLineEdit, "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):
|
|
toplevel = QtGui.qApp.topLevelWidgets()
|
|
for i in toplevel:
|
|
if i.metaObject().className() == "Gui::MainWindow":
|
|
return i
|
|
raise RuntimeError("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 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.
|
|
self.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
|
|
self.bounds[0] = maxX - minX
|
|
self.bounds[1] = max(maxY - minY, abs(maxY), abs(minY))
|
|
self.bounds[2] = maxZ - minZ
|
|
|
|
input_format = USys.getLengthFormat()
|
|
|
|
mw = self.getMainWindow()
|
|
form = mw.findChild(QtGui.QWidget, "TaskPanel")
|
|
form.length = self.widget(QtGui.QLineEdit, "Length")
|
|
form.breadth = self.widget(QtGui.QLineEdit, "Breadth")
|
|
form.draft = self.widget(QtGui.QLineEdit, "Draft")
|
|
|
|
qty = Units.Quantity(self.bounds[0], Units.Length)
|
|
form.length.setText(Locale.toString(input_format.format(
|
|
qty.getValueAs(USys.getLengthUnits()).Value)))
|
|
self.L = self.bounds[0] / Units.Metre.Value
|
|
qty = Units.Quantity(self.bounds[1], Units.Length)
|
|
form.breadth.setText(Locale.toString(input_format.format(
|
|
qty.getValueAs(USys.getLengthUnits()).Value)))
|
|
self.B = self.bounds[1] / Units.Metre.Value
|
|
qty = Units.Quantity(self.bounds[2], Units.Length)
|
|
form.draft.setText(Locale.toString(input_format.format(
|
|
0.5 * qty.getValueAs(USys.getLengthUnits()).Value)))
|
|
self.T = 0.5 * self.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 clampVal(self, widget, val_min, val_max, val):
|
|
if val >= val_min and val <= val_max:
|
|
return val
|
|
input_format = USys.getLengthFormat()
|
|
val = min(val_max, max(val_min, val))
|
|
qty = Units.Quantity('{} m'.format(val))
|
|
widget.setText(Locale.toString(input_format.format(
|
|
qty.getValueAs(USys.getLengthUnits()).Value)))
|
|
return val
|
|
|
|
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.QLineEdit, "Length")
|
|
form.breadth = self.widget(QtGui.QLineEdit, "Breadth")
|
|
form.draft = self.widget(QtGui.QLineEdit, "Draft")
|
|
|
|
qty = Units.Quantity(Locale.fromString(form.length.text()))
|
|
val_min = 0.001
|
|
val_max = self.bounds[0] / Units.Metre.Value
|
|
val = qty.getValueAs('m').Value
|
|
self.L = self.clampVal(form.length, val_min, val_max, val)
|
|
qty = Units.Quantity(Locale.fromString(form.breadth.text()))
|
|
val_min = 0.001
|
|
val_max = self.bounds[1] / Units.Metre.Value
|
|
val = qty.getValueAs('m').Value
|
|
self.B = self.clampVal(form.breadth, val_min, val_max, val)
|
|
qty = Units.Quantity(Locale.fromString(form.draft.text()))
|
|
val_min = 0.001
|
|
val_max = self.bounds[2] / Units.Metre.Value
|
|
val = qty.getValueAs('m').Value
|
|
self.T = self.clampVal(form.draft, val_min, val_max, val)
|
|
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 createTask():
|
|
panel = TaskPanel()
|
|
Gui.Control.showDialog(panel)
|
|
if panel.setupUi():
|
|
Gui.Control.closeDialog(panel)
|
|
return None
|
|
return panel
|