Source code for gfinder.tamn

"""TAMN module.

This module is a wrapper to the TAMN web service, and provides additional handling for LineString geometries.
"""

import json
from geojson import LineString, MultiLineString
import spiceypy as spice
import numpy as np
import requests
import geodaisy.converters as convert

TAMN_URL = 'http://tamn.spacefrog.design/'

DEFAULT_RADIUS = 50000      # 50000
"""Default radius used in TAMN algorithm.
"""

DEFAULT_POLE_DISTANCE = 0   # 500000
"""Default pole distance used in TAMN algorithm.
"""

[docs]def split_line(line): coords = line lines = [] i0 = 0 for i in range(len(coords)-1): flag, p0 = crossing(coords[i],coords[i+1]) if flag: if i0 > 0: line = [] line.append(p0_next) for coord in coords[i0:i]: line.append(coord) else: line = coords[i0:i] line.append(p0) if len(line) > 1: # exclude one-point line (workaround) lines.append(line) p0_next = [-p0[0], p0[1]] # first point of the next line i0 = i + 1 # start index of next line # add last line if i0 > 0: line = [] line.append(p0_next) for coord in coords[i0:]: line.append(coord) lines.append(line) else: lines = [line] return lines
[docs]def crossing(p1, p2): # [lon, lat] p0 = [0., 0.] p1_x = np.cos(p1[0]*spice.rpd()) p2_x = np.cos(p2[0]*spice.rpd()) if p1_x < 0 and p2_x < 0: p1_y = np.sin(p1[0]*spice.rpd()) p2_y = np.sin(p2[0]*spice.rpd()) if (p1_y > 0 and p2_y < 0) or (p1_y < 0 and p2_y > 0): lat0 = 0.5*(p1[1]+p2[1]) lon0 = p1_y/abs(p1_y) * 180. p0 = [lon0, lat0] return True, p0 return False, p0
[docs]def getSplitLineString(feature): if feature['geometry']['type'] != 'LineString': return feature coords = feature['geometry']['coordinates'] lines = split_line(coords) feature['geometry'] = MultiLineString(lines) # print(type(feature)) # if not feature.is_valid: # print('[WARNING] Invalid GeoJSON Feature.') return feature
[docs]def getSplitFeature(feature): # Handle LineString geometries independently of TAMN. # if feature['geometry']['type'] == 'LineString': return getSplitLineString(feature) # Otherwise, let TAMN handle other geometry types. # # set TAMN web server end-point request = TAMN_URL + 'split' # convert input feature GeoJSON time_inputs_dict in WKT string wkt = convert.geojson_to_wkt(json.dumps(feature['geometry'])) data = json.dumps({"geometry":wkt, "radius":DEFAULT_RADIUS, "pole_distance":DEFAULT_POLE_DISTANCE}) # send split request to TAMN web service r = requests.post(request, data=data, headers={ 'Content-Type':'application/json' } ) if r.status_code != 200: print('[ERROR] POST failed - {code} {text}'.format(code=r.status_code, text=r.text)) return 0 # set new geometry feature['geometry'] = json.loads(r.text)['geometry'] return feature
[docs]def splitGeoJSON(in_geojson_file, out_geojson_file): # Load input GeoJSON file that can contain either only one Feature or a FeatureCollection. with open(in_geojson_file) as f: geojson_dict = json.load(f) # If only one Feature, split and update feature geometry in geojson_dict if geojson_dict['type'] == 'Feature': splitFeature = getSplitFeature(geojson_dict) geojson_dict['geometry'] = splitFeature # If FeatureCollection, split and update each feature elif geojson_dict['type'] == 'FeatureCollection': splitFeatures = [] for feature in geojson_dict['features']: splitFeatures.append(getSplitFeature(feature)) geojson_dict['features'] = splitFeatures # Write geojson_dict input ouput GeoJSON file with open(out_geojson_file, 'w') as f: json.dump(geojson_dict, f)