Beispiel #1
0
def angles_poly(a=None, inside=True, in_deg=True):
    """Sequential 3 point angles from a poly* shape

    Parameters
    ----------
    a : array
        an array of points, derived from a polygon/polyline geometry
    inside : boolean
        determine inside angles, outside if False
    in_deg : boolean
        convert to degrees from radians

    Notes
    -----
    General comments::

        2 points - subtract 2nd and 1st points, effectively making the
        calculation relative to the origin and x axis, aka... slope
        n points - sequential angle between 3 points

    To keep::

        ``keep to convert object to array``
        a - a shape from the shape field
        a = p1.getPart()
        b = np.asarray([(i.X, i.Y) if i is not None else ()
                       for j in a for i in j])

    Sample data: the letter C

    >>> a = np.array([[ 0, 0], [ 0, 100], [100, 100], [100,  80],
                      [ 20,  80], [ 20, 20], [100, 20], [100, 0], [ 0, 0]])
    >>> angles_poly(a)  # array([ 90.,  90.,  90., 270., 270.,  90.,  90.])
    """
    a = _new_view_(a)
    if len(a) < 2:
        return None
    if len(a) == 2:
        ba = a[1] - a[0]
        return np.arctan2(*ba[::-1])
    dx, dy = a[0] - a[-1]
    if np.allclose(dx, dy):  # closed loop
        a = a[:-1]
    a0 = np.roll(a, -1, 0)
    a1 = a
    a2 = np.roll(a, 1, 0)
    ba = a1 - a0
    bc = a1 - a2
    cr = np.cross(ba, bc)
    dt = np.einsum('ij,ij->i', ba, bc)
    ang = np.arctan2(cr, dt)
    two_pi = np.pi*2.
    if inside:
        ang = np.where(ang < 0, ang + two_pi, ang)
    else:
        ang = np.where(ang > 0, two_pi - ang, ang)
    if in_deg:
        angles = np.degrees(ang)
    return angles
Beispiel #2
0
def rotate(pnts, angle=0):
    """Rotate points about the origin in degrees, (+ve for clockwise) """
    pnts = _new_view_(pnts)
    angle = np.deg2rad(angle)  # convert to radians
    s = np.sin(angle)
    c = np.cos(angle)  # rotation terms
    aff_matrix = np.array([[c, s], [-s, c]])  # rotation matrix
    XY_r = np.dot(pnts, aff_matrix)  # numpy magic to rotate pnts
    return XY_r
Beispiel #3
0
def angles_seq(a):
    """Sequential angles for a points list, relative to the x-axis.  See
    ``line_dir`` if you want to control the angle type output option.

    >>> angle = atan2(vector2.y, vector2.x) - atan2(vector1.y, vector1.x)
    Accepted answer from the poly_angles link
    """
    a = _new_view_(a)
    ba = a[1:] - a[:-1]
    ang_ab = np.arctan2(ba[:, 1], ba[:, 0])
    return np.degrees(ang_ab % (2 * np.pi))
Beispiel #4
0
def center_(a, remove_dup=True):
    """Return the center of an array. If the array represents a polygon, then
    a check is made for the duplicate first and last point to remove one.

    See Note above
    """
    if a.dtype.kind in ('V', 'O'):
        a = _new_view_(a)
    if remove_dup:
        if np.all(a[0] == a[-1]):
            a = a[:-1]
    return np.nanmean(a, axis=0)
Beispiel #5
0
def dx_dy_np(a):
    """Sequential difference in the x/y pairs from a table/array

    a : ndarray or structured array.
        It is changed as necessary to a 2D array of x/y values.
    _new_view_ : function
        Does the array conversion to 2D from structured if necessary
    """
    a = _new_view_(a)
    out = np.zeros_like(a)
    diff = a[1:] - a[:-1]
    out[1:] = diff
    return out
Beispiel #6
0
def densify_by_distance_old(a, spacing=1):
    """Densify a 2D array by adding points with a specified distance between
    them.  Only appropriate for data representing planar coordinates.

    Parameters
    ----------
    a : array
        A sequence of `points`, x,y pairs, representing the bounds of a polygon
        or polyline object
    spacing : number
        Spacing between the points to be added to the line.

    See Also
    --------
    densify_by_factor, insert_pnts and pnts_on_line

    References
    ----------
    `<https://stackoverflow.com/questions/54665326/adding-points-per-pixel-
    along-some-axis-for-2d-polygon>`_.

    `<https://stackoverflow.com/questions/51512197/python-equidistant-points
    -along-a-line-joining-set-of-points/51514725>`_.

    >>> a = np.array([[0,0], [3, 3], [3, 0], [0,0]])  # 3, 3 triangle
    >>> a = np.array([[0,0], [4, 3], [4, 0], [0,0]])  # 3-4-5 rule
    >>> a = np.array([[0,0], [3, 4], [3, 0], [0,0]])  # 3-4-5 rule
    """
    # ----
    a = _new_view_(a)
    a = np.squeeze(a)
    pnts = []
    for i, e in enumerate(a[1:]):
        s = a[i]  # 1st point, s
        dxdy = (e - s)  # end - start
        d = np.sqrt(np.sum(dxdy**2))  # end - start distance
        N = (d / spacing)
        if N < 1:
            pnts.append([s])
        else:
            delta = dxdy / N
            num = np.arange(N)
            delta = np.where(np.isfinite(delta), delta, 0)
            nn = np.array([num, num]).T
            pnts.append(nn * delta + s)
    pnts.append(a[-1])
    return np.vstack(pnts)
Beispiel #7
0
def poly2segments(a):
    """Segment poly* structures into o-d pairs from start to finish

    Parameters
    ----------
    a : array
        A 2D array of x,y coordinates representing polyline or polygons.
    fr_to : array
        Returns a 3D array of point pairs.
    """
    a = _new_view_(a)
    if a.shape[0] == 1:  # squeeze (1, n, m), (n, 1, m) (n, m, 1) arrays
        a = a.squeeze()
    s0, s1 = a.shape
    fr_to = np.zeros((s0 - 1, s1, 2), dtype=a.dtype)
    fr_to[..., 0] = a[:-1]
    fr_to[..., 1] = a[1:]
    return fr_to
Beispiel #8
0
def densify_by_factor(a, fact=2):
    """Densify a 2D array using np.interp.

    Parameters
    ----------
    a : array
        Input polyline or polygon array coordinates
    fact : number
        The factor to density the line segments by

    See Also
    --------
    densify_by_distance. This option used an absolute distance separation
    along the segments making up the line feature.

    Notes
    -----
    This is the original construction of c rather than the zero's approach
    outlined in the code which constructs and adds to a zeros array

    >>> c0 = c0.reshape(n, -1)
    >>> c1 = c1.reshape(n, -1)
    >>> c = np.concatenate((c0, c1), 1)
    """
    # Y = a changed all the y's to a
    a = _new_view_(a)
    a = np.squeeze(a)
    n_fact = len(a) * fact
    b = np.arange(0, n_fact, fact)
    b_new = np.arange(n_fact - 1)  # Where you want to interpolate
    c0 = np.interp(b_new, b, a[:, 0])
    c1 = np.interp(b_new, b, a[:, 1])
    n = c0.shape[0]
    c = np.zeros((n, 2))
    c[:, 0] = c0
    c[:, 1] = c1
    return c