Last active
December 14, 2015 04:49
-
-
Save alainravet/5031054 to your computer and use it in GitHub Desktop.
extract POIs from a TomTom *.ov2 file (in Ruby)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module BinaryFileStringUtils | |
def byte_to_int | |
self.unpack('U').first | |
end | |
def little_endian_to_int | |
# source : http://stackoverflow.com/questions/5236059/unpack-signed-little-endian-in-ruby | |
arr, bits, num = self.unpack('V*'), 0, 0 | |
arr.each do |int| | |
num += int << bits | |
bits += 32 | |
end | |
num >= 2**(bits-1) ? num - 2**bits : num # Convert from unsigned to signed | |
end | |
end | |
String.send :include, BinaryFileStringUtils |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
path = File.absolute_path File.join File.dirname($FILENAME), '..', 'data/poi/Amis.ov2' | |
File.open(path, 'rb') do |file| | |
@pois = POI::Reader.new(file).extract_pois | |
end | |
puts @pois | |
#<struct POI type=2, x=4.12345, y=50.1234, text="Al"> | |
#<struct POI type=2, x=4.23456, y=50.5678, text="Bob"> | |
#<struct POI type=2, x=4.34567, y=50.9012, text="Carl"> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class POI < Struct.new(:type, :x, :y, :text) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class POI | |
class Reader | |
attr_reader :file | |
def initialize(file) | |
@file = file | |
file.extend POIFileReadingUtils | |
end | |
def extract_pois | |
pois = [] | |
begin | |
poi = extract_poi | |
pois << poi if poi | |
end until file.eof? | |
pois | |
end | |
private | |
def extract_poi | |
raw_type = file.read(1) | |
type = raw_type.byte_to_int rescue raw_type | |
case type | |
when 0 then skip_type_0_poi | |
when 2 then extract_type_2_poi | |
when 1, 3 | |
raise "Not Implemented type : #{type.inspect}" | |
else | |
raise "Invalid type : #{type.inspect}" | |
end | |
end | |
def skip_type_0_poi | |
len = file.read_poi_record_len | |
rest = file.read(len - (1+4)) | |
nil | |
end | |
def extract_type_2_poi | |
len = file.read_poi_record_len | |
x = file.read_poi_x_coordinate | |
y = file.read_poi_y_coordinate | |
text = file.read_poi_text(len - (1+4+4+4)) | |
POI.new(2, x, y, text) | |
end | |
end | |
private | |
module POIFileReadingUtils | |
def read_poi_text(len) | |
read(len).chomp("\u0000") | |
end | |
def read_poi_record_len | |
read(4).little_endian_to_int | |
end | |
def read_poi_x_coordinate | |
read(4).little_endian_to_int/100_000.0 | |
end | |
alias read_poi_y_coordinate read_poi_x_coordinate | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment