graph layout

This commit is contained in:
kwikrick 2012-09-07 06:48:58 +00:00
parent 94d65af760
commit a4bee26e4e
3 changed files with 74 additions and 10 deletions

View File

@ -47,7 +47,6 @@ class CVConnection(QtGui.QGraphicsItem):
self.nodeFrom = nodeFrom
self.nodeTo = nodeTo
self.beziercurve = None
self.paintRect = None
self.setZValue(1)
self.determinePath()

View File

@ -95,7 +95,29 @@ class DecompositionView(QtGui.QDialog):
n = len(c.variables)
layers[n].append(c)
# sort clusters in layers
# ??
# start from layer N (largest clusters)
# clusters are initially ordered according to the order in which sub-clusters appear in the previous (n+1) layer
for n in reversed(range(1,N)):
print "ordering layers",n
# find subiable pseudo-ordering in previous layers
subordervalue = {}
clusterindex = 0
for cluster in layers[n+1]:
clusterindex = clusterindex+1
for sub in cluster.subs:
# order by first appearence in cluster from left to right
if sub not in subordervalue:
subordervalue[sub] = clusterindex
# determine pseudo-order clusters in this layers: sum subordervalues per cluster
clusterordervalue = {}
for cluster in layers[n]:
clusterordervalue[cluster] = 0
for sub in cluster.subs:
if sub in subordervalue:
clusterordervalue[cluster] += subordervalue[sub]
# sort clusters in layers
layers[n].sort(lambda x,y:clusterordervalue[x]<clusterordervalue[y])
# map GeometricDecompositions to CVClusters
for n in range(0,N+1):
layer = layers[n]
@ -112,10 +134,10 @@ class DecompositionView(QtGui.QDialog):
for child in c.subs:
self.ui.graphicsScene.addItem(CVConnection(self, self.map[c], self.map[child]))
# iteratively improve graph layout
# self.optimiseGraphLayout()
self.optimiseGraphLayout()
def optimiseGraphLayout(self):
print "optimising graph layout..."
# create a graph of clusters and connections
graph = geosolver.graph.Graph()
if self.ui.graphicsScene != None:
@ -140,10 +162,10 @@ class DecompositionView(QtGui.QDialog):
for j in range(i+1,n):
c1 = l[i]
c2 = l[j]
box1 = c1.paintRect.translated(c1.position)
box1 = c1.boundingRect().translated(c1.position)
box1.setWidth(2*box1.width())
box1.setHeight(2*box1.height())
box2 = c2.paintRect.translated(c2.position)
box2 = c2.boundingRect().translated(c2.position)
box2.setWidth(2*box2.width())
box2.setHeight(2*box2.height())
#print "box 1", box1
@ -166,20 +188,48 @@ class DecompositionView(QtGui.QDialog):
for e in graph.edges():
c1 = e[0]
c2 = e[1]
box1 = c1.paintRect.translated(c1.position)
box2 = c2.paintRect.translated(c2.position)
box1 = c1.boundingRect().translated(c1.position)
box2 = c2.boundingRect().translated(c2.position)
centerdiff = box2.center()-box1.center()
direction = numpy.array([centerdiff.x(),centerdiff.y()])
norm = numpy.linalg.norm(direction)
if norm != 0:
direction = direction / numpy.linalg.norm(direction)
goal = box1.height() + box2.height() + box1.width() + box2.width()
force = (norm - goal) / 20.0
#goal = max(box1.width(),box2.width())
goal = 5 * box1.height()
force = (norm - goal) / 50.0
#direction[1] = 0.0
c1.force += +force*direction;
c2.force += -force*direction;
#print "force ", force
# determine forces due to clusters overlapping connections
n = len(l)
for c in graph.vertices():
for e in graph.edges():
box1 = c.boundingRect().translated(c.position)
box1.setWidth(2*box1.width())
box1.setHeight(2*box1.height())
con = graph.get(e[0],e[1])
box2 = con.boundingRect()
box2.setWidth(2*box2.width())
box2.setHeight(2*box2.height())
#print "box 1", box1
#print "box 2", box2
if box1.intersects(box2):
#print "intersects"
force = box1.intersected(box2).width() + box1.intersected(box2).height()
centerdiff = box2.center()-box1.center()
direction = numpy.array([centerdiff.x(),centerdiff.y()])
norm = numpy.linalg.norm(direction)
if norm != 0:
direction = direction / numpy.linalg.norm(direction)
#direction[1] = 0.0
c.force += -force*direction / 50.0;
#print "force 1", c1.force
#print "force 2", c2.force
# apply forces
for c in l:
move = QtCore.QPointF(c.force[0],c.force[1])
@ -191,6 +241,7 @@ class DecompositionView(QtGui.QDialog):
for e in graph.edges():
connector = graph.get(e[0],e[1])
connector.determinePath()
print "done"
def updateViewports(self):
self.viewportManager.updateViewports()

View File

@ -0,0 +1,14 @@
<!DOCTYPE Geometric Constraints>
<Objects>
<Point posX="-101.660079249" posY="0.0" key="p1" posZ="-89.9399" name="p1"/>
<Point posX="116.978718304" posY="0.0" key="p4" posZ="-91.3343" name="p4"/>
<DistanceConstraint pBeginKey="p1" key="d5" distance="218.643244" pEndKey="p4" name="d5" fixed="False"/>
<Point posX="-1.39260383038" posY="0.0" key="p8" posZ="66.2348" name="p8"/>
<DistanceConstraint pBeginKey="p4" key="d9" distance="197.078134705" pEndKey="p8" name="d9" fixed="False"/>
<DistanceConstraint pBeginKey="p8" key="d12" distance="185.59122702" pEndKey="p1" name="d12" fixed="False"/>
<Point posX="0.0" posY="94.8203361356" key="p15" posZ="-27.1911" name="p15"/>
<DistanceConstraint pBeginKey="p1" key="d16" distance="152.522391009" pEndKey="p15" name="d16" fixed="False"/>
<DistanceConstraint pBeginKey="p15" key="d19" distance="163.674270388" pEndKey="p4" name="d19" fixed="False"/>
<DistanceConstraint pBeginKey="p15" key="d24" distance="133.121126352" pEndKey="p8" name="d24" fixed="False"/>
<Prototypes numberOfImports="0" number="27"/>
</Objects>