Simplified output of GeometricSolver.get_cluster.

New decompositionView (replacing compositionView) in workbench
This commit is contained in:
kwikrick 2009-11-16 20:01:47 +00:00
parent fd0438c86d
commit 38c71c882b
7 changed files with 432 additions and 946 deletions

View File

@ -150,6 +150,7 @@ class ClusterSolver3D(ClusterSolver):
# end for method # end for method
return False return False
def _add_method_complete(self, merge): def _add_method_complete(self, merge):
# diag_print("add_method_complete "+str(merge), "clsolver3D") # diag_print("add_method_complete "+str(merge), "clsolver3D")
# check that method has one output # check that method has one output

View File

@ -311,16 +311,26 @@ class GeometricSolver (Listener):
def get_cluster(self): def get_cluster(self):
"""Returns a GeometricCluster (the root of a tree of clusters), """Returns a GeometricCluster (the root of a tree of clusters),
describing the solutions and the decomposition of the problem.""" describing the solutions and the decomposition of the problem."""
# several drcluster can maps to a single geoclusters
map = {} map = {}
geoclusters = []
# map dr clusters # map dr clusters
for drcluster in self.dr.rigids(): for drcluster in self.dr.rigids():
# create geo cluster and map to drcluster (and vice versa) # create geocluster and map to drcluster (and vice versa)
geocluster = GeometricCluster() geocluster = GeometricCluster(drcluster.vars)
map[drcluster] = geocluster if geocluster not in map:
map[geocluster] = drcluster map[drcluster] = geocluster
# determine variables map[geocluster] = [drcluster]
for var in drcluster.vars: geoclusters.append(geocluster)
geocluster.variables.append(var) else:
geocluster = map[map[geocluster][0]]
map[drcluster] = geocluster
map[geocluster].append(drcluster)
for geocluster in geoclusters:
# pick drcluster with fewest solutions
drclusters = map[geocluster]
drcluster = min(drclusters, key=lambda c: len(self.dr.get(drcluster)))
# determine solutions # determine solutions
solutions = self.dr.get(drcluster) solutions = self.dr.get(drcluster)
underconstrained = False underconstrained = False
@ -332,6 +342,8 @@ class GeometricSolver (Listener):
# determine flag # determine flag
if drcluster.overconstrained: if drcluster.overconstrained:
geocluster.flag = GeometricCluster.S_OVER geocluster.flag = GeometricCluster.S_OVER
elif geocluster.solutions == None:
geocluster.flag = GeometricCluster.UNSOLVED
elif len(geocluster.solutions) == 0: elif len(geocluster.solutions) == 0:
geocluster.flag = GeometricCluster.I_OVER geocluster.flag = GeometricCluster.I_OVER
elif underconstrained: elif underconstrained:
@ -339,37 +351,24 @@ class GeometricSolver (Listener):
else: else:
geocluster.flag = GeometricCluster.OK geocluster.flag = GeometricCluster.OK
# determine subclusters # determine subclusters
for method in self.dr.methods(): for method in self.dr.methods():
if not isinstance(method, PrototypeMethod) and not isinstance(method, SelectionMethod):
for out in method.outputs(): for out in method.outputs():
if isinstance(out, Rigid): if isinstance(out, Rigid):
parent = map[out] parent = map[out]
for inp in method.inputs(): for inp in method.inputs():
if isinstance(inp, Rigid): if isinstance(inp, Rigid):
parent.subs.append(map[inp]) sub = map[inp]
if sub != parent:
# combine clusters due to selection parent.subs.append(sub)
if True:
for method in self.dr.methods():
if isinstance(method, PrototypeMethod):
incluster = method.inputs()[0]
outcluster = method.outputs()[0]
geoin = map[incluster]
geoout = map[outcluster]
geoout.subs = list(geoin.subs)
for method in self.dr.methods():
if isinstance(method, SelectionMethod):
incluster = method.inputs()[0]
outcluster = method.outputs()[0]
geoin = map[incluster]
geoout = map[outcluster]
geoout.subs = list(geoin.subs)
# determine top-level result # determine top-level result
rigids = filter(lambda c: isinstance(c, Rigid), self.dr.top_level()) rigids = filter(lambda c: isinstance(c, Rigid), self.dr.top_level())
if len(rigids) == 0: if len(rigids) == 0:
# no variables in problem? # no variables in problem?
result = GeometricCluster() result = GeometricCluster(self.problem.cg.variables())
result.variables = [] result.variables = []
result.subs = [] result.subs = []
result.solutions = [] result.solutions = []
@ -379,12 +378,13 @@ class GeometricSolver (Listener):
result = map[rigids[0]] result = map[rigids[0]]
else: else:
# structurally underconstrained cluster # structurally underconstrained cluster
result = GeometricCluster() result = GeometricCluster(self.problem.cg.variables())
result.flag = GeometricCluster.S_UNDER result.flag = GeometricCluster.S_UNDER
for rigid in rigids: for rigid in rigids:
result.subs.append(map[rigid]) result.subs.append(map[rigid])
return result return result
def get_solutions(self): def get_solutions(self):
"""Returns a list of Configurations, which will be empty if the """Returns a list of Configurations, which will be empty if the
problem has no solutions. Note: this method is problem has no solutions. Note: this method is
@ -647,13 +647,22 @@ class GeometricCluster:
UNSOLVED = "unsolved" UNSOLVED = "unsolved"
EMPTY = "empty" EMPTY = "empty"
def __init__(self): def __init__(self, variables):
"""initialise an empty new cluster""" """initialise an empty new cluster"""
self.variables = [] self.variables = frozenset(variables)
self.solutions = [] self.solutions = []
self.subs = [] self.subs = []
self.flag = GeometricCluster.OK self.flag = GeometricCluster.OK
def __eq__(self, other):
if isinstance(other, GeometricCluster):
return self.variables == other.variables
else:
return False
def __hash__(self):
return hash(self.variables)
def __str__(self): def __str__(self):
return self._str_recursive() return self._str_recursive()
@ -679,7 +688,7 @@ class GeometricCluster:
s = s + spaces + "|...\n" s = s + spaces + "|...\n"
# pritn cluster # pritn cluster
s = spaces + "cluster " + str(result.variables) + " " + str(result.flag) + " " + str(len(result.solutions)) + " solutions\n" + s s = spaces + "cluster " + str(list(result.variables)) + " " + str(result.flag) + " " + str(len(result.solutions)) + " solutions\n" + s
return s return s
# def # def

View File

@ -5,324 +5,324 @@ from cvitems import CVCluster, CVPoint, CVInfoOverlay, CVConnection
from parameters import Settings from parameters import Settings
class CompositionView(QtGui.QDialog): class CompositionView(QtGui.QDialog):
""" A view where the decomposition of the system of constraints is visualised as a tree """ """ A view where the decomposition of the system of constraints is visualised as a tree """
def __init__(self, viewport, viewportMngr, vpType, prototypeMngr, parent=None): def __init__(self, viewport, viewportMngr, vpType, prototypeMngr, parent=None):
""" Initialization of the CompositionView class """ Initialization of the CompositionView class
Parameters: Parameters:
viewportMngr - the manager of the viewports where the composition view can reside in viewportMngr - the manager of the viewports where the composition view can reside in
prototypeMngr - the manager of the prototypes is used to obtain the results of the solver prototypeMngr - the manager of the prototypes is used to obtain the results of the solver
""" """
QtGui.QDialog.__init__(self, parent) QtGui.QDialog.__init__(self, parent)
self.prototypeManager = prototypeMngr self.prototypeManager = prototypeMngr
self.viewport = viewport self.viewport = viewport
self.viewportManager = viewportMngr self.viewportManager = viewportMngr
self.settings = Settings() self.settings = Settings()
self.setWindowFlags(QtCore.Qt.Window) self.setWindowFlags(QtCore.Qt.Window)
self.timer = QtCore.QObject() self.timer = QtCore.QObject()
#QtCore.qsrand(QtCore.QTime(0,0,0).secsTo(QtCore.QTime.currentTime())) #QtCore.qsrand(QtCore.QTime(0,0,0).secsTo(QtCore.QTime.currentTime()))
self.tree = Tree(None) self.tree = Tree(None)
self.infoOverlay = CVInfoOverlay(self) self.infoOverlay = CVInfoOverlay(self)
self.connections = [] self.connections = []
self.ui = Ui_compositionView() self.ui = Ui_compositionView()
self.ui.setupUi(self) self.ui.setupUi(self)
self.ui.graphicsView.setupViewport(QtOpenGL.QGLWidget(QtOpenGL.QGLFormat(QtOpenGL.QGL.SampleBuffers|QtOpenGL.QGL.DoubleBuffer))) self.ui.graphicsView.setupViewport(QtOpenGL.QGLWidget(QtOpenGL.QGLFormat(QtOpenGL.QGL.SampleBuffers|QtOpenGL.QGL.DoubleBuffer)))
#self.ui.graphicsView.setViewport(QtGui.QWidget()) #self.ui.graphicsView.setViewport(QtGui.QWidget())
self.ui.graphicsView.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform) self.ui.graphicsView.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform)
self.collapsed = False self.collapsed = False
self.currentTool = None self.currentTool = None
self.viewportType = vpType self.viewportType = vpType
self.first = False self.first = False
self.nodeId = 0 self.nodeId = 0
self.overConstrainedColor = QtGui.QColor(0,0,255) self.overConstrainedColor = QtGui.QColor(0,0,255)
self.underConstrainedColor = QtGui.QColor(255,0,0) self.underConstrainedColor = QtGui.QColor(255,0,0)
self.wellConstrainedColor = QtGui.QColor(0,255,0) self.wellConstrainedColor = QtGui.QColor(0,255,0)
self.unsolvedColor = QtGui.QColor(125,124,255) self.unsolvedColor = QtGui.QColor(125,124,255)
self.setScene() self.setScene()
self.createTriggers() self.createTriggers()
def createTriggers(self): def createTriggers(self):
""" Create the triggers for the components in the graphical window """ """ Create the triggers for the components in the graphical window """
QtCore.QObject.connect(self.ui.zoomInButton,QtCore.SIGNAL("clicked()"),self.zoomIn) QtCore.QObject.connect(self.ui.zoomInButton,QtCore.SIGNAL("clicked()"),self.zoomIn)
QtCore.QObject.connect(self.ui.zoomOutButton,QtCore.SIGNAL("clicked()"),self.zoomOut) QtCore.QObject.connect(self.ui.zoomOutButton,QtCore.SIGNAL("clicked()"),self.zoomOut)
QtCore.QObject.connect(self.ui.fitButton, QtCore.SIGNAL("clicked()"), self.fit) QtCore.QObject.connect(self.ui.fitButton, QtCore.SIGNAL("clicked()"), self.fit)
QtCore.QObject.connect(self.ui.collapseButton, QtCore.SIGNAL("clicked()"), self.collapse) QtCore.QObject.connect(self.ui.collapseButton, QtCore.SIGNAL("clicked()"), self.collapse)
QtCore.QObject.connect(self.ui.graphicsScene, QtCore.SIGNAL("changed(const QList<QRectF> & )"), self.updateSceneRect) QtCore.QObject.connect(self.ui.graphicsScene, QtCore.SIGNAL("changed(const QList<QRectF> & )"), self.updateSceneRect)
QtCore.QObject.connect(self.ui.verticalSlider,QtCore.SIGNAL("valueChanged(int)"),self.setupMatrix) QtCore.QObject.connect(self.ui.verticalSlider,QtCore.SIGNAL("valueChanged(int)"),self.setupMatrix)
QtCore.QObject.connect(self.settings.dvData,QtCore.SIGNAL("treeOrientationChanged()"), self.updateTreeOrientation) QtCore.QObject.connect(self.settings.dvData,QtCore.SIGNAL("treeOrientationChanged()"), self.updateTreeOrientation)
def setScene(self): def setScene(self):
""" The scene where the tree is visualised in, will be created and set """ """ The scene where the tree is visualised in, will be created and set """
self.initView() self.initView()
def getViewportType(self): def getViewportType(self):
return self.viewportType return self.viewportType
def updateGL(self): def updateGL(self):
self.update() self.update()
def createDecomposition(self): def createDecomposition(self):
""" Create a new decomposition. If an older one exists it will be removed. """ """ Create a new decomposition. If an older one exists it will be removed. """
if self.ui.graphicsScene != None: if self.ui.graphicsScene != None:
for item in self.ui.graphicsView.items(): for item in self.ui.graphicsView.items():
item.hide() item.hide()
if item.parentItem() == None: if item.parentItem() == None:
self.ui.graphicsScene.removeItem(item) self.ui.graphicsScene.removeItem(item)
if self.tree.root != None: if self.tree.root != None:
self.tree.clear(self.tree.root) self.tree.clear(self.tree.root)
del self.connections[:] del self.connections[:]
del self.settings.dvData.fixedClusterIds[:] del self.settings.dvData.fixedClusterIds[:]
self.initView() self.initView()
def initView(self): def initView(self):
""" Updating the view with new data and nodes for the visualisation of the tree """ """ Updating the view with new data and nodes for the visualisation of the tree """
if self.prototypeManager.result != None: if self.prototypeManager.result != None:
self.nodeId = 0 self.nodeId = 0
self.tree.root = self.populateTree(self.prototypeManager.result.subs, None, self.prototypeManager.result) self.tree.root = self.populateTree(self.prototypeManager.result.subs, None, self.prototypeManager.result)
# return # Rick 20090522 debug self.drawTree(self.ui.graphicsScene, self.tree.root, self.tree.root.children)
self.drawTree(self.ui.graphicsScene, self.tree.root, self.tree.root.children) self.drawConnections(self.ui.graphicsScene)
self.drawConnections(self.ui.graphicsScene) self.determineCollapse(self.tree.root)
self.determineCollapse(self.tree.root) self.showConnections()
self.showConnections() self.tree.root.showChildren()
self.tree.root.showChildren() self.updateTree()
self.updateTree() self.addInfoOverlay()
self.addInfoOverlay() self.initFixStates()
self.initFixStates()
def updateViewports(self): def updateViewports(self):
self.viewportManager.updateViewports() self.viewportManager.updateViewports()
def updateTree(self): def updateTree(self):
""" Update the tree, where the node positions and connections between the nodes are updated """ """ Update the tree, where the node positions and connections between the nodes are updated """
self.tree.clear(self.tree.root) self.tree.clear(self.tree.root)
self.tree.updateTree() self.tree.updateTree()
self.updateNodePositions(self.tree.root) self.updateNodePositions(self.tree.root)
self.showConnections() self.showConnections()
def populateTree(self, nodes, rootNode, currentNode, id=0): def populateTree(self, nodes, rootNode, currentNode, id=0):
""" Recursive function to populate a tree, from the results of the solver to finally display it in the Decomposition View. """ Recursive function to populate a tree, from the results of the solver to finally display it in the Decomposition View.
The population is depth first. The population is depth first.
Parameters: Parameters:
nodes - the childnodes nodes - the childnodes
rootNode - root node of the (partial) tree rootNode - root node of the (partial) tree
currentNode - the current node of the result obtained from the constraints solver currentNode - the current node of the result obtained from the constraints solver
""" """
if len(currentNode.variables) == 1: if len(currentNode.variables) == 1:
self.createLeafPoint(rootNode, currentNode.variables[0], self.nodeId) self.createLeafPoint(rootNode, currentNode.variables[0], self.nodeId)
else: else:
newNode = CVCluster(self, rootNode, self.nodeId) newNode = CVCluster(self, rootNode, self.nodeId)
newNode.flag = currentNode.flag newNode.flag = currentNode.flag
newNode.variables = currentNode.variables newNode.variables = currentNode.variables
needCollapse = False needCollapse = False
""" Add children to the rootNode to create the full tree """ """ Add children to the rootNode to create the full tree """
if rootNode != None: if rootNode != None:
#self.setCollapse(newNode) #self.setCollapse(newNode)
rootNode.children += [newNode] rootNode.children += [newNode]
""" Create a connection between the nodes if the current node has a rootnode""" """ Create a connection between the nodes if the current node has a rootnode"""
newConnection = CVConnection(self, rootNode, newNode) newConnection = CVConnection(self, rootNode, newNode)
self.connections += [newConnection] self.connections += [newConnection]
""" get the leaf nodes """ """ get the leaf nodes """
if len(nodes) == 0: if len(nodes) == 0:
for variable in newNode.variables: for variable in newNode.variables:
self.createLeafPoint(newNode, variable, self.nodeId) self.createLeafPoint(newNode, variable, self.nodeId)
for node in nodes: # Rick 20091116 - skip this for debug
self.nodeId += 1 # for node in nodes:
self.populateTree(node.subs, newNode, node, self.nodeId) # self.nodeId += 1
# self.populateTree(node.subs, newNode, node, self.nodeId)
""" To return the whole tree, a check will be performed for the rootnode """ """ To return the whole tree, a check will be performed for the rootnode """
if rootNode == None: if rootNode == None:
return newNode return newNode
def initFixStates(self): def initFixStates(self):
""" Initialize the fix states from another view if available """ """ Initialize the fix states from another view if available """
for fixedId in self.settings.dvData.fixedClusterIds: for fixedId in self.settings.dvData.fixedClusterIds:
self.updateState(fixedId, True, self.tree.root) self.updateState(fixedId, True, self.tree.root)
def stateChange(self, id, fixed): def stateChange(self, id, fixed):
""" Change the state of the cluster which might be fixed and report it """ Change the state of the cluster which might be fixed and report it
to the other decomposition views. to the other decomposition views.
Paramaters: Paramaters:
id - unique id of the cluster id - unique id of the cluster
fixed - should the clusters be fixed or not fixed - should the clusters be fixed or not
""" """
self.viewportManager.updateDecompositionFixed(id, fixed) self.viewportManager.updateDecompositionFixed(id, fixed)
if fixed: if fixed:
self.settings.dvData.fixedClusterIds += [id] self.settings.dvData.fixedClusterIds += [id]
elif not fixed: elif not fixed:
self.settings.dvData.fixedClusterIds = filter(lambda x:x!=id, self.settings.dvData.fixedClusterIds) self.settings.dvData.fixedClusterIds = filter(lambda x:x!=id, self.settings.dvData.fixedClusterIds)
def updateState(self, id, fixed, rootNode): def updateState(self, id, fixed, rootNode):
""" Update the fixed cluster, with the visuals. """ Update the fixed cluster, with the visuals.
Parameters: Parameters:
id - unique id of the cluster id - unique id of the cluster
fixed - should the cluster be fixed or not fixed - should the cluster be fixed or not
rootNode - recursive funcion to walk the tree rootNode - recursive funcion to walk the tree
""" """
if rootNode.identifier == id: if rootNode.identifier == id:
if fixed and rootNode.isVisible(): if fixed and rootNode.isVisible():
rootNode.fixGraphic.show() rootNode.fixGraphic.show()
rootNode.clusterActive = True rootNode.clusterActive = True
elif fixed and not rootNode.isVisible(): elif fixed and not rootNode.isVisible():
rootNode.fixGraphic.hide() rootNode.fixGraphic.hide()
rootNode.clusterActive = True rootNode.clusterActive = True
else: else:
rootNode.fixGraphic.hide() rootNode.fixGraphic.hide()
rootNode.clusterActive = False rootNode.clusterActive = False
self.prototypeManager.removeClusterObjects([rootNode.permCluster], True, True) self.prototypeManager.removeClusterObjects([rootNode.permCluster], True, True)
rootNode.permCluster = None rootNode.permCluster = None
return True return True
for node in rootNode.children: for node in rootNode.children:
found = self.updateState(id, fixed, node) found = self.updateState(id, fixed, node)
if found: if found:
break break
return False return False
def createLeafPoint(self, node, variable, id): def createLeafPoint(self, node, variable, id):
cvPoint = CVPoint(self, node, id) cvPoint = CVPoint(self, node, id)
cvPoint.setWidthAndHeight(20, 20) cvPoint.setWidthAndHeight(20, 20)
cvPoint.prtRef = self.prototypeManager.getObjectByKey(variable) cvPoint.prtRef = self.prototypeManager.getObjectByKey(variable)
cvPoint.isCollapsed = False cvPoint.isCollapsed = False
cvPoint.canCollapse = False cvPoint.canCollapse = False
#cvPoint.setInfoOverlay() #cvPoint.setInfoOverlay()
node.children += [cvPoint] node.children += [cvPoint]
newConnection = CVConnection(self, node, cvPoint) newConnection = CVConnection(self, node, cvPoint)
self.connections += [newConnection] self.connections += [newConnection]
def setCollapse(self, node): def setCollapse(self, node):
node.isCollapsed = False node.isCollapsed = False
if not isinstance(node, CVPoint): if not isinstance(node, CVPoint):
if not node.collapseFromResult(): if not node.collapseFromResult():
node.updateCluster() node.updateCluster()
def determineCollapse(self, node): def determineCollapse(self, node):
self.setCollapse(node) self.setCollapse(node)
for child in node.children: for child in node.children:
self.determineCollapse(child) self.determineCollapse(child)
def addInfoOverlay(self): def addInfoOverlay(self):
self.ui.graphicsScene.addItem(self.infoOverlay) self.ui.graphicsScene.addItem(self.infoOverlay)
self.infoOverlay.hide() self.infoOverlay.hide()
def drawTree(self, scene, root, childNodes): def drawTree(self, scene, root, childNodes):
""" The different nodes are added to the scene and will automatically be drawn """ The different nodes are added to the scene and will automatically be drawn
Parameters: Parameters:
scene - the scene where the rootnode has to be drawn in scene - the scene where the rootnode has to be drawn in
root - the rootnode of the (sub-) tree root - the rootnode of the (sub-) tree
childNode - the children of this root node childNode - the children of this root node
""" """
root.setPos(root.position) root.setPos(root.position)
scene.addItem(root) scene.addItem(root)
#print "#nodes: ", len(childNodes), " position: ",root.position.x(), " " , root.position.y() #print "#nodes: ", len(childNodes), " position: ",root.position.x(), " " , root.position.y()
for node in childNodes: for node in childNodes:
self.drawTree(scene, node, node.children) self.drawTree(scene, node, node.children)
def drawConnections(self, scene): def drawConnections(self, scene):
""" The connections between the nodes are added to the scene and will automatically be drawn """ The connections between the nodes are added to the scene and will automatically be drawn
Parameters: Parameters:
scene - the scene where the connections has to be drawn in scene - the scene where the connections has to be drawn in
""" """
for connection in self.connections: for connection in self.connections:
#connection.setPos() #connection.setPos()
scene.addItem(connection) scene.addItem(connection)
def showConnections(self): def showConnections(self):
""" Show/hide the connections between the nodes, this depends if the node is collapsed """ """ Show/hide the connections between the nodes, this depends if the node is collapsed """
for connection in self.connections: for connection in self.connections:
connection.setPos(connection.nodeTo.position) connection.setPos(connection.nodeTo.position)
if connection.nodeFrom.isCollapsed or (connection.nodeTo.isVisible() == False): if connection.nodeFrom.isCollapsed or (connection.nodeTo.isVisible() == False):
connection.hide() connection.hide()
else: else:
connection.show() connection.show()
def updateConnections(self): def updateConnections(self):
for connection in self.connections: for connection in self.connections:
connection.update() connection.update()
def nrVisibleConnections(self): def nrVisibleConnections(self):
number = 0 number = 0
#for connection in self.connections: #for connection in self.connections:
#print "x, y: " , connection.x(), connection.y() #print "x, y: " , connection.x(), connection.y()
#print "nr of visible connections: " , number #print "nr of visible connections: " , number
def updateNodePositions(self, node): def updateNodePositions(self, node):
""" Map the position of the nodes in the tree on the graphical view """ Map the position of the nodes in the tree on the graphical view
Parameters: Parameters:
node - a node in the tree for which the position is set node - a node in the tree for which the position is set
""" """
node.setPos(node.position) node.setPos(node.position)
for childNode in node.children: for childNode in node.children:
self.updateNodePositions(childNode) self.updateNodePositions(childNode)
def updateSceneRect(self, rectList=None): def updateSceneRect(self, rectList=None):
self.ui.graphicsScene.setSceneRect(self.ui.graphicsScene.itemsBoundingRect()) self.ui.graphicsScene.setSceneRect(self.ui.graphicsScene.itemsBoundingRect())
def updateTreeOrientation(self): def updateTreeOrientation(self):
self.tree.orientation = self.settings.dvData.treeAlignment self.tree.orientation = self.settings.dvData.treeAlignment
def zoomIn(self): def zoomIn(self):
""" Zoom in the graphics view, by updating the vertical slider """ """ Zoom in the graphics view, by updating the vertical slider """
self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() + 1) self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() + 1)
def zoomOut(self): def zoomOut(self):
""" Zoom out the graphics view, by updating the vertical slider """ """ Zoom out the graphics view, by updating the vertical slider """
self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() - 1) self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() - 1)
def fit(self): def fit(self):
""" Fits the tree exactly in the graphics view """ """ Fits the tree exactly in the graphics view """
self.ui.graphicsView.fitInView(0.0, 0.0, self.ui.graphicsScene.width(), self.ui.graphicsScene.height(), QtCore.Qt.KeepAspectRatio) self.ui.graphicsView.fitInView(0.0, 0.0, self.ui.graphicsScene.width(), self.ui.graphicsScene.height(), QtCore.Qt.KeepAspectRatio)
""" Update the slider """ """ Update the slider """
value = (math.log(self.ui.graphicsView.matrix().m11(),2)*50) + 250.0 value = (math.log(self.ui.graphicsView.matrix().m11(),2)*50) + 250.0
self.ui.verticalSlider.setValue(value) self.ui.verticalSlider.setValue(value)
def collapseAll(self, node): def collapseAll(self, node):
if node.canCollapse: if node.canCollapse:
node.collapse() node.collapse()
for childNode in node.children: for childNode in node.children:
self.collapseAll(childNode) self.collapseAll(childNode)
def expandAll(self, node): def expandAll(self, node):
node.expand() node.expand()
for childNode in node.children: for childNode in node.children:
self.expandAll(childNode) self.expandAll(childNode)
def collapse(self): def collapse(self):
if self.collapsed: if self.collapsed:
self.collapsed = False self.collapsed = False
self.collapseAll(self.tree.root) self.collapseAll(self.tree.root)
else: else:
self.collapsed = True self.collapsed = True
self.expandAll(self.tree.root) self.expandAll(self.tree.root)
self.updateTree() self.updateTree()
self.update() self.update()
def setupMatrix(self, value): def setupMatrix(self, value):
""" Zoom in/out the graphics view, depending on the value of the slider """ Zoom in/out the graphics view, depending on the value of the slider
Parameters Parameters
value - value of the updated slider value - value of the updated slider
""" """
scale = math.pow(2.0, (self.ui.verticalSlider.value()-250.0)/50.0) scale = math.pow(2.0, (self.ui.verticalSlider.value()-250.0)/50.0)
matrix = QtGui.QMatrix() matrix = QtGui.QMatrix()
matrix.scale(scale,scale) matrix.scale(scale,scale)
self.ui.graphicsView.setMatrix(matrix) self.ui.graphicsView.setMatrix(matrix)

View File

@ -1,601 +1,77 @@
from includes import * from includes import *
from tree import Node
from geosolver import GeometricCluster from geosolver import GeometricCluster
from parameters import Settings from parameters import Settings
class CVCluster(QtGui.QGraphicsItem, Node): class CVCluster(QtGui.QGraphicsItem):
""" Visualisation of the clusters (nodes) in the decompositionView """ """ Visualisation of the clusters (nodes) in the decompositionView """
def __init__(self, compView, parentNode, id, parent=None): def __init__(self, compView, cluster, x,y):
QtGui.QGraphicsItem.__init__(self, parent) QtGui.QGraphicsItem.__init__(self)
Node.__init__(self, parentNode)
self.compositionView = compView
self.cluster = cluster
self.position = QtCore.QPointF(x, y)
self.textGraphic = QtGui.QGraphicsSimpleTextItem(str(list(self.cluster.variables)), self)
#self.textGraphic.translate(x,y)
self.paintRect = self.textGraphic.boundingRect()
#self.paintRect.translate(x,y)
self.translate(x,y)
def boundingRect(self):
""" Overridden function where a update area is determined for painting and returned """
return self.paintRect
def paint(self, painter, option, widget):
""" Visualisation of a clusteritem """
painter.setPen(QtGui.QColor(0,155,50))
if self.cluster.flag != None:
if self.cluster.flag == GeometricCluster.OK:
painter.setBrush(QtGui.QBrush(self.compositionView.wellConstrainedColor))
elif self.cluster.flag == GeometricCluster.I_UNDER or self.cluster.flag == GeometricCluster.S_UNDER:
painter.setBrush(QtGui.QBrush(self.compositionView.underConstrainedColor))
elif self.cluster.flag == GeometricCluster.I_OVER or self.cluster.flag == GeometricCluster.S_OVER:
painter.setBrush(QtGui.QBrush(self.compositionView.overConstrainedColor))
elif self.cluster.flag == GeometricCluster.UNSOLVED:
painter.setBrush(QtGui.QBrush(self.compositionView.unsolvedColor))
painter.drawRect(self.paintRect)
self.compositionView = compView
self.setFlags(QtGui.QGraphicsItem.ItemIsSelectable)
self.setAcceptsHoverEvents(True)
self.startAngle = 0
self.spanAngle = 0
self.paintRect = QtCore.QRectF(0, 0, self.width, self.height)
self.boundary = QtCore.QRectF(0.0, 0.0, 0.0, 0.0)
self.fixGraphic = QtGui.QGraphicsSimpleTextItem("F", self)
self.identifier = id
self.bezierCurve = None
self.initAngles()
self.bound = QtCore.QRectF()
self.updateBound()
self.flag = None
self.clusterHighlight = None
self.permCluster = None
self.clusterActive = False
self.fixGraphic.hide()
def initAngles(self):
""" Initialize the angles for the visual representation of the nodes, these are dependent on the orientation of the tree """
self.startAngle = 60 * 16
self.spanAngle = 60 * 16
if self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
self.startAngle = -self.startAngle
self.spanAngle = -self.spanAngle
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
self.startAngle = self.startAngle + 90 * 16
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
self.startAngle = self.startAngle - 90 * 16
def updateBound(self):
""" The bound where the user can click in to do a certain action, is set here. This bound is tightly set around the object """
pointBegin = QtCore.QPointF(0.0, 0.0)
pointBegin.setX((self.paintRect.width()/2.0) * math.cos(math.radians(self.startAngle/16.0)))
pointBegin.setY((self.paintRect.height()/2.0) * math.sin(math.radians(self.startAngle/16.0)))
pointEnd = QtCore.QPointF(0.0, 0.0)
pointEnd.setX((self.paintRect.width()/2.0) * math.cos(math.radians((self.startAngle+self.spanAngle)/16.0)))
pointEnd.setY((self.paintRect.height()/2.0) * math.sin(math.radians((self.startAngle+self.spanAngle)/16.0)))
pointMiddle = QtCore.QPointF(0.0, 0.0)
halfDegree = (self.startAngle+(self.spanAngle/2.0))/16.0
pointMiddle.setX((self.paintRect.width()/2.0) * math.cos(math.radians(halfDegree)))
pointMiddle.setY((self.paintRect.height()/2.0) * math.sin(math.radians(halfDegree)))
if pointBegin.x() < pointMiddle.x() and pointBegin.x() < pointEnd.x():
self.boundary.setLeft(pointBegin.x())
elif pointMiddle.x() < pointEnd.x():
self.boundary.setLeft(pointMiddle.x())
else:
self.boundary.setLeft(pointEnd.x())
if self.boundary.left() > 0.0:
self.boundary.setLeft(0.0)
if pointBegin.x() > pointMiddle.x() and pointBegin.x() > pointEnd.x():
self.boundary.setRight(pointBegin.x())
elif pointMiddle.x() > pointEnd.x():
self.boundary.setRight(pointMiddle.x())
else:
self.boundary.setRight(pointEnd.x())
if self.boundary.right() < 0.0:
self.boundary.setRight(0.0)
if pointBegin.y() < pointMiddle.y() and pointBegin.y() < pointEnd.y():
self.boundary.setBottom(pointBegin.y())
elif pointMiddle.y() < pointEnd.y():
self.boundary.setBottom(pointMiddle.y())
else:
self.boundary.setBottom(pointEnd.y())
if self.boundary.bottom() > 0.0:
self.boundary.setBottom(0.0)
if pointBegin.y() > pointMiddle.y() and pointBegin.y() > pointEnd.y():
self.boundary.setTop(pointBegin.y())
elif pointMiddle.y() > pointEnd.y():
self.boundary.setTop(pointMiddle.y())
else:
self.boundary.setTop(pointEnd.y())
if self.boundary.top() < 0.0:
self.boundary.setTop(0.0)
self.__translateBound()
def __translateBound(self):
""" Translation of the boundary, so that it fits exactly around the figure"""
self.boundary.setLeft(self.boundary.left()+self.paintRect.center().x())
self.boundary.setRight(self.boundary.right()+self.paintRect.center().x())
self.boundary.setTop(-self.boundary.top()+self.paintRect.center().y())
self.boundary.setBottom(-self.boundary.bottom()+self.paintRect.center().y())
def shape(self):
""" Overridden function to set the boundary wherein the user can perform an action """
path = QtGui.QPainterPath()
path.addRect(self.boundary)
return path
def boundingRect(self):
""" Overridden function where a update area is determined for painting and returned """
return self.paintRect
def paint(self, painter, option, widget):
""" Visualisation of a clusteritem """
painter.setPen(QtGui.QColor(0,155,50))
if self.flag != None:
if self.flag == GeometricCluster.OK:
painter.setBrush(QtGui.QBrush(self.compositionView.wellConstrainedColor))
elif self.flag == GeometricCluster.I_UNDER or self.flag == GeometricCluster.S_UNDER:
painter.setBrush(QtGui.QBrush(self.compositionView.underConstrainedColor))
elif self.flag == GeometricCluster.I_OVER or self.flag == GeometricCluster.S_OVER:
painter.setBrush(QtGui.QBrush(self.compositionView.overConstrainedColor))
elif self.flag == GeometricCluster.UNSOLVED:
painter.setBrush(QtGui.QBrush(self.compositionView.unsolvedColor))
painter.drawPie(self.paintRect, self.startAngle, self.spanAngle)
def setInfoOverlay(self):
constrInfo = QtCore.QString("")
if self.flag == GeometricCluster.OK:
constrInfo = QtCore.QString("Well-Constrained\n")
elif self.flag == GeometricCluster.I_UNDER:
constrInfo = QtCore.QString("Inc. Underconstrained\n")
elif self.flag == GeometricCluster.S_UNDER:
constrInfo = QtCore.QString("Struct. Underconstrained\n")
elif self.flag == GeometricCluster.I_OVER:
constrInfo = QtCore.QString("Inc. Overconstrained\n")
elif self.flag == GeometricCluster.S_OVER:
constrInfo = QtCore.QString("Struct. Overconstrained\n")
elif self.flag == GeometricCluster.UNSOLVED:
constrInfo = QtCore.QString("Unsolved\n")
constrInfo.append("Points: ")
for point in self.variables:
pointObject = self.compositionView.prototypeManager.getObjectByKey(point)
if pointObject != None:
constrInfo.append(pointObject.name)
if point != self.variables[-1]:
constrInfo.append(", ")
self.compositionView.infoOverlay.infoText = constrInfo
#painter.setBrush(QtCore.Qt.NoBrush)
#painter.drawRect(self.bound)
def mousePressEvent(self, event):
""" Handling the mouse press, where the cluster (visualisation) and tree can be updated
Parameters:
event - pressed mousebutton
"""
if event.button() == QtCore.Qt.LeftButton:
self.updateCluster()
self.updateBound()
self.compositionView.updateTree()
elif event.button() == QtCore.Qt.RightButton:
if not self.clusterActive:
self.permanentCluster()
self.clusterActive = True
self.fixGraphic.show()
self.compositionView.stateChange(self.identifier, True)
else:
self.compositionView.prototypeManager.removeClusterObjects([self.permCluster], True, True)
self.clusterActive = False
self.fixGraphic.hide()
self.compositionView.stateChange(self.identifier, False)
self.permCluster = None
self.compositionView.prototypeManager.setObjectVisibilityByClusters()
self.compositionView.updateViewports()
def hoverEnterEvent(self, event):
self.setZValue(2)
self.setInfoOverlay()
self.compositionView.infoOverlay.setPosition(event.scenePos())
self.compositionView.infoOverlay.show()
if not self.clusterActive:
self.compositionView.prototypeManager.selectObjectsByKeys(self.variables)
self.highlightCluster()
self.compositionView.update()
self.compositionView.updateViewports()
def hoverMoveEvent(self, event):
self.overlayPosition = self.compositionView.ui.graphicsView.mapFromScene(event.scenePos())
self.compositionView.infoOverlay.setPosition(event.scenePos())
self.compositionView.updateConnections()
self.compositionView.update()
def hoverLeaveEvent(self, event):
self.setZValue(0)
self.compositionView.infoOverlay.infoText = ""
self.compositionView.infoOverlay.hide()
self.compositionView.infoOverlay.update()
if not self.clusterActive:
self.compositionView.prototypeManager.deselectAllObjects()
self.compositionView.prototypeManager.removeClusterObjects([self.clusterHighlight], True, False)
self.compositionView.updateViewports()
def updateCluster(self):
""" Cluster update, where the cluster is (un-)collapsed depending on the state of the cluster, to visualise a certain part of the tree """
if self.canCollapse:
if self.isCollapsed:
self.isCollapsed = False
self.showChildren()
height = self.paintRect.height()*0.5
width = self.paintRect.width()*0.5
height2 = self.paintRect.height()
if self.compositionView.tree.orientation == TreeOrientation.TOP:
self.paintRect.setTop(self.paintRect.top() + height )
self.paintRect.setBottom(self.paintRect.bottom() + height)
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
self.paintRect.setTop(self.paintRect.top()- height )
self.paintRect.setBottom(self.paintRect.bottom() - height)
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
self.paintRect.setLeft(self.paintRect.left() + width)
self.paintRect.setRight(self.paintRect.right() + width)
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
self.paintRect.setLeft(self.paintRect.left() - width)
self.paintRect.setRight(self.paintRect.right() - width)
else:
self.isCollapsed = True
self.showChildren()
height = self.paintRect.height()*0.5
width = self.paintRect.width()*0.5
height2 = self.paintRect.height()
if self.compositionView.tree.orientation == TreeOrientation.TOP:
self.paintRect.setTop(self.paintRect.top() - height)
self.paintRect.setBottom(self.paintRect.bottom() - height)
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
self.paintRect.setTop(self.paintRect.top() + height)
self.paintRect.setBottom(self.paintRect.bottom() + height)
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
self.paintRect.setLeft(self.paintRect.left() - width)
self.paintRect.setRight(self.paintRect.right() - width)
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
self.paintRect.setLeft(self.paintRect.left() + width)
self.paintRect.setRight(self.paintRect.right() + width)
if self.compositionView.tree.orientation == TreeOrientation.LEFT or self.compositionView.tree.orientation == TreeOrientation.RIGHT:
self.startAngle = self.startAngle + 180 * 16
else:
self.startAngle = -self.startAngle
self.spanAngle = -self.spanAngle
def highlightCluster(self):
if self.clusterHighlight != None:
if self.clusterHighlight.temporary:
self.compositionView.prototypeManager.addClusterObject(self.clusterHighlight)
self.clusterHighlight.selected = True
else:
self.clusterHighlight = self.compositionView.prototypeManager.selectClusterObjectByKeys(self.variables)
if self.clusterHighlight == None:
self.clusterHighlight = self.compositionView.prototypeManager.createCluster(self.variables)
if self.clusterHighlight != None:
self.clusterHighlight.temporary = True
if self.clusterHighlight != None:
self.clusterHighlight.selected = True
def permanentCluster(self):
if self.permCluster == None:
self.permCluster = self.compositionView.prototypeManager.createCluster(self.variables, self.flag)
self.permCluster.temporary = True
self.permCluster.fixed = True
self.compositionView.prototypeManager.setObjectVisibilityByClusters()
else:
self.compositionView.prototypeManager.addClusterObject(self.permCluster)
self.permCluster.selected = False
def showChildren(self):
""" Show the children of this node """
if self.isCollapsed or (self.isVisible()==False):
for child in self.children:
child.hide()
child.showChildren()
if child.clusterActive:
child.fixGraphic.hide()
else:
for child in self.children:
child.show()
child.showChildren()
if child.clusterActive:
child.fixGraphic.show()
else:
child.fixGraphic.hide()
def collapseFromResult(self):
if self.flag == GeometricCluster.I_UNDER or self.flag == GeometricCluster.S_UNDER or self.flag == GeometricCluster.I_OVER or self.flag == GeometricCluster.S_OVER or self.flag == GeometricCluster.UNSOLVED:
return True
else:
return False
def collapse(self):
if not self.isCollapsed:
self.updateCluster()
self.updateBound()
def expand(self):
if self.isCollapsed:
self.updateCluster()
self.updateBound()
class CVPoint(QtGui.QGraphicsItem, Node):
""" Visualisation of the leaves of the 'leaf' clusters in the tree """
def __init__(self, compView, parentNode, id, parent=None):
QtGui.QGraphicsItem.__init__(self, parent)
Node.__init__(self, parentNode)
self.compositionView = compView
self.setFlags(QtGui.QGraphicsItem.ItemIsSelectable)
self.setAcceptsHoverEvents(True)
self.startAngle = 0
self.spanAngle = 0
self.paintRect = QtCore.QRectF(0, 0, self.width/2, self.height/2)
self.fixGraphic = QtGui.QGraphicsSimpleTextItem("F", self)
self.fixGraphic.hide()
self.bezierCurve = None
self.flag = None
self.prtRef = None
self.boundary = self.paintRect
self.clusterHighlight = None
self.permCluster = None
self.clusterActive = False
self.identifier = id
def paint(self, painter, option, widget):
painter.setPen(QtGui.QColor(0,155,50))
painter.setBrush(QtGui.QBrush(QtGui.QColor(0,155,50)))
painter.drawEllipse(self.paintRect)
def setInfoOverlay(self):
constrInfo = QtCore.QString("Points \n")
if self.prtRef != None:
constrInfo += "Name: " + self.prtRef.name + "\n"
constrInfo += "Position: (" + str(round(self.prtRef.position[0],2)) + " , " + str(round(self.prtRef.position[1])) + " , " + str(round(self.prtRef.position[2])) + ")"
self.compositionView.infoOverlay.infoText = constrInfo
def mousePressEvent(self, event):
""" Handling the mouse press, where the cluster (visualisation) is handled
Parameters:
event - pressed mousebutton
"""
if event.button() == QtCore.Qt.RightButton:
if not self.clusterActive:
self.permanentCluster()
self.clusterActive = True
self.fixGraphic.show()
self.compositionView.stateChange(self.identifier, True)
else:
self.compositionView.prototypeManager.removeClusterObjects([self.permCluster], True, True)
self.clusterActive = False
self.permCluster = None
self.fixGraphic.hide()
self.compositionView.stateChange(self.identifier, False)
self.compositionView.prototypeManager.setObjectVisibilityByClusters()
self.compositionView.updateViewports()
def hoverEnterEvent(self, event):
self.setZValue(2)
self.setInfoOverlay()
self.compositionView.infoOverlay.setPosition(event.scenePos())
self.compositionView.infoOverlay.show()
if not self.clusterActive:
self.compositionView.prototypeManager.selectObject(self.prtRef)
self.highlightCluster()
self.compositionView.update()
self.compositionView.updateViewports()
def hoverMoveEvent(self, event):
self.compositionView.infoOverlay.setPosition(event.scenePos())
self.compositionView.update()
def hoverLeaveEvent(self, event):
self.setZValue(0)
self.compositionView.infoOverlay.infoText = ""
self.compositionView.infoOverlay.hide()
self.compositionView.infoOverlay.update()
if not self.clusterActive:
self.compositionView.prototypeManager.deselectAllObjects()
self.compositionView.prototypeManager.removeClusterObjects([self.clusterHighlight], True)
self.compositionView.updateViewports()
def highlightCluster(self):
if self.clusterHighlight != None:
if self.clusterHighlight.temporary:
self.compositionView.prototypeManager.addClusterObject(self.clusterHighlight)
self.clusterHighlight.selected = True
else:
self.clusterHighlight = self.compositionView.prototypeManager.selectClusterObjectByKeys([self.prtRef.key])
if self.clusterHighlight == None:
self.clusterHighlight = self.compositionView.prototypeManager.createCluster([self.prtRef.key])
if self.clusterHighlight != None:
self.clusterHighlight.temporary = True
if self.clusterHighlight != None:
self.clusterHighlight.selected = True
def permanentCluster(self):
if self.permCluster == None:
self.permCluster = self.compositionView.prototypeManager.createCluster([self.prtRef.key])
self.permCluster.temporary = True
self.permCluster.fixed = True
self.compositionView.prototypeManager.setObjectVisibilityByClusters()
else:
self.compositionView.prototypeManager.addClusterObject(self.permCluster)
self.permCluster.selected = False
def boundingRect(self):
return self.paintRect
def setWidthAndHeight(self, width, height):
self.width = width
self.height = height
self.paintRect.setWidth(width)
self.paintRect.setHeight(height)
def showChildren(self):
""" Show the children of this node """
if self.isCollapsed or (self.isVisible()==False):
for child in self.children:
child.hide()
child.showChildren()
else:
for child in self.children:
child.show()
child.showChildren()
def collapse(self):
self.isCollapsed = True
def expand(self):
self.isCollapsed = False
class CVInfoOverlay(QtGui.QGraphicsItem):
def __init__(self, compView, parent=None):
QtGui.QGraphicsItem.__init__(self, parent)
self.node = None
self.compositionView = compView
self.infoText = QtCore.QString("")
self.setZValue(3)
self.infoOverlay = QtCore.QRectF(0, 0, 140, 50)
self.overlayPosition = QtCore.QPointF()
self.scenePosition = QtCore.QPointF()
self.overlayBGColor = QtGui.QColor(204, 251, 255, 200)
self.overlayLineColor = QtGui.QColor(33, 116, 154)
self.overlayTextColor = QtGui.QColor(0, 0, 0)
def paint(self, painter, option, widget):
painter.save()
painter.resetMatrix()
painter.translate(self.overlayPosition)
painter.translate(10.0, 10.0)
painter.setPen(self.overlayLineColor)
painter.setBrush(self.overlayBGColor)
painter.drawRect(self.infoOverlay)
infoFont = QtGui.QFont("Arial", 7)
infoFont.setStyleStrategy(QtGui.QFont.ForceOutline)
painter.setFont(infoFont)
painter.setRenderHint(QtGui.QPainter.TextAntialiasing, False)
painter.setPen(self.overlayTextColor)
textRect = QtCore.QRect(self.infoOverlay.left()+4, self.infoOverlay.top(), self.infoOverlay.width()-3, self.infoOverlay.height()-3)
painter.drawText(textRect, QtCore.Qt.AlignLeft|QtCore.Qt.TextWordWrap, self.infoText)
painter.restore()
def setPosition(self, position):
self.scenePosition = position
self.overlayPosition = self.compositionView.ui.graphicsView.mapFromScene(position)
def boundingRect(self):
check = QtCore.QRectF(self.infoOverlay)
return check
class CVConnection(QtGui.QGraphicsItem): class CVConnection(QtGui.QGraphicsItem):
""" Visualisation of the connections between the clusters, where two types of visualisation can be chosen: Bezier(default) and Lines """ """ Visualisation of the connections between the clusters, where two types of visualisation can be chosen: Bezier(default) and Lines """
def __init__(self, compView, nodeFrom , nodeTo, parent=None): def __init__(self, compView, nodeFrom , nodeTo):
QtGui.QGraphicsItem.__init__(self, parent) QtGui.QGraphicsItem.__init__(self)
self.settings = Settings() self.settings = Settings()
self.compositionView = compView self.compositionView = compView
self.nodeFrom = nodeFrom self.nodeFrom = nodeFrom
self.nodeTo = nodeTo self.nodeTo = nodeTo
self.connectType = self.settings.dvData.treeConnection self.beziercurve = None
#self.boundRect = QtCore.QRectF(0.0, 0.0, 0.0, 0.0) self.paintRect = None
self.beziercurve = None self.setZValue(1)
self.paintRect = QtCore.QRectF(0, 0, 0, 0)
self.setZValue(1)
def paint(self, painter, option, widget): self.determinePath()
""" Visualisation of the connection between two nodes """
if self.nodeFrom != None and self.nodeTo != None:
painter.setPen(QtGui.QColor(0,0,0))
diffPosExt = self.paintRect def determinePath(self):
endPoint = self.determineEndpoint(diffPosExt) if self.nodeFrom != None and self.nodeTo != None:
self.beziercurve = QtGui.QPainterPath()
x1 = self.nodeFrom.position.x() + self.nodeFrom.paintRect.width()/2
x2 = self.nodeTo.position.x() + self.nodeTo.paintRect.width()/2
y1 = self.nodeFrom.position.y()
y2 = self.nodeTo.position.y() + self.nodeFrom.paintRect.height()
p1 = QtCore.QPointF(x1,y1)
p2 = QtCore.QPointF(x1,y1+(y2-y1)/2)
p3 = QtCore.QPointF(x2,y1+(y2-y1)/2)
p4 = QtCore.QPointF(x2,y2)
self.beziercurve.moveTo(p1)
self.beziercurve.cubicTo(p2,p3,p4)
if self.connectType == ConnectionType.BEZIER: def paint(self, painter, option, widget):
""" display a bezier curve as connection """ """ Visualisation of the connection between two nodes """
self.beziercurve = QtGui.QPainterPath() if self.beziercurve:
painter.drawPath(self.beziercurve)
if self.compositionView.tree.orientation == TreeOrientation.TOP: def boundingRect(self):
self.beziercurve.moveTo(diffPosExt.x(), diffPosExt.y()) """ Overridden function where a update area is determined for painting and returned """
firstPoint = QtCore.QPointF(diffPosExt.x(), diffPosExt.height()*0.5) return self.beziercurve.boundingRect()
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
self.beziercurve.moveTo(diffPosExt.x(), diffPosExt.bottom())
firstPoint = QtCore.QPointF(diffPosExt.x(), -diffPosExt.height()*0.5 + self.nodeTo.paintRect.height())
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
self.beziercurve.moveTo(diffPosExt.x(), diffPosExt.y())
firstPoint = QtCore.QPointF(diffPosExt.width()*0.5, diffPosExt.y())
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
self.beziercurve.moveTo(diffPosExt.x(), diffPosExt.y())
firstPoint = QtCore.QPointF(self.nodeTo.paintRect.width() + diffPosExt.width()*0.5,diffPosExt.y())
if self.compositionView.tree.orientation == TreeOrientation.TOP:
secondPoint = QtCore.QPointF(diffPosExt.right(),diffPosExt.height()*0.5)
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
secondPoint = QtCore.QPointF(diffPosExt.right(), self.nodeTo.paintRect.height() - diffPosExt.height()*0.5)
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
secondPoint = QtCore.QPointF(diffPosExt.width()*0.5, diffPosExt.bottom())
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
secondPoint = QtCore.QPointF(self.nodeTo.paintRect.width() + diffPosExt.width()*0.5, diffPosExt.bottom())
self.beziercurve.cubicTo(firstPoint, secondPoint, endPoint)
painter.drawPath(self.beziercurve)
elif self.connectType == ConnectionType.LINES:
""" draw a straight line """
if self.compositionView.tree.orientation == TreeOrientation.TOP:
painter.drawLine(QtCore.QPointF(self.nodeTo.paintRect.width()*0.5, 0.0), QtCore.QPointF(endPoint.x(), endPoint.y()))
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
painter.drawLine(QtCore.QPointF(self.nodeTo.paintRect.width()*0.5, self.nodeTo.paintRect.height()), QtCore.QPointF(endPoint.x(), endPoint.y()))
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
painter.drawLine(QtCore.QPointF(0.0, self.nodeTo.paintRect.height()*0.5), QtCore.QPointF(endPoint.x(), endPoint.y()))
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
painter.drawLine(QtCore.QPointF(self.nodeTo.paintRect.width(), self.nodeTo.paintRect.height()*0.5), QtCore.QPointF(endPoint.x(), endPoint.y()))
def areaBetweenNodes(self):
diffPos = self.nodeTo.position - self.nodeFrom.position
area = QtCore.QRectF(0.0, 0.0, 0.0 , 0.0)
if self.compositionView.tree.orientation == TreeOrientation.TOP:
area.setX(self.nodeTo.paintRect.width()*0.5)
area.setY(0.0)
area.setRight(self.nodeFrom.paintRect.width()*0.5 - diffPos.x())
area.setBottom(self.nodeTo.boundary.height()-diffPos.y())
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
area.setX(self.nodeTo.paintRect.width()*0.5)
area.setY(-diffPos.y()+self.nodeFrom.boundary.height())
area.setRight(-diffPos.x()+self.nodeFrom.paintRect.width()*0.5)
area.setBottom(self.nodeTo.paintRect.height())
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
area.setX(0.0)
area.setY(self.nodeTo.paintRect.height()*0.5)
area.setRight(-diffPos.x()+self.nodeFrom.boundary.width())
area.setBottom(-diffPos.y() + self.nodeFrom.paintRect.height()*0.5)
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
area.setX(self.nodeTo.paintRect.width())
area.setY(self.nodeTo.paintRect.height()*0.5)
area.setRight(-diffPos.x() + self.nodeFrom.paintRect.width()*0.5)
area.setBottom(-diffPos.y() + self.nodeFrom.paintRect.height()*0.5)
return area
def determineEndpoint(self, area):
endPoint = QtCore.QPointF(0.0, 0.0)
if self.compositionView.tree.orientation == TreeOrientation.TOP:
endPoint.setX(area.right())
endPoint.setY(area.height())
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
endPoint.setX(area.right())
endPoint.setY(area.y())
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
endPoint.setX(area.right())
endPoint.setY(area.bottom())
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
endPoint.setX(area.right())
endPoint.setY(area.bottom())
return endPoint
def boundingRect(self):
""" Overridden function where a update area is determined for painting and returned """
self.paintRect = self.areaBetweenNodes()
return self.paintRect

View File

@ -1,4 +1,4 @@
import preferencesDlg, compositionView import preferencesDlg, decompositionView
from includes import * from includes import *
from viewportManager import * from viewportManager import *
from prototypeObjects import PrototypeManager from prototypeObjects import PrototypeManager
@ -191,7 +191,7 @@ class Ui_MainWindow(QtGui.QMainWindow):
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock)
def createDecompositionView(self): def createDecompositionView(self):
self.compositionView = CompositionView(None, self.viewportManager, ViewportType.DECOMPOSITION ,PrototypeManager()) self.compositionView = DecompositionView(None, self.viewportManager, ViewportType.DECOMPOSITION ,PrototypeManager())
def createSolutionView(self): def createSolutionView(self):
self.solutionView = SolutionView(self, self.viewportManager, ViewportType.SOLUTION ,PrototypeManager()) self.solutionView = SolutionView(self, self.viewportManager, ViewportType.SOLUTION ,PrototypeManager())

View File

@ -6,7 +6,7 @@ from parameters import Settings
class SolutionView(QtGui.QDialog): class SolutionView(QtGui.QDialog):
""" Visualises the solution from the constraint solver. """ """ Visualises the solution from the constraint solver. """
def __init__(self, mainWindow, viewportMngr, vpType, prototypeMngr, isViewport=False, parent=None): def __init__(self, mainWindow, viewportMngr, vpType, prototypeMngr, isViewport=False, parent=None):
""" Initialization of the CompositionView class """ Initialization of the SolutionView class
Parameters: Parameters:
mainWindow - main window of the application, necessary for updating mainWindow - main window of the application, necessary for updating

View File

@ -1,5 +1,5 @@
from includes import * from includes import *
from compositionView import CompositionView from decompositionView import DecompositionView
from solutionView import SolutionView from solutionView import SolutionView
from prototypeObjects import PrototypeManager from prototypeObjects import PrototypeManager
from glViewer import * from glViewer import *
@ -153,7 +153,7 @@ class Viewport(QtGui.QScrollArea):
elif viewportName == "Perspective": elif viewportName == "Perspective":
self.glViewport = GLViewport(self, ViewportType.PERSPECTIVE, None, QtOpenGL.QGLFormat(QtOpenGL.QGL.SampleBuffers)) self.glViewport = GLViewport(self, ViewportType.PERSPECTIVE, None, QtOpenGL.QGLFormat(QtOpenGL.QGL.SampleBuffers))
elif viewportName == "Decomposition": elif viewportName == "Decomposition":
self.glViewport = CompositionView(self, self.viewportManager, ViewportType.DECOMPOSITION, PrototypeManager()) #self.getMainWindow().compositionView # self.glViewport = DecompositionView(self, self.viewportManager, ViewportType.DECOMPOSITION, PrototypeManager()) #self.getMainWindow().compositionView #
elif viewportName == "Solution": elif viewportName == "Solution":
self.solutionView = SolutionView(self.getMainWindow(), self.viewportManager, ViewportType.SOLUTION, PrototypeManager(), True) self.solutionView = SolutionView(self.getMainWindow(), self.viewportManager, ViewportType.SOLUTION, PrototypeManager(), True)
self.glViewport = self.solutionView.solutionWidget self.glViewport = self.solutionView.solutionWidget