1package Geo::JSON;
2
3our $VERSION = '0.007';
4
5use strict;
6use warnings;
7use Carp;
8
9use JSON qw/ decode_json /;
10use List::Util qw/ first /;
11
12use constant GEOMETRY_OBJECTS => [
13    qw/ Point MultiPoint LineString MultiLineString Polygon MultiPolygon GeometryCollection /
14];
15use constant GEOJSON_OBJECTS => [    #
16    @{ +GEOMETRY_OBJECTS }, qw/ Feature FeatureCollection /
17];
18
19our $json = JSON->new->utf8->convert_blessed(1);
20
21sub from_json {
22    my ( $class, $json ) = @_;
23
24    my $data = decode_json($json);
25
26    croak "from_json requires a JSON object (hashref)"
27        unless ref $data eq 'HASH';
28
29    return $class->load($data);
30}
31
32sub load {
33    my ( $class, $data ) = @_;
34
35    my $type = delete $data->{type}
36        or croak "Invalid JSON data: no type specified";
37
38    my $geo_json_class = 'Geo::JSON::' . $type;
39
40    croak "Invalid type '$type'"
41        unless first { $type eq $_ } @{ +GEOJSON_OBJECTS };
42
43    eval "require $geo_json_class";
44
45    return $geo_json_class->new($data);
46}
47
48sub codec {
49    my $class = shift;
50
51    my $orig = $json;
52    $json = shift if @_;
53
54    return $orig;
55}
56
571;
58
59__END__
60
61=encoding utf-8
62
63=head1 NAME
64
65Geo::JSON - Perl OO interface for geojson
66
67=head1 SYNOPSIS
68
69    use Geo::JSON;
70
71    my $obj = Geo::JSON->from_json( $json );
72
73    $obj->to_json();
74
75=head1 DESCRIPTION
76
77Convert to and from geojson using Perl objects. GeoJSON objects represent
78various geographical positions - points, lines, polygons, etc.
79
80Currently supports 2 or 3 dimensions (longitude, latitude, altitude). Further
81dimensions in positions are ignored for calculations and comparisons, but will
82be read-from and written-to.
83
84=head1 GEOJSON SPECIFICATION
85
86See: L<http://www.geojson.org/geojson-spec.html>
87
88=head1 GEOJSON MEMBERS (ATTRIBUTES)
89
90See the specification for the full details, but the basics are as follows:
91
92=over
93
94=item * C<type>
95
96Determines the object the json will be turned into
97
98=item * C<position>
99
100Not explicitly named in the json, but an array of at least two numbers
101representing a location in x, y, z order (either Easting, Northing, Altitude
102or Longitude, Latitude, Altitude as appropriate).
103
104Additional numbers may be present but ignored by this package for
105calculations.
106
107=item * C<coordinates>
108
109Defined in geometry objects (Point, MultiPoint, LineString, MultiLineString,
110Polygon, MultiPolygon). Will consist of a single position (Point), an array
111of positions (MultiPoint, LineString), an array of arrays of positions
112(MultiLineString, Polygon) or an array of arrays of arrays of positions
113(MultiPolygon). The positions within a single object should all have the same
114number of axes and be in the same axis order.
115
116=item * C<bbox>
117
118Optional, defining a bounding box that the position(s) are contained by.
119
120The box is defined by a array of 2*n items, where n is the number of
121dimensions in a position. The items are the lowest value for an axis followed
122by the highest value for an axis, in the axis order used in the positions.
123
124The Co-ordinates Reference System for the bounding box is assumed to match
125that of the object.
126
127=item * C<crs>
128
129Optional, defining the Co-ordinates Reference System the object is using. See
130L<Geo::JSON::CRS> for more details.
131
132=back
133
134=head1 GEOMETRY OBJECTS
135
136=over
137
138=item * L<Geo::JSON::Point>
139
140A single position
141
142=item * L<Geo::JSON::MultiPoint>
143
144An array of positions, representing multiple points
145
146=item * L<Geo::JSON::LineString>
147
148An array of 2 or more positions, represening a connected line
149
150=item * L<Geo::JSON::MultiLineString>
151
152An array of lines
153
154=item * L<Geo::JSON::Polygon>
155
156An array of lines, defining a polygon. The first line represents the outside
157of the polygon, subsequent lines define any 'holes'. The lines must be
158'linear rings' - 4 or more points, with the first and last points being
159equivalent.
160
161=item * L<Geo::JSON::MultiPolygon>
162
163An array of polygons
164
165=item * L<Geo::JSON::GeometryCollection>
166
167An array of any of the above Geometry objects (as attribute C<geometries>)
168
169=back
170
171=head1 FEATURE OBJECTS
172
173=over
174
175=item * L<Geo::JSON::Feature>
176
177Any of the above objects (as attribute C<feature>), together with a data
178structure (as attruibute C<properties>)
179
180=back
181
182=head1 FEATURE COLLECTION OBJECTS
183
184=over
185
186=item * L<Geo::JSON::FeatureCollection>
187
188An array of Feature objects (as attribute C<features>)
189
190=back
191
192=head1 METHODS
193
194=head2 from_json
195
196    my $obj = Geo::JSON->from_json( $json );
197
198Takes a geojson string, returns the object it represents.
199
200=head2 to_json
201
202    $obj->to_json();
203    $obj->to_json( $codec );
204
205Call on a Geo::JSON object. Returns the JSON that represents the object.
206
207Pass in an optional L<JSON> codec to modify the default behaviour of the JSON
208returned.
209
210=head2 load
211
212    my $obj = Geo::JSON->load( { type => 'Point', coordinates => ... } );
213
214Creates a Geo::JSON object from a hashref.
215
216This is used for coercion of attributes during object creation, and probably
217should not be called directly otherwise.
218
219=head1 CLASS METHODS
220
221=head2 codec
222
223    Geo::JSON->codec->canonical(1)->pretty;
224
225    my $prev_codec = Geo::JSON->codec($new_codec);
226
227Set options on or replace L<JSON> codec.
228
229=head1 THANKS
230
231Tim Bunce - for codec suggestions and bug spotting.
232
233=head1 SEE ALSO
234
235=over
236
237=item *
238
239L<Geo::JSON::Simple> - simple interface to create Geo::JSON objects.
240
241=back
242
243=head1 SUPPORT
244
245=head2 Bugs / Feature Requests
246
247Please report any bugs or feature requests through the issue tracker
248at L<https://github.com/mjemmeson/Geo-JSON/issues>.
249You will be notified automatically of any progress on your issue.
250
251=head2 Source Code
252
253This is open source software.  The code repository is available for
254public review and contribution under the terms of the license.
255
256L<https://github.com/mjemmeson/Geo-JSON>
257
258  git clone https://github.com/mjemmeson/Geo-JSON.git
259
260=head1 AUTHOR
261
262Michael Jemmeson <mjemmeson@cpan.org>
263
264=head1 COPYRIGHT AND LICENSE
265
266This software is copyright (c) 2015 by Michael Jemmeson <mjemmeson@cpan.org>.
267
268This is free software; you can redistribute it and/or modify it under
269the same terms as the Perl 5 programming language system itself.
270
271=cut
272
273