Moved Create Ship to new paradigm.
This commit is contained in:
parent
aae0c84259
commit
8e09607c88
|
@ -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.
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue
Block a user