lib/svg/arc.py
def elliptical_arc_to(x1, y1, rx, ry, phi, large_arc_flag, sweep_flag, x2, y2):
    
	""" An elliptical arc approximated with Bezier curves or a line segment.
    Algorithm taken from the SVG 1.1 Implementation Notes:
    http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
    """
    
    # Basic normalization.
	rx = abs(rx)
	ry = abs(ry)
	phi = phi % 360
	
	# Check for certain special cases.
	if x1==x2 and y1==y2:
		# Omit the arc.
		# x1 and y1 can obviously remain the same for the next segment.
		return []
	if rx == 0 or ry == 0:
		# Line segment.
		return [(x2,y2)]

	rphi = radians(phi)
	cphi = cos(rphi)
	sphi = sin(rphi)

	# Step 1: Rotate to the local coordinates.
	dx = 0.5*(x1 - x2)
	dy = 0.5*(y1 - y2)
	x1p =  cphi * dx + sphi * dy
	y1p = -sphi * dx + cphi * dy
	# Ensure that rx and ry are large enough to have a unique solution.
	lam = (x1p/rx)**2 + (y1p/ry)**2
	if lam > 1.0:
		scale = sqrt(lam)
		rx *= scale
		ry *= scale

	# Step 2: Solve for the center in the local coordinates.
	num = max((rx*ry)**2 - (rx*y1p)**2 - (ry*x1p)**2, 0.0)
	den = ((rx*y1p)**2 + (ry*x1p)**2)
	a = sqrt(num / den)
	cxp = a * rx*y1p/ry
	cyp = -a * ry*x1p/rx
	if large_arc_flag == sweep_flag:
		cxp = -cxp
		cyp = -cyp

	# Step 3: Transform back.
	mx = 0.5*(x1+x2)
	my = 0.5*(y1+y2)

	# Step 4: Compute the start angle and the angular extent of the arc.
	# Note that theta1 is local to the phi-rotated coordinate space.
	dx = (x1p-cxp) / rx
	dy = (y1p-cyp) / ry
	dx2 = (-x1p-cxp) / rx
	dy2 = (-y1p-cyp) / ry
	theta1 = angle(1,0,dx,dy)
	dtheta = angle(dx,dy,dx2,dy2)
	if not sweep_flag and dtheta > 0:
		dtheta -= 360
	elif sweep_flag and dtheta < 0:
		dtheta += 360

	# Step 5: Break it apart into Bezier arcs.
	p = []
	control_points = bezier_arc(cxp-rx,cyp-ry,cxp+rx,cyp+ry, theta1, dtheta)
	for x1p,y1p, x2p,y2p, x3p,y3p, x4p,y4p in control_points:
		# Transform them back to asbolute space.
		p.append((
			transform_from_local(x2p,y2p,cphi,sphi,mx,my) +
			transform_from_local(x3p,y3p,cphi,sphi,mx,my) +
		transform_from_local(x4p,y4p,cphi,sphi,mx,my)
		))
	return p
def elliptical_arc_to(x1, y1, rx, ry, phi, large_arc_flag, sweep_flag, x2, y2):
    
	""" An elliptical arc approximated with Bezier curves or a line segment.
    Algorithm taken from the SVG 1.1 Implementation Notes:
    http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
    """
    
    # Basic normalization.
	rx = abs(rx)
	ry = abs(ry)
	phi = phi % 360
	
	# Check for certain special cases.
	if x1==x2 and y1==y2:
		# Omit the arc.
		# x1 and y1 can obviously remain the same for the next segment.
		return []
	if rx == 0 or ry == 0:
		# Line segment.
		return [(x2,y2)]

	rphi = radians(phi)
	cphi = cos(rphi)
	sphi = sin(rphi)

	# Step 1: Rotate to the local coordinates.
	dx = 0.5*(x1 - x2)
	dy = 0.5*(y1 - y2)
	x1p =  cphi * dx + sphi * dy
	y1p = -sphi * dx + cphi * dy
	# Ensure that rx and ry are large enough to have a unique solution.
	lam = (x1p/rx)**2 + (y1p/ry)**2
	if lam > 1.0:
		scale = sqrt(lam)
		rx *= scale
		ry *= scale

	# Step 2: Solve for the center in the local coordinates.
	num = max((rx*ry)**2 - (rx*y1p)**2 - (ry*x1p)**2, 0.0)
	den = ((rx*y1p)**2 + (ry*x1p)**2)
	a = sqrt(num / den)
	cxp = a * rx*y1p/ry
	cyp = -a * ry*x1p/rx
	if large_arc_flag == sweep_flag:
		cxp = -cxp
		cyp = -cyp

	# Step 3: Transform back.
	mx = 0.5*(x1+x2)
	my = 0.5*(y1+y2)

	# Step 4: Compute the start angle and the angular extent of the arc.
	# Note that theta1 is local to the phi-rotated coordinate space.
	dx = (x1p-cxp) / rx
	dy = (y1p-cyp) / ry
	dx2 = (-x1p-cxp) / rx
	dy2 = (-y1p-cyp) / ry
	theta1 = angle(1,0,dx,dy)
	dtheta = angle(dx,dy,dx2,dy2)
	if not sweep_flag and dtheta > 0:
		dtheta -= 360
	elif sweep_flag and dtheta < 0:
		dtheta += 360

	# Step 5: Break it apart into Bezier arcs.
	p = []
	control_points = bezier_arc(cxp-rx,cyp-ry,cxp+rx,cyp+ry, theta1, dtheta)
	for x1p,y1p, x2p,y2p, x3p,y3p, x4p,y4p in control_points:
		# Transform them back to asbolute space.
		p.append((
			transform_from_local(x2p,y2p,cphi,sphi,mx,my) +
			transform_from_local(x3p,y3p,cphi,sphi,mx,my) +
		transform_from_local(x4p,y4p,cphi,sphi,mx,my)
		))
	return p
def elliptical_arc_to ( x1 , y1 , rx , ry , phi , large_arc_flag , sweep_flag , x2 , y2 ) : # Basic normalization. rx = abs ( rx ) ry = abs ( ry ) phi = phi % 360 # Check for certain special cases. if x1 == x2 and y1 == y2 : # Omit the arc. # x1 and y1 can obviously remain the same for the next segment. return [ ] if rx == 0 or ry == 0 : # Line segment. return [ ( x2 , y2 ) ] rphi = radians ( phi ) cphi = cos ( rphi ) sphi = sin ( rphi ) # Step 1: Rotate to the local coordinates. dx = 0.5 * ( x1 - x2 ) dy = 0.5 * ( y1 - y2 ) x1p = cphi * dx + sphi * dy y1p = - sphi * dx + cphi * dy # Ensure that rx and ry are large enough to have a unique solution. lam = ( x1p / rx ) ** 2 + ( y1p / ry ) ** 2 if lam > 1.0 : scale = sqrt ( lam ) rx *= scale ry *= scale # Step 2: Solve for the center in the local coordinates. num = max ( ( rx * ry ) ** 2 - ( rx * y1p ) ** 2 - ( ry * x1p ) ** 2 , 0.0 ) den = ( ( rx * y1p ) ** 2 + ( ry * x1p ) ** 2 ) a = sqrt ( num / den ) cxp = a * rx * y1p / ry cyp = - a * ry * x1p / rx if large_arc_flag == sweep_flag : cxp = - cxp cyp = - cyp # Step 3: Transform back. mx = 0.5 * ( x1 + x2 ) my = 0.5 * ( y1 + y2 ) # Step 4: Compute the start angle and the angular extent of the arc. # Note that theta1 is local to the phi-rotated coordinate space. dx = ( x1p - cxp ) / rx dy = ( y1p - cyp ) / ry dx2 = ( - x1p - cxp ) / rx dy2 = ( - y1p - cyp ) / ry theta1 = angle ( 1 , 0 , dx , dy ) dtheta = angle ( dx , dy , dx2 , dy2 ) if not sweep_flag and dtheta > 0 : dtheta -= 360 elif sweep_flag and dtheta < 0 : dtheta += 360 # Step 5: Break it apart into Bezier arcs. p = [ ] control_points = bezier_arc ( cxp - rx , cyp - ry , cxp + rx , cyp + ry , theta1 , dtheta ) for x1p , y1p , x2p , y2p , x3p , y3p , x4p , y4p in control_points : # Transform them back to asbolute space. p . append ( ( transform_from_local ( x2p , y2p , cphi , sphi , mx , my ) + transform_from_local ( x3p , y3p , cphi , sphi , mx , my ) + transform_from_local ( x4p , y4p , cphi , sphi , mx , my ) ) ) return p
An elliptical arc approximated with Bezier curves or a line segment.
    Algorithm taken from the SVG 1.1 Implementation Notes:
    http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
An elliptical arc approximated with Bezier curves or a line segment . Algorithm taken from the SVG 1 . 1 Implementation Notes : http : // www . w3 . org / TR / SVG / implnote . html#ArcImplementationNotes