Last active
July 25, 2017 17:41
-
-
Save b-berry/97fa2117098979c86af28ba4a4aabfad to your computer and use it in GitHub Desktop.
lg-convert-ros
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
#!/usr/bin/env ruby | |
require 'fileutils' | |
require 'logger' | |
require 'nokogiri' | |
require 'open-uri' | |
require 'ostruct' | |
require 'optparse' | |
require 'securerandom' | |
require 'zip' | |
AbstractViewScalar = 1.35.to_f | |
BackupName = "tmp" | |
FileType = ["kml","kmz"] | |
HostROS ="http://localhost" | |
PortROS =":8765" | |
PathROS = "/query.html" | |
QueryROS = "?query=playtour=" | |
RangeMax = 10000 | |
$log = Logger.new('./batchTour.log') | |
$log.level = Logger::WARN | |
class Optparse | |
def self.parse(args) | |
# Parse Options | |
options = OpenStruct.new | |
options.autoplay = false | |
options.backup = BackupName | |
options.dir = './' | |
options.encoding = "utf8" | |
options.view = [] | |
opts = OptionParser.new do |opts| | |
# Set Defaults here | |
opts.banner = "Usage: convertROS.rb [options] -d $PATH" | |
opts.separator "" | |
opts.separator "Specific options:" | |
opts.on("-d", "--asset-dir PATH", | |
"Require asset-dir PATH") do |dir| | |
# Test asset-dir PATH | |
if Dir.exists?(dir) | |
options.dir = dir | |
else | |
STDERR.puts "Specified asset-dir: #{dir}" | |
STDERR.puts " Does not exist. Exiting!" | |
exit 1 | |
end | |
end | |
opts.on("-a", "--autoplay", | |
"Run AutoPlay conversion") do |a| | |
options.autoplay = true | |
end | |
opts.on("-b", "--backup-dir PATH", | |
"Specify backup-dir PATH") do |dir| | |
options.backup = dir | |
end | |
opts.on("-v", "--view initialFOV,targetFOV", Array, | |
"Specify initial,target FOV") do |v| | |
# Test input data type | |
if v.is_a?(Enumerable) | |
v.each do |fov| | |
unless fov.to_f > 0 | |
STDERR.puts "Specified view parameter: #{fov}" | |
STDERR.puts " Invalid. Exiting!" | |
exit 1 | |
end | |
options.view << fov.to_f | |
end | |
else | |
STDERR.puts "Specified view: #{v}:" | |
STDERR.puts " not an array of inital,target FOV. Exiting!" | |
exit 1 | |
end | |
end | |
opts.on_tail("-h", "--help", "Prints this help") do | |
STDOUT.puts opts | |
exit | |
end | |
end | |
opts.parse!(args) | |
options | |
end | |
end | |
def collectFiles(path) | |
files = {} | |
FileType.each do |ext| | |
files[ext.to_sym] = Dir.glob("#{path}/**.#{ext}") | |
STDOUT.puts "Found #{ext.upcase} in #{path.gsub('/','')}: #{files[ext.to_sym].length}" | |
end | |
return files | |
end | |
def backupFile(file,options) | |
# Test backup abs or rel | |
if options.backup[0] == '/' | |
dir = options.backup | |
else | |
dir = [options.dir,options.backup.gsub('./','')].join('/') | |
end | |
unless Dir.exists?(dir) | |
FileUtils.mkdir_p dir | |
end | |
# Test dir creation | |
unless Dir.exists?(dir) | |
STDERR.puts "Could not create specified backup-dir: #{dir}" | |
STDERR.puts " Does not exist. Exiting!" | |
exit 1 | |
end | |
## Backup file | |
FileUtils::cp file, dir | |
# Test backup | |
bfile = [dir,File.basename(file)].join('/') | |
unless File.exists?(bfile) | |
STDERR.puts "Filed to create specified backup-file: #{bfile}" | |
STDERR.puts " Check failed - File does not exist . Exiting!" | |
exit 2 | |
end | |
end | |
def parseFiles(files,options) | |
files.keys.each do |type| | |
STDOUT.puts "Processing #{type}:" | |
files[type].each do |file| | |
STDOUT.puts " #{file.split('/').last}" | |
# Test filetype | |
ftype = `file #{file}` | |
case ftype | |
when /XML/ | |
# Open KML file | |
doc = File.open(file) { |f| Nokogiri::XML(f) } | |
convertFile(doc,file,options) | |
writeFile(doc,file) | |
when /Zip/ | |
#zipFile(doc,file) | |
FileUtils::mkdir_p "#{options.dir}/#{TempDir}" | |
#processKmz(file) | |
unzipFile(file,options) | |
else | |
next | |
end | |
end | |
end | |
end | |
def convertAutoplay(url) | |
# Extract Director Url | |
href = URI.parse(url.css("href").text) | |
host = href.host | |
port = href.port | |
path = href.path | |
query = href.query | |
# Skip if query missing | |
return if query.empty? or query.nil? | |
# Extract #{tourname} | |
# Set delimiter | |
if query.include?('&') | |
del = '&' | |
else | |
del = '&' | |
end | |
if query.split(del).length > 1 | |
query.split(del).each do |que| | |
playtourTest = que.split('=').index('playtour') | |
next if playtourTest.nil? | |
@tourname = que.split('=')[playtourTest.to_f + 1] | |
end | |
else | |
playtourTest = query.split('=').index('playtour') | |
@tourname = query.split('=')[playtourTest.to_f + 1] | |
end | |
# Confirm tourname | |
if @tourname.nil? then | |
puts "No Tourname Found! Skipping NetworkLink" | |
return | |
end | |
#queryRosString = URI.encode_www_form(QueryROS => @tourname) | |
queryRosString = "#{QueryROS}#{@tourname}" | |
# Modify Autoplay Url | |
hrefRosReplace = URI.parse("#{HostROS}#{PortROS}#{PathROS}#{queryRosString}") | |
puts "...Modifying Url: #{hrefRosReplace}" | |
return hrefRosReplace | |
end | |
def convertFile(doc,file,options) | |
networkLink = doc.css("NetworkLink") | |
# Skip file if no NetworkLink present | |
return if networkLink.empty? | |
# Get networkLink Name | |
networkLinkName = networkLink.css("name") | |
if networkLinkName.css("name").text == "Autoplay" then | |
# Backup File to be modified | |
backupFile(file,options) | |
# Run autoplay convert | |
if options.autoplay | |
# Build updated URI | |
hrefRosReplace = convertAutoplay(networkLink) | |
STDOUT.puts "...Modifying Url: #{hrefRosReplace}" | |
networkLink.at_css("href").content = hrefRosReplace | |
end | |
# Run abstractView convert | |
unless options.view.empty? | |
abstractViews = doc.css("LookAt") | |
# Skip file if no LookAtpresent | |
return if abstractViews.empty? | |
# Run convertView method | |
STDOUT.puts "...Convertinv abstractView: #{file}" | |
abstractViews.each{ |lookat| | |
convertView(lookat,options.view) | |
} | |
end | |
end | |
return doc | |
end | |
def convertView(lookat,view) | |
# Extract View Variables | |
range = lookat.children.css("range").text.to_f | |
tilt = lookat.children.css("tilt").text.to_f | |
# Trig FOV calculation - Note: convert deg to radians during processing && acount for bezel and gaps in 3.5 screen calculation | |
range_i = ( range * Math.tan( ( 3.50 * view[0].to_f + 3 * 1.015 ) * ( Math::PI / 180 ) ) ).abs / ( Math.tan( ( 3.50 * view[1].to_f + 3 * 1.015 ) * ( Math::PI / 180 ) ) ).abs | |
tilt_i = tilt * 1.17 | |
STDOUT.puts "... #{[ range, range_i ].join(' => ')}" | |
STDOUT.puts "... #{[ tilt, tilt_i ].join(' => ')}" | |
# Modify view | |
unless lookat.children.at_css("range").nil? or tilt_i > 90.0 | |
lookat.children.at_css("range").content = range_i | |
lookat.children.at_css("tilt").content = tilt_i | |
end | |
end | |
def imageResize(file,img,entry) | |
img_r = "#{img.gsub('.png','')}-resize.png" | |
puts "...Resizing #{img} -> #{img_r}" | |
`convert #{img} -resize x2160 #{img_r}` | |
# fix | |
`ln -snf "#{File.basename(img_r)}" "#{img}"` | |
# Zip image | |
zipFile(file, img_r, entry) | |
end | |
def writeFile(doc,file) | |
puts "...Writing modifications: #{file}" | |
#File.open(file, 'w') { |f| f.print(doc.to_xml) } | |
File.write("#{file}", doc.to_xml) | |
puts "...done." | |
end | |
def processKmz(file) | |
puts "...Attempting Zip Extraction." | |
# ZipRuby gem usage | |
Zip::Archive.open(file) do |ar| | |
i = 0 | |
ar.each do |f| | |
fname = f.name | |
if fname.split('.').last == "kml" | |
ar.fopen(fname) do |d| | |
doc = Nokogiri::XML(d.read) | |
convertFile(doc) | |
# Replace w/ updated #{doc} | |
doc_update = doc.serialize | |
doc_replace = StringIO.new | |
doc_replace.write doc_update | |
ar.replace_io(i,doc_replace) | |
ar.commit | |
end | |
end | |
i += 1 | |
end | |
end | |
end | |
def userConfirm(options) | |
# Issue warning | |
STDOUT.puts "### WARNING!! ###" | |
STDOUT.puts "# Running this script will modify asset_files in: #{options.dir}" | |
STDOUT.puts "###" | |
STDOUT.puts | |
STDOUT.printf "Please type 'YES' to continue: " | |
prompt = STDIN.gets.chomp | |
exitRun unless prompt == 'YES' | |
end | |
def exitRun() | |
STDOUT.puts "User Aborted, exiting!" | |
exit 0 | |
end | |
def unzipFile(file,options) | |
puts "...Unpacking KMZ: #{file}..." | |
zip_entries = [] | |
# RubyZip gem usage | |
d_name = File.basename(file).gsub('.','-').gsub(' ','-') | |
t_path = "#{options.dir}/#{TempDir}/#{d_name}" | |
Zip::File.open(file).each do |entry| | |
fullname = entry.to_s | |
filename = File.basename(fullname) | |
case fullname.split('.').last | |
when 'kml' | |
doc_string = entry.get_input_stream.read | |
doc = Nokogiri::XML(doc_string) | |
## Process KML | |
convertFile(doc,file,options) | |
## Test KML | |
if doc_string == doc.serialize | |
puts "...No change found. Skipping." | |
next | |
end | |
zip_entries << { :name => entry, :content => doc.serialize } | |
## Write modified doc to disk | |
FileUtils.mkdir_p(t_path) unless File.directory?(t_path) | |
doc_update = "#{t_path}/#{filename}" | |
File.write("#{doc_update}", doc.to_xml) | |
zipFile(file, doc_update, fullname) | |
else | |
# Skip file | |
next | |
end | |
end | |
end | |
def zipFile(file, filename, entry) | |
if File.exists?(filename) | |
Zip::File.open(file) do |zip_update| | |
puts "...Updating: #{file}" | |
puts " #{filename} -> #{entry}" | |
#zip_update.replace("#{entry}","#{filename}") | |
f_ext = "#{File.basename(filename).split('.').last}" | |
temp_n = "#{SecureRandom.urlsafe_base64}.#{f_ext}" | |
zip_update.remove(entry) | |
zip_update.add(temp_n, filename) | |
zip_update.rename(temp_n, entry) | |
end | |
puts "...OK." | |
else | |
puts "...ERROR! File not found: #{filename}" | |
puts " Failed to update: #{file}" | |
puts " Archived file: #{entry}" | |
end | |
end | |
### Run Time Operations Start Here ### | |
options = Optparse.parse(ARGV) | |
# Set ZIP extraction dir | |
TempDir = "#{options.backup}/.zip" | |
STDOUT.puts options | |
files = collectFiles(options.dir) | |
# Get user permision to run conversion | |
userConfirm(options) | |
# Process files | |
parseFiles(files,options) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Current Issue:
FOV Conversion results in approximate view rendering for range0 => range1 modification, but testing on LG platform shows necessary
KML::LookAt:tilt
modification in order to replicate AbstractView across FOV change.Attaching a diagram of what I think needs to be formulated to find
a == tilt0 => c == tilt1
during transformation.