CXC-Number
view release on metacpan or search on metacpan
lib/CXC/Number/Grid/Tree.pm view on Meta::CPAN
sub snap_overlaid ( $self, $layer, $snap_to, $snap_dist ) { ## no critic(Subroutines::ProhibitManyArgs)
return if $snap_dist == 0;
# Tree::Range doesn't represent a range as a node with the ability
# to visit a predecessor. It essentially only allows one way
# tree traversal, so we need to traverse it forwards to handle
# snapping to the right, and backwards to handle snapping to the left.
$self->_snap_overlaid_edges( $layer, $snap_to, $snap_dist, $_ ) for qw( right left );
}
sub _snap_overlaid_edges ( $self, $layer, $snap_to, $snap_dist, $scan_direction ) { ## no critic(Subroutines::ProhibitManyArgs)
require CXC::Number::Grid::Range;
defined( my $scan_reversed = { right => 0, left => 1 }->{$scan_direction} )
or _croak( "illegal scan direction: '$scan_direction'" );
my sub iter ( $key = undef ) {
my $iter = $self->range_iter_closure( $key, $scan_reversed );
# first range goes from +-inf to real bound; remove
$iter->() unless defined $key;
return $iter;
}
my $iter = iter();
my sub next_range {
my @r = $iter->();
return @r
? CXC::Number::Grid::Range->new( {
value => $r[0],
lb => $r[1],
ub => $r[2],
} )
: undef;
}
my $current = next_range();
my $next;
my %SnapTo = (
overlay => {
right => sub {
# would prefer
# $self->range_set( $prev->lb, $current->ub, $current->value );
# but there's no way to get $prev from Tree::Range.
#
# This code depends upon Tree::Range storing [ $lb, $value ]
# in each node, so deleting a node extends the previous
# range.
$self->delete( $current->lb );
$iter = iter( $current->lb );
},
left => sub {
$self->range_set( $next->lb, $current->ub, $next->value );
$iter = iter( $current->ub );
},
},
underlay => {
right => sub {
$self->range_set( $current->lb, $next->ub, $next->value );
$iter = iter( $current->lb );
},
left => sub {
$self->range_set( $next->lb, $current->ub, $next->value );
$iter = iter( $current->ub );
},
},
);
my $snap = $SnapTo{$snap_to}{$scan_direction}
or _croak( "unknown layer to snap to: $snap_to" );
while ( defined( $next = next_range() ) ) {
if ( abs( $current->ub - $current->lb ) <= $snap_dist
&& $next->layer == $layer
&& $current->layer < $next->layer )
{
$snap->();
# all of the $snap routines reset the iterator
$current = next_range();
}
else {
$current = $next;
}
}
}
sub clone ( $self ) {
return __PACKAGE__->from_array( $self->to_array );
}
lib/CXC/Number/Grid/Tree.pm view on Meta::CPAN
This is a subclass of L<Tree::Range> which is used to manipulate grids
=head1 CONSTRUCTORS
=head2 new
$tree = CXC::Number::Grid::Tree->new( ?\%options )
Construct a new tree, using a default numerical key comparison
function. All options recognized by L<Tree::Range::RB> are accepted.
=head2 from_array
$tree = CXC::Number::Grid::Tree->from_array( \@array );
Construct a tree object from an array generated by L</to_array>.
=head2 from_grid
$tree = CXC::Number::Grid::Tree->from_grid( $grid );
Construct a tree object from a L<CXC::Number::Grid> object.
=head1 METHODS
=head2 to_string
$tree->to_string;
Return a string representation of the tree.
=head2 to_array
\@array = $tree->to_array;
Return an arrayref with one element per bin. Each element is an
arrayref and contains the lower bound, upper bound, and value stored
in the tree for the bin bin.
=head2 to_grid
$grid = $tree->to_grid;
Return a L<CXC::Number::Grid> object represented by the tree.
=head2 snap_overlaid
$tree->snap_overlaid( $layer, $snap_to, $snap_dist ) {
Snap overlaid bins' edges.
B<Works in place!!>
This assumes that the Tree has been
=over
=item 1
loaded with ranges from two grids, one of which overlays the other; and
=item 2
that the range values are arrayrefs with the first value being the
layer id (larger number indicates the top grid); and
=item 3
that the top grid is contiguous (e.g. no holes through which the
lower grid is visible)
=back
In the general case, the minimum and maximum edges of the top grid
will intersect bins in the lower grid. If the remnants of those bins
(e.g. the parts not covered by the top grid) are small enough (e.g,
smaller than C<$snap_dist> in width), then this routine will either:
=over
=item *
move the outer edge of the top grid to coincide with the remaining edge of the intersected lower bin
(C<$snap_to = 'underlay'>)
=item *
move the remaining edge of the intersected lower bin to coincide with the edge of the top grid.
(C<$snap_to = 'overlay'>)
=back
=head2 clone
$clone = $tree->clone;
Clone a tree, performing a shallow copy of the values associated with each bin in the tree.
=head1 INTERNALS
=head2 Methods
=head3 _snap_overlaid_edges
$self->_snap_overlaid_edges( $layer, $snap_to, $snap_dist, $scan_direction ) {
A helper for L</snap_to>. This routine is run twice, with
C<$scan_direction> set to C<left> and C<right>, then to handle the
extrema of the overlaid grid.
=head1 SUPPORT
=head2 Bugs
Please report any bugs or feature requests to bug-cxc-number@rt.cpan.org or through the web interface at: L<https://rt.cpan.org/Public/Dist/Display.html?Name=CXC-Number>
=head2 Source
Source is available at
https://gitlab.com/djerius/cxc-number
and may be cloned from
https://gitlab.com/djerius/cxc-number.git
=head1 SEE ALSO
Please see those modules/websites for more information related to this module.
=over 4
=item *
L<CXC::Number|CXC::Number>
=item *
L<CXC::Number::Grid|CXC::Number::Grid>
=item *
L<CXC::Number::Grid::Range|CXC::Number::Grid::Range>
=back
=head1 AUTHOR
Diab Jerius <djerius@cpan.org>
( run in 0.831 second using v1.01-cache-2.11-cpan-97f6503c9c8 )