klayjs icon indicating copy to clipboard operation
klayjs copied to clipboard

intCoordinates results in misaligned edges originating from and targeting the same port

Open jbeard4 opened this issue 7 years ago • 5 comments

Please consider the following example:

Options:

{
  "algorithm": "de.cau.cs.kieler.klay.layered",
  "spacing": 10,
  "borderSpacing" : 10,
  "labelSpacing" : 0,
  "layoutHierarchy": true,
  "intCoordinates": true,
  "edgeRouting": "ORTHOGONAL"
}

KLay JSON:

{
    "id": "root",
    "labels": [
        {
            "text": "root"
        }
    ],
    "edges": [
        {
            "id": "a:0",
            "source": "a",
            "target": "a2",
            "labels": [],
            "sourcePort": "a_enter0",
            "targetPort": "a2_enter0",
        },
        {
            "id": "a1:0",
            "source": "a1",
            "target": "b",
            "labels": [
                {
                    "text": "t",
                    "width": 1.109375,
                    "height": 5
                }
            ]
        },
        {
            "id": "$generated_a_initial_0:0",
            "source": "$generated_a_initial_0",
            "target": "a1",
            "labels": []
        },
        {
            "id": "$generated_root_initial_0:0",
            "source": "$generated_root_initial_0",
            "target": "a",
            "labels": []
        },
        {
            "id": "a_exit0_a_enter0",
            "source": "a",
            "target": "a",
            "sourcePort": "a_exit0",
            "targetPort": "a_enter0",
            "labels": [
                {
                    "text": "t",
                    "width": 1.109375,
                    "height": 5
                }
            ],
        }
    ],
    "width": 11.4375,
    "height": 10,
    "children": [
        {
            "id": "a",
            "labels": [
                {
                    "text": "a"
                }
            ],
            "edges": [],
            "width": 6.765625,
            "height": 10,
            "children": [
                {
                    "id": "a1",
                    "labels": [
                        {
                            "text": "a1"
                        }
                    ],
                    "edges": [],
                    "width": 8.765625,
                    "height": 10,
                    "x": 0,
                    "y": 0
                },
                {
                    "id": "a2",
                    "labels": [
                        {
                            "text": "a2"
                        }
                    ],
                    "edges": [],
                    "width": 8.765625,
                    "height": 10,
                    "ports": [
                        {
                            "id": "a2_enter0"
                        },
                        {
                            "id": "a2_exit0"
                        }
                    ],
                    "x": 0,
                    "y": 0
                },
                {
                    "id": "$generated_a_initial_0",
                    "labels": [],
                    "edges": [],
                    "width": 4,
                    "height": 4,
                    "x": 0,
                    "y": 0
                }
            ],
            "ports": [
                {
                    "id": "a_enter0"
                },
                {
                    "id": "a_exit0"
                }
            ],
            "x": 0,
            "y": 0
        },
        {
            "id": "b",
            "labels": [
                {
                    "text": "b"
                }
            ],
            "edges": [],
            "width": 7,
            "height": 10,
            "x": 0,
            "y": 0
        },
        {
            "id": "$generated_root_initial_0",
            "labels": [],
            "edges": [],
            "width": 4,
            "height": 4,
            "x": 0,
            "y": 0
        }
    ]
}

This yields the following layout:

{
    "id": "root",
    "labels": [
        {
            "text": "root"
        }
    ],
    "edges": [
        {
            "id": "a:0",
            "source": "a",
            "target": "a2",
            "labels": [],
            "sourcePort": "a_enter0",
            "targetPort": "a2_enter0",
            "sourcePoint": {
                "x": 0,
                "y": 38
            },
            "targetPoint": {
                "x": 24,
                "y": 38
            },
            "junctionPoints": []
        },
        {
            "id": "a1:0",
            "source": "a1",
            "target": "b",
            "labels": [
                {
                    "text": "t",
                    "width": 1,
                    "height": 5,
                    "x": 59,
                    "y": 14
                }
            ],
            "sourcePoint": {
                "x": 32,
                "y": 20
            },
            "targetPoint": {
                "x": 70,
                "y": 20
            },
            "junctionPoints": []
        },
        {
            "id": "$generated_a_initial_0:0",
            "source": "$generated_a_initial_0",
            "target": "a1",
            "labels": [],
            "sourcePoint": {
                "x": 14,
                "y": 20
            },
            "targetPoint": {
                "x": 24,
                "y": 20
            },
            "junctionPoints": []
        },
        {
            "id": "$generated_root_initial_0:0",
            "source": "$generated_root_initial_0",
            "target": "a",
            "labels": [],
            "sourcePoint": {
                "x": 14,
                "y": 45
            },
            "targetPoint": {
                "x": 27,
                "y": 45
            },
            "junctionPoints": []
        },
        {
            "id": "a_exit0_a_enter0",
            "source": "a",
            "target": "a",
            "sourcePort": "a_exit0",
            "targetPort": "a_enter0",
            "labels": [
                {
                    "text": "t",
                    "width": 1,
                    "height": 5,
                    "x": 10,
                    "y": 10
                }
            ],
            "sourcePoint": {
                "x": 70,
                "y": 26
            },
            "targetPoint": {
                "x": 27,
                "y": 55
            },
            "bendPoints": [
                {
                    "x": 80,
                    "y": 26
                },
                {
                    "x": 80,
                    "y": 10
                },
                {
                    "x": 20,
                    "y": 10
                },
                {
                    "x": 20,
                    "y": 55
                }
            ],
            "junctionPoints": []
        }
    ],
    "width": 115,
    "height": 82,
    "children": [
        {
            "id": "a",
            "labels": [
                {
                    "text": "a"
                }
            ],
            "edges": [],
            "width": 42,
            "height": 55,
            "children": [
                {
                    "id": "a1",
                    "labels": [
                        {
                            "text": "a1"
                        }
                    ],
                    "edges": [],
                    "width": 8.765625,
                    "height": 10,
                    "x": 24,
                    "y": 15
                },
                {
                    "id": "a2",
                    "labels": [
                        {
                            "text": "a2"
                        }
                    ],
                    "edges": [],
                    "width": 8.765625,
                    "height": 10,
                    "ports": [
                        {
                            "id": "a2_enter0",
                            "x": 0,
                            "y": 3,
                            "width": 0,
                            "height": 0,
                            "properties": {
                                "de.cau.cs.kieler.portSide": "WEST"
                            }
                        },
                        {
                            "id": "a2_exit0",
                            "x": 0,
                            "y": 6,
                            "width": 0,
                            "height": 0,
                            "properties": {
                                "de.cau.cs.kieler.portSide": "WEST"
                            }
                        }
                    ],
                    "x": 24,
                    "y": 35
                },
                {
                    "id": "$generated_a_initial_0",
                    "labels": [],
                    "edges": [],
                    "width": 4,
                    "height": 4,
                    "x": 10,
                    "y": 18
                }
            ],
            "ports": [
                {
                    "id": "a_enter0",
                    "x": 0,
                    "y": 38,
                    "width": 0,
                    "height": 0,
                    "properties": {
                        "de.cau.cs.kieler.portSide": "WEST"
                    }
                },
                {
                    "id": "a_exit0",
                    "x": 42,
                    "y": 10,
                    "width": 0,
                    "height": 0,
                    "properties": {
                        "de.cau.cs.kieler.portSide": "EAST"
                    }
                }
            ],
            "x": 27,
            "y": 16,
        },
        {
            "id": "b",
            "labels": [
                {
                    "text": "b"
                }
            ],
            "edges": [],
            "width": 7,
            "height": 10,
            "x": 98,
            "y": 32
        },
        {
            "id": "$generated_root_initial_0",
            "labels": [],
            "edges": [],
            "width": 4,
            "height": 4,
            "x": 10,
            "y": 43
        }
    ],
}

Which when visualized as SVG yields:

screen shot 2017-05-25 at 10 29 21 pm

You can see that the y attributes of the edge targeting port a_enter0 and the edge originating from port a_enter0 are misaligned.

Specifically, in screen coordinates, the y coordinate of target point of edge a:0 is 54 (16 + 38, which is coordinates of node a, plus target point of edge a:0). The y coordinate of target point of edge a_exit0_a_enter0 is 55. Therefore there is an off-by-one error on the coordinates of the port.

I was only able to reproduce this behavior when the layout yielded edges which were crossing, so I think that this might be related.

Please let me know what you think. Thank you.

jbeard4 avatar May 26 '17 03:05 jbeard4

Could be a bug. It shouldn't been related to the crossing but there are several places where this can go wrong. Can you check the coordinates you mention when you set intCoordinates to false? I would be interested if the original positions are already integral.

Thanks by the way for the nice presentation of the issue 👍 .

uruuru avatar May 29 '17 10:05 uruuru

Setting intCoordinates to false resolves this issue.

jbeard4 avatar May 29 '17 22:05 jbeard4

Can you also tell me the floating point values of the two coordinates? I'm wondering why they result in two different integers.

uruuru avatar May 30 '17 12:05 uruuru

Here are the floating point coordinates:

{
    "id": "root",
    "labels": [
        {
            "text": "root"
        }
    ],
    "edges": [
        {
            "id": "a:0",
            "source": "a",
            "target": "a2",
            "labels": [],
            "sourcePort": "a_enter0",
            "targetPort": "a2_enter0",
            "$hyperlink": "a_exit0_a_enter0",
            "sourcePoint": {
                "x": 0,
                "y": 38.41666666666667
            },
            "targetPoint": {
                "x": 24,
                "y": 38.41666666666667
            },
            "junctionPoints": []
        },
        {
            "id": "a1:0",
            "source": "a1",
            "target": "b",
            "labels": [
                {
                    "text": "t",
                    "width": 1.109375,
                    "height": 4.5,
                    "x": 59.26562476158142,
                    "y": 15
                }
            ],
            "sourcePoint": {
                "x": 32.765625,
                "y": 20.5
            },
            "targetPoint": {
                "x": 70.37499976158142,
                "y": 20.499999999999996
            },
            "junctionPoints": []
        },
        {
            "id": "$generated_a_initial_0:0",
            "source": "$generated_a_initial_0",
            "target": "a1",
            "labels": [],
            "sourcePoint": {
                "x": 14,
                "y": 20.5
            },
            "targetPoint": {
                "x": 24,
                "y": 20.5
            },
            "junctionPoints": []
        },
        {
            "id": "$generated_root_initial_0:0",
            "source": "$generated_root_initial_0",
            "target": "a",
            "labels": [],
            "sourcePoint": {
                "x": 14,
                "y": 45.41666654745738
            },
            "targetPoint": {
                "x": 27.99999976158142,
                "y": 45.41666654745738
            },
            "junctionPoints": []
        },
        {
            "id": "a_exit0_a_enter0",
            "source": "a",
            "target": "a",
            "sourcePort": "a_exit0",
            "targetPort": "a_enter0",
            "labels": [
                {
                    "text": "t",
                    "width": 1.109375,
                    "height": 4.5,
                    "x": 10,
                    "y": 10
                }
            ],
            "sourcePoint": {
                "x": 70.76562476158142,
                "y": 26.99999988079071
            },
            "targetPoint": {
                "x": 27.99999976158142,
                "y": 55.41666654745738
            },
            "bendPoints": [
                {
                    "x": 80.26562464237213,
                    "y": 26.99999988079071
                },
                {
                    "x": 80.26562464237213,
                    "y": 10
                },
                {
                    "x": 20.99999988079071,
                    "y": 10
                },
                {
                    "x": 20.99999988079071,
                    "y": 55.41666654745738
                }
            ],
            "junctionPoints": []
        }
    ],
    "width": 115.37499952316284,
    "height": 81.74999988079071,
    "children": [
        {
            "id": "a",
            "labels": [
                {
                    "text": "a"
                }
            ],
            "edges": [],
            "width": 42.765625,
            "height": 54.75,
            "children": [
                {
                    "id": "a1",
                    "labels": [
                        {
                            "text": "a1"
                        }
                    ],
                    "edges": [],
                    "width": 8.765625,
                    "height": 9.5,
                    "x": 24,
                    "y": 15.75
                },
                {
                    "id": "a2",
                    "labels": [
                        {
                            "text": "a2"
                        }
                    ],
                    "edges": [],
                    "width": 8.765625,
                    "height": 9.5,
                    "ports": [
                        {
                            "id": "a2_enter0",
                            "x": 0,
                            "y": 3.1666666666666674,
                            "width": 0,
                            "height": 0,
                            "properties": {
                                "de.cau.cs.kieler.portSide": "WEST"
                            }
                        },
                        {
                            "id": "a2_exit0",
                            "x": 0,
                            "y": 6.333333333333334,
                            "width": 0,
                            "height": 0,
                            "properties": {
                                "de.cau.cs.kieler.portSide": "WEST"
                            }
                        }
                    ],
                    "x": 24,
                    "y": 35.25
                },
                {
                    "id": "$generated_a_initial_0",
                    "labels": [],
                    "edges": [],
                    "width": 4,
                    "height": 4,
                    "x": 10,
                    "y": 18.5
                }
            ],
            "ports": [
                {
                    "id": "a_enter0",
                    "x": 0,
                    "y": 38.41666666666667,
                    "width": 0,
                    "height": 0,
                    "properties": {
                        "de.cau.cs.kieler.portSide": "WEST"
                    }
                },
                {
                    "id": "a_exit0",
                    "x": 42.765625,
                    "y": 10,
                    "width": 0,
                    "height": 0,
                    "properties": {
                        "de.cau.cs.kieler.portSide": "EAST"
                    }
                }
            ],
            "x": 27.99999976158142,
            "y": 16.99999988079071,
            "$H": 25
        },
        {
            "id": "b",
            "labels": [
                {
                    "text": "b"
                }
            ],
            "edges": [],
            "width": 7,
            "height": 9.5,
            "x": 98.37499952316284,
            "y": 32.74999988079071
        },
        {
            "id": "$generated_root_initial_0",
            "labels": [],
            "edges": [],
            "width": 4,
            "height": 4,
            "x": 10,
            "y": 43.41666654745738
        }
    ]
}

Rendering:

screen shot 2017-05-31 at 6 48 47 pm

Thank you for your help with this.

jbeard4 avatar May 31 '17 22:05 jbeard4

Ah I see, it's a bad idea to round the coordinates to integers if they represent relative positions that have to be added later on. We should fix this in the next version of the library.

uruuru avatar Jun 01 '17 07:06 uruuru