From 34cb60f8cf27fd7fb80acd5434112823b813ff02 Mon Sep 17 00:00:00 2001 From: Jose Luis Cercos Pita Date: Thu, 22 Nov 2012 19:25:54 +0100 Subject: [PATCH 1/3] Added real time reporting and cancel capabilities --- src/Mod/Ship/tankGZ/TaskPanel.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Mod/Ship/tankGZ/TaskPanel.py b/src/Mod/Ship/tankGZ/TaskPanel.py index ce7943139..b2b1b7b92 100644 --- a/src/Mod/Ship/tankGZ/TaskPanel.py +++ b/src/Mod/Ship/tankGZ/TaskPanel.py @@ -39,10 +39,13 @@ class TaskPanel: self.ui = Paths.modulePath() + "/tankGZ/TaskPanel.ui" self.ship = None self.tanks = {} + self.running = False def accept(self): if not self.ship: return False + if self.running: + return # Get general data disp = self.computeDisplacement() draft = self.computeDraft(disp[0], self.form.trim.value()) @@ -57,16 +60,28 @@ class TaskPanel: msg = QtGui.QApplication.translate("ship_console","Computing GZ", None,QtGui.QApplication.UnicodeUTF8) App.Console.PrintMessage(msg + "...\n") + loop=QtCore.QEventLoop() + timer=QtCore.QTimer() + timer.setSingleShot(True) + QtCore.QObject.connect(timer,QtCore.SIGNAL("timeout()"),loop,QtCore.SLOT("quit()")) + self.running = True for i in range(0, nRoll): App.Console.PrintMessage("\t%d/%d\n" % (i+1,nRoll)) roll.append(i*dRoll) GZ.append(self.computeGZ(draft[0], trim, roll[-1])) + timer.start(0.0) + loop.exec_() + if(not self.running): + break PlotAux.Plot(roll, GZ, disp[0]/1000.0, draft[0], trim) return True def reject(self): if not self.ship: return False + if self.running: + self.running = False + return return True def clicked(self, index): From efc67461b890565a3ca4f7eeb49f6bc8db06e617 Mon Sep 17 00:00:00 2001 From: Jose Luis Cercos Pita Date: Thu, 22 Nov 2012 19:42:20 +0100 Subject: [PATCH 2/3] Moved hydrostatics computation from PlotAux to Task manager --- src/Mod/Ship/shipHydrostatics/PlotAux.py | 111 +-------------------- src/Mod/Ship/shipHydrostatics/TaskPanel.py | 108 +++++++++++++++++++- 2 files changed, 110 insertions(+), 109 deletions(-) diff --git a/src/Mod/Ship/shipHydrostatics/PlotAux.py b/src/Mod/Ship/shipHydrostatics/PlotAux.py index 316bed13e..32b2f3fe3 100644 --- a/src/Mod/Ship/shipHydrostatics/PlotAux.py +++ b/src/Mod/Ship/shipHydrostatics/PlotAux.py @@ -27,11 +27,8 @@ import math from PyQt4 import QtGui,QtCore # FreeCAD modules import FreeCAD,FreeCADGui -from FreeCAD import Base, Vector -import Part, Image, ImageGui # FreeCADShip modules from shipUtils import Paths -import Tools header = """ ################################################################# @@ -47,32 +44,14 @@ header = """ ################################################################# """ class Plot(object): - def __init__(self, ship, trim, drafts): + def __init__(self, ship, trim, drafts, points): """ Constructor. performs plot and show it (Using pyxplot). @param ship Selected ship instance @param trim Trim in degrees. @param drafts List of drafts to be performed. + @param points List of computed hydrostatics. """ - # Compute data - # Get external faces - faces = self.externalFaces(ship.Shape) - if len(faces) == 0: - msg = QtGui.QApplication.translate("ship_console", "Can't detect external faces from ship object", - None,QtGui.QApplication.UnicodeUTF8) - FreeCAD.Console.PrintError(msg + '\n') - return - else: - faces = Part.makeShell(faces) - # Print data - msg = QtGui.QApplication.translate("ship_console", "Computing hydrostatics", - None,QtGui.QApplication.UnicodeUTF8) - FreeCAD.Console.PrintMessage(msg + '...\n') - self.points = [] - for i in range(0,len(drafts)): - FreeCAD.Console.PrintMessage("\t%d / %d\n" % (i+1, len(drafts))) - draft = drafts[i] - point = Tools.Point(ship,faces,draft,trim) - self.points.append(point) + self.points = points[:] # Try to plot self.plotVolume() self.plotStability() @@ -392,87 +371,3 @@ class Plot(object): FreeCAD.Console.PrintMessage(msg + ':\n\t' + "\'"+ self.dataFile + "\'\n") return False - def lineFaceSection(self,line,surface): - """ Returns the point of section of a line with a face - @param line Line object, that can be a curve. - @param surface Surface object (must be a Part::Shape) - @return Section points array, [] if line don't cut surface - """ - # Get initial data - result = [] - vertexes = line.Vertexes - nVertex = len(vertexes) - # Perform the cut - section = line.cut(surface) - # Filter all old points - points = section.Vertexes - return points - - def externalFaces(self, shape): - """ Returns detected external faces. - @param shape Shape where external faces wanted. - @return List of external faces detected. - """ - result = [] - faces = shape.Faces - bbox = shape.BoundBox - L = bbox.XMax - bbox.XMin - B = bbox.YMax - bbox.YMin - T = bbox.ZMax - bbox.ZMin - dist = math.sqrt(L*L + B*B + T*T) - msg = QtGui.QApplication.translate("ship_console", "Computing external faces", - None,QtGui.QApplication.UnicodeUTF8) - FreeCAD.Console.PrintMessage(msg + '...\n') - # Valid/unvalid faces detection loop - for i in range(0,len(faces)): - FreeCAD.Console.PrintMessage("\t%d / %d\n" % (i+1, len(faces))) - f = faces[i] - # Create a line normal to surface at middle point - u = 0.0 - v = 0.0 - try: - surf = f.Surface - u = 0.5*(surf.getUKnots()[0]+surf.getUKnots()[-1]) - v = 0.5*(surf.getVKnots()[0]+surf.getVKnots()[-1]) - except: - cog = f.CenterOfMass - [u,v] = f.Surface.parameter(cog) - p0 = f.valueAt(u,v) - try: - n = f.normalAt(u,v).normalize() - except: - continue - p1 = p0 + n.multiply(1.5*dist) - line = Part.makeLine(p0, p1) - # Look for faces in front of this - nPoints = 0 - for j in range(0,len(faces)): - f2 = faces[j] - section = self.lineFaceSection(line, f2) - if len(section) <= 2: - continue - # Add points discarding start and end - nPoints = nPoints + len(section) - 2 - # In order to avoid special directions we can modify line - # normal a little bit. - angle = 5 - line.rotate(p0,Vector(1,0,0),angle) - line.rotate(p0,Vector(0,1,0),angle) - line.rotate(p0,Vector(0,0,1),angle) - nPoints2 = 0 - for j in range(0,len(faces)): - if i == j: - continue - f2 = faces[j] - section = self.lineFaceSection(line, f2) - if len(section) <= 2: - continue - # Add points discarding start and end - nPoints2 = nPoints + len(section) - 2 - # If the number of intersection points is pair, is a - # external face. So if we found an odd points intersection, - # face must be discarded. - if (nPoints % 2) or (nPoints2 % 2): - continue - result.append(f) - return result diff --git a/src/Mod/Ship/shipHydrostatics/TaskPanel.py b/src/Mod/Ship/shipHydrostatics/TaskPanel.py index bc5e2d967..dfd4588b2 100644 --- a/src/Mod/Ship/shipHydrostatics/TaskPanel.py +++ b/src/Mod/Ship/shipHydrostatics/TaskPanel.py @@ -25,6 +25,8 @@ import math # FreeCAD modules import FreeCAD as App import FreeCADGui as Gui +from FreeCAD import Base, Vector +import Part # Qt library from PyQt4 import QtGui,QtCore # Module @@ -48,7 +50,26 @@ class TaskPanel: for i in range(1,self.form.nDraft.value()): draft = draft + dDraft drafts.append(draft) - PlotAux.Plot(self.ship, self.form.trim.value(), drafts) + # Compute data + # Get external faces + faces = self.externalFaces(self.ship.Shape) + if len(faces) == 0: + msg = QtGui.QApplication.translate("ship_console", "Can't detect external faces from ship object", + None,QtGui.QApplication.UnicodeUTF8) + App.Console.PrintError(msg + '\n') + return False + faces = Part.makeShell(faces) + # Get hydrostatics + msg = QtGui.QApplication.translate("ship_console", "Computing hydrostatics", + None,QtGui.QApplication.UnicodeUTF8) + App.Console.PrintMessage(msg + '...\n') + points = [] + for i in range(0,len(drafts)): + App.Console.PrintMessage("\t%d / %d\n" % (i+1, len(drafts))) + draft = drafts[i] + point = Tools.Point(self.ship,faces,draft,self.form.trim.value()) + points.append(point) + PlotAux.Plot(self.ship, self.form.trim.value(), drafts, points) return True def reject(self): @@ -235,6 +256,91 @@ class TaskPanel: self.ship.addProperty("App::PropertyInteger","HydrostaticsNDraft","Ship", tooltip) self.ship.HydrostaticsNDraft = self.form.nDraft.value() + def lineFaceSection(self,line,surface): + """ Returns the point of section of a line with a face + @param line Line object, that can be a curve. + @param surface Surface object (must be a Part::Shape) + @return Section points array, [] if line don't cut surface + """ + # Get initial data + result = [] + vertexes = line.Vertexes + nVertex = len(vertexes) + # Perform the cut + section = line.cut(surface) + # Filter all old points + points = section.Vertexes + return points + + def externalFaces(self, shape): + """ Returns detected external faces. + @param shape Shape where external faces wanted. + @return List of external faces detected. + """ + result = [] + faces = shape.Faces + bbox = shape.BoundBox + L = bbox.XMax - bbox.XMin + B = bbox.YMax - bbox.YMin + T = bbox.ZMax - bbox.ZMin + dist = math.sqrt(L*L + B*B + T*T) + msg = QtGui.QApplication.translate("ship_console", "Computing external faces", + None,QtGui.QApplication.UnicodeUTF8) + App.Console.PrintMessage(msg + '...\n') + # Valid/unvalid faces detection loop + for i in range(0,len(faces)): + App.Console.PrintMessage("\t%d / %d\n" % (i+1, len(faces))) + f = faces[i] + # Create a line normal to surface at middle point + u = 0.0 + v = 0.0 + try: + surf = f.Surface + u = 0.5*(surf.getUKnots()[0]+surf.getUKnots()[-1]) + v = 0.5*(surf.getVKnots()[0]+surf.getVKnots()[-1]) + except: + cog = f.CenterOfMass + [u,v] = f.Surface.parameter(cog) + p0 = f.valueAt(u,v) + try: + n = f.normalAt(u,v).normalize() + except: + continue + p1 = p0 + n.multiply(1.5*dist) + line = Part.makeLine(p0, p1) + # Look for faces in front of this + nPoints = 0 + for j in range(0,len(faces)): + f2 = faces[j] + section = self.lineFaceSection(line, f2) + if len(section) <= 2: + continue + # Add points discarding start and end + nPoints = nPoints + len(section) - 2 + # In order to avoid special directions we can modify line + # normal a little bit. + angle = 5 + line.rotate(p0,Vector(1,0,0),angle) + line.rotate(p0,Vector(0,1,0),angle) + line.rotate(p0,Vector(0,0,1),angle) + nPoints2 = 0 + for j in range(0,len(faces)): + if i == j: + continue + f2 = faces[j] + section = self.lineFaceSection(line, f2) + if len(section) <= 2: + continue + # Add points discarding start and end + nPoints2 = nPoints + len(section) - 2 + # If the number of intersection points is pair, is a + # external face. So if we found an odd points intersection, + # face must be discarded. + if (nPoints % 2) or (nPoints2 % 2): + continue + result.append(f) + return result + def createTask(): panel = TaskPanel() Gui.Control.showDialog(panel) From 9d8747f1f045c3cd6c58764468fdebbe099920fe Mon Sep 17 00:00:00 2001 From: Jose Luis Cercos Pita Date: Thu, 22 Nov 2012 19:58:19 +0100 Subject: [PATCH 3/3] Moved to real time reporting and cancel new stuff --- src/Mod/Ship/shipHydrostatics/PlotAux.py | 10 ++++----- src/Mod/Ship/shipHydrostatics/TaskPanel.py | 25 +++++++++++++++++++++- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/Mod/Ship/shipHydrostatics/PlotAux.py b/src/Mod/Ship/shipHydrostatics/PlotAux.py index 32b2f3fe3..a71b50b23 100644 --- a/src/Mod/Ship/shipHydrostatics/PlotAux.py +++ b/src/Mod/Ship/shipHydrostatics/PlotAux.py @@ -44,11 +44,10 @@ header = """ ################################################################# """ class Plot(object): - def __init__(self, ship, trim, drafts, points): + def __init__(self, ship, trim, points): """ Constructor. performs plot and show it (Using pyxplot). @param ship Selected ship instance @param trim Trim in degrees. - @param drafts List of drafts to be performed. @param points List of computed hydrostatics. """ self.points = points[:] @@ -59,7 +58,7 @@ class Plot(object): # Save data if self.createDirectory(): return - if self.saveData(ship, trim, drafts): + if self.saveData(ship, trim): return def plotVolume(self): @@ -324,11 +323,10 @@ class Plot(object): FreeCAD.Console.PrintError(msg + ':\n\t' + "\'"+ self.path + "\'\n") return False - def saveData(self, ship, trim, drafts): + def saveData(self, ship, trim): """ Write data file. @param ship Selected ship instance @param trim Trim in degrees. - @param drafts List of drafts to be performed. @return True if error happens. """ # Open the file @@ -359,7 +357,7 @@ class Plot(object): Output.write(" #\n") Output.write(" #################################################################\n") # Print data - for i in range(0,len(drafts)): + for i in range(0,len(self.points)): point = self.points[i] string = "%f %f %f %f %f %f %f %f %f %f %f\n" % (point.disp, point.draft, point.wet, point.mom, point.xcb, point.farea, point.KBt, point.BMt, point.Cb, point.Cf, point.Cm) Output.write(string) diff --git a/src/Mod/Ship/shipHydrostatics/TaskPanel.py b/src/Mod/Ship/shipHydrostatics/TaskPanel.py index dfd4588b2..84f3feca1 100644 --- a/src/Mod/Ship/shipHydrostatics/TaskPanel.py +++ b/src/Mod/Ship/shipHydrostatics/TaskPanel.py @@ -39,10 +39,13 @@ class TaskPanel: def __init__(self): self.ui = Paths.modulePath() + "/shipHydrostatics/TaskPanel.ui" self.ship = None + self.running = False def accept(self): if not self.ship: return False + if self.running: + return self.save() draft = self.form.minDraft.value() drafts = [draft] @@ -52,7 +55,14 @@ class TaskPanel: drafts.append(draft) # Compute data # Get external faces + self.loop=QtCore.QEventLoop() + self.timer=QtCore.QTimer() + self.timer.setSingleShot(True) + QtCore.QObject.connect(self.timer,QtCore.SIGNAL("timeout()"),self.loop,QtCore.SLOT("quit()")) + self.running = True faces = self.externalFaces(self.ship.Shape) + if not self.running: + return False if len(faces) == 0: msg = QtGui.QApplication.translate("ship_console", "Can't detect external faces from ship object", None,QtGui.QApplication.UnicodeUTF8) @@ -69,10 +79,19 @@ class TaskPanel: draft = drafts[i] point = Tools.Point(self.ship,faces,draft,self.form.trim.value()) points.append(point) - PlotAux.Plot(self.ship, self.form.trim.value(), drafts, points) + self.timer.start(0.0) + self.loop.exec_() + if(not self.running): + break + PlotAux.Plot(self.ship, self.form.trim.value(), points) return True def reject(self): + if not self.ship: + return False + if self.running: + self.running = False + return return True def clicked(self, index): @@ -339,6 +358,10 @@ class TaskPanel: if (nPoints % 2) or (nPoints2 % 2): continue result.append(f) + self.timer.start(0.0) + self.loop.exec_() + if(not self.running): + break return result def createTask():