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)
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)
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)