File Coverage

blib/lib/Geo/GoogleEarth/Pluggable/Plugin/AsGeoJSON.pm
Criterion Covered Total %
statement 33 36 91.6
branch 13 22 59.0
condition 1 3 33.3
subroutine 5 5 100.0
pod 1 1 100.0
total 53 67 79.1


line stmt bran cond sub pod time code
1             package Geo::GoogleEarth::Pluggable::Plugin::AsGeoJSON;
2 3     3   685635 use strict;
  3         14  
  3         81  
3 3     3   15 use warnings;
  3         6  
  3         104  
4 3     3   16 use Geo::GoogleEarth::Pluggable 0.16; #for Polygon and MultiPolygon support
  3         92  
  3         15  
5 3     3   1787 use JSON::XS qw{};
  3         13804  
  3         957  
6              
7             our $VERSION = '0.05';
8             our $PACKAGE=__PACKAGE__;
9              
10             =head1 NAME
11              
12             Geo::GoogleEarth::Pluggable::Plugin::AsGeoJSON - PostgreSQL ST_AsGeoJSON plugin for Geo::GoogleEarth::Pluggable
13              
14             =head1 SYNOPSIS
15              
16             use Geo::GoogleEarth::Pluggable;
17             use Geo::GoogleEarth::Pluggable::Plugin::AsGeoJSON; #can be runtime loaded
18             my $document = Geo::GoogleEarth::Pluggable->new;
19             my $object = $document->AsGeoJSON(name => $text,
20             description => $html,
21             json => $json_string,
22             style => $style,
23             );
24              
25             =head1 DESCRIPTION
26              
27             Parses the string as returned from the PostgreSQL ST_AsGeoJSON() function as Google Earth compatible objects.
28              
29             =head1 USAGE
30              
31             use DBIx::Array::Connect 0.06; #path
32             use Geo::GoogleEarth::Pluggable 0.16; #Polygon
33             my $document = Geo::GoogleEarth::Pluggable->new;
34             my $database = DBIx::Array::Connect->new->connect('gis');
35              
36             #Select data from PostgreSQL
37             my @gisdata = $database->sqlarrayhash(&gis_data_sql);
38              
39             #Add each row as Google Earth document object
40             $document->AsGeoJSON(%$_) foreach @gisdata;
41              
42             #Print the Google Earth KML document
43             print $document->render;
44            
45             sub gis_data_sql {
46             return qq{
47             SELECT 'Clifton, VA' AS "name",
48             ST_AsGeoJSON(ST_GeomFromText('POINT(-77.38670068 38.78025536)')) AS "json"
49             };
50             }
51              
52             =head1 METHODS
53              
54             =head2 AsGeoJSON
55              
56             $document->AsGeoJSON(
57             name => $text, #see Placemark
58             description => $html,
59             json => $json_string,
60             style => $style,
61             );
62              
63             JSON Example: Point
64              
65             {
66             "type" : "Point",
67             "coordinates" : [ -77.38670068, 38.78025536 ]
68             }
69              
70             JSON Example: Polygon
71              
72             {
73             "type" : "Polygon"
74             "coordinates" : [
75             [
76             [ -77.3883082, 38.7796903 ],
77             [ -77.3858487, 38.7791080 ],
78             [ -77.3859173, 38.7811742 ],
79             [ -77.3859710, 38.7812281 ],
80             [ -77.3861322, 38.7814079 ],
81             [ -77.3883082, 38.7796903 ]
82             ]
83             ],
84             }
85              
86             JSON Example: MultiPolygon
87              
88             {
89             "type" : "MultiPolygon"
90             "coordinates" : [
91             [
92             [
93             [ -77.3883082, 38.7796903 ],
94             [ -77.3858487, 38.7791080 ],
95             [ -77.3859173, 38.7811742 ],
96             [ -77.3859710, 38.7812281 ],
97             [ -77.3861322, 38.7814079 ],
98             [ -77.3883082, 38.7796903 ]
99             ]
100             ],
101             [
102             [
103             [ -77.3857118, 38.7789067 ],
104             [ -77.3852328, 38.7769665 ],
105             [ -77.3843158, 38.7770731 ],
106             [ -77.3850419, 38.7786809 ],
107             [ -77.3857118, 38.7789067 ]
108             ]
109             ]
110             ],
111             }
112              
113             =cut
114              
115             sub AsGeoJSON {
116 3     3 1 12729 my $self = shift; #$self isa Geo::GoogleEarth::Pluggable::Folder object
117 3         14 my %data = @_;
118 3 100       21 my $json = delete($data{"json"}) or die("Error: AsGeoJSON requires the json parameter.");
119 2         3 my $decode = eval{JSON::XS::decode_json($json)};
  2         19  
120 2         5 my $error = $@;
121 2 50       6 die(qq{Error: AsGeoJSON json parameter JSON decode failed. JSON: "$json", Error: "$error"}) if $error;
122 2 50       9 die(qq{Error: AsGeoJSON json parameter JSON must be an Object (Hash)}) unless ref($decode) eq "HASH";
123 2 50       7 my $type = $decode->{"type"} or die(qq{Error: AsGeoJSON json parameter JSON missing "type" value});
124 2 50       7 my $coordinates = $decode->{"coordinates"} or die(qq{Error: AsGeoJSON json parameter JSON missing "coordinates" value});
125 2 50       6 die(qq{Error: AsGeoJSON json parameter JSON Object "coordinates" must be an Array}) unless ref($coordinates) eq "ARRAY";
126 2   33     10 my $name = $data{"name"} ||= $type;
127 2         3 my $object;
128 2 100       12 if ($type eq "Point") {
    50          
    50          
    50          
129 1         3 $data{"lon"} = $coordinates->[0];
130 1         3 $data{"lat"} = $coordinates->[1];
131 1 50       3 $data{"alt"} = $coordinates->[2] if defined($coordinates->[2]);
132 1         12 $object = $self->Point(%data);
133             } elsif ($type eq "LineString") {
134 0         0 $object = $self->LineString(%data, coordinates => $coordinates);
135             } elsif ($type eq "Polygon") {
136 0         0 $object = $self->Polygon(%data, coordinates => $coordinates);
137             } elsif ($type eq "MultiPolygon") {
138 0         0 $object = $self->MultiPolygon(%data, coordinates => $coordinates)
139             } else {
140 1         64 warn(qq{Warning: $PACKAGE does not support type "$type".\n});
141 1         17 $object = $self->Folder(name => sprintf("%s - Unsupported %s", $data{"name"}, $type));
142             }
143 2         8986 return $object;
144             }
145              
146             =head1 SEE ALSO
147              
148             L, L
149              
150             =head1 AUTHOR
151              
152             Michael Davis, mrdvt@cpan.org
153              
154             =head1 COPYRIGHT AND LICENSE
155              
156             MIT License
157              
158             Copyright (c) 2021 Michael R. Davis
159              
160             Permission is hereby granted, free of charge, to any person obtaining a copy
161             of this software and associated documentation files (the "Software"), to deal
162             in the Software without restriction, including without limitation the rights
163             to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
164             copies of the Software, and to permit persons to whom the Software is
165             furnished to do so, subject to the following conditions:
166              
167             The above copyright notice and this permission notice shall be included in all
168             copies or substantial portions of the Software.
169              
170             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171             IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
172             FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
173             AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
174             LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
175             OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
176             SOFTWARE.
177              
178             =cut
179              
180             1;