Example #1
0
def test_length_geom_linestring_missing_epsg_from_global_settings(session):
    if session.bind.name == "postgresql":
        pytest.skip(
            "Postgres already has a constrain that checks on the length")
    factories.ChannelFactory(the_geom="SRID=4326;LINESTRING("
                             "-0.38222938832999598 -0.13872236685816669, "
                             "-0.38222930900909202 -0.13872236685816669)", )
    factories.ChannelFactory(the_geom="SRID=4326;LINESTRING("
                             "-0.38222938468305784 -0.13872235682908687, "
                             "-0.38222931083256106 -0.13872235591735235, "
                             "-0.38222930992082654 -0.13872207236791409, "
                             "-0.38222940929989008 -0.13872235591735235)", )

    q = Query(models.Channel).filter(
        geo_func.ST_Length(
            geo_func.ST_Transform(
                models.Channel.the_geom,
                Query(models.GlobalSetting.epsg_code).limit(1))) < 0.05)
    check_length_linestring = QueryCheck(
        column=models.Channel.the_geom,
        invalid=q,
        message=
        "Length of the v2_channel is too short, should be at least 0.05m",
    )

    errors = check_length_linestring.get_invalid(session)
    assert len(errors) == 0
Example #2
0
def test_length_geom_linestring_in_28992(session):
    if session.bind.name == "postgresql":
        pytest.skip(
            "Postgres already has a constrain that checks on the length")
    # around 0.109m
    factories.ChannelFactory(
        the_geom="SRID=4326;LINESTRING("
        "122829.98048471771471668 473589.68720115750329569, "
        "122830.00490918199648149 473589.68720115750329569, "
        "122829.95687440223991871 473589.70983449439518154, "
        "122829.9793449093849631 473589.68850379559444264)")
    # around 0.001m
    channel_too_short = factories.ChannelFactory(
        the_geom="SRID=4326;LINESTRING("
        "122829.98185859377554152 473589.69248294795397669, "
        "122829.98260150455462281 473589.69248294795397669)", )

    check_length_linestring = QueryCheck(
        column=models.Channel.the_geom,
        invalid=Query(models.Channel).filter(
            geo_func.ST_Length(models.Channel.the_geom) < 0.05),
        message=
        "Length of the v2_channel is too short, should be at least 0.05m",
    )

    errors = check_length_linestring.get_invalid(session)
    assert len(errors) == 1
    assert errors[0].id == channel_too_short.id
Example #3
0
def elevation(conn: directive.connection,
              tables: directive.tables,
              dem: directive.dem_file,
              oid: hug.types.number,
              segments: hug.types.in_range(1, 500) = 100):
    "Return the elevation profile of the route."

    if dem is None:
        raise hug.HTTPNotFound()

    r = tables.routes.data

    sel = sa.select([gf.ST_Points(gf.ST_Collect(
                         gf.ST_PointN(r.c.geom, 1),
                         gf.ST_LineInterpolatePoints(r.c.geom, 1.0/segments))),
                     sa.func.ST_Length2dSpheroid(gf.ST_Transform(r.c.geom, 4326),
                           'SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]]')
                    ]).where(r.c.id == oid)\
            .where(r.c.geom.ST_GeometryType() == 'ST_LineString')

    res = conn.execute(sel).first()

    if res is not None:
        geom = to_shape(res[0])
        ele = RouteElevation(oid, dem, geom.bounds)

        xcoord, ycoord = zip(*((p.x, p.y) for p in geom))
        geomlen = res[1]
        pos = [geomlen * i / float(segments) for i in range(segments + 1)]

        ele.add_segment(xcoord, ycoord, pos)

        return ele.as_dict()

    # special treatment for multilinestrings
    sel = sa.select([r.c.geom,
                     sa.literal_column("""ST_Length2dSpheroid(ST_MakeLine(ARRAY[ST_Points(ST_Transform(geom,4326))]),
                             'SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY["EPSG",\"7030\"]]')"""),
                     r.c.geom.ST_NPoints(),
                     gf.ST_Length(r.c.geom)])\
                .where(r.c.id == oid)

    res = conn.execute(sel).first()

    if res is None or res[0] is None:
        raise hug.HTTPNotFound()

    geom = to_shape(res[0])
    # Computing length in Mercator is slightly off, correct it via the
    # actual length.
    dist_fac = res[1] / res[3]
    ele = RouteElevation(oid, dem, geom.bounds)

    if res[2] > 10000:
        geom = geom.simplify(res[2] / 500, preserve_topology=False)
    elif res[2] > 4000:
        geom = geom.simplify(res[2] / 1000, preserve_topology=False)

    prev = None
    for seg in geom:
        p = seg.coords[0]
        xcoords = array('d', [p[0]])
        ycoords = array('d', [p[1]])
        pos = array('d')
        if prev is not None:
            pos.append(prev[2][-1] + \
                    Point(prev[0][-1], prev[1][-1]).distance(Point(*p)) * dist_fac)
        else:
            pos.append(0.0)
        for p in seg.coords[1:]:
            pos.append(pos[-1] +
                       Point(xcoords[-1], ycoords[-1]).distance(Point(*p)) *
                       dist_fac)
            xcoords.append(p[0])
            ycoords.append(p[1])

        ele.add_segment(xcoords, ycoords, pos)
        prev = (xcoords, ycoords, pos)

    return ele.as_dict()
Example #4
0
def length(col):
    return geo_func.ST_Length(transform(col))
def elevation(conn: directive.connection,
              tables: directive.tables,
              dem: directive.dem_file,
              oid: hug.types.number,
              segments: hug.types.in_range(1, 500) = 100):
    "Return the elevation profile of the way."

    if dem is None:
        raise hug.HTTPNotFound()

    w = tables.ways.data
    ws = tables.joined_ways.data

    sql = sa.select([gf.ST_LineMerge(gf.ST_Collect(w.c.geom)).label('geom')])\
            .where(w.c.id == ws.c.child)\
            .where(ws.c.id == oid)\
            .alias()

    sel = sa.select([
        sql.c.geom,
        sa.literal_column(
            """ST_Length2dSpheroid(ST_MakeLine(ARRAY[ST_Points(ST_Transform(geom,4326))]),
                             'SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY["EPSG",\"7030\"]]')"""
        ),
        sql.c.geom.ST_NPoints(),
        gf.ST_Length(sql.c.geom)
    ])

    res = conn.execute(sel).first()

    if res is None or res[0] is None:
        raise hug.HTTPNotFound()

    geom = to_shape(res[0])
    # Computing length in Mercator is slightly off, correct it via the
    # actual length.
    dist_fac = res[1] / res[3]

    ele = RouteElevation(oid, dem, geom.bounds)

    if res[2] > 10000:
        geom = geom.simplify(res[2] / 500, preserve_topology=False)
    elif res[2] > 4000:
        geom = geom.simplify(res[2] / 1000, preserve_topology=False)

    if geom.geom_type == 'LineString':
        geom = [geom]

    prev = None
    for seg in geom:
        p = seg.coords[0]
        xcoords = array('d', [p[0]])
        ycoords = array('d', [p[1]])
        pos = array('d')
        if prev is not None:
            pos.append(prev[2][-1] + \
                    Point(prev[0][-1], prev[1][-1]).distance(Point(*p)) * dist_fac)
        else:
            pos.append(0.0)
        for p in seg.coords[1:]:
            pos.append(pos[-1] +
                       Point(xcoords[-1], ycoords[-1]).distance(Point(*p)) *
                       dist_fac)
            xcoords.append(p[0])
            ycoords.append(p[1])

        ele.add_segment(xcoords, ycoords, pos)
        prev = (xcoords, ycoords, pos)

    return ele.as_dict()
Example #6
0
def get_route_length(route_id: uuid.UUID, db_session: Session) -> float:
    return (db_session.query(functions.ST_Length(
        Route.way_points, True)).filter_by(id=route_id).limit(1).scalar())