NAME
Geo::LibProj::FFI - Foreign function interface to PROJ coordinate transformation software
VERSION
version 0.06
SYNOPSIS
use Geo::LibProj::FFI 0.05 qw(:all);
use Feature::Compat::Defer;
my $ctx = proj_context_create()
or die "Cannot create threading context";
defer { proj_context_destroy($ctx); }
my $pj = proj_create_crs_to_crs($ctx, "EPSG:25833", "EPSG:2198", undef)
or die "Cannot create proj";
defer { proj_destroy($pj); }
($easting, $northing) = ( 500_000, 6094_800 );
$a = proj_coord( $easting, $northing, 0, 'Inf' );
$b = proj_trans( $pj, PJ_FWD, $a );
printf "Target: easting %.2f, northing %.2f\n",
$b->enu_e, $b->enu_n;
See also the example script eg/pj_obs_api_mini_demo.pl in this distribution.
DESCRIPTION
This module is a foreign function interface to the PROJ coordinate transformation / projection library. Please see the PROJ library's C function reference for further documentation. You should be able to use those C functions as if they were Perl.
This module is functional, but incomplete.
FUNCTIONS
Geo::LibProj::FFI currently offers the following functions.
Import all functions and constants by using the tag :all
.
- Threading contexts
-
proj_context_create
proj_context_destroy
proj_context_use_proj4_init_rules
- Transformation setup
-
proj_create
proj_create_argv
proj_create_crs_to_crs
proj_create_crs_to_crs_from_pj
proj_normalize_for_visualization
proj_destroy
- Area of interest
-
proj_area_create
proj_area_set_bbox
proj_area_destroy
- Coordinate transformation
-
proj_trans
- Error reporting
-
proj_context_errno
proj_errno
proj_errno_set
proj_errno_reset
proj_errno_restore
proj_errno_string
proj_context_errno_string
- Logging
-
proj_log_level
proj_log_func
- Info functions
-
proj_info
proj_pj_info
proj_grid_info
proj_init_info
- Lists
-
proj_list_operations
proj_list_ellps
proj_list_units
proj_list_angular_units
proj_list_prime_meridians
- Distances
-
proj_lp_dist
proj_lpz_dist
proj_xy_dist
proj_xyz_dist
proj_geod
- Various
-
proj_coord
- Cleanup
-
proj_cleanup
DATA TYPES
The PROJ library uses numerous composite data types to represent coordinate tuples. The primary coordinate type, PJ_COORD
, is a C union that gets passed by value. This construct is not well supported by FFI::Platypus, which this module relies on to make the PROJ library API available in Perl. The workaround implemented here is to just use the array v
internally and only model the union semantics using object methods, which is slightly slower than direct member access in C would be.
The method names are the combination of the names of the PJ_COORD
union member and the individual struct member, joined with an underscore. However, these methods will in turn access the coordinate array by calling the v()
method with the array index as argument. This extra method call may cost performance if called in a tight loop. So if speed is more important to you than readable code, you should consider just calling v()
directly rather than using the other named union/struct member methods.
$pj_coord = proj_coord( @coords );
@coords = $pj_coord->v->@*;
# Fast access to individual coordinate numbers:
$x = $pj_coord->v(0);
$y = $pj_coord->v(1);
# Access generic coordinates by named member methods:
($u, $v) = ( $c->uv_u, $c->uv_v );
($u, $v, $w) = ( $c->uvw_u, $c->uvw_v, $c->uvw_w );
($u, $v, $w, $t) = ( $c->uvwt_u, $c->uvwt_v, $c->uvwt_w, $c->uvwt_t );
# Access cartesian coordinates by named member methods:
($x, $y) = ( $c->xy_x, $c->xy_y );
($x, $y, $z) = ( $c->xyz_x, $c->xyz_y, $c->xyz_z );
($x, $y, $z, $t) = ( $c->xyzt_x, $c->xyzt_y, $c->xyzt_z, $c->xyzt_t );
# Access geodetic coordinates by named member methods:
($lamda, $phi) = ( $c->lp_lam, $c->lp_phi );
($lamda, $phi, $z) = ( $c->lpz_lam, $c->lpz_phi, $c->lpz_z );
($lamda, $phi, $z, $t) = ( $c->lpzt_lam, $c->lpzt_phi, $c->lpzt_z, $c->lpzt_t );
# Access ancillary data by named member methods:
($s, $az_fwd, $az_rev) = ( $c->geod_s, $c->geod_a1, $c->geod_a2 );
($omega, $phi, $kappa) = ( $c->opk_o, $c->opk_p, $c->opk_k );
($east, $north, $up) = ( $c->enu_e, $c->enu_n, $c->enu_u );
Modifying PJ_COORD
values is possible. All methods shown above act as mutators if a new value is passed as an argument. In the case of v()
, you can pass either an array reference or two arguments representing the array index and the new value, respectively.
$c = proj_coord( 0, 0, 0, 0 );
$c->v( [12, 34, 56] );
$c->v(1, 78);
$c->xy_x(99);
say join ' ', $c->v->@*; # 99 78 56 0
Creating new PJ_COORD
values should only be done with the proj_coord()
function. Other ways to construct such values may exist, but these must be considered implementation details that are subject to change. The proj_coord()
function is the only supported way to create PJ_COORD
values.
Before version 0.05 of Geo::LibProj::FFI, PJ_COORD
method names were joined with the arrow operator instead of an underscore ($c->xyz->x
etc.). The old syntax is now discouraged, but there are no immediate plans to remove it.
Data types other than PJ_COORD
are available as well. Please see the PROJ data type reference for further documentation.
BUGS AND LIMITATIONS
PROJ makes heavy use of C union
pass-by-value, which is unsupported by FFI::Platypus. In earlier versions of this module, the workaround for working with PJ_COORD
values was quite slow. This performance issue has been addressed as of version 0.03.
Some implementation details of the glue this module provides may change in future, for example to better match the API or to increase performance. Should you decide to use this module in production, it would be wise to watch the GitHub project for changes, at least until the version has reached 1.00.
This module is designed to be used with PROJ version 8. PROJ versions as far back as 6.2.0 should work as well; please report any issues.
SEE ALSO
PROJ C API Reference: Data types, Functions
API LICENSE
The API this module gives access to is the proj.h
API, which is available under the terms of the Expat MIT license.
Copyright (c) 2016, 2017, Thomas Knudsen / SDFE
Copyright (c) 2018, Even Rouault
The API designers didn't write this Perl module, and the module author didn't design the API.
AUTHOR
Arne Johannessen <ajnn@cpan.org>
If you contact me by email, please make sure you include the word "Perl" in your subject header to help beat the spam filters.
COPYRIGHT AND LICENSE
This software is Copyright (c) 2021-2023 by Arne Johannessen.
This is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 or (at your option) the same terms as the Perl 5 programming language system itself.