diff --git a/src/Mod/Ship/Instance.py b/src/Mod/Ship/Instance.py index adba4d22b..54a262b1d 100644 --- a/src/Mod/Ship/Instance.py +++ b/src/Mod/Ship/Instance.py @@ -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. diff --git a/src/Mod/Ship/shipCreateShip/TaskPanel.py b/src/Mod/Ship/shipCreateShip/TaskPanel.py index cbb5319c8..eeb474ccc 100644 --- a/src/Mod/Ship/shipCreateShip/TaskPanel.py +++ b/src/Mod/Ship/shipCreateShip/TaskPanel.py @@ -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() diff --git a/src/Mod/Ship/shipCreateShip/TaskPanel.ui b/src/Mod/Ship/shipCreateShip/TaskPanel.ui index 9642e1bd2..5cd6a79b6 100644 --- a/src/Mod/Ship/shipCreateShip/TaskPanel.ui +++ b/src/Mod/Ship/shipCreateShip/TaskPanel.ui @@ -7,9 +7,15 @@ 0 0 260 - 514 + 316 + + + 0 + 316 + + Create new ship @@ -184,112 +190,6 @@ - - - - - 240 - 160 - - - - Qt::LeftToRight - - - Discretization - - - - - 0 - 20 - 241 - 101 - - - - - - - 10 - - - 0 - - - 10 - - - 0 - - - - - Number of sections - - - - - - - 50 - - - 500 - - - 50 - - - 50 - - - - - - - - - 10 - - - 0 - - - 10 - - - 0 - - - - - Points per section - - - - - - - 10 - - - 500 - - - 10 - - - 10 - - - - - - - - -