int
geography_tree_distance(const GSERIALIZED* g1, const GSERIALIZED* g2, const SPHEROID* s, double tolerance, double* distance)
{
    CIRC_NODE* circ_tree1 = NULL;
    CIRC_NODE* circ_tree2 = NULL;
    LWGEOM* lwgeom1 = NULL;
    LWGEOM* lwgeom2 = NULL;
    POINT4D pt1, pt2;

    lwgeom1 = lwgeom_from_gserialized(g1);
    lwgeom2 = lwgeom_from_gserialized(g2);
    circ_tree1 = lwgeom_calculate_circ_tree(lwgeom1);
    circ_tree2 = lwgeom_calculate_circ_tree(lwgeom2);
    lwgeom_startpoint(lwgeom1, &pt1);
    lwgeom_startpoint(lwgeom2, &pt2);

    if ( CircTreePIP(circ_tree1, g1, &pt2) || CircTreePIP(circ_tree2, g2, &pt1) )
    {
        *distance = 0.0;
    }
    else
    {
        /* Calculate tree/tree distance */
        *distance = circ_tree_distance_tree(circ_tree1, circ_tree2, s, tolerance);
    }

    circ_tree_free(circ_tree1);
    circ_tree_free(circ_tree2);
    lwgeom_free(lwgeom1);
    lwgeom_free(lwgeom2);
    return LW_SUCCESS;
}
예제 #2
0
int
lwcollection_startpoint(const LWCOLLECTION* col, POINT4D* pt)
{
	if ( col->ngeoms < 1 )
		return LW_FAILURE;
		
	return lwgeom_startpoint(col->geoms[0], pt);
}
static int
geography_distance_cache_tolerance(FunctionCallInfoData* fcinfo, const GSERIALIZED* g1, const GSERIALIZED* g2, const SPHEROID* s, double tolerance, double* distance)
{
    CircTreeGeomCache* tree_cache = NULL;

    int type1 = gserialized_get_type(g1);
    int type2 = gserialized_get_type(g2);

    Assert(distance);

    /* Two points? Get outa here... */
    if ( type1 == POINTTYPE && type2 == POINTTYPE )
        return LW_FAILURE;

    /* Fetch/build our cache, if appropriate, etc... */
    tree_cache = GetCircTreeGeomCache(fcinfo, g1, g2);

    /* OK, we have an index at the ready! Use it for the one tree argument and */
    /* fill in the other tree argument */
    if ( tree_cache && tree_cache->argnum && tree_cache->index )
    {
        CIRC_NODE* circtree_cached = tree_cache->index;
        CIRC_NODE* circtree = NULL;
        const GSERIALIZED* g_cached;
        const GSERIALIZED* g;
        LWGEOM* lwgeom = NULL;
        int geomtype_cached;
        int geomtype;
        POINT4D p4d;

        /* We need to dynamically build a tree for the uncached side of the function call */
        if ( tree_cache->argnum == 1 )
        {
            g_cached = g1;
            g = g2;
            geomtype_cached = type1;
            geomtype = type2;
        }
        else if ( tree_cache->argnum == 2 )
        {
            g_cached = g2;
            g = g1;
            geomtype_cached = type2;
            geomtype = type1;
        }
        else
        {
            lwpgerror("geography_distance_cache this cannot happen!");
            return LW_FAILURE;
        }

        lwgeom = lwgeom_from_gserialized(g);
        if ( geomtype_cached == POLYGONTYPE || geomtype_cached == MULTIPOLYGONTYPE )
        {
            lwgeom_startpoint(lwgeom, &p4d);
            if ( CircTreePIP(circtree_cached, g_cached, &p4d) )
            {
                *distance = 0.0;
                lwgeom_free(lwgeom);
                return LW_SUCCESS;
            }
        }

        circtree = lwgeom_calculate_circ_tree(lwgeom);
        if ( geomtype == POLYGONTYPE || geomtype == MULTIPOLYGONTYPE )
        {
            POINT2D p2d;
            circ_tree_get_point(circtree_cached, &p2d);
            p4d.x = p2d.x;
            p4d.y = p2d.y;
            if ( CircTreePIP(circtree, g, &p4d) )
            {
                *distance = 0.0;
                circ_tree_free(circtree);
                lwgeom_free(lwgeom);
                return LW_SUCCESS;
            }
        }

        *distance = circ_tree_distance_tree(circtree_cached, circtree, s, tolerance);
        circ_tree_free(circtree);
        lwgeom_free(lwgeom);
        return LW_SUCCESS;
    }
    else
    {
        return LW_FAILURE;
    }
}