#!/usr/bin/python
import urllib
import re
import math
import os
import Image
class HtFld(object):
'''Contains a grid of points'''
def __init__(self, imageFileName, htScale = None):
self.img = Image.open(imageFileName)
self.img.load()
self.width, self.height = self.img.size
self.scale = (1,1,1)
self.pos = (0,0,0)
if htScale:
self.htScale = htScale
else:
self.htScale = 1./1024.
def getElev(self,x,z):
# '%d %d && %d %d'%(self.scale[0], self.scale[2], self.pos[0], self.pos[2])
'''return smoothed elevation (and slope?)'''
nx = x - self.pos[0]
nz = z - self.pos[2]
#print '%d %d -> %d %d'%(x,z,nx,nz)
nx *= self.width/self.scale[0]
nz *= self.height/self.scale[2]
nx = min(max(0, nx),self.width-1)
nz = min(max(0, nz),self.height-1)
#print '%d %d -> %d %d'%(x,z,nx,nz)
elev = self.img.getpixel((nx,nz))
elev *= self.htScale
return elev
class btbFile(object):
def __init__(self, filename, htFldImage = None, htScale = None):
'''htfldImage= None means use the first image you find'''
self.htFldImage, self.filename, self.htScale = htFldImage, filename, htScale
self.htFld = None
def writeNewFile(self, alterTracks = None, outfilename = None):
if not outfilename:
# bits = os.path.split(outfilename)
# bits[-1] = 'new_'+bits[-1]
# outfilename = os.path.join(bits)
outfilename = 'new_'+self.filename
'''cheap-ass xml alterer. Changes only list tracks if dict is provided'''
''' not at all tolerant of human edited files'''
re_inbg = re.compile(r'.*<[Bb]ackgroundImage[\s>]+')
re_outbg = re.compile(r'.*</[Bb]ackgroundImage[\s>]+')
re_pathbg = re.compile(r'<Path PathType=".*">([^<]+)</Path>')
re_intrack = re.compile(r'.*<[Tt]rack[\s>]+')
re_outtrack = re.compile(r'.*</[Tt]rack[\s>]+')
re_interrain = re.compile(r'.*<[Tt]errain[Aa]nchor[\s>]+')
re_outterrain = re.compile(r'.*</[Tt]errain[Aa]nchor[\s>]+')
re_innode = re.compile(r'.*<[Nn]ode[\s]+[Nn]odeId\s*=\s*"([0-9]+)')
re_outnode = re.compile(r'.*</[Nn]ode[\s>]+')
re_name = re.compile(r'.*<[Nn]ame>([^<]+)</')
re_pos = re.compile(r'.*<Position x="([e\-\.0-9]+)" y="([e\-\.0-9]+)" z="([e\-\.0-9]+)" />')
re_scale = re.compile(r'.*<Scale x="([e\-\.0-9]+)" y="([e\-\.0-9]+)" z="([e\-\.0-9]+)" />')
re_buildpos = re.compile(r'(.*<Position\s+x="[e\-\.0-9]+"\s+y=")([e\-\.0-9]+)("\s+z="[e\-\.0-9]+" />.*)')
print 'Opening '+self.filename
readfile = open(self.filename,'r')
print 'Will write to '+outfilename
writefile = open(outfilename,'w')
inTrack = False
inNode = False
inTerrain = False
inBg = False
bgPos = None
bgScale = None
bgPath = None
name = None
nodeId = None
doAlter = False
npositions = 0
naltered = 0
for line in readfile.readlines():
if re_inbg.search(line):
#print 'in bg '+line
inBg = True
writefile.write(line)
continue #fast assumption that only one node per line
if re_outbg.search(line):
#update the htFiled as we exit the def for it
bits = os.path.split(bgPath)
print 'out bg '+bgPath+' '+line
#make this the htfld if it is the first one we encountered and the user didn;t ask forone
if (self.htFldImage == None and self.htFld == None) or bits[-1] == self.htFldImage:
self.htFld = HtFld(bgPath, htScale = self.htScale)
self.htFld.pos = bgPos
self.htFld.scale = bgScale
inBg = False
bgPath = None
writefile.write(line)
continue
if inBg:
match = re_pathbg.search(line)
if match:
bgPath = match.group(1)
print 'pathbg '+bgPath
writefile.write(line)
continue
match = re_pos.search(line)
if match:
x = float(match.group(1))
y = float(match.group(2))
z = float(match.group(3))
bgPos = (x,y,z)
#print 'path pos: %f %f %f'%(x,y,z)
writefile.write(line)
continue
match = re_scale.search(line)
if match:
x = float(match.group(1))
y = float(match.group(2))
z = float(match.group(3))
bgScale = (x,y,z)
#print 'path scale: %f %f %f'%(x,y,z)
writefile.write(line)
continue
if re_intrack.search(line):
#print 'in track '+line
inTrack = True
writefile.write(line)
continue #fast assumption that only one node per line
if re_outtrack.search(line):
print 'out track '+name+' '+line
inTrack = False
name = None
writefile.write(line)
continue
if re_interrain.search(line):
#print 'in terrain '+line
inTerrain = True
writefile.write(line)
continue #fast assumption that only one node per line
if re_outterrain.search(line):
#print 'out terrain '+line
inTerrain = False
writefile.write(line)
continue
if name == None and inTrack: #only if we are looking for a name
match = re_name.search(line)
if match:
name = match.group(1)
#print 'name: "'+name+'"'
writefile.write(line)
continue
match = re_innode.search(line)
if match:
nodeId = match.group(1)
#print 'in node '+nodeId
inNode = True
writefile.write(line)
continue #fast assumption that only one node per line
if re_outnode.search(line):
#print 'out node'
nodeId = None
inNode = False
writefile.write(line)
continue
if not (inTrack and inNode) and not inTerrain:
writefile.write(line)
continue #not interested in any more data until we get in a track and node
match = re_pos.search(line)
if match:
x = float(match.group(1))
y = float(match.group(2))
z = float(match.group(3))
y = self.htFld.getElev(x,z)
#print 'new pos: %f %f %f'%(x,y,z)
npositions += 1
naltered += 1
rematch = re_buildpos.search(line)
newline = '%s%f%s\n'%(rematch.group(1),y,rematch.group(3))
writefile.write(newline)
continue
#if nothing else
writefile.write(line)
writefile.close()
print 'Found %d positons, altered %d'%(npositions,naltered)
print 'Wrote to '+outfilename