VertexCoordinate Rules and VertexList from GraphPlot Graphic

后端 未结 3 999
谎友^
谎友^ 2020-12-10 18:56

Is there any way of abstracting the vertex order that GraphPlot applies to VertexCoordinate Rules from the (FullForm or InputForm) of the graphic produced by GraphPlot? I d

3条回答
  •  抹茶落季
    2020-12-10 19:29

    With vertex labeling, one way is to get coordinates of the labels. Notice that output of GraphPlot is in GraphicsComplex where coordinates of coordinate aliases are as first label, you can get it as

    points = Cases[gp1, GraphicsComplex[points_, __] :> points, Infinity] // First
    

    Looking at FullForm you'll see that labels are in text objects, extract them as

    labels = Cases[gp1, Text[___], Infinity]
    

    The actual label seems to be two levels deep so you get

    actualLabels = labels[[All, 1, 1]];
    

    Coordinate alias is the second parameter so you get them as

     coordAliases = labels[[All, 2]]
    

    Actual coordinates were specified in GraphicsComplex, so we get them as

     actualCoords = points[[coordAliases]]
    

    There a 1-1 correspondence between list of coordinates and list of labels, so you can use Thread to return them as list of "label"->coordinate pairs.

    here's a function that this all together

    getLabelCoordinateMap[gp1_] := 
     Module[{points, labels, actualLabels, coordAliases, actualCoords},
      points = 
       Cases[gp1, GraphicsComplex[points_, __] :> points, Infinity] // 
        First;
      labels = Cases[gp1, Text[___], Infinity];
      actualLabels = labels[[All, 1, 1]];
      coordAliases = labels[[All, 2]];
      actualCoords = points[[coordAliases]];
      Thread[actualLabels -> actualCoords]
      ];
    getLabelCoordinateMap[gp1]
    

    Not that this only works on labelled GraphPlot. For ones without labels you could try to extract from other graphics objects, but you may get different results depending on what objects you extract the mapping from because there seems to be a bug which sometimes assigns line endpoints and vertex labels to different vertices. I've reported it. The way to work around the bug is to either always use explicit vertex->coordinate specification for VertexCoordinateList, or always use "adjacency matrix" representation. Here's an example of discrepancy

    graphName = {"Grid", {3, 3}};
    gp1 = GraphPlot[Rule @@@ GraphData[graphName, "EdgeIndices"], 
      VertexCoordinateRules -> GraphData[graphName, "VertexCoordinates"], 
      VertexLabeling -> True]
    gp2 = GraphPlot[GraphData[graphName, "AdjacencyMatrix"], 
      VertexCoordinateRules -> GraphData[graphName, "VertexCoordinates"], 
      VertexLabeling -> True]
    

    BTW, as an aside, here are the utility functions I use for converting between adjacency matrix and edge rule representation

    edges2mat[edges_] := Module[{a, nodes, mat, n},
       (* custom flatten to allow edges be lists *)
    
       nodes = Sequence @@@ edges // Union // Sort;
       nodeMap = (# -> (Position[nodes, #] // Flatten // First)) & /@ 
         nodes;
       n = Length[nodes];
       mat = (({#1, #2} -> 1) & @@@ (edges /. nodeMap)) // 
         SparseArray[#, {n, n}] &
       ];
    mat2edges[mat_List] := Rule @@@ Position[mat, 1];
    mat2edges[mat_SparseArray] := 
     Rule @@@ (ArrayRules[mat][[All, 1]] // Most)
    

提交回复
热议问题