def intersection_over_union(target, list_of_bboxes, xp): print list_of_bboxes.shape target = LinearRing(get_vertex(target)) list_of_bboxes = [LinearRing(get_vertex(i)) for i in list_of_bboxes] areas = xp.zeros(len(list_of_bboxes)) for index, item in enumerate(list_of_bboxes): vertex = [] if target.intersects(item): if isinstance(target.intersection(item),Point): continue for ver in target.intersection(item): if isinstance(ver,LineString): u, v = ver.xy vertex.append([u[0], v[0]]) vertex.append([u[1], v[1]]) else: vertex.append([ver.x, ver.y]) for ver in target.coords[:4]: if Point(ver).within(Polygon(item)): vertex.append(list(ver)) for ver in item.coords[:4]: if Point(ver).within(Polygon(target)): vertex.append(list(ver)) areas[index] = Polygon(PolygonSort(vertex)).area return areas
def test_stitch(self): # The following LinearRing wanders in/out of the map domain # but importantly the "vertical" lines at 0'E and 360'E are both # chopped by the map boundary. This results in their ends being # *very* close to each other and confusion over which occurs # first when navigating around the boundary. # Check that these ends are stitched together to avoid the # boundary ordering ambiguity. # NB. This kind of polygon often occurs with MPL's contouring. coords = [(0.0, -70.70499926182919), (0.0, -71.25), (0.0, -72.5), (0.0, -73.49076371657017), (360.0, -73.49076371657017), (360.0, -72.5), (360.0, -71.25), (360.0, -70.70499926182919), (350, -73), (10, -73)] src_proj = ccrs.PlateCarree() target_proj = ccrs.Stereographic(80) linear_ring = LinearRing(coords) rings, mlinestr = target_proj.project_geometry(linear_ring, src_proj) self.assertEqual(len(mlinestr), 1) self.assertEqual(len(rings), 0) # Check the stitch works in either direction. linear_ring = LinearRing(coords[::-1]) rings, mlinestr = target_proj.project_geometry(linear_ring, src_proj) self.assertEqual(len(mlinestr), 1) self.assertEqual(len(rings), 0)
def test_linearring_from_empty(): ring = LinearRing() assert ring.is_empty assert ring.coords[:] == [] ring = LinearRing([]) assert ring.is_empty assert ring.coords[:] == []
def intersections(a, b): ea = LinearRing(a) eb = LinearRing(b) mp = ea.intersection(eb) x = [p.x for p in mp] y = [p.y for p in mp] return x, y
def test_linearring_from_coordinate_sequence(): expected_coords = [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (0.0, 0.0)] ring = LinearRing(((0.0, 0.0), (0.0, 1.0), (1.0, 1.0))) assert ring.coords[:] == expected_coords ring = LinearRing([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)]) assert ring.coords[:] == expected_coords
def test_linearring_from_short_closed_linestring(self): # Create linearring from linestring where the coordinate sequence is # too short but appears to be closed (first and last coordinates # are the same) coords = [(0.0, 0.0), (0.0, 0.0), (0.0, 0.0)] line = LineString(coords) ring1 = LinearRing(coords) ring2 = LinearRing(line) assert ring1.coords[:] == ring2.coords[:]
def test_linearring_from_empty(): ring = LinearRing() assert ring.is_empty assert isinstance(ring.coords, CoordinateSequence) assert ring.coords[:] == [] ring = LinearRing([]) assert ring.is_empty assert isinstance(ring.coords, CoordinateSequence) assert ring.coords[:] == []
def ellipse_intersect(a, b, ret_points=False): ea = LinearRing(a) eb = LinearRing(b) mp = ea.intersection(eb) if ret_points: x = [p.x for p in mp] y = [p.y for p in mp] return x, y return bool(mp)
def test_linearring(self): # Initialization # Linear rings won't usually be created by users, but by polygons coords = ((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)) ring = LinearRing(coords) self.assertEqual(len(ring.coords), 5) self.assertEqual(ring.coords[0], ring.coords[4]) self.assertEqual(ring.coords[0], ring.coords[-1]) self.assertTrue(ring.is_ring) # Ring from sequence of Points self.assertEqual(LinearRing((map(Point, coords))), ring)
def highres_Orthographic(projection, r=R_Mars_km * 1e3): """ Increases the resolution of the circular outline in cartopy.crs.Orthographic projection. Parameters ---------- projection : obj A cartopy.crs.Orthographic() projection. r : float The radius of the globe in meters (e.g., for Mars this is the radius of Mars in meters). Returns ------- None. Changes the resolution of an existing projection. """ # re-implement the cartopy code to figure out the new boundary shape a = np.float(projection.globe.semimajor_axis or r) b = np.float(projection.globe.semiminor_axis or a) t = np.linspace(0, 2 * np.pi, 3601) coords = np.vstack([a * 0.99999 * np.cos(t), b * 0.99999 * np.sin(t)])[:, ::-1] # update the projection boundary projection._boundary = LinearRing(coords.T)
def _get_geometry(self, element): # Point, LineString, # Polygon, LinearRing if element.tag == ('%sPoint' % self.ns): coords = self._get_coordinates(element) self._get_geometry_spec(element) return Point(coords[0]) if element.tag == ('%sLineString' % self.ns): coords = self._get_coordinates(element) self._get_geometry_spec(element) return LineString(coords) if element.tag == ('%sPolygon' % self.ns): self._get_geometry_spec(element) outer_boundary = element.find('%souterBoundaryIs' % self.ns) ob = self._get_linear_ring(outer_boundary) inner_boundaries = element.findall('%sinnerBoundaryIs' % self.ns) ibs = [ self._get_linear_ring(inner_boundary) for inner_boundary in inner_boundaries ] return Polygon(ob, ibs) if element.tag == ('%sLinearRing' % self.ns): coords = self._get_coordinates(element) self._get_geometry_spec(element) return LinearRing(coords)
def get_intersecting_list_service_for_polygon(location: geodetic_polygon, boundary_table, engine, return_intersection_area=False, proximity_search = False, proximity_buffer = 0 ): """ Executes an intersection query for a polygon. :param location: location object :type location: :py:class:Geodetic2D :param boundary_table: The name of the service boundary table. :type boundary_table: `str` :param engine: SQLAlchemy database engine. :type engine: :py:class:`sqlalchemy.engine.Engine` :param return_intersection_area: Flag which triggers an area calculation on the Intersecting polygons. :type return_intersection_area: `bool` :return: A list of dictionaries containing the contents of returned rows. """ # Pull out just the number from the SRID trimmed_srid = int(location.spatial_ref.split('::')[1]) p = [] points = location.vertices for point in points: long, lat = gc_geom.reproject_point(point[0], point[1], trimmed_srid, 4326) p.append([long, lat]) ring = LinearRing(p) wkb_ring = location.to_wkbelement(project_to=trimmed_srid) return (_get_intersecting_list_service_for_geom(engine, i, wkb_ring, return_intersection_area) for i in boundary_table)
def highres_NearsidePerspective(projection, altitude, r=R_Mars_km * 1e3): """ Increases the resolution of the circular outline in cartopy.crs.NearsidePerspective projection. Parameters ---------- projection : obj A cartopy.crs.NearsidePerspective() projection. altitude : int, float Apoapse altitude in meters. r : float The radius of the globe in meters (e.g., for Mars this is the radius of Mars in meters). Returns ------- None. Changes the resolution of an existing projection. """ # re-implement the cartopy code to figure out the new boundary shape a = np.float(projection.globe.semimajor_axis or r) h = np.float(altitude) max_x = a * np.sqrt(h / (2 * a + h)) t = np.linspace(0, 2 * np.pi, 3601) coords = np.vstack([max_x * np.cos(t), max_x * np.sin(t)])[:, ::-1] # update the projection boundary projection._boundary = LinearRing(coords.T)
def test_linearring_from_numpy(): # Construct from a numpy array np = pytest.importorskip("numpy") coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)] ring = LinearRing(np.array(coords)) assert ring.coords[:] == [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]
def get_intersecting_boundaries_for_polygon(location: geodetic_polygon, boundary_table, engine, return_intersection_area=False, proximity_search = False, proximity_buffer = 0 ): """ Executes an intersection query for a polygon. :param location: location object :type location: :py:class:Geodetic2D :param boundary_table: The name of the service boundary table. :type boundary_table: `str` :param engine: SQLAlchemy database engine. :type engine: :py:class:`sqlalchemy.engine.Engine` :param return_intersection_area: Flag which triggers an area calculation on the Intersecting polygons. :type return_intersection_area: `bool` :return: A list of dictionaries containing the contents of returned rows. """ # Pull out just the number from the SRID trimmed_srid = int(location.spatial_ref.split('::')[1]) points = location.vertices ring = LinearRing(points) shapely_polygon = Polygon(ring) # load up a new Shapely Polygon from the WKT and convert it to a GeoAlchemy2 WKBElement # that we can use to query. poly = loads(shapely_polygon.wkt) wkb_poly = location.to_wkbelement(project_to=trimmed_srid) if proximity_search == True: return get_intersecting_boundaries_with_buffer(points[0][0], points[0][1], engine, boundary_table, wkb_poly, proximity_buffer, return_intersection_area) else: return _get_intersecting_boundaries_for_geom(engine, boundary_table, wkb_poly, return_intersection_area)
def is_ccw(self, region): coords = self.get_region_coords(region) ring = LinearRing(coords) if ring.is_ccw: return True else: return False
def to_poly(self): """Convert to a polygon. Returns: (shapely.geometry.polygon.LinearRing): Outline of the hexagon. """ centre = self.to_geographic() # the corners of a hexagon are at 60 degree increments. Start halfway # through an increment because we have flat topped ones DEG_TO_RAD = math.pi / 180 angles = [ 30 * DEG_TO_RAD, 90 * DEG_TO_RAD, 150 * DEG_TO_RAD, 210 * DEG_TO_RAD, 270 * DEG_TO_RAD, 330 * DEG_TO_RAD ] return LinearRing( [ ( centre[0] + self.D * math.sin(t), centre[1] + self.D * math.cos(t) ) for t in angles ] )
def test_linearring_from_too_short_linestring(self): # Creation of LinearRing request at least 3 coordinates (unclosed) or # 4 coordinates (closed) coords = [(0.0, 0.0), (0.0, 0.0)] line = LineString(coords) with self.assertRaises(ValueError): LinearRing(line)
def intersections(self, a, b): """check if two polylines are intersected Args: a (polyline): polyline a b (polyline): polyline b Returns: boolean: true if polylines are intersected """ try: ea = LinearRing(a) eb = LinearRing(b) return ea.intersection(eb) except: return False
def test_polygon_from_linearring(): coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)] ring = LinearRing(coords) polygon = Polygon(ring) assert polygon.exterior.coords[:] == coords assert len(polygon.interiors) == 0
def TMApoly(Fwaypt = None, fname_STA = None): MeterPntList = [] if Fwaypt != None: with open(Fwaypt,'r') as csvfile: line = csv.reader(csvfile) for field in line: MeterPntList.append([float(field[1]),float(field[0])]) # else: # All_Meter_Name = np.array([]) # for name in fname_STA: # a = np.genfromtxt(os.getcwd()+'\STA_DATA\\'+name, usecols = (6,7,8),dtype=[('RWY','S10'),('FAF','S10'),('MFX','S10')],delimiter=",") # All_Meter_Name = np.append(All_Meter_Name,a['MFX']) # All_Meter_Name = np.unique(All_Meter_Name) # with open('WayPoint1.csv','wb') as wcsvfile: # wri = csv.writer(wcsvfile) # for MFX in All_Meter_Name: # Coords = FixCoords(MFX) # if len(Coords) != 0: # MeterPntList.append(Coords) # wri.writerow(Coords+[MFX]) # else: # pass mlat = sum(x[0] for x in MeterPntList) / len(MeterPntList) mlng = sum(x[1] for x in MeterPntList) / len(MeterPntList) def algo(x): return (math.atan2(x[0] - mlat, x[1] - mlng) + 2 * math.pi) % (2*math.pi) MeterPntList.sort(key=algo) TMA_Ring = LinearRing(MeterPntList) TMA_Poly = Polygon(MeterPntList) return TMA_Poly, TMA_Ring, MeterPntList
def _xywh_to_ring(self, x, y, width, height): points = [(x - (width / 2.0), y - (height / 2.0)), (x - (width / 2.0), y + (height / 2.0)), (x + (width / 2.0), y + (height / 2.0)), (x + (width / 2.0), y - (height / 2.0)), (x - (width / 2.0), y - (height / 2.0))] return Polygon(LinearRing(points))
def generate_offset_track(self, mid_track, thickness): poly_line = LinearRing(mid_track) poly_line_offset_left = poly_line.parallel_offset(thickness, side="left", resolution=16, join_style=2, mitre_limit=2) poly_line_offset_right = poly_line.parallel_offset(thickness, side="right", resolution=16, join_style=2, mitre_limit=2) offset_left_track = [] for coord in poly_line_offset_left.coords: p = [coord[0], coord[1]] offset_left_track.append(p) offset_left_track.append(offset_left_track[0]) offset_right_track = [] for coord in poly_line_offset_right.coords: p = [coord[0], coord[1]] offset_right_track.append(p) offset_right_track.append(offset_right_track[0]) return offset_left_track, offset_right_track
def add_box(ax, x0, x1, y0, y1, **kwargs): """ Add a polygon/box to any cartopy projection. Parameters ---------- ax : axes instance (should be from make_cartopy command) x0: float; western longitude bound of box. x1: float; eastern longitude bound of box. y0: float; southern latitude bound of box. y1: float; northern latitude bound of box. **kwargs: optional keywords Will modify the color, etc. of the bounding box. Returns ------- None Examples -------- import esm_analysis as et fig, ax = et.vis.make_cartopy() et.visualization.add_box(ax, [-150, -110, 30, 50], edgecolor='k', facecolor='#D3D3D3', linewidth=2, alpha=0.5) """ lons = [x0, x0, x1, x1] lats = [y0, y1, y1, y0] ring = LinearRing(list(zip(lons, lats))) ax.add_geometries([ring], ccrs.PlateCarree(), **kwargs)
def _get_geometry(self, element): # Point, LineString, # Polygon, LinearRing if element.tag == ('%sPoint' % self.ns): coords = self._get_coordinates(element) self._get_geometry_spec(element) return Point(coords[0]) if element.tag == ('%sLineString' % self.ns): coords = self._get_coordinates(element) # issue seen with Garmin kml feeds with one coordinate linestrings if len(coords) < 2: logger.warn('LineStrings must have at least 2 coordinate tuples') return self._get_geometry_spec(element) return LineString(coords) if element.tag == ('%sPolygon' % self.ns): self._get_geometry_spec(element) outer_boundary = element.find('%souterBoundaryIs' % self.ns) ob = self._get_linear_ring(outer_boundary) inner_boundaries = element.findall('%sinnerBoundaryIs' % self.ns) ibs = [] for inner_boundary in inner_boundaries: ibs.append(self._get_linear_ring(inner_boundary)) return Polygon(ob, ibs) if element.tag == ('%sLinearRing' % self.ns): coords = self._get_coordinates(element) self._get_geometry_spec(element) return LinearRing(coords)
def test_linearring_from_too_short_linestring(): # Creation of LinearRing request at least 3 coordinates (unclosed) or # 4 coordinates (closed) coords = [(0.0, 0.0), (1.0, 1.0)] line = LineString(coords) with pytest.raises(ValueError, match="at least 3 coordinate tuple"): LinearRing(line)
def test_cuts(self): # Check that fragments do not start or end with one of the # original ... ? linear_ring = LinearRing([(-10, 30), (10, 60), (10, 50)]) projection = ccrs.Robinson(170.5) rings, multi_line_string = projection.project_geometry(linear_ring) # The original ring should have been split into multiple pieces. self.assertGreater(len(multi_line_string), 1) self.assertFalse(rings) def assert_intersection_with_boundary(segment_coords): # Double the length of the segment. start = segment_coords[0] end = segment_coords[1] end = [end[i] + 2 * (end[i] - start[i]) for i in (0, 1)] extended_segment = sgeom.LineString([start, end]) # And see if it crosses the boundary. intersection = extended_segment.intersection(projection.boundary) self.assertFalse(intersection.is_empty, 'Bad topology near boundary') # Each line resulting from the split should start and end with a # segment that crosses the boundary when extended to double length. # (This is important when considering polygon rings which need to be # attached to the boundary.) for line_string in multi_line_string: coords = list(line_string.coords) self.assertGreaterEqual(len(coords), 2) assert_intersection_with_boundary(coords[1::-1]) assert_intersection_with_boundary(coords[-2:])
def test_out_of_bounds(self): # Check that a ring that is completely out of the map boundary # produces an empty result. # XXX Check efficiency? projection = ccrs.TransverseMercator(central_longitude=0) rings = [ # All valid ([(86, 1), (86, -1), (88, -1), (88, 1)], -1), # One NaN ([(86, 1), (86, -1), (130, -1), (88, 1)], 1), # A NaN segment ([(86, 1), (86, -1), (130, -1), (130, 1)], 1), # All NaN ([(120, 1), (120, -1), (130, -1), (130, 1)], 0), ] # Try all four combinations of valid/NaN vs valid/NaN. for coords, expected_n_lines in rings: linear_ring = LinearRing(coords) rings, mlinestr = projection.project_geometry(linear_ring) if expected_n_lines == -1: self.assertTrue(rings) self.assertFalse(mlinestr) else: self.assertEqual(len(mlinestr), expected_n_lines) if expected_n_lines == 0: self.assertTrue(mlinestr.is_empty)
def get_ring(coords): '''tuple in format: west_lon, east_lon, south_lat, north_lat ''' west_lon, east_lon, south_lat, north_lat = coords lons_sq = [west_lon, west_lon, east_lon, east_lon] lats_sq = [north_lat, south_lat, south_lat, north_lat] ring = [LinearRing(list(zip(lons_sq, lats_sq)))] return ring
def test_linearring_from_unclosed_linestring(): coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)] line = LineString(coords[:-1]) # Pass in unclosed line ring = LinearRing(line) assert len(ring.coords) == 4 assert ring.coords[:] == coords assert ring.geom_type == 'LinearRing'