Beispiel #1
0
bool Polygon::covers(PointRef& ref) const
{
    GEOSCoordSequence* coords = GEOSCoordSeq_create_r(m_ctx, 1, 3);
    if (!coords)
        throw pdal_error("Unable to allocate coordinate sequence");

    const double x = ref.getFieldAs<double>(Dimension::Id::X);
    const double y = ref.getFieldAs<double>(Dimension::Id::Y);
    const double z = ref.getFieldAs<double>(Dimension::Id::Z);

    if (!GEOSCoordSeq_setX_r(m_ctx, coords, 0, x))
        throw pdal_error("unable to set x for coordinate sequence");
    if (!GEOSCoordSeq_setY_r(m_ctx, coords, 0, y))
        throw pdal_error("unable to set y for coordinate sequence");
    if (!GEOSCoordSeq_setZ_r(m_ctx, coords, 0, z))
        throw pdal_error("unable to set z for coordinate sequence");
    GEOSGeometry* p = GEOSGeom_createPoint_r(m_ctx, coords);
    if (!p)
        throw pdal_error("unable to allocate candidate test point");

    bool covers = (bool)(GEOSPreparedCovers_r(m_ctx, m_prepGeom, p));
    GEOSGeom_destroy_r(m_ctx, p);

    return covers;
}
Beispiel #2
0
State get_state(const Point &point, const GEOSPreparedGeometry *gp_domain,
                GEOSContextHandle_t handle)
{
    State state;

    if (isfinite(point.x) && isfinite(point.y))
    {
        // TODO: Avoid create-destroy
        GEOSCoordSequence *coords = GEOSCoordSeq_create_r(handle, 1, 2);
        GEOSCoordSeq_setX_r(handle, coords, 0, point.x);
        GEOSCoordSeq_setY_r(handle, coords, 0, point.y);
        GEOSGeometry *g_point = GEOSGeom_createPoint_r(handle, coords);
        state = GEOSPreparedCovers_r(handle, gp_domain, g_point) ? POINT_IN : POINT_OUT;
        GEOSGeom_destroy_r(handle, g_point);
    }
    else
    {
        state = POINT_NAN;
    }
    return state;
}
Beispiel #3
0
/*
 * Return whether the given line segment is suitable as an
 * approximation of the projection of the source line.
 *
 * t_start: Interpolation parameter for the start point.
 * p_start: Projected start point.
 * t_end: Interpolation parameter for the end point.
 * p_start: Projected end point.
 * interpolator: Interpolator for current source line.
 * threshold: Lateral tolerance in target projection coordinates.
 * handle: Thread-local context handle for GEOS.
 * gp_domain: Prepared polygon of target map domain.
 * inside: Whether the start point is within the map domain.
 */
bool straightAndDomain(double t_start, const Point &p_start,
                       double t_end, const Point &p_end,
                       Interpolator *interpolator, double threshold,
                       GEOSContextHandle_t handle,
                       const GEOSPreparedGeometry *gp_domain,
                       bool inside)
{
    // Straight and in-domain (de9im[7] == 'F')
    
    bool valid;

    // This could be optimised out of the loop.
    if (!(isfinite(p_start.x) && isfinite(p_start.y)))
    {
        valid = false;
    }
    else if (!(isfinite(p_end.x) && isfinite(p_end.y)))
    {
        valid = false;
    }
    else
    {
        // TODO: Re-use geometries, instead of create-destroy!

        // Create a LineString for the current end-point.
        GEOSCoordSequence *coords = GEOSCoordSeq_create_r(handle, 2, 2);
        GEOSCoordSeq_setX_r(handle, coords, 0, p_start.x);
        GEOSCoordSeq_setY_r(handle, coords, 0, p_start.y);
        GEOSCoordSeq_setX_r(handle, coords, 1, p_end.x);
        GEOSCoordSeq_setY_r(handle, coords, 1, p_end.y);
        GEOSGeometry *g_segment = GEOSGeom_createLineString_r(handle, coords);

        // Find the projected mid-point
        double t_mid = (t_start + t_end) * 0.5;
        Point p_mid = interpolator->interpolate(t_mid);

        // Make it into a GEOS geometry
        coords = GEOSCoordSeq_create_r(handle, 1, 2);
        GEOSCoordSeq_setX_r(handle, coords, 0, p_mid.x);
        GEOSCoordSeq_setY_r(handle, coords, 0, p_mid.y);
        GEOSGeometry *g_mid = GEOSGeom_createPoint_r(handle, coords);

        double along = GEOSProjectNormalized_r(handle, g_segment, g_mid);
        if(isnan(along))
        {
            valid = true;
        }
        else
        {
            valid = 0.0 < along && along < 1.0;
            if (valid)
            {
                double separation;
                GEOSDistance_r(handle, g_segment, g_mid, &separation);
                if (inside)
                {
                    // Scale the lateral threshold by the distance from
                    // the nearest end. I.e. Near the ends the lateral
                    // threshold is much smaller; it only has its full
                    // value in the middle.
                    valid = separation <= threshold * 2.0 *
                                            (0.5 - fabs(0.5 - along));
                }
                else
                {
                    // Check if the mid-point makes less than ~11 degree
                    // angle with the straight line.
                    // sin(11') => 0.2
                    // To save the square-root we just use the square of
                    // the lengths, hence:
                    // 0.2 ^ 2 => 0.04
                    double hypot_dx = p_mid.x - p_start.x;
                    double hypot_dy = p_mid.y - p_start.y;
                    double hypot = hypot_dx * hypot_dx + hypot_dy * hypot_dy;
                    valid = ((separation * separation) / hypot) < 0.04;
                }
            }
        }

        if (valid)
        {
            if(inside)
                valid = GEOSPreparedCovers_r(handle, gp_domain, g_segment);
            else
                valid = GEOSPreparedDisjoint_r(handle, gp_domain, g_segment);
        }

        GEOSGeom_destroy_r(handle, g_segment);
        GEOSGeom_destroy_r(handle, g_mid);
    }

    return valid;
}