proj4dart 1.0.4

  • Readme
  • Changelog
  • Example
  • Installing
  • 90

PROJ4DART #

Proj4dart is a Dart library to transform point coordinates from one coordinate system to another, including datum transformations (Dart version of proj4js/proj4js).

Installing #

Add proj4dart to pubspec.yml (dependencies section), then run pub get to download the new dependencies.

dependencies:
  proj4dart: any # or the latest version on Pub

Using #

Predefined Projection #

There are 3 predefined Projections and 5 aliases by default:

  • EPSG:4326, which has the following alias:
    • WGS84
  • EPSG:4269
  • EPSG:3857, which has the following aliases:
    • EPSG:3785
    • GOOGLE
    • EPSG:900913
    • EPSG:102113

If you wish to use one of the predefined ones use Named Projection which has the following signature:

  var projection = Projection('EPSG:4326');

User-defined Projection #

Proj4dart supports Proj4 definition strings, OGC WKT definitions and ESRI WKT definitions. They can be obtained from epsg.io.

With Proj4 string definition

If you wish to define your own projection you can create it with a valid Proj4 string (here for EPSG:23700):

+proj=somerc +lat_0=47.14439372222222 +lon_0=19.04857177777778 +k_0=0.99993 +x_0=650000 +y_0=200000 +ellps=GRS67 +towgs84=52.17,-71.82,-14.9,0,0,0,0 +units=m +no_defs

The signature is:

var def = '+proj=somerc +lat_0=47.14439372222222 +lon_0=19.04857177777778 +k_0=0.99993 +x_0=650000 +y_0=200000 +ellps=GRS67 +towgs84=52.17,-71.82,-14.9,0,0,0,0 +units=m +no_defs';

// Named Projection signature, later find it from anywhere via Projection('EPSG:23700')
var namedProjection = Projection.add('EPSG:23700', def);
// Projection without name signature
var projection = Projection.parse(def);

For full example visit example/proj4dart_example.dart

With OGC WKT definition

If you wish to define your own projection you can create it with a valid OGC WKT string (here for EPSG:23700):

PROJCS["HD72 / EOV",GEOGCS["HD72",DATUM["Hungarian_Datum_1972",SPHEROID["GRS 1967",6378160,298.247167427,AUTHORITY["EPSG","7036"]],TOWGS84[52.17,-71.82,-14.9,0,0,0,0],AUTHORITY["EPSG","6237"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4237"]],PROJECTION["Hotine_Oblique_Mercator_Azimuth_Center"],PARAMETER["latitude_of_center",47.14439372222222],PARAMETER["longitude_of_center",19.04857177777778],PARAMETER["azimuth",90],PARAMETER["rectified_grid_angle",90],PARAMETER["scale_factor",0.99993],PARAMETER["false_easting",650000],PARAMETER["false_northing",200000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Y",EAST],AXIS["X",NORTH],AUTHORITY["EPSG","23700"]]

The signature is:

var def = 'PROJCS["HD72 / EOV",GEOGCS["HD72",DATUM["Hungarian_Datum_1972",SPHEROID["GRS 1967",6378160,298.247167427,AUTHORITY["EPSG","7036"]],TOWGS84[52.17,-71.82,-14.9,0,0,0,0],AUTHORITY["EPSG","6237"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4237"]],PROJECTION["Hotine_Oblique_Mercator_Azimuth_Center"],PARAMETER["latitude_of_center",47.14439372222222],PARAMETER["longitude_of_center",19.04857177777778],PARAMETER["azimuth",90],PARAMETER["rectified_grid_angle",90],PARAMETER["scale_factor",0.99993],PARAMETER["false_easting",650000],PARAMETER["false_northing",200000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Y",EAST],AXIS["X",NORTH],AUTHORITY["EPSG","23700"]]';

// Named Projection signature, later find it from anywhere via Projection('EPSG:23700')
var namedProjection = Projection.add('EPSG:23700', def);
// Projection without name signature
var projection = Projection.parse(def);

For full example visit example/proj4dart_ogc_wkt_example.dart

With ESRI WKT definition

If you wish to define your own projection you can create it with a valid ESRI WKT string (here for EPSG:23700):

PROJCS["HD72_EOV",GEOGCS["GCS_HD72",DATUM["D_Hungarian_1972",SPHEROID["GRS_1967",6378160,298.247167427]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Hotine_Oblique_Mercator_Azimuth_Center"],PARAMETER["latitude_of_center",47.14439372222222],PARAMETER["longitude_of_center",19.04857177777778],PARAMETER["azimuth",90],PARAMETER["scale_factor",0.99993],PARAMETER["false_easting",650000],PARAMETER["false_northing",200000],UNIT["Meter",1]]

The signature is:

var def = 'PROJCS["HD72_EOV",GEOGCS["GCS_HD72",DATUM["D_Hungarian_1972",SPHEROID["GRS_1967",6378160,298.247167427]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Hotine_Oblique_Mercator_Azimuth_Center"],PARAMETER["latitude_of_center",47.14439372222222],PARAMETER["longitude_of_center",19.04857177777778],PARAMETER["azimuth",90],PARAMETER["scale_factor",0.99993],PARAMETER["false_easting",650000],PARAMETER["false_northing",200000],UNIT["Meter",1]]');

// Named Projection signature, later find it from anywhere via Projection('EPSG:23700')
var namedProjection = Projection.add('EPSG:23700', def);
// Projection without name signature
var projection = Projection.parse(def);

For full example visit example/proj4dart_esri_wkt_example.dart

Transform between Projections #

import 'package:proj4dart/proj4dart.dart';

void main() {
  // Define Point
  var pointSrc = Point(x: 17.888058560281515, y: 46.89226406700879);

  // Use built-in projection
  var projSrc = Projection('EPSG:4326');

  // Find Projection by name or define it if not exists
  var projDst = Projection('EPSG:23700') ??
      Projection.add(
        'EPSG:23700',
        '+proj=somerc +lat_0=47.14439372222222 +lon_0=19.04857177777778 +k_0=0.99993 +x_0=650000 +y_0=200000 +ellps=GRS67 +towgs84=52.17,-71.82,-14.9,0,0,0,0 +units=m +no_defs',
      );

  // Forward transform (lonlat -> projected crs)
  var pointForward = projSrc.transform(projDst, pointSrc);
  print(
      'FORWARD: Transform point ${pointSrc.toArray()} from EPSG:4326 to EPSG:23700: ${pointForward.toArray()}');
  // FORWARD: Transform point [17.888058560281515, 46.89226406700879] from EPSG:4326 to EPSG:23700: [561651.8408065987, 172658.61998377228]

  // Inverse transform (projected crs -> lonlat)
  var pointInverse = projDst.transform(projSrc, pointForward);
  print(
      'INVERSE: Transform point ${pointForward.toArray()} from EPSG:23700 to EPSG:4326: ${pointInverse.toArray()}');
  // INVERSE: Transform point [561651.8408065987, 172658.61998377228] from EPSG:23700 to EPSG:4326: [17.888058565574845, 46.89226406698969]
}

Transform between Projections using ProjectionTuple #

import 'package:proj4dart/proj4dart.dart';

void main() {
  // Define Point
  var pointSrc = Point(x: 17.888058560281515, y: 46.89226406700879);

  // Define ProjectionTuple which makes vice versa conversions even easier
  var tuple = ProjectionTuple(
    // Use built-in projection
    fromProj: Projection('EPSG:4326'),
    // Define custom projection
    toProj: Projection.parse(
      '+proj=somerc +lat_0=47.14439372222222 +lon_0=19.04857177777778 +k_0=0.99993 +x_0=650000 +y_0=200000 +ellps=GRS67 +towgs84=52.17,-71.82,-14.9,0,0,0,0 +units=m +no_defs',
    ),
  );

  // Forward transform (lonlat -> projected crs)
  var pointForward = tuple.forward(pointSrc);
  print(
      'FORWARD: Transform point ${pointSrc.toArray()} from EPSG:4326 to EPSG:23700: ${pointForward.toArray()}');
  // FORWARD: Transform point [17.888058560281515, 46.89226406700879] from EPSG:4326 to EPSG:23700: [561651.8408065987, 172658.61998377228]

  // Inverse transform (projected crs -> lonlat)
  var pointInverse = tuple.inverse(pointForward);
  print(
      'INVERSE: Transform point ${pointForward.toArray()} from EPSG:23700 to EPSG:4326: ${pointInverse.toArray()}');
  // INVERSE: Transform point [561651.8408065987, 172658.61998377228] from EPSG:23700 to EPSG:4326: [17.888058565574845, 46.89226406698969]
}

Accuracy #

Proj4dart was tested with

Forward and inverse transformations were both performed and checked in each case. The expected forward and inverse results were pre-calculated using proj4js (test/results/all_proj4_results.dart, test/results/all_proj4_ogc_wkt_results.dart, test/results/all_proj4_esri_wkt_results.dart).

The following table shows the avarage deltas of different Projections (using EPSG:4326 point of [17.888058560281515, 46.89226406700879] and transformed to Custom CRS defined with Proj4 definition string which gave the forward result then transformed back the received forward result which gave the inverse result):

ProjectionNo. testsavg delta forward_xavg delta forward_yavg delta inverse_xavg delta inverse_y
Albers Projection582.8260822953849e-91.6378431484617036e-91.0719394720518753e-141.0903155772870503e-14
Azimuthal Equidistant Projection127.761021455128987e-111.5522042910257974e-101.7763568394002505e-151.1842378929335002e-15
Cassini Projection333.9510654680656665e-103.3866275440562856e-103.2297397080004555e-160.0
Central Cylindrical Projection50.00.00.00.0
Equidistant Conic Projection91.2935035758548312e-110.01.578983857244667e-150.0
Equidistant Cylindrical Projection250.00.00.00.0
Geocentric Projection1960.00.09.06304509898087e-170.0
Gnomic Projection20.00.03.552713678800501e-150.0
Hotine Oblique Mercator Projection514.460304683330012e-98.017819959158991e-96.339155779820502e-153.901018941428001e-15
Krovak Projection99.054525030983819e-101.448724004957411e-91.578983857244667e-153.157967714489334e-15
Lambert Azimuthal Equal-Area Projection205.820766091346741e-110.05.329070518200751e-160.0
Lambert Conformal Conic Projection20281.8960008225716005e-81.2588414830372427e-84.613097105712702e-148.064379757884726e-14
LongLat11521.6961740653995446e-160.02.312964634635743e-162.7755575615628914e-16
Miller Cylindrical Projection20.00.00.00.0
Mollweide Projection20.00.00.00.0
New Zealand Map Grid Projection10.00.00.0000032949084527444940.000008533214440831216
Orthographic Projection20.00.07.105427357601002e-153.552713678800501e-15
Polyconic Projection100.00.01.1842378929335002e-150.0
Pseudo Mercator Projection250.03.7252902984619143e-101.4210854715202004e-162.842170943040401e-16
Robinson Projection20.00.00.00.0
Sinusoidal Projection30.00.00.00.0
Stereographic North Projection212.217434701465425e-112.993536846978324e-104.906128413581644e-151.3534147347811431e-15
Stereographic South Projection442.43414258446509e-102.063731004268861e-101.3726393759001935e-150.0
Swiss Oblique Mercator Projection54.656612873077393e-110.01.4210854715202005e-150.0
Transverse Mercator Projection34457.527289676908484e-125.01819311793899e-123.966550829771659e-133.0942861377693824e-13
Universal Transverse Mercator Projection12793.4847229055075836e-103.429655454604303e-103.4304936617033767e-152.4999548951684524e-15
Van der Grinten Projection23.3760443329811096e-92.3283064365386963e-90.00.0

Example (using EPSG:4326 point of [17.888058560281515, 46.89226406700879] and transformed to EPSG:23700 defined with Proj4 definition string):

LIBRARYforward_xforward_yinverse_xinverse_y
proj4dart561651.8408065987172658.6199837722817.88805856557484546.89226406698969
proj4js561651.8408065989172658.6199837722817.88805856557485246.89226406698969
delta0.00000000020.00.0000000000000070.0

In some cases also manual PostGIS testing (PostgreSQL 12.1, PostGIS 3.0.0 r17983) was performed such as the following (using EPSG:4326 point of [17.888058560281515, 46.89226406700879] and transformed to EPSG:23700 defined with Proj4 definition string):

LIBRARYforward_xforward_yinverse_xinverse_y
proj4dart561651.8408065987172658.6199837722817.88805856557484546.89226406698969
PostGIS561651.8408065987172658.619983772417.8880585655748246.8922640683514
delta0.00.000000000120.0000000000000250.00000000136171

Used by #

  • Proj4dart is currently the default projection handler of flutter_map.

Authors #

Proj4dart was ported from proj4js by @maRci002 and Gergely Padányi-Gulyás (@fegyi001) at Ulyssys Ltd, Budapest, Hungary.

Changelog #

1.0.4 #

  • Named Projection returns null instead of throwing Exception if Projection not found by name
  • Some tests precalculate worst closeTos because these may depend on Dart version / OS

1.0.3 #

  • add meta.dart to pubspec.yaml (avoid pub warning)

1.0.2 #

  • Support ProjectionTuple
  • Support Projection.parse
  • Add more definitions
  • Add more tests
    • support exception compare
    • use blacklist when necessary
    • make closeTo even strict
  • Update wkt-parser-dart
  • fix axis order in some cases

1.0.1 #

  • Support OGC WKT definitions
  • Support ESRI WKT definitions
  • Simplify globals logic

1.0.0 #

  • Initial version
  • Can use 3 predefined projections + 5 aliases
  • Can create and use any custom projections with Proj4 string
  • Forward and inverse transformation between projections
  • Tested with ~4000 existing projections (from epsg.io)

example/proj4dart_example.dart

import 'package:proj4dart/proj4dart.dart';

void main() {
  // Define Point
  var pointSrc = Point(x: 17.888058560281515, y: 46.89226406700879);

  // Use built-in projection
  var projSrc = Projection('EPSG:4326');

  // Find Projection by name or define it if not exists
  var projDst = Projection('EPSG:23700') ??
      Projection.add(
        'EPSG:23700',
        '+proj=somerc +lat_0=47.14439372222222 +lon_0=19.04857177777778 +k_0=0.99993 +x_0=650000 +y_0=200000 +ellps=GRS67 +towgs84=52.17,-71.82,-14.9,0,0,0,0 +units=m +no_defs',
      );

  // Forward transform (lonlat -> projected crs)
  var pointForward = projSrc.transform(projDst, pointSrc);
  print(
      'FORWARD: Transform point ${pointSrc.toArray()} from EPSG:4326 to EPSG:23700: ${pointForward.toArray()}');
  // FORWARD: Transform point [17.888058560281515, 46.89226406700879] from EPSG:4326 to EPSG:23700: [561651.8408065987, 172658.61998377228]

  // Inverse transform (projected crs -> lonlat)
  var pointInverse = projDst.transform(projSrc, pointForward);
  print(
      'INVERSE: Transform point ${pointForward.toArray()} from EPSG:23700 to EPSG:4326: ${pointInverse.toArray()}');
  // INVERSE: Transform point [561651.8408065987, 172658.61998377228] from EPSG:23700 to EPSG:4326: [17.888058565574845, 46.89226406698969]
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  proj4dart: ^1.0.4

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:proj4dart/proj4dart.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
80
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
90
Learn more about scoring.

We analyzed this package on Apr 7, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.0 <3.0.0
meta ^1.1.8 1.1.8
mgrs_dart ^1.0.1 1.0.1
wkt_parser ^1.0.7 1.0.7
Transitive dependencies
lists 0.1.5
unicode 0.2.2
Dev dependencies
pedantic ^1.9.0
test ^1.14.1