Skip to content

Instantly share code, notes, and snippets.

@lpm11
Created March 24, 2012 15:00
Show Gist options
  • Save lpm11/2183954 to your computer and use it in GitHub Desktop.
Save lpm11/2183954 to your computer and use it in GitHub Desktop.
OruxMaps が吐き出した KML を Evernote 形式に一括変換
#!/bin/env ruby
#-*- coding: utf-8 -*-
require("rubygems");
require("term/ansicolor");
require("term/ansicolor/logger");
require("optparshie");
require("date");
require("digest/md5");
require("base64");
require("cgi");
require("libxml");
require("nokogiri");
require("open-uri");
# Usage/Versions
$HELP_DESC = "";
$HELP_INPUT = "";
$HELP_OUTPUT = "";
::Version = "0.00 @ " + File.mtime($0).strftime("%Y%m%d-%H%M%S");
$log = Term::ANSIColor::Logger.new(STDERR);
$log.progname = $0;
$log.datetime_format = "%Y-%m-%d %H:%M:%S";
$log.level = Logger::DEBUG;
$log.warn_decorate(:yellow);
$log.error_decorate(:yellow, :bold);
$log.fatal_decorate(:red, :bold);
$log.debug_green_bold("#{$log.progname} started, version: #{::Version}");
$opt = OptionParshie.new();
$opt.on_tail("-h","--help","Show this message.") { puts("#{$0} #{::Version}: #{$HELP_DESC}"," input: #{$HELP_INPUT}"," output: #{$HELP_OUTPUT}","",$opt.help); exit(0); }
$opt.parse!(ARGV);
def segment_point_distance(ax,ay,bx,by,px,py)
t = (ax**2 + ay**2 + bx*px - ax*(bx + px) + by*py - ay*(by + py))/(ax**2 + ay**2 - 2*ax*bx + bx**2 - 2*ay*by + by**2);
return ((ax-px)**2 + (ay-py)**2) if (t<0);
return ((bx-px)**2 + (by-py)**2) if (1<t);
x = ax - ((ax - bx)*(ax**2 + ay**2 + bx*px - ax*(bx + px) + by*py - ay*(by + py)))/(ax**2 + ay**2 - 2*ax*bx + bx**2 - 2*ay*by + by**2);
y = ay - ((ay - by)*(ax**2 + ay**2 + bx*px - ax*(bx + px) + by*py - ay*(by + py)))/(ax**2 + ay**2 - 2*ax*bx + bx**2 - 2*ay*by + by**2);
return ((x-px)**2 + (y-py)**2);
end
def rank(a,c)
l = Hash.new();
c -= 2;
n = Math.log(c,2).ceil;
rank_sub(a,0,0,n,l);
return l;
end
def rank_sub(a,b,s,n,l)
return if (s>n || a.empty?);
if (a.size==1)
l[b] = 0;
return;
end
fx,fy = a.first;
ex,ey = a.last;
d = a.map { |px,py| segment_point_distance(fx,fy,ex,ey,px,py); }
m,v = d.each_with_index.max;
l[b+v] = m;
rank_sub(a[0...v],b,s+1,n,l);
rank_sub(a[v...a.size],b+v,s+1,n,l);
end
def make_c_str(a,c,l)
c-=2;
result = [ a.first ];
l.to_a.sort_by { |x| -x[1] }[0...c].sort_by { |x| x[0] }.each { |i,d|
next if (i==0 || i==a.size-1);
result << a[i];
}
result << a.last;
end
xmlns = { "kml"=>"http://earth.google.com/kml/2.2" };
fpw = File.open("export-#{Time.now.strftime('%Y%m%d%H%M%S')}.enex","w:utf-8");
fpw.puts('<?xml version="1.0" encoding="UTF-8"?>');
fpw.puts('<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export.dtd">');
fpw.puts('<en-export export-date="'+Time.now.strftime("%Y%m%dT%H%M%SZ")+'" application="Evernote/Windows" version="4.x">');
ARGV.each { |path|
doc = LibXML::XML::Document.file(path);
positions = [];
doc.find("//kml:kml/kml:Document/kml:Folder/kml:Placemark/kml:MultiGeometry/kml:LineString/kml:coordinates",xmlns).each { |coordinates|
coordinates.content.split(/\n/).each { |s|
next if (s.empty?);
tuple = s.split(/,/);
positions << [ tuple[1].to_f()*10000.round()/10000, tuple[0].to_f()*10000.round()/10000 ];
}
}
data_html = doc.find("//kml:kml/kml:Document/kml:description",xmlns)[0].content;
data_doc = Nokogiri::HTML.parse(data_html);
data_name = data_doc.xpath("//h2").inner_text.gsub(/^[^:]+:\s+/,"");
data_array = data_doc.xpath("//p").map { |e| e.inner_text.split(/: /); };
data_array.map! { |k,v| k="平均移動速度" if (k=="平均速度Mov。"); [ k,v ]; }
cdt = DateTime.strptime(data_array[0][1],format="%m/%d/%Y %H:%M");
mdt = DateTime.strptime(data_array[1][1],format="%m/%d/%Y %H:%M");
ctime = Time.gm(cdt.year, cdt.mon, cdt.day, cdt.hour, cdt.min);
mtime = Time.gm(mdt.year, mdt.mon, mdt.day, mdt.hour, mdt.min);
marker = "&markers=color:red%7Clabel:S%7C#{positions.first[0]},#{positions.first[1]}&markers=color:red%7Clabel:E%7C#{positions.last[0]},#{positions.last[1]}";
l = rank(positions,96);
# 手抜き
c = 96;
url = nil;
while (true)
result = make_c_str(positions,c,l);
# URL生成
c_str = result.map { |px,py| "#{px},#{py}" }.join("%7C");
url = "http://maps.google.co.jp/maps/api/staticmap?path=color:0xff0000a0%7Cweight:4%7C#{c_str}&size=640x640&sensor=false#{marker}";
break if (url.length <= 2048);
c-=1;
end
puts(url);
puts("size = #{url.size}, path = #{result.size}");
image_data = open(url).read();
image_data_md5 = Digest::MD5.hexdigest(image_data);
fpw.puts('<note>');
fpw.puts('<title>'+"GPS記録: #{data_name}"+'</title>');
fpw.puts('<content>');
fpw.puts('<![CDATA[<?xml version="1.0" encoding="UTF-8"?>');
fpw.puts('<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">');
fpw.puts('');
fpw.puts('<en-note style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">');
fpw.puts('<div style="font-family: &apos;MS Pゴシック&apos;">');
fpw.puts('<div style="float:left;width:644px">');
fpw.puts(' <en-media hash="' + image_data_md5 + '" type="image/png" />');
fpw.puts('</div>');
fpw.puts('<div>');
fpw.puts('<table style="float:left;margin:3px 0;">');
data_array.each { |k,v|
fpw.puts('<tr><th style="color:white;background-color:steelblue;font-weight:normal;padding:6px">' + k + '</th><td style="background-color:lightsteelblue;padding:6px">' + v + '</td></tr>');
}
fpw.puts('</table>');
fpw.puts('</div>');
fpw.puts('</div>');
fpw.puts('</en-note>]]>');
fpw.puts('</content>');
fpw.puts('<resource><data encoding="base64">');
fpw.puts(Base64.encode64(image_data));
fpw.puts('</data><mime>image/png</mime><resource-attributes><source-url>' + CGI::escapeHTML(url) + '</source-url><file-name>staticmap.png</file-name></resource-attributes></resource>');
fpw.puts('<created>'+ctime.strftime("%Y%m%dT%H%M%SZ")+'</created>');
fpw.puts('<updated>'+mtime.strftime("%Y%m%dT%H%M%SZ")+'</updated>');
fpw.puts('</note>');
}
fpw.puts("</en-export>");
fpw.close();
@lpm11
Copy link
Author

lpm11 commented Mar 24, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment