Exemple #1
0
def get_additional_data_for_ellipse(location: geodetic_ellipse, buffer_distance, boundary_table, engine):
    """
    Executes a contains query for a ellipse.

    :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`
    :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])
    long, lat = gc_geom.reproject_point(location.longitude, location.latitude, trimmed_srid, 4326)
    utmsrid = gc_geom.getutmsrid(long, lat)

    wkb_ellipse = location.to_wkbelement(project_to=4326)
    results = _get_additional_data_for_geometry(engine, wkb_ellipse, boundary_table)
    if results is None:
        results = _get_additional_data_for_geometry_with_buffer(engine, wkb_ellipse, boundary_table,
                                                                buffer_distance, utmsrid)

    return results
Exemple #2
0
    def build_shapely_geometry(self) -> BaseGeometry:
        """
        Builds the internal shapely representation of the geometry.  This is used by other base class methods
        to build the other output types.

        :return: A shapely geometry specific to the derived type.
        :rtype: :py:class:`BaseGeometry`
        """
        # Get the UTMSRID so we can transform the center point to a coordinate system where distance is
        # measured in meters.
        utmsrid: int = getutmsrid(self.longitude, self.latitude, self.sr_id)
        # Create the OGR Point
        center: ogr.Geometry = ogr.Geometry(ogr.wkbPoint)
        center.AssignSpatialReference(Geodetic2D.get_ogr_sr(self.sr_id))
        center.AddPoint(self.longitude, self.latitude)
        # Project the point from its native projection to the UTM system.
        center = reproject_geom(center, self.sr_id, utmsrid)

        # adjust for the fact that we're not doing standard geometry - back up 90 degress
        # to start from north.
        start_angle: float = 90 - self.start_angle
        # find the end angle, which is the sweep relative to the start angle going clockwise so we subtract.
        end_angle: float = start_angle - self.opening_angle

        # plot a line for the outer arc.
        outer_arc_x, outer_arc_y = \
            calculate_arc(center.GetX(), center.GetY(), self.outer_radius, start_angle, end_angle)

        # plot a line for the inner arc.
        inner_arc_x, inner_arc_y = \
            calculate_arc(center.GetX(), center.GetY(), self.inner_radius, start_angle, end_angle)

        # reverse the inner arc to set is up to be welded to the outer arc into a polygon.
        inner_arc_x = np.flip(inner_arc_x, 0)
        inner_arc_y = np.flip(inner_arc_y, 0)

        # glue the arcs together
        band_x = np.append(outer_arc_x, inner_arc_x)
        band_y = np.append(outer_arc_y, inner_arc_y)

        # complete the ring by adding taking the first point and adding it again at the end.
        first_x = band_x[0]
        first_y = band_y[0]
        band_x = np.append(band_x, first_x)
        band_y = np.append(band_y, first_y)

        # smash the x and y arrays together to get coordinate pairs.
        ring_coordinates = np.column_stack([band_x, band_y])

        # Build the shapely linear ring . . .
        line_string: shp_geom.LinearRing = shp_geom.LinearRing(ring_coordinates)
        # so we can build a shapely polygon . . .
        arc_band_polygon: shp_geom.Polygon = shp_geom.Polygon(line_string)
        # so we can create the OGR geometry . . .
        arcband: ogr.Geometry = ogr.CreateGeometryFromWkb(arc_band_polygon.wkb)
        # so we can reproject back to the original coordinate system
        arcband = reproject_geom(arcband, utmsrid, self._spatial_ref_id)
        # so we can build and return a shapely geometry.  (Whew!)
        return loads(arcband.ExportToWkt())
Exemple #3
0
    def test_getutmsrid(self):
        """
        Convert Long/Lat to UTM Zone WGS_1984_UTM_Zone_19N 32619
        :return: 
        """

        longitude = -68.84724495254032
        latitude = 46.899295967195435

        result = getutmsrid(longitude, latitude)

        self.assertEqual(result, 32619)
Exemple #4
0
def _transform_circle(long, lat, srid, radius, uom):
    """
    Takes the fundamental bits of a circle and converts it to a descritized circle (polygon)
    transformed to 4326.

    :param long: The x coordinate of the center.
    :type long: `float`
    :param lat: The lat coordinate of the center.
    :type lat: `float`
    :param srid: The spatial reference id of the center point.
    :type srid: `str`
    :param radius: The radius of the circle.
    :type radius: `float`
    :param uom: The unit of measure of the radius.
    :type uom: `str`
    :return: A WKBElement representation of the circle.
    :rtype: :py:class:geoalchemy2.types.WKBElement
    """

    # Source spatial reference.
    source = osr.SpatialReference()
    source.ImportFromEPSG(srid)

    # TODO - Need to handle different values for the incoming UOM
    # TODO - Must have a lookup table of some kind.
    # The target will depend on the value of uom, but we'll just assume
    # it's 9001/meters for now and project to 3857.
    target = osr.SpatialReference()
    #target.ImportFromEPSG(3857)
    target.ImportFromEPSG(gc_geom.getutmsrid(longitude=long, latitude=lat))

    # Set up the transform.
    transform = osr.CoordinateTransformation(source, target)

    # Create a geometry we can use with the transform.
    center = ogr.CreateGeometryFromWkt('POINT({0} {1})'.format(long, lat))

    # Transform it and apply the buffer.
    center.Transform(transform)
    circle = center.Buffer(radius)

    # Now transform it back and extract the wkt
    reverse_transform = osr.CoordinateTransformation(target, source)
    circle.Transform(reverse_transform)
    wkt_circle = circle.ExportToWkt()

    # load up a new Shapely Polygon from the WKT and convert it to a GeoAlchemy2 WKBElement
    # that we can use to query.
    poly = loads(wkt_circle)
    wkb_circle = from_shape(poly, srid)

    return wkb_circle
Exemple #5
0
    def build_shapely_geometry(self) -> BaseGeometry:
        """
        Builds the internal shapely representation of the geometry.  This is used by other base class methods
        to build the other output types.

        :return: A shapely geometry specific to the derived type.
        :rtype: :py:class:`BaseGeometry`
        """
        # Get the UTMSRID so we can transform the center point to a coordinate system where distance is
        # measured in meters.
        utmsrid: int = getutmsrid(self.longitude, self.latitude, self.sr_id)
        # Create the OGR Point
        center: ogr.Geometry = ogr.Geometry(ogr.wkbPoint)
        center.AssignSpatialReference(Geodetic2D.get_ogr_sr(self.sr_id))
        center.AddPoint(self.longitude, self.latitude)
        # Project the point from its native projection to the UTM system.
        center = reproject_geom(center, self.sr_id, utmsrid)
        # Buffer the point with the radius to get a polygon of the circle.
        circle: ogr.Geometry = center.Buffer(1)

        # Create the shapely object so we can do the ellipse magic.
        proto_ellipse: BaseGeometry = loads(circle.ExportToWkt())
        # stretch the ellipse along the major and minor axes
        scaled_ellipse: BaseGeometry = affinity.scale(proto_ellipse, self.majorAxis, self.minorAxis)

        rotate_angle = calculate_orientation(self.orientation)

        rotated_ellipse: BaseGeometry = None
        if rotate_angle >= 0:
            # Let rotate the ellipse (clockwise, x axis pointing right):
            rotated_ellipse = affinity.rotate(scaled_ellipse, rotate_angle, use_radians=True)
        else:
            # If one need to rotate it clockwise along an upward pointing x axis:
            rotated_ellipse = affinity.rotate(scaled_ellipse, 90 - rotate_angle, use_radians=True)
            # According to the man, a positive value means a anti-clockwise angle,
            # and a negative one a clockwise angle.

        # Now build an OGR geometry so we can reproject.
        ogr_ellipse: ogr.Geometry = ogr.CreateGeometryFromWkt(rotated_ellipse.wkt)
        ogr_ellipse.AssignSpatialReference(Geodetic2D.get_ogr_sr(utmsrid))
        ogr_ellipse = reproject_geom(ogr_ellipse, utmsrid, self.sr_id)

        return loads(ogr_ellipse.ExportToWkt())
Exemple #6
0
def get_intersecting_boundaries_with_buffer(long, lat, engine, table_name, geom, buffer_distance, return_intersection_area = False):
    retval = None
    try:
        # Get a reference to the table we're going to look in.
        tbl_metadata = MetaData(bind=engine)
        the_table = Table(table_name, tbl_metadata, autoload=True)

        # Construct the "contains" query and execute it.
        utmsrid = gc_geom.getutmsrid(long, lat, geom.srid)


        if return_intersection_area:
        # include a calculation for the intersecting the area

            s = select([the_table, the_table.c.wkb_geometry.ST_AsGML(), func.ST_Area(
            func.ST_Intersection(
                func.ST_Buffer(func.ST_Transform(func.ST_SetSRID(geom, geom.srid), utmsrid), buffer_distance), the_table.c.wkb_geometry.ST_Transform(utmsrid))).label(
            'AREA_RET')],
                   func.ST_Intersects(
                       func.ST_Buffer(func.ST_Transform(func.ST_SetSRID(geom, geom.srid), utmsrid), buffer_distance),
                       the_table.c.wkb_geometry.ST_Transform(utmsrid)))


        else:

            s = select([the_table, the_table.c.wkb_geometry.ST_AsGML()],
                   func.ST_Intersects(func.ST_Buffer(func.ST_Transform(func.ST_SetSRID(geom,4326), utmsrid), buffer_distance),
                                      the_table.c.wkb_geometry.ST_Transform(utmsrid)))



        retval = _execute_query(engine, s)

    except SQLAlchemyError as ex:
        logger.error(ex)
        raise SpatialQueryException(
            'Unable to construct contains query.', ex)
    except SpatialQueryException as ex:
        logger.error(ex)
        raise

    return retval
Exemple #7
0
def _get_nearest_point(long, lat, engine, table_name, geom, buffer_distance=None):
    """
    Queries the given table for the nearest boundary

    :param engine: SQLAlchemy database engine
    :type engine: :py:class:`sqlalchemy.engine.Engine`
    :param table_name: The name of the service boundary table.
    :type table_name: `str`
    :param geom: The geometry to use in the search as a GeoAlchemy WKBElement.
    :type geom: :py:class:geoalchemy2.types.WKBElement
    :return: A list of dictionaries containing the contents of returned rows.
    """
    retval = None
    try:
        # Get a reference to the table we're going to look in.
        tbl_metadata = MetaData(bind=engine)
        the_table = Table(table_name, tbl_metadata, autoload=True)
        # Construct the "contains" query and execute it.
        utmsrid = gc_geom.getutmsrid(long, lat)
        s = select([the_table, the_table.c.wkb_geometry.ST_AsGML(),
                    the_table.c.wkb_geometry.ST_Distance(geom).label('DISTANCE')],
                   the_table.c.wkb_geometry.ST_Intersects(
                       func.ST_Transform(
                           func.ST_Buffer(
                           func.ST_Transform(
                               func.st_centroid(geom),
                               utmsrid
                           ),buffer_distance, 32), 4326))
                   ).order_by('DISTANCE').limit(1)

        retval = _execute_query(engine, s)
    except SQLAlchemyError as ex:
        logger.error(ex)
        raise SpatialQueryException(
            'Unable to construct contains query.', ex)
    except SpatialQueryException as ex:
        logger.error(ex)
        raise
    return retval
Exemple #8
0
    def build_shapely_geometry(self) -> BaseGeometry:
        """
        Builds the internal shapely representation of the geometry.  This is used by other base class methods
        to build the other output types.

        :return: A shapely geometry specific to the derived type.
        :rtype: :py:class:`BaseGeometry`
        """
        # Get the UTMSRID so we can transform the center point to a coordinate system where distance is
        # measured in meters.
        utmsrid: int = getutmsrid(self.longitude, self.latitude, self.sr_id)
        # Create the OGR Point
        center: ogr.Geometry = ogr.Geometry(ogr.wkbPoint)
        center.AddPoint(self.longitude, self.latitude)
        # Project the point from its native projection to the UTM system.
        center = reproject_geom(center, self.sr_id, utmsrid)
        # Buffer the point with the radius to get a polygon of the circle.
        circle: ogr.Geometry = center.Buffer(self.radius)
        # Project the circle back to the original system.
        circle = reproject_geom(circle, utmsrid, self.sr_id)
        # Return a shapely object constructed from the WKT of the OGR polygon
        return loads(circle.ExportToWkt())
Exemple #9
0
def get_additionaldata_for_polygon(location: geodetic_polygon, boundary_table, engine, buffer_distance):
    """

    Executes an addtional data 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])
    utmsrid = gc_geom.getutmsrid(p[0][0], p[0][1])
    ring = LinearRing(p)

    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)
    results = _get_additional_data_for_geometry(engine, wkb_poly, boundary_table)
    if results is None:
        results = _get_additional_data_for_geometry_with_buffer(engine, wkb_poly, boundary_table,
                                                                buffer_distance, utmsrid)
    return results
Exemple #10
0
def _transform_ellipse(long ,lat , major, minor, orientation, srid):
    """
    Takes the fundamental bits of a ellipse and converts it to a descritized ellipse (polygon)
    transformed to 4326.
    :param long: 
    :param lat: 
    :param major: 
    :param minor: 
    :param orientation: 
    :param srid: 
    :return: 
    """

    # Source spatial reference.
    source = osr.SpatialReference()
    source.ImportFromEPSG(srid)

    # TODO - Need to handle different values for the incoming UOM
    # TODO - Must have a lookup table of some kind.
    # The target will depend on the value of uom, but we'll just assume
    # it's 9001/meters for now.
    target = osr.SpatialReference()
    # target.ImportFromEPSG(3857)
    target.ImportFromEPSG(gc_geom.getutmsrid(long, lat, srid))

    # Set up the transform.
    transform = osr.CoordinateTransformation(source, target)

    # Create a geometry we can use with the transform.
    center = ogr.CreateGeometryFromWkt('POINT({0} {1})'.format(long, lat))

    # Transform it and apply the buffer.
    center.Transform(transform)
    cir = center.Buffer(1)

    wkt_cir = cir.ExportToWkt()

    # load up a new Shapely Polygon from the WKT and convert it to a GeoAlchemy2 WKBElement
    # that we can use to query.
    circle = loads(wkt_cir)

    # Let create the ellipse along x and y:
    ell = affinity.scale(circle,
                            major,
                            minor)

    # xml.py parse method has already converted GML degree's to radians
    rotate_angle = calculate_orientation(orientation)


    if rotate_angle >= 0:
        # Let rotate the ellipse (clockwise, x axis pointing right):
        ellr = affinity.rotate(ell, rotate_angle, use_radians=True)
    else:
        # If one need to rotate it clockwise along an upward pointing x axis:
        ellr = affinity.rotate(ell, 90 - rotate_angle, use_radians=True)
        # According to the man, a positive value means a anti-clockwise angle,
        # and a negative one a clockwise angle.

    # Convert from shapely to org
    org_ellipse = ogr.CreateGeometryFromWkt(ellr.wkt)

    # Now transform it back to 4326 and extract the wkt
    reverse_transform = osr.CoordinateTransformation(target, source)
    org_ellipse.Transform(reverse_transform)
    wkt_ellipse = org_ellipse.ExportToWkt()

    # load up a new Shapely Polygon from the WKT and convert it to a GeoAlchemy2 WKBElement
    # that we can use to query.
    poly = loads(wkt_ellipse)
    wkb_ellipse = from_shape(poly, srid)

    return wkb_ellipse