package Graph::Layout::Aesthetic::Force::Perl;
use 5.006001;
use strict;
use warnings;

our $VERSION = '0.01';
use base qw(Graph::Layout::Aesthetic::Force);

1;
__END__

=head1 NAME

Graph::Layout::Aesthetic::Force::Perl - Write aesthetic forces in perl

=head1 SYNOPSIS

  package Something;
  use base qw(Graph::Layout::Aesthetic::Force::Perl);

  # If you need a private constructor, don't forget to chain it
  # sub new {
  #     my $force = shift->SUPER::new;
  #     # do something, maybe with $force->_private_data
  #     return $force;
  # }

  sub setup {
      my ($force, $aglo) = @_;
      # Do any needed preparations
      return $closure;
  }

  sub gradient {
      my ($force, $aglo, $gradient, $closure) = @_;
      # Calculate forces into $gradient
  }

  sub cleanup {
      my ($force, $aglo, $closure) = @_;
      # Maybe need some cleanup on $closure
  }

  # If you need a DESTROY, don't forget to chain it
  # sub DESTROY {
  #     my $force = shift;
  #     # do something, maybe with $force->_private_data
  #     $force->SUPER::DESTROY;
  # }

  # Override name if you don't like the default
  # sub name {
  #    return "Something";
  # }

  # Typically you then provide one instance of your force and register it
  __PACKAGE__->new->register;

=head1 DESCRIPTION

Graph::Layout::Aesthetic::Force::Perl is a baseclass for writing perl based
L<aesthetic forces|Graph::Layout::Aesthetic::Force>. This can be as simple as
just providing a gradient method.

=head1 EXAMPLE

This code duplicates what
L<Graph::Layout::Aesthetic::Force::MinEdgeLength|Graph::Layout::Aesthetic::Force::MinEdgeLength>
does (minimize edge lengths), but in pure perl.

    package Graph::Layout::Aesthetic::Force::Mel;
    use warnings;
    use strict;

    use base qw(Graph::Layout::Aesthetic::Force::Perl);

    sub gradient {
        my (undef, $state, $gradient) = @_;
        my @delta;

        my @coordinates = $state->all_coordinates;
        my $max_d = $state->nr_dimensions()-1;

        for ($state->topology->edges) {
            my $from = $coordinates[$_->[0]];
            my $to   = $coordinates[$_->[1]];
            my $dist = 0;
            $dist += ($delta[$_] = $to->[$_]-$from->[$_])**2 for 0..$max_d;
            $dist = sqrt($dist);
            next if $dist < 1e-8;

            $from = $gradient->[$_->[0]];
            $to   = $gradient->[$_->[1]];
            for(0..$max_d) {
                $from->[$_] += $delta[$_] *= $dist;
                $to->[$_]   -= $delta[$_];
            }
        }
    }

    __PACKAGE__->new->register;

=head1 METHODS

Graph::Layout::Aesthetic::Force::Perl inherits from
L<Graph::Layout::Aesthetic::Force|Graph::Layout::Aesthetic::Force>, so all
methods of that class are available. As extension writer you will probably be
most interested in L<register|Graph::Layout::Aesthetic::Force/register> and
L<_private_data|Graph::Layout::Aesthetic::Force/_private_data>.

The methods explained here aren't normally directly called by the user or
even the programmer of the force, but implicitely by using the
L<Graph::Layout::Aesthetic|Graph::Layout::Aesthetic> package. They are
documented here so the implementer of a force class (who can override the
defaults) can see when and with which arguments his methods get called

=over

=item X<new>$force = Graph::Layout::Aesthetic::Force::Perl->new

This is the default constructor provided by
Graph::Layout::Aesthetic::Force::Perl. It is returns a perl wrapper around a
C-structure (which is what a
L<Graph::Layout::Aesthetic::Force|Graph::Layout::Aesthetic::Force> object must
be). So if you want to write your own constructor, you'll still need to call
this internally, and then you can use
L<_private_data|Graph::Layout::Aesthetic::Force/_private_data> to associate
extra state with the force.

=item X<setup>$closure = $force->setup($state)

This method gets called when a L<force|Graph::Layout::Aesthetic::Force> gets
associated with L<a layout state|Graph::Layout::Aesthetic> (it corresponds to
L<aesth_setup in Graph::Layout::Aesthetic::Force|Graph::Layout::Aesthetic::Force/aesth_setup>).
It is supposed to return some scalar that will then later be passed again to
any corresponding L<gradient|"gradient"> and L<cleanup|"cleanup"> method calls.
So the $closure value can be used to associate state with a force/state pair.

The default provided by Graph::Layout::Aesthetic::Force::Perl does nothing
and simply returns undef.

=item X<gradient>@gradient = $force->gradient($state, $gradient, $closure)

This method gets called whenever a preferred gradient for a force is needed
while laying out a graph (it corresponds to
L<aesth_gradient in Graph::Layout::Aesthetic::Force|Graph::Layout::Aesthetic::Force/aesth_gradient>). It gets passed a starting $gradient, which is an array
reference with an element for each vertex. Each element in turn is an array
reference to coordinate forces. All of these have already been initialized to
zero at the start of the method call. The method is now responsible for filling
in these values. The direction of the force should be a direction in which an
infinitesimal step will improve the target aesthetic, and the size should
correspond with how fast it improves in that direction.

There is no default gradient method, you must provide one yourself in your
subclass.

=item X<cleanup>$force->cleanup($state, $closure)

This method gets called when $force gets disassociated from $state (it
corresponds to
L<aesth_cleanup in Graph::Layout::Aesthetic::Force|Graph::Layout::Aesthetic::Force/aesth_cleanup>).
A typical use would be to clean up things implied by $closure.

Since perl has its own garbage collection and you can already associate methods
with data going away, quite often you don't want to do anything here. Which is
exactly what the default cleanup method does: nothing.

=item X<DESTROY>$force->DESTROY

Actually Graph::Layout::Aesthetic::Force::Perl (currently) has no DESTROY
method, but inherits the one from
L<Graph::Layout::Aesthetic::Force|Graph::Layout::Aesthetic::Force>. That one
however must be called if in the end the $force object was constructed with
the local L<new|"new"> method. So if you override DESTROY in your subclass, 
you need to chain to that one (simply using $force->SUPER::DESTROY should be 
good enough).

=back

=head1 EXPORT

None.

=head1 SEE ALSO

L<Graph::Layout::Aesthetic>,
L<Graph::Layout::Aesthetic::Force>

=head1 AUTHOR

Ton Hospel, E<lt>Graph::Layout::Aesthetic@ton.iguana.be<gt>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2004 by Ton Hospel

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.6.1 or,
at your option, any later version of Perl 5 you may have available.

=cut
