In this answer the goal is simply to build an adjancy matrix first, that gives you all the information about the graph. The great thing about the code is that you can change how the matrix is connected. For example, in your case you want diagonal components to be connected, here you can change to have only diagonal, only lateral or both.
At the moment, is simply set by hand. If you want self connections then one can simply replace the array of positions
{#[[1,1]],....,#[[3,3]]}
with
Flatten[#]
Otherwise this should allow you to generate the adjancy matrix.
myadjancyMatrixforcrystalC[crystal_] :=
Module[{list = crystal, positions, newcrystal},
positions = Position[list, 1];
newcrystal =
SparseArray[# -> Range[Length[#]], Dimensions[list], 0] &[positions];
Return[Map[DeleteCases[#,0] &,
{#[[1, 1]], #[[1, 2]], #[[1, 3]], #[[2, 1]], #[[2, 3]], #[[3, 1]], #[[3, 2]], #[[3, 3]]} & /@ (Function[{y},
Take[ArrayPad[newcrystal,1], ##]&@@((# + {1, 1} + {-1, +1}) & /@ y)] /@ positions)]];
];
since I was dealing with huge matrixes at the time I wrote it, everything was kept as SparseMatrices, but it may not make much of a difference.
Also I don't keep track of the positions of the points, but one could easily return that as part of the code too, to have a graph that can be overlaid over the matrix as some of the other answers, I might add that later.
Here is a small code to takes that adjancy matrix and generates undirected edges.
myedges[adj_] := Module[{myadj = adj},
Return[
DeleteDuplicates[
Sort /@ Flatten[
MapIndexed[UndirectedEdge[First@#2, #1] &, myadj, {2}]]]];
];
And the graph for your matrix then is simply.
Graph[myedges[
myadjancyMatrixforcrystalC[
{{0, 1, 0, 0, 1, 0, 1, 0},
{0, 1, 0, 0,1, 0, 1, 0},
{0, 0, 1, 0, 1, 0, 1, 0},
{0, 0, 0, 1, 0, 0, 1, 0},
{0, 0, 0, 0, 1, 1, 0, 0},
{0, 0, 0, 0, 1, 0, 0, 0}}]]]
Since I didn't keep track of the positions it leads to the same topological graph.
As I mentioned you can also keep track of the positions in the first part of the code,
myadjancyMatrixforcrystalC[crystal_] :=
Module[{list = crystal, positions, newcrystal},
positions = Position[list, 1];
newcrystal =
SparseArray[# -> Range[Length[#]], Dimensions[list], 0] &[
positions];
Return[{Map[
DeleteCases[#,0] &, {#[[1, 1]], #[[1, 2]], #[[1, 3]], #[[2, 1]], #[[2,
3]], #[[3, 1]], #[[3, 2]], #[[3, 3]]} & /@ (Function[{y},
Take[ArrayPad[newcrystal,
1], ##] & @@ ((# + {1, 1} + {-1, +1}) & /@ y)] /@
positions)],
Rule @@@
Thread[{Range[Length[#]], #}] &@({1, -1}*# & /@ (Reverse /@
positions))}];
];
Now the module myadjancyMatrixforcrystalC
returns {adjancy_matrix,vertex->posisionts}
, where the second component is given above by
Rule@@@
Thread[{Range[Length[#]], #}] &@({1, -1}*#&/@(Reverse /@
positions))
which is simply vertexid->position, the rest of the math is simply due to the fact Position
measures the upper left matrix location as {1,1}
and increases as we go to further rows and columns, and therefore matches with results from say ArrayPlot
The positions can be added as option in Graph.
Graph[myedges[#[[1]]], VertexCoordinates -> #[[2]]] &[
myadjancyMatrixforcrystalC[{{0, 1, 0, 0, 1, 0, 1, 0}, {0, 1, 0, 0, 1,
0, 1, 0}, {0, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 1, 0, 0, 1, 0}, {0,
0, 0, 0, 1, 1, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0}}]]
{{0,1,0,0,1,0,1,0}, {0,1,0,0,1,0,1,0}, {0,0,1,0,1,0,1,0}, {0,0,0,1,0,0,1,0}, {0,0,0,0,1,1,0,0}, {0,0,0,0,1,0,0,0}}
$\endgroup$