Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # -*- coding: utf-8 -*-
- """
- Monotonic increasing sinusoidal curve with same entrance/exit angle
- """
- import numpy as np
- import pylab
- def discrt_tan(x0, y0, x1, y1):
- """ discrete tangent function for tuple of points """
- return np.divide(np.subtract(y1,y0), np.subtract(x1,x0))
- def curve(xs, size, mid_angle=0.0):
- """ monotonic raising curve function with sinusoidal accent.
- Function for a monotonic raising curve with same entrance/exit angle.
- Sinusoidal setup for *monotonic increasing* constraints angles in following fashion;
- - mid_angle must be between [0..pi/4) - approaching pi/4 yields straight line.
- - generated entrance/exit angles are between [45..~63.43] degrees
- The curve is expresses as;
- y = x + [sin(2PI * x / size)] / accent
- Args:
- xs (array like): input value(s)
- size: size range of the input/output values
- mid_angle: middle angle of the sinusoidal in radians
- Returns:
- array-like curve value.
- Raises:
- `ValueError` for params. that out of range;
- mid_angle - must be between [0..pi/4)
- xs - must be in range between [0..size]
- Todo:
- - `accent` does not well-define middle angle parameter.
- - if curve will not be limited in size range, derivation will be step-wise continuous.
- More calculation can be made for continuous derivation. (tangents at 0 and size)
- """
- if mid_angle<0 or mid_angle>=np.pi/4:
- raise ValueError("mid-angle must be between [0..pi/4)")
- if np.any(xs < 0) or np.any(xs > size):
- raise ValueError("xs must be between [0..size]")
- accent = 2*np.pi/size * np.tan(np.pi/4+mid_angle) # TODO: not well-defined mid-angle param.
- return xs + np.sin(2*np.pi*xs/size) / accent
- if __name__ == "__main__":
- """
- Test and plot `curve` function for various values and mid_angle degrees
- """
- eps = 1e-11
- #eps = np.finfo(float).eps
- size = 1
- print "### testing values..."
- print "x= {:.15f}, y={:.15f}".format(size, curve(size, size))
- print "x= {:.15f}, y={:.15f}".format(np.subtract(size,eps), curve(np.subtract(size,eps), size))
- print "x= {:.15f}, y={:.15f}".format(size/2.0, curve(size/2.0, size))
- # angles at 0, mid, size
- mids = [0, np.pi/128, np.pi/64, np.pi/32, np.pi/16, np.pi/8, np.pi/6, np.pi/4-eps]
- max_err = 0.0
- params = {'legend.fontsize': 'small',
- 'axes.labelsize': 'small',
- 'axes.titlesize':'small',
- 'xtick.labelsize':'small',
- 'ytick.labelsize':'small'}
- pylab.rcParams.update(params)
- colc = 2
- rowc = (len(mids)+1)/colc
- f, axarr = pylab.subplots(rowc, colc)
- print "\n### testing angles..."
- for i,mid in enumerate(mids):
- print "mid (input) = {:.15f}".format(np.rad2deg(mid))
- t = discrt_tan(size/2.0, curve(size/2.0, size, mid),
- np.add(size/2.0,eps), curve(np.add(size/2.0,eps), size, mid))
- print "angle at mid = {:.15f}".format(np.rad2deg(np.arctan(t)))
- t = discrt_tan(0, curve(0, size, mid),
- eps, curve(eps, size, mid))
- print "angle at 0 = {:.15f}".format(np.rad2deg(np.arctan(t)))
- t1 = discrt_tan(size, curve(size, size, mid),
- np.subtract(size,eps), curve(np.subtract(size,eps), size, mid))
- print "angle at size = {:.15f}".format(np.rad2deg(np.arctan(t1)))
- # error
- err = np.abs(np.subtract(np.rad2deg(np.arctan(t1)), np.rad2deg(np.arctan(t))))
- max_err = np.maximum(max_err, err)
- print "error = {:.15f}\n".format(err)
- # plot
- xs = np.linspace(0, size, 100)
- ys = curve(xs, size, mid)
- row = i/colc
- col = i - row*colc
- axarr[row, col].plot(xs, ys)
- axarr[row, col].set_title('mid_angle={:.4f} rad.'.format(mid))
- axarr[row, col].text(0.95, 0.15, 'alpha={:.6f} deg.'.format(np.rad2deg(np.arctan(t))),
- verticalalignment='bottom', horizontalalignment='right',
- transform=axarr[row, col].transAxes,
- color='green', fontsize=10)
- axarr[row, col].text(0.95, 0.03, 'err={:.6f} deg.'.format(err),
- verticalalignment='bottom', horizontalalignment='right',
- transform=axarr[row, col].transAxes,
- color='red', fontsize=10)
- print"Max. Error = {:.15f}".format(max_err)
- pylab.show()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement