package Geo::GDAL::FFI::Layer;
use v5.10;
use strict;
use warnings;
use Carp;
use base 'Geo::GDAL::FFI::Object';
our $VERSION = 0.0900;
sub DESTROY {
my $self = shift;
Geo::GDAL::FFI::OGR_L_SyncToDisk($$self);
#say STDERR "delete parent $parent{$$self}";
Geo::GDAL::FFI::_deregister_parent_ref ($$self);
#say STDERR "destroy $self";
}
sub GetParentDataset {
my ($self) = @_;
return Geo::GDAL::FFI::_get_parent_ref ($$self);
}
sub GetDefn {
my $self = shift;
my $d = Geo::GDAL::FFI::OGR_L_GetLayerDefn($$self);
return bless \$d, 'Geo::GDAL::FFI::FeatureDefn';
}
sub CreateField {
my $self = shift;
my $def = shift;
unless (ref $def) {
# name => type calling syntax
my $name = $def;
my $type = shift;
$def = Geo::GDAL::FFI::FieldDefn->new({Name => $name, Type => $type})
} elsif (ref $def eq 'HASH') {
$def = Geo::GDAL::FFI::FieldDefn->new($def)
}
my $approx_ok = shift // 1;
my $e = Geo::GDAL::FFI::OGR_L_CreateField($$self, $$def, $approx_ok);
return unless $e;
confess Geo::GDAL::FFI::error_msg({OGRError => $e});
}
sub CreateGeomField {
my $self = shift;
my $def = shift;
unless (ref $def) {
# name => type calling syntax
my $name = $def;
my $type = shift;
$def = Geo::GDAL::FFI::GeomFieldDefn->new({Name => $name, Type => $type});
} elsif (ref $def eq 'HASH') {
$def = Geo::GDAL::FFI::GeomFieldDefn->new($def)
}
my $approx_ok = shift // 1;
my $e = Geo::GDAL::FFI::OGR_L_CreateGeomField($$self, $$def, $approx_ok);
return unless $e;
confess Geo::GDAL::FFI::error_msg({OGRError => $e});
}
sub GetSpatialRef {
my ($self) = @_;
my $sr = Geo::GDAL::FFI::OGR_L_GetSpatialRef($$self);
return unless $sr;
return bless \$sr, 'Geo::GDAL::FFI::SpatialReference';
}
sub ResetReading {
my $self = shift;
Geo::GDAL::FFI::OGR_L_ResetReading($$self);
}
sub GetNextFeature {
my $self = shift;
my $f = Geo::GDAL::FFI::OGR_L_GetNextFeature($$self);
return unless $f;
return bless \$f, 'Geo::GDAL::FFI::Feature';
}
sub GetFeature {
my ($self, $fid) = @_;
my $f = Geo::GDAL::FFI::OGR_L_GetFeature($$self, $fid);
confess unless $f;
return bless \$f, 'Geo::GDAL::FFI::Feature';
}
sub SetFeature {
my ($self, $f) = @_;
Geo::GDAL::FFI::OGR_L_SetFeature($$self, $$f);
}
sub CreateFeature {
my ($self, $f) = @_;
my $e = Geo::GDAL::FFI::OGR_L_CreateFeature($$self, $$f);
return $f unless $e;
}
sub DeleteFeature {
my ($self, $fid) = @_;
my $e = Geo::GDAL::FFI::OGR_L_DeleteFeature($$self, $fid);
return unless $e;
confess Geo::GDAL::FFI::error_msg({OGRError => $e});
}
__PACKAGE__->_make_overlay_methods();
sub _make_overlay_methods {
my ($pkg) = @_;
my @methods = (qw /
Intersection Union SymDifference
Identity Update Clip Erase
/);
no strict 'refs';
foreach my $method_name (@methods) {
*{$pkg . '::' . $method_name} =
sub {
my ($self, $method, $args) = @_;
confess "Method layer missing." unless $method;
$args //= {};
my $result = $args->{Result};
unless ($result) {
my $schema = {
GeometryType => 'Unknown'
};
$result = Geo::GDAL::FFI::GetDriver('Memory')->Create->CreateLayer($schema);
}
my $o = 0;
for my $key (keys %{$args->{Options}}) {
$o = Geo::GDAL::FFI::CSLAddString($o, "$key=$args->{Options}{$key}");
}
my $p = 0;
$p = FFI::Platypus->new->closure($args->{Progress}) if $args->{Progress};
my $e = &{'Geo::GDAL::FFI::OGR_L_'.$method_name} ($$self, $$method, $$result, $o, $p, $args->{ProgressData});
Geo::GDAL::FFI::CSLDestroy($o);
return $result unless $e;
confess Geo::GDAL::FFI::error_msg({OGRError => $e});
};
}
return;
}
sub GetExtent {
my ($self, $force) = @_;
my $extent = [0,0,0,0];
$force = $force ? \1 : \0; # ensure $force is a ref
my $e = Geo::GDAL::FFI::OGR_L_GetExtent ($$self, $extent, $force);
return $extent unless $e;
confess Geo::GDAL::FFI::error_msg({OGRError => $e});
}
sub GetName {
my ($self) = @_;
return $self->GetDefn->GetName;
}
1;
=pod
=encoding UTF-8
=head1 NAME
Geo::GDAL::FFI::Layer - A collection of vector features in GDAL
=head1 SYNOPSIS
=head1 DESCRIPTION
A set of (vector) features having a same schema (the same Defn
object). Obtain a layer object by the CreateLayer or GetLayer method
of a vector dataset object.
=head1 METHODS
=head2 GetDefn
my $defn = $layer->GetDefn;
Returns the FeatureDefn object for this layer.
=head2 ResetReading
$layer->ResetReading;
=head2 GetNextFeature
my $feature = $layer->GetNextFeature;
=head2 GetFeature
my $feature = $layer->GetFeature($fid);
=head2 SetFeature
$layer->SetFeature($feature);
=head2 CreateFeature
$layer->CreateFeature($feature);
=head2 DeleteFeature
$layer->DeleteFeature($fid);
=head2 GetExtent
$layer->GetExtent();
$layer->GetExtent(1);
Returns an array ref with [minx, miny, maxx, maxy].
Argument is a boolean to force calculation even
if it is expensive.
=head2 Intersection, Union, SymDifference, Identity, Update, Clip, Erase
$result = $layer-><Method>($method, $args);
Runs the <method> algorithm between layer and method layer. Named
arguments are the following.
=over 4
=item C<Result>
Optional, allows the user to define the result layer.
=item C<Options>
Optional, allows the user to define the options (see GDAL docs).
=item C<Progress>
Optional, the progress indicator callback.
=item C<ProgressData>
Optional, data for the progress callback.
=back
=head1 LICENSE
This software is released under the Artistic License. See
L<perlartistic>.
=head1 AUTHOR
Ari Jolma - Ari.Jolma at gmail.com
=head1 SEE ALSO
L<Geo::GDAL::FFI>
L<Alien::gdal>, L<FFI::Platypus>, L<http://www.gdal.org>
=cut
__END__;