Package sabx10 :: Package oxm :: Module utils
[hide private]
[frames] | no frames]

Source Code for Module sabx10.oxm.utils

  1  ############################################################################### 
  2  # 
  3  # sabx10.oxm - an SABX file manipulation library 
  4  # Copyright (C) 2009, 2010 Jay Farrimond (jay@sabikerides.com) 
  5  # 
  6  # This file is part of sabx10.oxm. 
  7  # 
  8  # sabx10.oxm is free software: you can redistribute it and/or modify it under 
  9  # the terms of the GNU Lesser General Public License as published by the Free 
 10  # Software Foundation, either version 3 of the License, or (at your option) any 
 11  # later version. 
 12  # 
 13  # sabx10.oxm is distributed in the hope that it will be useful, but WITHOUT ANY 
 14  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 
 15  # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
 16  # details. 
 17  # 
 18  # You should have received a copy of the GNU Lesser General Public License 
 19  # along with sabx10.oxm.  If not, see <http://www.gnu.org/licenses/>. 
 20  # 
 21  ############################################################################### 
 22  """ 
 23  Various constants and utility functions used by the SABX library. 
 24   
 25  @var cur_version: current version of the SABX file format (always "1.0" for  
 26  the SABX10 library) 
 27  @type cur_version: C{string} 
 28  @var rad_to_nm: multiply a radian value by this to convert it to nautical miles 
 29  @type rad_to_nm: C{float} 
 30  @var nm_to_rad: multiply a nautical mile value by this to convert it to radians 
 31  @type nm_to_rad: C{float} 
 32  @var nm_to_statute: multiply a nautical mile value by this to convert it to  
 33  statute miles 
 34  @type nm_to_statute: C{float} 
 35  @var statute_to_nm: multiply a statute mile value by this to convert it to  
 36  nautical miles 
 37  @type statute_to_nm: C{float} 
 38  @var meter_feet: number of feet in a meter 
 39  @type meter_feet: C{float} 
 40  @var mile_feet: number of feet in a mile 
 41  @type mile_feet: C{float} 
 42  """ 
 43  from math import * 
 44  import xml.etree.ElementTree as et 
 45   
 46  ############################################ 
 47  # GREAT CIRCLE CALCULATIONS 
 48  ############################################ 
 49   
 50  rad_to_nm = 180 * 60 / pi 
 51  nm_to_rad = pi / (180 * 60) 
 52  nm_to_statute = 57875.0 / 50292.0 
 53  statute_to_nm = 50292.0 / 57875.0 
 54  meter_feet = 3.28083989501312 
 55  mile_feet = 5280.0 
 56  kilometer_miles = 0.621371192 
 57   
58 -def calculate_distance(lat1, lon1, lat2, lon2):
59 ''' 60 Calculate the distance between the two points (C{lat1},C{lon1}) and 61 (C{lat2},C{lon2}) in statute miles. 62 63 @param lat1: decimal degrees 64 @type lat1: C{float} 65 @param lon1: decimal degrees (west is negative) 66 @type lon1: C{float} 67 @param lat2: decimal degrees 68 @type lat2: C{float} 69 @param lon2: decimal degrees (west is negative) 70 @type lon2: C{float} 71 72 @return: distance in statute miles 73 @rtype: C{float} 74 ''' 75 lat1 = radians(float(lat1)) 76 lon1 = radians(float(lon1)) 77 lat2 = radians(float(lat2)) 78 lon2 = radians(float(lon2)) 79 rad_dist = 2 * asin( 80 sqrt( 81 pow(sin((lat1-lat2)/2), 2) + 82 cos(lat1) * cos(lat2) * 83 pow(sin((lon1-lon2)/2),2) 84 ) 85 ) 86 nm_dist = rad_dist * rad_to_nm 87 return nm_dist * nm_to_statute
88
89 -def pt_dist_from_pt(lat1, lon1, distance, true_course):
90 """ 91 Calculate a point (C{lat},C{lon}) that is C{distance} statute miles 92 from the point (C{lat1},C{lon1}) along a course C{true_course} degrees. 93 94 Some useful C{true_course} values: 95 - 0.0 - north 96 - 90.0 - east 97 - 180.0 - south 98 - 270.0 - west 99 100 @param lat1: decimal degrees 101 @type lat1: C{float} 102 @param lon1: decimal degrees (west is negative) 103 @type lon1: C{float} 104 @param distance: distance from the point in statute miles 105 @type distance: C{float} 106 @param true_course: true course from the point in degrees 107 @type true_course: C{float} 108 109 @return: (C{lat},C{lon}) representing the calculated point 110 @rtype: (C{float},C{float}) 111 """ 112 # angle_radians=(pi/180)*angle_degrees 113 distance = (distance * statute_to_nm) * nm_to_rad 114 true_course = (pi / 180) * true_course 115 lat1 = radians(lat1) 116 lon1 = radians(-lon1) 117 118 lat = asin( sin(lat1) * cos(distance) + cos(lat1) * 119 sin(distance) * cos(true_course) ) 120 if cos(lat) == 0.0: 121 lon = lon1 # endpoint a pole 122 else: 123 lon = ( 124 (lon1 - asin( sin(true_course) * sin(distance) / cos(lat) ) + pi) % 125 (2*pi) ) - pi 126 127 return degrees(lat), degrees(-lon)
128 129 ############################################ 130 # SABX VERSION 131 ############################################ 132 133 cur_version = "1.0" 134
135 -class VersionException(Exception):
136 """ 137 This exception is raised to indicate an incorrect SABX file version was 138 encoutered. 139 """ 140 pass
141
142 -def check_version(xml_tree):
143 """ 144 Check the version of the XML tree. 145 146 @param xml_tree: an C{ElementTree} C{Element} that's the root of an SABX 147 XML tree 148 @type xml_tree: C{Element} 149 150 @raise VersionException: when the given tree is not of the current version, 151 this exception is raised 152 153 @return: C{True} to indicate good version 154 @rtype: C{boolean} 155 """ 156 if xml_tree.attrib['version'] != cur_version: 157 raise VersionException('Version %s of SABX format expected.' % 158 cur_version) 159 return True
160 161 ############################################ 162 # ELEMENTTREE UTILS 163 ############################################ 164
165 -def get_from_id(elements, id):
166 """ 167 Find an C{ElementTree} element with the given id in a list of elements. 168 169 I can't believe element tree doesn't provide something like this. 170 Actually, it looks like element tree 1.3 may provide something like this 171 with their XPath support - I need to check this out. 172 173 @param elements: C{list} of C{ElementTree} C{Element}s 174 @type elements: C{list} 175 @param id: id of element to find 176 @type id: C{string} 177 178 @return: C{Eement} found or C{None} 179 @rtype: C{Element} 180 """ 181 for element in elements: 182 if element.attrib['id'] == id: 183 return element 184 return None
185
186 -def parse_no_def_namespaces(source):
187 """ 188 Read an XML file using C{ElementTree} tree, stripping default namespace 189 strings from all elements. 190 191 This routine is a little bit precarious. Its aim is to strip the default 192 namespace {uri} from tags so that you don't have to put all that text into 193 find, findall, findtext, etc... when searching the XML tree using the 194 C{ElementTree} stuff. 195 196 This should work most of the time. That is, when there is only one default 197 namespace declared, in the root of the XML tree, then it will be just fine. 198 In other instances, where the default namespace changes throughout the XML 199 document, the behavior can be unexpected. 200 201 Actually, the behavior of this function isn't unexpected. It will work 202 just fine. It's the behaviour of anything using it that will be 203 unexpected. If you change default namespaces, and you have tags that have 204 duplicate local portions that are differentiated by the namespace, then 205 they will all be retrieved by the find... calls. This may not be what you 206 want. Luckily, in the limited world that this routine operates in (so 207 far), this isn't a problem. GPX, TCX, and SABX files all have one default 208 namespace, declared in the root element. Let's hope. 209 210 @param source: XML file to read 211 @type source: C{string} or open file handle 212 213 @return: tree root C{Element} (B{NOT} an C{ElementTree} object) 214 @rtype: C{Element} 215 """ 216 events = ("start", "end", "start-ns") 217 root = None 218 def_namespace = "" 219 for event, elem in et.iterparse(source, events=events): 220 if event == "start": 221 if root is None: 222 root = elem 223 elif event == "start-ns": 224 if elem[0] == '': 225 if elem[1]: 226 def_namespace = "{%s}" % elem[1] 227 else: 228 def_namespace = "" 229 else: 230 if def_namespace: 231 elem.tag = elem.tag.replace(def_namespace, "") 232 return root
233