Moved Create Ship to new paradigm.

This commit is contained in:
Jose Luis Cercós pita 2012-06-08 13:49:37 +02:00
parent aae0c84259
commit 8e09607c88
3 changed files with 55 additions and 251 deletions

View File

@ -35,9 +35,10 @@ from FreeCAD import Part, Base, Vector
from shipUtils import Paths, Translator, Math
class Ship:
def __init__(self, obj, faces):
def __init__(self, obj, solids):
""" Creates a new ship on active document.
@param faces Ship faces (Part::Shape entities).
@param obj Part::FeaturePython created object.
@param faces Ship solids components.
"""
# Add uniqueness property to identify Ship instances
obj.addProperty("App::PropertyBool","IsShip","Ship", str(Translator.translate("True if is a valid ship instance"))).IsShip=True
@ -46,20 +47,23 @@ class Ship:
obj.addProperty("App::PropertyLength","Beam","Ship", str(Translator.translate("Ship beam (B) [m]"))).Beam=0.0
obj.addProperty("App::PropertyLength","Draft","Ship", str(Translator.translate("Ship draft (T) [m]"))).Draft=0.0
# Add shapes
obj.Shape = Part.makeShell(faces)
obj.Shape = Part.makeCompound(solids)
obj.Proxy = self
self.obj = obj
def onChanged(self, fp, prop):
''' Print the name of the property that has changed '''
# FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n")
""" 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
def execute(self, obj):
''' Print a short message when doing a recomputation, this method is mandatory '''
# FreeCAD.Console.PrintMessage("Recompute Ship\n")
obj.Shape = Part.makeShell(obj.Shape.Faces)
def execute(self, fp):
""" Called when a recomputation is needed.
@param fp Part::FeaturePython object.
"""
fp.Shape = Part.makeCompound(fp.Shape.Solids)
def lineFaceSection(self,line,surface):
""" Returns the point of section of a line with a face
@ -92,94 +96,6 @@ class Ship:
result.append(points[i])
return result
def discretize(self, nS, nP):
""" Discretize the surface.
@param nS Number of sections
@param nP Number of points per section
"""
self.obj.addProperty("App::PropertyInteger","nSections","Ship", str(Translator.translate("Number of sections"))).nSections=nS
self.obj.addProperty("App::PropertyIntegerList","nPoints","Ship", str(Translator.translate("List of number of points per sections (accumulated histogram)"))).nPoints=[0]
self.obj.addProperty("App::PropertyFloatList","xSection","Ship", str(Translator.translate("List of sections x coordinate"))).xSection=[]
self.obj.addProperty("App::PropertyVectorList","mSections","Ship", str(Translator.translate("List of sections points"))).mSections=[]
nPoints = [0]
xSection = []
mSections = []
# Get bounds
shape = self.obj.Shape
bbox = shape.BoundBox
x0 = bbox.XMin
x1 = bbox.XMax
y0 = bbox.YMin
y1 = bbox.YMax
z0 = bbox.ZMin
z1 = bbox.ZMax
# Create a set of planes to perfom edges sections
planes = []
dz = (z1 - z0) / (nP - 1)
for j in range(0,nP):
z = z0 + j*dz
rX = x1 - x0
rY = max(y1 - y0, abs(y1), abs(y0))
planes.append(Part.makePlane(4*rX,4*rY,Base.Vector(-2*rX,-2*rY,z),Base.Vector(0,0,1)))
# Division are performed at x axis
dx = (x1 - x0) / (nS - 1.0)
for i in range(0,nS):
section = []
x = x0 + i*dx
xSection.append(x)
percen = i*100 / (nS-1)
FreeCAD.Console.PrintMessage('%d%%\n' % (percen));
# Slice the surface to get curves
wires = shape.slice(Vector(1.0,0.0,0.0), x)
if not wires:
if (i != 0) or (i != nS-1):
msg = 'Found empty section at x=%g\n' % (x)
msg = Translator.translate(msg)
FreeCAD.Console.PrintWarning(msg)
FreeCAD.Console.PrintWarning('\tThis may happens if a bad defined (or really complex) surface has been provided.\n')
FreeCAD.Console.PrintWarning('\tPlease, ensure that this section is correct, or fix surfaces and create a new ship.\n')
nPoints.append(0)
continue
# Desarrollate wires into edges list
edges = []
for j in range(0,len(wires)):
wire = wires[j].Edges
for k in range(0,len(wire)):
edges.append(wire[k])
# Slice curves to get points
points = []
for k in range(0,nP):
planePoints = []
for j in range(0,len(edges)):
aux = self.lineFaceSection(edges[j], planes[k])
for l in range(0,len(aux)):
planePoints.append(Vector(aux[l].X, aux[l].Y, aux[l].Z))
if not planePoints: # No section found, symmetry plane point will used
planePoints.append(Vector(x,0,z0 + k*dz))
# Get Y coordinates
auxY = []
for l in range(0,len(planePoints)):
auxY.append(planePoints[l].y)
# Sort them
auxY.sort()
# And store
for l in range(0,len(planePoints)):
points.append(Vector(planePoints[l].x, auxY[l], planePoints[l].z))
# Store points
section = points[:]
nPoints.append(len(section))
for j in range(0,len(section)):
mSections.append(section[j])
# Save data
for i in range(1,len(nPoints)):
nPoints[i] = nPoints[i] + nPoints[i-1]
self.obj.nPoints = nPoints[:]
self.obj.xSection = xSection[:]
self.obj.mSections = mSections[:]
msg = '%d Discretization points performed\n' % (len(mSections))
msg = Translator.translate(msg)
FreeCAD.Console.PrintMessage(msg)
class ViewProviderShip:
def __init__(self, obj):
"Set this object to the proxy object of the actual view provider"
@ -660,21 +576,6 @@ class ViewProviderShip:
" "};
"""
def sections(obj):
""" Returns the discretization points of sections, with the advantage
that is a list of nSections lists, with the points.
@param obj Ship object
@return Sections points
"""
histogram = obj.nPoints[:]
points = obj.mSections[:]
sections = []
for i in range(0, len(histogram) - 1):
sections.append([])
for j in range(histogram[i],histogram[i+1]):
sections[i].append(points[j])
return sections
def weights(obj):
""" Returns Ship weights list. If weights has not been sets,
this tool creates it.

View File

@ -30,7 +30,6 @@ from PyQt4 import QtGui,QtCore
import Preview
import Instance
from shipUtils import Paths, Translator
from surfUtils import Geometry
class TaskPanel:
def __init__(self):
@ -41,7 +40,7 @@ class TaskPanel:
self.preview.clean()
# Create new ship instance
obj = App.ActiveDocument.addObject("Part::FeaturePython","Ship")
ship = Instance.Ship(obj, self.faces)
ship = Instance.Ship(obj, self.solids)
Instance.ViewProviderShip(obj.ViewObject)
# Set main dimensions
obj.Length = self.form.length.value()
@ -84,8 +83,6 @@ class TaskPanel:
form.length = form.findChild(QtGui.QDoubleSpinBox, "Length")
form.beam = form.findChild(QtGui.QDoubleSpinBox, "Beam")
form.draft = form.findChild(QtGui.QDoubleSpinBox, "Draft")
form.nSections = form.findChild(QtGui.QSpinBox, "NSections")
form.nPoints = form.findChild(QtGui.QSpinBox, "NPoints")
form.mainLogo = form.findChild(QtGui.QLabel, "MainLogo")
iconPath = Paths.iconsPath() + "/Ico.xpm"
form.mainLogo.setPixmap(QtGui.QPixmap(iconPath))
@ -99,8 +96,6 @@ class TaskPanel:
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)
QtCore.QObject.connect(form.nSections, QtCore.SIGNAL("valueChanged(int)"), self.onDiscretization)
QtCore.QObject.connect(form.nPoints, QtCore.SIGNAL("valueChanged(int)"), self.onDiscretization)
def getMainWindow(self):
"returns the main window"
@ -117,36 +112,36 @@ class TaskPanel:
""" Set initial values for fields
"""
# Get objects
self.faces = None
selObjs = Geometry.getSelectedObjs()
self.solids = None
selObjs = Gui.Selection.getSelection()
if not selObjs:
msg = Translator.translate("Ship objects can only be created on top of hull geometry (no object selected).\n")
msg = Translator.translate("Ship objects can only be created on top of hull geometry (any object selected).")
App.Console.PrintError(msg)
msg = Translator.translate("Please create or download a ship hull geometry before using this tool\n")
msg = Translator.translate("Please create or load a ship hull geometry before using this tool.")
App.Console.PrintError(msg)
return True
self.faces = []
self.solids = []
for i in range(0, len(selObjs)):
faces = Geometry.getFaces(selObjs[i])
for j in range(0, len(faces)):
self.faces.append(faces[j])
if not self.faces:
msg = Translator.translate("Ship objects can only be created on top of hull geometry (no face object selected).\n")
solids = self.getSolids(selObjs[i])
for j in range(0, len(solids)):
self.solids.append(solids[j])
if not self.solids:
msg = Translator.translate("Ship objects can only be created on top of hull geometry (no solid found at selected objects).\n")
App.Console.PrintError(msg)
msg = Translator.translate("Please create or download a ship hull geometry before using this tool\n")
msg = Translator.translate("Please create or load a ship hull geometry before using this tool\n")
App.Console.PrintError(msg)
return True
# Get bounds
bounds = [0.0, 0.0, 0.0]
bbox = self.faces[0].BoundBox
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.faces)):
bbox = self.faces[i].BoundBox
for i in range(1,len(self.solids)):
bbox = self.solids[i].BoundBox
if minX > bbox.XMin:
minX = bbox.XMin
if maxX < bbox.XMax:
@ -170,7 +165,7 @@ class TaskPanel:
self.form.beam.setMaximum(2.0*bounds[1])
self.form.beam.setMinimum(0.001)
self.form.beam.setValue(2.0*bounds[1])
self.B = 2.0*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])
@ -186,8 +181,6 @@ class TaskPanel:
self.form.findChild(QtGui.QLabel, "LengthLabel").setText(Translator.translate("Length"))
self.form.findChild(QtGui.QLabel, "BeamLabel").setText(Translator.translate("Beam"))
self.form.findChild(QtGui.QLabel, "DraftLabel").setText(Translator.translate("Draft"))
self.form.findChild(QtGui.QLabel, "NSectionsLabel").setText(Translator.translate("Number of sections"))
self.form.findChild(QtGui.QLabel, "NPointsLabel").setText(Translator.translate("Points per section"))
def onData(self, value):
""" Method called when ship data is changed.
@ -199,16 +192,26 @@ class TaskPanel:
self.T = self.form.draft.value()
self.preview.update(self.L, self.B, self.T)
def onDiscretization(self, value):
""" Method called when discretization data is changed.
Annotations must be showed.
@param value Changed value.
"""
pass
def close(self):
""" Destroy all dependant objects
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()

View File

@ -7,9 +7,15 @@
<x>0</x>
<y>0</y>
<width>260</width>
<height>514</height>
<height>316</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>316</height>
</size>
</property>
<property name="windowTitle">
<string>Create new ship</string>
</property>
@ -184,112 +190,6 @@
</widget>
</widget>
</item>
<item>
<widget class="QGroupBox" name="DiscretizationBox">
<property name="minimumSize">
<size>
<width>240</width>
<height>160</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="title">
<string>Discretization</string>
</property>
<widget class="QWidget" name="verticalLayoutWidget_3">
<property name="geometry">
<rect>
<x>0</x>
<y>20</y>
<width>241</width>
<height>101</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="NSectionsLabel">
<property name="text">
<string>Number of sections</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="NSections">
<property name="minimum">
<number>50</number>
</property>
<property name="maximum">
<number>500</number>
</property>
<property name="singleStep">
<number>50</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="NPointsLabel">
<property name="text">
<string>Points per section</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="NPoints">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>500</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
</layout>