Edit
- We try to deal with the boundary pattern. To do this,we can fixed the boundary pattern of the four corners. The main idea is that we add one more layer to the
Rectangle[{1,1},{n,n}]
and using the original idea so that we can distinguish the interior pattern and the outer pattern.
n = 10;
coords = Tuples[Range[0, n + 1], 2];
SW = {{0, 1} <-> {1, 0}, {1, 0} <-> {2, 1}, {1, 2} <-> {2, 1}, {0,
2} <-> {1, 1}};
g0 = Graph[coords,
NestList[
Map[RotationTransform[π/
2, {(n + 1)/2, (n + 1)/2}], #, {2}] &, SW, 3] // Flatten,
VertexCoordinates -> coords];
edges :=
Flatten[Table[
If[0 <= i < 2 && 0 <= j < 2 || 0 <= i < 2 && n - 1 <= j < n + 1 ||
n - 1 <= i < n + 1 && 0 <= j < 2 ||
n - 1 <= i <= n + 1 && n - 1 <= j <= n + 1, Nothing,
RandomChoice[
If[Mod[j, 2] ==
0, {.7, .3}, {.3, .7}] -> {{i, j} <-> {i + 1, j + 1}, {i + 1,
j} <-> {i, j + 1}}]], {i, 0, n}, {j, 0, n}]];
graph :=
GraphUnion[Graph[coords, edges], g0, VertexCoordinates -> coords];
g = Block[{g = graph},
While[(!
And @@ Flatten@
Table[1 <= VertexDegree[g, {i, j}] <= 3, {i, 1, n}, {j, 1,
n}]), g = graph]; g];
HighlightGraph[g, EdgeList@g0]
edges = EdgeList[g];
{boundary, interior} =
GatherBy[edges,
RegionWithin[Rectangle[{1, 1}, {n, n}],
Rectangle @@ CoordinateBoundingBox[List @@ #]] &];
arc[type_][edge_] :=
Module[{p, q, a, b, c, d, in, u, v, o, s, type1, type2}, {p, q} =
List @@ edge;
{a, c} = CoordinateBoundingBox[{p, q}];
{b, d} = {a + {1, 0}, c + {-1, 0}};
in = Select[Complement[{a, b, c, d}, {p, q}],
RegionWithin[Rectangle[{1, 1}, {n, n}], Point@#] &];
o = Mean[{p, q}];
u = Function[in, Mean[{in, p}]];
v = Function[in, Mean[{in, q}]];
s = (4/3)*Tan[π/8];
type1 =
BezierCurve[{u@#, {1 - s, s} . {u@#, o}, {1 - s, s} . {v@#, o},
v@#}] & /@ in;
type2 = Line[{u@#, o, v@#}] & /@ in;
Which[type == "type1", Return[type1], type == "type2",
Return[RandomChoice[{10, 1} -> {type1, type2}]]]]
Graphics[{AbsolutePointSize[5], Point@coords,
arc["type1"] /@ boundary, arc["type2"] /@ interior}]
- More other styles of such graphics.
edges = EdgeList[g];
{boundary, interior} =
GatherBy[edges,
RegionWithin[Rectangle[{1, 1}, {n, n}],
Rectangle @@ CoordinateBoundingBox[List @@ #]] &];
arc[type_][edge_] :=
Module[{p, q, a, b, c, d, in, u, v, o, s, type1, type3},
{p, q} = List @@ edge;
{a, c} = CoordinateBoundingBox[{p, q}];
{b, d} = {a + {1, 0}, c + {-1, 0}};
in = Select[Complement[{a, b, c, d}, {p, q}],
RegionWithin[Rectangle[{1, 1}, {n, n}], Point@#] &];
o = Mean[{p, q}];
u = Function[in, Mean[{in, p}]];
v = Function[in, Mean[{in, q}]];
s = (4/3)*Tan[π/8];
type3 = {{BezierCurve[{u@#, {1 - s, s} . {u@#, o}, {1 - s,
s} . {v@#, o}, v@#}]}, Opacity[.35], RandomColor[],
FilledCurve[{Line[{p, u@#}],
BezierCurve[{{1 - s, s} . {u@#, o}, {1 - s, s} . {v@#, o},
v@#}], Line[{v@#, q}]}]} & /@ in;
type1 =
BezierCurve[{u@#, {1 - s, s} . {u@#, o}, {1 - s, s} . {v@#, o},
v@#}] & /@ in;
Which[type == "type1", Return[type1], type == "type3",
Return[type3]]]
Graphics[{AbsolutePointSize[5], Point@coords,
arc["type3"] /@ interior, arc["type1"] /@ boundary},
GridLines -> {Range[0, n + 1], Range[0, n + 1]}]
Animate
- The main idea is that we using
Graph
again for the pair of the Line
.
- Needs to be updated later to simplify the code and the idea.
edges = EdgeList[g];
relation[edge_] :=
Module[{p, q, a, b, c, d, in}, {p, q} = List @@ edge;
{a, c} = CoordinateBoundingBox[{p, q}];
{b, d} = {a + {1, 0}, c + {-1, 0}};
in = Select[Complement[{a, b, c, d}, {p, q}],
RegionWithin[Rectangle[{1, 1}, {n, n}], Point@#] &];
Line[Sort@{#, p}] <-> Line[Sort@{#, q}] & /@ in]
edges2 = Flatten[relation /@ edges];
g2 = Graph[edges2];
paths = FindHamiltonianPath /@ ConnectedGraphComponents[g2];
curve[line1_, line2_] :=
Module[{o, u, v, c, w, ends1, ends2, s, c1, c2}, ends1 = line1[[1]];
ends2 = line2[[1]];
o = Intersection[ends1, ends2] // First;
u = Mean@ends1;
v = Mean@ends2;
w = u + v - o;
s = (4/3)*Tan[π/8];
c1 = {1 - s, s} . {u, w};
c2 = {1 - s, s} . {v, w};
BezierCurve[{u, c1, c2, v}]]
arcs = Flatten[
Table[curve @@@ Partition[paths[[i]], 2, 1], {i, 1, Length@paths}]];
ani = Animate[
Graphics[Take[arcs, j], PlotRange -> {{0, n + 1}, {0, n + 1}}], {j,
1, Length@arcs, 1}]
The OP animation.
Clear["Global`*"];
n = 10;
coords = Tuples[Range[0, n + 1], 2];
SW = {{0, 1} <-> {1, 0}, {1, 0} <-> {2, 1}, {1, 2} <-> {2, 1}, {0,
2} <-> {1, 1}};
corner =
Join[Tuples[{Range[0, 1], Range[0, 1]}],
Tuples[{Range[0, 1], Range[n - 1, n]}],
Tuples[{Range[n - 1, n], Range[0, 1]}],
Tuples[{Range[n - 1, n], Range[n - 1, n]}]];
g0 = Graph[coords,
NestList[
Map[RotationTransform[π/
2, {(n + 1)/2, (n + 1)/2}], #, {2}] &, SW, 3] // Flatten,
VertexCoordinates -> coords];
crosses =
RandomChoice[Complement[Tuples[Range[2, n - 1], 2], corner], 4];
edges :=
Flatten[Table[
If[MemberQ[corner, {i, j}] || MemberQ[crosses, {i, j}], Nothing,
RandomChoice[
If[Mod[j, 2] ==
0, {.7, .3}, {.3, .7}] -> {{i, j} <-> {i + 1, j + 1}, {i + 1,
j} <-> {i, j + 1}}]], {i, 0, n}, {j, 0, n}]];
graph :=
GraphUnion[Graph[coords, edges], g0, VertexCoordinates -> coords];
g = Block[{g = graph},
While[(!
And @@ Flatten@
Table[1 <= VertexDegree[g, {i, j}] <= 3, {i, 1, n}, {j, 1,
n}]), g = graph]; g];
HighlightGraph[g, EdgeList@g0];
edges1 = EdgeList[g];
relation[edge_] :=
Module[{p, q, a, b, c, d, in}, {p, q} = List @@ edge;
{a, c} = CoordinateBoundingBox[{p, q}];
{b, d} = {a + {1, 0}, c + {-1, 0}};
in = Select[Complement[{a, b, c, d}, {p, q}],
RegionWithin[Rectangle[{1, 1}, {n, n}], Point@#] &];
Line[Sort@{#, p}] <-> Line[Sort@{#, q}] & /@ in]
edges2 = Flatten[relation /@ edges1];
g2 = Graph[edges2];
f = {i, j} |-> {Line[{{i, j}, {i + 1, j}}] <->
Line[{{i, j + 1}, {i + 1, j + 1}}],
Line[{{i, j}, {i, j + 1}}] <-> Line[{{i + 1, j}, {i + 1, j + 1}}]};
g3 = Graph[f @@@ crosses // Flatten];
g4 = GraphUnion[g2, g3];
curve[edge_] :=
Module[{line1, line2, o, u, v, c, w, ends1, ends2, int, s, c1, c2},
line1 = edge[[1]];
line2 = edge[[2]];
ends1 = line1[[1]];
ends2 = line2[[1]];
int = Intersection[ends1, ends2];
If[int == {}, Return[Line[Mean /@ {ends1, ends2}]],
o = First@int;
u = Mean@ends1;
v = Mean@ends2;
w = u + v - o;
s = (4/3)*Tan[π/8];
c1 = {1 - s, s} . {u, w};
c2 = {1 - s, s} . {v, w};
Return[BezierCurve[{u, c1, c2, v}]]]];
paths = FindHamiltonianPath /@ (ConnectedGraphComponents[g4]);
arcs = Flatten[curve /@ EdgeList@Subgraph[g4, #] & /@ paths, 1];
ani = Manipulate[
Graphics[{AbsolutePointSize[5], Point@coords, AbsoluteThickness[5],
Take[arcs, j]}], {j, 1, Length@arcs, 1}]
- Reply to comment @VitaliyKaurov
Clear["Global`*"];
n = 10;
coords = Tuples[Range[0, n + 1], 2];
SW = {{0, 1} <-> {1, 0}, {1, 0} <-> {2, 1}, {1, 2} <-> {2, 1}, {0,
2} <-> {1, 1}};
corner = Join[Tuples[{Range[0, 1], Range[0, 1]}],
Tuples[{Range[0, 1], Range[n - 1, n]}],
Tuples[{Range[n - 1, n], Range[0, 1]}],
Tuples[{Range[n - 1, n], Range[n - 1, n]}]];
g0 = Graph[coords,
NestList[
Map[RotationTransform[π/
2, {(n + 1)/2, (n + 1)/2}], #, {2}] &, SW, 3] // Flatten,
VertexCoordinates -> coords];
crosses =
RandomChoice[Complement[Tuples[Range[2, n - 1], 2], corner], 4];
crosses = {};
edges := Flatten[
Table[If[MemberQ[corner, {i, j}] || MemberQ[crosses, {i, j}],
Nothing,
RandomChoice[
If[Mod[j, 2] ==
0, {.7, .3}, {.3, .7}] -> {{i, j} <-> {i + 1, j + 1}, {i + 1,
j} <-> {i, j + 1}}]], {i, 0, n}, {j, 0, n}]];
graph := GraphUnion[Graph[coords, edges], g0,
VertexCoordinates -> coords];
g = Block[{g = graph},
While[(!
And @@
Flatten@Table[
1 <= VertexDegree[g, {i, j}] <= 3, {i, 1, n}, {j, 1, n}]),
g = graph]; g];
HighlightGraph[g, EdgeList@g0];
edges1 = EdgeList[g];
relation[edge_] :=
Module[{p, q, a, b, c, d, in}, {p, q} = List @@ edge;
{a, c} = CoordinateBoundingBox[{p, q}];
{b, d} = {a + {1, 0}, c + {-1, 0}};
in = Select[Complement[{a, b, c, d}, {p, q}],
RegionWithin[Rectangle[{1, 1}, {n, n}], Point@#] &];
Line[Sort@{#, p}] <-> Line[Sort@{#, q}] & /@ in]
edges2 = Flatten[relation /@ edges1];
g2 = Graph[edges2];
f = {i, j} |-> {Line[{{i, j}, {i + 1, j}}] <->
Line[{{i, j + 1}, {i + 1, j + 1}}],
Line[{{i, j}, {i, j + 1}}] <-> Line[{{i + 1, j}, {i + 1, j + 1}}]};
g3 = Graph[f @@@ crosses // Flatten];
g4 = GraphUnion[g2, g3];
curve[type_][edge_] :=
Module[{line1, line2, o, u, v, c, w, ends1, ends2, int, s, c1, c2,
p, q, type1, type2, regs},
line1 = edge[[1]];
line2 = edge[[2]];
ends1 = line1[[1]];
ends2 = line2[[1]];
int = Intersection[ends1, ends2];
If[int == {}, Return[Line[Mean /@ {ends1, ends2}]],
o = First@int;
p = Complement[ends1, {o}][[1]];
q = Complement[ends2, {o}][[1]];
u = Mean@ends1;
v = Mean@ends2;
w = u + v - o;
s = (4/3)*Tan[π/8];
c1 = {1 - s, s} . {u, w};
c2 = {1 - s, s} . {v, w};
type1 = {RandomColor[], Opacity[.3],
FilledCurve[{Line[{p, u}],
BezierCurve[{{1 - s, s} . {u, w}, {1 - s, s} . {v, w}, v}],
Line[{v, q}]}]};
type2 = {BezierCurve[{u, c1, c2, v}]};
Which[type == "type1", Return[type1], type == "type2",
Return[type2]]]];
paths = FindHamiltonianPath /@ (ConnectedGraphComponents[g4]);
arcs = Flatten[curve["type2"] /@ EdgeList@Subgraph[g4, #] & /@ paths,
1];
regs = Flatten[curve["type1"] /@ EdgeList@Subgraph[g4, #] & /@ paths,
1];
ani = Manipulate[
Graphics[{AbsolutePointSize[5], arcs, Take[regs, j]},
PlotRange -> {{-1, n + 2}, {-1, n + 2}},
PlotRangePadding -> .1], {j, 1, Length@regs, 1}]
Original
- The idea is that we find the pattern as the picture show below.
n = 10;
coords = Tuples[Range[n + 1], 2];
edges :=
Flatten[Table[
RandomChoice[
If[Mod[j, 2] ==
0, {.7, .3}, {.3, .7}] -> {UndirectedEdge[{i, j}, {i + 1,
j + 1}], UndirectedEdge[{i + 1, j}, {i, j + 1}]}], {i, 1,
n}, {j, 1, n}, 1]];
graph := Graph[coords, edges, VertexCoordinates -> coords];
g = Block[{g = graph},
While[(!
And @@ Thread[VertexDegree[g] < 4]) || (FindCycle[g] != {}),
g = graph]; g]
- There are three patterns. The first and second pattern is two separate quarter, the third pattern is cross.
pattern[edge_] :=
Which[Last@edge - First@edge == {1, 1}, {Circle[First@edge,
1/2, {0, π/2}], Circle[Last@edge, 1/2, {π, 3/2 π}]},
Last@edge - First@edge == {-1, 1}, {Circle[First@edge,
1/2, {π/2, π}],
Circle[Last@edge, 1/2, {3/2 π, 2 π}]},
Last@edge - First@edge == {0,
0}, {Line[{First@edge - {1/2, 0}, First@edge + {1/2, 0}}],
Line[{First@edge - {0, 1/2}, First@edge + {0, 1/2}}]}]
With[{i = 3,
j = 8}, {Graphics[{FaceForm[], EdgeForm[Dashed], Rectangle[{i, j}],
AbsoluteThickness[5],
pattern[{i, j} \[UndirectedEdge] {i + 1, j + 1}]}],
Graphics[{FaceForm[], EdgeForm[Dashed], Rectangle[{i, j}],
AbsoluteThickness[5],
pattern[{i + 1, j} \[UndirectedEdge] {i, j + 1}]}],
Graphics[{FaceForm[], EdgeForm[Dashed], Rectangle[{i, j}],
AbsoluteThickness[5],
pattern[{i + 1/2, j + 1/2} \[UndirectedEdge] {i + 1/2,
j + 1/2}]}]}]
list = List /@ RandomInteger[{1, n*n}, 4];
edges = MapAt[
Mean[{#[[2]], #[[1]]}] \[UndirectedEdge] Mean[{#[[2]], #[[1]]}] &,
EdgeList[g], list];
Graphics[{AbsoluteThickness[5], AbsolutePointSize[10],
pattern /@ edges, Point@coords}]
Remark
After I found the way to draw the original picture,I found that the simple cases have been drawn by Trotte
in his book,The Mathematica Guidebook for Graphics,Page 318~319,but need to point out that, my method avoid a single circle, and does not contain cycles.