diff --git a/doc/planar.xml b/doc/planar.xml
index 6c9e44d5c..fae0f411e 100644
--- a/doc/planar.xml
+++ b/doc/planar.xml
@@ -427,3 +427,34 @@ fail
<#/GAPDoc>
+
+<#GAPDoc Label="DualPlanarGraph">
+
+
+ A digraph or fail.
+
+ If digraph is a planar digraph, then DualPlanarGraph returns the the dual graph of digraph.
+ If digraph is not planar, then fail is returned.
+
+ The dual graph of a planar digraph digraph has a vertex for each face of digraph and an edge for
+ each pair of faces that are separated by an edge from each other.
+ Vertex i of the dual graph corresponds to the facial walk at the i-th position calling
+ FacialWalks of digraph with the rotation system returned by PlanarEmbedding.
+
+ D := CompleteDigraph(4);;
+gap> dualD := DualPlanarGraph(D);
+
+gap> IsIsomorphicDigraph(D, dualD);
+true
+gap> cube := Digraph([[2, 4, 5], [1, 3, 6], [2, 4, 7], [1, 3, 8],
+> [1, 6, 8], [2, 5, 7], [3, 6, 8], [4, 5, 7]]);
+
+gap> oct := DualPlanarGraph(cube);;
+gap> IsIsomorphicDigraph(oct, CompleteMultipartiteDigraph([2, 2, 2]));
+true
+]]>
+
+
+
+<#/GAPDoc>
\ No newline at end of file
diff --git a/doc/z-chap4.xml b/doc/z-chap4.xml
index 789c3f1f7..d0c764ab1 100644
--- a/doc/z-chap4.xml
+++ b/doc/z-chap4.xml
@@ -106,6 +106,7 @@
<#Include Label="PlanarEmbedding">
<#Include Label="OuterPlanarEmbedding">
<#Include Label="SubdigraphHomeomorphicToK">
+ <#Include Label="DualPlanarGraph">
Hashing
diff --git a/gap/planar.gd b/gap/planar.gd
index 6afb5f1e8..36e0726a4 100644
--- a/gap/planar.gd
+++ b/gap/planar.gd
@@ -25,6 +25,7 @@ DeclareAttribute("KuratowskiOuterPlanarSubdigraph", IsDigraph);
DeclareAttribute("SubdigraphHomeomorphicToK23", IsDigraph);
DeclareAttribute("SubdigraphHomeomorphicToK4", IsDigraph);
DeclareAttribute("SubdigraphHomeomorphicToK33", IsDigraph);
+DeclareAttribute("DualPlanarGraph", IsDigraph);
# Properties . . .
diff --git a/gap/planar.gi b/gap/planar.gi
index 8a36385ca..dbcee889e 100644
--- a/gap/planar.gi
+++ b/gap/planar.gi
@@ -73,6 +73,47 @@ SUBGRAPH_HOMEOMORPHIC_TO_K4);
InstallMethod(SubdigraphHomeomorphicToK33, "for a digraph", [IsDigraph],
SUBGRAPH_HOMEOMORPHIC_TO_K33);
+InstallMethod(DualPlanarGraph, "for a digraph", [IsDigraph],
+function(D)
+ local digraph, rotationSystem, facialWalks, dualEdges,
+ cycle1, cycle2, commonNodes, i;
+
+ if not IsPlanarDigraph(D) then
+ return fail;
+ fi;
+
+ digraph := DigraphSymmetricClosure(DigraphRemoveLoops(
+ DigraphRemoveAllMultipleEdges(DigraphMutableCopyIfMutable(D))));
+ rotationSystem := PlanarEmbedding(digraph);
+ facialWalks := FacialWalks(digraph, rotationSystem);
+
+ dualEdges := [];
+ for cycle1 in [1 .. Length(facialWalks) - 1] do
+ for cycle2 in [cycle1 .. Length(facialWalks)] do
+ if cycle1 = cycle2 then
+ if not IsDuplicateFree(facialWalks[cycle1]) then
+ Add(dualEdges, [cycle1, cycle1]);
+ fi;
+ else
+ commonNodes := Intersection(facialWalks[cycle1],
+ facialWalks[cycle2]);
+ if Length(commonNodes) = Length(facialWalks[cycle1]) then
+ for i in [1 .. Length(commonNodes)] do
+ Add(dualEdges, [cycle1, cycle2]);
+ Add(dualEdges, [cycle2, cycle1]);
+ od;
+ else
+ for i in [1 .. Length(commonNodes) - 1] do
+ Add(dualEdges, [cycle1, cycle2]);
+ Add(dualEdges, [cycle2, cycle1]);
+ od;
+ fi;
+ fi;
+ od;
+ od;
+ return DigraphByEdges(dualEdges);
+end);
+
########################################################################
# 2. Properties
########################################################################
diff --git a/tst/standard/attr.tst b/tst/standard/attr.tst
index 8e87659b5..39a88872e 100644
--- a/tst/standard/attr.tst
+++ b/tst/standard/attr.tst
@@ -1074,11 +1074,11 @@ gap> DigraphAllUndirectedSimpleCircuits(g);
# FacialCycles
gap> g := Digraph([]);;
gap> rotationSy := [];;
-gap> FacialWalks(g,rotationSy);
+gap> FacialWalks(g, rotationSy);
[ ]
-gap> g := Digraph([[2],[1,3],[2,4],[3]]);;;
-gap> rotationSy := [[2],[1,3],[2,4],[3]];;
-gap> FacialWalks(g,rotationSy);
+gap> g := Digraph([[2], [1, 3], [2, 4], [3]]);;;
+gap> rotationSy := [[2], [1, 3], [2, 4], [3]];;
+gap> FacialWalks(g, rotationSy);
[ [ 1, 2, 3, 4, 3, 2 ] ]
gap> g := CycleDigraph(4);;
gap> planar := PlanarEmbedding(g);
@@ -1095,6 +1095,13 @@ gap> rotationSystem := PlanarEmbedding(g);
gap> FacialWalks(g, rotationSystem);
[ [ 1, 3, 6 ], [ 1, 4, 5 ], [ 1, 5, 3 ], [ 1, 6, 4 ], [ 2, 3, 5 ],
[ 2, 4, 6 ], [ 2, 5, 4 ], [ 2, 6, 3 ] ]
+gap> g := Digraph([[2, 3, 4], [1, 3, 5], [1, 2, 4], [1, 3, 5], [2, 4, 6], [5, 7, 9], [6, 8, 10], [7, 9, 10], [6, 8, 10], [7, 8, 9]]);;
+gap> rotationSy := PlanarEmbedding(g);
+[ [ 2, 4, 3 ], [ 3, 5, 1 ], [ 1, 4, 2 ], [ 1, 5, 3 ], [ 2, 4, 6 ],
+ [ 5, 7, 9 ], [ 8, 10, 6 ], [ 9, 10, 7 ], [ 6, 10, 8 ], [ 7, 8, 9 ] ]
+gap> FacialWalks(g, rotationSy);
+[ [ 1, 2, 3 ], [ 1, 3, 4 ], [ 1, 4, 5, 6, 7, 8, 9, 6, 5, 2 ], [ 2, 5, 4, 3 ],
+ [ 6, 9, 10, 7 ], [ 7, 10, 8 ], [ 8, 10, 9 ] ]
# Issue #676
gap> D := Digraph([[], [3], []]);;
diff --git a/tst/standard/planar.tst b/tst/standard/planar.tst
index b0d08f622..870f2d6f7 100644
--- a/tst/standard/planar.tst
+++ b/tst/standard/planar.tst
@@ -230,6 +230,26 @@ gap> D := CompleteDigraph(3);
gap> KuratowskiOuterPlanarSubdigraph(D);
fail
+# DualPlanarGraph
+gap> DualPlanarGraph(CompleteDigraph(5));
+fail
+gap> D := CycleDigraph(4);
+
+gap> DualPlanarGraph(D);
+
+gap> D := ChainDigraph(4);
+
+gap> DualPlanarGraph(D);
+
+gap> D := Digraph([[2, 3, 4], [1, 3, 5], [1, 2, 4], [1, 3, 5], [2, 4, 6], [5, 7, 9], [6, 8, 10], [7, 9, 10], [6, 8, 10], [7, 8, 9]]);;
+gap> dualD := DualPlanarGraph(D);
+
+gap> DigraphHasLoops(dualD);
+true
+gap> D := CompleteDigraph(3);;
+gap> DualPlanarGraph(D);
+
+
# Kernel function boyers_planarity_check, errors
gap> IS_PLANAR(2);
Error, Digraphs: boyers_planarity_check (C): the 1st argument must be a digrap\