# Copyright 2015 Kevin Ryde
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3, or (at your option) any later
# version.
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this file.  See the file COPYING.  If not, see
# <http://www.gnu.org/licenses/>.

package Graph::Maker::TwindragonAreaTree;
use 5.004;
use strict;
use Math::PlanePath::DragonCurve 117; # v.117 for level_to_n_range()
use Math::PlanePath::ComplexPlus;

use base 'Graph::Maker';

use vars '$VERSION';
$VERSION = 4;

# uncomment this to run the ### lines
# use Smart::Comments;

sub _default_graph_maker {
  require Graph;
  Graph->new(@_);
}
sub init {
  my ($self, %params) = @_;

  my $level = delete($params{level}) || 0;
  ### $level

  my $graph_maker = delete($params{'graph_maker'});
  $graph_maker ||= \&_default_graph_maker;

  my $graph = $graph_maker->(%params);
  $graph->set_graph_attribute(name => "Twindragon Area Tree level=$level");
  $graph->add_vertex(0);
  my $directed = $graph->is_directed;

 V: foreach my $v (0 .. 2**$level-1) {
    # ...1 edge to ...0
    if ($v & 1) {
      my $to = $v ^ 1;
      $graph->add_edge($v, $to);
      if ($directed) { $graph->add_edge($to, $v); }
    }

    #  ...10 11...11
    #        \-----/ zero or more low 1 bits
    # edge to
    #  ...01 00...00
    #
    my $bit = 1;
    for (my $pos = 1; ; $pos++) {
      $pos < $level or next V;
      $v & $bit or last;
      $bit <<= 1;
    }
    $bit <<= 1;
    if ($v & $bit) {
      my $to = $v-$bit+1;
      $graph->add_edge($v, $to);
      if ($directed) { $graph->add_edge($to, $v); }
    }
  }
  return $graph;
}

Graph::Maker->add_factory_type('twindragon_area_tree' => __PACKAGE__);
1;

=for stopwords Ryde

=head1 NAME

Graph::Maker::TwindragonAreaTree - create twindragon area tree graph

=for test_synopsis my ($graph)

=head1 SYNOPSIS

 use Graph::Maker::TwindragonAreaTree;
 $graph = Graph::Maker->new ('twindragon_area_tree', level => 5);

=head1 DESCRIPTION

C<Graph::Maker::TwindragonAreaTree> creates C<Graph.pm> graphs of the
twindragon area tree.

In the twindragon area tree vertices are unit squares enclosed inside the
twindragon curve.  Edges are between pairs of squares which have sides
consecutive in the curve.  Or equivalently if the curve is drawn with
corners chamfered off to leave little gaps at corners then edges connect
squares through those gaps.

Vertices are numbered 0 to 2^level-1 which are the complex base i+1 points
corresponding to each unit square in the twindragon.  With such vertices
edges are between those with bit patterns

            ...0   <-->   ...1            toggle low bit

    ...01 00..00   <-->   ...10 11..11    zero or more trailing
          \----/                \----/    0s/1s, same count both

The value on the right is the bigger of each.  The current code takes each
of those and connects the smaller.

In tree level 0 there is a single vertex and no edges.

In tree level 1 there are two vertices 0 and 1 and an edge between them by
the toggle low bit rule.

    0---1          level => 1

In tree level 2 the trailing bits rule connects vertices 1 = 01 binary and 2
= 10 binary.  There are no trailing 0s on 01 and corresponding no trailing
1s on 10.

        2---3  
        |          level => 2
    0---1

In tree level 3 the first degree-3 vertices arise.  Vertex 2 = binary 010 is
connected to 3=011 by the low bit rule, to 1=001 by the trailing rule, and
up to 5=101 by the trailing rule.

        6---7
        |
    4---5          level => 3
        |
        2---3
        |
    0---1

Some properties of the twindragon area tree can be found in the author's
mathematical write-up

=over

L<http://user42.tuxfamily.org/dragon/index.html>

=back

A level 10 twindragon area tree appears in Mandelbrot's "Fractal Geometry of
Nature", second edition, 1983, page 67, called by Mandelbrot the "twindragon
river".

=head1 FUNCTIONS

=over

=item C<$graph = Graph::Maker-E<gt>new('twindragon_area_tree', key =E<gt> value, ...)>

The key/value parameters are

    level      =>  integer

Other parameters are passed to C<Graph-E<gt>new()>.

Like C<Graph::Maker::BalancedTree>, if the graph is directed (the default)
then edges are added in both directions between nodes.  Option C<undirected
=E<gt> 1> creates an undirected graph and for it there is a single edge
between vertices.

=back

=head1 SEE ALSO

L<Graph::Maker>,
L<Graph::Maker::BalancedTree>

=head1 LICENSE

Copyright 2015 Kevin Ryde

This file is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any later
version.

This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
more details.

You should have received a copy of the GNU General Public License along with
This file.  If not, see L<http://www.gnu.org/licenses/>.

=cut
