Simplified output of GeometricSolver.get_cluster.
New decompositionView (replacing compositionView) in workbench
This commit is contained in:
parent
fd0438c86d
commit
38c71c882b
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user