def METHOD_NAME(points, return_normal=True, return_angle=True):
    """
    Given three points on a 2D or 3D arc find the center,
    radius, normal, and angular span.
    Parameters
    ---------
    points : (3, dimension) float
      Points in space, where dimension is either 2 or 3
    return_normal : bool
      If True calculate the 3D normal unit vector
    return_angle : bool
      If True calculate the start and stop angle and span
    Returns
    ---------
    result : dict
      Contains arc center and other keys:
       'center' : (d,) float, cartesian center of the arc
       'radius' : float, radius of the arc
       'normal' : (3,) float, the plane normal.
       'angles' : (2,) float, angle of start and end in radians
       'span'   : float, angle swept by the arc in radians
    """
    points = np.asanyarray(points, dtype=np.float64)
    # get the non-unit vectors of the three points
    vectors = points[[2, 0, 1]] - points[[1, 2, 0]]
    # we need both the squared row sum and the non-squared
    abc2 = np.dot(vectors ** 2, [1] * points.shape[1])
    # same as np.linalg.norm(vectors, axis=1)
    abc = np.sqrt(abc2)
    # perform radius calculation scaled to shortest edge
    # to avoid precision issues with small or large arcs
    scale = abc.min()
    # get the edge lengths scaled to the smallest
    edges = abc / scale
    # half the total length of the edges
    half = edges.sum() / 2.0
    # check the denominator for the radius calculation
    denom = half * np.prod(half - edges)
    if denom < tol.merge:
        raise ValueError('arc is colinear!')
    # find the radius and scale back after the operation
    radius = scale * ((np.prod(edges) / 4.0) / np.sqrt(denom))
    # use a barycentric approach to get the center
    ba2 = (abc2[[1, 2, 0, 0, 2, 1, 0, 1, 2]] *
           [1, 1, -1, 1, 1, -1, 1, 1, -1]).reshape(
               (3, 3)).sum(axis=1) * abc2
    center = points.T.dot(ba2) / ba2.sum()
    if tol.strict:
        # all points should be at the calculated radius from center
        assert util.allclose(
            np.linalg.norm(points - center, axis=1),
            radius)
    # start with initial results
    result = {'center': center,
              'radius': radius}
    if return_normal:
        if points.shape == (3, 2):
            # for 2D arcs still use the cross product so that
            # the sign of the normal vector is consistent
            result['normal'] = util.unitize(
                np.cross(np.append(-vectors[1], 0),
                         np.append(vectors[2], 0)))
        else:
            # otherwise just take the cross product
            result['normal'] = util.unitize(
                np.cross(-vectors[1], vectors[2]))
    if return_angle:
        # vectors from points on arc to center point
        vector = util.unitize(points - center)
        edge_direction = np.diff(points, axis=0)
        # find the angle between the first and last vector
        dot = np.dot(*vector[[0, 2]])
        if dot < (_TOL_ZERO - 1):
            angle = np.pi
        elif dot > 1 - _TOL_ZERO:
            angle = 0.0
        else:
            angle = np.arccos(dot)
        # if the angle is nonzero and vectors are opposite direction
        # it means we have a long arc rather than the short path
        if abs(angle) > _TOL_ZERO and np.dot(*edge_direction) < 0.0:
            angle = (np.pi * 2) - angle
        # convoluted angle logic
        angles = np.arctan2(*vector[:, :2].T[::-1]) + np.pi * 2
        angles_sorted = np.sort(angles[[0, 2]])
        reverse = angles_sorted[0] < angles[1] < angles_sorted[1]
        angles_sorted = angles_sorted[::(1 - int(not reverse) * 2)]
        result['angles'] = angles_sorted
        result['span'] = angle
    return result