First we draw a 4-cycle $C_4$ on the plane such that its edges form a convex quadrilateral $f$. I'd like to draw a pair of new crossing edges inside the exterior face of $f$. (Notice that the two new crossing edges cross exactly once, and they don't cross any boundaries of $f$.) Clearly, whatever the shape of the quadrilateral, at least one of these two new edges must be curved.
If the shape of the quadrilateral is fixed (i.e. , the coordinates of vertices on the boundary of $f$ are given), then we can choose to add two new edges manually.
g = Graph[{1 <-> 2, 2 <-> 3, 3 <-> 4, 4 <-> 1, 4 <-> 2, 1 <-> 3},
EdgeShapeFunction -> {1 <-> 3 -> {"CurvedEdge", "Curvature" -> 3},
2 <-> 4 -> {"CurvedEdge", "Curvature" -> -3}},
VertexCoordinates -> {{0, 0}, {1, 0}, {1, -1}, {0, -1}}]
If the shape of the quadrilateral is random, (i.e., the coordinates of the quadrilateral are chosen randomly), how do we add the two new edges well?
This question arises from a drawing problem involving graphs. I got some 3-connected quadrangulation graphs. I want to add a pair of crossing edges to every face of these planar graphs at once. For these planar graphs, I first chose the Tutte spring embedding. So the external faces are bounded by convex polygons. But the coordinates of the external faces of these embeddings are random.
<< IGraphM`;
s = {"KsTAB?oBGL?[", "Ks`IB?oE?K_]", "Ks`Ib?oE?K_["};
s1 = ImportString[#, "Graph6"] & /@ s;
addCrossingEdgesToFaces[g_] :=
Module[{g1 = g, newgraph, p, addedge}, p = PlanarFaceList[g1];
addedge = {#[[1]] <-> #[[3]], #[[2]] <-> #[[4]]} & /@ p //
Flatten;
newgraph = EdgeAdd[g1, addedge];
HighlightGraph[newgraph,
Style[ addedge, {{Dashed, Red, AbsoluteThickness[1]}}]]];
S2 = IGLayoutTutte /@ s1
addCrossingEdgesToFaces /@ S2
For beauty and clarity, the pair of crossing edges that should be on the exterior face of each graph above need to be adjusted.
In response to Azerbajdzan's doubts, I gave a more detailed manual solution.
Step 1. We need to identify the exterior face of the plane embedding of a graph g
. I don't know if there's a code to seek the exterior face. (perhaps as a new problem), but for the specific graph, we can see from the label of the drawn graph.
g = Graph[ImportString["KsTAB?oBGL?[", "Graph6"]];
gtest = Graph[ImportString["KsTAB?oBGL?[", "Graph6"],
VertexLabels -> Placed[Automatic, Center], VertexSize -> 0.8,
GraphLayout -> "TutteEmbedding"];
coords = GraphEmbedding[gtest];
So $1-2-3-8-1$ is the exterior face of graph g
.
Step 2. add two new crossing edges in the exterior face $1-2-3-8-1$.
addedge = {1 <-> 8, 2 <-> 3};
g1 = Graph[EdgeAdd[g, addedge],
VertexCoordinates -> coords,
EdgeShapeFunction -> {1 <-> 8 -> {"CurvedEdge", "Curvature" -> 3},
2 <-> 3 -> {"CurvedEdge", "Curvature" -> -3}}];
HighlightGraph[g1, Style[ addedge, {{Dashed, Red, AbsoluteThickness[1]}}]]
The remaining faces are added with a pair of crossing edges. As they are guaranteed to be straight lines (since each face is a strictly convex polygon). It's easy. So let's skip that.