Beispiel #1
0
def contained_circle_aq(poly):
    """
    The contained circle areal quotient is defined by the 
    ratio of the area of the
    largest contained circle and the shape itself.
    """
    pointset = _get_pointset(poly)
    radius, (cx, cy) = _mcc(pointset)
    return poly.area / (_PI * radius ** 2)
Beispiel #2
0
def flaherty_crumplin_radius(poly):
    """
    The Flaherty & Crumplin (1992) index, OS_3 in Altman's thesis. 
    
    The ratio of the radius of the equi-areal circle to the radius of the MBC
    """
    pointset = _get_pointset(poly) 
    r_eac = np.sqrt(poly.area/_PI)
    r_mbc, _ = _mbc(pointset)
    return r_eac / r_mbc
Beispiel #3
0
def reock(poly):
    """
    The Reock compactness measure, defined by the ratio of areas between the
    minimum bounding/containing circle of a shape and the shape itself. 

    Measure A1 in Altman's thesis, cited for Frolov (1974), but earlier from Reock
    (1963)
    """
    pointset = _get_pointset(poly) 
    radius, (cx, cy) = _mbc(pointset)
    return poly.area / (_PI * radius ** 2)
Beispiel #4
0
def eig_seitzinger(poly):
    """
    The Eig & Seitzinger (1981) shape measure, defined as:

    L - W

    Where L is the maximal east-west extent and W is the maximal north-south
    extent. 

    Defined as measure LW_5 in Altman's thesis
    """
    ptset = _get_pointset(poly) 
    xs, ys = [p[0] for p in ptset], [p[1] for p in ptset]
    l = np.max(xs) - np.min(xs)
    w = np.max(ys) - np.min(ys)
    return l - w
Beispiel #5
0
def moment_of_inertia(poly, dmetric=_dst.euclidean):
    """
    Computes the moment of inertia of the poly. 

    This treats each boundary point as a point-mass of 1.

    Thus, for constant unit mass at each boundary point, 
    the MoI of this pointcloud is

    \sum_i d_{i,c}^2

    where c is the centroid of the poly
    
    Altman's OS_1 measure, cited in Boyce and Clark (1964), also used in Weaver
    and Hess (1963).
    """
    pointset = _get_pointset(poly) 
    dists = [dmetric(pt, poly.centroid)**2 for pt in pointset]
    return poly.area / np.sqrt(2 * np.sum(dists))
Beispiel #6
0
def minimum_bounding_circle(points):
    """
    Implements Skyum (1990)'s algorithm for the minimum bounding circle in R^2. 

    0. Store points clockwise. 
    1. Find p in S that maximizes angle(prec(p), p, succ(p) THEN radius(prec(p),
    p, succ(p)). This is also called the lexicographic maximum, and is the last
    entry of a list of (radius, angle) in lexicographical order. 
    2a. If angle(prec(p), p, succ(p)) <= 90 degrees, then finish. 
    2b. If not, remove p from set. 
    """
    was_polygon = not isinstance(points, (np.ndarray,list))
    if was_polygon:
        from .compactness import _get_pointset
        points = _get_pointset(points)
    chull = ConvexHull(points)
    points = np.asarray(points)[chull.vertices]
    points = points[::-1] #shift from ccw to cw
    points = list(map(tuple, points))
    POINTS = copy.deepcopy(points)
    removed = []
    i=0
    while True:
        triple = _nples(points)
        angles = [_angle(*next(triple)) for p in points]
        circles = [_circle(*next(triple)) for p in points]
        radii = [np.max(c[0]) for c in circles]
        lexord = np.lexsort((angles, radii))#really weird defaults
        lexmax = lexord[-1] #recall, we're addressing p, previous_p, two_before_p

        #recall the triple generator is in leading-index order.
        candidate = points[lexmax], points[lexmax-1], points[lexmax-2]
        
        if angles[lexmax] > PI/2:
            removed = points.pop(lexmax-1)
        else:
            radius, center = circles[lexmax]
            if was_polygon:
                from shapely import geometry
                return geometry.Point(tuple(center)).buffer(radius)
            return circles[lexmax]
        i+=1
Beispiel #7
0
def pairwise_lw(chain):
    """
    Construct the diameter and width of a polygon, as defined as the longest and
    shortest pairwise distances between a polygon's vertices. 

    Returns
    --------

    Returns the indices of all minima/maxima pairs, as well as their values. 

    That is, if two points are minimal with distance d and three pairs are
    maximal with distance D, this would return:

    ((p1, p2), d, (p1, p2, p3), d)
    
    Thus, you need to be careful with automated unpacking.
    """
    ptset = _get_pointset(chain)
    pwds = d.pdist(ptset)
    sqf = d.squareform(pwds)
    minval = pwds[np.nonzero(pwds)].min()  #have to account for zero selfdist
    amin, amax = np.where(sqf == minval), np.where(sqf == pwds.max())
    return amin, sqf[amin], amax, sqf[amax]
Beispiel #8
0
        #Warn('angle close to zero')
        radii = dist.euclidean(A,B)/2.
        center_x = float(Ax + Bx)/2.
        center_y = float(Ay + By)/2.
    else:
        try:
            D = 2*(Ax*(By - Cy) + Bx*(Cy - Ay) + Cx*(Ay - By))
            center_x = float(((Ax**2 + Ay**2)*(By-Cy) 
                            + (Bx**2 + By**2)*(Cy-Ay) 
                            + (Cx**2 + Cy**2)*(Ay-By)) / D)
            center_y = float(((Ax**2 + Ay**2)*(Cx-Bx) 
                            + (Bx**2 + By**2)*(Ax-Cx) 
                            + (Cx**2 + Cy**2)*(Bx-Ax)) / D)
            radii = np.max([dmetric((center_x, center_y), pt) for pt in [A,B,C]])
        except dec.InvalidOperation:
            center_x = center_y = radii = -np.inf
    return radii, (center_x, center_y)

if __name__ == '__main__':
    import libpysal 
    from libpysal.weights._contW_lists import _get_verts as _get_pointset
    import geopandas

    df = geopandas.read_file(libpysal.examples.get_path('columbus.shp'))
    ix = np.random.randint(0,len(df.geometry))
    #ix = 5
    ptset = _get_pointset(df.geometry[ix])

    _mbc_animation(ptset, plotname='test', buffer_=.66)
    print(ix)