Module: PathCompare

Defined in:
lib/path_compare/version.rb,
lib/path_compare/path_compare.rb

Constant Summary collapse

VERSION =
"0.1.0"
RAD_PER_DEG =
Math::PI / 180
EARTH_DIAMETER_KM =
6371

Class Method Summary collapse

Class Method Details

.calc(dlat, lat1, lat2, dlon) ⇒ Object



50
51
52
# File 'lib/path_compare/path_compare.rb', line 50

def self.calc(dlat, lat1, lat2, dlon)
    (Math.sin(deg_to_rad(dlat)/2))**2 + Math.cos(deg_to_rad(lat1)) * Math.cos((deg_to_rad(lat2))) * (Math.sin(deg_to_rad(dlon)/2))**2
end

.compare(p1, p2) ⇒ Object

p1 and p2 given as geojson strings



4
5
6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/path_compare/path_compare.rb', line 4

def self.compare(p1, p2)
    p1 = JSON.parse(p1)['coordinates'].first
    p2 = JSON.parse(p2)['coordinates'].first
    p1 = even_split(p1, 10)
    p2 = even_split(p2, 10)

    point_distances = []
    p1.each_with_index do |coord, index|
        unless p2.size < index + 1  #TODO: Handle different length paths
            point_distances << Math.sqrt((coord[0] - p2[index][0]) ** 2) + Math.sqrt((coord[1] - p2[index][1]) ** 2)
        end
    end
    return point_distances.sum / point_distances.size
end

.deg_to_rad(num) ⇒ Object



47
48
49
# File 'lib/path_compare/path_compare.rb', line 47

def self.deg_to_rad(num)
    num * RAD_PER_DEG
end

.distance(lat1, lon1, lat2, lon2) ⇒ Object



39
40
41
42
43
44
45
46
# File 'lib/path_compare/path_compare.rb', line 39

def self.distance(lat1, lon1, lat2, lon2)
    dlon = lon2 - lon1
    dlat = lat2 - lat1

    a = calc(dlat, lat1, lat2, dlon)

    2 * Math.atan2( Math.sqrt(a), Math.sqrt(1-a)) * EARTH_DIAMETER_KM * 1000
end

.even_split(coords, split_size) ⇒ Object

Splits a linestring in to points split_size apart. (Not quite but it should be close)



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/path_compare/path_compare.rb', line 20

def self.even_split(coords, split_size)
    new_coords = []
    current_distance = 0
    target_distance = split_size
    last_coord = coords.first
    coords.each do |coord|
        if current_distance < target_distance
            current_distance += distance(coord[0], coord[1], last_coord[0], last_coord[1])
        else
            new_coords << last_coord #TODO: Add a new point at exactly the right spot instead of using last point
            target_distance += split_size
        end
        last_coord = coord
    end
    new_coords
end