Source code for kiva.arc_conversion
# (C) Copyright 2005-2022 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!
from math import acos, atan2
from numpy import array, dot, pi, sin, sqrt
[docs]def two_point_arc_to_kiva_arc(p1, p2, theta):
"""
Converts an arc in two point and subtended angle format (startpoint,
endpoint, theta (positive for ccw, negative for cw)) into kiva format
(x, y, radius, start_angle, end_angle, cw)
"""
chord = p2 - p1
chordlen = sqrt(dot(chord, chord))
radius = abs(chordlen / (2 * sin(theta / 2)))
altitude = sqrt(pow(radius, 2) - pow(chordlen / 2, 2))
if theta > pi or theta < 0:
altitude = -altitude
chordmidpoint = (p1 + p2) / 2
rotate90 = array(((0.0, -1.0), (1.0, 0.0)))
centerpoint = dot(rotate90, (chord / chordlen)) * altitude + chordmidpoint
start_angle = atan2(*(p1 - centerpoint)[::-1])
end_angle = start_angle + theta
if theta < 0:
start_angle, end_angle, = end_angle, start_angle
cw = False
radius = abs(radius)
return (centerpoint[0], centerpoint[1], radius, start_angle, end_angle, cw)
[docs]def arc_to_tangent_points(start, p1, p2, radius):
""" Given a starting point, two endpoints of a line segment, and a radius,
calculate the tangent points for arc_to().
"""
def normalize_vector(x, y):
""" Given a vector, return its unit length representation.
"""
length = sqrt(x ** 2 + y ** 2)
if length <= 1e-6:
return (0.0, 0.0)
return (x / length, y / length)
# calculate the angle between the two line segments
v1 = normalize_vector(start[0] - p1[0], start[1] - p1[1])
v2 = normalize_vector(p2[0] - p1[0], p2[1] - p1[1])
angle = acos(v1[0] * v2[0] + v1[1] * v2[1])
# punt if the half angle is zero or a multiple of pi
sin_half_angle = sin(angle / 2.0)
if sin_half_angle == 0.0:
return (p1, p2)
# calculate the distance from p1 to the center of the arc
dist_to_center = radius / sin_half_angle
# calculate the distance from p1 to each tangent point
dist_to_tangent = sqrt(dist_to_center ** 2 - radius ** 2)
# calculate the tangent points
t1 = (p1[0] + v1[0] * dist_to_tangent, p1[1] + v1[1] * dist_to_tangent)
t2 = (p1[0] + v2[0] * dist_to_tangent, p1[1] + v2[1] * dist_to_tangent)
return (t1, t2)