-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfind-kml-duplicates
86 lines (79 loc) · 2.23 KB
/
find-kml-duplicates
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use XML::Simple qw(:strict);
use Getopt::Long qw(GetOptions);
sub extractPlacemarks {
my @results = ();
my $xml = XMLin(shift(), ForceArray => 0, KeyAttr => [ 'id' ]);
my @documents = $xml->{Document};
foreach my $document (@documents) {
my @folders = $document->{Folder};
foreach my $folder (@folders) {
if (ref $folder ne 'ARRAY') {
$folder = [ $folder ];
}
foreach my $f (@{$folder}) {
my $s1 = $f->{name};
chomp($s1);
my @placemarks = $f->{Placemark};
foreach my $placemark (@placemarks) {
if (ref $placemark ne 'ARRAY') {
$placemark = [ $placemark ];
}
foreach my $p (@{$placemark}) {
my $s2 = $p->{name};
chomp($s2);
my $name = $s1 . '/' . $s2;
my $coordinates = $p->{Point}->{coordinates};
$coordinates =~ s/^\s+|\s+$//g;
my ($longitude, $latitude, $altitude) = split(',', $coordinates);
push(@results, [ $name, $longitude, $latitude ]);
}
}
}
}
}
return @results;
}
sub computeDistance {
my $lon1 = shift();
my $lat1 = shift();
my $lon2 = shift();
my $lat2 = shift();
my $dLat = deg2rad($lat2-$lat1);
my $dLon = deg2rad($lon2-$lon1);
my $a = sin($dLat/2.0) * sin($dLat/2.0) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon/2.0) * sin($dLon/2.0);
return 12742.0 * atan2(sqrt($a), sqrt(1-$a));
}
sub deg2rad {
return shift() * (3.14159265359 / 180.0)
}
Getopt::Long::Configure qw(gnu_getopt);
my $radius = 1;
GetOptions('radius|r=f' => \$radius) or die "Usage: $0 [-r radius] file.kml\n";
foreach my $file (@ARGV) {
my @placemarks = extractPlacemarks($file);
my @markers = ();
for (my $i = 0; $i < scalar(@placemarks) - 1; $i++) {
if ($markers[$i]) {
next;
}
my @duplicates = ();
for (my $j = $i + 1; $j < scalar(@placemarks); $j++) {
my $distance = computeDistance($placemarks[$i][1], $placemarks[$i][2], $placemarks[$j][1], $placemarks[$j][2]);
if ($distance <= $radius) {
if (scalar(@duplicates) == 0) {
$markers[$i] = 1;
push(@duplicates, $placemarks[$i]);
}
$markers[$j] = 1;
push(@duplicates, $placemarks[$j]);
}
}
if (scalar(@duplicates) > 0) {
print join(', ', map { $_->[0] } @duplicates) . "\n";
}
}
}