Exemple #1
0
def arc_by_center(x, y, arc_box, constant_length, thickness, gaussian_width):
    """
    Arc with Gaussian fall-off after the solid ring-shaped region and specified
    by point of tangency (x and y) and arc width and height.

    This function calculates the start and end radian from the given width and
    height, and then calls arc_by_radian function to draw the curve.
    """

    arc_w = arc_box[0]
    arc_h = abs(arc_box[1])

    if arc_w == 0.0:  # arc_w=0, don't draw anything
        radius = 0.0
        angles = (0.0, 0.0)
    elif arc_h == 0.0:  # draw a horizontal line, width=arc_w
        return smooth_rectangle(x, y, arc_w, thickness, 0.0, gaussian_width)
    else:
        if constant_length:
            curvature = arc_h / arc_w
            radius = arc_w / (2 * pi * curvature)
            angle = curvature * (2 * pi) / 2.0
        else:  # constant width
            radius = arc_h / 2.0 + arc_w**2.0 / (8 * arc_h)
            angle = arcsin(arc_w / 2.0 / radius)
        if arc_box[1] < 0:  # convex shape
            y = y + radius
            angles = (3.0 / 2.0 * pi - angle, 3.0 / 2.0 * pi + angle)
        else:  # concave shape
            y = y - radius
            angles = (pi / 2.0 - angle, pi / 2.0 + angle)

    return arc_by_radian(x, y, radius * 2.0, angles, thickness, gaussian_width)
Exemple #2
0
def arc_by_center(x, y, arc_box, constant_length, thickness, gaussian_width):
    """
    Arc with Gaussian fall-off after the solid ring-shaped region and specified
    by point of tangency (x and y) and arc width and height.

    This function calculates the start and end radian from the given width and
    height, and then calls arc_by_radian function to draw the curve.
    """

    arc_w=arc_box[0]
    arc_h=abs(arc_box[1])

    if arc_w==0.0: # arc_w=0, don't draw anything
        radius=0.0
        angles=(0.0,0.0)
    elif arc_h==0.0:  # draw a horizontal line, width=arc_w
        return smooth_rectangle(x, y, arc_w, thickness, 0.0, gaussian_width)
    else:
        if constant_length:
            curvature=arc_h/arc_w
            radius=arc_w/(2*pi*curvature)
            angle=curvature*(2*pi)/2.0
        else:  # constant width
            radius=arc_h/2.0+arc_w**2.0/(8*arc_h)
            angle=arcsin(arc_w/2.0/radius)
        if arc_box[1]<0: # convex shape
            y=y+radius
            angles=(3.0/2.0*pi-angle, 3.0/2.0*pi+angle)
        else:  # concave shape
            y=y-radius
            angles=(pi/2.0-angle, pi/2.0+angle)

    return arc_by_radian(x, y, radius*2.0, angles, thickness, gaussian_width)
Exemple #3
0
def arc_by_radian(x, y, height, radian_range, thickness, gaussian_width):
    """
    Radial arc with Gaussian fall-off after the solid ring-shaped
    region with the given thickness, with shape specified by the
    (start,end) radian_range.
    """

    # Create a circular ring (copied from the ring function)
    radius = height/2.0
    half_thickness = thickness/2.0

    distance_from_origin = sqrt(x**2+y**2)
    distance_outside_outer_disk = distance_from_origin - radius - half_thickness
    distance_inside_inner_disk = radius - half_thickness - distance_from_origin

    ring = 1.0-bitwise_xor(greater_equal(distance_inside_inner_disk,0.0),greater_equal(distance_outside_outer_disk,0.0))

    sigmasq = gaussian_width*gaussian_width

    if sigmasq==0.0:
        inner_falloff = x*0.0
        outer_falloff = x*0.0
    else:
        with float_error_ignore():
            inner_falloff = exp(divide(-distance_inside_inner_disk*distance_inside_inner_disk, 2.0*sigmasq))
            outer_falloff = exp(divide(-distance_outside_outer_disk*distance_outside_outer_disk, 2.0*sigmasq))
            
    output_ring = maximum(inner_falloff,maximum(outer_falloff,ring))

    # Calculate radians (in 4 phases) and cut according to the set range)

    # RZHACKALERT:
    # Function float_error_ignore() cannot catch the exception when
    # both dividend and divisor are 0.0, and when only divisor is 0.0
    # it returns 'Inf' rather than 0.0. In x, y and
    # distance_from_origin, only one point in distance_from_origin can
    # be 0.0 (circle center) and in this point x and y must be 0.0 as
    # well. So here is a hack to avoid the 'invalid value encountered
    # in divide' error by turning 0.0 to 1e-5 in distance_from_origin.
    distance_from_origin += where(distance_from_origin == 0.0, 1e-5, 0)

    with float_error_ignore():
        sines = divide(y, distance_from_origin)
        cosines = divide(x, distance_from_origin)
        arcsines = arcsin(sines)

    phase_1 = where(logical_and(sines >= 0, cosines >= 0), 2*pi-arcsines, 0)
    phase_2 = where(logical_and(sines >= 0, cosines <  0), pi+arcsines,   0)
    phase_3 = where(logical_and(sines <  0, cosines <  0), pi+arcsines,   0)
    phase_4 = where(logical_and(sines <  0, cosines >= 0), -arcsines,     0)
    arcsines = phase_1 + phase_2 + phase_3 + phase_4

    if radian_range[0] <= radian_range[1]:
        return where(logical_and(arcsines >= radian_range[0], arcsines <= radian_range[1]),
                     output_ring, 0.0)
    else:
        return where(logical_or(arcsines >= radian_range[0], arcsines <= radian_range[1]),
                     output_ring, 0.0)
def arc_by_radian(x, y, height, radian_range, thickness, gaussian_width):
    """
    Radial arc with Gaussian fall-off after the solid ring-shaped
    region with the given thickness, with shape specified by the
    (start,end) radian_range.
    """

    # Create a circular ring (copied from the ring function)
    radius = height/2.0
    half_thickness = thickness/2.0

    distance_from_origin = sqrt(x**2+y**2)
    distance_outside_outer_disk = distance_from_origin - radius - half_thickness
    distance_inside_inner_disk = radius - half_thickness - distance_from_origin

    ring = 1.0-bitwise_xor(greater_equal(distance_inside_inner_disk,0.0),greater_equal(distance_outside_outer_disk,0.0))

    sigmasq = gaussian_width*gaussian_width

    if sigmasq==0.0:
        inner_falloff = x*0.0
        outer_falloff = x*0.0
    else:
        with float_error_ignore():
            inner_falloff = exp(divide(-distance_inside_inner_disk*distance_inside_inner_disk, 2.0*sigmasq))
            outer_falloff = exp(divide(-distance_outside_outer_disk*distance_outside_outer_disk, 2.0*sigmasq))

    output_ring = maximum(inner_falloff,maximum(outer_falloff,ring))

    # Calculate radians (in 4 phases) and cut according to the set range)

    # RZHACKALERT:
    # Function float_error_ignore() cannot catch the exception when
    # both dividend and divisor are 0.0, and when only divisor is 0.0
    # it returns 'Inf' rather than 0.0. In x, y and
    # distance_from_origin, only one point in distance_from_origin can
    # be 0.0 (circle center) and in this point x and y must be 0.0 as
    # well. So here is a hack to avoid the 'invalid value encountered
    # in divide' error by turning 0.0 to 1e-5 in distance_from_origin.
    distance_from_origin += where(distance_from_origin == 0.0, 1e-5, 0)

    with float_error_ignore():
        sines = divide(y, distance_from_origin)
        cosines = divide(x, distance_from_origin)
        arcsines = arcsin(sines)

    phase_1 = where(logical_and(sines >= 0, cosines >= 0), 2*pi-arcsines, 0)
    phase_2 = where(logical_and(sines >= 0, cosines <  0), pi+arcsines,   0)
    phase_3 = where(logical_and(sines <  0, cosines <  0), pi+arcsines,   0)
    phase_4 = where(logical_and(sines <  0, cosines >= 0), -arcsines,     0)
    arcsines = phase_1 + phase_2 + phase_3 + phase_4

    if radian_range[0] <= radian_range[1]:
        return where(logical_and(arcsines >= radian_range[0], arcsines <= radian_range[1]),
                     output_ring, 0.0)
    else:
        return where(logical_or(arcsines >= radian_range[0], arcsines <= radian_range[1]),
                     output_ring, 0.0)