Tulip-Dev / tulip

Large graphs analysis, drawing and visualization framework
http://tulip.labri.fr/
GNU Lesser General Public License v3.0
125 stars 24 forks source link

[Python] Tulip cannot select nodes if the nodes coordinators are not symmetric #144

Open lqtruong opened 5 years ago

lqtruong commented 5 years ago

Dear Tulip Dev,

Currently, we got an issue when we were trying to select the nodes of Tulip's view. Below are our investigation.

The below example is showing issue

#!/bin/python

"""Test interaction with view"""
from tulip import tlp
from tulipgui import tlpgui

WIDTH = 256
HEIGHT = 256

g = tlp.newGraph()

viewLayout = g.getLayoutProperty("viewLayout")
viewSelection = g.getBooleanProperty("viewSelection")
viewColor = g.getColorProperty("viewColor")
viewLabel = g.getStringProperty("viewLabel")

nodes = g.addNodes(4)
n1 = nodes[0]
n2 = nodes[1]
n3 = nodes[2]
n4 = nodes[3]

# (*) When the coordinators are not symmetric, the result was not as expected.
viewLayout[n1] = (-17,-5,0)
viewLayout[n2] = (-14,-4,0)
viewLayout[n3] = (-11,-5,0)
viewLayout[n4] = (-15,-7,0)

gui = tlpgui.createNodeLinkDiagramView(g)

gui.resize(WIDTH, HEIGHT)
gui.setQuickAccessBarVisible(False) 
gui.setOverviewVisible(False)
gui.centerView()
gui.draw()

for nodei in g.getNodes():
    worldToView = gui.worldToView(viewLayout[nodei])
    (found, node, edge) = gui.pickNodeEdge(worldToView[0], worldToView[1], True, False)
    print("Pick Node {}".format((found, node, edge)))

    # colorize selected node
    if found:
        viewColor[nodei] = (0, 0, 255)  # Blue
        viewSelection[nodei] = True
        gui.draw()  # reflect on UI

input("wait")

Expected: All nodes should be selected. Actual result: None of the nodes were selected Screenshot from 2019-07-12 14-59-58

But when I replaced the coordinators of the nodes with the symmetric ones, all nodes were perfectly selected as expected, below is the code that worked perfectly.

Replace

# (*) When the coordinators are not symmetric, the result was not as expected.
viewLayout[n1] = (-17,-5,0)
viewLayout[n2] = (-14,-4,0)
viewLayout[n3] = (-11,-5,0)
viewLayout[n4] = (-15,-7,0)

by

# Attention: to replace the previous nodes coordinators {e.g. previous code at (*)} 
#  by the symmetric ones as followings ==> The result is perfect.
viewLayout[n1] = (-3, 3, 0)
viewLayout[n2] = (-3, -3, 0)
viewLayout[n3] = (3, 3, 0)
viewLayout[n4] = (3, -3, 0)

Actual result: All of the nodes were selected (as expected) Screenshot from 2019-07-12 15-01-24

Could you please help me to check this case? Thank you very much.

Best regards, Truong.

rgiot commented 5 years ago

I do not know if it is a bug of your code, or Tulip or a lack of explanations in the documentation. However, I have found the reason and a workaround.

Y axis needs to be reverted: instead of using the Y coordinate computed by worldToView, use the height of view substracted by this Y coordinate. @p-mary or @anlambert : is it the normal behavior ? I let you close (or not) the comment depending on the answer. Because it has other impacts: the suer may change the height of the window; so it should be obtained programmaticlly and not hardcoded.

So your second test is faulty and does not work despite the apperances : the picked nodes are not the good ones, but the mirrored ones.

Look at this updated example that works:

#!/bin/python

"""Test interaction with view"""
from tulip import tlp
from tulipgui import tlpgui

WIDTH = 512
HEIGHT = 512

g = tlp.newGraph()

viewLayout = g.getLayoutProperty("viewLayout")
viewSelection = g.getBooleanProperty("viewSelection")
viewColor = g.getColorProperty("viewColor")
viewLabel = g.getStringProperty("viewLabel")

nodes = g.addNodes(6)
n1 = nodes[0]
n2 = nodes[1]
n3 = nodes[2]
n4 = nodes[3]

n5 = nodes[4]
n6 = nodes[5]

# (*) When the coordinators are not symmetric, the result was not as expected.
viewLayout[n1] = (-9, 9, 0)
viewLayout[n2] = (-9, -9, 0)
viewLayout[n3] = (9, 9, 0)
viewLayout[n4] = (9, -9, 0)

viewLayout[n5] = (3, 3, 0)
viewLayout[n6] = (3, -9, 0)

gui = tlpgui.createNodeLinkDiagramView(g)

gui.resize(WIDTH, HEIGHT)
gui.setQuickAccessBarVisible(False) 
gui.setOverviewVisible(False)
gui.setViewOrtho(True)
gui.centerView()
gui.draw()

for nodei in g.getNodes():
    worldToView = gui.worldToView(viewLayout[nodei])
    print("screen {}".format(worldToView))
    (found, node, edge) = gui.pickNodeEdge(int(worldToView[0]), HEIGHT-int(worldToView[1]), True, False)
    print("Pick Node {}".format((found, node, edge)))

    # colorize selected node
    if found:
        viewColor[nodei] = (0, 0, 255)  # Blue
        viewSelection[nodei] = True
        gui.draw()  # reflect on UI

input("wait")

image