Edge labelling on a directed graph

May 14, 2012 at 11:18 PM
Edited May 14, 2012 at 11:21 PM

Hi Tony,

1.  I have a non-symmetric, directed graph.  The labels for each direction are there, but somewhat overlap making it hard (although not impossible) to make out exactly what values they have.  The labels in my case are single digit numbers.  Is it possible to move them apart?

    Ideally (speaking for myself) one would be above the line and the other below.  If they were placed so that the value for each was closest to its own arrow,head, it would be possible to tell which was which.

2.  In Autofill, in the drop down box that informs NodeXL what column to take the label from, I can choose between "edge weight" and "reciprocal?"  I use "edge weight" but am curious about what "reciprocal?" refers to. 

Thanks for your help.

Peter

 

 

May 15, 2012 at 1:29 AM

Hello, Peter:

In my opinion, the real fix for the overlapping label problem is to stop the edges themselves from overlapping.  Separate the edges by "bowing" them apart and you automatically separate the labels.  We've talked about having an option for that, and it's one I think we really need, but we haven't gotten to it yet.

Unfortunately, I can't think of a workaround for now.  Labels on parallel edges always overlap.

"Edge Weight" is a column created when you merge duplicate edges (NodeXL, Data, Prepare Data, Merge Duplicate Edges).  You can also add such a column yourself and fill it with whatever data is appropriate for your graph.  "Reciprocated?" is a column that gets created when you calculate graph metrics (NodeXL, Analysis, Graph Metrics) and check the "edge reciprocation" checkbox.  Here is the definition of edge reciprocation, which I copied from the Graph Metrics dialog box:

"In a directed graph, an edge from vertex A to vertex B is reciprocated if the graph also has an edge from vertex B to vertex A.  In an undirected graph, edge reciprocation is undefined and is not calculated."

-- Tony

Dec 23, 2012 at 2:24 AM

Hi, Tony,

I'm having this same problem and from my attempts to fiddle with edge curvature I'm assuming that there's still no way to bow edges apart. Have I missed a new development?

I've got some edges circling back to the vertex of origin on the same graph and the edge labels on those don't display. Any ideas?

Thanks!

 

Jen

Dec 24, 2012 at 3:00 AM

Hello, Jen:

The NodeXL team has had many requests for non-overlapping edges, but I'm afraid that feature hasn't been added yet.

Labels don't show on self-loop edges because those edges aren't long enough to draw anything on top of them.  That's by design.

-- Tony

Jan 9, 2013 at 5:09 PM

I am trying to come up with a strategy to address the overlapping edges issue.  In the DrawGraph() call we have this code (open to ideas):

        // Draw the edges.  The edges don't need to be hit-tested, but they
        // might need to be redrawn by RedrawEdge(), so each edge is put into
        // its own DrawingVisual that becomes a child of either
        // m_oUnselectedEdgeDrawingVisuals or m_oSelectedEdgeDrawingVisuals.

        foreach (IEdge oEdge in graph.Edges)
        {
            DrawEdge(oEdge, graphDrawingContext);
        }

 Further underneath the DrawEdge call there is a check to see if Bezier edge lines are being drawn.

It seems that we could find all edges with a common ID and then "bow" the set of overlapping edges such that they form an oval of vectors converging on the same endpoints with a common centerline that is the non-Bezier (straight line) vector between the common vertices.

So there would need to be a pre-processing step prior to the above foreach such that common edges are grouped together and drawn in succession such that the vector endpoints form an oval of beziers to the common end points.  A simple biasing strategy based on the total number of converging points could be used to determine the size or roundness of the oval.  The oval being flatter with fewer edges.

I think this would be a reasonable solution to the overlapping edge issue.  A global flag could control the use of this drawing method.

Addressing the overlapping edge issue would make NodeXL applicable to a much broader set of problems!

As a test I randomly adjusted the BezierDisplacementFactor for all edges drawn.  This does allow overlapping edges to be disambiguated, but in a non deterministic and aesthetically unappealing way.

 

Coordinator
Jan 9, 2013 at 6:32 PM

Thanks for this very useful suggestion.  We share your interest in improved edge handling in NodeXL!  

We will be sure to bring your message into our next team discussion!

While many work items are competing for scarce resources I suspect you will see edge improvements coming soon!

Regards,

Marc

Jan 9, 2013 at 8:08 PM

Here's the change I made to NodeXL to handle the case of two overlapping edges, this works for my case since I only ever have at most two edges overlap:

In DrawBezierCurve() I adjusted this line:

        Point oBezierControlPoint = GetBezierControlPoint(oGraphDrawingContext,
            oEdgeEndpoint1, oEdgeEndpoint2, !oEdge.IsFlagged ? m_dBezierDisplacementFactor : m_dBezierDisplacementFactor * 3.1416);

I added the IsFlagged property to IEdge/Edge so that I could set a flag when an edge has an overlapping edge.

In the code where I create my list of edges I have:

            List<string> commonedges = new List<string>();


            foreach (var transition in xmlParser.Transitions)
            {
                IVertex from;
                oGraph.Vertices.Find(transition.From, out from);

                IVertex to;
                oGraph.Vertices.Find(transition.To, out to);

                IEdge oEdge = oEdges.Add(from, to, true);

                //PointF[] pa = (PointF[])oEdge.GetValue(ReservedMetadataKeys.PerEdgeIntermediateCurvePoints);

                string vcomboname;

                if (oEdge.Vertex1.ID > oEdge.Vertex2.ID)
                    vcomboname = oEdge.Vertex2.ID.ToString() + "+" + oEdge.Vertex1.ID.ToString();
                else
                    vcomboname = oEdge.Vertex1.ID.ToString() + "+" + oEdge.Vertex2.ID.ToString();

                if (!commonedges.Contains(vcomboname))
                    commonedges.Add(vcomboname);
                else
                    oEdge.IsFlagged = true;

                oEdge.SetValue(ReservedMetadataKeys.PerEdgeLabel, transition.Trigger);
            }

This is too simplistic as a general solution, but does the trick when you only have two edges overlap.  I would prefer to see a solution along what I described earlier, but I needed to get something done fast.  The overlapped edges handling belongs in DrawGraph.  If I had a couple more hours, a generic solution would have been possible.  I'm sure those well versed with the code could come up with something even faster.  Perhaps a delegate to handle how to "splay" the common vectors with a few default ways of performing the splay operation (splay vectors across an oval, spheroid, square, etc.)?  The user should only have to set splay delegate to a predefined operation type.  DrawGraph would to the rest.

Thank you very much for such a great tool!!

Mar 6, 2013 at 8:48 AM
Hi NodeXL team,

Any progress on this issues with overlapping edge labels? I would be absolutely terrific if would have time to look at it.

Rgs

Cai
Coordinator
Mar 6, 2013 at 2:40 PM
Sadly, no. We have Edge improvements on the pending work item list, but not at the top of that list.

Up next are improvements to the network description below the graph gallery images, a backend database to hold more than one workbook of data, and updates to meet requirements for the Twitter 1.1 API changes.

Edges are likely to come to the top of the list this summer.

Regards,
Marc
Nov 6, 2013 at 3:35 PM
Marc - Any updates on this ? Approximate timing on when we can see this feature
Nov 6, 2013 at 4:03 PM
noemata wrote:
I am trying to come up with a strategy to address the overlapping edges issue.  In the DrawGraph() call we have this code (open to ideas):         // Draw the edges.  The edges don't need to be hit-tested, but they         // might need to be redrawn by RedrawEdge(), so each edge is put into         // its own DrawingVisual that becomes a child of either         // m_oUnselectedEdgeDrawingVisuals or m_oSelectedEdgeDrawingVisuals.         foreach (IEdge oEdge in graph.Edges)         {             DrawEdge(oEdge, graphDrawingContext);         }  Further underneath the DrawEdge call there is a check to see if Bezier edge lines are being drawn. It seems that we could find all edges with a common ID and then "bow" the set of overlapping edges such that they form an oval of vectors converging on the same endpoints with a common centerline that is the non-Bezier (straight line) vector between the common vertices. So there would need to be a pre-processing step prior to the above foreach such that common edges are grouped together and drawn in succession such that the vector endpoints form an oval of beziers to the common end points.  A simple biasing strategy based on the total number of converging points could be used to determine the size or roundness of the oval.  The oval being flatter with fewer edges. I think this would be a reasonable solution to the overlapping edge issue.  A global flag could control the use of this drawing method. Addressing the overlapping edge issue would make NodeXL applicable to a much broader set of problems! As a test I randomly adjusted the BezierDisplacementFactor for all edges drawn.  This does allow overlapping edges to be disambiguated, but in a non deterministic and aesthetically unappealing way.  
Hi Noemata - Could you share your updated Template with your code changes?
Nov 18, 2013 at 7:49 PM
Hi Nodexl Team

Is there any solution to this? Really essential to what I'm doing.

Great product by the way, exactly what I needed.

Dom