def ellipsoid(self, acronym): '''Return the ellipsoid associated with the acronym''' if acronym == 'WGS84': return (Geodesic.WGS84) elif acronym in self.acronymList: param = self.acronymList[acronym].parameters return(Geodesic(param.semiMajor, 1.0 / param.inverseFlattening)) elif acronym in historical_ellipsoids: return(Geodesic(historical_ellipsoids[acronym][1], 1.0 / historical_ellipsoids[acronym][2])) else: return(None)
def test_GeodSolve33(self): # Check max(-0.0,+0.0) issues 2015-08-22 (triggered by bugs in # Octave -- sind(-0.0) = +0.0 -- and in some version of Visual # Studio -- fmod(-0.0, 360.0) = +0.0. inv = Geodesic.WGS84.Inverse(0, 0, 0, 179) self.assertAlmostEqual(inv["azi1"], 90.00000, delta=0.5e-5) self.assertAlmostEqual(inv["azi2"], 90.00000, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 19926189, delta=0.5) inv = Geodesic.WGS84.Inverse(0, 0, 0, 179.5) self.assertAlmostEqual(inv["azi1"], 55.96650, delta=0.5e-5) self.assertAlmostEqual(inv["azi2"], 124.03350, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 19980862, delta=0.5) inv = Geodesic.WGS84.Inverse(0, 0, 0, 180) self.assertAlmostEqual(inv["azi1"], 0.00000, delta=0.5e-5) self.assertAlmostEqual(abs(inv["azi2"]), 180.00000, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 20003931, delta=0.5) inv = Geodesic.WGS84.Inverse(0, 0, 1, 180) self.assertAlmostEqual(inv["azi1"], 0.00000, delta=0.5e-5) self.assertAlmostEqual(abs(inv["azi2"]), 180.00000, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 19893357, delta=0.5) geod = Geodesic(6.4e6, 0) inv = geod.Inverse(0, 0, 0, 179) self.assertAlmostEqual(inv["azi1"], 90.00000, delta=0.5e-5) self.assertAlmostEqual(inv["azi2"], 90.00000, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 19994492, delta=0.5) inv = geod.Inverse(0, 0, 0, 180) self.assertAlmostEqual(inv["azi1"], 0.00000, delta=0.5e-5) self.assertAlmostEqual(abs(inv["azi2"]), 180.00000, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 20106193, delta=0.5) inv = geod.Inverse(0, 0, 1, 180) self.assertAlmostEqual(inv["azi1"], 0.00000, delta=0.5e-5) self.assertAlmostEqual(abs(inv["azi2"]), 180.00000, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 19994492, delta=0.5) geod = Geodesic(6.4e6, -1 / 300.0) inv = geod.Inverse(0, 0, 0, 179) self.assertAlmostEqual(inv["azi1"], 90.00000, delta=0.5e-5) self.assertAlmostEqual(inv["azi2"], 90.00000, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 19994492, delta=0.5) inv = geod.Inverse(0, 0, 0, 180) self.assertAlmostEqual(inv["azi1"], 90.00000, delta=0.5e-5) self.assertAlmostEqual(inv["azi2"], 90.00000, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 20106193, delta=0.5) inv = geod.Inverse(0, 0, 0.5, 180) self.assertAlmostEqual(inv["azi1"], 33.02493, delta=0.5e-5) self.assertAlmostEqual(inv["azi2"], 146.97364, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 20082617, delta=0.5) inv = geod.Inverse(0, 0, 1, 180) self.assertAlmostEqual(inv["azi1"], 0.00000, delta=0.5e-5) self.assertAlmostEqual(abs(inv["azi2"]), 180.00000, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 20027270, delta=0.5)
def _Geodesic(points, closed, datum, line, wrap): # Compute the area or perimeter of a polygon/-line # using the GeographicLib package, iff installed try: from geographiclib.geodesic import Geodesic except ImportError: raise ImportError('no %s' % ('geographiclib', )) if not wrap: # capability LONG_UNROLL always set raise ValueError('%s invalid: %s' % ('wrap', wrap)) _, points = polygon(points, closed=closed) # base=LatLonEllipsoidalBase(0, 0) E = datum.ellipsoid g = Geodesic(E.a, E.f).Polygon(line) # note, lon deltas are unrolled, by default for p in points: g.AddPoint(p.lat, p.lon) if line and closed: p = points[0] g.AddPoint(p.lat, p.lon) # g.Compute returns (number_of_points, perimeter, signed area) return g.Compute(False, True)[1 if line else 2]
def get_endpoint(lat1, lon1, bearing, d): geod = Geodesic(Constants.WGS84_a, Constants.WGS84_f) d = geod.Direct(lat1, lon1, bearing, d)#* 1852.0) return d['lat2'], d['lon2']
class CtxLocalizer(GeodesicLocalizer): """ A localizer for the CTX instrument (subclass of :py:class:`GeodesicLocalizer`) """ DEFAULT_RESOLUTION_M = 1e-3 """ Sets the default resolution for CTX localization """ BODY = Geodesic(MARS_RADIUS_M, 0.0) # Works better assuming sphere """ Uses a Geodesic model for CTX that assumes Mars is spherical, which seems to work better in practice. """ def __init__(self, metadata): """ :param metadata: "ctx" :py:class:`~pdsc.metadata.PdsMetadata` object """ flipped_na = (180 - metadata.north_azimuth if metadata.usage_note == 'F' else metadata.north_azimuth) super(CtxLocalizer, self).__init__( metadata.lines / 2.0, metadata.samples / 2.0, metadata.center_latitude, metadata.center_longitude, metadata.lines, metadata.samples, metadata.image_height / metadata.lines, metadata.image_width / metadata.samples, flipped_na, -1 )
def get_gc_positions(start, end): """ Get positions along a Great Circle to enable plotting. I couldn't do this with Basemap as we have to instantiate first and we don't know the map boundaries until we have the GC positions. :param start: The start position :type start: tuple :param end: The end position :type end: tuple :return: list of positions :rtype: list of dict """ positions = [] spacing = 100000 # Positions 100km apart geoid = Geodesic(Constants.WGS84_a, Constants.WGS84_f) gc = geoid.InverseLine( start[0], start[1], end[0], end[1] ) n = math.ceil(gc.s13 / spacing) for i in range(n + 1): s = min(spacing * i, gc.s13) result = gc.Position(s, Geodesic.STANDARD | Geodesic.LONG_UNROLL) position = { 'Lat': result['lat2'], 'Lon': result['lon2'] } positions.append(position) return positions
class MocLocalizer(GeodesicLocalizer): """ A localizer for the MOC observations (subclass of :py:class:`GeodesicLocalizer`) """ DEFAULT_RESOLUTION_M = 1e-3 """ Sets the default resolution for MOC localization """ BODY = Geodesic(MARS_RADIUS_M, 0.0) """ Uses a Geodesic model for MOC that assumes Mars is spherical, which seems to work better in practice. """ def __init__(self, metadata): """ :param metadata: "moc" :py:class:`~pdsc.metadata.PdsMetadata` object """ super(MocLocalizer, self).__init__( metadata.lines / 2.0, metadata.samples / 2.0, metadata.center_latitude, metadata.center_longitude, metadata.lines, metadata.samples, metadata.image_height / metadata.lines, metadata.image_width / metadata.samples, metadata.north_azimuth, 1 )
def getEndpoint(lat1, lon1, d1, d2): bearing = random.uniform(0, 360) dist = random.uniform(d1, d2) radius = (d2-d1)/2 geod = Geodesic(Constants.WGS84_a, Constants.WGS84_f) d = geod.Direct(lat1, lon1, bearing, dist) return d['lon2'], d['lat2'], radius
def __init__(self): """Initiate all instances of the classes that are needed for the simulation, and start PyGame. Raises: Exception: If you fail to choose a valid simulation setting, an Exception is raised. """ while True: try: string = str( input('Do you want to take in live GNSS-signals? (y/n)\t')) if string in ('y', 'yes'): self.test_mode_on = False try: self.gps = serial.Serial('/dev/ttyACM0', baudrate=9600) except Exception: print( "The port cannot be opened. Check that your unit is connected to the port you're opening." ) exit() elif string in ('n', 'no'): self.test_mode_on = True else: raise Exception except Exception: print('Please type "y" or "n".') else: break self.clock = pg.time.Clock() self.the_arrow = Arrow() self.map = Map(60.75, 11.99) self.the_text = Text() self.earth = Geodesic(cf.R_E, 0) self.out_q = mp.Manager().Value('i', [0.0, 0.0]) self.NS = self.map.center_y self.EW = self.map.center_x self.the_background = pg.image.load('background.jpg') self.process = False self.background = False self.dot_x, self.dot_y = self.the_arrow.two_d_pos.x, self.the_arrow.two_d_pos.y self.pastNS, self.pastEW = self.NS, self.EW # Create a new log file for this session. with open("log.txt", "w") as log: log.write("") try: what_os = platform.system() if what_os == 'Linux': self.g_earth = subprocess.Popen('google-earth-pro') elif what_os == 'Darwin': subprocess.call([ "/usr/bin/open", "-n", "-a", "/Applications/Google Earth Pro.app" ]) except Exception: pass # Wait for Google Earth Pro to open so that the PyGame window opens as the top layer. time.sleep(5) pg.init() pg.display.set_caption("Real time spoofer") self.screen = pg.display.set_mode((cf.SCREEN_WIDTH, cf.SCREEN_HEIGHT))
def test_GeodSolve12(self): # Check fix for inverse geodesics on extreme prolate/oblate # ellipsoids Reported 2012-08-29 Stefan Guenther # <*****@*****.**>; fixed 2012-10-07 geod = Geodesic(89.8, -1.83) inv = geod.Inverse(0, 0, -10, 160) self.assertAlmostEqual(inv["azi1"], 120.27, delta=1e-2) self.assertAlmostEqual(inv["azi2"], 105.15, delta=1e-2) self.assertAlmostEqual(inv["s12"], 266.7, delta=1e-1)
def gps2dist_azimuth(lat1, lon1, lat2, lon2, a=WGS84_A, f=WGS84_F): """ Computes the distance between two geographic points on the WGS84 ellipsoid and the forward and backward azimuths between these points. :param lat1: Latitude of point A in degrees (positive for northern, negative for southern hemisphere) :param lon1: Longitude of point A in degrees (positive for eastern, negative for western hemisphere) :param lat2: Latitude of point B in degrees (positive for northern, negative for southern hemisphere) :param lon2: Longitude of point B in degrees (positive for eastern, negative for western hemisphere) :param a: Radius of Earth in m. Uses the value for WGS84 by default. :param f: Flattening of Earth. Uses the value for WGS84 by default. :return: (Great circle distance in m, azimuth A->B in degrees, azimuth B->A in degrees) .. note:: This function will check if you have installed the Python module `geographiclib <http://geographiclib.sf.net>`_ - a very fast module for converting between geographic, UTM, UPS, MGRS, and geocentric coordinates, for geoid calculations, and for solving geodesic problems. Otherwise the locally implemented Vincenty's Inverse formulae (:func:`obspy.core.util.geodetics.calc_vincenty_inverse`) is used which has known limitations for two nearly antipodal points and is ca. 4x slower. """ if HAS_GEOGRAPHICLIB: if lat1 > 90 or lat1 < -90: msg = "Latitude of Point 1 out of bounds! (-90 <= lat1 <=90)" raise ValueError(msg) if lat2 > 90 or lat2 < -90: msg = "Latitude of Point 2 out of bounds! (-90 <= lat2 <=90)" raise ValueError(msg) result = Geodesic(a=a, f=f).Inverse(lat1, lon1, lat2, lon2) azim = result['azi1'] if azim < 0: azim += 360 bazim = result['azi2'] + 180 return (result['s12'], azim, bazim) else: try: values = calc_vincenty_inverse(lat1, lon1, lat2, lon2, a, f) if np.alltrue(np.isnan(values)): raise StopIteration return values except StopIteration: msg = ("Catching unstable calculation on antipodes. " "The currently used Vincenty's Inverse formulae " "has known limitations for two nearly antipodal points. " "Install the Python module 'geographiclib' to solve this " "issue.") warnings.warn(msg) return (20004314.5, 0.0, 0.0) except ValueError as e: raise e
def calc_dist_azi(source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg, radius_of_planet_in_km, flattening_of_planet): """ Given the source and receiver location, calculate the azimuth from the source to the receiver at the source, the backazimuth from the receiver to the source at the receiver and distance between the source and receiver. :param source_latitude_in_deg: Source location latitude in degrees :type source_latitude_in_deg: float :param source_longitude_in_deg: Source location longitude in degrees :type source_longitude_in_deg: float :param receiver_latitude_in_deg: Receiver location latitude in degrees :type receiver_latitude_in_deg: float :param receiver_longitude_in_deg: Receiver location longitude in degrees :type receiver_longitude_in_deg: float :param radius_of_planet_in_km: Radius of the planet in km :type radius_of_planet_in_km: float :param flattening_of_planet: Flattening of planet (0 for a sphere) :type receiver_longitude_in_deg: float :returns: distance_in_deg (in degrees), source_receiver_azimuth (in degrees) and receiver_to_source_backazimuth (in degrees). :rtype: tuple of three floats """ if geodetics.HAS_GEOGRAPHICLIB: ellipsoid = Geodesic(a=radius_of_planet_in_km * 1000.0, f=flattening_of_planet) g = ellipsoid.Inverse(source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg) distance_in_deg = g['a12'] source_receiver_azimuth = g['azi1'] % 360 receiver_to_source_backazimuth = (g['azi2'] + 180) % 360 else: # geographiclib is not installed - use obspy/geodetics values = gps2dist_azimuth(source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg, a=radius_of_planet_in_km * 1000.0, f=flattening_of_planet) distance_in_km = values[0] / 1000.0 source_receiver_azimuth = values[1] % 360 receiver_to_source_backazimuth = values[2] % 360 # NB - km2deg assumes spherical planet... generate a warning if flattening_of_planet != 0.0: msg = "Assuming spherical planet when calculating epicentral " + \ "distance. Install the Python module 'geographiclib' " + \ "to solve this." warnings.warn(msg) distance_in_deg = kilometer2degrees(distance_in_km, radius=radius_of_planet_in_km) return (distance_in_deg, source_receiver_azimuth, receiver_to_source_backazimuth)
def test_GeodSolve2(self): # Check fix for antipodal prolate bug found 2010-09-04 geod = Geodesic(6.4e6, -1 / 150.0) inv = geod.Inverse(0.07476, 0, -0.07476, 180) self.assertAlmostEqual(inv["azi1"], 90.00078, delta=0.5e-5) self.assertAlmostEqual(inv["azi2"], 90.00078, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 20106193, delta=0.5) inv = geod.Inverse(0.1, 0, -0.1, 180) self.assertAlmostEqual(inv["azi1"], 90.00105, delta=0.5e-5) self.assertAlmostEqual(inv["azi2"], 90.00105, delta=0.5e-5) self.assertAlmostEqual(inv["s12"], 20106193, delta=0.5)
def measure(self, a, b): a, b = Point(a), Point(b) lat1, lon1 = a.latitude, a.longitude lat2, lon2 = b.latitude, b.longitude if not (isinstance(self.geod, Geodesic) and self.geod.a == self.ELLIPSOID[0] and self.geod.f == self.ELLIPSOID[2]): self.geod = Geodesic(self.ELLIPSOID[0], self.ELLIPSOID[2]) s12 = self.geod.Inverse(lat1, lon1, lat2, lon2, Geodesic.DISTANCE)['s12'] return s12
def calc_dist(source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg, radius_of_earth_in_km, flattening_of_earth): """ Given the source and receiver location, calculate the azimuth and distance. :param source_latitude_in_deg: Source location latitude in degrees :type source_latitude_in_deg: float :param source_longitude_in_deg: Source location longitude in degrees :type source_longitude_in_deg: float :param receiver_latitude_in_deg: Receiver location latitude in degrees :type receiver_latitude_in_deg: float :param receiver_longitude_in_deg: Receiver location longitude in degrees :type receiver_longitude_in_deg: float :param radius_of_earth_in_km: Radius of the Earth in km :type radius_of_earth_in_km: float :param flattening_of_earth: Flattening of Earth (0 for a sphere) :type receiver_longitude_in_deg: float :return: distance_in_deg :rtype: float """ if geodetics.HAS_GEOGRAPHICLIB: ellipsoid = Geodesic(a=radius_of_earth_in_km*1000.0, f=flattening_of_earth) g = ellipsoid.Inverse(source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg) distance_in_deg = g['a12'] else: # geographiclib is not installed - use obspy/geodetics values = gps2dist_azimuth(source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg, a=radius_of_earth_in_km*1000.0, f=flattening_of_earth) distance_in_km = values[0]/1000.0 # NB - km2deg assumes spherical Earth... generate a warning if flattening_of_earth != 0.0: msg = "Assuming spherical Earth when calculating epicentral " + \ "distance. Install the Python module 'geographiclib' " + \ "to solve this." warnings.warn(msg) distance_in_deg = kilometer2degrees(distance_in_km, radius=radius_of_earth_in_km) return distance_in_deg
def find_corners(lat_lon_file, tolerance=1, min_angle=np.pi * 0.22, geoid=Geodesic(6371., 0.), lsz=None): """ Credit to unutbu from Stack Overflow (https://stackoverflow.com/questions/14631776/calculate-turning-points-pivot-points-in-trajectory-path) Modifed by PySkew author Kevin Gaastra to run on a sphere Runs the Ramer-Douglas-Peucker algorithm to simplify the lat, lon path stored in the specified lat_lon_file. It prints out the number of points in the origional path and the number of points in the simplified path. Then calculates the points in the simplified path that constitute a turn greater than min_angle. Parameters ---------- lat_lon_file - file containing lattitude and longitude in that order in columns seperated by whitespace tolerance - the tolerance of the RDP algorithm more tolerance=less points kept (default=1) min_angle - angle in radians that should constitute a "significant" change in heading Returns ------- Tuple - (numpy array number_of_points_in_origionalx2 containing the origional data, number_of_points_in_simplifiedx2 containing the simplified data, and an array containing the locations in the simplified data where turns exceeding min_angle are found) """ path = os.path.expanduser(lat_lon_file) points = np.genfromtxt(path) print("original number of points = %d" % len(points)) # Use the Ramer-Douglas-Peucker algorithm to simplify the path # http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm # Python implementation: https://github.com/sebleier/RDP/ simplified = np.array( rdp.rdp(points.tolist(), tolerance, dist=create_geo_gc_dist(geoid))) # simplified = np.array(kmg9_rdp(points.tolist(), tolerance, create_geo_gc_dist(geoid),lsz=lsz)) print("simplified number of points = %d" % len(simplified)) # compute the direction vectors on the simplified curve # directions = np.diff(simplified, axis=0) theta = geo_angle(simplified) # Select the index of the points with the greatest theta # Large theta is associated with greatest change in direction. idx = np.where(theta > np.rad2deg(min_angle))[0] + 1 print("number of significant turns = %d" % len(idx)) return points, simplified, idx
def destination(self, point, bearing, distance=None): point = Point(point) lat1 = point.latitude lon1 = point.longitude azi1 = bearing if distance is None: distance = self if isinstance(distance, Distance): distance = distance.kilometers if not (isinstance(self.geod, Geodesic) and self.geod.a == self.ELLIPSOID[0] and self.geod.f == self.ELLIPSOID[2]): self.geod = Geodesic(self.ELLIPSOID[0], self.ELLIPSOID[2]) r = self.geod.Direct(lat1, lon1, azi1, distance, Geodesic.LATITUDE | Geodesic.LONGITUDE) return Point(r['lat2'], r['lon2'])
def geo_angle(points, geoid=Geodesic(6371., 0.)): """ Returns the angles between two great circles for a set of points Parameters ---------- points : 2D-Ndarray lat-lon array of points on a sphere between which to calculate angles Returns ---------- angles : 1D-Ndarray angles between the great circles defined by points of shape (N-1,), with each value between 0 and 180 degrees. """ return np.abs( np.diff( list( map(lambda a, b, c, d: geoid.Inverse(a, b, c, d)["azi1"], points[:-1, 0], points[:-1, 1], points[1:, 0], points[1:, 1]))))
def calculate_distances(self): #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Calculates the distance between all neuron positions *along the surface* (using geodesic distances) ~ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # The geographiclib.geodesic module is needed to calculate geodesic distance along the surface of a spheroid. # - Library is based on Karney 2013 (seemingly written by Karney himself) # - See https://geographiclib.sourceforge.io/1.48/python/ try: from geographiclib.geodesic import Geodesic except: exitOnNetworkGeometryError("The geographiclib.geodesic module is needed to calculate geodesic distance along the surface of a spheroid, but this module could not be imported.") # The Geodesic object constructor has two parameters: # - a: the equatorial (xy) radius of the ellipsoid # - f: the flattening of the ellipsoid. b = a(1-f) --> f = 1 - b/a (where b is the polar (z) axis) a = self.r_xy b = self.r_z f = 1.0 - b/a geodesic = Geodesic(a, f) # Convert parametric coordinates (theta(lon), phi(lat)) from radian to degree angles degreecoords = numpy.degrees(self.parametricCoords) # print self.coordinates # print "degrees" # print degreecoords for i in range(self.N): for j in range(self.N): # Geodesic.Inverse(...) calculates the geodesic distance between two points along a spheroid surface. # arguments: (lat1, lon1, lat2, lon2, outmask=1025) # - expects lat1, lon1, lat2, lon2 to be latitude(theta)/longitude(phi) angles in degrees # - outmask=1025 tells it to return the distance measure # returns: a Geodesic dictionary including key-value pair 's12', which is the calculated distance between the points. lat1 = degreecoords[i][1] lon1 = degreecoords[i][0] lat2 = degreecoords[j][1] lon2 = degreecoords[j][0] # print geodesic.Inverse(lat1, lon1, lat2, lon2, outmask=1025) # print "lat" + str(lat1) + " lon" + str(lon1) + " :: lat" + str(lat2) + " lon" + str(lon2) dist = geodesic.Inverse(lat1, lon1, lat2, lon2, outmask=1025)['s12'] self.distances[i,j] = dist
def globe_distance( lat1: float, lon1: float, lat2: float, lon2: float, round_to: int = 5, ) -> float: """ Compute the great circle distance in km between two points on Earth. """ _check_latitude(lat1, 'lat1') _check_latitude(lat2, 'lat2') result = Geodesic(a=WGS84_A, f=WGS84_F).Inverse(lat1, lon1, lat2, lon2) # Used to cope with minor floating point differences between operating # systems that we don't care about for ESCI451 if round_to: return round(result['s12'] / 1000., round_to) else: return result['s12'] / 1000.
# Declarar bibliotecas-------------------------------------------------------------------------------------------- import os import netCDF4 import numpy as np import pandas as pd from geographiclib.geodesic import Geodesic # Definir os parâmetros do elipsoide TOPEX --------------------------------------------------------------------------------------- a=6378136.300000 b=6356751.600563 f=(a-b)/a geod = Geodesic(a, f) # Inserir os passes ------------------------------------------------------------------------------------------------ for escolha_passe in ['0239', '0228', '0163', '0152', '0076', '0050']: # Abrir os arquivos com extensão .nc e ler os dados-------------------------------------------------------------- def dados_EOT(num): jday=[] jlon=[] jlat=[] jltide=[] jotide=[] missions=os.listdir('Link do diretório do Modelo EOT') for i in range(0,len(missions),1): print('Missão escolhida:',missions[i]) link='Link do diretório do Modelo EOT/%s'%(missions[i])
def test_GeodSolve28(self): # Check for bad placement of assignment of r.a12 with |f| > 0.01 (bug in # Java implementation fixed on 2015-05-19). geod = Geodesic(6.4e6, 0.1) dir = geod.Direct(1, 2, 10, 5e6) self.assertAlmostEqual(dir["a12"], 48.55570690, delta=0.5e-8)
def test_GeodSolve26(self): # Check 0/0 problem with area calculation on sphere 2015-09-08 geod = Geodesic(6.4e6, 0) inv = geod.Inverse(1, 2, 3, 4, Geodesic.AREA) self.assertAlmostEqual(inv["S12"], 49911046115.0, delta=0.5)
def test_GeodSolve15(self): # Initial implementation of Math::eatanhe was wrong for e^2 < 0. This # checks that this is fixed. geod = Geodesic(6.4e6, -1 / 150.0) dir = geod.Direct(1, 2, 3, 4, Geodesic.AREA) self.assertAlmostEqual(dir["S12"], 23700, delta=0.5)
event.az = 253 event.latitude = 15.09 event.longitude = 179.59 elif event.name == "S0325a": event.distance = 38.4 event.baz = 0.0 event.az = 180.0 from geographiclib.geodesic import Geodesic radius = 3389.5 flattening = 0.0 dict = Geodesic(a=radius, f=flattening).ArcDirect( lat1=rec.latitude, lon1=rec.longitude, azi1=event.baz, a12=event.distance, outmask=1929, ) event.latitude = dict["lat2"] event.longitude = dict["lon2"] """ Define forward modeler """ forward_method = "INSTASEIS" # db_path = v["db_path"] # npz_file = v["npz_file"] db_nr = 0 for db_path, npz_file in zip(db_names, npz_file_names): db_nr += 0 # mnt_folder = "/mnt/marshost/" # if not lsdir(mnt_folder):
Requirements: geographiclib==1.46.3 pyproj==1.9.5.1 geopy==1.11.0 git+https://github.com/xoolive/geodesy@c4eb611cc225908872715f7558ca6a686271327a ''' from math import radians, sin, cos, asin, sqrt, pi, atan, atan2, fabs from time import time import geopy.distance import pyproj from geographiclib.geodesic import Geodesic, Constants import geodesy.sphere as geo geod = pyproj.Geod(ellps='WGS84') geodesic = Geodesic(a=Constants.WGS84_a, f=Constants.WGS84_f) p_minsk = (27.561831, 53.902257) p_moscow = (37.620393, 55.75396) # https://en.wikipedia.org/wiki/Earth_radius#Mean_radius EARTH_MEAN_RADIUS = 6371008.8 EARTH_MEAN_DIAMETER = 2 * EARTH_MEAN_RADIUS # https://en.wikipedia.org/wiki/Earth_radius#Equatorial_radius EARTH_EQUATORIAL_RADIUS = 6378137.0 EARTH_EQUATORIAL_METERS_PER_DEGREE = pi * EARTH_EQUATORIAL_RADIUS / 180 # 111319.49079327358 I_EARTH_EQUATORIAL_METERS_PER_DEGREE = 1 / EARTH_EQUATORIAL_METERS_PER_DEGREE def approximate_distance(point1, point2):
Python geographiclib is also required: pip install geographiclib """ import math import pandas as pd import matplotlib.pyplot as plt from scipy.misc import imread from geographiclib.geodesic import Geodesic geod = Geodesic.WGS84 geod = Geodesic(6378388, 1/297.0) # the international ellipsoid plt.style.use('ggplot') def makemap(title): # plot all the airports dots fig = plt.figure(figsize=(48,24)) ax = fig.add_subplot(111) ax.set_title(title.decode('utf8')) ax.grid(b=False) for spine in ['left','right','top','bottom']: ax.spines[spine].set_color('k') img = imread("earthmap_hires.jpg")
class GeodesicLocalizer(Localizer): """ The :py:class:`GeodesicLocalizer` is a type of localizer that is used when observation locations are described in terms of a center latitude/longitude and a line-of-flight direction. This localizer assumes that along-track pixels in the center column of the observaton roughly follow a geodesic path in the direction of flight and cross-track pixels in each row are perpendicular to this path. """ BODY = Geodesic(MARS_RADIUS_M, MARS_FLATTENING) """ A :py:class:`~geographiclib.geodesic.Geodesic` object describing the target body """ def __init__(self, center_row, center_col, center_lat, center_lon, n_rows, n_cols, pixel_height_m, pixel_width_m, north_azimuth_deg, flight_direction=1): """ :param center_row: the center row of the observation :param center_col: the center column of the observation :param center_lat: the latitude (in degrees) of the pixel at the center of the observation :param center_lat: the longitude (east, in degrees) of the pixel at the center of the observation :param n_rows: the total number of rows in the observation :param n_cols: the total number of columns in the observation :param pixel_height_m: the pixel height (in meters) :param pixel_width_m: the pixel width (in meters) :param north_azimuth_deg: the clockwise angle (in degrees) from a vector that points 90 degrees counter-clockwise from the line-of-flight direction to north :param flight_direction: a multiplicative factor indicating the direction of flight relative to the :math:`y`-direction in pixel space; if ``flight_direction=1``, then the flight direction is from the the top down, whereas ``flight_direction=-1`` indicates a bottom-up direction of flight .. Note:: If :py:attr:`~Localizer.NORMALIZED_PIXEL_SPACE` for this localizer is ``True``, then the pixel coordinates range from zero to one. Consequently, the attributes :py:attr:`~GeodesicLocalizer.n_cols` and :py:attr:`~GeodesicLocalizer.n_rows` are both equal to one, and the attributes :py:attr:`~GeodesicLocalizer.pixel_width_m` and :py:attr:`~GeodesicLocalizer.pixel_height_m` are both the width and height of the *entire* observation. """ if n_rows <= 0: raise ValueError('No image rows') if n_cols <= 0: raise ValueError('No image columns') if pixel_height_m <= 0: raise ValueError('Negative pixel height') if pixel_width_m <= 0: raise ValueError('Negative pixel width') self.center_row = center_row self.center_col = center_col self.center_lat = center_lat self.center_lon = center_lon self.n_rows = n_rows self.n_cols = n_cols self.pixel_height_m = pixel_height_m self.pixel_width_m = pixel_width_m self.north_azimuth_deg = north_azimuth_deg self.flight_direction = flight_direction self._height = None self._width = None @property def observation_width_m(self): if self._width is None: self._width = self.pixel_width_m*self.n_cols return self._width @property def observation_length_m(self): if self._height is None: self._height = self.pixel_height_m*self.n_rows return self._height def pixel_to_latlon(self, row, col): x_m = (col - self.center_col) * self.pixel_width_m y_m = (row - self.center_row) * self.pixel_height_m y_m *= self.flight_direction flight_line_point = self.BODY.Direct( self.center_lat, self.center_lon, 90 - self.north_azimuth_deg, y_m ) cross_line_point = self.BODY.Direct( flight_line_point['lat2'], flight_line_point['lon2'], flight_line_point['azi2'] - 90, x_m ) return cross_line_point['lat2'], cross_line_point['lon2'] def location_mask(self, subsample_rows=10, subsample_cols=25, reinterpolate=True, verbose=False): """ Compute a latitude and longitude for every pixel in an observation (with subsampling/reinterpolation to increase efficiency) :param subsample_rows: only compute location once every this many rows :param subsample_cols: only compute location once every this many columns :param reinterpolate: if subsampling is used, reinterpolate values for skipped pixels :param verbose: if ``True``, display a progress bar :return: a :py:class:`numpy.array` containing the latitude and east longitude (in degrees) along the last dimension for every pixel in the image, modulo subsampling .. Warning:: This function is experimental and the reinterpolation step does not correctly handle discontinuities that arise near the "date line" or the poles. """ nrows = int(np.ceil(self.n_rows // subsample_rows)) ncols = int(np.ceil(self.n_cols // subsample_cols)) progress = standard_progress_bar('Computing Location Mask', verbose) L = np.array([ [self.pixel_to_latlon(r, c) for c in np.linspace(0, self.n_cols - 1, ncols)] for r in progress(np.linspace(0, self.n_rows - 1, nrows)) ]) if reinterpolate: zoom_factor = ( float(self.n_rows) / L.shape[0], float(self.n_cols) / L.shape[1] ) L = np.dstack([ zoom(L[..., 0], zoom_factor, order=1, mode='nearest'), zoom(L[..., 1], zoom_factor, order=1, mode='nearest') ]) return L
def add_geo_to_arrivals(arrivals, source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg, radius_of_earth_in_km, flattening_of_earth): """ Add geographical information to arrivals. :param arrivals: Set of taup arrivals :type: :class:`Arrivals` :param source_latitude_in_deg: Source location latitude in degrees :type source_latitude_in_deg: float :param source_longitude_in_deg: Source location longitude in degrees :type source_longitude_in_deg: float :param receiver_latitude_in_deg: Receiver location latitude in degrees :type receiver_latitude_in_deg: float :param receiver_longitude_in_deg: Receiver location longitude in degrees :type receiver_longitude_in_deg: float :param radius_of_earth_in_km: Radius of the Earth in km :type radius_of_earth_in_km: float :param flattening_of_earth: Flattening of Earth (0 for a sphere) :type receiver_longitude_in_deg: float :return: List of ``Arrival`` objects, each of which has the time, corresponding phase name, ray parameter, takeoff angle, etc. as attributes. :rtype: :class:`Arrivals` """ if geodetics.HAS_GEOGRAPHICLIB: ellipsoid = Geodesic(a=radius_of_earth_in_km * 1000.0, f=flattening_of_earth) g = ellipsoid.Inverse(source_latitude_in_deg, source_longitude_in_deg, receiver_latitude_in_deg, receiver_longitude_in_deg) azimuth = g['azi1'] line = ellipsoid.Line(source_latitude_in_deg, source_longitude_in_deg, azimuth) # We may need to update many arrival objects # and each could have pierce points and a # path for arrival in arrivals: if arrival.pierce is not None: geo_pierce = np.empty(arrival.pierce.shape, dtype=TimeDistGeo) for i, pierce_point in enumerate(arrival.pierce): pos = line.ArcPosition(np.degrees(pierce_point['dist'])) geo_pierce[i] = (pierce_point['p'], pierce_point['time'], pierce_point['dist'], pierce_point['depth'], pos['lat2'], pos['lon2']) arrival.pierce = geo_pierce if arrival.path is not None: geo_path = np.empty(arrival.path.shape, dtype=TimeDistGeo) for i, path_point in enumerate(arrival.path): pos = line.ArcPosition(np.degrees(path_point['dist'])) geo_path[i] = (path_point['p'], path_point['time'], path_point['dist'], path_point['depth'], pos['lat2'], pos['lon2']) arrival.path = geo_path else: # geographiclib is not installed ... # and obspy/geodetics does not help much msg = "You need to install the Python module 'geographiclib' in " + \ "order to add geographical information to arrivals." raise ImportError(msg) return arrivals
def run(self): """Run method that performs all the real work""" # show the dialog self.dlg.show() # set default values self.inLayer = self.dlg.mMapLayerComboBox.currentLayer() # set segmenting method self.segmentMethod = '' if self.dlg.spacingRadioButton.isChecked(): self.segmentMethod = 'spacing' else: self.segmentMethod = 'count' def set_in_layer(): """ function to set the input layer from the GUI """ self.inLayer = self.dlg.mMapLayerComboBox.currentLayer() if self.inLayer: if self.inLayer.crs(): self.dlg.messageBox.setText("Input Layer Set: " + str(self.inLayer.name())) else: self.dlg.messageBox.setText( "Error: Input must have projection defined") # listener to set input layer when combo box changes self.dlg.mMapLayerComboBox.layerChanged.connect(set_in_layer) # clear the ellipsoid combobox self.dlg.EllipsoidcomboBox.clear() # this is a dictionary of common ellipsoid parameters # http://www.ga.gov.au/__data/assets/file/0019/11377/Vincentys-formulae-to-calculate-distance-and-bearing-from-latitude-and-longitude.xls ellipsoid_dict = { '165': [6378165.000, 298.3], 'ANS': [6378160, 298.25], 'CLARKE 1858': [6378293.645, 294.26], 'GRS80': [6378137, 298.2572221], 'WGS72': [6378135, 298.26], 'International 1924': [6378388, 297], 'WGS84': [6378137, 298.2572236] } # add items to ellipsoid combobox for k in list(ellipsoid_dict.keys()): self.dlg.EllipsoidcomboBox.addItem(str(k)) # default ellipsoid is WGS84 self.ellipsoid_a = 6378137.0 self.ellipsoid_f = 298.2572236 self.ellipsoid_name = 'WGS84' self.dlg.EllipsoidcomboBox.setCurrentText(self.ellipsoid_name) def set_in_ellipsoid(): """ This function gets the ellipsoid name from the GUI and sets the parameters """ in_ellipsoid_name = self.dlg.EllipsoidcomboBox.currentText() for k in list(ellipsoid_dict.keys()): if k == in_ellipsoid_name: self.ellipsoid_a = ellipsoid_dict[k][0] self.ellipsoid_f = ellipsoid_dict[k][1] self.ellipsoid_name = k self.dlg.messageBox.setText("Ellipsoid set to " + str(k)) # listener to set input ellipsoid when combo box changes self.dlg.EllipsoidcomboBox.currentIndexChanged.connect( set_in_ellipsoid) # default is point spacing with 900m self.spacing = 900 self.dlg.spacingSpinBox.setValue(self.spacing) self.dlg.spacingRadioButton.setChecked(True) # choose segment length def set_in_spacing(): self.spacing = int(self.dlg.spacingSpinBox.value()) self.dlg.messageBox.setText("Point spacing set to " + str(self.spacing) + "m") # listener to set input point spacing when spin box changes self.dlg.spacingSpinBox.valueChanged.connect(set_in_spacing) # default segment number is 10 self.segmentCount = 10 self.dlg.segmentsSpinBox.setValue(self.segmentCount) self.dlg.segmentsRadioButton.setChecked(False) # choose number of segments def set_in_segments(): self.segmentCount = int(self.dlg.segmentsSpinBox.value()) self.dlg.messageBox.setText("Segment count set to " + str(self.segmentCount)) # listener to set input point spacing when spin box changes self.dlg.segmentsSpinBox.valueChanged.connect(set_in_segments) # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: # set the input layer self.inLayer = self.dlg.mMapLayerComboBox.currentLayer() # set segmenting method self.segmentMethod = '' if self.dlg.spacingRadioButton.isChecked(): self.segmentMethod = 'spacing' else: self.segmentMethod = 'count' # get the field list fields = self.inLayer.fields() # handle layers that aren't WGS84 (EPSG:4326) wgs84crs = QgsCoordinateReferenceSystem("EPSG:4326") if self.inLayer.crs() != wgs84crs: transtowgs84 = QgsCoordinateTransform(self.inLayer.crs(), wgs84crs, QgsProject.instance()) transfromwgs84 = QgsCoordinateTransform( wgs84crs, self.inLayer.crs(), QgsProject.instance()) # get input geometry type self.inType = 'Unknown' if self.inLayer.geometryType() == QgsWkbTypes.PointGeometry: self.inType = 'Point' elif self.inLayer.geometryType() == QgsWkbTypes.LineGeometry: self.inType = 'LineString' elif self.inLayer.geometryType() == QgsWkbTypes.PolygonGeometry: self.inType = 'Polygon' else: self.iface.messageBar().pushWarning( "Error", "geometry type not recognized") # setup output layers if self.inType == 'Point': self.create_point = True # create and add to map canvas a point memory layer layer_name = "Densified Point " + str( self.ellipsoid_name) + " " + str(self.spacing) + "m" out_point_layer = self.iface.addVectorLayer( "Point?crs={}".format(self.inLayer.crs().authid()), layer_name, "memory") # set data provider provider = out_point_layer.dataProvider() # add attribute fields provider.addAttributes(fields) self.pointTypeField = '' for fieldName in ["pointType", "pntType", "pntTyp"]: if fieldName not in [field.name() for field in fields]: self.pointTypeField = fieldName provider.addAttributes( [QgsField(self.pointTypeField, QVariant.String)]) out_point_layer.updateFields() else: self.create_point = False if self.inType == 'LineString': self.create_polyline = True # create and add to map canvas a polyline memory layer layer_name = "Densified Line " + str( self.ellipsoid_name) + " " + str(self.spacing) + "m" out_line_layer = self.iface.addVectorLayer( "LineString?crs={}".format(self.inLayer.crs().authid()), layer_name, "memory") # set data provider provider = out_line_layer.dataProvider() # add attribute fields provider.addAttributes(fields) out_line_layer.updateFields() else: self.create_polyline = False if self.inType == 'Polygon': self.create_polygon = True # create and add to map canvas a polyline memory layer layer_name = "Densified Polygon " + str( self.ellipsoid_name) + " " + str(self.spacing) + "m" out_poly_layer = self.iface.addVectorLayer( "Polygon?crs={}".format(self.inLayer.crs().authid()), layer_name, "memory") # set data provider provider = out_poly_layer.dataProvider() # add attribute fields provider.addAttributes(fields) out_poly_layer.updateFields() else: self.create_polygon = False # Create a geographiclib Geodesic object self.geod = Geodesic(self.ellipsoid_a, 1 / self.ellipsoid_f) def densify_point(in_layer, pr): """ This function densifies the input point layer and writes it to the output provider""" # iterator to read input layer iterator = in_layer.getFeatures() # counter to mark first point as "original" counter = 0 # empty feature used to store temporary data current_feature = QgsFeature() # counter to report features that don't work bad_geom = 0 for feature in iterator: if not feature.geometry().isMultipart(): try: if counter == 0: # this is only for the first point pointxy = feature.geometry().asPoint() current_feature.setGeometry( QgsGeometry.fromPointXY(pointxy)) attr = feature.attributes() attr.append("Original") current_feature.setAttributes(attr) pr.addFeatures([current_feature]) else: start_pt = current_feature.geometry().asPoint() end_pt = feature.geometry().asPoint() if self.inLayer.crs() != wgs84crs: start_pt = transtowgs84.transform(start_pt) end_pt = transtowgs84.transform(end_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) # adjust the spacing distance seglen = line_object.s13 / n # create densified points along the line object for i in range(1, n): if i > 0: s = seglen * i g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) geom = QgsPointXY(g['lon2'], g['lat2']) attr = feature.attributes() attr.append("Densified") current_feature.setAttributes(attr) if self.inLayer.crs( ) != wgs84crs: # Convert each point back to the output CRS geom = transfromwgs84.transform( geom) current_feature.setGeometry( QgsGeometry.fromPointXY(geom)) # write the point pr.addFeatures([current_feature]) # write the last point geom = feature.geometry().asPoint() current_feature.setGeometry( QgsGeometry.fromPointXY(geom)) attr = feature.attributes() attr.append("Original") current_feature.setAttributes(attr) pr.addFeatures([current_feature]) counter += 1 except: bad_geom += 1 counter += 1 else: bad_geom += 1 self.iface.messageBar().pushWarning( "error", "multipoint geometries will not be densified") if bad_geom > 0: # report number of features that didn't work self.iface.messageBar().pushWarning( "Error", "{} features failed".format(bad_geom)) def densify_poly(in_layer, pr): bad_geom = 0 iterator = in_layer.getFeatures() # create empty feature to write to for feature in iterator: try: if feature.geometry().wkbType( ) == QgsWkbTypes.LineString: line_geom = feature.geometry().asPolyline() geom_type = "LineString" elif feature.geometry().wkbType( ) == QgsWkbTypes.MultiLineString: multiline_geom = feature.geometry( ).asMultiPolyline() geom_type = "MultiLineString" elif feature.geometry().wkbType( ) == QgsWkbTypes.Polygon: poly_geom = feature.geometry().asPolygon() geom_type = "Polygon" elif feature.geometry().wkbType( ) == QgsWkbTypes.MultiPolygon: multipoly_geom = feature.geometry().asMultiPolygon( ) geom_type = "MultiPolygon" else: bad_geom += 1 except: bad_geom += 1 if geom_type == "LineString": dense_points = [] point_count = len(line_geom) start_pt = QgsPointXY(line_geom[0][0], line_geom[0][1]) dense_points.append(start_pt) if self.inLayer.crs() != wgs84crs: start_pt = transtowgs84.transform(start_pt) for j in range(1, point_count): end_pt = QgsPointXY(line_geom[j][0], line_geom[j][1]) if self.inLayer.crs() != wgs84crs: end_pt = transtowgs84.transform(end_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) if line_object.s13 > self.spacing: seglen = line_object.s13 / n for k in range(1, n): s = seglen * k g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) waypoint = QgsPointXY(g['lon2'], g['lat2']) if self.inLayer.crs() != wgs84crs: waypoint = transfromwgs84.transform( waypoint) dense_points.append(waypoint) if self.inLayer.crs() != wgs84crs: end_pt = transfromwgs84.transform(end_pt) dense_points.append(end_pt) start_pt = end_pt elif geom_type == "MultiLineString": dense_features = [] for i in range(len(multiline_geom)): dense_points = [] line = multiline_geom[i] point_count = len(line) start_pt = QgsPointXY(line[0][0], line[0][1]) dense_points.append(start_pt) for j in range(1, point_count): end_pt = QgsPointXY(line[j][0], line[j][1]) if self.inLayer.crs() != wgs84crs: start_pt = transtowgs84.transform(start_pt) end_pt = transtowgs84.transform(end_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) if line_object.s13 > self.spacing: seglen = line_object.s13 / n for k in range(1, n): s = seglen * k g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) waypoint = QgsPointXY( g['lon2'], g['lat2']) if self.inLayer.crs() != wgs84crs: waypoint = transfromwgs84.transform( waypoint) dense_points.append(waypoint) if self.inLayer.crs() != wgs84crs: end_pt = transfromwgs84.transform( end_pt) dense_points.append(end_pt) start_pt = end_pt dense_features.append(dense_points) elif geom_type == "Polygon": for poly in poly_geom: dense_points = [] point_count = len(poly) start_pt = QgsPointXY(poly[0][0], poly[0][1]) dense_points.append(start_pt) for j in range(1, point_count): end_pt = QgsPointXY(poly[j][0], poly[j][1]) if self.inLayer.crs() != wgs84crs: end_pt = transtowgs84.transform(end_pt) start_pt = transtowgs84.transform(start_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) if line_object.s13 > self.spacing: seglen = line_object.s13 / n for k in range(1, n): s = seglen * k g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) waypoint = QgsPointXY( g['lon2'], g['lat2']) if self.inLayer.crs() != wgs84crs: waypoint = transfromwgs84.transform( waypoint) dense_points.append(waypoint) if self.inLayer.crs() != wgs84crs: end_pt = transfromwgs84.transform( end_pt) dense_points.append(end_pt) start_pt = end_pt if geom_type == "MultiPolygon": dense_features = [] for i in range(len(multipoly_geom)): dense_points = [] poly = multipoly_geom[i][0] point_count = len(poly) start_pt = QgsPointXY(poly[0][0], poly[0][1]) dense_points.append(start_pt) for j in range(1, point_count): end_pt = QgsPointXY(poly[j][0], poly[j][1]) if self.inLayer.crs() != wgs84crs: start_pt = transtowgs84.transform(start_pt) end_pt = transtowgs84.transform(end_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) if line_object.s13 > self.spacing: seglen = line_object.s13 / n for k in range(1, n): s = seglen * k g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) waypoint = QgsPointXY( g['lon2'], g['lat2']) if self.inLayer.crs() != wgs84crs: waypoint = transfromwgs84.transform( waypoint) dense_points.append(waypoint) if self.inLayer.crs() != wgs84crs: end_pt = transfromwgs84.transform( end_pt) dense_points.append(end_pt) start_pt = end_pt dense_features.append(dense_points) new_poly = QgsFeature() if geom_type == "LineString": new_poly.setGeometry( QgsGeometry.fromPolylineXY(dense_points)) elif geom_type == "MultiLineString": new_poly.setGeometry( QgsGeometry.fromMultiPolylineXY(dense_features)) elif geom_type == "Polygon": new_poly.setGeometry( QgsGeometry.fromPolygonXY([dense_points])) elif geom_type == "MultiPolygon": new_poly.setGeometry( QgsGeometry.fromMultiPolygonXY([dense_features])) new_poly.setAttributes(feature.attributes()) pr.addFeatures([new_poly]) if bad_geom > 0: self.iface.messageBar().pushWarning( "", "{} features failed".format(bad_geom)) if self.create_point: densify_point(self.inLayer, provider) out_point_layer.reload() if self.create_polyline: densify_poly(self.inLayer, provider) out_line_layer.reload() if self.create_polygon: densify_poly(self.inLayer, provider) out_poly_layer.reload()