Geo::GDAL  2.2
all.pm
Go to the documentation of this file.
1 #** @class Geo::GDAL
2 # @brief GDAL utility functions and a root class for raster classes.
3 # @details Geo::GDAL wraps many GDAL utility functions and is as a root class
4 # for all GDAL raster classes. A "raster" is an object, whose core is
5 # a rectagular grid of cells, called a "band" in GDAL. Each cell
6 # contains a numeric value of a specific data type.
7 #*
8 package Geo::GDAL;
9 
10 #** @method ApplyVerticalShiftGrid()
11 #*
12 sub ApplyVerticalShiftGrid {
13 }
14 
15 #** @method BuildVRT()
16 #*
17 sub BuildVRT {
18  for (keys %Geo::GDAL::Const::) {
19  next if /TypeCount/;
20  push(@DATA_TYPES, $1), next if /^GDT_(\w+)/;
21  push(@OPEN_FLAGS, $1), next if /^OF_(\w+)/;
22  push(@RESAMPLING_TYPES, $1), next if /^GRA_(\w+)/;
23  push(@RIO_RESAMPLING_TYPES, $1), next if /^GRIORA_(\w+)/;
24  push(@NODE_TYPES, $1), next if /^CXT_(\w+)/;
25  }
26  for my $string (@DATA_TYPES) {
27  my $int = eval "\$Geo::GDAL::Const::GDT_$string";
28  $S2I{data_type}{$string} = $int;
29  $I2S{data_type}{$int} = $string;
30  }
31  for my $string (@OPEN_FLAGS) {
32  my $int = eval "\$Geo::GDAL::Const::OF_$string";
33  $S2I{open_flag}{$string} = $int;
34  }
35  for my $string (@RESAMPLING_TYPES) {
36  my $int = eval "\$Geo::GDAL::Const::GRA_$string";
37  $S2I{resampling}{$string} = $int;
38  $I2S{resampling}{$int} = $string;
39  }
40  for my $string (@RIO_RESAMPLING_TYPES) {
41  my $int = eval "\$Geo::GDAL::Const::GRIORA_$string";
42  $S2I{rio_resampling}{$string} = $int;
43  $I2S{rio_resampling}{$int} = $string;
44  }
45  for my $string (@NODE_TYPES) {
46  my $int = eval "\$Geo::GDAL::Const::CXT_$string";
47  $S2I{node_type}{$string} = $int;
48  $I2S{node_type}{$int} = $string;
49  }
50  our $HAVE_PDL;
51  eval 'require PDL';
52  $HAVE_PDL = 1 unless $@;
53 }
54 
55 #** @method CPLBinaryToHex()
56 #*
57 sub CPLBinaryToHex {
58 }
59 
60 #** @method CPLHexToBinary()
61 #*
62 sub CPLHexToBinary {
63 }
64 
65 #** @method CreatePansharpenedVRT()
66 #*
67 sub CreatePansharpenedVRT {
68 }
69 
70 #** @method scalar DataTypeIsComplex($DataType)
71 # Package subroutine.
72 # @param DataType A GDAL raster cell data type (one of those listed by Geo::GDAL::DataTypes).
73 # @return true if the data type is a complex number.
74 #*
75 sub DataTypeIsComplex {
76  return _DataTypeIsComplex(s2i(data_type => shift));
77 }
78 
79 #** @method list DataTypeValueRange($DataType)
80 # Package subroutine.
81 # @param DataType Data type (one of those listed by Geo::GDAL::DataTypes).
82 # @note Some returned values are inaccurate.
83 #
84 # @return the minimum, maximum range of the data type.
85 #*
86 sub DataTypeValueRange {
87  my $t = shift;
88  s2i(data_type => $t);
89  # these values are from gdalrasterband.cpp
90  return (0,255) if $t =~ /Byte/;
91  return (0,65535) if $t =~/UInt16/;
92  return (-32768,32767) if $t =~/Int16/;
93  return (0,4294967295) if $t =~/UInt32/;
94  return (-2147483648,2147483647) if $t =~/Int32/;
95  return (-4294967295.0,4294967295.0) if $t =~/Float32/;
96  return (-4294967295.0,4294967295.0) if $t =~/Float64/;
97 }
98 
99 #** @method list DataTypes()
100 # Package subroutine.
101 # @return a list of GDAL raster cell data types. These are currently:
102 # Byte, CFloat32, CFloat64, CInt16, CInt32, Float32, Float64, Int16, Int32, UInt16, UInt32, and Unknown.
103 #*
104 sub DataTypes {
105  return @DATA_TYPES;
106 }
107 
108 #** @method scalar DecToDMS($angle, $axis, $precision=2)
109 # Package subroutine.
110 # Convert decimal degrees to degrees, minutes, and seconds string
111 # @param angle A number
112 # @param axis A string specifying latitude or longitude ('Long').
113 # @param precision
114 # @return a string nndnn'nn.nn'"L where n is a number and L is either
115 # N or E
116 #*
117 sub DecToDMS {
118 }
119 
120 #** @method scalar DecToPackedDMS($dec)
121 # Package subroutine.
122 # @param dec Decimal degrees
123 # @return packed DMS, i.e., a number DDDMMMSSS.SS
124 #*
125 sub DecToPackedDMS {
126 }
127 
128 #** @method DontUseExceptions()
129 # Package subroutine.
130 # Do not use the Perl exception mechanism for GDAL messages. Instead
131 # the messages are printed to standard error.
132 #*
133 sub DontUseExceptions {
134 }
135 
136 #** @method Geo::GDAL::Driver Driver($Name)
137 # Package subroutine.
138 # Access a format driver.
139 # @param Name The short name of the driver. One of
140 # Geo::GDAL::DriverNames or Geo::OGR::DriverNames.
141 # @note This subroutine is imported into the main namespace if Geo::GDAL
142 # is used with qw/:all/.
143 # @return a Geo::GDAL::Driver object.
144 #*
145 sub Driver {
146  return 'Geo::GDAL::Driver' unless @_;
147  my $name = shift;
148  my $driver = GetDriver($name);
149  error("Driver \"$name\" not found. Is it built in? Check with Geo::GDAL::Drivers or Geo::OGR::Drivers.")
150  unless $driver;
151  return $driver;
152 }
153 
154 #** @method list DriverNames()
155 # Package subroutine.
156 # Available raster format drivers.
157 # \code
158 # perl -MGeo::GDAL -e '@d=Geo::GDAL::DriverNames;print "@d\n"'
159 # \endcode
160 # @note Use Geo::OGR::DriverNames for vector drivers.
161 # @return a list of the short names of all available GDAL raster drivers.
162 #*
163 sub DriverNames {
164 }
165 
166 #** @method list Drivers()
167 # Package subroutine.
168 # @note Use Geo::OGR::Drivers for vector drivers.
169 # @return a list of all available GDAL raster drivers.
170 #*
171 sub Drivers {
172  my @drivers;
173  for my $i (0..GetDriverCount()-1) {
174  my $driver = GetDriver($i);
175  push @drivers, $driver if $driver->TestCapability('RASTER');
176  }
177  return @drivers;
178 }
179 
180 #** @method EscapeString()
181 #*
182 sub EscapeString {
183 }
184 
185 #** @method scalar FindFile($basename)
186 # Package subroutine.
187 # Search for GDAL support files.
188 #
189 # An example:
190 # \code
191 # use Geo::GDAL;
192 # $a = Geo::GDAL::FindFile('pcs.csv');
193 # print STDERR "$a\n";
194 # \endcode
195 # Prints (for example):
196 # \code
197 # c:\msys\1.0\local\share\gdal\pcs.csv
198 # \endcode
199 #
200 # @param basename The name of the file to search for. For example
201 # 'pcs.csv'.
202 # @return the path to the searched file or undef.
203 #*
204 sub FindFile {
205  if (@_ == 1) {
206  _FindFile('', @_);
207  } else {
208  _FindFile(@_);
209  }
210 }
211 
212 #** @method FinderClean()
213 # Package subroutine.
214 # Clear the set of support file search paths.
215 #*
216 sub FinderClean {
217 }
218 
219 #** @method GOA2GetAccessToken()
220 #*
221 sub GOA2GetAccessToken {
222 }
223 
224 #** @method GOA2GetAuthorizationURL()
225 #*
226 sub GOA2GetAuthorizationURL {
227 }
228 
229 #** @method GOA2GetRefreshToken()
230 #*
231 sub GOA2GetRefreshToken {
232 }
233 
234 #** @method scalar GetCacheMax()
235 # Package subroutine.
236 # @return maximum amount of memory (as bytes) for caching within GDAL.
237 #*
238 sub GetCacheMax {
239 }
240 
241 #** @method scalar GetCacheUsed()
242 # Package subroutine.
243 # @return the amount of memory currently used for caching within GDAL.
244 #*
245 sub GetCacheUsed {
246 }
247 
248 #** @method scalar GetConfigOption($key)
249 # Package subroutine.
250 # @param key A GDAL config option. Consult <a
251 # href="https://trac.osgeo.org/gdal/wiki/ConfigOptions">the GDAL
252 # documentation</a> for available options and their use.
253 # @return the value of the GDAL config option.
254 #*
255 sub GetConfigOption {
256 }
257 
258 #** @method scalar GetDataTypeSize($DataType)
259 # Package subroutine.
260 # @param DataType A GDAL raster cell data type (one of those listed by Geo::GDAL::DataTypes).
261 # @return the size as the number of bits.
262 #*
263 sub GetDataTypeSize {
264  return _GetDataTypeSize(s2i(data_type => shift, 1));
265 }
266 
267 #** @method GetJPEG2000StructureAsString()
268 #*
269 sub GetJPEG2000StructureAsString {
270 }
271 
272 #** @method Geo::GDAL::Driver IdentifyDriver($path, $siblings)
273 # Package subroutine.
274 # @param path a dataset path.
275 # @param siblings [optional] A list of names of files that belong to the data format.
276 # @return a Geo::GDAL::Driver.
277 #*
278 sub IdentifyDriver {
279 }
280 
281 #** @method IdentifyDriverEx()
282 #*
283 sub IdentifyDriverEx {
284 }
285 
286 #** @method Geo::GDAL::Dataset Open(%params)
287 # Package subroutine.
288 # Open a dataset.
289 # An example, which opens an existing raster dataset for editing:
290 # \code
291 # use Geo::GDAL qw/:all/;
292 # $ds = Open(Name => 'existing.tiff', Access => 'Update');
293 # \endcode
294 # @param params Named parameters:
295 # - \a Name Dataset string (typically a filename). Default is '.'.
296 # - \a Access Access type, either 'ReadOnly' or 'Update'. Default is 'ReadOnly'.
297 # - \a Type Dataset type, either 'Raster', 'Vector', or 'Any'. Default is 'Any'.
298 # - \a Options A hash of GDAL open options passed to candidate drivers. Default is {}.
299 # - \a Files A list of names of files that are auxiliary to the main file. Default is [].
300 #
301 # @note This subroutine is imported into the main namespace if Geo::GDAL
302 # is use'd with qw/:all/.
303 #
304 # @note Some datasets / dataset strings do not explicitly imply the
305 # dataset type (for example a PostGIS database). If the type is not
306 # specified in such a case the returned dataset may be of either type.
307 #
308 # @return a new Geo::GDAL::Dataset object if success.
309 #*
310 sub Open {
311  my $p = named_parameters(\@_, Name => '.', Access => 'ReadOnly', Type => 'Any', Options => {}, Files => []);
312  my @flags;
313  my %o = (READONLY => 1, UPDATE => 1);
314  error(1, $p->{access}, \%o) unless $o{uc($p->{access})};
315  push @flags, uc($p->{access});
316  %o = (RASTER => 1, VECTOR => 1, ANY => 1);
317  error(1, $p->{type}, \%o) unless $o{uc($p->{type})};
318  push @flags, uc($p->{type}) unless uc($p->{type}) eq 'ANY';
319  my $dataset = OpenEx(Name => $p->{name}, Flags => \@flags, Options => $p->{options}, Files => $p->{files});
320  unless ($dataset) {
321  my $t = "Failed to open $p->{name}.";
322  $t .= " Is it a ".lc($p->{type})." dataset?" unless uc($p->{type}) eq 'ANY';
323  error($t);
324  }
325  return $dataset;
326 }
327 
328 #** @method Geo::GDAL::Dataset OpenEx(%params)
329 # Package subroutine.
330 # The generic dataset open method, used internally by all Open and OpenShared methods.
331 # @param params Named parameters:
332 # - \a Name The name of the data set or source to open. (Default is '.')
333 # - \a Flags A list of access mode flags. Available flags are listed by Geo::GDAL::OpenFlags(). (Default is [])
334 # - \a Drivers A list of short names of drivers that may be used. Empty list means all. (Default is [])
335 # - \a Options A hash of GDAL open options passed to candidate drivers. (Default is {})
336 # - \a Files A list of names of files that are auxiliary to the main file. (Default is [])
337 #
338 # An example
339 # \code
340 # $ds = Geo::GDAL::OpenEx(Name => 'existing.tiff', Flags => [qw/RASTER UPDATE/]);
341 # \endcode
342 # @return a new Geo::GDAL::Dataset object.
343 #*
344 sub OpenEx {
345  my $p = named_parameters(\@_, Name => '.', Flags => [], Drivers => [], Options => {}, Files => []);
346  unless ($p) {
347  my $name = shift // '';
348  my @flags = @_;
349  $p = {name => $name, flags => \@flags, drivers => [], options => {}, files => []};
350  }
351  if ($p->{flags}) {
352  my $f = 0;
353  for my $flag (@{$p->{flags}}) {
354  $f |= s2i(open_flag => $flag);
355  }
356  $p->{flags} = $f;
357  }
358  return _OpenEx($p->{name}, $p->{flags}, $p->{drivers}, $p->{options}, $p->{files});
359 }
360 
361 #** @method list OpenFlags()
362 # Package subroutine.
363 # @return a list of GDAL data set open modes. These are currently:
364 # ALL, GNM, RASTER, READONLY, SHARED, UPDATE, VECTOR, and VERBOSE_ERROR.
365 #*
366 sub OpenFlags {
367  return @DATA_TYPES;
368 }
369 
370 #** @method scalar PackCharacter($DataType)
371 # Package subroutine.
372 # Get the character that is needed for Perl's pack and unpack when
373 # they are used with Geo::GDAL::Band::ReadRaster and
374 # Geo::GDAL::Band::WriteRaster. Note that Geo::GDAL::Band::ReadTile
375 # and Geo::GDAL::Band::WriteTile have simpler interfaces that do not
376 # require pack and unpack.
377 # @param DataType A GDAL raster cell data type, typically from $band->DataType.
378 # @return a character which can be used in Perl's pack and unpack.
379 #*
380 sub PackCharacter {
381  my $t = shift;
382  $t = i2s(data_type => $t);
383  s2i(data_type => $t); # test
384  my $is_big_endian = unpack("h*", pack("s", 1)) =~ /01/; # from Programming Perl
385  return 'C' if $t =~ /^Byte$/;
386  return ($is_big_endian ? 'n': 'v') if $t =~ /^UInt16$/;
387  return 's' if $t =~ /^Int16$/;
388  return ($is_big_endian ? 'N' : 'V') if $t =~ /^UInt32$/;
389  return 'l' if $t =~ /^Int32$/;
390  return 'f' if $t =~ /^Float32$/;
391  return 'd' if $t =~ /^Float64$/;
392 }
393 
394 #** @method scalar PackedDMSToDec($packed)
395 # Package subroutine.
396 # @param packed DMS as a number DDDMMMSSS.SS
397 # @return decimal degrees
398 #*
399 sub PackedDMSToDec {
400 }
401 
402 #** @method PopFinderLocation()
403 # Package subroutine.
404 # Remove the latest addition from the set of support file search
405 # paths. Note that calling this subroutine may remove paths GDAL put
406 # into the finder.
407 #*
408 sub PopFinderLocation {
409 }
410 
411 #** @method PushFinderLocation($path)
412 # Package subroutine.
413 # Add a path to the set of paths from where GDAL support files are
414 # sought. Note that GDAL puts initially into the finder the current
415 # directory and value of GDAL_DATA environment variable (if it
416 # exists), installation directory (prepended with '/share/gdal' or
417 # '/Resources/gdal'), or '/usr/local/share/gdal'. It is usually only
418 # needed to add paths to the finder if using an alternate set of data
419 # files or a non-installed GDAL is used (as in testing).
420 #*
421 sub PushFinderLocation {
422 }
423 
424 #** @method RELEASE_PARENT()
425 #*
426 sub RELEASE_PARENT {
427 }
428 
429 #** @method list RIOResamplingTypes()
430 # Package subroutine.
431 # @return a list of GDAL raster IO resampling methods. These are currently:
432 # Average, Bilinear, Cubic, CubicSpline, Gauss, Lanczos, Mode, and NearestNeighbour.
433 #*
434 sub RIOResamplingTypes {
435  return @RIO_RESAMPLING_TYPES;
436 }
437 
438 #** @method list ResamplingTypes()
439 # Package subroutine.
440 # @return a list of GDAL resampling methods. These are currently:
441 # Average, Bilinear, Cubic, CubicSpline, Lanczos, Mode, and NearestNeighbour.
442 #*
443 sub ResamplingTypes {
444  return @RESAMPLING_TYPES;
445 }
446 
447 #** @method SetCacheMax($Bytes)
448 # Package subroutine.
449 # @param Bytes New maximum amount of memory for caching within GDAL.
450 #*
451 sub SetCacheMax {
452 }
453 
454 #** @method SetConfigOption($key, $value)
455 # Package subroutine.
456 # @param key A GDAL config option. Consult <a
457 # href="https://trac.osgeo.org/gdal/wiki/ConfigOptions">the GDAL
458 # documentation</a> for available options and their use.
459 # @param value A value for the option, typically 'YES', 'NO',
460 # undef, path, numeric value, or a filename.
461 #*
462 sub SetConfigOption {
463 }
464 
465 #** @method UseExceptions()
466 # Package subroutine.
467 # Use the Perl exception mechanism for GDAL messages (failures are
468 # confessed and warnings are warned) and collect the messages
469 # into \@Geo::GDAL::error. This is the default.
470 #*
471 sub UseExceptions {
472 }
473 
474 #** @method VSIFOpenExL()
475 #*
476 sub VSIFOpenExL {
477 }
478 
479 #** @method VSIGetLastErrorMsg()
480 #*
481 sub VSIGetLastErrorMsg {
482 }
483 
484 #** @method VSIGetLastErrorNo()
485 #*
486 sub VSIGetLastErrorNo {
487 }
488 
489 #** @method scalar VersionInfo($request = 'VERSION_NUM')
490 # Package subroutine.
491 # @param request A string specifying the request. Currently either
492 # "VERSION_NUM", "RELEASE_DATE", "RELEASE_NAME", or
493 # "--version". Default is "VERSION_NUM".
494 # @return Requested information.
495 #*
496 sub VersionInfo {
497 }
498 
499 #** @method scalar errstr()
500 # Package subroutine.
501 # Clear the error stack and return all generated GDAL error messages in one (possibly multiline) string.
502 # @return the chomped error stack joined with newlines.
503 #*
504 sub errstr {
505  my @stack = @error;
506  chomp(@stack);
507  @error = ();
508  return join("\n", @stack);
509 }
510 # usage: named_parameters(\@_, key value list of default parameters);
511 # returns parameters in a hash with low-case-without-_ keys
512 }
513 
514 #** @method i2s()
515 #*
516 sub i2s {
517  my ($class, $int) = @_;
518  return $I2S{$class}{$int} if exists $I2S{$class}{$int};
519  return $int;
520 }
521 
522 #** @method keep()
523 #*
524 sub keep {
525  my ($child, $parent) = @_;
526  $keeper{tied(%$child)} = $parent;
527  return $child;
528 }
529 # this is called from RELEASE_PARENT, so the child is already the tied one
530 }
531 
532 #** @method note()
533 #*
534 sub note {
535  my ($object, $note) = @_;
536  if (defined wantarray) {
537  return unless $note{$object};
538  return $notes{$object}{$note};
539  }
540  $notes{$object}{$note} = 1;
541 }
542 
543 #** @method parent()
544 #*
545 sub parent {
546  my ($child) = @_;
547  $child = tied(%$child) if $child->isa('HASH');
548  return $keeper{$child};
549 }
550 
551 #** @method s2i()
552 #*
553 sub s2i {
554  my ($class, $string, $backwards, $default) = @_;
555  $string = $default if defined $default && !defined $string;
556  return unless defined $string;
557  return $string if $backwards && exists $I2S{$class}{$string};
558  error(1, $string, $S2I{$class}) unless exists $S2I{$class}{$string};
559  $S2I{$class}{$string};
560 }
561 
562 #** @method s_exists()
563 #*
564 sub s_exists {
565  my ($class, $string) = @_;
566  return exists $S2I{$class}{$string};
567 }
568 
569 #** @method unkeep()
570 #*
571 sub unkeep {
572  my ($child) = @_;
573  delete $keeper{$child};
574 }
575 
576 #** @method unnote()
577 #*
578 sub unnote {
579  my ($object, $note) = @_;
580  if ($note) {
581  delete $notes{$object}{$note};
582  } else {
583  delete $notes{$object};
584  }
585 }
586 
587 #** @class Geo::GDAL::AsyncReader
588 # @brief Enable asynchronous requests.
589 # @details This class is not yet documented nor tested in the GDAL Perl wrappers
590 # @todo Test and document.
591 #*
592 package Geo::GDAL::AsyncReader;
593 
594 use base qw(Geo::GDAL)
595 
596 #** @method GetNextUpdatedRegion()
597 #*
598 sub GetNextUpdatedRegion {
599 }
600 
601 #** @method LockBuffer()
602 #*
603 sub LockBuffer {
604 }
605 
606 #** @method UnlockBuffer()
607 #*
608 sub UnlockBuffer {
609 }
610 
611 #** @class Geo::GDAL::Band
612 # @brief A raster band.
613 # @details
614 #*
615 package Geo::GDAL::Band;
616 
618 
619 #** @attr $XSize
620 # Object attribute.
621 # scalar (access as $band->{XSize})
622 #*
623 
624 #** @attr $YSize
625 # Object attribute.
626 # scalar (access as $band->{YSize})
627 #*
628 
629 #** @method Geo::GDAL::RasterAttributeTable AttributeTable($AttributeTable)
630 # Object method.
631 # @param AttributeTable [optional] A Geo::GDAL::RasterAttributeTable object.
632 # @return a new Geo::GDAL::RasterAttributeTable object, whose data is
633 # contained within the band.
634 #*
635 sub AttributeTable {
636  my $self = shift;
637  SetDefaultRAT($self, $_[0]) if @_ and defined $_[0];
638  return unless defined wantarray;
639  my $r = GetDefaultRAT($self);
640  keep($r, $self) if $r;
641 }
642 
643 #** @method list BlockSize()
644 # Object method.
645 # A.k.a GetBlockSize
646 # @return The size of a preferred i/o raster block size as a list
647 # (width, height).
648 #*
649 sub BlockSize {
650 }
651 
652 #** @method list CategoryNames(@names)
653 # Object method.
654 # @param names [optional]
655 # @return
656 #*
657 sub CategoryNames {
658  my $self = shift;
659  SetRasterCategoryNames($self, \@_) if @_;
660  return unless defined wantarray;
661  my $n = GetRasterCategoryNames($self);
662  return @$n;
663 }
664 
665 #** @method scalar Checksum($xoff = 0, $yoff = 0, $xsize = undef, $ysize = undef)
666 # Object method.
667 # Computes a checksum from the raster or a part of it.
668 # @param xoff
669 # @param yoff
670 # @param xsize
671 # @param ysize
672 # @return the checksum.
673 #*
674 sub Checksum {
675 }
676 
677 #** @method hashref ClassCounts($classifier, $progress = undef, $progress_data = undef)
678 # Object method.
679 # Compute the counts of cell values or number of cell values in ranges.
680 # @note Classifier is required only for float bands. Do not specify
681 # one for integer bands.
682 # @note NoData values are counted similar to other values.
683 #
684 # @param classifier Anonymous array of format [ $comparison,
685 # $classifier ], where $comparison is a string '<', '<=', '>', or '>='
686 # and $classifier is an anonymous array of format [ $value,
687 # $value|$classifier, $value|$classifier ], where $value is numeric
688 # value against which the reclassified value is compared to.
689 # @note Numeric value requires decimal point.
690 #
691 # In the example below, the real line is divided into ranges
692 # [-inf..3), [3..5), and [5..inf], i.e., three ranges with indexes 0,
693 # 1, and 2.
694 # \code
695 # $classifier = [ '<', [5.0, [3.0, 1.0, 2.0], 3.0] ];
696 # \endcode
697 # @return a reference to an anonymous hash, which contains the class
698 # values (indexes) as keys and the number of cells with that value or
699 # in that range as values. If the subroutine is user terminated an
700 # error is raised.
701 #*
702 sub ClassCounts {
703 }
704 
705 #** @method scalar ColorInterpretation($color_interpretation)
706 # Object method.
707 # @note a.k.a. GetRasterColorInterpretation and GetColorInterpretation
708 # (get only and returns an integer), SetRasterColorInterpretation and
709 # SetColorInterpretation (set only and requires an integer)
710 # @param color_interpretation [optional] new color interpretation, one
711 # of Geo::GDAL::Band::ColorInterpretations.
712 # @return The color interpretation of this band. One of Geo::GDAL::Band::ColorInterpretations.
713 #*
714 sub ColorInterpretation {
715  my($self, $ci) = @_;
716  if (defined $ci) {
717  $ci = s2i(color_interpretation => $ci);
718  SetRasterColorInterpretation($self, $ci);
719  }
720  return unless defined wantarray;
721  i2s(color_interpretation => GetRasterColorInterpretation($self));
722 }
723 
724 #** @method ColorInterpretations()
725 # Package subroutine.
726 # @return a list of types of color interpretation for raster
727 # bands. These are currently:
728 # AlphaBand, BlackBand, BlueBand, CyanBand, GrayIndex, GreenBand, HueBand, LightnessBand, MagentaBand, PaletteIndex, RedBand, SaturationBand, Undefined, YCbCr_CbBand, YCbCr_CrBand, YCbCr_YBand, and YellowBand.
729 #*
730 sub ColorInterpretations {
731  return @COLOR_INTERPRETATIONS;
732 }
733 
734 #** @method Geo::GDAL::ColorTable ColorTable($ColorTable)
735 # Object method.
736 # Get or set the color table of this band.
737 # @param ColorTable [optional] a Geo::GDAL::ColorTable object
738 # @return A new Geo::GDAL::ColorTable object which represents the
739 # internal color table associated with this band. Returns undef this
740 # band does not have an associated color table.
741 #*
742 sub ColorTable {
743  my $self = shift;
744  SetRasterColorTable($self, $_[0]) if @_ and defined $_[0];
745  return unless defined wantarray;
746  GetRasterColorTable($self);
747 }
748 
749 #** @method ComputeBandStats($samplestep = 1)
750 # Object method.
751 # @param samplestep the row increment in computing the statistics.
752 # @note Returns uncorrected sample standard deviation.
753 #
754 # See also Geo::GDAL::Band::ComputeStatistics.
755 # @return a list (mean, stddev).
756 #*
757 sub ComputeBandStats {
758 }
759 
760 #** @method ComputeRasterMinMax($approx_ok = 0)
761 # Object method.
762 # @return arrayref MinMax = [min, max]
763 #*
764 sub ComputeRasterMinMax {
765 }
766 
767 #** @method list ComputeStatistics($approx_ok, $progress = undef, $progress_data = undef)
768 # Object method.
769 # @param approx_ok Whether it is allowed to compute the statistics
770 # based on overviews or similar.
771 # @note Returns uncorrected sample standard deviation.
772 #
773 # See also Geo::GDAL::Band::ComputeBandStats.
774 # @return a list ($min, $max, $mean, $stddev).
775 #*
776 sub ComputeStatistics {
777 }
778 
779 #** @method Geo::OGR::Layer Contours($DataSource, hashref LayerConstructor, $ContourInterval, $ContourBase, arrayref FixedLevels, $NoDataValue, $IDField, $ElevField, coderef Progress, $ProgressData)
780 # Object method.
781 # Generate contours for this raster band. This method can also be used with named parameters.
782 # @note This method is a wrapper for ContourGenerate.
783 #
784 # An example:
785 # \code
786 # use Geo::GDAL;
787 # $dem = Geo::GDAL::Open('dem.gtiff');
788 # $contours = $dem->Band->Contours(ContourInterval => 10, ElevField => 'z');
789 # $n = $contours->GetFeatureCount;
790 # \endcode
791 #
792 # @param DataSource a Geo::OGR::DataSource object, default is a Memory data source
793 # @param LayerConstructor data for Geo::OGR::DataSource::CreateLayer, default is {Name => 'contours'}
794 # @param ContourInterval default is 100
795 # @param ContourBase default is 0
796 # @param FixedLevels a reference to a list of fixed contour levels, default is []
797 # @param NoDataValue default is undef
798 # @param IDField default is '', i.e., no field (the field is created if this is given)
799 # @param ElevField default is '', i.e., no field (the field is created if this is given)
800 # @param progress [optional] a reference to a subroutine, which will
801 # be called with parameters (number progress, string msg, progress_data)
802 # @param progress_data [optional]
803 # @return
804 #*
805 sub Contours {
806  my $self = shift;
807  my $p = named_parameters(\@_,
808  DataSource => undef,
809  LayerConstructor => {Name => 'contours'},
810  ContourInterval => 100,
811  ContourBase => 0,
812  FixedLevels => [],
813  NoDataValue => undef,
814  IDField => -1,
815  ElevField => -1,
816  Progress => undef,
817  ProgressData => undef);
818  $p->{datasource} //= Geo::OGR::GetDriver('Memory')->CreateDataSource('ds');
819  $p->{layerconstructor}->{Schema} //= {};
820  $p->{layerconstructor}->{Schema}{Fields} //= [];
821  my %fields;
822  unless ($p->{idfield} =~ /^[+-]?\d+$/ or $fields{$p->{idfield}}) {
823  push @{$p->{layerconstructor}->{Schema}{Fields}}, {Name => $p->{idfield}, Type => 'Integer'};
824  }
825  unless ($p->{elevfield} =~ /^[+-]?\d+$/ or $fields{$p->{elevfield}}) {
826  my $type = $self->DataType() =~ /Float/ ? 'Real' : 'Integer';
827  push @{$p->{layerconstructor}->{Schema}{Fields}}, {Name => $p->{elevfield}, Type => $type};
828  }
829  my $layer = $p->{datasource}->CreateLayer($p->{layerconstructor});
830  my $schema = $layer->GetLayerDefn;
831  for ('idfield', 'elevfield') {
832  $p->{$_} = $schema->GetFieldIndex($p->{$_}) unless $p->{$_} =~ /^[+-]?\d+$/;
833  }
834  $p->{progressdata} = 1 if $p->{progress} and not defined $p->{progressdata};
835  ContourGenerate($self, $p->{contourinterval}, $p->{contourbase}, $p->{fixedlevels},
836  $p->{nodatavalue}, $layer, $p->{idfield}, $p->{elevfield},
837  $p->{progress}, $p->{progressdata});
838  return $layer;
839 }
840 
841 #** @method CreateMaskBand(@flags)
842 # Object method.
843 # @note May invalidate any previous mask band obtained with Geo::GDAL::Band::GetMaskBand.
844 #
845 # @param flags one or more mask flags. The flags are Geo::GDAL::Band::MaskFlags.
846 #*
847 sub CreateMaskBand {
848  my $self = shift;
849  my $f = 0;
850  if (@_ and $_[0] =~ /^\d$/) {
851  $f = shift;
852  } else {
853  for my $flag (@_) {
854  carp "Unknown mask flag: '$flag'." unless $MASK_FLAGS{$flag};
855  $f |= $MASK_FLAGS{$flag};
856  }
857  }
858  $self->_CreateMaskBand($f);
859 }
860 
861 #** @method scalar DataType()
862 # Object method.
863 # @return The data type of this band. One of Geo::GDAL::DataTypes.
864 #*
865 sub DataType {
866  my $self = shift;
867  return i2s(data_type => $self->{DataType});
868 }
869 
870 #** @method Geo::GDAL::Dataset Dataset()
871 # Object method.
872 # @return The dataset which this band belongs to.
873 #*
874 sub Dataset {
875  my $self = shift;
876  parent($self);
877 }
878 
879 #** @method scalar DeleteNoDataValue()
880 # Object method.
881 #*
882 sub DeleteNoDataValue {
883 }
884 
885 #** @method Geo::GDAL::Band Distance(%params)
886 # Object method.
887 # Compute distances to specific cells of this raster.
888 # @param params Named parameters:
889 # - \a Distance A raster band, into which the distances are computed. If not given, a not given, a new in-memory raster band is created and returned. The data type of the raster can be given in the options.
890 # - \a Options Hash of options. Options are:
891 # - \a Values A list of cell values in this band to measure the distance from. If this option is not provided, the distance will be computed to non-zero pixel values. Currently pixel values are internally processed as integers.
892 # - \a DistUnits=PIXEL|GEO Indicates whether distances will be computed in cells or in georeferenced units. The default is pixel units. This also determines the interpretation of MaxDist.
893 # - \a MaxDist=n The maximum distance to search. Distances greater than this value will not be computed. Instead output cells will be set to a NoData value.
894 # - \a NoData=n The NoData value to use on the distance band for cells that are beyond MaxDist. If not provided, the distance band will be queried for a NoData value. If one is not found, 65535 will be used (255 if the type is Byte).
895 # - \a Use_Input_NoData=YES|NO If this option is set, the NoData value of this band will be respected. Leaving NoData cells in the input as NoData pixels in the distance raster.
896 # - \a Fixed_Buf_Val=n If this option is set, all cells within the MaxDist threshold are set to this value instead of the distance value.
897 # - \a DataType The data type for the result if it is not given.
898 # - \a Progress Progress function.
899 # - \a ProgressData Additional parameter for the progress function.
900 #
901 # @note This GDAL function behind this API is called GDALComputeProximity.
902 #
903 # @return The distance raster.
904 #*
905 sub Distance {
906  my $self = shift;
907  my $p = named_parameters(\@_, Distance => undef, Options => undef, Progress => undef, ProgressData => undef);
908  for my $key (keys %{$p->{options}}) {
909  $p->{options}{uc($key)} = $p->{options}{$key};
910  }
911  $p->{options}{TYPE} //= $p->{options}{DATATYPE} //= 'Float32';
912  unless ($p->{distance}) {
913  my ($w, $h) = $self->Size;
914  $p->{distance} = Geo::GDAL::Driver('MEM')->Create(Name => 'distance', Width => $w, Height => $h, Type => $p->{options}{TYPE})->Band;
915  }
916  Geo::GDAL::ComputeProximity($self, $p->{distance}, $p->{options}, $p->{progress}, $p->{progressdata});
917  return $p->{distance};
918 }
919 
920 #** @method Domains()
921 #*
922 sub Domains {
923  return @DOMAINS;
924 }
925 
926 #** @method Fill($real_part, $imag_part = 0.0)
927 # Object method.
928 # Fill the band with a constant value.
929 # @param real_part Real component of fill value.
930 # @param imag_part Imaginary component of fill value.
931 #
932 #*
933 sub Fill {
934 }
935 
936 #** @method FillNoData($mask, $max_search_dist, $smoothing_iterations, $options, coderef progress, $progress_data)
937 # Object method.
938 # Interpolate values for cells in this raster. The cells to fill
939 # should be marked in the mask band with zero.
940 #
941 # @param mask [optional] a mask band indicating cells to be interpolated (zero valued) (default is to get it with Geo::GDAL::Band::GetMaskBand).
942 # @param max_search_dist [optional] the maximum number of cells to
943 # search in all directions to find values to interpolate from (default is 10).
944 # @param smoothing_iterations [optional] the number of 3x3 smoothing filter passes to run (0 or more) (default is 0).
945 # @param options [optional] A reference to a hash. No options have been defined so far for this algorithm (default is {}).
946 # @param progress [optional] a reference to a subroutine, which will
947 # be called with parameters (number progress, string msg, progress_data) (default is undef).
948 # @param progress_data [optional] (default is undef).
949 #
950 # <a href="http://www.gdal.org/gdal__alg_8h.html">Documentation for GDAL algorithms</a>
951 #*
952 sub FillNoData {
953 }
954 
955 #** @method FlushCache()
956 # Object method.
957 # Write cached data to disk. There is usually no need to call this
958 # method.
959 #*
960 sub FlushCache {
961 }
962 
963 #** @method scalar GetBandNumber()
964 # Object method.
965 # @return The index of this band in the parent dataset list of bands.
966 #*
967 sub GetBandNumber {
968 }
969 
970 #** @method GetBlockSize()
971 #*
972 sub GetBlockSize {
973 }
974 
975 #** @method list GetDefaultHistogram($force = 1, coderef progress = undef, $progress_data = undef)
976 # Object method.
977 # @param force true to force the computation
978 # @param progress [optional] a reference to a subroutine, which will
979 # be called with parameters (number progress, string msg, progress_data)
980 # @param progress_data [optional]
981 # @note See Note in Geo::GDAL::Band::GetHistogram.
982 # @return a list: ($min, $max, arrayref histogram).
983 #*
984 sub GetDefaultHistogram {
985 }
986 
987 #** @method list GetHistogram(%parameters)
988 # Object method.
989 # Compute histogram from the raster.
990 # @param parameters Named parameters:
991 # - \a Min the lower bound, default is -0.5
992 # - \a Max the upper bound, default is 255.5
993 # - \a Buckets the number of buckets in the histogram, default is 256
994 # - \a IncludeOutOfRange whether to use the first and last values in the returned list
995 # for out of range values, default is false;
996 # the bucket size is (Max-Min) / Buckets if this is false and
997 # (Max-Min) / (Buckets-2) if this is true
998 # - \a ApproxOK if histogram can be computed from overviews, default is false
999 # - \a Progress an optional progress function, the default is undef
1000 # - \a ProgressData data for the progress function, the default is undef
1001 # @note Histogram counts are treated as strings in the bindings to be
1002 # able to use large integers (if GUIntBig is larger than Perl IV). In
1003 # practice this is only important if you have a 32 bit machine and
1004 # very large bucket counts. In those cases it may also be necessary to
1005 # use Math::BigInt.
1006 # @return a list which contains the count of values in each bucket
1007 #*
1008 sub GetHistogram {
1009  my $self = shift;
1010  my $p = named_parameters(\@_,
1011  Min => -0.5,
1012  Max => 255.5,
1013  Buckets => 256,
1014  IncludeOutOfRange => 0,
1015  ApproxOK => 0,
1016  Progress => undef,
1017  ProgressData => undef);
1018  $p->{progressdata} = 1 if $p->{progress} and not defined $p->{progressdata};
1019  _GetHistogram($self, $p->{min}, $p->{max}, $p->{buckets},
1020  $p->{includeoutofrange}, $p->{approxok},
1021  $p->{progress}, $p->{progressdata});
1022 }
1023 
1024 #** @method Geo::GDAL::Band GetMaskBand()
1025 # Object method.
1026 # @return the mask band associated with this
1027 # band.
1028 #*
1029 sub GetMaskBand {
1030  my $self = shift;
1031  my $band = _GetMaskBand($self);
1032  keep($band, $self);
1033 }
1034 
1035 #** @method list GetMaskFlags()
1036 # Object method.
1037 # @return the mask flags of the mask band associated with this
1038 # band. The flags are one or more of Geo::GDAL::Band::MaskFlags.
1039 #*
1040 sub GetMaskFlags {
1041  my $self = shift;
1042  my $f = $self->_GetMaskFlags;
1043  my @f;
1044  for my $flag (keys %MASK_FLAGS) {
1045  push @f, $flag if $f & $MASK_FLAGS{$flag};
1046  }
1047  return wantarray ? @f : $f;
1048 }
1049 
1050 #** @method scalar GetMaximum()
1051 # Object method.
1052 # @note Call Geo::GDAL::Band::ComputeStatistics before calling
1053 # GetMaximum to make sure the value is computed.
1054 #
1055 # @return statistical minimum of the band or undef if statistics are
1056 # not kept or computed in scalar context. In list context returns the
1057 # maximum value or a (kind of) maximum value supported by the data
1058 # type and a boolean value, which indicates which is the case (true is
1059 # first, false is second).
1060 #*
1061 sub GetMaximum {
1062 }
1063 
1064 #** @method scalar GetMinimum()
1065 # Object method.
1066 # @note Call Geo::GDAL::Band::ComputeStatistics before calling
1067 # GetMinimum to make sure the value is computed.
1068 #
1069 # @return statistical minimum of the band or undef if statistics are
1070 # not kept or computed in scalar context. In list context returns the
1071 # minimum value or a (kind of) minimum value supported by the data
1072 # type and a boolean value, which indicates which is the case (true is
1073 # first, false is second).
1074 #*
1075 sub GetMinimum {
1076 }
1077 
1078 #** @method Geo::GDAL::Band GetOverview($index)
1079 # Object method.
1080 # @param index 0..GetOverviewCount-1
1081 # @return a Geo::GDAL::Band object, which represents the internal
1082 # overview band, or undef. if the index is out of bounds.
1083 #*
1084 sub GetOverview {
1085  my ($self, $index) = @_;
1086  my $band = _GetOverview($self, $index);
1087  keep($band, $self);
1088 }
1089 
1090 #** @method scalar GetOverviewCount()
1091 # Object method.
1092 # @return the number of overviews available of the band.
1093 #*
1094 sub GetOverviewCount {
1095 }
1096 
1097 #** @method list GetStatistics($approx_ok, $force)
1098 # Object method.
1099 # @param approx_ok Whether it is allowed to compute the statistics
1100 # based on overviews or similar.
1101 # @param force Whether to force scanning of the whole raster.
1102 # @note Uses Geo::GDAL::Band::ComputeStatistics internally.
1103 #
1104 # @return a list ($min, $max, $mean, $stddev).
1105 #*
1106 sub GetStatistics {
1107 }
1108 
1109 #** @method HasArbitraryOverviews()
1110 # Object method.
1111 # @return true or false.
1112 #*
1113 sub HasArbitraryOverviews {
1114 }
1115 
1116 #** @method list MaskFlags()
1117 # Package subroutine.
1118 # @return the list of mask flags. These are
1119 # - \a AllValid: There are no invalid cell, all mask values will be 255.
1120 # When used this will normally be the only flag set.
1121 # - \a PerDataset: The mask band is shared between all bands on the dataset.
1122 # - \a Alpha: The mask band is actually an alpha band and may have values
1123 # other than 0 and 255.
1124 # - \a NoData: Indicates the mask is actually being generated from NoData values.
1125 # (mutually exclusive of Alpha).
1126 #*
1127 sub MaskFlags {
1128  my @f = sort {$MASK_FLAGS{$a} <=> $MASK_FLAGS{$b}} keys %MASK_FLAGS;
1129  return @f;
1130 }
1131 
1132 #** @method scalar NoDataValue($NoDataValue)
1133 # Object method.
1134 # Get or set the "no data" value.
1135 # @param NoDataValue [optional]
1136 # @note $band->NoDataValue(undef) sets the NoData value to the
1137 # Posix floating point maximum. Use Geo::GDAL::Band::DeleteNoDataValue
1138 # to stop this band using a NoData value.
1139 # @return The NoData value or undef in scalar context. An undef
1140 # value indicates that there is no NoData value associated with this
1141 # band.
1142 #*
1143 sub NoDataValue {
1144  my $self = shift;
1145  if (@_ > 0) {
1146  if (defined $_[0]) {
1147  SetNoDataValue($self, $_[0]);
1148  } else {
1149  SetNoDataValue($self, POSIX::FLT_MAX); # hopefully an "out of range" value
1150  }
1151  }
1152  GetNoDataValue($self);
1153 }
1154 
1155 #** @method scalar PackCharacter()
1156 # Object method.
1157 # @return The character to use in Perl pack and unpack for the data of this band.
1158 #*
1159 sub PackCharacter {
1160  my $self = shift;
1161  return Geo::GDAL::PackCharacter($self->DataType);
1162 }
1163 
1164 #** @method Piddle($piddle, $xoff = 0, $yoff = 0, $xsize = <width>, $ysize = <height>, $xdim, $ydim)
1165 # Object method.
1166 # Read or write band data from/into a piddle.
1167 #
1168 # \note The PDL module must be available for this method to work. Also, you
1169 # should 'use PDL' in the code that you use this method.
1170 #
1171 # @param piddle [only when writing] The piddle from which to read the data to be written into the band.
1172 # @param xoff, yoff The offset for data in the band, default is top left (0, 0).
1173 # @param xsize, ysize [optional] The size of the window in the band.
1174 # @param xdim, ydim [optional, only when reading from a band] The size of the piddle to create.
1175 # @return A new piddle when reading from a band (no not use when writing into a band).
1176 #*
1177 sub Piddle {
1178  # TODO: add Piddle sub to dataset too to make Width x Height x Bands piddles
1179  error("PDL is not available.") unless $Geo::GDAL::HAVE_PDL;
1180  my $self = shift;
1181  my $t = $self->{DataType};
1182  unless (defined wantarray) {
1183  my $pdl = shift;
1184  error("The datatype of the Piddle and the band do not match.")
1185  unless $PDL2DATATYPE{$pdl->get_datatype} == $t;
1186  my ($xoff, $yoff, $xsize, $ysize) = @_;
1187  $xoff //= 0;
1188  $yoff //= 0;
1189  my $data = $pdl->get_dataref();
1190  my ($xdim, $ydim) = $pdl->dims();
1191  if ($xdim > $self->{XSize} - $xoff) {
1192  warn "Piddle XSize too large ($xdim) for this raster band (width = $self->{XSize}, offset = $xoff).";
1193  $xdim = $self->{XSize} - $xoff;
1194  }
1195  if ($ydim > $self->{YSize} - $yoff) {
1196  $ydim = $self->{YSize} - $yoff;
1197  warn "Piddle YSize too large ($ydim) for this raster band (height = $self->{YSize}, offset = $yoff).";
1198  }
1199  $xsize //= $xdim;
1200  $ysize //= $ydim;
1201  $self->_WriteRaster($xoff, $yoff, $xsize, $ysize, $data, $xdim, $ydim, $t, 0, 0);
1202  return;
1203  }
1204  my ($xoff, $yoff, $xsize, $ysize, $xdim, $ydim, $alg) = @_;
1205  $xoff //= 0;
1206  $yoff //= 0;
1207  $xsize //= $self->{XSize} - $xoff;
1208  $ysize //= $self->{YSize} - $yoff;
1209  $xdim //= $xsize;
1210  $ydim //= $ysize;
1211  $alg //= 'NearestNeighbour';
1212  $alg = s2i(rio_resampling => $alg);
1213  my $buf = $self->_ReadRaster($xoff, $yoff, $xsize, $ysize, $xdim, $ydim, $t, 0, 0, $alg);
1214  my $pdl = PDL->new;
1215  my $datatype = $DATATYPE2PDL{$t};
1216  error("The band datatype is not supported by PDL.") if $datatype < 0;
1217  $pdl->set_datatype($datatype);
1218  $pdl->setdims([$xdim, $ydim]);
1219  my $data = $pdl->get_dataref();
1220  $$data = $buf;
1221  $pdl->upd_data;
1222  # FIXME: we want approximate equality since no data value can be very large floating point value
1223  my $bad = GetNoDataValue($self);
1224  return $pdl->setbadif($pdl == $bad) if defined $bad;
1225  return $pdl;
1226 }
1227 
1228 #** @method Geo::OGR::Layer Polygonize(%params)
1229 # Object method.
1230 # Polygonize this raster band.
1231 #
1232 # @param params Named parameters:
1233 # - \a Mask A raster band, which is used as a mask to select polygonized areas. Default is undef.
1234 # - \a OutLayer A vector layer into which the polygons are written. If not given, an in-memory layer 'polygonized' is created and returned.
1235 # - \a PixValField The name of the field in the output layer into which the cell value of the polygon area is stored. Default is 'val'.
1236 # - \a Options Hash or list of options. Connectedness can be set to 8
1237 # to use 8-connectedness, otherwise 4-connectedness is
1238 # used. ForceIntPixel can be set to 1 to force using a 32 bit int buffer
1239 # for cell values in the process. If this is not set and the data type
1240 # of this raster does not fit into a 32 bit int buffer, a 32 bit float
1241 # buffer is used.
1242 # - \a Progress Progress function.
1243 # - \a ProgressData Additional parameter for the progress function.
1244 #
1245 # @return Output vector layer.
1246 #*
1247 sub Polygonize {
1248  my $self = shift;
1249  my $p = named_parameters(\@_, Mask => undef, OutLayer => undef, PixValField => 'val', Options => undef, Progress => undef, ProgressData => undef);
1250  my %known_options = (Connectedness => 1, ForceIntPixel => 1, DATASET_FOR_GEOREF => 1, '8CONNECTED' => 1);
1251  for my $option (keys %{$p->{options}}) {
1252  error(1, $option, \%known_options) unless exists $known_options{$option};
1253  }
1254  my $dt = $self->DataType;
1255  my %leInt32 = (Byte => 1, Int16 => 1, Int32 => 1, UInt16 => 1);
1256  my $leInt32 = $leInt32{$dt};
1257  $dt = $dt =~ /Float/ ? 'Real' : 'Integer';
1258  $p->{outlayer} //= Geo::OGR::Driver('Memory')->Create()->
1259  CreateLayer(Name => 'polygonized',
1260  Fields => [{Name => 'val', Type => $dt},
1261  {Name => 'geom', Type => 'Polygon'}]);
1262  $p->{pixvalfield} = $p->{outlayer}->GetLayerDefn->GetFieldIndex($p->{pixvalfield});
1263  $p->{options}{'8CONNECTED'} = 1 if $p->{options}{Connectedness} && $p->{options}{Connectedness} == 8;
1264  if ($leInt32 || $p->{options}{ForceIntPixel}) {
1265  Geo::GDAL::_Polygonize($self, $p->{mask}, $p->{outlayer}, $p->{pixvalfield}, $p->{options}, $p->{progress}, $p->{progressdata});
1266  } else {
1267  Geo::GDAL::FPolygonize($self, $p->{mask}, $p->{outlayer}, $p->{pixvalfield}, $p->{options}, $p->{progress}, $p->{progressdata});
1268  }
1269  set the srs of the outlayer if it was created here
1270  return $p->{outlayer};
1271 }
1272 
1273 #** @method RELEASE_PARENT()
1274 #*
1275 sub RELEASE_PARENT {
1276  my $self = shift;
1277  unkeep($self);
1278 }
1279 
1280 #** @method RasterAttributeTable()
1281 #*
1282 sub RasterAttributeTable {
1283 }
1284 
1285 #** @method scalar ReadRaster(%params)
1286 # Object method.
1287 # Read data from the band.
1288 #
1289 # @param params Named parameters:
1290 # - \a XOff x offset (cell coordinates) (default is 0)
1291 # - \a YOff y offset (cell coordinates) (default is 0)
1292 # - \a XSize width of the area to read (default is the width of the band)
1293 # - \a YSize height of the area to read (default is the height of the band)
1294 # - \a BufXSize (default is undef, i.e., the same as XSize)
1295 # - \a BufYSize (default is undef, i.e., the same as YSize)
1296 # - \a BufType data type of the buffer (default is the data type of the band)
1297 # - \a BufPixelSpace (default is 0)
1298 # - \a BufLineSpace (default is 0)
1299 # - \a ResampleAlg one of Geo::GDAL::RIOResamplingTypes (default is 'NearestNeighbour'),
1300 # - \a Progress reference to a progress function (default is undef)
1301 # - \a ProgressData (default is undef)
1302 #
1303 # <a href="http://www.gdal.org/classGDALDataset.html">Entry in GDAL docs (method RasterIO)</a>
1304 # @return a buffer, open the buffer with \a unpack function of Perl. See Geo::GDAL::Band::PackCharacter.
1305 #*
1306 sub ReadRaster {
1307  my $self = shift;
1308  my ($width, $height) = $self->Size;
1309  my ($type) = $self->DataType;
1310  my $p = named_parameters(\@_,
1311  XOff => 0,
1312  YOff => 0,
1313  XSize => $width,
1314  YSize => $height,
1315  BufXSize => undef,
1316  BufYSize => undef,
1317  BufType => $type,
1318  BufPixelSpace => 0,
1319  BufLineSpace => 0,
1320  ResampleAlg => 'NearestNeighbour',
1321  Progress => undef,
1322  ProgressData => undef
1323  );
1324  $p->{resamplealg} = s2i(rio_resampling => $p->{resamplealg});
1325  $p->{buftype} = s2i(data_type => $p->{buftype}, 1);
1326  $self->_ReadRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bufpixelspace},$p->{buflinespace},$p->{resamplealg},$p->{progress},$p->{progressdata});
1327 }
1328 
1329 #** @method array reference ReadTile($xoff = 0, $yoff = 0, $xsize = <width>, $ysize = <height>)
1330 # Object method.
1331 # Read band data into a Perl array.
1332 #
1333 # \note Accessing band data in this way is slow. Consider using PDL and Geo::GDAL::Band::Piddle.
1334 #
1335 # Usage example (print the data from a band):
1336 # \code
1337 # print "@$_\n" for ( @{ $band->ReadTile() } );
1338 # \endcode
1339 # Another usage example (process the data of a large dataset that has one band):
1340 # \code
1341 # my($W,$H) = $dataset->Band()->Size();
1342 # my($xoff,$yoff,$w,$h) = (0,0,200,200);
1343 # while (1) {
1344 # if ($xoff >= $W) {
1345 # $xoff = 0;
1346 # $yoff += $h;
1347 # last if $yoff >= $H;
1348 # }
1349 # my $data = $dataset->Band(1)->ReadTile($xoff,$yoff,min($W-$xoff,$w),min($H-$yoff,$h));
1350 # # add your data processing code here
1351 # $dataset->Band(1)->WriteTile($data,$xoff,$yoff);
1352 # $xoff += $w;
1353 # }
1354 #
1355 # sub min {
1356 # return $_[0] < $_[1] ? $_[0] : $_[1];
1357 # }
1358 # \endcode
1359 # @param xoff Number of cell to skip before starting to read from a row. Pixels are read from left to right.
1360 # @param yoff Number of cells to skip before starting to read from a column. Pixels are read from top to bottom.
1361 # @param xsize Number of cells to read from each row.
1362 # @param ysize Number of cells to read from each column.
1363 # @return a two-dimensional Perl array, organizes as data->[y][x], y =
1364 # 0..height-1, x = 0..width-1. I.e., y is row and x is column.
1365 #*
1366 sub ReadTile {
1367  my($self, $xoff, $yoff, $xsize, $ysize, $w_tile, $h_tile, $alg) = @_;
1368  $xoff //= 0;
1369  $yoff //= 0;
1370  $xsize //= $self->{XSize} - $xoff;
1371  $ysize //= $self->{YSize} - $yoff;
1372  $w_tile //= $xsize;
1373  $h_tile //= $ysize;
1374  $alg //= 'NearestNeighbour';
1375  $alg = s2i(rio_resampling => $alg);
1376  my $t = $self->{DataType};
1377  my $buf = $self->_ReadRaster($xoff, $yoff, $xsize, $ysize, $w_tile, $h_tile, $t, 0, 0, $alg);
1378  my $pc = Geo::GDAL::PackCharacter($t);
1379  my $w = $w_tile * Geo::GDAL::GetDataTypeSize($t)/8;
1380  my $offset = 0;
1381  my @data;
1382  for my $y (0..$h_tile-1) {
1383  my @d = unpack($pc."[$w_tile]", substr($buf, $offset, $w));
1384  push @data, \@d;
1385  $offset += $w;
1386  }
1387  return \@data;
1388 }
1389 
1390 #** @method Reclassify($classifier, $progress = undef, $progress_data = undef)
1391 # Object method.
1392 # Reclassify the cells in the band.
1393 # @note This method is defined only for integer bands.
1394 # @note NoData values are reclassified if explicitly specified in the
1395 # map. However, they are not reclassified to the default value, if one
1396 # is specified.
1397 # @note If the subroutine is user terminated or the classifier is
1398 # incorrect, already reclassified cells will stay reclassified but an
1399 # error is raised.
1400 # @param classifier For integer rasters an anonymous hash, which
1401 # contains old class values as keys and new class values as values. A
1402 # special key '*' (star) can be used as default, to act as a fallback
1403 # new class value. For float rasters as in Geo::GDAL::Band::ClassCounts.
1404 #*
1405 sub Reclassify {
1406 }
1407 
1408 #** @method RegenerateOverview(Geo::GDAL::Band overview, $resampling, coderef progress, $progress_data)
1409 # Object method.
1410 # @param overview a Geo::GDAL::Band object for the overview.
1411 # @param resampling [optional] the resampling method (one of Geo::GDAL::RIOResamplingTypes) (default is Average).
1412 # @param progress [optional] a reference to a subroutine, which will
1413 # be called with parameters (number progress, string msg, progress_data)
1414 # @param progress_data [optional]
1415 #*
1416 sub RegenerateOverview {
1417  my $self = shift;
1418  #Geo::GDAL::Band overview, scalar resampling, subref callback, scalar callback_data
1419  my @p = @_;
1420  Geo::GDAL::RegenerateOverview($self, @p);
1421 }
1422 
1423 #** @method RegenerateOverviews(arrayref overviews, $resampling, coderef progress, $progress_data)
1424 # Object method.
1425 # @todo This is not yet available
1426 #
1427 # @param overviews a list of Geo::GDAL::Band objects for the overviews.
1428 # @param resampling [optional] the resampling method (one of Geo::GDAL::RIOResamplingTypes) (default is Average).
1429 # @param progress [optional] a reference to a subroutine, which will
1430 # be called with parameters (number progress, string msg, progress_data)
1431 # @param progress_data [optional]
1432 #*
1433 sub RegenerateOverviews {
1434  my $self = shift;
1435  #arrayref overviews, scalar resampling, subref callback, scalar callback_data
1436  my @p = @_;
1437  Geo::GDAL::RegenerateOverviews($self, @p);
1438 }
1439 
1440 #** @method ScaleAndOffset($scale, $offset)
1441 # Object method.
1442 # Scale and offset are used to transform raw cell values into the
1443 # units returned by GetUnits(). The conversion function is:
1444 # \code
1445 # Units value = (raw value * scale) + offset
1446 # \endcode
1447 # @return a list ($scale, $offset), the values are undefined if they
1448 # are not set.
1449 # @since version 1.9 of the bindings.
1450 #*
1451 sub ScaleAndOffset {
1452  my $self = shift;
1453  SetScale($self, $_[0]) if @_ > 0 and defined $_[0];
1454  SetOffset($self, $_[1]) if @_ > 1 and defined $_[1];
1455  return unless defined wantarray;
1456  my $scale = GetScale($self);
1457  my $offset = GetOffset($self);
1458  return ($scale, $offset);
1459 }
1460 
1461 #** @method list SetDefaultHistogram($min, $max, $histogram)
1462 # Object method.
1463 # @param min
1464 # @param max
1465 # @note See Note in Geo::GDAL::Band::GetHistogram.
1466 # @param histogram reference to an array containing the histogram
1467 #*
1468 sub SetDefaultHistogram {
1469 }
1470 
1471 #** @method SetStatistics($min, $max, $mean, $stddev)
1472 # Object method.
1473 # Save the statistics of the band if possible (the format can save
1474 # arbitrary metadata).
1475 # @param min
1476 # @param max
1477 # @param mean
1478 # @param stddev
1479 #*
1480 sub SetStatistics {
1481 }
1482 
1483 #** @method Geo::GDAL::Band Sieve(%params)
1484 # Object method.
1485 # Remove small areas by merging them into the largest neighbour area.
1486 # @param params Named parameters:
1487 # - \a Mask A raster band, which is used as a mask to select sieved areas. Default is undef.
1488 # - \a Dest A raster band into which the result is written. If not given, an new in-memory raster band is created and returned.
1489 # - \a Threshold The smallest area size (in number of cells) which are not sieved away.
1490 # - \a Options Hash or list of options. {Connectedness => 4} can be specified to use 4-connectedness, otherwise 8-connectedness is used.
1491 # - \a Progress Progress function.
1492 # - \a ProgressData Additional parameter for the progress function.
1493 #
1494 # @return The filtered raster band.
1495 #*
1496 sub Sieve {
1497  my $self = shift;
1498  my $p = named_parameters(\@_, Mask => undef, Dest => undef, Threshold => 10, Options => undef, Progress => undef, ProgressData => undef);
1499  unless ($p->{dest}) {
1500  my ($w, $h) = $self->Size;
1501  $p->{dest} = Geo::GDAL::Driver('MEM')->Create(Name => 'sieved', Width => $w, Height => $h, Type => $self->DataType)->Band;
1502  }
1503  my $c = 8;
1504  if ($p->{options}{Connectedness}) {
1505  $c = $p->{options}{Connectedness};
1506  delete $p->{options}{Connectedness};
1507  }
1508  Geo::GDAL::SieveFilter($self, $p->{mask}, $p->{dest}, $p->{threshold}, $c, $p->{options}, $p->{progress}, $p->{progressdata});
1509  return $p->{dest};
1510 }
1511 
1512 #** @method list Size()
1513 # Object method.
1514 # @return The size of the band as a list (width, height).
1515 #*
1516 sub Size {
1517  my $self = shift;
1518  return ($self->{XSize}, $self->{YSize});
1519 }
1520 
1521 #** @method Unit($type)
1522 # Object method.
1523 # @param type [optional] the unit (a string).
1524 # @note $band->Unit(undef) sets the unit value to an empty string.
1525 # @return the unit (a string).
1526 # @since version 1.9 of the bindings.
1527 #*
1528 sub Unit {
1529  my $self = shift;
1530  if (@_ > 0) {
1531  my $unit = shift;
1532  $unit //= '';
1533  SetUnitType($self, $unit);
1534  }
1535  return unless defined wantarray;
1536  GetUnitType($self);
1537 }
1538 
1539 #** @method WriteRaster(%params)
1540 # Object method.
1541 # Write data into the band.
1542 #
1543 # @param params Named parameters:
1544 # - \a XOff x offset (cell coordinates) (default is 0)
1545 # - \a YOff y offset (cell coordinates) (default is 0)
1546 # - \a XSize width of the area to write (default is the width of the band)
1547 # - \a YSize height of the area to write (default is the height of the band)
1548 # - \a Buf a buffer (or a reference to a buffer) containing the data. Create the buffer with \a pack function of Perl. See Geo::GDAL::Band::PackCharacter.
1549 # - \a BufXSize (default is undef, i.e., the same as XSize)
1550 # - \a BufYSize (default is undef, i.e., the same as YSize)
1551 # - \a BufType data type of the buffer (default is the data type of the band)
1552 # - \a BufPixelSpace (default is 0)
1553 # - \a BufLineSpace (default is 0)
1554 #
1555 # <a href="http://www.gdal.org/classGDALDataset.html">Entry in GDAL docs (method RasterIO)</a>
1556 #*
1557 sub WriteRaster {
1558  my $self = shift;
1559  my ($width, $height) = $self->Size;
1560  my ($type) = $self->DataType;
1561  my $p = named_parameters(\@_,
1562  XOff => 0,
1563  YOff => 0,
1564  XSize => $width,
1565  YSize => $height,
1566  Buf => undef,
1567  BufXSize => undef,
1568  BufYSize => undef,
1569  BufType => $type,
1570  BufPixelSpace => 0,
1571  BufLineSpace => 0
1572  );
1573  confess "Usage: \$band->WriteRaster( Buf => \$data, ... )" unless defined $p->{buf};
1574  $p->{buftype} = s2i(data_type => $p->{buftype}, 1);
1575  $self->_WriteRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{buf},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bufpixelspace},$p->{buflinespace});
1576 }
1577 
1578 #** @method WriteTile($data, $xoff = 0, $yoff = 0)
1579 # Object method.
1580 # Write band data from a Perl array.
1581 #
1582 # \note Accessing band data in this way is slow. Consider using PDL and Geo::GDAL::Band::Piddle.
1583 #
1584 # @param data A two-dimensional Perl array, organizes as data->[y][x], y =
1585 # 0..height-1, x = 0..width-1.
1586 # @param xoff
1587 # @param yoff
1588 #
1589 #*
1590 sub WriteTile {
1591  my($self, $data, $xoff, $yoff) = @_;
1592  $xoff //= 0;
1593  $yoff //= 0;
1594  error('The data must be in a two-dimensional array') unless ref $data eq 'ARRAY' && ref $data->[0] eq 'ARRAY';
1595  my $xsize = @{$data->[0]};
1596  if ($xsize > $self->{XSize} - $xoff) {
1597  warn "Buffer XSize too large ($xsize) for this raster band (width = $self->{XSize}, offset = $xoff).";
1598  $xsize = $self->{XSize} - $xoff;
1599  }
1600  my $ysize = @{$data};
1601  if ($ysize > $self->{YSize} - $yoff) {
1602  $ysize = $self->{YSize} - $yoff;
1603  warn "Buffer YSize too large ($ysize) for this raster band (height = $self->{YSize}, offset = $yoff).";
1604  }
1605  my $pc = Geo::GDAL::PackCharacter($self->{DataType});
1606  for my $i (0..$ysize-1) {
1607  my $scanline = pack($pc."[$xsize]", @{$data->[$i]});
1608  $self->WriteRaster( $xoff, $yoff+$i, $xsize, 1, $scanline );
1609  }
1610 }
1611 
1612 #** @class Geo::GDAL::ColorTable
1613 # @brief A color table from a raster band or a color table, which can be used for a band.
1614 # @details
1615 #*
1616 package Geo::GDAL::ColorTable;
1617 
1618 use base qw(Geo::GDAL)
1619 
1620 #** @method Geo::GDAL::ColorTable Clone()
1621 # Object method.
1622 # Clone an existing color table.
1623 # @return a new Geo::GDAL::ColorTable object
1624 #*
1625 sub Clone {
1626 }
1627 
1628 #** @method list Color($index, @color)
1629 # Object method.
1630 # Get or set a color in this color table.
1631 # @param index The index of the color in the table. Note that the
1632 # color table may expand if the index is larger than the current max
1633 # index of this table and a color is given. An attempt to retrieve a
1634 # color out of the current size of the table causes an error.
1635 # @param color [optional] The color, either a list or a reference to a
1636 # list. If the list is too short or has undef values, the undef values
1637 # are taken as 0 except for alpha, which is taken as 255.
1638 # @note A color is an array of four integers having a value between 0
1639 # and 255: (gray, red, cyan or hue; green, magenta, or lightness;
1640 # blue, yellow, or saturation; alpha or blackband)
1641 # @return A color, in list context a list and in scalar context a reference to an anonymous array.
1642 #*
1643 sub Color {
1644 }
1645 
1646 #** @method list Colors(@colors)
1647 # Object method.
1648 # Get or set the colors in this color table.
1649 # @note The color table will expand to the size of the input list but
1650 # it will not shrink.
1651 # @param colors [optional] A list of all colors (a list of lists) for this color table.
1652 # @return A list of colors (a list of lists).
1653 #*
1654 sub Colors {
1655 }
1656 
1657 #** @method CreateColorRamp($start_index, arrayref start_color, $end_index, arrayref end_color)
1658 # Object method.
1659 # @param start_index
1660 # @param start_color
1661 # @param end_index
1662 # @param end_color
1663 #*
1664 sub CreateColorRamp {
1665 }
1666 
1667 #** @method scalar GetCount()
1668 # Object method.
1669 # @return The number of colors in this color table.
1670 #*
1671 sub GetCount {
1672 }
1673 
1674 #** @method scalar GetPaletteInterpretation()
1675 # Object method.
1676 # @return palette interpretation (string)
1677 #*
1678 sub GetPaletteInterpretation {
1679  my $self = shift;
1680  return i2s(palette_interpretation => GetPaletteInterpretation($self));
1681 }
1682 
1683 #** @method Geo::GDAL::ColorTable new($GDALPaletteInterp = 'RGB')
1684 # Class method.
1685 # Create a new empty color table.
1686 # @return a new Geo::GDAL::ColorTable object
1687 #*
1688 sub new {
1689  my($pkg, $pi) = @_;
1690  $pi //= 'RGB';
1691  $pi = s2i(palette_interpretation => $pi);
1692  my $self = Geo::GDALc::new_ColorTable($pi);
1693  bless $self, $pkg if defined($self);
1694 }
1695 
1696 #** @class Geo::GDAL::Dataset
1697 # @brief A set of associated raster bands or vector layer source.
1698 # @details
1699 #*
1700 package Geo::GDAL::Dataset;
1701 
1702 use base qw(Geo::GDAL::MajorObject Geo::GDAL)
1703 
1704 #** @attr $RasterCount
1705 # scalar (access as $dataset->{RasterCount})
1706 #*
1707 
1708 #** @attr $RasterXSize
1709 # scalar (access as $dataset->{RasterXSize})
1710 #*
1711 
1712 #** @attr $RasterYSize
1713 # scalar (access as $dataset->{RasterYSize})
1714 #*
1715 
1716 #** @method AddBand($datatype = 'Byte', hashref options = {})
1717 # Object method.
1718 # Add a new band to the dataset. The driver must support the action.
1719 # @param datatype GDAL raster cell data type (one of those listed by Geo::GDAL::DataTypes).
1720 # @param options reference to a hash of format specific options.
1721 # @return The added band.
1722 #*
1723 sub AddBand {
1724  my ($self, $type, $options) = @_;
1725  $type //= 'Byte';
1726  $type = s2i(data_type => $type);
1727  $self->_AddBand($type, $options);
1728  return unless defined wantarray;
1729  return $self->GetRasterBand($self->{RasterCount});
1730 }
1731 
1732 #** @method Geo::GDAL::Band Band($index)
1733 # Object method.
1734 # Create a band object for the band within the dataset.
1735 # @note a.k.a. GetRasterBand
1736 # @param index 1...RasterCount, default is 1.
1737 # @return a new Geo::GDAL::Band object
1738 #*
1739 sub Band {
1740 }
1741 
1742 #** @method list Bands()
1743 # Object method.
1744 # @return a list of new Geo::GDAL::Band objects
1745 #*
1746 sub Bands {
1747  my $self = shift;
1748  my @bands;
1749  for my $i (1..$self->{RasterCount}) {
1750  push @bands, GetRasterBand($self, $i);
1751  }
1752  return @bands;
1753 }
1754 
1755 #** @method BuildOverviews($resampling, arrayref overviews, coderef progress, $progress_data)
1756 # Object method.
1757 # @param resampling the resampling method, one of Geo::GDAL::RIOResamplingTypes.
1758 # @param overviews The list of overview decimation factors to
1759 # build. For example [2,4,8].
1760 # @param progress [optional] a reference to a subroutine, which will
1761 # be called with parameters (number progress, string msg, progress_data)
1762 # @param progress_data [optional]
1763 #*
1764 sub BuildOverviews {
1765  my $self = shift;
1766  my @p = @_;
1767  $p[0] = uc($p[0]) if $p[0];
1768  eval {
1769  $self->_BuildOverviews(@p);
1770  };
1771  confess(last_error()) if $@;
1772 }
1773 
1774 #** @method Geo::GDAL::Dataset BuildVRT($Dest, arrayref Sources, hashref Options, coderef progress, $progress_data)
1775 # Object method.
1776 # Build a virtual dataset from a set of datasets.
1777 # @param Dest Destination raster dataset definition string (typically
1778 # filename), or an object, which implements write and close.
1779 # @param Sources A list of filenames of input datasets or a list of
1780 # dataset objects.
1781 # @param Options See section \ref index_processing_options.
1782 # @return Dataset object
1783 #
1784 # @note This subroutine is imported into the main namespace if Geo::GDAL
1785 # is use'd with qw/:all/.
1786 #*
1787 sub BuildVRT {
1788  my ($dest, $sources, $options, $progress, $progress_data) = @_;
1789  $options = Geo::GDAL::GDALBuildVRTOptions->new(make_processing_options($options));
1790  error("Usage: Geo::GDAL::DataSet::BuildVRT(\$vrt_file_name, \\\@sources)")
1791  unless ref $sources eq 'ARRAY' && defined $sources->[0];
1792  unless (blessed($dest)) {
1793  if (blessed($sources->[0])) {
1794  return Geo::GDAL::wrapper_GDALBuildVRT_objects($dest, $sources, $options, $progress, $progress_data);
1795  } else {
1796  return Geo::GDAL::wrapper_GDALBuildVRT_names($dest, $sources, $options, $progress, $progress_data);
1797  }
1798  } else {
1799  if (blessed($sources->[0])) {
1800  return stdout_redirection_wrapper(
1801  $sources, $dest,
1802  \&Geo::GDAL::wrapper_GDALBuildVRT_objects,
1803  $options, $progress, $progress_data);
1804  } else {
1805  return stdout_redirection_wrapper(
1806  $sources, $dest,
1807  \&Geo::GDAL::wrapper_GDALBuildVRT_names,
1808  $options, $progress, $progress_data);
1809  }
1810  }
1811 }
1812 
1813 #** @method CommitTransaction()
1814 #*
1815 sub CommitTransaction {
1816 }
1817 
1818 #** @method Geo::GDAL::ColorTable ComputeColorTable(%params)
1819 # Object method.
1820 # Compute a color table from an RGB image
1821 # @param params Named parameters:
1822 # - \a Red The red band, the default is to use the red band of this dataset.
1823 # - \a Green The green band, the default is to use the green band of this dataset.
1824 # - \a Blue The blue band, the default is to use the blue band of this dataset.
1825 # - \a NumColors The number of colors in the computed color table. Default is 256.
1826 # - \a Progress reference to a progress function (default is undef)
1827 # - \a ProgressData (default is undef)
1828 # - \a Method The computation method. The default and currently only option is the median cut algorithm.
1829 #
1830 # @return a new color table object.
1831 #*
1832 sub ComputeColorTable {
1833  my $self = shift;
1834  my $p = named_parameters(\@_,
1835  Red => undef,
1836  Green => undef,
1837  Blue => undef,
1838  NumColors => 256,
1839  Progress => undef,
1840  ProgressData => undef,
1841  Method => 'MedianCut');
1842  for my $b ($self->Bands) {
1843  for my $cion ($b->ColorInterpretation) {
1844  if ($cion eq 'RedBand') { $p->{red} //= $b; last; }
1845  if ($cion eq 'GreenBand') { $p->{green} //= $b; last; }
1846  if ($cion eq 'BlueBand') { $p->{blue} //= $b; last; }
1847  }
1848  }
1849  my $ct = Geo::GDAL::ColorTable->new;
1850  Geo::GDAL::ComputeMedianCutPCT($p->{red},
1851  $p->{green},
1852  $p->{blue},
1853  $p->{numcolors},
1854  $ct, $p->{progress},
1855  $p->{progressdata});
1856  return $ct;
1857 }
1858 
1859 #** @method Geo::OGR::Layer CopyLayer($layer, $name, hashref options = undef)
1860 # Object method.
1861 # @param layer A Geo::OGR::Layer object to be copied.
1862 # @param name A name for the new layer.
1863 # @param options A ref to a hash of format specific options.
1864 # @return a new Geo::OGR::Layer object.
1865 #*
1866 sub CopyLayer {
1867 }
1868 
1869 #** @method Geo::OGR::Layer CreateLayer(%params)
1870 # Object method.
1871 # @brief Create a new vector layer into this dataset.
1872 #
1873 # @param %params Named parameters:
1874 # - \a Name (scalar) name for the new layer.
1875 # - \a Fields (array reference) a list of (scalar and geometry) field definitions as in
1876 # Geo::OGR::Layer::CreateField.
1877 # - \a ApproxOK (boolean value, default is true) a flag, which is forwarded to Geo::OGR::Layer::CreateField.
1878 # - \a Options (hash reference) driver specific hash of layer creation options.
1879 # - \a Schema (hash reference, deprecated, use \a Fields and \a Name) may contain keys Name, Fields, GeomFields, GeometryType.
1880 # - \a SRS (scalar) the spatial reference for the default geometry field.
1881 # - \a GeometryType (scalar) the type of the default geometry field
1882 # (if only one geometry field). Default is 'Unknown'.
1883 #
1884 # @note If Fields or Schema|Fields is not given, a default geometry
1885 # field (Name => '', GeometryType => 'Unknown') is created. If it is
1886 # given and it contains spatial fields, GeometryType is ignored. The
1887 # type can be also set with the named parameter.
1888 #
1889 # Example:
1890 # \code
1891 # my $roads = Geo::OGR::Driver('Memory')->Create('road')->
1892 # CreateLayer(
1893 # Fields => [ { Name => 'class',
1894 # Type => 'Integer' },
1895 # { Name => 'geom',
1896 # Type => 'LineString25D' } ] );
1897 # \endcode
1898 #
1899 # @note Many formats allow only one spatial field, which currently
1900 # requires the use of GeometryType.
1901 #
1902 # @return a new Geo::OGR::Layer object.
1903 #*
1904 sub CreateLayer {
1905  my $self = shift;
1906  my $p = named_parameters(\@_,
1907  Name => 'unnamed',
1908  SRS => undef,
1909  GeometryType => 'Unknown',
1910  Options => {},
1911  Schema => undef,
1912  Fields => undef,
1913  ApproxOK => 1);
1914  error("The 'Fields' argument must be an array reference.") if $p->{fields} && ref($p->{fields}) ne 'ARRAY';
1915  if (defined $p->{schema}) {
1916  my $s = $p->{schema};
1917  $p->{geometrytype} = $s->{GeometryType} if exists $s->{GeometryType};
1918  $p->{fields} = $s->{Fields} if exists $s->{Fields};
1919  $p->{name} = $s->{Name} if exists $s->{Name};
1920  }
1921  $p->{fields} = [] unless ref($p->{fields}) eq 'ARRAY';
1922  # if fields contains spatial fields, then do not create default one
1923  for my $f (@{$p->{fields}}) {
1924  error("Field definitions must be hash references.") unless ref $f eq 'HASH';
1925  if ($f->{GeometryType} || ($f->{Type} && s_exists(geometry_type => $f->{Type}))) {
1926  $p->{geometrytype} = 'None';
1927  last;
1928  }
1929  }
1930  my $gt = s2i(geometry_type => $p->{geometrytype});
1931  my $layer = _CreateLayer($self, $p->{name}, $p->{srs}, $gt, $p->{options});
1932  for my $f (@{$p->{fields}}) {
1933  $layer->CreateField($f);
1934  }
1935  keep($layer, $self);
1936 }
1937 
1938 #** @method CreateMaskBand()
1939 # Object method.
1940 # Add a mask band to the dataset.
1941 #*
1942 sub CreateMaskBand {
1943  return _CreateMaskBand(@_);
1944 }
1945 
1946 #** @method Geo::GDAL::Dataset DEMProcessing($Dest, $Processing, $ColorFilename, hashref Options, coderef progress, $progress_data)
1947 # Object method.
1948 # Apply a DEM processing to this dataset.
1949 # @param Dest Destination raster dataset definition string (typically filename) or an object, which implements write and close.
1950 # @param Processing Processing to apply, one of "hillshade", "slope", "aspect", "color-relief", "TRI", "TPI", or "Roughness".
1951 # @param ColorFilename The color palette for color-relief.
1952 # @param Options See section \ref index_processing_options.
1953 # @param progress [optional] A reference to a subroutine, which will
1954 # be called with parameters (number progress, string msg, progress_data).
1955 # @param progress_data [optional]
1956 #
1957 #*
1958 sub DEMProcessing {
1959  my ($self, $dest, $Processing, $ColorFilename, $options, $progress, $progress_data) = @_;
1960  $options = Geo::GDAL::GDALDEMProcessingOptions->new(make_processing_options($options));
1961  return $self->stdout_redirection_wrapper(
1962  $dest,
1963  \&Geo::GDAL::wrapper_GDALDEMProcessing,
1964  $Processing, $ColorFilename, $options, $progress, $progress_data
1965  );
1966 }
1967 
1968 #** @method Dataset()
1969 #*
1970 sub Dataset {
1971  my $self = shift;
1972  parent($self);
1973 }
1974 
1975 #** @method DeleteLayer($name)
1976 # Object method.
1977 # Deletes a layer from the data source. Note that if there is a layer
1978 # object for the deleted layer, it becomes unusable.
1979 # @param name name of the layer to delete.
1980 #*
1981 sub DeleteLayer {
1982  my ($self, $name) = @_;
1983  my $index;
1984  for my $i (0..$self->GetLayerCount-1) {
1985  my $layer = GetLayerByIndex($self, $i);
1986  $index = $i, last if $layer->GetName eq $name;
1987  }
1988  error(2, $name, 'Layer') unless defined $index;
1989  _DeleteLayer($self, $index);
1990 }
1991 
1992 #** @method Geo::GDAL::Band Dither(%params)
1993 # Object method.
1994 # Compute one band with color table image from an RGB image
1995 # @params params Named parameters:
1996 # - \a Red The red band, the default is to use the red band of this dataset.
1997 # - \a Green The green band, the default is to use the green band of this dataset.
1998 # - \a Blue The blue band, the default is to use the blue band of this dataset.
1999 # - \a Dest The destination band. If this is not defined, a new in-memory band (and a dataset) will be created.
2000 # - \a ColorTable The color table for the result. If this is not defined, and the destination band does not contain one, it will be computed with the ComputeColorTable method.
2001 # - \a Progress Reference to a progress function (default is undef). Note that if ColorTable is computed using ComputeColorTable method, the progress will run twice from 0 to 1.
2002 # - \a ProgressData (default is undef)
2003 #
2004 # @return the destination band.
2005 #
2006 # Usage example. This code converts an RGB JPEG image into a one band PNG image with a color table.
2007 # \code
2008 # my $d = Geo::GDAL::Open('pic.jpg');
2009 # Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
2010 # \endcode
2011 #*
2012 sub Dither {
2013  my $self = shift;
2014  my $p = named_parameters(\@_,
2015  Red => undef,
2016  Green => undef,
2017  Blue => undef,
2018  Dest => undef,
2019  ColorTable => undef,
2020  Progress => undef,
2021  ProgressData => undef);
2022  for my $b ($self->Bands) {
2023  for my $cion ($b->ColorInterpretation) {
2024  if ($cion eq 'RedBand') { $p->{red} //= $b; last; }
2025  if ($cion eq 'GreenBand') { $p->{green} //= $b; last; }
2026  if ($cion eq 'BlueBand') { $p->{blue} //= $b; last; }
2027  }
2028  }
2029  my ($w, $h) = $self->Size;
2030  $p->{dest} //= Geo::GDAL::Driver('MEM')->Create(Name => 'dithered',
2031  Width => $w,
2032  Height => $h,
2033  Type => 'Byte')->Band;
2034  $p->{colortable}
2035  //= $p->{dest}->ColorTable
2036  // $self->ComputeColorTable(Red => $p->{red},
2037  Green => $p->{green},
2038  Blue => $p->{blue},
2039  Progress => $p->{progress},
2040  ProgressData => $p->{progressdata});
2041  Geo::GDAL::DitherRGB2PCT($p->{red},
2042  $p->{green},
2043  $p->{blue},
2044  $p->{dest},
2045  $p->{colortable},
2046  $p->{progress},
2047  $p->{progressdata});
2048  $p->{dest}->ColorTable($p->{colortable});
2049  return $p->{dest};
2050 }
2051 
2052 #** @method Domains()
2053 #*
2054 sub Domains {
2055  return @DOMAINS;
2056 }
2057 
2058 #** @method Geo::GDAL::Driver Driver()
2059 # Object method.
2060 # @note a.k.a. GetDriver
2061 # @return a Geo::GDAL::Driver object that was used to open or create this dataset.
2062 #*
2063 sub Driver {
2064 }
2065 
2066 #** @method Geo::OGR::Layer ExecuteSQL($statement, $geom = undef, $dialect = "")
2067 # Object method.
2068 # @param statement A SQL statement.
2069 # @param geom A Geo::OGR::Geometry object.
2070 # @param dialect
2071 # @return a new Geo::OGR::Layer object. The data source object will
2072 # exist as long as the layer object exists.
2073 #*
2074 sub ExecuteSQL {
2075  my $self = shift;
2076  my $layer = $self->_ExecuteSQL(@_);
2077  note($layer, "is result set");
2078  keep($layer, $self);
2079 }
2080 
2081 #** @method Geo::GDAL::Extent Extent(@params)
2082 # Object method.
2083 # @param params nothing, or a list ($xoff, $yoff, $w, $h)
2084 # @return A new Geo::GDAL::Extent object that represents the area that
2085 # this raster or the specified tile covers.
2086 #*
2087 sub Extent {
2088  my $self = shift;
2089  my $t = $self->GeoTransform;
2090  my $extent = $t->Extent($self->Size);
2091  if (@_) {
2092  my ($xoff, $yoff, $w, $h) = @_;
2093  my ($x, $y) = $t->Apply([$xoff, $xoff+$w, $xoff+$w, $xoff], [$yoff, $yoff, $yoff+$h, $yoff+$h]);
2094  my $xmin = shift @$x;
2095  my $xmax = $xmin;
2096  for my $x (@$x) {
2097  $xmin = $x if $x < $xmin;
2098  $xmax = $x if $x > $xmax;
2099  }
2100  my $ymin = shift @$y;
2101  my $ymax = $ymin;
2102  for my $y (@$y) {
2103  $ymin = $y if $y < $ymin;
2104  $ymax = $y if $y > $ymax;
2105  }
2106  $extent = Geo::GDAL::Extent->new($xmin, $ymin, $xmax, $ymax);
2107  }
2108  return $extent;
2109 }
2110 
2111 #** @method list GCPs(@GCPs, Geo::OSR::SpatialReference sr)
2112 # Object method.
2113 # Get or set the GCPs and their projection.
2114 # @param GCPs [optional] a list of Geo::GDAL::GCP objects
2115 # @param sr [optional] the projection of the GCPs.
2116 # @return a list of Geo::GDAL::GCP objects followed by a Geo::OSR::SpatialReference object.
2117 #*
2118 sub GCPs {
2119  my $self = shift;
2120  if (@_ > 0) {
2121  my $proj = pop @_;
2122  $proj = $proj->Export('WKT') if $proj and ref($proj);
2123  SetGCPs($self, \@_, $proj);
2124  }
2125  return unless defined wantarray;
2126  my $proj = Geo::OSR::SpatialReference->new(GetGCPProjection($self));
2127  my $GCPs = GetGCPs($self);
2128  return (@$GCPs, $proj);
2129 }
2130 
2131 #** @method Geo::GDAL::GeoTransform GeoTransform(Geo::GDAL::GeoTransform $geo_transform)
2132 # Object method.
2133 # Transformation from cell coordinates (column,row) to projection
2134 # coordinates (x,y)
2135 # \code
2136 # x = geo_transform[0] + column*geo_transform[1] + row*geo_transform[2]
2137 # y = geo_transform[3] + column*geo_transform[4] + row*geo_transform[5]
2138 # \endcode
2139 # @param geo_transform [optional]
2140 # @return the geo transform in a non-void context.
2141 #*
2142 sub GeoTransform {
2143  my $self = shift;
2144  eval {
2145  if (@_ == 1) {
2146  SetGeoTransform($self, $_[0]);
2147  } elsif (@_ > 1) {
2148  SetGeoTransform($self, \@_);
2149  }
2150  };
2151  confess(last_error()) if $@;
2152  return unless defined wantarray;
2153  my $t = GetGeoTransform($self);
2154  if (wantarray) {
2155  return @$t;
2156  } else {
2157  return Geo::GDAL::GeoTransform->new($t);
2158  }
2159 }
2160 
2161 #** @method GetDriver()
2162 #*
2163 sub GetDriver {
2164 }
2165 
2166 #** @method list GetFileList()
2167 # Object method.
2168 # @return list of files GDAL believes to be part of this dataset.
2169 #*
2170 sub GetFileList {
2171 }
2172 
2173 #** @method scalar GetGCPProjection()
2174 # Object method.
2175 # @return projection string.
2176 #*
2177 sub GetGCPProjection {
2178 }
2179 
2180 #** @method Geo::OGR::Layer GetLayer($name)
2181 # Object method.
2182 # @param name the name of the requested layer. If not given, then
2183 # returns the first layer in the data source.
2184 # @return a new Geo::OGR::Layer object that represents the layer
2185 # in the data source.
2186 #*
2187 sub GetLayer {
2188  my($self, $name) = @_;
2189  my $layer = defined $name ? GetLayerByName($self, "$name") : GetLayerByIndex($self, 0);
2190  $name //= '';
2191  error(2, $name, 'Layer') unless $layer;
2192  keep($layer, $self);
2193 }
2194 
2195 #** @method list GetLayerNames()
2196 # Object method.
2197 # @note Delivers the functionality of undocumented method GetLayerCount.
2198 # @return a list of the names of the layers this data source provides.
2199 #*
2200 sub GetLayerNames {
2201  my $self = shift;
2202  my @names;
2203  for my $i (0..$self->GetLayerCount-1) {
2204  my $layer = GetLayerByIndex($self, $i);
2205  push @names, $layer->GetName;
2206  }
2207  return @names;
2208 }
2209 
2210 #** @method GetNextFeature()
2211 #*
2212 sub GetNextFeature {
2213 }
2214 
2215 #** @method GetStyleTable()
2216 #*
2217 sub GetStyleTable {
2218 }
2219 
2220 #** @method Geo::GDAL::Dataset Grid($Dest, hashref Options)
2221 # Object method.
2222 # Creates a regular raster grid from this data source.
2223 # This is equivalent to the gdal_grid utility.
2224 # @param Dest Destination raster dataset definition string (typically
2225 # filename) or an object, which implements write and close.
2226 # @param Options See section \ref index_processing_options.
2227 #*
2228 sub Grid {
2229  my ($self, $dest, $options, $progress, $progress_data) = @_;
2230  $options = Geo::GDAL::GDALGridOptions->new(make_processing_options($options));
2231  return $self->stdout_redirection_wrapper(
2232  $dest,
2233  \&Geo::GDAL::wrapper_GDALGrid,
2234  $options, $progress, $progress_data
2235  );
2236 }
2237 
2238 #** @method scalar Info(hashref Options)
2239 # Object method.
2240 # Information about this dataset.
2241 # @param Options See section \ref index_processing_options.
2242 #*
2243 sub Info {
2244  my ($self, $o) = @_;
2245  $o = Geo::GDAL::GDALInfoOptions->new(make_processing_options($o));
2246  return GDALInfo($self, $o);
2247 }
2248 
2249 #** @method Geo::GDAL::Dataset Nearblack($Dest, hashref Options, coderef progress, $progress_data)
2250 # Object method.
2251 # Convert nearly black/white pixels to black/white.
2252 # @param Dest Destination raster dataset definition string (typically
2253 # filename), destination dataset to which to add an alpha or mask
2254 # band, or an object, which implements write and close.
2255 # @param Options See section \ref index_processing_options.
2256 # @return Dataset if destination dataset definition string was given,
2257 # otherwise a boolean for success/fail but the method croaks if there
2258 # was an error.
2259 #*
2260 sub Nearblack {
2261  my ($self, $dest, $options, $progress, $progress_data) = @_;
2262  $options = Geo::GDAL::GDALNearblackOptions->new(make_processing_options($options));
2263  my $b = blessed($dest);
2264  if ($b && $b eq 'Geo::GDAL::Dataset') {
2265  Geo::GDAL::wrapper_GDALNearblackDestDS($dest, $self, $options, $progress, $progress_data);
2266  } else {
2267  return $self->stdout_redirection_wrapper(
2268  $dest,
2269  \&Geo::GDAL::wrapper_GDALNearblackDestName,
2270  $options, $progress, $progress_data
2271  );
2272  }
2273 }
2274 
2275 #** @method Geo::GDAL::Dataset Open()
2276 # Package subroutine.
2277 # The same as Geo::GDAL::Open
2278 #*
2279 sub Open {
2280 }
2281 
2282 #** @method Geo::GDAL::Dataset OpenShared()
2283 # Package subroutine.
2284 # The same as Geo::GDAL::OpenShared
2285 #*
2286 sub OpenShared {
2287 }
2288 
2289 #** @method RELEASE_PARENT()
2290 #*
2291 sub RELEASE_PARENT {
2292  my $self = shift;
2293  unkeep($self);
2294 }
2295 
2296 #** @method Geo::GDAL::Dataset Rasterize($Dest, hashref Options, coderef progress, $progress_data)
2297 # Object method.
2298 # Render data from this data source into a raster.
2299 # @param Dest Destination raster dataset definition string (typically
2300 # filename), destination dataset, or an object, which implements write and close.
2301 # @param Options See section \ref index_processing_options.
2302 # @return Dataset if destination dataset definition string was given,
2303 # otherwise a boolean for success/fail but the method croaks if there
2304 # was an error.
2305 #
2306 #*
2307 sub Rasterize {
2308  my ($self, $dest, $options, $progress, $progress_data) = @_;
2309  $options = Geo::GDAL::GDALRasterizeOptions->new(make_processing_options($options));
2310  my $b = blessed($dest);
2311  if ($b && $b eq 'Geo::GDAL::Dataset') {
2312  Geo::GDAL::wrapper_GDALRasterizeDestDS($dest, $self, $options, $progress, $progress_data);
2313  } else {
2314  # TODO: options need to force a new raster be made, otherwise segfault
2315  return $self->stdout_redirection_wrapper(
2316  $dest,
2317  \&Geo::GDAL::wrapper_GDALRasterizeDestName,
2318  $options, $progress, $progress_data
2319  );
2320  }
2321 }
2322 
2323 #** @method scalar ReadRaster(%params)
2324 # Object method.
2325 # Read data from the dataset.
2326 #
2327 # @param params Named parameters:
2328 # - \a XOff x offset (cell coordinates) (default is 0)
2329 # - \a YOff y offset (cell coordinates) (default is 0)
2330 # - \a XSize width of the area to read (default is the width of the dataset)
2331 # - \a YSize height of the area to read (default is the height of the dataset)
2332 # - \a BufXSize (default is undef, i.e., the same as XSize)
2333 # - \a BufYSize (default is undef, i.e., the same as YSize)
2334 # - \a BufType data type of the buffer (default is the data type of the first band)
2335 # - \a BandList a reference to an array of band indices (default is [1])
2336 # - \a BufPixelSpace (default is 0)
2337 # - \a BufLineSpace (default is 0)
2338 # - \a BufBandSpace (default is 0)
2339 # - \a ResampleAlg one of Geo::GDAL::RIOResamplingTypes (default is 'NearestNeighbour'),
2340 # - \a Progress reference to a progress function (default is undef)
2341 # - \a ProgressData (default is undef)
2342 #
2343 # <a href="http://www.gdal.org/classGDALDataset.html">Entry in GDAL docs (method RasterIO)</a>
2344 # @return a buffer, open the buffer with \a unpack function of Perl. See Geo::GDAL::Band::PackCharacter.
2345 #*
2346 sub ReadRaster {
2347  my $self = shift;
2348  my ($width, $height) = $self->Size;
2349  my ($type) = $self->Band->DataType;
2350  my $p = named_parameters(\@_,
2351  XOff => 0,
2352  YOff => 0,
2353  XSize => $width,
2354  YSize => $height,
2355  BufXSize => undef,
2356  BufYSize => undef,
2357  BufType => $type,
2358  BandList => [1],
2359  BufPixelSpace => 0,
2360  BufLineSpace => 0,
2361  BufBandSpace => 0,
2362  ResampleAlg => 'NearestNeighbour',
2363  Progress => undef,
2364  ProgressData => undef
2365  );
2366  $p->{resamplealg} = s2i(rio_resampling => $p->{resamplealg});
2367  $p->{buftype} = s2i(data_type => $p->{buftype}, 1);
2368  $self->_ReadRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bandlist},$p->{bufpixelspace},$p->{buflinespace},$p->{bufbandspace},$p->{resamplealg},$p->{progress},$p->{progressdata});
2369 }
2370 
2371 #** @method ReadTile()
2372 #*
2373 sub ReadTile {
2374  my ($self, $xoff, $yoff, $xsize, $ysize, $w_tile, $h_tile, $alg) = @_;
2375  my @data;
2376  for my $i (0..$self->Bands-1) {
2377  $data[$i] = $self->Band($i+1)->ReadTile($xoff, $yoff, $xsize, $ysize, $w_tile, $h_tile, $alg);
2378  }
2379  return \@data;
2380 }
2381 
2382 #** @method ReleaseResultSet($layer)
2383 # Object method.
2384 # @param layer A layer the has been created with ExecuteSQL.
2385 # @note There is no need to call this method. The result set layer is
2386 # released in the destructor of the layer that was created with SQL.
2387 #*
2388 sub ReleaseResultSet {
2389  # a no-op, _ReleaseResultSet is called from Layer::DESTROY
2390 }
2391 
2392 #** @method ResetReading()
2393 #*
2394 sub ResetReading {
2395 }
2396 
2397 #** @method RollbackTransaction()
2398 #*
2399 sub RollbackTransaction {
2400 }
2401 
2402 #** @method SetStyleTable()
2403 #*
2404 sub SetStyleTable {
2405 }
2406 
2407 #** @method list Size()
2408 # Object method.
2409 # @return (width, height)
2410 #*
2411 sub Size {
2412  my $self = shift;
2413  return ($self->{RasterXSize}, $self->{RasterYSize});
2414 }
2415 
2416 #** @method Geo::OSR::SpatialReference SpatialReference(Geo::OSR::SpatialReference sr)
2417 # Object method.
2418 # Get or set the projection of this dataset.
2419 # @param sr [optional] a Geo::OSR::SpatialReference object,
2420 # which replaces the existing projection definition of this dataset.
2421 # @return a Geo::OSR::SpatialReference object, which represents the
2422 # projection of this dataset.
2423 # @note Methods GetProjection, SetProjection, and Projection return WKT strings.
2424 #*
2425 sub SpatialReference {
2426  my($self, $sr) = @_;
2427  SetProjection($self, $sr->As('WKT')) if defined $sr;
2428  if (defined wantarray) {
2429  my $p = GetProjection($self);
2430  return unless $p;
2431  return Geo::OSR::SpatialReference->new(WKT => $p);
2432  }
2433 }
2434 
2435 #** @method StartTransaction()
2436 #*
2437 sub StartTransaction {
2438 }
2439 
2440 #** @method TestCapability()
2441 #*
2442 sub TestCapability {
2443  return _TestCapability(@_);
2444 }
2445 
2446 #** @method Tile(Geo::GDAL::Extent e)
2447 # Object method.
2448 # Compute the top left cell coordinates and width and height of the
2449 # tile that covers the given extent.
2450 # @param e The extent whose tile is needed.
2451 # @note Requires that the raster is a strictly north up one.
2452 # @return A list ($xoff, $yoff, $xsize, $ysize).
2453 #*
2454 sub Tile {
2455  my ($self, $e) = @_;
2456  my ($w, $h) = $self->Size;
2457  my $t = $self->GeoTransform;
2458  confess "GeoTransform is not \"north up\"." unless $t->NorthUp;
2459  my $xoff = floor(($e->[0] - $t->[0])/$t->[1]);
2460  $xoff = 0 if $xoff < 0;
2461  my $yoff = floor(($e->[1] - $t->[3])/$t->[5]);
2462  $yoff = 0 if $yoff < 0;
2463  my $xsize = ceil(($e->[2] - $t->[0])/$t->[1]) - $xoff;
2464  $xsize = $w - $xoff if $xsize > $w - $xoff;
2465  my $ysize = ceil(($e->[3] - $t->[3])/$t->[5]) - $yoff;
2466  $ysize = $h - $yoff if $ysize > $h - $yoff;
2467  return ($xoff, $yoff, $xsize, $ysize);
2468 }
2469 
2470 #** @method Geo::GDAL::Dataset Translate($Dest, hashref Options, coderef progress, $progress_data)
2471 # Object method.
2472 # Convert this dataset into another format.
2473 # @param Dest Destination dataset definition string (typically
2474 # filename) or an object, which implements write and close.
2475 # @param Options See section \ref index_processing_options.
2476 # @return New dataset object if destination dataset definition
2477 # string was given, otherwise a boolean for success/fail but the
2478 # method croaks if there was an error.
2479 #*
2480 sub Translate {
2481  my ($self, $dest, $options, $progress, $progress_data) = @_;
2482  return $self->stdout_redirection_wrapper(
2483  $dest,
2484 }
2485 
2486 #** @method Geo::GDAL::Dataset Warp($Dest, hashref Options, coderef progress, $progress_data)
2487 # Object method.
2488 # Reproject this dataset.
2489 # @param Dest Destination raster dataset definition string (typically
2490 # filename) or an object, which implements write and close.
2491 # @param Options See section \ref index_processing_options.
2492 # @note This method can be run as a package subroutine with a list of
2493 # datasets as the first argument to mosaic several datasets.
2494 #*
2495 sub Warp {
2496  my ($self, $dest, $options, $progress, $progress_data) = @_;
2497  # can be run as object method (one dataset) and as package sub (a list of datasets)
2498  $options = Geo::GDAL::GDALWarpAppOptions->new(make_processing_options($options));
2499  my $b = blessed($dest);
2500  $self = [$self] unless ref $self eq 'ARRAY';
2501  if ($b && $b eq 'Geo::GDAL::Dataset') {
2502  Geo::GDAL::wrapper_GDALWarpDestDS($dest, $self, $options, $progress, $progress_data);
2503  } else {
2504  return stdout_redirection_wrapper(
2505  $self,
2506  $dest,
2507  \&Geo::GDAL::wrapper_GDALWarpDestName,
2508  $options, $progress, $progress_data
2509  );
2510  }
2511 }
2512 
2513 #** @method Geo::GDAL::Dataset Warped(%params)
2514 # Object method.
2515 # Create a virtual warped dataset from this dataset.
2516 #
2517 # @param params Named parameters:
2518 # - \a SrcSRS Override the spatial reference system of this dataset if there is one (default is undef).
2519 # - \a DstSRS The target spatial reference system of the result (default is undef).
2520 # - \a ResampleAlg The resampling algorithm (default is 'NearestNeighbour').
2521 # - \a MaxError Maximum error measured in input cellsize that is allowed in approximating the transformation (default is 0 for exact calculations).
2522 #
2523 # # <a href="http://www.gdal.org/gdalwarper_8h.html">Documentation for GDAL warper.</a>
2524 #
2525 # @return a new Geo::GDAL::Dataset object
2526 #*
2527 sub Warped {
2528  my $self = shift;
2529  my $p = named_parameters(\@_, SrcSRS => undef, DstSRS => undef, ResampleAlg => 'NearestNeighbour', MaxError => 0);
2530  for my $srs (qw/srcsrs dstsrs/) {
2531  $p->{$srs} = $p->{$srs}->ExportToWkt if $p->{$srs} && blessed $p->{$srs};
2532  }
2533  $p->{resamplealg} = s2i(resampling => $p->{resamplealg});
2534  my $warped = Geo::GDAL::_AutoCreateWarpedVRT($self, $p->{srcsrs}, $p->{dstsrs}, $p->{resamplealg}, $p->{maxerror});
2535  keep($warped, $self) if $warped; # self must live as long as warped
2536 }
2537 
2538 #** @method WriteRaster(%params)
2539 # Object method.
2540 # Write data into the dataset.
2541 #
2542 # @param params Named parameters:
2543 # - \a XOff x offset (cell coordinates) (default is 0)
2544 # - \a YOff y offset (cell coordinates) (default is 0)
2545 # - \a XSize width of the area to write (default is the width of the dataset)
2546 # - \a YSize height of the area to write (default is the height of the dataset)
2547 # - \a Buf a buffer (or a reference to a buffer) containing the data. Create the buffer with \a pack function of Perl. See Geo::GDAL::Band::PackCharacter.
2548 # - \a BufXSize (default is undef, i.e., the same as XSize)
2549 # - \a BufYSize (default is undef, i.e., the same as YSize)
2550 # - \a BufType data type of the buffer (default is the data type of the first band)
2551 # - \a BandList a reference to an array of band indices (default is [1])
2552 # - \a BufPixelSpace (default is 0)
2553 # - \a BufLineSpace (default is 0)
2554 # - \a BufBandSpace (default is 0)
2555 #
2556 # <a href="http://www.gdal.org/classGDALDataset.html">Entry in GDAL docs (method RasterIO)</a>
2557 #*
2558 sub WriteRaster {
2559  my $self = shift;
2560  my ($width, $height) = $self->Size;
2561  my ($type) = $self->Band->DataType;
2562  my $p = named_parameters(\@_,
2563  XOff => 0,
2564  YOff => 0,
2565  XSize => $width,
2566  YSize => $height,
2567  Buf => undef,
2568  BufXSize => undef,
2569  BufYSize => undef,
2570  BufType => $type,
2571  BandList => [1],
2572  BufPixelSpace => 0,
2573  BufLineSpace => 0,
2574  BufBandSpace => 0
2575  );
2576  $p->{buftype} = s2i(data_type => $p->{buftype}, 1);
2577  $self->_WriteRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{buf},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bandlist},$p->{bufpixelspace},$p->{buflinespace},$p->{bufbandspace});
2578 }
2579 
2580 #** @method WriteTile()
2581 #*
2582 sub WriteTile {
2583  my ($self, $data, $xoff, $yoff) = @_;
2584  $xoff //= 0;
2585  $yoff //= 0;
2586  for my $i (0..$self->Bands-1) {
2587  $self->Band($i+1)->WriteTile($data->[$i], $xoff, $yoff);
2588  }
2589 }
2590 
2591 #** @class Geo::GDAL::Driver
2592 # @brief A driver for a specific dataset format.
2593 # @details
2594 #*
2595 package Geo::GDAL::Driver;
2596 
2597 use base qw(Geo::GDAL::MajorObject Geo::GDAL)
2598 
2599 #** @attr $HelpTopic
2600 # $driver->{HelpTopic}
2601 #*
2602 
2603 #** @attr $LongName
2604 # $driver->{LongName}
2605 #*
2606 
2607 #** @attr $ShortName
2608 # $driver->{ShortName}
2609 #*
2610 
2611 #** @method list Capabilities()
2612 # Object method.
2613 # @return A list of capabilities. When executed as a package subroutine
2614 # returns a list of all potential capabilities a driver may have. When
2615 # executed as an object method returns a list of all capabilities the
2616 # driver has.
2617 #
2618 # Currently capabilities are:
2619 # CREATE, CREATECOPY, DEFAULT_FIELDS, NOTNULL_FIELDS, NOTNULL_GEOMFIELDS, OPEN, RASTER, VECTOR, and VIRTUALIO.
2620 #
2621 # Examples.
2622 # \code
2623 # @all_capabilities = Geo::GDAL::Driver::Capabilities;
2624 # @capabilities_of_the_geotiff_driver = Geo::GDAL::Driver('GTiff')->Capabilities;
2625 # \endcode
2626 #*
2627 sub Capabilities {
2628  my $self = shift;
2629  return @CAPABILITIES unless $self;
2630  my $h = $self->GetMetadata;
2631  my @cap;
2632  for my $cap (@CAPABILITIES) {
2633  my $test = $h->{'DCAP_'.uc($cap)};
2634  push @cap, $cap if defined($test) and $test eq 'YES';
2635  }
2636  return @cap;
2637 }
2638 
2639 #** @method Geo::GDAL::Dataset Copy(%params)
2640 # Object method.
2641 # Create a new raster Geo::GDAL::Dataset as a copy of an existing dataset.
2642 # @note a.k.a. CreateCopy
2643 #
2644 # @param params Named parameters:
2645 # - \a Name name for the new raster dataset.
2646 # - \a Src the source Geo::GDAL::Dataset object.
2647 # - \a Strict 1 (default) if the copy must be strictly equivalent, or 0 if the copy may adapt.
2648 # - \a Options an anonymous hash of driver specific options.
2649 # - \a Progress [optional] a reference to a subroutine, which will
2650 # be called with parameters (number progress, string msg, progress_data).
2651 # - \a ProgressData [optional]
2652 # @return a new Geo::GDAL::Dataset object.
2653 #*
2654 sub Copy {
2655  my $self = shift;
2656  my $p = named_parameters(\@_, Name => 'unnamed', Src => undef, Strict => 1, Options => {}, Progress => undef, ProgressData => undef);
2657  return $self->stdout_redirection_wrapper(
2658  $p->{name},
2659  $self->can('_CreateCopy'),
2660  $p->{src}, $p->{strict}, $p->{options}, $p->{progress}, $p->{progressdata});
2661 }
2662 
2663 #** @method CopyFiles($NewName, $OldName)
2664 # Object method.
2665 # Copy the files of a dataset.
2666 # @param NewName String.
2667 # @param OldName String.
2668 #*
2669 sub CopyFiles {
2670 }
2671 
2672 #** @method Geo::GDAL::Dataset Create(%params)
2673 # Object method.
2674 # Create a raster dataset using this driver.
2675 # @note a.k.a. CreateDataset
2676 #
2677 # @param params Named parameters:
2678 # - \a Name The name for the dataset (default is 'unnamed') or an object, which implements write and close.
2679 # - \a Width The width for the raster dataset (default is 256).
2680 # - \a Height The height for the raster dataset (default is 256).
2681 # - \a Bands The number of bands to create into the raster dataset (default is 1).
2682 # - \a Type The data type for the raster cells (default is 'Byte'). One of Geo::GDAL::Driver::CreationDataTypes.
2683 # - \a Options Driver creation options as a reference to a hash (default is {}).
2684 #
2685 # @return A new Geo::GDAL::Dataset object.
2686 #*
2687 sub Create {
2688  my $self = shift;
2689  my $p = named_parameters(\@_, Name => 'unnamed', Width => 256, Height => 256, Bands => 1, Type => 'Byte', Options => {});
2690  my $type = s2i(data_type => $p->{type});
2691  return $self->stdout_redirection_wrapper(
2692  $p->{name},
2693  $self->can('_Create'),
2694  $p->{width}, $p->{height}, $p->{bands}, $type, $p->{options}
2695  );
2696 }
2697 
2698 #** @method list CreationDataTypes()
2699 # Object method.
2700 # @return a list of data types that can be used for new datasets of this format. A subset of Geo::GDAL::DataTypes
2701 #*
2702 sub CreationDataTypes {
2703  my $self = shift;
2704  my $h = $self->GetMetadata;
2705  return split /\s+/, $h->{DMD_CREATIONDATATYPES} if $h->{DMD_CREATIONDATATYPES};
2706 }
2707 
2708 #** @method list CreationOptionList()
2709 # Object method.
2710 # @return a list of options, each option is a hashref, the keys are
2711 # name, type and description or Value. Value is a listref.
2712 #*
2713 sub CreationOptionList {
2714  my $self = shift;
2715  my @options;
2716  my $h = $self->GetMetadata->{DMD_CREATIONOPTIONLIST};
2717  if ($h) {
2718  $h = ParseXMLString($h);
2719  my($type, $value) = NodeData($h);
2720  if ($value eq 'CreationOptionList') {
2721  for my $o (Children($h)) {
2722  my %option;
2723  for my $a (Children($o)) {
2724  my(undef, $key) = NodeData($a);
2725  my(undef, $value) = NodeData(Child($a, 0));
2726  if ($key eq 'Value') {
2727  push @{$option{$key}}, $value;
2728  } else {
2729  $option{$key} = $value;
2730  }
2731  }
2732  push @options, \%option;
2733  }
2734  }
2735  }
2736  return @options;
2737 }
2738 
2739 #** @method Delete($name)
2740 # Object method.
2741 # @param name
2742 #*
2743 sub Delete {
2744 }
2745 
2746 #** @method Domains()
2747 #*
2748 sub Domains {
2749  return @DOMAINS;
2750 }
2751 
2752 #** @method scalar Extension()
2753 # Object method.
2754 # @note The returned extension does not contain a '.' prefix.
2755 # @return a suggested single extension or a list of extensions (in
2756 # list context) for datasets.
2757 #*
2758 sub Extension {
2759  my $self = shift;
2760  my $h = $self->GetMetadata;
2761  if (wantarray) {
2762  my $e = $h->{DMD_EXTENSIONS};
2763  my @e = split / /, $e;
2764  @e = split /\//, $e if $e =~ /\//; # ILWIS returns mpr/mpl
2765  for my $i (0..$#e) {
2766  $e[$i] =~ s/^\.//; # CALS returns extensions with a dot prefix
2767  }
2768  return @e;
2769  } else {
2770  my $e = $h->{DMD_EXTENSION};
2771  return '' if $e =~ /\//; # ILWIS returns mpr/mpl
2772  $e =~ s/^\.//;
2773  return $e;
2774  }
2775 }
2776 
2777 #** @method scalar MIMEType()
2778 # Object method.
2779 # @return a suggested MIME type for datasets.
2780 #*
2781 sub MIMEType {
2782  my $self = shift;
2783  my $h = $self->GetMetadata;
2784  return $h->{DMD_MIMETYPE};
2785 }
2786 
2787 #** @method scalar Name()
2788 # Object method.
2789 # @return The short name of the driver.
2790 #*
2791 sub Name {
2792  my $self = shift;
2793  return $self->{ShortName};
2794 }
2795 
2796 #** @method Open()
2797 # Object method.
2798 # The same as Geo::GDAL::Open except that only this driver is allowed.
2799 #*
2800 sub Open {
2801  my $self = shift;
2802  my @p = @_; # name, update
2803  my @flags = qw/RASTER/;
2804  push @flags, qw/READONLY/ if $p[1] eq 'ReadOnly';
2805  push @flags, qw/UPDATE/ if $p[1] eq 'Update';
2806  my $dataset = OpenEx($p[0], \@flags, [$self->Name()]);
2807  error("Failed to open $p[0]. Is it a raster dataset?") unless $dataset;
2808  return $dataset;
2809 }
2810 
2811 #** @method Rename($NewName, $OldName)
2812 # Object method.
2813 # Rename (move) a GDAL dataset.
2814 # @param NewName String.
2815 # @param OldName String.
2816 #*
2817 sub Rename {
2818 }
2819 
2820 #** @method scalar TestCapability($cap)
2821 # Object method.
2822 # Test whether the driver has the specified capability.
2823 # @param cap A capability string (one of those returned by Capabilities).
2824 # @return a boolean value.
2825 #*
2826 sub TestCapability {
2827  my($self, $cap) = @_;
2828  my $h = $self->GetMetadata->{'DCAP_'.uc($cap)};
2829  return (defined($h) and $h eq 'YES') ? 1 : undef;
2830 }
2831 
2832 #** @method stdout_redirection_wrapper()
2833 #*
2834 sub stdout_redirection_wrapper {
2835  my ($self, $name, $sub, @params) = @_;
2836  my $object = 0;
2837  if ($name && blessed $name) {
2838  $object = $name;
2839  my $ref = $object->can('write');
2840  VSIStdoutSetRedirection($ref);
2841  $name = '/vsistdout/';
2842  }
2843  my $ds;
2844  eval {
2845  $ds = $sub->($self, $name, @params);
2846  };
2847  if ($object) {
2848  if ($ds) {
2849  $Geo::GDAL::stdout_redirection{tied(%$ds)} = $object;
2850  } else {
2851  VSIStdoutUnsetRedirection();
2852  $object->close;
2853  }
2854  }
2855  confess(last_error()) if $@;
2856  confess("Failed. Use Geo::OGR::Driver for vector drivers.") unless $ds;
2857  return $ds;
2858 }
2859 
2860 #** @class Geo::GDAL::Extent
2861 # @brief A rectangular area in projection coordinates: xmin, ymin, xmax, ymax.
2862 #*
2863 package Geo::GDAL::Extent;
2864 
2865 #** @method ExpandToInclude($extent)
2866 # Package subroutine.
2867 # Extends this extent to include the other extent.
2868 # @param extent Another Geo::GDAL::Extent object.
2869 #*
2870 sub ExpandToInclude {
2871  my ($self, $e) = @_;
2872  return if $e->IsEmpty;
2873  if ($self->IsEmpty) {
2874  @$self = @$e;
2875  } else {
2876  $self->[0] = $e->[0] if $e->[0] < $self->[0];
2877  $self->[1] = $e->[1] if $e->[1] < $self->[1];
2878  $self->[2] = $e->[2] if $e->[2] > $self->[2];
2879  $self->[3] = $e->[3] if $e->[3] > $self->[3];
2880  }
2881 }
2882 
2883 #** @method IsEmpty()
2884 #*
2885 sub IsEmpty {
2886  my $self = shift;
2887  return $self->[2] < $self->[0];
2888 }
2889 
2890 #** @method scalar Overlap($extent)
2891 # Package subroutine.
2892 # @param extent Another Geo::GDAL::Extent object.
2893 # @return A new, possibly empty, Geo::GDAL::Extent object, which
2894 # represents the joint area of the two extents.
2895 #*
2896 sub Overlap {
2897  my ($self, $e) = @_;
2898  return Geo::GDAL::Extent->new() unless $self->Overlaps($e);
2899  my $ret = Geo::GDAL::Extent->new($self);
2900  $ret->[0] = $e->[0] if $self->[0] < $e->[0];
2901  $ret->[1] = $e->[1] if $self->[1] < $e->[1];
2902  $ret->[2] = $e->[2] if $self->[2] > $e->[2];
2903  $ret->[3] = $e->[3] if $self->[3] > $e->[3];
2904  return $ret;
2905 }
2906 
2907 #** @method scalar Overlaps($extent)
2908 # Package subroutine.
2909 # @param extent Another Geo::GDAL::Extent object.
2910 # @return True if this extent overlaps the other extent, false otherwise.
2911 #*
2912 sub Overlaps {
2913  my ($self, $e) = @_;
2914  return $self->[0] < $e->[2] && $self->[2] > $e->[0] && $self->[1] < $e->[3] && $self->[3] > $e->[1];
2915 }
2916 
2917 #** @method list Size()
2918 # Package subroutine.
2919 # @return A list ($width, $height).
2920 #*
2921 sub Size {
2922  my $self = shift;
2923  return (0,0) if $self->IsEmpty;
2924  return ($self->[2] - $self->[0], $self->[3] - $self->[1]);
2925 }
2926 
2927 #** @method Geo::GDAL::Extent new(@params)
2928 # Package subroutine.
2929 # @param params nothing, a list ($xmin, $ymin, $xmax, $ymax), or an Extent object
2930 # @return A new Extent object (empty if no parameters, a copy of the parameter if it is an Extent object).
2931 #*
2932 sub new {
2933  my $class = shift;
2934  my $self;
2935  if (@_ == 0) {
2936  $self = [0,0,-1,0];
2937  } elsif (ref $_[0]) {
2938  @$self = @{$_[0]};
2939  } else {
2940  @$self = @_;
2941  }
2942  bless $self, $class;
2943  return $self;
2944 }
2945 
2946 #** @class Geo::GDAL::GCP
2947 # @brief A ground control point for georeferencing rasters.
2948 # @details
2949 #*
2950 package Geo::GDAL::GCP;
2951 
2952 use base qw(Geo::GDAL)
2953 
2954 #** @attr $Column
2955 # cell x coordinate (access as $gcp->{Column})
2956 #*
2957 
2958 #** @attr $Id
2959 # unique identifier (string) (access as $gcp->{Id})
2960 #*
2961 
2962 #** @attr $Info
2963 # informational message (access as $gcp->{Info})
2964 #*
2965 
2966 #** @attr $Row
2967 # cell y coordinate (access as $gcp->{Row})
2968 #*
2969 
2970 #** @attr $X
2971 # projection coordinate (access as $gcp->{X})
2972 #*
2973 
2974 #** @attr $Y
2975 # projection coordinate (access as $gcp->{Y})
2976 #*
2977 
2978 #** @attr $Z
2979 # projection coordinate (access as $gcp->{Z})
2980 #*
2981 
2982 #** @method scalar new($x = 0.0, $y = 0.0, $z = 0.0, $column = 0.0, $row = 0.0, $info = "", $id = "")
2983 # Class method.
2984 # @param x projection coordinate
2985 # @param y projection coordinate
2986 # @param z projection coordinate
2987 # @param column cell x coordinate
2988 # @param row cell y coordinate
2989 # @param info informational message
2990 # @param id unique identifier (string)
2991 # @return a new Geo::GDAL::GCP object
2992 #*
2993 sub new {
2994  my $pkg = shift;
2995  my $self = Geo::GDALc::new_GCP(@_);
2996  bless $self, $pkg if defined($self);
2997 }
2998 
2999 #** @class Geo::GDAL::GeoTransform
3000 # @brief An array of affine transformation coefficients.
3001 # @details The geo transformation has the form
3002 # \code
3003 # x = a + column * b + row * c
3004 # y = d + column * e + row * f
3005 # \endcode
3006 # where
3007 # (column,row) is the location in cell coordinates, and
3008 # (x,y) is the location in projection coordinates, or vice versa.
3009 # A Geo::GDAL::GeoTransform object is a reference to an anonymous array [a,b,c,d,e,f].
3010 #*
3011 package Geo::GDAL::GeoTransform;
3012 
3013 #** @method Apply($x, $y)
3014 # Object method.
3015 # @param x Column or x, or a reference to an array of columns or x's
3016 # @param y Row or y, or a reference to an array of rows or y's
3017 # @return a list (x, y), where x and y are the transformed coordinates
3018 # or references to arrays of transformed coordinates.
3019 #*
3020 sub Apply {
3021  my ($self, $columns, $rows) = @_;
3022  return Geo::GDAL::ApplyGeoTransform($self, $columns, $rows) unless ref($columns) eq 'ARRAY';
3023  my (@x, @y);
3024  for my $i (0..$#$columns) {
3025  ($x[$i], $y[$i]) =
3026  Geo::GDAL::ApplyGeoTransform($self, $columns->[$i], $rows->[$i]);
3027  }
3028  return (\@x, \@y);
3029 }
3030 
3031 #** @method Inv()
3032 # Object method.
3033 # @return a new Geo::GDAL::GeoTransform object, which is the inverse
3034 # of this one (in void context changes this object).
3035 #*
3036 sub Inv {
3037  my $self = shift;
3038  my @inv = Geo::GDAL::InvGeoTransform($self);
3039  return Geo::GDAL::GeoTransform->new(@inv) if defined wantarray;
3040  @$self = @inv;
3041 }
3042 
3043 #** @method NorthUp()
3044 #*
3045 sub NorthUp {
3046  my $self = shift;
3047  return $self->[2] == 0 && $self->[4] == 0;
3048 }
3049 
3050 #** @method new(@params)
3051 # Class method.
3052 # @param params nothing, a reference to an array [a,b,c,d,e,f], a list
3053 # (a,b,c,d,e,f), or named parameters
3054 # - \a GCPs A reference to an array of Geo::GDAL::GCP objects.
3055 # - \a ApproxOK Minimize the error in the coefficients (integer, default is 1 (true), used with GCPs).
3056 # - \a Extent A Geo::GDAL::Extent object used to obtain the coordinates of the up left corner position.
3057 # - \a CellSize The cell size (width and height) (default is 1, used with Extent).
3058 #
3059 # @note When Extent is specifid, the created geo transform will be
3060 # north up, have square cells, and coefficient f will be -1 times the
3061 # cell size (image y - row - will increase downwards and projection y
3062 # will increase upwards).
3063 # @return a new Geo::GDAL::GeoTransform object.
3064 #*
3065 sub new {
3066  my $class = shift;
3067  my $self;
3068  if (@_ == 0) {
3069  $self = [0,1,0,0,0,1];
3070  } elsif (ref $_[0]) {
3071  @$self = @{$_[0]};
3072  } elsif ($_[0] =~ /^[a-zA-Z]/i) {
3073  my $p = named_parameters(\@_, GCPs => undef, ApproxOK => 1, Extent => undef, CellSize => 1);
3074  if ($p->{gcps}) {
3075  $self = Geo::GDAL::GCPsToGeoTransform($p->{gcps}, $p->{approxok});
3076  } elsif ($p->{extent}) {
3077  $self = Geo::GDAL::GeoTransform->new($p->{extent}[0], $p->{cellsize}, 0, $p->{extent}[2], 0, -$p->{cellsize});
3078  } else {
3079  error("Missing GCPs or Extent");
3080  }
3081  } else {
3082  my @a = @_;
3083  $self = \@a;
3084  }
3085  bless $self, $class;
3086 }
3087 
3088 #** @class Geo::GDAL::MajorObject
3089 # @brief An object, which holds meta data.
3090 # @details
3091 #*
3092 package Geo::GDAL::MajorObject;
3093 
3094 use base qw(Geo::GDAL)
3095 
3096 #** @method scalar Description($description)
3097 # Object method.
3098 # @param description [optional]
3099 # @return the description in a non-void context.
3100 #*
3101 sub Description {
3102  my($self, $desc) = @_;
3103  SetDescription($self, $desc) if defined $desc;
3104  GetDescription($self) if defined wantarray;
3105 }
3106 
3107 #** @method Domains()
3108 # Package subroutine.
3109 # @return the class specific DOMAINS list
3110 #*
3111 sub Domains {
3112  return @DOMAINS;
3113 }
3114 
3115 #** @method scalar GetDescription()
3116 # Object method.
3117 # @return
3118 #*
3119 sub GetDescription {
3120 }
3121 
3122 #** @method hash reference GetMetadata($domain = "")
3123 # Object method.
3124 # @note see Metadata
3125 # @param domain
3126 # @return
3127 #*
3128 sub GetMetadata {
3129 }
3130 
3131 #** @method GetMetadataDomainList()
3132 #*
3133 sub GetMetadataDomainList {
3134 }
3135 
3136 #** @method hash reference Metadata(hashref metadata = undef, $domain = '')
3137 # Object method.
3138 # @param metadata
3139 # @param domain
3140 # @return the metadata in a non-void context.
3141 #*
3142 sub Metadata {
3143  my $self = shift,
3144  my $metadata = ref $_[0] ? shift : undef;
3145  my $domain = shift // '';
3146  SetMetadata($self, $metadata, $domain) if defined $metadata;
3147  GetMetadata($self, $domain) if defined wantarray;
3148 }
3149 
3150 #** @method SetDescription($NewDesc)
3151 # Object method.
3152 # @param NewDesc
3153 #
3154 #*
3155 sub SetDescription {
3156 }
3157 
3158 #** @method SetMetadata(hashref metadata, $domain = "")
3159 # Object method.
3160 # @note see Metadata
3161 # @param metadata
3162 # @param domain
3163 #
3164 #*
3165 sub SetMetadata {
3166 }
3167 
3168 #** @class Geo::GDAL::RasterAttributeTable
3169 # @brief An attribute table in a raster band.
3170 # @details
3171 #*
3172 package Geo::GDAL::RasterAttributeTable;
3173 
3174 use base qw(Geo::GDAL)
3175 
3176 #** @method Band()
3177 #*
3178 sub Band {
3179  my $self = shift;
3180  parent($self);
3181 }
3182 
3183 #** @method ChangesAreWrittenToFile()
3184 #*
3185 sub ChangesAreWrittenToFile {
3186 }
3187 
3188 #** @method Geo::GDAL::RasterAttributeTable Clone()
3189 # Object method.
3190 # @return a new Geo::GDAL::RasterAttributeTable object
3191 #*
3192 sub Clone {
3193 }
3194 
3195 #** @method hash Columns(%columns)
3196 # Object method.
3197 # A get/set method for the columns of the RAT
3198 # @param columns optional, a the keys are column names and the values are anonymous
3199 # hashes with keys Type and Usage
3200 # @return a hash similar to the optional input parameter
3201 #*
3202 sub Columns {
3203  my $self = shift;
3204  my %columns;
3205  if (@_) { # create columns
3206  %columns = @_;
3207  for my $name (keys %columns) {
3208  $self->CreateColumn($name, $columns{$name}{Type}, $columns{$name}{Usage});
3209  }
3210  }
3211  %columns = ();
3212  for my $c (0..$self->GetColumnCount-1) {
3213  my $name = $self->GetNameOfCol($c);
3214  $columns{$name}{Type} = $self->GetTypeOfCol($c);
3215  $columns{$name}{Usage} = $self->GetUsageOfCol($c);
3216  }
3217  return %columns;
3218 }
3219 
3220 #** @method CreateColumn($name, $type, $usage)
3221 # Object method.
3222 # @param name
3223 # @param type one of FieldTypes
3224 # @param usage one of FieldUsages
3225 #*
3226 sub CreateColumn {
3227  my($self, $name, $type, $usage) = @_;
3228  for my $color (qw/Red Green Blue Alpha/) {
3229  carp "RAT column type will be 'Integer' for usage '$color'." if $usage eq $color and $type ne 'Integer';
3230  }
3231  $type = s2i(rat_field_type => $type);
3232  $usage = s2i(rat_field_usage => $usage);
3233  _CreateColumn($self, $name, $type, $usage);
3234 }
3235 
3236 #** @method DumpReadable()
3237 #*
3238 sub DumpReadable {
3240 
3241 #** @method list FieldTypes()
3242 # Package subroutine.
3243 # @return
3244 #*
3245 sub FieldTypes {
3246  return @FIELD_TYPES;
3248 
3249 #** @method list FieldUsages()
3250 # Package subroutine.
3251 # @return
3252 #*
3253 sub FieldUsages {
3254  return @FIELD_USAGES;
3256 
3257 #** @method scalar GetColOfUsage($usage)
3258 # Object method.
3259 # @param usage
3260 # @return
3261 #*
3262 sub GetColOfUsage {
3263  my($self, $usage) = @_;
3264  _GetColOfUsage($self, s2i(rat_field_usage => $usage));
3265 }
3266 
3267 #** @method scalar GetColumnCount()
3268 # Object method.
3269 # @return
3270 #*
3271 sub GetColumnCount {
3272 }
3273 
3274 #** @method scalar GetNameOfCol($column)
3275 # Object method.
3276 # @param column
3277 # @return
3278 #*
3279 sub GetNameOfCol {
3280 }
3281 
3282 #** @method scalar GetRowCount()
3283 # Object method.
3284 #*
3285 sub GetRowCount {
3286 }
3287 
3288 #** @method scalar GetRowOfValue($value)
3289 # Object method.
3290 # @param value a cell value
3291 # @return row index or -1
3292 #*
3293 sub GetRowOfValue {
3294 }
3295 
3296 #** @method scalar GetTypeOfCol($column)
3297 # Object method.
3298 # @param column
3299 # @return
3300 #*
3301 sub GetTypeOfCol {
3302  my($self, $col) = @_;
3303  i2s(rat_field_type => _GetTypeOfCol($self, $col));
3304 }
3305 
3306 #** @method scalar GetUsageOfCol($column)
3307 # Object method.
3308 # @param column
3309 # @return
3310 #*
3311 sub GetUsageOfCol {
3312  my($self, $col) = @_;
3313  i2s(rat_field_usage => _GetUsageOfCol($self, $col));
3314 }
3315 
3316 #** @method scalar GetValueAsDouble($row, $column)
3317 # Object method.
3318 # @param row
3319 # @param column
3320 # @return
3321 #*
3322 sub GetValueAsDouble {
3323 }
3324 
3325 #** @method scalar GetValueAsInt($row, $column)
3326 # Object method.
3327 # @param row
3328 # @param column
3329 # @return
3330 #*
3331 sub GetValueAsInt {
3332 }
3333 
3334 #** @method scalar GetValueAsString($row, $column)
3335 # Object method.
3336 # @param row
3337 # @param column
3338 # @return
3339 #*
3340 sub GetValueAsString {
3341 }
3342 
3343 #** @method LinearBinning($Row0MinIn, $BinSizeIn)
3344 # Object method.
3345 # @param Row0MinIn [optional] the lower bound (cell value) of the first category.
3346 # @param BinSizeIn [optional] the width of each category (in cell value units).
3347 # @return ($Row0MinIn, $BinSizeIn) or an empty list if LinearBinning is not set.
3348 #*
3349 sub LinearBinning {
3350  my $self = shift;
3351  SetLinearBinning($self, @_) if @_ > 0;
3352  return unless defined wantarray;
3353  my @a = GetLinearBinning($self);
3354  return $a[0] ? ($a[1], $a[2]) : ();
3355 }
3356 
3357 #** @method RELEASE_PARENT()
3358 #*
3359 sub RELEASE_PARENT {
3360  my $self = shift;
3361  unkeep($self);
3362 }
3363 
3364 #** @method SetRowCount($count)
3365 # Object method.
3366 # @param count
3367 #
3368 #*
3369 sub SetRowCount {
3370 }
3371 
3372 #** @method SetValueAsDouble($row, $column, $value)
3373 # Object method.
3374 # @param row
3375 # @param column
3376 # @param value
3377 #
3378 #*
3379 sub SetValueAsDouble {
3380 }
3381 
3382 #** @method SetValueAsInt($row, $column, $value)
3383 # Object method.
3384 # @param row
3385 # @param column
3386 # @param value
3387 #
3388 #*
3389 sub SetValueAsInt {
3390 }
3391 
3392 #** @method SetValueAsString($row, $column, $value)
3393 # Object method.
3394 # @param row
3395 # @param column
3396 # @param value
3397 #
3398 #*
3399 sub SetValueAsString {
3400 }
3401 
3402 #** @method scalar Value($row, $column, $value)
3403 # Object method.
3404 # @param row
3405 # @param column
3406 # @param value [optional]
3407 # @return
3408 #*
3409 sub Value {
3410  my($self, $row, $column) = @_;
3411  SetValueAsString($self, $row, $column, $_[3]) if defined $_[3];
3412  return unless defined wantarray;
3413  GetValueAsString($self, $row, $column);
3414 }
3415 
3416 #** @method Geo::GDAL::RasterAttributeTable new()
3417 # Class method.
3418 # @return a new Geo::GDAL::RasterAttributeTable object
3419 #*
3420 sub new {
3421  my $pkg = shift;
3422  my $self = Geo::GDALc::new_RasterAttributeTable(@_);
3423  bless $self, $pkg if defined($self);
3424 }
3425 
3426 #** @class Geo::GDAL::Transformer
3427 # @brief
3428 # @details This class is not yet documented for the GDAL Perl bindings.
3429 # @todo Test and document.
3430 #*
3431 package Geo::GDAL::Transformer;
3432 
3433 use base qw(Geo::GDAL)
3434 
3435 #** @method TransformGeolocations()
3436 #*
3437 sub TransformGeolocations {
3438 }
3439 
3440 #** @method TransformPoint()
3441 #*
3442 sub TransformPoint {
3443 }
3444 
3445 #** @method new()
3446 #*
3447 sub new {
3448  my $pkg = shift;
3449  my $self = Geo::GDALc::new_Transformer(@_);
3450  bless $self, $pkg if defined($self);
3451 }
3452 
3453 #** @class Geo::GDAL::VSIF
3454 # @brief A GDAL virtual file system.
3455 # @details
3456 #*
3457 package Geo::GDAL::VSIF;
3458 
3459 use base qw(our Exporter)
3460 
3461 #** @method Close()
3462 # Object method.
3463 #*
3464 sub Close {
3465  my ($self, $data) = @_;
3466  Geo::GDAL::VSIFCloseL($self);
3467 }
3468 
3469 #** @method MkDir($path)
3470 # Package subroutine.
3471 # Make a directory.
3472 # @param path The directory to make.
3473 # @note The name of this method is VSIMkdir in GDAL.
3474 #*
3475 sub MkDir {
3476  my ($path) = @_;
3477  # mode unused in CPL
3478  Geo::GDAL::Mkdir($path, 0);
3479 }
3480 
3481 #** @method Geo::GDAL::VSIF Open($filename, $mode)
3482 # Package subroutine.
3483 # @param filename Name of the file to open. For example "/vsimem/x".
3484 # @param mode Access mode. 'r', 'r+', 'w', etc.
3485 # @return A file handle on success.
3486 #*
3487 sub Open {
3488  my ($path, $mode) = @_;
3489  my $self = Geo::GDAL::VSIFOpenL($path, $mode);
3490  bless $self, 'Geo::GDAL::VSIF';
3491 }
3492 
3493 #** @method scalar Read($count)
3494 # Object method.
3495 # @param count The number of bytes to read from the file.
3496 # @return A byte string.
3497 #*
3498 sub Read {
3499  my ($self, $count) = @_;
3500  Geo::GDAL::VSIFReadL($count, $self);
3501 }
3502 
3503 #** @method list ReadDir($dir)
3504 # Package subroutine.
3505 # @return Contents of a directory in an anonymous array or as a list.
3506 #*
3507 sub ReadDir {
3508  my ($path) = @_;
3509  Geo::GDAL::ReadDir($path);
3510 }
3511 
3512 #** @method scalar ReadDirRecursive($dir)
3513 # Package subroutine.
3514 # @note Give the directory in the form '/vsimem', i.e., without trailing '/'.
3515 # @return Contents of a directory tree in an anonymous array.
3516 #*
3517 sub ReadDirRecursive {
3518  my ($path) = @_;
3519  Geo::GDAL::ReadDirRecursive($path);
3520 }
3521 
3522 #** @method Rename($old, $new)
3523 # Package subroutine.
3524 # Rename a file.
3525 # @note The name of this method is VSIRename in GDAL.
3526 #*
3527 sub Rename {
3528  my ($old, $new) = @_;
3529  Geo::GDAL::Rename($old, $new);
3530 }
3531 
3532 #** @method RmDir($path)
3533 # Package subroutine.
3534 # Remove a directory.
3535 # @note The name of this method is VSIRmdir in GDAL.
3536 #*
3537 sub RmDir {
3538  my ($dirname, $recursive) = @_;
3539  eval {
3540  if (!$recursive) {
3541  Geo::GDAL::Rmdir($dirname);
3542  } else {
3543  for my $f (ReadDir($dirname)) {
3544  next if $f eq '..' or $f eq '.';
3545  my @s = Stat($dirname.'/'.$f);
3546  if ($s[0] eq 'f') {
3547  Unlink($dirname.'/'.$f);
3548  } elsif ($s[0] eq 'd') {
3549  Rmdir($dirname.'/'.$f, 1);
3550  Rmdir($dirname.'/'.$f);
3551  }
3552  }
3553  RmDir($dirname);
3554  }
3555  };
3556  if ($@) {
3557  my $r = $recursive ? ' recursively' : '';
3558  error("Cannot remove directory \"$dirname\"$r.");
3559  }
3560 }
3561 
3562 #** @method Seek($offset, $whence)
3563 # Object method.
3564 #*
3565 sub Seek {
3566  my ($self, $offset, $whence) = @_;
3567  Geo::GDAL::VSIFSeekL($self, $offset, $whence);
3568 }
3569 
3570 #** @method list Stat($filename)
3571 # Package subroutine.
3572 # @return ($filemode, $filesize). filemode is f for a plain file, d
3573 # for a directory, l for a symbolic link, p for a named pipe (FIFO), S
3574 # for a socket, b for a block special file, and c for a character
3575 # special file.
3576 #*
3577 sub Stat {
3578  my ($path) = @_;
3579  Geo::GDAL::Stat($path);
3580 }
3581 
3582 #** @method scalar Tell()
3583 # Object method.
3584 #*
3585 sub Tell {
3586  my ($self) = @_;
3587  Geo::GDAL::VSIFTellL($self);
3588 }
3589 
3590 #** @method Truncate($new_size)
3591 # Object method.
3592 #*
3593 sub Truncate {
3594  my ($self, $new_size) = @_;
3595  Geo::GDAL::VSIFTruncateL($self, $new_size);
3596 }
3597 
3598 #** @method Unlink($filename)
3599 # Package subroutine.
3600 # @param filename The file to delete.
3601 # @return 0 on success and -1 on an error.
3602 #*
3603 sub Unlink {
3604  my ($filename) = @_;
3605  Geo::GDAL::Unlink($filename);
3606 }
3607 
3608 #** @method Write($scalar)
3609 # Object method.
3610 # @param scalar The byte string to write to the file.
3611 # @return Number of bytes written into the file.
3612 #*
3613 sub Write {
3614  my ($self, $data) = @_;
3615  Geo::GDAL::VSIFWriteL($data, $self);
3616 }
3617 
3618 #** @class Geo::GDAL::XML
3619 # @brief A simple XML parser
3620 # @details
3621 #*
3622 package Geo::GDAL::XML;
3623 
3624 #** @method new($string)
3625 # Object method.
3626 # @param string String containing XML.
3627 # @return A new Geo::GDAL::XML object, which is a reference to an anonymous array.
3628 #*
3629 sub new {
3630  my $class = shift;
3631  my $xml = shift // '';
3632  my $self = ParseXMLString($xml);
3633  bless $self, $class;
3634  $self->traverse(sub {my $node = shift; bless $node, $class});
3635  return $self;
3636 }
3637 
3638 #** @method serialize()
3639 # Object method.
3640 # @return The XML serialized into a string.
3641 #*
3642 sub serialize {
3643  my $self = shift;
3644  return SerializeXMLTree($self);
3645 }
3646 1;
3647 # This file was automatically generated by SWIG (http://www.swig.org).
3648 # Version 2.0.7
3649 #
3650 # Do not make changes to this file unless you know what you are doing--modify
3651 # the SWIG interface file instead.
3652 }
3653 
3654 #** @method traverse(coderef subroutine)
3655 # Object method.
3656 # @param subroutine Code reference, which will be called for each node in the XML with parameters: node, node_type, node_value. Node type is either Attribute, Comment, Element, Literal, or Text.
3657 #*
3658 sub traverse {
3659  my ($self, $sub) = @_;
3660  my $type = $self->[0];
3661  my $data = $self->[1];
3662  $type = NodeType($type);
3663  $sub->($self, $type, $data);
3664  for my $child (@{$self}[2..$#$self]) {
3665  traverse($child, $sub);
3666  }
3667 }
3668 
3669 #** @class Geo::GNM
3670 # @brief Base class for geographical networks in GDAL.
3671 # @details
3672 #*
3673 package Geo::GNM;
3674 
3675 #** @method CastToGenericNetwork()
3676 #*
3677 sub CastToGenericNetwork {
3678 }
3679 
3680 #** @method CastToNetwork()
3681 #*
3682 sub CastToNetwork {
3683 }
3684 
3685 #** @method GATConnectedComponents()
3686 #*
3687 sub GATConnectedComponents {
3688 }
3689 
3690 #** @method GATDijkstraShortestPath()
3691 #*
3692 sub GATDijkstraShortestPath {
3693 }
3694 
3695 #** @method GATKShortestPath()
3696 #*
3697 sub GATKShortestPath {
3698 }
3699 
3700 #** @method GNM_EDGE_DIR_BOTH()
3701 #*
3702 sub GNM_EDGE_DIR_BOTH {
3703 }
3704 
3705 #** @method GNM_EDGE_DIR_SRCTOTGT()
3706 #*
3707 sub GNM_EDGE_DIR_SRCTOTGT {
3708 }
3709 
3710 #** @method GNM_EDGE_DIR_TGTTOSRC()
3711 #*
3712 sub GNM_EDGE_DIR_TGTTOSRC {
3713  1;
3714 }
3715 
3716 #** @class Geo::GNM::GenericNetwork
3717 # @details
3718 #*
3719 package Geo::GNM::GenericNetwork;
3720 
3721 use base qw(Geo::GNM::Network Geo::GNM)
3722 
3723 #** @method ChangeAllBlockState()
3724 #*
3725 sub ChangeAllBlockState {
3726 }
3727 
3728 #** @method ChangeBlockState()
3729 #*
3730 sub ChangeBlockState {
3731 }
3732 
3733 #** @method ConnectFeatures()
3734 #*
3735 sub ConnectFeatures {
3736 }
3737 
3738 #** @method ConnectPointsByLines()
3739 #*
3740 sub ConnectPointsByLines {
3741 }
3742 
3743 #** @method CreateRule()
3744 #*
3745 sub CreateRule {
3746 }
3747 
3748 #** @method DeleteAllRules()
3749 #*
3750 sub DeleteAllRules {
3751 }
3752 
3753 #** @method DeleteRule()
3754 #*
3755 sub DeleteRule {
3756 }
3757 
3758 #** @method DisconnectFeatures()
3759 #*
3760 sub DisconnectFeatures {
3761 }
3762 
3763 #** @method DisconnectFeaturesWithId()
3764 #*
3765 sub DisconnectFeaturesWithId {
3766 }
3767 
3768 #** @method GetRules()
3769 #*
3770 sub GetRules {
3771 }
3772 
3773 #** @method ReconnectFeatures()
3774 #*
3775 sub ReconnectFeatures {
3776 }
3777 
3778 #** @class Geo::GNM::MajorObject
3779 # @details
3780 #*
3781 package Geo::GNM::MajorObject;
3782 
3783 #** @class Geo::GNM::Network
3784 # @details
3785 #*
3786 package Geo::GNM::Network;
3787 
3788 use base qw(Geo::GDAL::MajorObject Geo::GNM)
3789 
3790 #** @method CommitTransaction()
3791 #*
3792 sub CommitTransaction {
3793 }
3794 
3795 #** @method CopyLayer()
3796 #*
3797 sub CopyLayer {
3798 }
3799 
3800 #** @method DisconnectAll()
3801 #*
3802 sub DisconnectAll {
3803 }
3804 
3805 #** @method GetFeatureByGlobalFID()
3806 #*
3807 sub GetFeatureByGlobalFID {
3808 }
3809 
3810 #** @method GetFileList()
3811 #*
3812 sub GetFileList {
3813 }
3814 
3815 #** @method GetLayerByIndex()
3816 #*
3817 sub GetLayerByIndex {
3818 }
3819 
3820 #** @method GetLayerByName()
3821 #*
3822 sub GetLayerByName {
3823 }
3824 
3825 #** @method GetLayerCount()
3826 #*
3827 sub GetLayerCount {
3828 }
3829 
3830 #** @method GetName()
3831 #*
3832 sub GetName {
3833 }
3834 
3835 #** @method GetPath()
3836 #*
3837 sub GetPath {
3838 }
3839 
3840 #** @method GetProjection()
3841 #*
3842 sub GetProjection {
3843 }
3844 
3845 #** @method GetProjectionRef()
3846 #*
3847 sub GetProjectionRef {
3848 }
3849 
3850 #** @method GetVersion()
3851 #*
3852 sub GetVersion {
3853 }
3854 
3855 #** @method RollbackTransaction()
3856 #*
3857 sub RollbackTransaction {
3858 }
3859 
3860 #** @method StartTransaction()
3861 #*
3862 sub StartTransaction {
3863 }
3864 
3865 #** @class Geo::OGR
3866 # @brief OGR utility functions.
3867 # @details A wrapper for many OGR utility functions and a root class for all
3868 # OGR classes.
3869 #*
3870 package Geo::OGR;
3871 
3872 #** @method list ByteOrders()
3873 # Package subroutine.
3874 # @return a list of byte order types, XDR and NDR. XDR denotes
3875 # big-endian and NDR denotes little-endian.
3876 #*
3877 sub ByteOrders {
3878 }
3879 
3880 #** @method Geo::GDAL::Driver Driver($name)
3881 # Package subroutine.
3882 # A.k.a GetDriver.
3883 # @param name the short name of the driver.
3884 # @note No check is made that the driver is actually a vector driver.
3885 # @return a Geo::GDAL::Driver object.
3886 #*
3887 sub Driver {
3888  return 'Geo::GDAL::Driver' unless @_;
3889  bless Geo::GDAL::Driver(@_), 'Geo::OGR::Driver';
3890 }
3891 
3892 #** @method list DriverNames()
3893 # Package subroutine.
3894 # A.k.a GetDriverNames
3895 # \code
3896 # perl -MGeo::GDAL -e '@d=Geo::OGR::DriverNames;print "@d\n"'
3897 # \endcode
3898 # @note Use Geo::GDAL::DriverNames for raster drivers.
3899 # @return a list of the short names of all available GDAL vector drivers.
3900 #*
3901 sub DriverNames {
3902 }
3903 
3904 #** @method list Drivers()
3905 # Package subroutine.
3906 # @note Use Geo::GDAL::Drivers for raster drivers.
3907 # @return a list of all available GDAL vector drivers.
3908 #*
3909 sub Drivers {
3910  my @drivers;
3911  for my $i (0..GetDriverCount()-1) {
3912  my $driver = Geo::GDAL::GetDriver($i);
3913  push @drivers, $driver if $driver->TestCapability('VECTOR');
3914  }
3915  return @drivers;
3916 }
3917 
3918 #** @method Flatten()
3919 #*
3920 sub Flatten {
3921 }
3922 
3923 #** @method scalar GeometryTypeModify($type, $modifier)
3924 # Object method.
3925 # @param type a geometry type (one of Geo::OGR::GeometryTypes).
3926 # @param modifier one of 'flatten', 'set_Z', 'make_collection', 'make_curve', or 'make_linear'.
3927 # @return modified geometry type.
3928 #*
3929 sub GeometryTypeModify {
3930  my($type, $modifier) = @_;
3931  $type = s2i(geometry_type => $type);
3932  return i2s(geometry_type => GT_Flatten($type)) if $modifier =~ /flat/i;
3933  return i2s(geometry_type => GT_SetZ($type)) if $modifier =~ /z/i;
3934  return i2s(geometry_type => GT_GetCollection($type)) if $modifier =~ /collection/i;
3935  return i2s(geometry_type => GT_GetCurve($type)) if $modifier =~ /curve/i;
3936  return i2s(geometry_type => GT_GetLinear($type)) if $modifier =~ /linear/i;
3937  error(1, $modifier, {Flatten => 1, SetZ => 1, GetCollection => 1, GetCurve => 1, GetLinear => 1});
3938 }
3939 
3940 #** @method scalar GeometryTypeTest($type, $test, $type2)
3941 # Object method.
3942 # @param type a geometry type (one of Geo::OGR::GeometryTypes).
3943 # @param test one of 'has_z', 'is_subclass_of', 'is_curve', 'is_surface', or 'is_non_linear'.
3944 # @param type2 a geometry type (one of Geo::OGR::GeometryTypes). Required for 'is_subclass_of' test.
3945 # @return result of the test.
3946 #*
3947 sub GeometryTypeTest {
3948  my($type, $test, $type2) = @_;
3949  $type = s2i(geometry_type => $type);
3950  if (defined $type2) {
3951  $type = s2i(geometry_type => $type);
3952  } else {
3953  error("Usage: GeometryTypeTest(type1, 'is_subclass_of', type2).") if $test =~ /subclass/i;
3954  }
3955  return GT_HasZ($type) if $test =~ /z/i;
3956  return GT_IsSubClassOf($type, $type2) if $test =~ /subclass/i;
3957  return GT_IsCurve($type) if $test =~ /curve/i;
3958  return GT_IsSurface($type) if $test =~ /surface/i;
3959  return GT_IsNonLinear($type) if $test =~ /linear/i;
3960  error(1, $test, {HasZ => 1, IsSubClassOf => 1, IsCurve => 1, IsSurface => 1, IsNonLinear => 1});
3961 }
3962 
3963 #** @method list GeometryTypes()
3964 # Package subroutine.
3965 # @return a list of all geometry types, currently:
3966 # CircularString, CircularStringM, CircularStringZ, CircularStringZM, CompoundCurve, CompoundCurveM, CompoundCurveZ, CompoundCurveZM, Curve, CurveM, CurvePolygon, CurvePolygonM, CurvePolygonZ, CurvePolygonZM, CurveZ, CurveZM, GeometryCollection, GeometryCollection25D, GeometryCollectionM, GeometryCollectionZM, LineString, LineString25D, LineStringM, LineStringZM, LinearRing, MultiCurve, MultiCurveM, MultiCurveZ, MultiCurveZM, MultiLineString, MultiLineString25D, MultiLineStringM, MultiLineStringZM, MultiPoint, MultiPoint25D, MultiPointM, MultiPointZM, MultiPolygon, MultiPolygon25D, MultiPolygonM, MultiPolygonZM, MultiSurface, MultiSurfaceM, MultiSurfaceZ, MultiSurfaceZM, None, Point, Point25D, PointM, PointZM, Polygon, Polygon25D, PolygonM, PolygonZM, PolyhedralSurface, PolyhedralSurfaceM, PolyhedralSurfaceZ, PolyhedralSurfaceZM, Surface, SurfaceM, SurfaceZ, SurfaceZM, TIN, TINM, TINZ, TINZM, Triangle, TriangleM, TriangleZ, TriangleZM, and Unknown.
3967 #*
3968 sub GeometryTypes {
3969  1;
3970  # This file was automatically generated by SWIG (http://www.swig.org).
3971  # Version 2.0.7
3972  #
3973  # Do not make changes to this file unless you know what you are doing--modify
3974  # the SWIG interface file instead.
3975 }
3976 
3977 #** @method GetNonLinearGeometriesEnabledFlag()
3978 #*
3979 sub GetNonLinearGeometriesEnabledFlag {
3980 }
3981 
3982 #** @method GetOpenDSCount()
3983 #*
3984 sub GetOpenDSCount {
3985 }
3986 
3987 #** @method HasM()
3988 #*
3989 sub HasM {
3990 }
3991 
3992 #** @method HasZ()
3993 #*
3994 sub HasZ {
3995 }
3996 
3997 #** @method Geo::GDAL::Dataset Open($name, $update = 0)
3998 # Object method.
3999 # Open a vector data source.
4000 # @param name The data source string (directory, filename, etc.).
4001 # @param update Whether to open the data source in update mode (default is not).
4002 # @return a new Geo::GDAL::Dataset object.
4003 #*
4004 sub Open {
4005  my @p = @_; # name, update
4006  my @flags = qw/VECTOR/;
4007  push @flags, qw/UPDATE/ if $p[1];
4008  my $dataset = Geo::GDAL::OpenEx($p[0], \@flags);
4009  error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
4010  return $dataset;
4011 }
4012 
4013 #** @method Geo::GDAL::Dataset OpenShared($name, $update = 0)
4014 # Object method.
4015 # Open a vector data source in shared mode.
4016 # @param name The data source string (directory, filename, etc.).
4017 # @param update Whether to open the data source in update mode.
4018 # @return a new Geo::GDAL::Dataset object.
4019 #*
4020 sub OpenShared {
4021  my @p = @_; # name, update
4022  my @flags = qw/VECTOR SHARED/;
4023  push @flags, qw/UPDATE/ if $p[1];
4024  my $dataset = Geo::GDAL::OpenEx($p[0], \@flags);
4025  error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
4026  return $dataset;
4027 }
4028 
4029 #** @method RELEASE_PARENT()
4030 #*
4031 sub RELEASE_PARENT {
4032 }
4033 
4034 #** @method SetGenerate_DB2_V72_BYTE_ORDER($Generate_DB2_V72_BYTE_ORDER)
4035 # Object method.
4036 # Needed only on IBM DB2.
4037 #*
4038 sub SetGenerate_DB2_V72_BYTE_ORDER {
4039 }
4040 
4041 #** @method SetNonLinearGeometriesEnabledFlag()
4042 #*
4043 sub SetNonLinearGeometriesEnabledFlag {
4044 }
4045 
4046 #** @class Geo::OGR::DataSource
4047 # @brief A vector dataset.
4048 # @details This is a legacy class which should not be
4049 # used in new code. Use Geo::GDAL::Dataset.
4050 #*
4051 package Geo::OGR::DataSource;
4052 
4053 #** @method Geo::GDAL::Dataset Open()
4054 # Package subroutine.
4055 # The same as Geo::OGR::Open
4056 #*
4057 sub Open {
4058 }
4059 
4060 #** @method Geo::GDAL::Dataset OpenShared()
4061 # Package subroutine.
4062 # The same as Geo::OGR::OpenShared
4063 #*
4064 sub OpenShared {
4065 }
4066 
4067 #** @class Geo::OGR::Driver
4068 # @brief A vector format driver.
4069 # @details This is a legacy class which
4070 # should not be used in new code. Use Geo::GDAL::Driver.
4071 #*
4072 package Geo::OGR::Driver;
4073 
4074 use base qw(our /Geo::GDAL::Driver/)
4075 
4076 #** @method Geo::GDAL::Dataset Copy(Geo::GDAL::Dataset source, $name, arrayref options = undef)
4077 # Object method.
4078 # Copy a vector data source into a new data source with this driver.
4079 # @param source The Geo::GDAL::Dataset object to be copied.
4080 # @param name The name for the new data source.
4081 # @param options Driver specific options. In addition to options
4082 # specified in GDAL documentation the option STRICT can be set to 'NO'
4083 # for a more relaxed copy. Otherwise the STRICT is 'YES'.
4084 # @note The order of the first two parameters is different from that in Geo::GDAL::Driver::Copy.
4085 # @return a new Geo::GDAL::Dataset object.
4086 #*
4087 sub Copy {
4088  my ($self, @p) = @_; # src, name, options
4089  my $strict = 1; # the default in bindings
4090  $strict = 0 if $p[2] && $p[2]->{STRICT} eq 'NO';
4091  $self->SUPER::Copy($p[1], $p[0], $strict, @{$p[2..4]}); # path, src, strict, options, cb, cb_data
4092 }
4093 
4094 #** @method Geo::GDAL::Dataset Create($name, hashref options = undef )
4095 # Object method.
4096 # Create a new vector data source using this driver.
4097 # @param name The data source name.
4098 # @param options Driver specific dataset creation options.
4099 #*
4100 sub Create {
4101  my ($self, $name, $options) = @_; # name, options
4102  $options //= {};
4103  $self->SUPER::Create(Name => $name, Width => 0, Height => 0, Bands => 0, Type => 'Byte', Options => $options);
4104 }
4105 
4106 #** @method Open()
4107 # Object method.
4108 # The same as Geo::OGR::Open except that only this driver is allowed.
4109 #*
4110 sub Open {
4111  my $self = shift;
4112  my @p = @_; # name, update
4113  my @flags = qw/VECTOR/;
4114  push @flags, qw/UPDATE/ if $p[1];
4115  my $dataset = Geo::GDAL::OpenEx($p[0], \@flags, [$self->Name()]);
4116  error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
4117  return $dataset;
4118 }
4119 
4120 #** @class Geo::OGR::Feature
4121 # @brief A collection of non-spatial and spatial attributes.
4122 # @details A feature is a collection of non-spatial and spatial attributes and
4123 # an id, which is a special attribute, and data records according to
4124 # this data model. Attributes are called fields and some fields are
4125 # spatial, i.e., their value is a geometry. Fields have at least a
4126 # name and a type. Features may exist within a layer or
4127 # separetely. The data model of a feature is a definition object.
4128 #*
4129 package Geo::OGR::Feature;
4130 
4131 use base qw(Geo::OGR)
4132 
4133 #** @method Geo::OGR::Feature Clone()
4134 # Object method.
4135 # @return a new Geo::OGR::Feature object
4136 #*
4137 sub Clone {
4138 }
4139 
4140 #** @method DumpReadable()
4141 # Object method.
4142 # Write the contents of this feature to stdout.
4143 #*
4144 sub DumpReadable {
4145 }
4146 
4147 #** @method scalar Equal($feature)
4148 # Object method.
4149 # @param feature a Geo::OGR::Feature object for comparison
4150 # @return boolean
4151 #*
4152 sub Equal {
4153 }
4154 
4155 #** @method scalar FID($id)
4156 # Object method.
4157 # @brief Get or set the id of this feature.
4158 # @param id [optional] the id to set for this feature.
4159 # @return integer the id of this feature.
4160 #*
4161 sub FID {
4162  my $self = shift;
4163  $self->SetFID($_[0]) if @_;
4164  return unless defined wantarray;
4165  $self->GetFID;
4166 }
4167 
4168 #** @method Field($name, $value, ...)
4169 # Object method.
4170 # @brief Get, set, or unset the field value.
4171 # @param name the name (or the index) of the field.
4172 # @param value a scalar, a list of scalars or a reference to a
4173 # list. If undef, the field is unset. If a scalar or a list of
4174 # scalars, the field is set from them.
4175 # @note Non-scalar fields (for example Date) can be set either from a
4176 # scalar, which is then assumed to be a string and parsed, or from a
4177 # list of values (for example year, month, day for Date).
4178 # @note Setting and getting Integer64 fields requires 'use bigint' if
4179 # \$Config{ivsize} is smaller than 8, i.e., in a 32 bit machine.
4180 # @return in non-void context the value of the field, which may be a
4181 # scalar or a list, depending on the field type. For unset fields the
4182 # undef value is returned.
4183 #*
4184 sub Field {
4185  my $self = shift;
4186  my $field = $self->GetFieldIndex(shift // 0);
4187  $self->SetField($field, @_) if @_;
4188  $self->GetField($field) if defined wantarray;
4189 }
4190 
4191 #** @method FillUnsetWithDefault()
4192 #*
4193 sub FillUnsetWithDefault {
4194 }
4195 
4196 #** @method Geometry($name, $geometry)
4197 # Object method.
4198 # @brief Get or set the value of a geometry field.
4199 # @note This method delivers the functionality of undocumented methods
4200 # SetGeometry($geometry), SetGeometryDirectly, SetGeomField,
4201 # SetGeomFieldDirectly, GetGeometry, GetGeometryRef.
4202 #
4203 # Set or get the geometry in the feature. When setting, does a check
4204 # against the schema (GeometryType) of the feature. If the parameter
4205 # is a geometry object, it is cloned.
4206 # @param name [optional] the name of the spatial field,
4207 # whose geometry is to be set. If not given, sets or gets the geometry
4208 # of the first (or the single) spatial field.
4209 # @param geometry [optional] a Geo::OGR::Geometry object or a
4210 # reference to a hash from which such can be created (using
4211 # Geo::OGR::Geometry::new).
4212 # @return in a non-void context the indicated geometry in the feature
4213 # as a Geo::OGR::Geometry object. The returned object contains a
4214 # reference to the actual geometry data in the feature (the geometry
4215 # is not cloned) and to the feature object, thus keeping the feature
4216 # object from being destroyed while the geometry object exists.
4217 #*
4218 sub Geometry {
4219  my $self = shift;
4220  my $field = ((@_ > 0 and ref($_[0]) eq '') or (@_ > 2 and @_ % 2 == 1)) ? shift : 0;
4221  $field = $self->GetGeomFieldIndex($field);
4222  my $geometry;
4223  if (@_ and @_ % 2 == 0) {
4224  %$geometry = @_;
4225  } else {
4226  $geometry = shift;
4227  }
4228  if ($geometry) {
4229  my $type = $self->GetDefn->GetGeomFieldDefn($field)->Type;
4230  if (blessed($geometry) and $geometry->isa('Geo::OGR::Geometry')) {
4231  my $gtype = $geometry->GeometryType;
4232  error("The type of the inserted geometry ('$gtype') is not the same as the type of the field ('$type').")
4233  if $type ne 'Unknown' and $type ne $gtype;
4234  eval {
4235  $self->SetGeomFieldDirectly($field, $geometry->Clone);
4236  };
4237  confess last_error() if $@;
4238  } elsif (ref($geometry) eq 'HASH') {
4239  $geometry->{GeometryType} //= $type;
4240  eval {
4241  $geometry = Geo::OGR::Geometry->new($geometry);
4242  };
4243  my $gtype = $geometry->GeometryType;
4244  error("The type of the inserted geometry ('$gtype') is not the same as the type of the field ('$type').")
4245  if $type ne 'Unknown' and $type ne $gtype;
4246  eval {
4247  $self->SetGeomFieldDirectly($field, $geometry);
4248  };
4249  confess last_error() if $@;
4250  } else {
4251  error("Usage: \$feature->Geometry([field],[geometry])");
4252  }
4253  }
4254  return unless defined wantarray;
4255  $geometry = $self->GetGeomFieldRef($field);
4256  return unless $geometry;
4257  keep($geometry, $self);
4258 }
4259 
4260 #** @method Geo::OGR::FeatureDefn GetDefn()
4261 # Object method.
4262 # @note A.k.a GetDefnRef.
4263 # @return a Geo::OGR::FeatureDefn object, which represents the definition of this feature.
4264 #*
4265 sub GetDefn {
4266  my $self = shift;
4267  my $defn = $self->GetDefnRef;
4268  keep($defn, $self);
4269 }
4270 
4271 #** @method scalar GetFID()
4272 # Object method.
4273 # @return the feature id (an integer).
4274 #*
4275 sub GetFID {
4276 }
4277 
4278 #** @method list GetField($name)
4279 # Object method.
4280 # See Field().
4281 #*
4282 sub GetField {
4283  my ($self, $field) = @_;
4284  $field = $self->GetFieldIndex($field);
4285  return unless IsFieldSet($self, $field);
4286  my $type = GetFieldType($self, $field);
4287  return GetFieldAsInteger($self, $field) if $type == $Geo::OGR::OFTInteger;
4288  return GetFieldAsInteger64($self, $field) if $type == $Geo::OGR::OFTInteger64;
4289  return GetFieldAsDouble($self, $field) if $type == $Geo::OGR::OFTReal;
4290  return GetFieldAsString($self, $field) if $type == $Geo::OGR::OFTString;
4291  if ($type == $Geo::OGR::OFTIntegerList) {
4292  my $ret = GetFieldAsIntegerList($self, $field);
4293  return wantarray ? @$ret : $ret;
4294  }
4295  if ($type == $Geo::OGR::OFTInteger64List) {
4296  my $ret = GetFieldAsInteger64List($self, $field);
4297  return wantarray ? @$ret : $ret;
4298  }
4299  if ($type == $Geo::OGR::OFTRealList) {
4300  my $ret = GetFieldAsDoubleList($self, $field);
4301  return wantarray ? @$ret : $ret;
4302  }
4303  if ($type == $Geo::OGR::OFTStringList) {
4304  my $ret = GetFieldAsStringList($self, $field);
4305  return wantarray ? @$ret : $ret;
4306  }
4307  if ($type == $Geo::OGR::OFTBinary) {
4308  return GetFieldAsBinary($self, $field);
4309  }
4310  if ($type == $Geo::OGR::OFTDate) {
4311  my @ret = GetFieldAsDateTime($self, $field);
4312  # year, month, day, hour, minute, second, timezone
4313  return wantarray ? @ret[0..2] : [@ret[0..2]];
4314  }
4315  if ($type == $Geo::OGR::OFTTime) {
4316  my @ret = GetFieldAsDateTime($self, $field);
4317  return wantarray ? @ret[3..6] : [@ret[3..6]];
4318  }
4319  if ($type == $Geo::OGR::OFTDateTime) {
4320  my @ret = GetFieldAsDateTime($self, $field);
4321  return wantarray ? @ret : [@ret];
4322  }
4323  error("Perl bindings do not support the field type '".i2s(field_type => $type)."'.");
4324 }
4325 
4326 #** @method scalar GetFieldDefn($name)
4327 # Object method.
4328 # Get the definition of a field.
4329 # @param name the name of the field.
4330 # @return a Geo::OGR::FieldDefn object.
4331 #*
4332 sub GetFieldDefn {
4333  my $self = shift;
4334  my $field = $self->GetFieldIndex(shift);
4335  return $self->GetFieldDefnRef($field);
4336 }
4337 
4338 #** @method list GetFieldNames()
4339 # Object method.
4340 # Get the names of the fields in this feature.
4341 #*
4342 sub GetFieldNames {
4343 }
4344 
4345 #** @method scalar GetGeomFieldDefn($name)
4346 # Object method.
4347 # Get the definition of a spatial field.
4348 # @param name the name of the spatial field.
4349 # @return a Geo::OGR::GeomFieldDefn object.
4350 #*
4351 sub GetGeomFieldDefn {
4352  my $self = shift;
4353  my $field = $self->GetGeomFieldIndex(shift);
4354  return $self->GetGeomFieldDefnRef($field);
4355 }
4356 
4357 #** @method GetNativeData()
4358 #*
4359 sub GetNativeData {
4360 }
4361 
4362 #** @method GetNativeMediaType()
4363 #*
4364 sub GetNativeMediaType {
4365 }
4366 
4367 #** @method hash reference GetSchema()
4368 # Object method.
4369 # @brief Get the schema of this feature.
4370 #
4371 # @return the schema as a hash whose keywords are Name, StyleIgnored
4372 # and Fields. Fields is an anonymous array of first non-spatial and
4373 # then spatial field schemas as in Geo::OGR::FieldDefn::Schema() and
4374 # Geo::OGR::GeomFieldDefn::Schema().
4375 #*
4376 sub GetSchema {
4377  my $self = shift;
4378  error("Schema of a feature cannot be set directly.") if @_;
4379  return $self->GetDefnRef->Schema;
4380 }
4381 
4382 #** @method scalar GetStyleString()
4383 # Object method.
4384 # @return a string
4385 #*
4386 sub GetStyleString {
4387 }
4388 
4389 #** @method IsFieldNull()
4390 #*
4391 sub IsFieldNull {
4392 }
4393 
4394 #** @method IsFieldSetAndNotNull()
4395 #*
4396 sub IsFieldSetAndNotNull {
4397 }
4398 
4399 #** @method Geo::OGR::Layer Layer()
4400 # Object method.
4401 # @return the layer to which this feature belongs to or undef.
4402 #*
4403 sub Layer {
4404  my $self = shift;
4405  parent($self);
4406 }
4407 
4408 #** @method RELEASE_PARENT()
4409 #*
4410 sub RELEASE_PARENT {
4411  my $self = shift;
4412  unkeep($self);
4413 }
4414 
4415 #** @method hash reference Row(%row)
4416 # Object method.
4417 # @note This method discards the data the destination feature (or
4418 # layer) does not support. Changes in data due to differences between
4419 # field types may also occur.
4420 #
4421 # Get and/or set the data of the feature. The key of the (key,value)
4422 # pairs of the row is the field name. Special field names FID and
4423 # Geometry are used for feature id and (single) geometry
4424 # respectively. The geometry/ies is/are set and get using the
4425 # Geo::OGR::Feature::Geometry method. Field values are set using the
4426 # Geo::OGR::Feature::Field method.
4427 # @param row [optional] feature data in a hash.
4428 # @return a reference to feature data in a hash. Spatial fields are
4429 # returned as Geo::OGR::Geometry objects.
4430 #*
4431 sub Row {
4432  my $self = shift;
4433  my $nf = $self->GetFieldCount;
4434  my $ngf = $self->GetGeomFieldCount;
4435  if (@_) { # update
4436  my %row;
4437  if (@_ == 1 and ref($_[0]) eq 'HASH') {
4438  %row = %{$_[0]};
4439  } elsif (@_ and @_ % 2 == 0) {
4440  %row = @_;
4441  } else {
4442  error('Usage: $feature->Row(%FeatureData).');
4443  }
4444  $self->SetFID($row{FID}) if defined $row{FID};
4445  #$self->Geometry($schema, $row{Geometry}) if $row{Geometry};
4446  for my $name (keys %row) {
4447  next if $name eq 'FID';
4448  if ($name eq 'Geometry') {
4449  $self->Geometry(0, $row{$name});
4450  next;
4451  }
4452  my $f = 0;
4453  for my $i (0..$nf-1) {
4454  if ($self->GetFieldDefnRef($i)->Name eq $name) {
4455  $self->SetField($i, $row{$name});
4456  $f = 1;
4457  last;
4458  }
4459  }
4460  next if $f;
4461  for my $i (0..$ngf-1) {
4462  if ($self->GetGeomFieldDefnRef($i)->Name eq $name) {
4463  $self->Geometry($i, $row{$name});
4464  $f = 1;
4465  last;
4466  }
4467  }
4468  next if $f;
4469  carp "Unknown field: '$name'.";
4470  }
4471  }
4472  return unless defined wantarray;
4473  my %row = ();
4474  for my $i (0..$nf-1) {
4475  my $name = $self->GetFieldDefnRef($i)->Name;
4476  $row{$name} = $self->GetField($i);
4477  }
4478  for my $i (0..$ngf-1) {
4479  my $name = $self->GetGeomFieldDefnRef($i)->Name || 'Geometry';
4480  $row{$name} = $self->GetGeometry($i);
4481  }
4482  $row{FID} = $self->GetFID;
4483  return \%row;
4484 }
4485 
4486 #** @method SetFID($id)
4487 # Object method.
4488 # @param id the feature id.
4489 #*
4490 sub SetFID {
4491 }
4492 
4493 #** @method SetField($name, @Value)
4494 # Object method.
4495 # See Field().
4496 #*
4497 sub SetField {
4498  my $self = shift;
4499  my $field = $self->GetFieldIndex(shift);
4500  my $arg = $_[0];
4501  if (@_ == 0 or !defined($arg)) {
4502  _UnsetField($self, $field);
4503  return;
4504  }
4505  $arg = [@_] if @_ > 1;
4506  my $type = $self->GetFieldType($field);
4507  if (ref($arg)) {
4508  if ($type == $Geo::OGR::OFTIntegerList) {
4509  SetFieldIntegerList($self, $field, $arg);
4510  }
4511  elsif ($type == $Geo::OGR::OFTInteger64List) {
4512  SetFieldInteger64List($self, $field, $arg);
4513  }
4514  elsif ($type == $Geo::OGR::OFTRealList) {
4515  SetFieldDoubleList($self, $field, $arg);
4516  }
4517  elsif ($type == $Geo::OGR::OFTStringList) {
4518  SetFieldStringList($self, $field, $arg);
4519  }
4520  elsif ($type == $Geo::OGR::OFTDate) {
4521  _SetField($self, $field, @$arg[0..2], 0, 0, 0, 0);
4522  }
4523  elsif ($type == $Geo::OGR::OFTTime) {
4524  $arg->[3] //= 0;
4525  _SetField($self, $field, 0, 0, 0, @$arg[0..3]);
4526  }
4527  elsif ($type == $Geo::OGR::OFTDateTime) {
4528  $arg->[6] //= 0;
4529  _SetField($self, $field, @$arg[0..6]);
4530  }
4531  elsif ($type == $Geo::OGR::OFTInteger64)
4532  {
4533  SetFieldInteger64($self, $field, $arg);
4534  }
4535  else {
4536  $type = i2s(field_type => $type);
4537  my $name = $self->GetFieldDefnRef($field)->Name;
4538  error("'$arg' is not a suitable value for field $name($type).");
4539  }
4540  } else {
4541  if ($type == $Geo::OGR::OFTBinary) {
4542  #$arg = unpack('H*', $arg); # remove when SetFieldBinary is available
4543  $self->SetFieldBinary($field, $arg);
4544  }
4545  elsif ($type == $Geo::OGR::OFTInteger64)
4546  {
4547  SetFieldInteger64($self, $field, $arg);
4548  }
4549  elsif ($type == $Geo::OGR::OFTInteger or $type == $Geo::OGR::OFTReal or $type == $Geo::OGR::OFTString)
4550  {
4551  _SetField($self, $field, $arg);
4552  }
4553  else {
4554  $type = i2s(field_type => $type);
4555  my $name = $self->GetFieldDefnRef($field)->Name;
4556  error("'$arg' is not a suitable value for field $name($type).");
4557  }
4558  }
4559 }
4560 
4561 #** @method SetFieldNull()
4562 #*
4563 sub SetFieldNull {
4564 }
4565 
4566 #** @method SetFrom($other, $forgiving = 1, hashref map)
4567 # Object method.
4568 # @param other a Geo::OGR::Feature object
4569 # @param forgiving [optional] set to false if the operation should not
4570 # continue if output fields do not match some of the source fields
4571 # @param map [optional] a mapping from output field indexes to source
4572 # fields, include into the hash all field indexes of this feature
4573 # which should be set
4574 #*
4575 sub SetFrom {
4576  my($self, $other) = @_;
4577  _SetFrom($self, $other), return if @_ <= 2;
4578  my $forgiving = $_[2];
4579  _SetFrom($self, $other, $forgiving), return if @_ <= 3;
4580  my $map = $_[3];
4581  my @list;
4582  for my $i (1..GetFieldCount($self)) {
4583  push @list, ($map->{$i} || -1);
4584  }
4585  SetFromWithMap($self, $other, 1, \@list);
4586 }
4587 
4588 #** @method SetNativeData()
4589 #*
4590 sub SetNativeData {
4591 }
4592 
4593 #** @method SetNativeMediaType()
4594 #*
4595 sub SetNativeMediaType {
4596 }
4597 
4598 #** @method SetStyleString($string)
4599 # Object method.
4600 # @param string
4601 #*
4602 sub SetStyleString {
4603 }
4604 
4605 #** @method list Tuple(@tuple)
4606 # Object method.
4607 # @note This method discards the data the destination feature (or
4608 # layer) does not support. Changes in data due to differences between
4609 # field types may also occur.
4610 #
4611 # @note The schema of the tuple needs to be the same as that of the
4612 # feature.
4613 #
4614 # Get and/set the data of the feature. The expected data in the tuple
4615 # is ([feature_id,] non-spatial fields, spatial fields). The fields in
4616 # the tuple are in the order they are in the schema. Field values are
4617 # set using the Geo::OGR::Feature::Field method. Geometries are set
4618 # and get using the Geo::OGR::Feature::Geometry method.
4619 # @param tuple [optional] feature data in an array
4620 # @return feature data in an array
4621 #*
4622 sub Tuple {
4623  my $self = shift;
4624  my $nf = $self->GetFieldCount;
4625  my $ngf = $self->GetGeomFieldCount;
4626  if (@_) {
4627  my $values = ref $_[0] ? $_[0] : \@_;
4628  my $FID;
4629  $FID = shift @$values if @$values == $nf + $ngf + 1;
4630  $self->SetFID($FID) if defined $FID;
4631  if (@$values != $nf + $ngf) {
4632  my $n = $nf + $ngf;
4633  error("Too many or too few attribute values for a feature (need $n).");
4634  }
4635  my $index = 0; # index to non-geometry and geometry fields
4636  for my $i (0..$nf-1) {
4637  $self->SetField($i, $values->[$i]);
4638  }
4639  for my $i (0..$ngf-1) {
4640  $self->Geometry($i, $values->[$nf+$i]);
4641  }
4642  }
4643  return unless defined wantarray;
4644  my @ret = ($self->GetFID);
4645  for my $i (0..$nf-1) {
4646  my $v = $self->GetField($i);
4647  push @ret, $v;
4648  }
4649  for my $i (0..$ngf-1) {
4650  my $v = $self->GetGeometry($i);
4651  push @ret, $v;
4652  }
4653  return @ret;
4654 }
4655 
4656 #** @method scalar Validate(list flags)
4657 # Object method.
4658 # @param flags one of more of null, geom_type, width,
4659 # allow_null_when_default, or all.
4660 # @exception croaks with an error message if the feature is not valid.
4661 # @return integer denoting the validity of the feature object.
4662 #*
4663 sub Validate {
4664  my $self = shift;
4665  my $flags = 0;
4666  for my $flag (@_) {
4667  my $f = eval '$Geo::OGR::'.uc($flag);
4668  $flags |= $f;
4669  }
4670  _Validate($self, $flags);
4671 }
4672 
4673 #** @method Geo::OGR::Feature new(%schema)
4674 # Class method.
4675 # @brief Create a new feature.
4676 # @param Named parameters:
4677 # - \a Schema a reference to a schema hash, or a Geo::OGR::Layer,
4678 # Geo::OGR::Feature, or Geo::OGR::FeatureDefn object.
4679 # - \a Values values for the feature attributes.
4680 # - \a StyleIgnored whether the style can be omitted when fetching
4681 # features. (default is false)
4682 #
4683 # Schema is a hash with the following keys:
4684 # - \a Name name of the schema (not used).
4685 # - \a Fields a list of Geo::OGR::FieldDefn or Geo::OGR::GeomFieldDefn
4686 # objects or references to hashes from which fields can be created.
4687 # - \a GeometryType the geometry type if the feature has only one spatial field.
4688 #
4689 # @note Do not mix GeometryType and geometry fields in Fields list.
4690 # @note Old syntax where the argument is a Geo::OGR::FeatureDefn
4691 # object or Schema hash is supported.
4692 #
4693 # @return a new Geo::OGR::Feature object.
4694 #*
4695 sub new {
4696  my $pkg = shift;
4697  my $arg;
4698  if (ref $_[0]) {
4699  if (ref $_[0] eq 'HASH' && $_[0]->{Schema}) {
4700  $arg = $_[0];
4701  } else {
4702  $arg = {Schema => $_[0]};
4703  }
4704  } elsif (@_ and @_ % 2 == 0) {
4705  %$arg = @_;
4706  unless ($arg->{Schema}) {
4707  my %tmp = @_;
4708  $arg->{Schema} = \%tmp;
4709  }
4710  } else {
4711  error("The argument must be either a schema or a hash.");
4712  }
4713  error("Missing schema.") unless $arg->{Schema};
4714  my $defn;
4715  for (ref $arg->{Schema}) {
4716  (/Geo::OGR::Layer$/ || /Geo::OGR::Feature$/) && do {
4717  $defn = $arg->{Schema}->GetDefn;
4718  last;
4719  };
4720  /Geo::OGR::FeatureDefn$/ && do {
4721  $defn = $arg->{Schema};
4722  last;
4723  };
4724  $defn = Geo::OGR::FeatureDefn->new($arg->{Schema});
4725  }
4726  my $self = Geo::OGRc::new_Feature($defn);
4727  error("Feature creation failed.") unless $self;
4728  bless $self, $pkg;
4729  for (ref $arg->{Values}) {
4730  /ARRAY/ && do {
4731  $self->Tuple($arg->{Values});
4732  last;
4733  };
4734  /HASH/ && do {
4735  $self->Row($arg->{Values});
4736  last;
4737  };
4738  /Geo::OGR::Feature$/ && do {
4739  $self->Tuple($arg->{Values}->Tuple);
4740  last;
4741  };
4742  /^$/ && do {
4743  last;
4744  };
4745  error("Value parameter must be an array, hash, or another feature. Not $_.");
4746  }
4747  return $self;
4748 }
4749 
4750 #** @class Geo::OGR::FeatureDefn
4751 # @brief The schema of a feature or a layer.
4752 # @details A FeatureDefn object is a collection of field definition objects. A
4753 # read-only FeatureDefn object can be obtained from a layer
4754 # (Geo::OGR::Layer::GetDefn()) or a feature
4755 # (Geo::OGR::Feature::GetDefn()).
4756 #*
4757 package Geo::OGR::FeatureDefn;
4758 
4759 use base qw(Geo::OGR)
4760 
4761 #** @method AddField(%params)
4762 # Object method.
4763 # @param params Named parameters to create a new Geo::OGR::FieldDefn
4764 # or Geo::OGR::GeomFieldDefn object.
4765 #*
4766 sub AddField {
4767  my $self = shift;
4768  error("Read-only definition.") if parent($self);
4769  my %params;
4770  if (@_ == 0) {
4771  } elsif (ref($_[0]) eq 'HASH') {
4772  %params = %{$_[0]};
4773  } elsif (@_ % 2 == 0) {
4774  %params = @_;
4775  }
4776  $params{Type} //= '';
4777  if (s_exists(field_type => $params{Type})) {
4778  my $fd = Geo::OGR::FieldDefn->new(%params);
4779  $self->AddFieldDefn($fd);
4780  } else {
4781  my $fd = Geo::OGR::GeomFieldDefn->new(%params);
4782  $self->AddGeomFieldDefn($fd);
4783  }
4784 }
4785 
4786 #** @method DeleteField($name)
4787 # Object method.
4788 # @note Currently only geometry fields can be deleted.
4789 # @param index the index of the geometry field to be deleted.
4790 #*
4791 sub DeleteField {
4792  my ($self, $name) = @_;
4793  error("Read-only definition.") if parent($self);
4794  for my $i (0..$self->GetFieldCount-1) {
4795  error("Non-spatial fields cannot be deleted.") if $self->_GetFieldDefn($i)->Name eq $name;
4796  }
4797  for my $i (0..$self->GetGeomFieldCount-1) {
4798  $self->DeleteGeomFieldDefn($i) if $self->_GetGeomFieldDefn($i)->Name eq $name;
4799  }
4800  error(2, $name, 'Field');
4801 }
4802 
4803 #** @method Feature()
4804 #*
4805 sub Feature {
4806  my $self = shift;
4807  return parent($self);
4808 }
4809 
4810 #** @method scalar GetFieldDefn($name)
4811 # Object method.
4812 # Get the definition of a field.
4813 # @param name the name of the field.
4814 # @return a Geo::OGR::FieldDefn object.
4815 #*
4816 sub GetFieldDefn {
4817  my $self = shift;
4818  my $field = $self->GetFieldIndex(shift);
4819  return $self->_GetFieldDefn($field);
4820 }
4821 
4822 #** @method list GetFieldNames()
4823 # Object method.
4824 # The names of the fields in this layer or feature definition.
4825 # @return the list of field names.
4826 #*
4827 sub GetFieldNames {
4828  my $self = shift;
4829  my @names = ();
4830  for my $i (0..$self->GetFieldCount-1) {
4831  push @names, $self->_GetFieldDefn($i)->Name;
4832  }
4833  for my $i (0..$self->GetGeomFieldCount-1) {
4834  push @names, $self->_GetGeomFieldDefn($i)->Name;
4835  }
4836  return @names;
4837 }
4838 
4839 #** @method scalar GetGeomFieldDefn($name)
4840 # Object method.
4841 # Get the definition of a spatial field.
4842 # @param name the name of the spatial field.
4843 # @return a Geo::OGR::GeomFieldDefn object.
4844 #*
4845 sub GetGeomFieldDefn {
4846  my $self = shift;
4847  my $field = $self->GetGeomFieldIndex(shift);
4848  return $self->_GetGeomFieldDefn($field);
4849 }
4850 
4851 #** @method scalar GetName()
4852 # Object method.
4853 # @return the name of this layer or feature definition.
4854 #*
4855 sub GetName {
4856 }
4857 
4858 #** @method hash reference GetSchema()
4859 # Object method.
4860 # @brief Get the schema of this feature or layer definition.
4861 #
4862 # @return the schema as a hash whose keywords are Name, StyleIgnored
4863 # and Fields. Fields is an anonymous array of first non-spatial and
4864 # then spatial field schemas as in Geo::OGR::FieldDefn::Schema() and
4865 # Geo::OGR::GeomFieldDefn::Schema().
4866 #*
4867 sub GetSchema {
4868  my $self = shift;
4869  carp "Schema of a feature definition should not be set directly." if @_;
4870  if (@_ and @_ % 2 == 0) {
4871  my %schema = @_;
4872  if ($schema{Fields}) {
4873  for my $field (@{$schema{Fields}}) {
4874  $self->AddField($field);
4875  }
4876  }
4877  }
4878  my %schema;
4879  $schema{Name} = $self->Name();
4880  $schema{StyleIgnored} = $self->StyleIgnored();
4881  $schema{Fields} = [];
4882  for my $i (0..$self->GetFieldCount-1) {
4883  my $s = $self->_GetFieldDefn($i)->Schema;
4884  push @{$schema{Fields}}, $s;
4885  }
4886  for my $i (0..$self->GetGeomFieldCount-1) {
4887  my $s = $self->_GetGeomFieldDefn($i)->Schema;
4888  push @{$schema{Fields}}, $s;
4889  }
4890  return wantarray ? %schema : \%schema;
4891 }
4892 
4893 #** @method IsSame(Geo::OGR::FeatureDefn defn)
4894 # Object method.
4895 # @return true if this definition is similar to the other definition,
4896 # false otherwise.
4897 #*
4898 sub IsSame {
4899 }
4900 
4901 #** @method scalar IsStyleIgnored()
4902 # Object method.
4903 # Get the ignore status of style information when fetching features.
4904 # @return the ignore status of style information
4905 # @since 1.9.0
4906 #*
4907 sub IsStyleIgnored {
4908 }
4909 
4910 #** @method RELEASE_PARENT()
4911 #*
4912 sub RELEASE_PARENT {
4913  my $self = shift;
4914  unkeep($self);
4915 }
4916 
4917 #** @method SetStyleIgnored($IgnoreState)
4918 # Object method.
4919 # Set the ignore status of style information when fetching features.
4920 # @since 1.9.0
4921 #*
4922 sub SetStyleIgnored {
4923 }
4924 
4925 #** @method Geo::OGR::FeatureDefn new(%schema)
4926 # Class method.
4927 # Creates a new layer or feature definition. The new definition is
4928 # either initialized to the given schema or it will contain no
4929 # non-spatial fields and one spatial field, whose Name is '' and
4930 # GeometryType is 'Unknown' or the value of the named parameter
4931 # GeometryType.
4932 # @param schema [optional] The schema for the new feature definition,
4933 # as in Geo::OGR::FeatureDefn::Schema().
4934 # @return a Geo::OGR::FeatureDefn object
4935 #
4936 # Example usage:
4937 # \code
4938 # $fd = Geo::OGR::FeatureDefn->new(
4939 # Name => "name",
4940 # Fields => [{ Name => 'field1', Type => 'String' },
4941 # { Name => 'geom', GeometryType => 'Point' }] );
4942 # \endcode
4943 #*
4944 sub new {
4945  my $pkg = shift;
4946  my %schema;
4947  if (@_ == 1 and ref($_[0]) eq 'HASH') {
4948  %schema = %{$_[0]};
4949  } elsif (@_ and @_ % 2 == 0) {
4950  %schema = @_;
4951  }
4952  my $fields = $schema{Fields};
4953  error("The 'Fields' argument must be an array reference.") if $fields and ref($fields) ne 'ARRAY';
4954  $schema{Name} //= '';
4955  my $self = Geo::OGRc::new_FeatureDefn($schema{Name});
4956  bless $self, $pkg;
4957  my $gt = $schema{GeometryType};
4958  if ($gt) {
4959  $self->GeometryType($gt);
4960  } elsif ($fields) {
4961  $self->DeleteGeomFieldDefn(0);
4962  }
4963  $self->StyleIgnored($schema{StyleIgnored}) if exists $schema{StyleIgnored};
4964  for my $fd (@{$fields}) {
4965  my $d = $fd;
4966  if (ref($fd) eq 'HASH') {
4967  # if Name and Type are missing, assume Name => Type
4968  if (!(exists $fd->{Name} && exists $fd->{Type})) {
4969  for my $key (sort keys %$fd) {
4970  if (s_exists(field_type => $fd->{$key}) ||
4971  s_exists(geometry_type => $fd->{$key}))
4972  {
4973  $fd->{Name} = $key;
4974  $fd->{Type} = $fd->{$key};
4975  delete $fd->{$key};
4976  last;
4977  }
4978  }
4979  }
4980  if ($fd->{GeometryType} or ($fd->{Type} && s_exists(geometry_type => $fd->{Type}))) {
4981  $d = Geo::OGR::GeomFieldDefn->new(%$fd);
4982  } else {
4983  $d = Geo::OGR::FieldDefn->new(%$fd);
4984  }
4985  }
4986  if (blessed($d) and $d->isa('Geo::OGR::FieldDefn')) {
4987  AddFieldDefn($self, $d);
4988  } elsif (blessed($d) and $d->isa('Geo::OGR::GeomFieldDefn')) {
4989  error("Do not mix GeometryType and geometry fields in Fields.") if $gt;
4990  AddGeomFieldDefn($self, $d);
4991  } else {
4992  error("Item in field list does not define a field.");
4993  }
4994  }
4995  return $self;
4996 }
4997 
4998 #** @class Geo::OGR::FieldDefn
4999 # @brief A definition of a non-spatial attribute.
5000 # @details
5001 #*
5002 package Geo::OGR::FieldDefn;
5003 
5004 use base qw(Geo::OGR)
5005 
5006 #** @method scalar Default($value)
5007 # Object method.
5008 # Get or set the default value for this field.
5009 # @note a.k.a. GetDefault and SetDefault
5010 # @param value [optional]
5011 # @return the default value of this field in non-void context.
5012 #*
5013 sub Default {
5014  my $self = shift;
5015  SetDefault($self, $_[0]) if @_;
5016  GetDefault($self) if defined wantarray;
5017 }
5018 
5019 #** @method GetSchema()
5020 #*
5021 sub GetSchema {
5022 }
5023 
5024 #** @method scalar Ignored($ignore)
5025 # Object method.
5026 # Get and/or set the ignore status (whether this field should be
5027 # omitted when fetching features) of this field.
5028 # @note a.k.a. IsIgnored, SetIgnored
5029 # @param ignore [optional]
5030 # @return the ignore status of this field in non-void context.
5031 # @since 1.9.0
5032 #*
5033 sub Ignored {
5034  my $self = shift;
5035  SetIgnored($self, $_[0]) if @_;
5036  IsIgnored($self) if defined wantarray;
5037 }
5038 
5039 #** @method IsDefaultDriverSpecific()
5040 #*
5041 sub IsDefaultDriverSpecific {
5042 }
5043 
5044 #** @method scalar Justify($justify)
5045 # Object method.
5046 # Get and/or set the justification of this field.
5047 # @note a.k.a. GetJustify, SetJustify
5048 # @param justify [optional] One of field justify types (Geo::OGR::FieldDefn::JustifyValues).
5049 # @return the justify value of this field in non-void context.
5050 #*
5051 sub Justify {
5052  my($self, $justify) = @_;
5053  if (defined $justify) {
5054  $justify = s2i(justify => $justify);
5055  SetJustify($self, $justify);
5056  }
5057  return i2s(justify => GetJustify($self)) if defined wantarray;
5058 }
5059 
5060 #** @method list JustifyValues()
5061 # Package subroutine.
5062 # Justify values supported by GDAL. Current list is
5063 # Left, Right, and Undefined.
5064 #*
5065 sub JustifyValues {
5066  return @JUSTIFY;
5067 }
5068 
5069 #** @method scalar Name($name)
5070 # Object method.
5071 # Get and/or set the name of the field.
5072 # @note a.k.a. GetName, GetNameRef, SetName
5073 # @param name [optional]
5074 # @return the name in non-void context
5075 #*
5076 sub Name {
5077  my $self = shift;
5078  SetName($self, $_[0]) if @_;
5079  GetName($self) if defined wantarray;
5080 }
5081 
5082 #** @method scalar Nullable($nullable)
5083 # Object method.
5084 # Get or set the nullable constraint for this field.
5085 # @note a.k.a. IsNullable and SetNullable
5086 # @param nullable [optional]
5087 # @return the nullable value of this field in non-void context.
5088 #*
5089 sub Nullable {
5090  my $self = shift;
5091  SetNullable($self, $_[0]) if @_;
5092  IsNullable($self) if defined wantarray;
5093 }
5094 
5095 #** @method scalar Precision($precision)
5096 # Object method.
5097 # Get and/or set the precision of this field.
5098 # @note a.k.a. GetPrecision, SetPrecision
5099 # @param precision [optional]
5100 # @return the precision of this field in non-void context.
5101 #*
5102 sub Precision {
5103  my $self = shift;
5104  SetPrecision($self, $_[0]) if @_;
5105  GetPrecision($self) if defined wantarray;
5106 }
5107 
5108 #** @method hash reference Schema(%params)
5109 # Object method.
5110 # Get the schema or set parts of the schema
5111 # @param params [optional] as those in Geo::OGR::FieldDefn::new.
5112 # @return a reference to a hash whose keys are as those in Geo::OGR::FieldDefn::new.
5113 #*
5114 sub Schema {
5115  my $self = shift;
5116  if (@_) {
5117  my $params = @_ % 2 == 0 ? {@_} : shift;
5118  for my $key (keys %SCHEMA_KEYS) {
5119  next unless exists $params->{$key};
5120  eval "\$self->$key(\$params->{$key})";
5121  confess(last_error()) if $@;
5122  }
5123  }
5124  return unless defined wantarray;
5125  my %schema = ();
5126  for my $key (keys %SCHEMA_KEYS) {
5127  $schema{$key} = eval '$self->'.$key;
5128  }
5129  return wantarray ? %schema : \%schema;
5130 }
5131 
5132 #** @method SetSchema()
5133 #*
5134 sub SetSchema {
5135 }
5136 
5137 #** @method scalar SubType($SubType)
5138 # Object method.
5139 # @note a.k.a. GetSubType, SetSubType
5140 # @param SubType [optional] One of field sub types (Geo::OGR::FieldDefn::SubTypes).
5141 # @return the sub type of this field in non-void context.
5142 #*
5143 sub SubType {
5144  my($self, $subtype) = @_;
5145  if (defined $subtype) {
5146  $subtype = s2i(field_subtype => $subtype);
5147  SetSubType($self, $subtype);
5148  }
5149  return i2s(field_subtype => GetSubType($self)) if defined wantarray;
5150 }
5151 
5152 #** @method SubTypes()
5153 #*
5154 sub SubTypes {
5155  return @SUBTYPES;
5156 }
5157 
5158 #** @method scalar Type($type)
5159 # Object method.
5160 # Get and/or set the type of the field.
5161 # @note a.k.a. GetFieldTypeName, GetTypeName, GetType, SetType
5162 # @param type [optional] One of field types (Geo::OGR::FieldDefn::Types).
5163 # @return one of field types in non-void context.
5164 #*
5165 sub Type {
5166  my($self, $type) = @_;
5167  if (defined $type) {
5168  $type = s2i(field_type => $type);
5169  SetType($self, $type);
5170  }
5171  return i2s(field_type => GetType($self)) if defined wantarray;
5172 }
5173 
5174 #** @method list Types()
5175 # Package subroutine.
5176 # Field types supported by GDAL. Current list is
5177 # Binary, Date, DateTime, Integer, Integer64, Integer64List, IntegerList, Real, RealList, String, StringList, Time, WideString, and WideStringList.
5178 # (However, WideString is not supported.)
5179 #*
5180 sub Types {
5181  return @TYPES;
5182 }
5183 
5184 #** @method scalar Width($width)
5185 # Object method.
5186 # Get and/or set the field width.
5187 # @note a.k.a. GetWidth, SetWidth
5188 # @param width [optional]
5189 # @return the width of this field in non-void context.
5190 #*
5191 sub Width {
5192  my $self = shift;
5193  SetWidth($self, $_[0]) if @_;
5194  GetWidth($self) if defined wantarray;
5195 }
5196 
5197 #** @method Geo::OGR::FieldDefn new(%params)
5198 # Class method.
5199 # @brief Create a new field definition.
5200 #
5201 # @param Named parameters:
5202 # - \a Name Field name (default is 'unnamed').
5203 # - \a Type Field type, one of Geo::OGR::FieldDefn::Types (default is 'String').
5204 # - \a SubType Field sub type, one of Geo::OGR::FieldDefn::SubTypes.
5205 # - \a Justify Justify value, one of Geo::OGR::FieldDefn::JustifyValues
5206 # - \a Width
5207 # - \a Precision
5208 # - \a Nullable (default is true)
5209 # - \a Default
5210 # - \a Ignored (default is false)
5211 #
5212 # @note Simplified parameters <name> => <type> is also supported.
5213 #
5214 # @return a new Geo::OGR::FieldDefn object
5215 #*
5216 sub new {
5217  my $pkg = shift;
5218  my $params = {Name => 'unnamed', Type => 'String'};
5219  if (@_ == 0) {
5220  } elsif (@_ == 1 and not ref $_[0]) {
5221  $params->{Name} = shift;
5222  } elsif (@_ == 2 and not $Geo::OGR::FieldDefn::SCHEMA_KEYS{$_[0]}) {
5223  $params->{Name} = shift;
5224  $params->{Type} = shift;
5225  } else {
5226  my $tmp = @_ % 2 == 0 ? {@_} : shift;
5227  for my $key (keys %$tmp) {
5228  if ($Geo::OGR::FieldDefn::SCHEMA_KEYS{$key}) {
5229  $params->{$key} = $tmp->{$key};
5230  } else {
5231  carp "Unknown parameter: '$key'." if $key ne 'Index';
5232  }
5233  }
5234  }
5235  $params->{Type} = s2i(field_type => $params->{Type});
5236  my $self = Geo::OGRc::new_FieldDefn($params->{Name}, $params->{Type});
5237  bless $self, $pkg;
5238  delete $params->{Name};
5239  delete $params->{Type};
5240  $self->Schema($params);
5241  return $self;
5242 }
5243 
5244 #** @class Geo::OGR::GeomFieldDefn
5245 # @brief A definition of a spatial attribute.
5246 # @details
5247 #*
5248 package Geo::OGR::GeomFieldDefn;
5249 
5250 use base qw(Geo::OGR)
5251 
5252 #** @method scalar GeometryType($type)
5253 # Object method.
5254 # @note a.k.a. GetType, SetType
5255 # @return the geometry type of the field.
5256 #*
5257 sub GeometryType {
5258 }
5259 
5260 #** @method GetSchema()
5261 #*
5262 sub GetSchema {
5263 }
5264 
5265 #** @method scalar Ignored($ignore)
5266 # Object method.
5267 # @note a.k.a. IsIgnored, SetIgnored
5268 # @return the ignore status of the field.
5269 #*
5270 sub Ignored {
5271  my $self = shift;
5272  SetIgnored($self, $_[0]) if @_;
5273  IsIgnored($self) if defined wantarray;
5274 }
5275 
5276 #** @method scalar Name($name)
5277 # Object method.
5278 # @note a.k.a. GetName, GetNameRef, SetName
5279 # @return the name of the field.
5280 #*
5281 sub Name {
5282  my $self = shift;
5283  SetName($self, $_[0]) if @_;
5284  GetName($self) if defined wantarray;
5285 }
5286 
5287 #** @method scalar Nullable($nullable)
5288 # Object method.
5289 # @note a.k.a. IsNullable, SetNullable
5290 # @return the nullable status of the field.
5291 #*
5292 sub Nullable {
5293  my $self = shift;
5294  SetNullable($self, $_[0]) if @_;
5295  IsNullable($self) if defined wantarray;
5296 }
5297 
5298 #** @method hash reference Schema(%params)
5299 # Object method.
5300 # Get the schema or set parts of the schema.
5301 # @param params [optional] as those in Geo::OGR::GeomFieldDefn::new.
5302 # @return a reference to a hash whose keys are as those in Geo::OGR::GeomFieldDefn::new.
5303 #*
5304 sub Schema {
5305  my $self = shift;
5306  if (@_) {
5307  my $params = @_ % 2 == 0 ? {@_} : shift;
5308  for my $key (keys %SCHEMA_KEYS) {
5309  next unless exists $params->{$key};
5310  eval "\$self->$key(\$params->{$key})";
5311  confess last_error() if $@;
5312  }
5313  }
5314  return unless defined wantarray;
5315  my %schema = ();
5316  for my $key (keys %SCHEMA_KEYS) {
5317  $schema{$key} = eval '$self->'.$key;
5318  }
5319  return wantarray ? %schema : \%schema;
5320 }
5321 
5322 #** @method SetSchema()
5323 #*
5324 sub SetSchema {
5325 }
5326 
5327 #** @method scalar SpatialReference($sr)
5328 # Object method.
5329 # @note a.k.a. GetSpatialRef, SetSpatialRef
5330 # @return the spatial reference of the field as a Geo::OSR::SpatialReference object.
5331 #*
5332 sub SpatialReference {
5333  my $self = shift;
5334  SetSpatialRef($self, $_[0]) if @_;
5335  GetSpatialRef($self) if defined wantarray;
5336 }
5337 
5338 #** @method Type()
5339 # Object method.
5340 # @return the type of this geometry field. One of Geo::OGR::GeomFieldDefn::Types
5341 #*
5342 sub Type {
5343  my($self, $type) = @_;
5344  if (defined $type) {
5345  $type = s2i(geometry_type => $type);
5346  SetType($self, $type);
5347  }
5348  i2s(geometry_type => GetType($self)) if defined wantarray;
5349 }
5350 
5351 #** @method Types()
5352 # Package subroutine.
5353 # @return a list of all geometry types, currently:
5354 # CircularString, CircularStringM, CircularStringZ, CircularStringZM, CompoundCurve, CompoundCurveM, CompoundCurveZ, CompoundCurveZM, Curve, CurveM, CurvePolygon, CurvePolygonM, CurvePolygonZ, CurvePolygonZM, CurveZ, CurveZM, GeometryCollection, GeometryCollection25D, GeometryCollectionM, GeometryCollectionZM, LineString, LineString25D, LineStringM, LineStringZM, LinearRing, MultiCurve, MultiCurveM, MultiCurveZ, MultiCurveZM, MultiLineString, MultiLineString25D, MultiLineStringM, MultiLineStringZM, MultiPoint, MultiPoint25D, MultiPointM, MultiPointZM, MultiPolygon, MultiPolygon25D, MultiPolygonM, MultiPolygonZM, MultiSurface, MultiSurfaceM, MultiSurfaceZ, MultiSurfaceZM, None, Point, Point25D, PointM, PointZM, Polygon, Polygon25D, PolygonM, PolygonZM, PolyhedralSurface, PolyhedralSurfaceM, PolyhedralSurfaceZ, PolyhedralSurfaceZM, Surface, SurfaceM, SurfaceZ, SurfaceZM, TIN, TINM, TINZ, TINZM, Triangle, TriangleM, TriangleZ, TriangleZM, and Unknown.
5355 #*
5356 sub Types {
5358 }
5359 
5360 #** @method Geo::OGR::GeomFieldDefn new(%params)
5361 # Class method.
5362 # @brief Create a new spatial field definition.
5363 #
5364 # @param params one or more of:
5365 # - \a Name name for the field (default is 'geom').
5366 # - \a GeometryType type for the field type, one of Geo::OGR::GeomFieldDefn::Types (default is 'Unknown').
5367 # - \a SpatialReference a Geo::OSR::SpatialReference object.
5368 # - \a Nullable (default is true)
5369 # - \a Ignored (default is false)
5370 #
5371 # @note Simplified parameters <name> => <type> is also supported.
5372 #
5373 # @return a new Geo::OGR::GeomFieldDefn object
5374 #*
5375 sub new {
5376  my $pkg = shift;
5377  my $params = {Name => 'geom', Type => 'Unknown'};
5378  if (@_ == 0) {
5379  } elsif (@_ == 1) {
5380  $params->{Name} = shift;
5381  } elsif (@_ == 2 and not $Geo::OGR::GeomFieldDefn::SCHEMA_KEYS{$_[0]}) {
5382  $params->{Name} = shift;
5383  $params->{Type} = shift;
5384  } else {
5385  my $tmp = @_ % 2 == 0 ? {@_} : shift;
5386  for my $key (keys %$tmp) {
5387  if ($Geo::OGR::GeomFieldDefn::SCHEMA_KEYS{$key}) {
5388  $params->{$key} = $tmp->{$key};
5389  } else {
5390  carp "Unknown parameter: '$key'." if $key ne 'Index' && $key ne 'GeometryType';
5391  }
5392  }
5393  $params->{Type} //= $tmp->{GeometryType};
5394  }
5395  $params->{Type} = s2i(geometry_type => $params->{Type});
5396  my $self = Geo::OGRc::new_GeomFieldDefn($params->{Name}, $params->{Type});
5397  bless $self, $pkg;
5398  delete $params->{Name};
5399  delete $params->{Type};
5400  $self->Schema($params);
5401  return $self;
5402 }
5403 
5404 #** @class Geo::OGR::Geometry
5405 # @brief Spatial data.
5406 # @details A geometry is spatial data (coordinate values, and a reference to a
5407 # spatial reference system) organized into one of the geometry
5408 # types. Geometries can be created from several type of data including
5409 # a Perl data structure. There are several methods, which modify,
5410 # compare, test, or compute values from geometries.
5411 # @note Most spatial analysis methods require <a
5412 # href="http://geos.osgeo.org/doxygen/">GEOS</a> to work rigorously.
5413 #*
5414 package Geo::OGR::Geometry;
5415 
5416 use base qw(Geo::OGR)
5417 
5418 #** @method AddGeometry($other)
5419 # Object method.
5420 # Add a copy of another geometry to a geometry collection
5421 # @param other a Geo::OGR::Geometry object
5422 #*
5423 sub AddGeometry {
5424 }
5425 
5426 #** @method AddGeometryDirectly($other)
5427 # Object method.
5428 # @param other a Geo::OGR::Geometry object
5429 #*
5430 sub AddGeometryDirectly {
5431 }
5432 
5433 #** @method AddPoint($x, $y, $z)
5434 # Object method.
5435 # Set the data of a point or add a point to a line string. Consider
5436 # using Geo::OGR::Geometry::Points. Note that the coordinate
5437 # dimension is automatically upgraded to 25D (3) if z is given.
5438 # @param x
5439 # @param y
5440 # @param z [optional]
5441 # Calls internally the 2D or 3D version depending on the number of parameters.
5442 #*
5443 sub AddPoint {
5444  my $self = shift;
5445  my $t = $self->GetGeometryType;
5446  my $has_z = HasZ($t);
5447  my $has_m = HasM($t);
5448  if (!$has_z && !$has_m) {
5449  $self->AddPoint_2D(@_[0..1]);
5450  } elsif ($has_z && !$has_m) {
5451  $self->AddPoint_3D(@_[0..2]);
5452  } elsif (!$has_z && $has_m) {
5453  $self->AddPointM(@_[0..2]);
5454  } else {
5455  $self->AddPointZM(@_[0..3]);
5456  }
5457 }
5458 
5459 #** @method AddPointM()
5460 #*
5461 sub AddPointM {
5462 }
5464 #** @method AddPointZM()
5465 #*
5466 sub AddPointZM {
5467 }
5468 
5469 #** @method AddPoint_2D($x, $y)
5470 # Object method.
5471 # Set the data of a point or add a point to a line string. Consider
5472 # using Geo::OGR::Geometry::Points.
5473 # @param x
5474 # @param y
5475 #*
5476 sub AddPoint_2D {
5477 }
5478 
5479 #** @method AddPoint_3D($x, $y, $z)
5480 # Object method.
5481 # Set the data of a point or add a point to a line string. Note that
5482 # the coordinate dimension is automatically upgraded to 25D (3). Consider
5483 # using Geo::OGR::Geometry::Points.
5484 # @param x
5485 # @param y
5486 # @param z
5487 #*
5488 sub AddPoint_3D {
5489 }
5490 
5491 #** @method Geo::OGR::Geometry ApproximateArcAngles(%params)
5492 # Package subroutine.
5493 # Create a line string, which approximates an arc.
5494 # @note All angles are in degrees.
5495 #
5496 # @param %params Named parameters:
5497 # - \a Center center point (default is [0, 0, 0])
5498 # - \a PrimaryRadius default is 1.
5499 # - \a SecondaryAxis default is 1.
5500 # - \a Rotation default is 0.
5501 # - \a StartAngle default is 0.
5502 # - \a EndAngle default is 360.
5503 # - \a MaxAngleStepSizeDegrees default is 4.
5504 # @return a new Geo::OGR::Geometry object.
5505 #*
5506 sub ApproximateArcAngles {
5507  my %p = @_;
5508  my %default = ( Center => [0,0,0],
5509  PrimaryRadius => 1,
5510  SecondaryAxis => 1,
5511  Rotation => 0,
5512  StartAngle => 0,
5513  EndAngle => 360,
5514  MaxAngleStepSizeDegrees => 4
5515  );
5516  for my $p (keys %p) {
5517  if (exists $default{$p}) {
5518  $p{$p} //= $default{$p};
5519  } else {
5520  carp "Unknown parameter: '$p'.";
5521  }
5522  }
5523  for my $p (keys %default) {
5524  $p{$p} //= $default{$p};
5525  }
5526  error("Usage: Center => [x,y,z].") unless ref($p{Center}) eq 'ARRAY';
5527  for my $i (0..2) {
5528  $p{Center}->[$i] //= 0;
5529  }
5530  return Geo::OGR::ApproximateArcAngles($p{Center}->[0], $p{Center}->[1], $p{Center}->[2], $p{PrimaryRadius}, $p{SecondaryAxis}, $p{Rotation}, $p{StartAngle}, $p{EndAngle}, $p{MaxAngleStepSizeDegrees});
5531 }
5532 
5533 #** @method scalar Area()
5534 # Object method.
5535 # @note a.k.a. GetArea
5536 # @return the area of the polygon or multipolygon
5537 #*
5538 sub Area {
5539 }
5540 
5541 #** @method scalar As(%params)
5542 # Object method.
5543 # Export the geometry into a known format.
5544 #
5545 # @param params Named parameters:
5546 # - \a Format One of
5547 # - \a WKT Well Known Text.
5548 # - <em>ISO WKT</em>
5549 # - \a Text Same as WKT.
5550 # - \a WKB Well Known Binary.
5551 # - <em>ISO WKB</em>
5552 # - \a Binary Same as WKB.
5553 # - \a HEXWKB
5554 # - \a HEXEWKB
5555 # - \a GML
5556 # - \a GeoJSON
5557 # - \a ByteOrder Byte order for binary formats. Default is 'XDR'.
5558 # - \a SRID Spatial reference id for HEXEWKB.
5559 # - \a Options GML generation options.
5560 # - \a AltitudeMode For KML.
5561 #
5562 # @return the geometry in a given format.
5563 #*
5564 sub As {
5565  my $self = shift;
5566  my $p = named_parameters(\@_, Format => undef, ByteOrder => 'XDR', SRID => undef, Options => undef, AltitudeMode => undef);
5567  my $f = $p->{format};
5568  if ($f =~ /text/i) {
5569  return $self->AsText;
5570  } elsif ($f =~ /wkt/i) {
5571  if ($f =~ /iso/i) {
5572  return $self->ExportToIsoWkt;
5573  } else {
5574  return $self->AsText;
5575  }
5576  } elsif ($f =~ /binary/i) {
5577  return $self->ExportToWkb($p->{byteorder});
5578  } elsif ($f =~ /wkb/i) {
5579  if ($f =~ /iso/i) {
5580  $p->{byteorder} = s2i(byte_order => $p->{byteorder});
5581  return $self->ExportToIsoWkb($p->{byteorder});
5582  } elsif ($f =~ /ewkb/i) {
5583  return $self->AsHEXEWKB($p->{srid});
5584  } elsif ($f =~ /hex/i) {
5585  return $self->AsHEXWKB;
5586  } else {
5587  return $self->ExportToWkb($p->{byteorder});
5588  }
5589  } elsif ($f =~ /gml/i) {
5590  return $self->ExportToGML($p->{options});
5591  } elsif ($f =~ /kml/i) {
5592  return $self->ExportToKML($p->{altitudemode});
5593  } elsif ($f =~ /json/i) {
5594  return $self->AsJSON;
5595  } else {
5596  error(1, $f, map {$_=>1} qw/Text WKT ISO_WKT ISO_WKB HEX_WKB HEX_EWKB Binary GML KML JSON/);
5597  }
5598 }
5599 
5600 #** @method AssignSpatialReference($srs)
5601 # Object method.
5602 # @param srs a Geo::OSR::SpatialReference object
5603 #*
5604 sub AssignSpatialReference {
5605 }
5606 
5607 #** @method Geo::OGR::Geometry Boundary()
5608 # Object method.
5609 # @note a.k.a. GetBoundary
5610 # @return the boundary of this geometry as a geometry
5611 # @since 1.8.0
5612 #*
5613 sub Boundary {
5614 }
5615 
5616 #** @method Geo::OGR::Geometry Buffer($distance, $quadsecs = 30)
5617 # Object method.
5618 # @param distance
5619 # @param quadsecs
5620 # @return a new Geo::OGR::Geometry object
5621 #*
5622 sub Buffer {
5623 }
5624 
5625 #** @method Geo::OGR::Geometry BuildPolygonFromEdges($BestEffort = 0, $AutoClose = 0, $Tolerance = 0)
5626 # Object method.
5627 # Attempt to create a polygon from a collection of lines or from a multilinestring.
5628 # @param BestEffort For future
5629 # @param AutoClose Assure the first and last points of rings are same.
5630 # @param Tolerance Snap distance.
5631 # @exception Several possibilities, some are reported, some are general errors.
5632 # @return a new Geo::OGR::Geometry object (Polygon)
5633 #*
5634 sub BuildPolygonFromEdges {
5635 }
5636 
5637 #** @method list ByteOrders()
5638 # Package subroutine.
5639 # Same as Geo::OGR::ByteOrders
5640 #*
5641 sub ByteOrders {
5642  return @BYTE_ORDER_TYPES;
5643 }
5644 
5645 #** @method Geo::OGR::Geometry Centroid()
5646 # Object method.
5647 # @return a new Geo::OGR::Geometry object
5648 # @since 1.8.0
5649 #*
5650 sub Centroid {
5651 }
5652 
5653 #** @method Geo::OGR::Geometry Clone()
5654 # Object method.
5655 # @return a new Geo::OGR::Geometry object
5656 #*
5657 sub Clone {
5658 }
5659 
5660 #** @method CloseRings()
5661 # Object method.
5662 #*
5663 sub CloseRings {
5664 }
5665 
5666 #** @method Geo::OGR::Geometry Collect(@geometries)
5667 # Object method.
5668 # Create a geometrycollection from this and possibly other geometries.
5669 # @param geometries [optional] More geometries to add to the collection.
5670 # @return a new Geo::OGR::Geometry object of type geometrycollection.
5671 #*
5672 sub Collect {
5673 }
5674 
5675 #** @method scalar Contains($other)
5676 # Object method.
5677 # @param other a Geo::OGR::Geometry object
5678 # @return true if this geometry contains the other geometry, false otherwise
5679 #*
5680 sub Contains {
5682 
5683 #** @method Geo::OGR::Geometry ConvexHull()
5684 # Object method.
5685 # @return a new Geo::OGR::Geometry object
5686 #*
5687 sub ConvexHull {
5688 }
5689 
5690 #** @method scalar CoordinateDimension($dimension)
5691 # Object method.
5692 # @param dimension [optional]
5693 # @return 2 or 3
5694 #*
5695 sub CoordinateDimension {
5696  my $self = shift;
5697  SetCoordinateDimension($self, $_[0]) if @_;
5698  GetCoordinateDimension($self) if defined wantarray;
5699 }
5700 
5701 #** @method scalar Crosses($other)
5702 # Object method.
5703 # @param other a Geo::OGR::Geometry object
5704 # @return true if this geometry crosses the other geometry, false otherwise
5705 #*
5706 sub Crosses {
5707 }
5708 
5709 #** @method DelaunayTriangulation()
5710 #*
5711 sub DelaunayTriangulation {
5712 }
5713 
5714 #** @method Geo::OGR::Geometry Difference($other)
5715 # Object method.
5716 # @param other a Geo::OGR::Geometry object
5717 # @return a new Geo::OGR::Geometry object
5718 #*
5719 sub Difference {
5720 }
5721 
5722 #** @method scalar Disjoint($other)
5723 # Object method.
5724 # @param other a Geo::OGR::Geometry object
5725 # @return true if this geometry is disjoint from the other geometry, false otherwise
5726 #*
5727 sub Disjoint {
5728 }
5729 
5730 #** @method list Dissolve()
5731 # Object method.
5732 # Dissolve a geometrycollection into separate geometries.
5733 # @return a list of new Geo::OGR::Geometry objects cloned from the collection.
5734 #*
5735 sub Dissolve {
5736  my $self = shift;
5737  my @c;
5738  my $n = $self->GetGeometryCount;
5739  if ($n > 0) {
5740  for my $i (0..$n-1) {
5741  push @c, $self->GetGeometryRef($i)->Clone;
5742  }
5743  } else {
5744  push @c, $self;
5745  }
5746  return @c;
5747 }
5748 
5749 #** @method scalar Distance($other)
5750 # Object method.
5751 # @param other a Geo::OGR::Geometry object
5752 # @return the distance to the other geometry
5753 #*
5754 sub Distance {
5755 }
5756 
5757 #** @method Distance3D()
5758 #*
5759 sub Distance3D {
5760 }
5761 
5762 #** @method Empty()
5763 # Object method.
5764 # Clear geometry data, i.e., remove all points, or, for a point, set
5765 # the coordinate dimension as zero.
5766 #*
5767 sub Empty {
5768 }
5769 
5770 #** @method scalar Equals($other)
5771 # Object method.
5772 # @note a.k.a. Equal (deprecated)
5773 # @param other a Geo::OGR::Geometry object
5774 # @return true if this geometry is equivalent to the other geometry, false otherwise
5775 #*
5776 sub Equals {
5777 }
5778 
5779 #** @method Extent()
5780 #*
5781 sub Extent {
5782  my $self = shift;
5783  return Geo::GDAL::Extent->new($self->GetEnvelope);
5784 }
5785 
5786 #** @method Feature()
5787 #*
5788 sub Feature {
5789  my $self = shift;
5790  parent($self);
5791 }
5792 
5793 #** @method FlattenTo2D()
5794 # Object method.
5795 #*
5796 sub FlattenTo2D {
5797 }
5798 
5799 #** @method Geo::OGR::Geometry ForceTo($type, ref options)
5800 # Object method.
5801 # Attempt to make a geometry of type 'type' out of this geometry.
5802 # @param type target geometry type. One of Geo::OGR::GeometryTypes.
5803 # @param options not used currently.
5804 # @return a new Geo::OGR::Geometry object.
5805 #*
5806 sub ForceTo {
5807  my $self = shift;
5808  my $type = shift;
5809  $type = s2i(geometry_type => $type);
5810  eval {
5811  $self = Geo::OGR::ForceTo($self, $type, @_);
5812  };
5813  confess last_error() if $@;
5814  return $self;
5815 }
5816 
5817 #** @method Geo::OGR::Geometry ForceToCollection(@geometries)
5818 # Object method.
5819 # Create a geometrycollection from the geometry.
5820 # @param geometries [optional] More geometries to add to the collection.
5821 # @return a new Geo::OGR::Geometry object of type geometrycollection.
5822 #*
5823 sub ForceToCollection {
5824  my $self = Geo::OGR::Geometry->new(GeometryType => 'GeometryCollection');
5825  for my $g (@_) {
5826  $self->AddGeometry($g);
5827  }
5828  return $self;
5829 }
5830 
5831 #** @method Geo::OGR::Geometry ForceToLineString()
5832 # Object method.
5833 # Attempt to create a line string from this geometry.
5834 # @return a new Geo::OGR::Geometry object.
5835 #*
5836 sub ForceToLineString {
5837  my $self = shift;
5838  return Geo::OGR::ForceToLineString($self);
5839 }
5840 
5841 #** @method Geo::OGR::Geometry ForceToMultiLineString(@linestrings)
5842 # Object method.
5843 # Attempt to create a multilinestring from the geometry, which must be a linestring.
5844 # @param linestrings [optional] More linestrings to add to the collection.
5845 # @return a new Geo::OGR::Geometry object of type multilinestring.
5846 #*
5847 sub ForceToMultiLineString {
5848  my $self = shift;
5849  $self = Geo::OGR::ForceToMultiLineString($self);
5850  for my $g (@_) {
5851  $self->AddGeometry($g);
5852  }
5853  return $self;
5854 }
5855 
5856 #** @method Geo::OGR::Geometry ForceToMultiPoint(@points)
5857 # Object method.
5858 # Attempt to create a multipoint from the geometry, which must be a point.
5859 # @param points [optional] More points to add to the collection.
5860 # @return a new Geo::OGR::Geometry object of type multipoint.
5861 #*
5862 sub ForceToMultiPoint {
5863  my $self = shift;
5864  $self = Geo::OGR::ForceToMultiPoint($self);
5865  for my $g (@_) {
5866  $self->AddGeometry($g);
5867  }
5868  return $self;
5869 }
5870 
5871 #** @method Geo::OGR::Geometry ForceToMultiPolygon(@polygons)
5872 # Object method.
5873 # Attempt to create a multipolygon from the geometry, which must be a polygon.
5874 # @param polygons [optional] More polygons to add to the collection.
5875 # @return a new Geo::OGR::Geometry object of type multipolygon.
5876 #*
5877 sub ForceToMultiPolygon {
5878  my $self = shift;
5879  $self = Geo::OGR::ForceToMultiPolygon($self);
5880  for my $g (@_) {
5881  $self->AddGeometry($g);
5882  }
5883  return $self;
5884 }
5885 
5886 #** @method Geo::OGR::Geometry ForceToPolygon()
5887 # Object method.
5888 # Attempt to create a polygon from this geometry.
5889 # @exception None reported. If this method fails, just a copy is returned.
5890 # @return a new Geo::OGR::Geometry object.
5891 #*
5892 sub ForceToPolygon {
5893 }
5894 
5895 #** @method scalar GeometryType()
5896 # Object method.
5897 # @return the geometry type of this geometry (one of Geo::OGR::GeometryTypes).
5898 #*
5899 sub GeometryType {
5900  my $self = shift;
5901  return i2s(geometry_type => $self->GetGeometryType);
5902 }
5903 
5904 #** @method list GeometryTypes()
5905 # Package subroutine.
5906 # Same as Geo::OGR::GeometryTypes
5907 #*
5908 sub GeometryTypes {
5909  return @GEOMETRY_TYPES;
5910 }
5911 
5912 #** @method scalar GetCoordinateDimension()
5913 # Object method.
5914 # @return an integer
5915 #*
5916 sub GetCoordinateDimension {
5917 }
5918 
5919 #** @method GetCurveGeometry()
5920 #*
5921 sub GetCurveGeometry {
5922 }
5923 
5924 #** @method scalar GetDimension()
5925 # Object method.
5926 # @return 0, 1, or 2
5927 #*
5928 sub GetDimension {
5929 }
5930 
5931 #** @method list GetEnvelope()
5932 # Object method.
5933 # @note In scalar context returns a reference to an anonymous array
5934 # containing the envelope.
5935 # @return the envelope ($minx, $maxx, $miny, $maxy)
5936 #*
5937 sub GetEnvelope {
5938 }
5939 
5940 #** @method list GetEnvelope3D()
5941 # Object method.
5942 # @note In scalar context returns a reference to an anonymous array
5943 # containing the envelope.
5944 # @return the 3-D envelope ($minx, $maxx, $miny, $maxy, $minz, $maxz)
5945 # @since 1.9.0
5946 #*
5947 sub GetEnvelope3D {
5948 }
5949 
5950 #** @method scalar GetGeometryCount()
5951 # Object method.
5952 # @return an integer
5953 #*
5954 sub GetGeometryCount {
5955 }
5956 
5957 #** @method scalar GetGeometryName()
5958 # Object method.
5959 # @deprecated use Geo::OGR::Geometry::GeometryType.
5960 #
5961 # @return a string
5962 #*
5963 sub GetGeometryName {
5964 }
5965 
5966 #** @method scalar GetGeometryRef($index)
5967 # Object method.
5968 # @param index index to the geometry, which is a part of this geometry
5969 # @return a new Geo::OGR::Geometry object whose data is a part of the
5970 # parent geometry
5971 #*
5972 sub GetGeometryRef {
5973 }
5974 
5975 #** @method scalar GetGeometryType()
5976 # Object method.
5977 # @deprecated use Geo::OGR::Geometry::GeometryType, which returns the
5978 # type as a string.
5979 #
5980 # @return type as an integer
5981 #*
5982 sub GetGeometryType {
5983 }
5984 
5985 #** @method GetLinearGeometry()
5986 #*
5987 sub GetLinearGeometry {
5988 }
5989 
5990 #** @method GetM()
5991 #*
5992 sub GetM {
5993 }
5994 
5995 #** @method list GetPoint($index = 0)
5996 # Object method.
5997 # @param index
5998 # @return (x,y) or a list with more coordinates
5999 #*
6000 sub GetPoint {
6001  my($self, $i) = @_;
6002  $i //= 0;
6003  my $t = $self->GetGeometryType;
6004  my $has_z = HasZ($t);
6005  my $has_m = HasM($t);
6006  my $point;
6007  if (!$has_z && !$has_m) {
6008  $point = $self->GetPoint_2D($i);
6009  } elsif ($has_z && !$has_m) {
6010  $point = $self->GetPoint_3D($i);
6011  } elsif (!$has_z && $has_m) {
6012  $point = $self->GetPointZM($i);
6013  @$point = ($point->[0], $point->[1], $point->[3]);
6014  } else {
6015  $point = $self->GetPointZM($i);
6016  }
6017  return wantarray ? @$point : $point;
6018 }
6019 
6020 #** @method scalar GetPointCount()
6021 # Object method.
6022 # @return an integer
6023 #*
6024 sub GetPointCount {
6025 }
6026 
6027 #** @method GetPointZM()
6028 #*
6029 sub GetPointZM {
6030 }
6031 
6032 #** @method scalar GetPoint_2D($index = 0)
6033 # Object method.
6034 # @param index
6035 # @return (x,y) or a list with more coordinates
6036 #*
6037 sub GetPoint_2D {
6038 }
6039 
6040 #** @method scalar GetPoint_3D($index = 0)
6041 # Object method.
6042 # @param index
6043 # @return (x,y) or a list with more coordinates
6044 #*
6045 sub GetPoint_3D {
6046 }
6047 
6048 #** @method Geo::OSR::SpatialReference GetSpatialReference()
6049 # Object method.
6050 # @return a new Geo::OSR::SpatialReference object
6051 #*
6052 sub GetSpatialReference {
6053 }
6054 
6055 #** @method scalar GetX($index = 0)
6056 # Object method.
6057 # @param index
6058 # @return a number
6059 #*
6060 sub GetX {
6061 }
6062 
6063 #** @method scalar GetY($index = 0)
6064 # Object method.
6065 # @param index
6066 # @return a number
6067 #*
6068 sub GetY {
6069 }
6070 
6071 #** @method scalar GetZ($index = 0)
6072 # Object method.
6073 # @param index
6074 # @return a number
6075 #*
6076 sub GetZ {
6077 }
6078 
6079 #** @method HasCurveGeometry()
6080 #*
6081 sub HasCurveGeometry {
6082 }
6083 
6084 #** @method Geo::OGR::Geometry Intersection($other)
6085 # Object method.
6086 # @param other a Geo::OGR::Geometry object
6087 # @return a new Geo::OGR::Geometry object
6088 #*
6089 sub Intersection {
6090 }
6091 
6092 #** @method scalar Intersects($other)
6093 # Object method.
6094 # @note a.k.a. Intersect (deprecated)
6095 # @param other a Geo::OGR::Geometry object
6096 # @return true if this geometry intersects with the other geometry, false otherwise
6097 #*
6098 sub Intersects {
6099 }
6100 
6101 #** @method Is3D()
6102 #*
6103 sub Is3D {
6104 }
6105 
6106 #** @method scalar IsEmpty()
6107 # Object method.
6108 # Test whether the geometry is empty (has no points, or, for a point,
6109 # has coordinate dimension of zero).
6110 # @return boolean
6111 #*
6112 sub IsEmpty {
6113 }
6114 
6115 #** @method IsMeasured()
6116 #*
6117 sub IsMeasured {
6118 }
6119 
6120 #** @method scalar IsRing()
6121 # Object method.
6122 # Test if the geometry is a ring. Requires GEOS in GDAL.
6123 # @return boolean
6124 #*
6125 sub IsRing {
6126 }
6127 
6128 #** @method scalar IsSimple()
6129 # Object method.
6130 # Test the simplicity of the geometry (OGC sense). Requires GEOS in GDAL.
6131 # @return boolean
6132 #*
6133 sub IsSimple {
6134 }
6135 
6136 #** @method scalar IsValid()
6137 # Object method.
6138 # Test the validity of the geometry (OGC sense). Requires GEOS in GDAL.
6139 # @return boolean
6140 #*
6141 sub IsValid {
6142 }
6143 
6144 #** @method scalar Length()
6145 # Object method.
6146 # @return the length of the linestring
6147 #*
6148 sub Length {
6149 }
6150 
6151 #** @method Move($dx, $dy, $dz)
6152 # Object method.
6153 # Move every point of the object as defined by the parameters.
6154 # @param dx
6155 # @param dy
6156 # @param dz [optional]
6157 #*
6158 sub Move {
6159 }
6160 
6161 #** @method scalar Overlaps($other)
6162 # Object method.
6163 # @param other a Geo::OGR::Geometry object
6164 # @return true if this geometry overlaps the other geometry, false otherwise
6165 #*
6166 sub Overlaps {
6167 }
6168 
6169 #** @method list Point($index, $x, $y, $z)
6170 # Object method.
6171 # Get or set the point
6172 # @param index The index of the point. Optional (ignored if given) for
6173 # Point and Point25D geometries.
6174 # @param x [optional]
6175 # @param y [optional]
6176 # @param z [optional]
6177 # @return
6178 #*
6179 sub Point {
6180  my $self = shift;
6181  my $i;
6182  if (@_) {
6183  my $t = $self->GetGeometryType;
6184  my $i;
6185  if (Flatten($t) == $Geo::OGR::wkbPoint) {
6186  my $has_z = HasZ($t);
6187  my $has_m = HasM($t);
6188  if (!$has_z && !$has_m) {
6189  shift if @_ > 2;
6190  $i = 0;
6191  } elsif ($has_z || $has_m) {
6192  shift if @_ > 3;
6193  $i = 0;
6194  } else {
6195  shift if @_ > 4;
6196  $i = 0;
6197  }
6198  }
6199  $i = shift unless defined $i;
6200  $self->SetPoint($i, @_);
6201  }
6202  return unless defined wantarray;
6203  my $point = $self->GetPoint;
6204  return wantarray ? @$point : $point;
6205 }
6206 
6207 #** @method PointOnSurface()
6208 #*
6209 sub PointOnSurface {
6210 }
6211 
6212 #** @method array reference Points(arrayref points)
6213 # Object method.
6214 # Get or set the points of the geometry. The points (vertices) are
6215 # stored in obvious lists of lists. When setting, the geometry is
6216 # first emptied. The method uses internally either AddPoint_2D or
6217 # AddPoint_3D depending on the coordinate dimension of the input data.
6218 #
6219 # @note The same structure may represent different geometries
6220 # depending on the actual geometry type of the object.
6221 #
6222 # @param points [optional] A reference to an array. A point is a reference to an
6223 # array of numbers, a linestring or a ring is a reference to an array of points,
6224 # a polygon is a reference to an array of rings, etc.
6225 #
6226 # @return A reference to an array.
6227 #*
6228 sub Points {
6229  my $self = shift;
6230  my $t = $self->GetGeometryType;
6231  my $has_z = HasZ($t);
6232  my $has_m = HasM($t);
6233  my $postfix = '';
6234  $postfix .= 'Z' if HasZ($t);
6235  $postfix .= 'M' if HasM($t);
6236  $t = i2s(geometry_type => Flatten($t));
6237  my $points = shift;
6238  if ($points) {
6239  Empty($self);
6240  if ($t eq 'Unknown' or $t eq 'None' or $t eq 'GeometryCollection') {
6241  error("Can't set points of a geometry of type '$t'.");
6242  } elsif ($t eq 'Point') {
6243  # support both "Point" as a list of one point and one point
6244  if (ref($points->[0])) {
6245  $self->AddPoint(@{$points->[0]});
6246  } else {
6247  $self->AddPoint(@$points);
6248  }
6249  } elsif ($t eq 'LineString' or $t eq 'LinearRing' or $t eq 'CircularString') {
6250  for my $p (@$points) {
6251  $self->AddPoint(@$p);
6252  }
6253  } elsif ($t eq 'Polygon') {
6254  for my $r (@$points) {
6255  my $ring = Geo::OGR::Geometry->new('LinearRing');
6256  $ring->Set3D(1) if $has_z;
6257  $ring->SetMeasured(1) if $has_m;
6258  $ring->Points($r);
6259  $self->AddGeometryDirectly($ring);
6260  }
6261  } elsif ($t eq 'MultiPoint') {
6262  for my $p (@$points) {
6263  my $point = Geo::OGR::Geometry->new('Point'.$postfix);
6264  $point->Points($p);
6265  $self->AddGeometryDirectly($point);
6266  }
6267  } elsif ($t eq 'MultiLineString') {
6268  for my $l (@$points) {
6269  my $linestring = Geo::OGR::Geometry->new('LineString'.$postfix);
6270  $linestring->Points($l);
6271  $self->AddGeometryDirectly($linestring);
6272  }
6273  } elsif ($t eq 'MultiPolygon') {
6274  for my $p (@$points) {
6275  my $polygon = Geo::OGR::Geometry->new('Polygon'.$postfix);
6276  $polygon->Points($p);
6277  $self->AddGeometryDirectly($polygon);
6278  }
6279  }
6280  }
6281  return unless defined wantarray;
6282  $self->_GetPoints();
6283 }
6284 
6285 #** @method RELEASE_PARENT()
6286 #*
6287 sub RELEASE_PARENT {
6288  my $self = shift;
6289  unkeep($self);
6290 }
6291 
6292 #** @method Segmentize($MaxLength)
6293 # Object method.
6294 # Modify the geometry such it has no segment longer than the given length.
6295 # @param MaxLength the given length
6296 #*
6297 sub Segmentize {
6298 }
6299 
6300 #** @method Set3D()
6301 #*
6302 sub Set3D {
6303 }
6304 
6305 #** @method SetCoordinateDimension($dimension)
6306 # Object method.
6307 # @param dimension
6308 #*
6309 sub SetCoordinateDimension {
6310 }
6311 
6312 #** @method SetMeasured()
6313 #*
6314 sub SetMeasured {
6315 }
6316 
6317 #** @method SetPoint($index, $x, $y, $z)
6318 # Object method.
6319 # Set the data of a point or a line string. Note that the coordinate
6320 # dimension is automatically upgraded to 25D (3) if z is given.
6321 # @param index
6322 # @param x
6323 # @param y
6324 # @param z [optional]
6325 #*
6326 sub SetPoint {
6327  my $self = shift;
6328  my $t = $self->GetGeometryType;
6329  my $has_z = HasZ($t);
6330  my $has_m = HasM($t);
6331  if (!$has_z && !$has_m) {
6332  $self->SetPoint_2D(@_[0..2]);
6333  } elsif ($has_z && !$has_m) {
6334  $self->SetPoint_3D(@_[0..3]);
6335  } elsif (!$has_z && $has_m) {
6336  $self->SetPointM(@_[0..3]);
6337  } else {
6338  $self->SetPointZM(@_[0..4]);
6339  }
6340 }
6341 
6342 #** @method SetPointM()
6343 #*
6344 sub SetPointM {
6345 }
6346 
6347 #** @method SetPointZM()
6348 #*
6349 sub SetPointZM {
6350 }
6351 
6352 #** @method SetPoint_2D($index, $x, $y)
6353 # Object method.
6354 # @param index
6355 # @param x
6356 # @param y
6357 #*
6358 sub SetPoint_2D {
6359 }
6360 
6361 #** @method SetPoint_3D($index, $x, $y, $z)
6362 # Object method.
6363 # Set the data of a point or a line string. Note that the coordinate
6364 # dimension is automatically upgraded to 25D (3).
6365 # @param index
6366 # @param x
6367 # @param y
6368 # @param z
6369 #*
6370 sub SetPoint_3D {
6371 }
6372 
6373 #** @method Geo::OGR::Geometry Simplify($Tolerance)
6374 # Object method.
6375 # Simplify the geometry.
6376 # @param Tolerance the length tolerance for the simplification
6377 # @since 1.8.0
6378 # @return a new Geo::OSR::Geometry object
6379 #*
6380 sub Simplify {
6381 }
6382 
6383 #** @method SimplifyPreserveTopology()
6384 #*
6385 sub SimplifyPreserveTopology {
6386 }
6387 
6388 #** @method Geo::OGR::Geometry SymDifference($other)
6389 # Object method.
6390 # Compute symmetric difference.
6391 # @note a.k.a. SymmetricDifference
6392 # @param other a Geo::OGR::Geometry object
6393 # @return a new Geo::OGR::Geometry object
6394 # @since 1.8.0
6395 #*
6396 sub SymDifference {
6397 }
6398 
6399 #** @method scalar Touches($other)
6400 # Object method.
6401 # @param other a Geo::OGR::Geometry object
6402 # @return true if this geometry touches the other geometry, false otherwise
6403 #*
6404 sub Touches {
6405 }
6406 
6407 #** @method Transform($trans)
6408 # Object method.
6409 # @param trans a Geo::OSR::CoordinateTransformation object
6410 #*
6411 sub Transform {
6412 }
6413 
6414 #** @method TransformTo($srs)
6415 # Object method.
6416 # @param srs a Geo::OSR::SpatialReference object
6417 #*
6418 sub TransformTo {
6419 }
6420 
6421 #** @method Geo::OGR::Geometry Union($other)
6422 # Object method.
6423 # @param other a Geo::OGR::Geometry object
6424 # @return a new Geo::OGR::Geometry object
6425 #*
6426 sub Union {
6427 }
6428 
6429 #** @method Geo::OGR::Geometry UnionCascaded()
6430 # Object method.
6431 # @return a new Geo::OGR::Geometry object
6432 # @since 1.8.0
6433 #*
6434 sub UnionCascaded {
6435 }
6436 
6437 #** @method Value()
6438 #*
6439 sub Value {
6440 }
6441 
6442 #** @method scalar Within($other)
6443 # Object method.
6444 # @param other a Geo::OGR::Geometry object
6445 # @return true if this geometry is within the other geometry, false otherwise
6446 #*
6447 sub Within {
6448 }
6449 
6450 #** @method scalar WkbSize()
6451 # Object method.
6452 # @return an integer
6453 #*
6454 sub WkbSize {
6455 }
6456 
6457 #** @method Geo::OGR::Geometry new(%params)
6458 # Class method.
6459 # @param %params A named parameter, one of:
6460 # - \a GeometryType one the supported geometry types, see Geo::OGR::GeometryTypes.
6461 # - \a WKT a well known text string, which defines a geometry.
6462 # - \a WKB a well known binary string, which defines a geometry.
6463 # - \a HEXWKB WKB in hexadecimal.
6464 # - \a HEXEWKB PostGIS extended WKB.
6465 # - \a GML geometry written in Geographic Markup Language.
6466 # - \a GeoJSON geometry written in GeoJSON (JavaScript Object Notation for Geographic data).
6467 # - \a arc a reference to a list of values defining an arc: [CenterX,
6468 # CenterY, CenterZ, PrimaryRadius, SecondaryRadius, Rotation,
6469 # StartAngle, EndAngle, MaxAngleStepSizeDegrees] (see also Geo::OGR::Geometry::ApproximateArcAngles)
6470 # - \a Points An anonymous array as in method
6471 # Geo::OGR::Geometry::Points; Note: requires also GeometryType
6472 # parameter
6473 #
6474 # @return a new Geo::OGR::Geometry object.
6475 #*
6476 sub new {
6477  my $pkg = shift;
6478  my %param;
6479  if (@_ == 1 and ref($_[0]) eq 'HASH') {
6480  %param = %{$_[0]};
6481  } elsif (@_ % 2 == 0) {
6482  %param = @_;
6483  } else {
6484  ($param{GeometryType}) = @_;
6485  }
6486  my $type = $param{GeometryType} // $param{Type} // $param{type};
6487  my $srs = $param{SRS} // $param{srs};
6488  my $wkt = $param{WKT} // $param{wkt};
6489  my $wkb = $param{WKB} // $param{wkb};
6490  my $hex = $param{HEXEWKB} // $param{HEX_EWKB} // $param{hexewkb} // $param{hex_ewkb};
6491  my $srid;
6492  if ($hex) {
6493  # EWKB contains SRID
6494  $srid = substr($hex, 10, 8);
6495  substr($hex, 10, 8) = '';
6496  } else {
6497  $hex = $param{HEXWKB} // $param{HEX_WKB} // $param{hexwkb} // $param{hex_wkb};
6498  }
6499  if ($hex) {
6500  $wkb = '';
6501  for (my $i = 0; $i < length($hex); $i+=2) {
6502  $wkb .= chr(hex(substr($hex,$i,2)));
6503  }
6504  }
6505  my $gml = $param{GML} // $param{gml};
6506  my $json = $param{GeoJSON} // $param{geojson} // $param{JSON} // $param{json};
6507  my $points = $param{Points} // $param{points};
6508  my $arc = $param{Arc} // $param{arc};
6509  my $self;
6510  if (defined $wkt) {
6511  $self = Geo::OGRc::CreateGeometryFromWkt($wkt, $srs);
6512  } elsif (defined $wkb) {
6513  $self = Geo::OGRc::CreateGeometryFromWkb($wkb, $srs);
6514  } elsif (defined $gml) {
6515  $self = Geo::OGRc::CreateGeometryFromGML($gml);
6516  } elsif (defined $json) {
6517  $self = Geo::OGRc::CreateGeometryFromJson($json);
6518  } elsif (defined $type) {
6519  $type = s2i(geometry_type => $type);
6520  $self = Geo::OGRc::new_Geometry($type); # flattens the type
6521  $self->Set3D(1) if HasZ($type);
6522  $self->SetMeasured(1) if HasM($type);
6523  } elsif (defined $arc) {
6524  $self = Geo::OGRc::ApproximateArcAngles(@$arc);
6525  } else {
6526  error(1, undef, map {$_=>1} qw/GeometryType WKT WKB HEXEWKB HEXWKB GML GeoJSON Arc/);
6527  }
6528  bless $self, $pkg if defined $self;
6529  $self->Points($points) if $points;
6530  return $self;
6531 }
6532 
6533 #** @class Geo::OGR::Layer
6534 # @brief A collection of similar features.
6535 # @details A layer object is typically obtained with a data source object. A
6536 # layer has a data model (a schema), which is maintained in a
6537 # definition object, and a set of features, which contain data
6538 # according to the data model. The schema is typically set when the
6539 # layer is created or opened, but it may be altered somewhat with
6540 # methods Geo::OGR::Layer::CreateField,
6541 # Geo::OGR::Layer::AlterFieldDefn, and
6542 # Geo::OGR::Layer::DeleteField. Features and/or their data can be
6543 # read, inserted and deleted. Reading can be filtered. Layers can be
6544 # compared to each other with methods Clip, Erase, Identity,
6545 # Intersection, SymDifference, Union, and Update.
6546 # A layer may have metadata OLMD_FID64 => 'YES' if it holds features
6547 # with 64 bit FIDs. The metadata of a layer can be obtained with
6548 # GetMetadata method.
6549 #*
6550 package Geo::OGR::Layer;
6551 
6552 use base qw(Geo::GDAL::MajorObject Geo::OGR)
6553 
6554 #** @method AlterFieldDefn($name, %params)
6555 # Object method.
6556 # @param field the name of the field to be altered.
6557 # @param params as in Geo::OGR::FieldDefn::new. Width and
6558 # Precision should be both or neither.
6559 # @note Only non-spatial fields can be altered.
6560 # @note Also the deprecated form AlterFieldDefn($field,
6561 # Geo::OGR::FieldDefn $Defn, $Flags) works.
6562 #*
6563 sub AlterFieldDefn {
6564  my $self = shift;
6565  my $index = $self->GetLayerDefn->GetFieldIndex(shift // 0);
6566  my $param = @_ % 2 == 0 ? {@_} : shift;
6567  if (blessed($param) and $param->isa('Geo::OGR::FieldDefn')) {
6568  _AlterFieldDefn($self, $index, @_);
6569  } else {
6570  my $definition = Geo::OGR::FieldDefn->new($param);
6571  my $flags = 0;
6572  $flags |= 1 if exists $param->{Name};
6573  $flags |= 2 if exists $param->{Type};
6574  $flags |= 4 if exists $param->{Width} or exists $param->{Precision};
6575  $flags |= 8 if exists $param->{Nullable};
6576  $flags |= 16 if exists $param->{Default};
6577  _AlterFieldDefn($self, $index, $definition, $flags);
6578  }
6579 }
6580 
6581 #** @method list Capabilities()
6582 # Object method.
6583 # Both a package subroutine and an object method.
6584 # @return a list of capabilities. The object method returns a list of
6585 # the capabilities the layer has. The package subroutine returns a list of
6586 # all potential capabilities a layer may have. These are currently:
6587 # AlterFieldDefn, CreateField, CreateGeomField, CurveGeometries, DeleteFeature, DeleteField, FastFeatureCount, FastGetExtent, FastSetNextByIndex, FastSpatialFilter, IgnoreFields, MeasuredGeometries, RandomRead, RandomWrite, ReorderFields, SequentialWrite, StringsAsUTF8, and Transactions.
6588 #
6589 # Examples:
6590 # \code
6591 # @cap = Geo::OGR::Layer::Capabilities(); # the package subroutine
6592 # @cap = $layer->Capabilities(); # the object method
6593 # \endcode
6594 #*
6595 sub Capabilities {
6596  return @CAPABILITIES if @_ == 0;
6597  my $self = shift;
6598  my @cap;
6599  for my $cap (@CAPABILITIES) {
6600  push @cap, $cap if _TestCapability($self, $CAPABILITIES{$cap});
6601  }
6602  return @cap;
6603 }
6604 
6605 #** @method Clip(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
6606 # Object method.
6607 # Clip off areas that are not covered by the method layer. The schema
6608 # of the result layer can be set before calling this method, or is
6609 # initialized to to contain all fields from
6610 # this and method layer.
6611 # @param method method layer.
6612 # @param result result layer.
6613 # @param options a reference to an options hash.
6614 # @param callback [optional] a reference to a subroutine, which will
6615 # be called with parameters (number progress, string msg, callback_data)
6616 # @param callback_data [optional]
6617 #*
6618 sub Clip {
6619 }
6620 
6621 #** @method CommitTransaction()
6622 # Object method.
6623 #*
6624 sub CommitTransaction {
6625 }
6626 
6627 #** @method CreateFeature()
6628 #*
6629 sub CreateFeature {
6630 }
6631 
6632 #** @method CreateField(%params)
6633 # Object method.
6634 # Create a field.
6635 # @param params as in Geo::OGR::FieldDefn::new or
6636 # Geo::OGR::GeomFieldDefn::new, plus ApproxOK (whose default is true).
6637 #*
6638 sub CreateField {
6639  my $self = shift;
6640  my %defaults = ( ApproxOK => 1,
6641  Type => '' );
6642  my %params;
6643  if (@_ == 0) {
6644  } elsif (ref($_[0]) eq 'HASH') {
6645  %params = %{$_[0]};
6646  } elsif (@_ % 2 == 0) {
6647  %params = @_;
6648  } else {
6649  ($params{Defn}) = @_;
6650  }
6651  for my $k (keys %defaults) {
6652  $params{$k} //= $defaults{$k};
6653  }
6654  if (blessed($params{Defn}) and $params{Defn}->isa('Geo::OGR::FieldDefn')) {
6655  $self->_CreateField($params{Defn}, $params{ApproxOK});
6656  } elsif (blessed($_[0]) and $params{Defn}->isa('Geo::OGR::GeomFieldDefn')) {
6657  $self->CreateGeomField($params{Defn}, $params{ApproxOK});
6658  } else {
6659  # if Name and Type are missing, assume Name => Type
6660  if (!(exists $params{Name} && exists $params{Type})) {
6661  for my $key (sort keys %params) {
6662  if (s_exists(field_type => $params{$key}) ||
6663  s_exists(geometry_type => $params{$key}))
6664  {
6665  $params{Name} = $key;
6666  $params{Type} = $params{$key};
6667  delete $params{$key};
6668  last;
6669  }
6670  }
6671  }
6672  my $a = $params{ApproxOK};
6673  delete $params{ApproxOK};
6674  if (exists $params{GeometryType}) {
6675  $params{Type} = $params{GeometryType};
6676  delete $params{GeometryType};
6677  }
6678  if (s_exists(field_type => $params{Type})) {
6679  my $fd = Geo::OGR::FieldDefn->new(%params);
6680  _CreateField($self, $fd, $a);
6681  } elsif (s_exists(geometry_type => $params{Type})) {
6682  my $fd = Geo::OGR::GeomFieldDefn->new(%params);
6683  CreateGeomField($self, $fd, $a);
6684  } elsif ($params{Type} ) {
6685  error("Invalid field type: $params{Type}.")
6686  } elsif ($params{Name} ) {
6687  error("Missing type for field: $params{Name}.")
6688  } else {
6689  error("Missing name and type for a field.")
6690  }
6691  }
6692 }
6693 
6694 #** @method DataSource()
6695 #*
6696 sub DataSource {
6697 }
6698 
6699 #** @method Dataset()
6700 #*
6701 sub Dataset {
6702  my $self = shift;
6703  parent($self);
6704 }
6705 
6706 #** @method DeleteFeature($fid)
6707 # Object method.
6708 # @param fid feature id
6709 #*
6710 sub DeleteFeature {
6711 }
6712 
6713 #** @method DeleteField($field)
6714 # Object method.
6715 # Delete an existing field from a layer.
6716 # @param field name (or index) of the field which is deleted
6717 # @note Only non-spatial fields can be deleted.
6718 #*
6719 sub DeleteField {
6720  my ($self, $field) = @_;
6721  my $index = $self->GetLayerDefn->GetFieldIndex($field // 0);
6722  _DeleteField($self, $index);
6723 }
6724 
6725 #** @method Erase(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
6726 # Object method.
6727 # The result layer contains features whose geometries represent areas
6728 # that are in the input layer but not in the method layer. The
6729 # features in the result layer have attributes from the input
6730 # layer. The schema of the result layer can be set by the user or, if
6731 # it is empty, is initialized to contain all fields in the input
6732 # layer.
6733 # @param method method layer.
6734 # @param result result layer.
6735 # @param options a reference to an options hash.
6736 # @param callback [optional] a reference to a subroutine, which will
6737 # be called with parameters (number progress, string msg, callback_data)
6738 # @param callback_data [optional]
6739 #*
6740 sub Erase {
6741 }
6742 
6743 #** @method Geo::OGR::Feature Feature($f)
6744 # Object method.
6745 #
6746 # @param f [optional] feature id, a feature, a row, or a tuple
6747 #
6748 # @note If the argument feature has a null FID (FID not set) the
6749 # feature is inserted into the layer as a new feature. If the FID is
6750 # non null, then the feature replaces the feature in the layer with
6751 # that FID.
6752 #
6753 # @return a new Geo::OGR::Feature object that represents the feature
6754 # in the layer.
6755 #*
6756 sub Feature {
6757  my $self = shift;
6758  my $x = shift;
6759  return $self->GetFeature($x) unless $x && ref $x;
6760  # Insert or Set depending on the FID
6761  my $fid;
6762  if (ref $x eq 'ARRAY') {
6763  # FID is the first item in the array
6764  $fid = $x->[0];
6765  } elsif (ref $x eq 'HASH') {
6766  # FID is FID
6767  $fid = $x->{FID};
6768  } else {
6769  $fid = $x->FID;
6770  }
6771  # OGRNullFID is -1
6772  if (!defined $fid || $fid < 0) {
6773  $self->InsertFeature($x);
6774  } else {
6775  $self->SetFeature($x);
6776  }
6777 }
6778 
6779 #** @method scalar FeatureCount($force = 1)
6780 # Object method.
6781 # A.k.a GetFeatureCount
6782 # @param force
6783 # @return integer
6784 #*
6785 sub FeatureCount {
6786 }
6787 
6788 #** @method ForFeatures($code, $in_place)
6789 # Object method.
6790 # @note experimental, the syntax may change
6791 #
6792 # Call code for all features. This is a simple wrapper for
6793 # ResetReading and while(GetNextFeature).
6794 #
6795 # Example usage:
6796 # \code
6797 # $layer->ForFeatures(sub {my $f = shift; $self->DeleteFeature($f->FID)}); # empties the layer
6798 # \endcode
6799 #
6800 # @param code a reference to a subroutine, which is called with each
6801 # feature as an argument
6802 # @param in_place if set to true, the feature is stored back to the
6803 # layer
6804 #*
6805 sub ForFeatures {
6806  my $self = shift;
6807  my $code = shift;
6808  my $in_place = shift;
6809  $self->ResetReading;
6810  while (my $f = $self->GetNextFeature) {
6811  keep($f, $self);
6812  $code->($f);
6813  $self->SetFeature($f) if $in_place;
6814  };
6815 }
6816 
6817 #** @method ForGeometries($code, $in_place)
6818 # Object method.
6819 # @note experimental, the syntax may change
6820 #
6821 # Call code for all geometries. This is a simple wrapper for
6822 # ResetReading and while(GetNextFeature).
6823 #
6824 # Example usage:
6825 # \code
6826 # my $area = 0;
6827 # $layer->ForGeometries(sub {my $g = shift; $area += $g->Area}); # computes the total area
6828 # \endcode
6829 #
6830 # @param code a reference to a subroutine, which is called with each
6831 # geometry as an argument
6832 # @param in_place if set to true, the geometry is stored back to the
6833 # layer
6834 #*
6835 sub ForGeometries {
6836  my $self = shift;
6837  my $code = shift;
6838  my $in_place = shift;
6839  $self->ResetReading;
6840  while (my $f = $self->GetNextFeature) {
6841  my $g = $f->Geometry();
6842  $code->($g);
6843  if ($in_place) {
6844  $f->Geometry($g);
6845  $self->SetFeature($f);
6846  }
6847  }
6848 }
6849 
6850 #** @method scalar GeometryType($field)
6851 # Object method.
6852 # @param field the name or index of the spatial field.
6853 # @return the geometry type of the spatial field.
6854 #*
6855 sub GeometryType {
6856  my $self = shift;
6857  my $d = $self->GetDefn;
6858  my $field = $d->GetGeomFieldIndex(shift // 0);
6859  my $fd = $d->_GetGeomFieldDefn($field);
6860  return $fd->Type if $fd;
6861 }
6862 
6863 #** @method Geo::OGR::DataSource GetDataSource()
6864 # Object method.
6865 # @return the data source object to which this layer object belongs to.
6866 #*
6867 sub GetDataSource {
6868  my $self = shift;
6869  parent($self);
6870 }
6871 
6872 #** @method Geo::OGR::FeatureDefn GetDefn()
6873 # Object method.
6874 # A.k.a GetLayerDefn.
6875 # @return a Geo::OGR::FeatureDefn object.
6876 #*
6877 sub GetDefn {
6878  my $self = shift;
6879  my $defn = $self->GetLayerDefn;
6880  keep($defn, $self);
6881 }
6882 
6883 #** @method list GetExtent($force = 1)
6884 # Object method.
6885 # @param force compute the extent even if it is expensive
6886 # @note In scalar context returns a reference to an anonymous array
6887 # containing the extent.
6888 # @return the extent ($minx, $maxx, $miny, $maxy)
6889 # @param force
6890 # @return the extent = ($minx, $maxx, $miny, $maxy) as a listref
6891 #*
6892 sub GetExtent {
6893 }
6894 
6895 #** @method scalar GetFIDColumn()
6896 # Object method.
6897 # @return the name of the underlying database column being used as the
6898 # FID column, or "" if not supported.
6899 #*
6900 sub GetFIDColumn {
6901 }
6902 
6903 #** @method Geo::OGR::Feature GetFeature($fid)
6904 # Object method.
6905 # @param fid feature id
6906 # @return a new Geo::OGR::Feature object that represents the feature in the layer.
6907 #*
6908 sub GetFeature {
6909  my ($self, $fid) = @_;
6910  $fid //= 0;
6911  my $f = $self->_GetFeature($fid);
6912  error(2, "FID=$fid", '"Feature') unless ref $f eq 'Geo::OGR::Feature';
6913  keep($f, $self);
6914 }
6915 
6916 #** @method GetFeatureCount()
6917 #*
6918 sub GetFeatureCount {
6919 }
6920 
6921 #** @method scalar GetFeaturesRead()
6922 # Object method.
6923 # @return integer
6924 #*
6925 sub GetFeaturesRead {
6926 }
6927 
6928 #** @method scalar GetFieldDefn($name)
6929 # Object method.
6930 # Get the definition of a field.
6931 # @param name the name of the field.
6932 # @return a Geo::OGR::FieldDefn object.
6933 #*
6934 sub GetFieldDefn {
6935  my $self = shift;
6936  my $d = $self->GetDefn;
6937  my $field = $d->GetFieldIndex(shift // 0);
6938  return $d->_GetFieldDefn($field);
6939 }
6940 
6941 #** @method list GetFieldNames()
6942 # Object method.
6943 # @return a list of the names of the fields in this layer. The
6944 # non-geometry field names are first in the list and then the geometry
6945 # fields.
6946 #*
6947 sub GetFieldNames {
6948  my $self = shift;
6949  my $d = $self->GetDefn;
6950  my @ret;
6951  for (my $i = 0; $i < $d->GetFieldCount; $i++) {
6952  push @ret, $d->GetFieldDefn($i)->Name();
6953  }
6954  for (my $i = 0; $i < $d->GetGeomFieldCount; $i++) {
6955  push @ret, $d->GetGeomFieldDefn($i)->Name();
6956  }
6957  return @ret;
6958 }
6959 
6960 #** @method scalar GetGeomFieldDefn($name)
6961 # Object method.
6962 # Get the definition of a spatial field.
6963 # @param name the name of the spatial field.
6964 # @return a Geo::OGR::GeomFieldDefn object.
6965 #*
6966 sub GetGeomFieldDefn {
6967  my $self = shift;
6968  my $d = $self->GetDefn;
6969  my $field = $d->GetGeomFieldIndex(shift // 0);
6970  return $d->_GetGeomFieldDefn($field);
6971 }
6972 
6973 #** @method scalar GetName()
6974 # Object method.
6975 # @return the name of the layer.
6976 #*
6977 sub GetName {
6978 }
6979 
6980 #** @method Geo::OGR::Feature GetNextFeature()
6981 # Object method.
6982 # @return iteratively Geo::OGR::Feature objects from the layer. The
6983 # iteration obeys the spatial and the attribute filter.
6984 #*
6985 sub GetNextFeature {
6986 }
6987 
6988 #** @method hash reference GetSchema()
6989 # Object method.
6990 # @brief Get the schema of this layer.
6991 # @note The schema of a layer cannot be set with this method. If you
6992 # have a Geo::OGR::FeatureDefn object before creating the layer, use
6993 # its schema in the Geo::OGR::CreateLayer method.
6994 # @return the schema of this layer, as in Geo::OGR::FeatureDefn::Schema.
6995 #*
6996 sub GetSchema {
6997  my $self = shift;
6998  carp "Schema of a layer should not be set directly." if @_;
6999  if (@_ and @_ % 2 == 0) {
7000  my %schema = @_;
7001  if ($schema{Fields}) {
7002  for my $field (@{$schema{Fields}}) {
7003  $self->CreateField($field);
7004  }
7005  }
7006  }
7007  return $self->GetDefn->Schema;
7008 }
7009 
7010 #** @method Geo::OGR::Geometry GetSpatialFilter()
7011 # Object method.
7012 # @return a new Geo::OGR::Geometry object
7013 #*
7014 sub GetSpatialFilter {
7015 }
7016 
7017 #** @method GetStyleTable()
7018 #*
7019 sub GetStyleTable {
7020 }
7021 
7022 #** @method Identity(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
7023 # Object method.
7024 # The result layer contains features whose geometries represent areas
7025 # that are in the input layer. The features in the result layer have
7026 # attributes from both input and method layers. The schema of the
7027 # result layer can be set by the user or, if it is empty, is
7028 # initialized to contain all fields in input and method layers.
7029 # @param method method layer.
7030 # @param result result layer.
7031 # @param options a reference to an options hash.
7032 # @param callback [optional] a reference to a subroutine, which will
7033 # be called with parameters (number progress, string msg, callback_data)
7034 # @param callback_data [optional]
7035 #*
7036 sub Identity {
7037 }
7038 
7039 #** @method InsertFeature($feature)
7040 # Object method.
7041 # Creates a new feature which has the schema of the layer and
7042 # initializes it with data from the argument. Then inserts the feature
7043 # into the layer (using CreateFeature). Uses Geo::OGR::Feature::Row or
7044 # Geo::OGR::Feature::Tuple.
7045 # @param feature a Geo::OGR::Feature object or reference to feature
7046 # data in a hash (as in Geo::OGR::Feature::Row) or in an array (as in
7047 # Geo::OGR::Feature::Tuple)
7048 # @return the new feature.
7049 #*
7050 sub InsertFeature {
7051  my $self = shift;
7052  my $feature = shift;
7053  error("Usage: \$feature->InsertFeature(reference to a hash or array).") unless ref($feature);
7054  my $new = Geo::OGR::Feature->new(Schema => $self, Values => $feature);
7055  $self->CreateFeature($new);
7056  return unless defined wantarray;
7057  keep($new, $self);
7058 }
7059 
7060 #** @method Intersection(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
7061 # Object method.
7062 # The result layer contains features whose geometries represent areas
7063 # that are common between features in the input layer and in the
7064 # method layer. The schema of the result layer can be set before
7065 # calling this method, or is initialized to contain all fields from
7066 # this and method layer.
7067 # @param method method layer.
7068 # @param result result layer.
7069 # @param options a reference to an options hash.
7070 # @param callback [optional] a reference to a subroutine, which will
7071 # be called with parameters (number progress, string msg, callback_data)
7072 # @param callback_data [optional]
7073 #*
7074 sub Intersection {
7075 }
7076 
7077 #** @method RELEASE_PARENT()
7078 #*
7079 sub RELEASE_PARENT {
7080  my $self = shift;
7081  unkeep($self);
7082 }
7083 
7084 #** @method ReorderField()
7085 #*
7086 sub ReorderField {
7087 }
7088 
7089 #** @method ReorderFields()
7090 #*
7091 sub ReorderFields {
7092 }
7093 
7094 #** @method ResetReading()
7095 # Object method.
7096 # Initialize the layer object for iterative reading.
7097 #*
7098 sub ResetReading {
7099 }
7100 
7101 #** @method RollbackTransaction()
7102 # Object method.
7103 #*
7104 sub RollbackTransaction {
7105 }
7106 
7107 #** @method hash reference Row(%row)
7108 # Object method.
7109 # Get and/or set the data of a feature that has the supplied feature
7110 # id (the next feature obtained with GetNextFeature is used if feature
7111 # id is not given). Calls Geo::OGR::Feature::Row.
7112 # @param row [optional] feature data
7113 # @return a reference to feature data in a hash
7114 #*
7115 sub Row {
7116  my $self = shift;
7117  my $update = @_ > 0;
7118  my %row = @_;
7119  my $feature = defined $row{FID} ? $self->GetFeature($row{FID}) : $self->GetNextFeature;
7120  return unless $feature;
7121  my $ret;
7122  if (defined wantarray) {
7123  $ret = $feature->Row(@_);
7124  } else {
7125  $feature->Row(@_);
7126  }
7127  $self->SetFeature($feature) if $update;
7128  return unless defined wantarray;
7129  return $ret;
7130 }
7131 
7132 #** @method SetAttributeFilter($filter_string)
7133 # Object method.
7134 # Set or clear the attribute filter.
7135 # @param filter_string a SQL WHERE clause or undef to clear the
7136 # filter.
7137 #*
7138 sub SetAttributeFilter {
7139 }
7140 
7141 #** @method SetFeature($feature)
7142 # Object method.
7143 # @note The feature should have the same schema as the layer.
7144 #
7145 # Replaces a feature in the layer based on the given feature's
7146 # id. Requires RandomWrite capability.
7147 # @param feature a Geo::OGR::Feature object
7148 #*
7149 sub SetFeature {
7150 }
7151 
7152 #** @method SetIgnoredFields(@fields)
7153 # Object method.
7154 # @param fields a list of field names
7155 #*
7156 sub SetIgnoredFields {
7157 }
7158 
7159 #** @method SetNextByIndex($new_index)
7160 # Object method.
7161 # @param new_index the index to which set the read cursor in the
7162 # current iteration
7163 #*
7164 sub SetNextByIndex {
7165 }
7166 
7167 #** @method SetSpatialFilter($filter)
7168 # Object method.
7169 # @param filter [optional] a Geo::OGR::Geometry object. If not given,
7170 # removes the filter if there is one.
7171 #*
7172 sub SetSpatialFilter {
7173 }
7174 
7175 #** @method SetSpatialFilterRect($minx, $miny, $maxx, $maxy)
7176 # Object method.
7177 # @param minx
7178 # @param miny
7179 # @param maxx
7180 # @param maxy
7181 #*
7182 sub SetSpatialFilterRect {
7183 }
7184 
7185 #** @method SetStyleTable()
7186 #*
7187 sub SetStyleTable {
7188 }
7189 
7190 #** @method Geo::OGR::Geometry SpatialFilter(@filter)
7191 # Object method.
7192 # @param filter [optional] a Geo::OGR::Geometry object or a string. An
7193 # undefined value removes the filter if there is one.
7194 # @return a new Geo::OGR::Geometry object
7195 # @param filter [optional] a rectangle ($minx, $miny, $maxx, $maxy).
7196 # @return a new Geo::OGR::Geometry object
7197 #*
7198 sub SpatialFilter {
7199  my $self = shift;
7200  $self->SetSpatialFilter($_[0]) if @_ == 1;
7201  $self->SetSpatialFilterRect(@_) if @_ == 4;
7202  return unless defined wantarray;
7203  $self->GetSpatialFilter;
7204 }
7205 
7206 #** @method Geo::OSR::SpatialReference SpatialReference($name, Geo::OSR::SpatialReference sr)
7207 # Object method.
7208 # @note A.k.a GetSpatialRef.
7209 # Get or set the projection of a spatial field of this layer. Gets or
7210 # sets the projection of the first field if no field name is given.
7211 # @param name [optional] a name of a spatial field in this layer.
7212 # @param sr [optional] a Geo::OSR::SpatialReference object,
7213 # which replaces the existing projection.
7214 # @return a Geo::OSR::SpatialReference object, which represents the
7215 # projection in the given spatial field.
7216 #*
7217 sub SpatialReference {
7218  my $self = shift;
7219  my $d = $self->GetDefn;
7220  my $field = @_ == 2 ? $d->GetGeomFieldIndex(shift // 0) : 0;
7221  my $sr = shift;
7222  my $d2 = $d->_GetGeomFieldDefn($field);
7223  $d2->SpatialReference($sr) if defined $sr;
7224  return $d2->SpatialReference() if defined wantarray;
7225 }
7226 
7227 #** @method StartTransaction()
7228 # Object method.
7229 #*
7230 sub StartTransaction {
7231 }
7232 
7233 #** @method SymDifference(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
7234 # Object method.
7235 # The result layer contains features whose geometries represent areas
7236 # that are in either in the input layer or in the method layer but not
7237 # in both. The features in the result layer have attributes from both
7238 # input and method layers. For features which represent areas that are
7239 # only in the input or in the method layer the respective attributes
7240 # have undefined values. The schema of the result layer can be set by
7241 # the user or, if it is empty, is initialized to contain all fields in
7242 # the input and method layers.
7243 # @param method method layer.
7244 # @param result result layer.
7245 # @param options a reference to an options hash.
7246 # @param callback [optional] a reference to a subroutine, which will
7247 # be called with parameters (number progress, string msg, callback_data)
7248 # @param callback_data [optional]
7249 #*
7250 sub SymDifference {
7251 }
7252 
7253 #** @method SyncToDisk()
7254 # Object method.
7255 #*
7256 sub SyncToDisk {
7257 }
7258 
7259 #** @method scalar TestCapability($cap)
7260 # Object method.
7261 # @param cap A capability string.
7262 # @return a boolean value indicating whether the layer has the
7263 # specified capability.
7264 #*
7265 sub TestCapability {
7266  my($self, $cap) = @_;
7267  return _TestCapability($self, $CAPABILITIES{$cap});
7268 }
7269 
7270 #** @method list Tuple(@tuple)
7271 # Object method.
7272 # Get and/set the data of a feature that has the supplied feature id
7273 # (the next feature obtained with GetNextFeature is used if feature id
7274 # is not given). The expected data in the tuple is: ([feature id,]
7275 # non-spatial fields, spatial fields). Calls Geo::OGR::Feature::Tuple.
7276 # @param tuple [optional] feature data
7277 # @note The schema of the tuple needs to be the same as that of the
7278 # layer.
7279 # @return a reference to feature data in an array
7280 #*
7281 sub Tuple {
7282  my $self = shift;
7283  my $FID = shift;
7284  my $feature = defined $FID ? $self->GetFeature($FID) : $self->GetNextFeature;
7285  return unless $feature;
7286  my $set = @_ > 0;
7287  unshift @_, $feature->GetFID if $set;
7288  my @ret;
7289  if (defined wantarray) {
7290  @ret = $feature->Tuple(@_);
7291  } else {
7292  $feature->Tuple(@_);
7293  }
7294  $self->SetFeature($feature) if $set;
7295  return unless defined wantarray;
7296  return @ret;
7297 }
7298 
7299 #** @method Union(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
7300 # Object method.
7301 # The result layer contains features whose geometries represent areas
7302 # that are in either in the input layer or in the method layer. The
7303 # schema of the result layer can be set before calling this method, or
7304 # is initialized to contain all fields from this and method layer.
7305 # @param method method layer.
7306 # @param result result layer.
7307 # @param options a reference to an options hash.
7308 # @param callback [optional] a reference to a subroutine, which will
7309 # be called with parameters (number progress, string msg, callback_data)
7310 # @param callback_data [optional]
7311 #*
7312 sub Union {
7313 }
7314 
7315 #** @method Update(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
7316 # Object method.
7317 # The result layer contains features whose geometries represent areas
7318 # that are either in the input layer or in the method layer. The
7319 # features in the result layer have areas of the features of the
7320 # method layer or those ares of the features of the input layer that
7321 # are not covered by the method layer. The features of the result
7322 # layer get their attributes from the input layer. The schema of the
7323 # result layer can be set by the user or, if it is empty, is
7324 # initialized to contain all fields in the input layer.
7325 # @param method method layer.
7326 # @param result result layer.
7327 # @param options a reference to an options hash.
7328 # @param callback [optional] a reference to a subroutine, which will
7329 # be called with parameters (number progress, string msg, callback_data)
7330 # @param callback_data [optional]
7331 #*
7332 sub Update {
7333 }
7334 
7335 #** @class Geo::OGR::StyleTable
7336 #*
7337 package Geo::OGR::StyleTable;
7338 
7339 use base qw(Geo::OGR)
7340 
7341 #** @method AddStyle()
7342 #*
7343 sub AddStyle {
7344 }
7345 
7346 #** @method Find()
7347 #*
7348 sub Find {
7349 }
7350 
7351 #** @method GetLastStyleName()
7352 #*
7353 sub GetLastStyleName {
7354 }
7355 
7356 #** @method GetNextStyle()
7357 #*
7358 sub GetNextStyle {
7359 }
7360 
7361 #** @method LoadStyleTable()
7362 #*
7363 sub LoadStyleTable {
7364 }
7365 
7366 #** @method ResetStyleStringReading()
7367 #*
7368 sub ResetStyleStringReading {
7369 }
7370 
7371 #** @method SaveStyleTable()
7372 #*
7373 sub SaveStyleTable {
7374 }
7375 
7376 #** @method new()
7377 #*
7378 sub new {
7379  my $pkg = shift;
7380  my $self = Geo::OGRc::new_StyleTable(@_);
7381  bless $self, $pkg if defined($self);
7382 }
7383 
7384 #** @class Geo::OSR
7385 # @brief Base class for projection related classes.
7386 # @details
7387 #*
7388 package Geo::OSR;
7389 
7390 #** @method list AngularUnits()
7391 # Package subroutine.
7392 # @return list of known angular units.
7393 #*
7394 sub AngularUnits {
7395  return keys %ANGULAR_UNITS;
7396 }
7397 
7398 #** @method CreateCoordinateTransformation()
7399 #*
7400 sub CreateCoordinateTransformation {
7401 }
7402 
7403 #** @method list Datums()
7404 # Package subroutine.
7405 # @return list of known datums.
7406 #*
7407 sub Datums {
7408  return keys %DATUMS;
7409 }
7410 
7411 #** @method list GetProjectionMethodParamInfo($projection, $parameter)
7412 # Package subroutine.
7413 # @param projection one of Geo::OSR::Projections
7414 # @param parameter one of Geo::OSR::Parameters
7415 # @return a list ($user_friendly_name, $type, $default_value).
7416 #*
7417 sub GetProjectionMethodParamInfo {
7418 }
7419 
7420 #** @method list GetProjectionMethodParameterList($projection)
7421 # Package subroutine.
7422 # @param projection one of Geo::OSR::Projections
7423 # @return a list (arrayref parameters, $projection_name).
7424 #*
7425 sub GetProjectionMethodParameterList {
7426 }
7427 
7428 #** @method array reference GetProjectionMethods()
7429 # Package subroutine.
7430 # @deprecated Use Geo::OSR::Projections.
7431 #
7432 # @return reference to an array of possible projection methods.
7433 #*
7434 sub GetProjectionMethods {
7435 }
7436 
7437 #** @method scalar GetUserInputAsWKT($name)
7438 # Package subroutine.
7439 # @param name the user input
7440 # @return a WKT string.
7441 #*
7442 sub GetUserInputAsWKT {
7443 }
7444 
7445 #** @method scalar GetWellKnownGeogCSAsWKT($name)
7446 # Package subroutine.
7447 # @brief Get well known geographic coordinate system as WKT
7448 # @param name a well known name
7449 # @return a WKT string.
7450 #*
7451 sub GetWellKnownGeogCSAsWKT {
7452 }
7453 
7454 #** @method list LinearUnits()
7455 # Package subroutine.
7456 # @return list of known linear units.
7457 #*
7458 sub LinearUnits {
7459  return keys %LINEAR_UNITS;
7460 }
7461 
7462 #** @method OAO_Down()
7463 #*
7464 sub OAO_Down {
7465 }
7466 
7467 #** @method OAO_East()
7468 #*
7469 sub OAO_East {
7470 }
7471 
7472 #** @method OAO_North()
7473 #*
7474 sub OAO_North {
7475 }
7476 
7477 #** @method OAO_Other()
7478 #*
7479 sub OAO_Other {
7480 }
7481 
7482 #** @method OAO_South()
7483 #*
7484 sub OAO_South {
7485 }
7486 
7487 #** @method OAO_Up()
7488 #*
7489 sub OAO_Up {
7490 }
7491 
7492 #** @method OAO_West()
7493 #*
7494 sub OAO_West {
7495 }
7496 
7497 #** @method list Parameters()
7498 # Package subroutine.
7499 # @return list of known projection parameters.
7500 #*
7501 sub Parameters {
7502  return keys %PARAMETERS;
7503 }
7504 
7505 #** @method list Projections()
7506 # Package subroutine.
7507 # @return list of known projections.
7508 #*
7509 sub Projections {
7510  return keys %PROJECTIONS;
7511 }
7512 
7513 #** @method RELEASE_PARENT()
7514 #*
7515 sub RELEASE_PARENT {
7516 }
7517 
7518 #** @method SRS_PM_GREENWICH()
7519 #*
7520 sub SRS_PM_GREENWICH {
7521 }
7522 
7523 #** @method SRS_WGS84_INVFLATTENING()
7524 #*
7525 sub SRS_WGS84_INVFLATTENING {
7526 }
7527 
7528 #** @method SRS_WGS84_SEMIMAJOR()
7529 #*
7530 sub SRS_WGS84_SEMIMAJOR {
7531 }
7532 
7533 #** @method SRS_WKT_WGS84()
7534 #*
7535 sub SRS_WKT_WGS84 {
7536 }
7537 
7538 #** @class Geo::OSR::CoordinateTransformation
7539 # @brief An object for transforming from one projection to another.
7540 # @details
7541 #*
7542 package Geo::OSR::CoordinateTransformation;
7543 
7544 use base qw(Geo::OSR)
7545 
7546 #** @method array reference TransformPoint($x, $y, $z)
7547 # Object method.
7548 # @param x
7549 # @param y
7550 # @param z [optional]
7551 # @return arrayref = [$x, $y, $z]
7552 #*
7553 sub TransformPoint {
7554 }
7555 
7556 #** @method TransformPoints(arrayref points)
7557 # Object method.
7558 # @param points [in/out] a reference to a list of points (line string
7559 # or ring) that is modified in-place. A list of points is: ([x, y, z],
7560 # [x, y, z], ...), where z is optional. Supports also lists of line
7561 # strings and polygons.
7562 #*
7563 sub TransformPoints {
7564  my($self, $points) = @_;
7565  _TransformPoints($self, $points), return unless ref($points->[0]->[0]);
7566  for my $p (@$points) {
7567  TransformPoints($self, $p);
7568  }
7569 }
7570 1;
7571 # This file was automatically generated by SWIG (http://www.swig.org).
7572 # Version 2.0.7
7573 #
7574 # Do not make changes to this file unless you know what you are doing--modify
7575 # the SWIG interface file instead.
7576 }
7577 
7578 #** @method Geo::OSR::CoordinateTransformation new($src, $dst)
7579 # Class method.
7580 # @param src a Geo::OSR::SpatialReference object
7581 # @param dst a Geo::OSR::SpatialReference object
7582 # @return a new Geo::OSR::CoordinateTransformation object
7583 #*
7584 sub new {
7585  my $pkg = shift;
7586  my $self = Geo::OSRc::new_CoordinateTransformation(@_);
7587  bless $self, $pkg if defined($self);
7588 }
7589 
7590 #** @class Geo::OSR::SpatialReference
7591 # @brief A spatial reference system.
7592 # @details <a href="http://www.gdal.org/classOGRSpatialReference.html">Documentation
7593 # of the underlying C++ class at www.gdal.org</a>
7594 #*
7595 package Geo::OSR::SpatialReference;
7596 
7597 use base qw(Geo::OSR)
7598 
7599 #** @method As()
7600 #*
7601 sub As {
7602 }
7603 
7604 #** @method AutoIdentifyEPSG()
7605 # Object method.
7606 # Set EPSG authority info if possible.
7607 #*
7608 sub AutoIdentifyEPSG {
7609 }
7610 
7611 #** @method Geo::OSR::SpatialReference Clone()
7612 # Object method.
7613 # Make a duplicate of this SpatialReference object.
7614 # @return a new Geo::OSR::SpatialReference object
7615 #*
7616 sub Clone {
7617 }
7618 
7619 #** @method Geo::OSR::SpatialReference CloneGeogCS()
7620 # Object method.
7621 # Make a duplicate of the GEOGCS node of this SpatialReference object.
7622 # @return a new Geo::OSR::SpatialReference object
7623 #*
7624 sub CloneGeogCS {
7625 }
7626 
7627 #** @method CopyGeogCSFrom($rhs)
7628 # Object method.
7629 # @param rhs Geo::OSR::SpatialReference
7630 #*
7631 sub CopyGeogCSFrom {
7632 }
7633 
7634 #** @method EPSGTreatsAsLatLong()
7635 # Object method.
7636 # Returns TRUE if EPSG feels this geographic coordinate system should be treated as having lat/long coordinate ordering.
7637 #*
7638 sub EPSGTreatsAsLatLong {
7639 }
7640 
7641 #** @method EPSGTreatsAsNorthingEasting()
7642 #*
7643 sub EPSGTreatsAsNorthingEasting {
7644 }
7645 
7646 #** @method Export($format)
7647 # Object method.
7648 # Export the spatial reference to a selected format.
7649 # @note a.k.a. As
7650 #
7651 # @param format One of the following. The return value is explained
7652 # after the format. Other arguments are explained in parenthesis.
7653 # - WKT (Text): Well Known Text string
7654 # - PrettyWKT: Well Known Text string nicely formatted (simplify)
7655 # - Proj4: PROJ.4 string
7656 # - PCI: a list: ($proj_string, $units, [$parms1, ...])
7657 # - USGS: a list: ($code, $zone, [$parms1, ...], $datum)
7658 # - GML (XML): GML based string (dialect)
7659 # - MapInfoCS (MICoordSys): MapInfo style co-ordinate system definition
7660 #
7661 # @note The named parameter syntax also works and is needed is those
7662 # cases when other arguments need or may be given. The format should
7663 # be given using key as, 'to' or 'format'.
7664 #
7665 # @note ExportTo* and AsText methods also exist but are not documented here.
7666 #
7667 # @return a scalar or a list depending on the export format
7668 #*
7669 sub Export {
7670  my $self = shift;
7671  my $format;
7672  $format = pop if @_ == 1;
7673  my %params = @_;
7674  $format //= $params{to} //= $params{format} //= $params{as} //= '';
7675  my $simplify = $params{simplify} // 0;
7676  my $dialect = $params{dialect} // '';
7677  my %converters = (
7678  WKT => sub { return ExportToWkt($self) },
7679  Text => sub { return ExportToWkt($self) },
7680  PrettyWKT => sub { return ExportToPrettyWkt($self, $simplify) },
7681  Proj4 => sub { return ExportToProj4($self) },
7682  PCI => sub { return ExportToPCI($self) },
7683  USGS => sub { return ExportToUSGS($self) },
7684  GML => sub { return ExportToXML($self, $dialect) },
7685  XML => sub { return ExportToXML($self, $dialect) },
7686  MICoordSys => sub { return ExportToMICoordSys() },
7687  MapInfoCS => sub { return ExportToMICoordSys() },
7688  );
7689  error(1, $format, \%converters) unless $converters{$format};
7690  return $converters{$format}->();
7691 }
7692 
7693 #** @method Fixup()
7694 # Object method.
7695 #*
7696 sub Fixup {
7697 }
7698 
7699 #** @method FixupOrdering()
7700 # Object method.
7701 #*
7702 sub FixupOrdering {
7703 }
7704 
7705 #** @method scalar GetAngularUnits()
7706 # Object method.
7707 # @return a number
7708 #*
7709 sub GetAngularUnits {
7710 }
7711 
7712 #** @method GetAngularUnitsName()
7713 #*
7714 sub GetAngularUnitsName {
7715 }
7716 
7717 #** @method scalar GetAttrValue($name, $child = 0)
7718 # Object method.
7719 # @param name
7720 # @param child
7721 # @return string
7722 #*
7723 sub GetAttrValue {
7724 }
7725 
7726 #** @method scalar GetAuthorityCode($target_key)
7727 # Object method.
7728 # @param target_key
7729 # @return string
7730 #*
7731 sub GetAuthorityCode {
7732 }
7733 
7734 #** @method scalar GetAuthorityName($target_key)
7735 # Object method.
7736 # @param target_key
7737 # @return string
7738 #*
7739 sub GetAuthorityName {
7740 }
7741 
7742 #** @method GetAxisName()
7743 #*
7744 sub GetAxisName {
7745 }
7746 
7747 #** @method GetAxisOrientation()
7748 #*
7749 sub GetAxisOrientation {
7750 }
7751 
7752 #** @method GetInvFlattening()
7753 # Object method.
7754 #*
7755 sub GetInvFlattening {
7756 }
7757 
7758 #** @method scalar GetLinearUnits()
7759 # Object method.
7760 # @return a number
7761 #*
7762 sub GetLinearUnits {
7763 }
7764 
7765 #** @method scalar GetLinearUnitsName()
7766 # Object method.
7767 # @return string
7768 #*
7769 sub GetLinearUnitsName {
7770 }
7771 
7772 #** @method scalar GetNormProjParm($name, $default_val = 0.0)
7773 # Object method.
7774 # @param name
7775 # @param default_val
7776 # @return a number
7777 #*
7778 sub GetNormProjParm {
7779 }
7780 
7781 #** @method scalar GetProjParm($name, $default_val = 0.0)
7782 # Object method.
7783 # @param name
7784 # @param default_val
7785 # @return a number
7786 #*
7787 sub GetProjParm {
7788 }
7789 
7790 #** @method GetSemiMajor()
7791 # Object method.
7792 #*
7793 sub GetSemiMajor {
7794 }
7795 
7796 #** @method GetSemiMinor()
7797 # Object method.
7798 #*
7799 sub GetSemiMinor {
7800 }
7801 
7802 #** @method GetTOWGS84()
7803 # Object method.
7804 # @return array = ($p1, $p2, $p3, $p4, $p5, $p6, $p7)
7805 #*
7806 sub GetTOWGS84 {
7807 }
7808 
7809 #** @method GetTargetLinearUnits()
7810 #*
7811 sub GetTargetLinearUnits {
7812 }
7813 
7814 #** @method GetUTMZone()
7815 # Object method.
7816 # Get UTM zone information.
7817 # @return The UTM zone (integer). In scalar context the returned value
7818 # is negative for southern hemisphere zones. In list context returns
7819 # two values ($zone, $north), where $zone is always non-negative and
7820 # $north is true or false.
7821 #*
7822 sub GetUTMZone {
7823  my $self = shift;
7824  my $zone = _GetUTMZone($self);
7825  if (wantarray) {
7826  my $north = 1;
7827  if ($zone < 0) {
7828  $zone *= -1;
7829  $north = 0;
7830  }
7831  return ($zone, $north);
7832  } else {
7833  return $zone;
7834  }
7835 }
7836 
7837 #** @method ImportFromOzi()
7838 #*
7839 sub ImportFromOzi {
7840 }
7841 
7842 #** @method scalar IsCompound()
7843 # Object method.
7844 # @return boolean
7845 #*
7846 sub IsCompound {
7847 }
7848 
7849 #** @method scalar IsGeocentric()
7850 # Object method.
7851 # @return boolean
7852 #*
7853 sub IsGeocentric {
7854 }
7855 
7856 #** @method scalar IsGeographic()
7857 # Object method.
7858 # @return boolean
7859 #*
7860 sub IsGeographic {
7861 }
7862 
7863 #** @method scalar IsLocal()
7864 # Object method.
7865 # @return boolean
7866 #*
7867 sub IsLocal {
7868 }
7869 
7870 #** @method scalar IsProjected()
7871 # Object method.
7872 # @return boolean
7873 #*
7874 sub IsProjected {
7875 }
7876 
7877 #** @method scalar IsSame($rs)
7878 # Object method.
7879 # @param rs a Geo::OSR::SpatialReference object
7880 # @return boolean
7881 #*
7882 sub IsSame {
7883 }
7884 
7885 #** @method scalar IsSameGeogCS($rs)
7886 # Object method.
7887 # @param rs a Geo::OSR::SpatialReference object
7888 # @return boolean
7889 #*
7890 sub IsSameGeogCS {
7891 }
7892 
7893 #** @method scalar IsSameVertCS($rs)
7894 # Object method.
7895 # @param rs a Geo::OSR::SpatialReference object
7896 # @return boolean
7897 #*
7898 sub IsSameVertCS {
7899 }
7900 
7901 #** @method scalar IsVertical()
7902 # Object method.
7903 # @return boolean
7904 #*
7905 sub IsVertical {
7906 }
7907 
7908 #** @method MorphFromESRI()
7909 # Object method.
7910 #*
7911 sub MorphFromESRI {
7912 }
7913 
7914 #** @method MorphToESRI()
7915 # Object method.
7916 #*
7917 sub MorphToESRI {
7918 }
7919 
7920 #** @method Set(%params)
7921 # Object method.
7922 # Set a parameter or parameters in the spatial reference object.
7923 # @param params Named parameters. Recognized keys and respective
7924 # values are the following.
7925 # - Authority: authority name (give also TargetKey, Node and Code)
7926 # - TargetKey:
7927 # - Node: partial or complete path to the target node (Node and Value together sets an attribute value)
7928 # - Code: code for value with an authority
7929 # - Value: value to be assigned to a node, a projection parameter or an object
7930 # - AngularUnits: angular units for the geographic coordinate system (give also Value) (one of Geo::OSR::LinearUnits)
7931 # - LinearUnits: linear units for the target node or the object (give also Value and optionally Node) (one of Geo::OSR::LinearUnits)
7932 # - Parameter: projection parameter to set (give also Value and Normalized) (one of Geo::OSR::Parameters)
7933 # - Normalized: set to true to indicate that the Value argument is in "normalized" form
7934 # - Name: a well known name of a geographic coordinate system (e.g. WGS84)
7935 # - GuessFrom: arbitrary text that specifies a projection ("user input")
7936 # - LOCAL_CS: name of a local coordinate system
7937 # - GeocentricCS: name of a geocentric coordinate system
7938 # - VerticalCS: name of a vertical coordinate system (give also Datum and optionally VertDatumType [default is 2005])
7939 # - Datum: a known (OGC or EPSG) name (or(?) one of Geo::OSR::Datums)
7940 # - CoordinateSystem: 'WGS', 'UTM', 'State Plane', or a user visible name (give optionally also Parameters, Zone, North, NAD83, UnitName, UnitConversionFactor, Datum, Spheroid, HorizontalCS, and/or VerticalCS
7941 # - Parameters: a reference to a list containing the coordinate system or projection parameters
7942 # - Zone: zone for setting up UTM or State Plane coordinate systems (State Plane zone in USGS numbering scheme)
7943 # - North: set false for southern hemisphere
7944 # - NAD83: set false if the NAD27 zone definition should be used instead of NAD83
7945 # - UnitName: to override the legal definition for a zone
7946 # - UnitConversionFactor: to override the legal definition for a zone
7947 # - Spheroid: user visible name
7948 # - HorizontalCS: Horizontal coordinate system name
7949 # - Projection: name of a projection, one of Geo::OSR::Projections (give also optionally Parameters and Variant)
7950 #
7951 # @note Numerous Set* methods also exist but are not documented here.
7952 #*
7953 sub Set {
7954  my($self, %params) = @_;
7955  if (exists $params{Authority} and exists $params{TargetKey} and exists $params{Node} and exists $params{Code}) {
7956  SetAuthority($self, $params{TargetKey}, $params{Authority}, $params{Code});
7957  } elsif (exists $params{Node} and exists $params{Value}) {
7958  SetAttrValue($self, $params{Node}, $params{Value});
7959  } elsif (exists $params{AngularUnits} and exists $params{Value}) {
7960  SetAngularUnits($self, $params{AngularUnits}, $params{Value});
7961  } elsif (exists $params{LinearUnits} and exists $params{Node} and exists $params{Value}) {
7962  SetTargetLinearUnits($self, $params{Node}, $params{LinearUnits}, $params{Value});
7963  } elsif (exists $params{LinearUnits} and exists $params{Value}) {
7964  SetLinearUnitsAndUpdateParameters($self, $params{LinearUnits}, $params{Value});
7965  } elsif ($params{Parameter} and exists $params{Value}) {
7966  error(1, $params{Parameter}, \%Geo::OSR::PARAMETERS) unless exists $Geo::OSR::PARAMETERS{$params{Parameter}};
7967  $params{Normalized} ?
7968  SetNormProjParm($self, $params{Parameter}, $params{Value}) :
7969  SetProjParm($self, $params{Parameter}, $params{Value});
7970  } elsif (exists $params{Name}) {
7971  SetWellKnownGeogCS($self, $params{Name});
7972  } elsif (exists $params{GuessFrom}) {
7973  SetFromUserInput($self, $params{GuessFrom});
7974  } elsif (exists $params{LOCAL_CS}) {
7975  SetLocalCS($self, $params{LOCAL_CS});
7976  } elsif (exists $params{GeocentricCS}) {
7977  SetGeocCS($self, $params{GeocentricCS});
7978  } elsif (exists $params{VerticalCS} and $params{Datum}) {
7979  my $type = $params{VertDatumType} || 2005;
7980  SetVertCS($self, $params{VerticalCS}, $params{Datum}, $type);
7981  } elsif (exists $params{CoordinateSystem}) {
7982  my @parameters = ();
7983  @parameters = @{$params{Parameters}} if ref($params{Parameters});
7984  if ($params{CoordinateSystem} eq 'State Plane' and exists $params{Zone}) {
7985  my $NAD83 = exists $params{NAD83} ? $params{NAD83} : 1;
7986  my $name = exists $params{UnitName} ? $params{UnitName} : undef;
7987  my $c = exists $params{UnitConversionFactor} ? $params{UnitConversionFactor} : 0.0;
7988  SetStatePlane($self, $params{Zone}, $NAD83, $name, $c);
7989  } elsif ($params{CoordinateSystem} eq 'UTM' and exists $params{Zone} and exists $params{North}) {
7990  my $north = exists $params{North} ? $params{North} : 1;
7991  SetUTM($self, $params{Zone}, $north);
7992  } elsif ($params{CoordinateSystem} eq 'WGS') {
7993  SetTOWGS84($self, @parameters);
7994  } elsif ($params{CoordinateSystem} and $params{Datum} and $params{Spheroid}) {
7995  SetGeogCS($self, $params{CoordinateSystem}, $params{Datum}, $params{Spheroid}, @parameters);
7996  } elsif ($params{CoordinateSystem} and $params{HorizontalCS} and $params{VerticalCS}) {
7997  SetCompoundCS($self, $params{CoordinateSystem}, $params{HorizontalCS}, $params{VerticalCS});
7998  } else {
7999  SetProjCS($self, $params{CoordinateSystem});
8000  }
8001  } elsif (exists $params{Projection}) {
8002  error(1, $params{Projection}, \%Geo::OSR::PROJECTIONS) unless exists $Geo::OSR::PROJECTIONS{$params{Projection}};
8003  my @parameters = ();
8004  @parameters = @{$params{Parameters}} if ref($params{Parameters});
8005  if ($params{Projection} eq 'Albers_Conic_Equal_Area') {
8006  SetACEA($self, @parameters);
8007  } elsif ($params{Projection} eq 'Azimuthal_Equidistant') {
8008  SetAE($self, @parameters);
8009  } elsif ($params{Projection} eq 'Bonne') {
8010  SetBonne($self, @parameters);
8011  } elsif ($params{Projection} eq 'Cylindrical_Equal_Area') {
8012  SetCEA($self, @parameters);
8013  } elsif ($params{Projection} eq 'Cassini_Soldner') {
8014  SetCS($self, @parameters);
8015  } elsif ($params{Projection} eq 'Equidistant_Conic') {
8016  SetEC($self, @parameters);
8017  # Eckert_I, Eckert_II, Eckert_III, Eckert_V ?
8018  } elsif ($params{Projection} eq 'Eckert_IV') {
8019  SetEckertIV($self, @parameters);
8020  } elsif ($params{Projection} eq 'Eckert_VI') {
8021  SetEckertVI($self, @parameters);
8022  } elsif ($params{Projection} eq 'Equirectangular') {
8023  @parameters == 4 ?
8024  SetEquirectangular($self, @parameters) :
8025  SetEquirectangular2($self, @parameters);
8026  } elsif ($params{Projection} eq 'Gauss_Schreiber_Transverse_Mercator') {
8027  SetGaussSchreiberTMercator($self, @parameters);
8028  } elsif ($params{Projection} eq 'Gall_Stereographic') {
8029  SetGS($self, @parameters);
8030  } elsif ($params{Projection} eq 'Goode_Homolosine') {
8031  SetGH($self, @parameters);
8032  } elsif ($params{Projection} eq 'Interrupted_Goode_Homolosine') {
8033  SetIGH($self);
8034  } elsif ($params{Projection} eq 'Geostationary_Satellite') {
8035  SetGEOS($self, @parameters);
8036  } elsif ($params{Projection} eq 'Gnomonic') {
8037  SetGnomonic($self, @parameters);
8038  } elsif ($params{Projection} eq 'Hotine_Oblique_Mercator') {
8039  # Hotine_Oblique_Mercator_Azimuth_Center ?
8040  SetHOM($self, @parameters);
8041  } elsif ($params{Projection} eq 'Hotine_Oblique_Mercator_Two_Point_Natural_Origin') {
8042  SetHOM2PNO($self, @parameters);
8043  } elsif ($params{Projection} eq 'Krovak') {
8044  SetKrovak($self, @parameters);
8045  } elsif ($params{Projection} eq 'Lambert_Azimuthal_Equal_Area') {
8046  SetLAEA($self, @parameters);
8047  } elsif ($params{Projection} eq 'Lambert_Conformal_Conic_2SP') {
8048  SetLCC($self, @parameters);
8049  } elsif ($params{Projection} eq 'Lambert_Conformal_Conic_1SP') {
8050  SetLCC1SP($self, @parameters);
8051  } elsif ($params{Projection} eq 'Lambert_Conformal_Conic_2SP_Belgium') {
8052  SetLCCB($self, @parameters);
8053  } elsif ($params{Projection} eq 'miller_cylindrical') {
8054  SetMC($self, @parameters);
8055  } elsif ($params{Projection} =~ /^Mercator/) {
8056  # Mercator_1SP, Mercator_2SP, Mercator_Auxiliary_Sphere ?
8057  # variant is in Variant (or Name)
8058  SetMercator($self, @parameters);
8059  } elsif ($params{Projection} eq 'Mollweide') {
8060  SetMollweide($self, @parameters);
8061  } elsif ($params{Projection} eq 'New_Zealand_Map_Grid') {
8062  SetNZMG($self, @parameters);
8063  } elsif ($params{Projection} eq 'Oblique_Stereographic') {
8064  SetOS($self, @parameters);
8065  } elsif ($params{Projection} eq 'Orthographic') {
8066  SetOrthographic($self, @parameters);
8067  } elsif ($params{Projection} eq 'Polyconic') {
8068  SetPolyconic($self, @parameters);
8069  } elsif ($params{Projection} eq 'Polar_Stereographic') {
8070  SetPS($self, @parameters);
8071  } elsif ($params{Projection} eq 'Robinson') {
8072  SetRobinson($self, @parameters);
8073  } elsif ($params{Projection} eq 'Sinusoidal') {
8074  SetSinusoidal($self, @parameters);
8075  } elsif ($params{Projection} eq 'Stereographic') {
8076  SetStereographic($self, @parameters);
8077  } elsif ($params{Projection} eq 'Swiss_Oblique_Cylindrical') {
8078  SetSOC($self, @parameters);
8079  } elsif ($params{Projection} eq 'Transverse_Mercator_South_Orientated') {
8080  SetTMSO($self, @parameters);
8081  } elsif ($params{Projection} =~ /^Transverse_Mercator/) {
8082  my($variant) = $params{Projection} =~ /^Transverse_Mercator_(\w+)/;
8083  $variant //= $params{Variant} //= $params{Name};
8084  $variant ?
8085  SetTMVariant($self, $variant, @parameters) :
8086  SetTM($self, @parameters);
8087  } elsif ($params{Projection} eq 'Tunisia_Mining_Grid') {
8088  SetTMG($self, @parameters);
8089  } elsif ($params{Projection} eq 'VanDerGrinten') {
8090  SetVDG($self, @parameters);
8091  } else {
8092  # Aitoff, Craster_Parabolic, International_Map_of_the_World_Polyconic, Laborde_Oblique_Mercator
8093  # Loximuthal, Miller_Cylindrical, Quadrilateralized_Spherical_Cube, Quartic_Authalic, Two_Point_Equidistant
8094  # Wagner_I, Wagner_II, Wagner_III, Wagner_IV, Wagner_V, Wagner_VI, Wagner_VII
8095  # Winkel_I, Winkel_II, Winkel_Tripel
8096  # ?
8097  SetProjection($self, $params{Projection});
8098  }
8099  } else {
8100  error("Not enough information to create a spatial reference object.");
8101  }
8102 }
8103 
8104 #** @method StripCTParms()
8105 # Object method.
8106 #*
8107 sub StripCTParms {
8108 }
8109 
8110 #** @method Validate()
8111 # Object method.
8112 #*
8113 sub Validate {
8114 }
8115 
8116 #** @method Geo::OSR::SpatialReference new(%params)
8117 # Class method.
8118 # Create a new spatial reference object using a named parameter. This
8119 # constructor recognizes the following key words (alternative in
8120 # parenthesis): WKT (Text), Proj4, ESRI, EPSG, EPSGA, PCI, USGS, GML
8121 # (XML), URL, ERMapper (ERM), MapInfoCS (MICoordSys). The value
8122 # depends on the key.
8123 # - WKT: Well Known Text string
8124 # - Proj4: PROJ.4 string
8125 # - ESRI: reference to a list of strings (contents of ESRI .prj file)
8126 # - EPSG: EPSG code number
8127 # - EPSGA: EPSG code number (the resulting CS will have EPSG preferred axis ordering)
8128 # - PCI: listref: [PCI_projection_string, Grid_units_code, [17 cs parameters]]
8129 # - USGS: listref: [Projection_system_code, Zone, [15 cs parameters], Datum_code, Format_flag]
8130 # - GML: GML string
8131 # - URL: URL for downloading the spatial reference from
8132 # - ERMapper: listref: [Projection, Datum, Units]
8133 # - MapInfoCS: MapInfo style co-ordinate system definition
8134 #
8135 # For more information, consult the import methods in <a href="http://www.gdal.org/classOGRSpatialReference.html">OGR documentation</a>.
8136 #
8137 # @note ImportFrom* methods also exist but are not documented here.
8138 #
8139 # Usage:
8140 # \code
8141 # $sr = Geo::OSR::SpatialReference->new( key => value );
8142 # \endcode
8143 # @return a new Geo::OSR::SpatialReference object
8144 #*
8145 sub new {
8146  my $pkg = shift;
8147  my %param = @_;
8148  my $self = Geo::OSRc::new_SpatialReference();
8149  if (exists $param{WKT}) {
8150  ImportFromWkt($self, $param{WKT});
8151  } elsif (exists $param{Text}) {
8152  ImportFromWkt($self, $param{Text});
8153  } elsif (exists $param{Proj4}) {
8154  ImportFromProj4($self, $param{Proj4});
8155  } elsif (exists $param{ESRI}) {
8156  ImportFromESRI($self, @{$param{ESRI}});
8157  } elsif (exists $param{EPSG}) {
8158  ImportFromEPSG($self, $param{EPSG});
8159  } elsif (exists $param{EPSGA}) {
8160  ImportFromEPSGA($self, $param{EPSGA});
8161  } elsif (exists $param{PCI}) {
8162  ImportFromPCI($self, @{$param{PCI}});
8163  } elsif (exists $param{USGS}) {
8164  ImportFromUSGS($self, @{$param{USGS}});
8165  } elsif (exists $param{XML}) {
8166  ImportFromXML($self, $param{XML});
8167  } elsif (exists $param{GML}) {
8168  ImportFromGML($self, $param{GML});
8169  } elsif (exists $param{URL}) {
8170  ImportFromUrl($self, $param{URL});
8171  } elsif (exists $param{ERMapper}) {
8172  ImportFromERM($self, @{$param{ERMapper}});
8173  } elsif (exists $param{ERM}) {
8174  ImportFromERM($self, @{$param{ERM}});
8175  } elsif (exists $param{MICoordSys}) {
8176  ImportFromMICoordSys($self, $param{MICoordSys});
8177  } elsif (exists $param{MapInfoCS}) {
8178  ImportFromMICoordSys($self, $param{MapInfoCS});
8179  } elsif (exists $param{WGS}) {
8180  eval {
8181  SetWellKnownGeogCS($self, 'WGS'.$param{WGS});
8182  };
8183  confess last_error() if $@;
8184  } else {
8185  error("Unrecognized/missing parameters: @_.");
8186  }
8187  bless $self, $pkg if defined $self;
8188 }
8189