############################################################################ # # File: curves.icn # # Subject: Procedures to generate points on plain curves # # Author: Ralph E. Griswold # # Date: March 25, 2002 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This file links procedure files that generate traces of points on various # plain curves. # # The first two parameters determine the defining position of the # curve: # # x x coordinate # y y coordinate # # The meaning of "definition position" depends on the curve. In some # cases it is the position at which plotting starts. In others, it # is a "center" for the curve. # # The next arguments vary and generally refer to parameters of the # curve. There is no practical way to describe these here. If they # are not obvious, the best reference is # # A Catalog of Special Plane Curves, J. Dennis Lawrence, # Dover Publications, Inc., New York, 1972. # # This book, which is in print at the time of this writing, is a # marvelous source of information about plane curves and is inexpensive # as well. # # The trailing parameters give the number of steps and the end points # (generally in angles) of the curves: # # steps number of points, default varies # lo beginning of plotting range, default varies # hi end of plotting range, default varies # # Because of floating-point roundoff, the number of steps # may not be exactly the number specified. # # Note: Some of the curves may be "upside down" when plotted on # coordinate systems in which the y axis increases in a downward direction. # # Caution: Some of these procedures generate very large values # in portions of their ranges. These may cause run-time errors when # used in versions of Icon prior to 8.10. One work-around is to # turn on error conversion in such cases. # # Warning: The procedures that follow have not been tested thoroughly. # Corrections and additions are most welcome. # # These procedures are, in fact, probably most useful for the parametric # equations they contain. # ############################################################################ # # Links: gobject, math, step # ############################################################################ link gobject link math link step procedure bullet_nose(x, y, a, b, steps, lo, hi) local incr, theta /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do suspend Point( x + a * cos(theta), y + b * tan(&pi / 2 - theta), 0 ) end procedure cardioid(x, y, a, steps, lo, hi) local incr, theta, fact /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { fact := 2 * a * (1 + cos(theta)) suspend Point( x + cos(theta) * fact, y + sin(theta) * fact, 0 ) } end procedure cissoid_diocles(x, y, a, steps, lo, hi) local incr, theta, radius /steps := 300 lo := dtor(\lo) | (-2 * &pi) hi := dtor(\hi) | (2 * &pi) incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { radius := a * sin(theta) * cos(theta) suspend Point( x + radius * cos(theta), y + radius * sin(theta), 0 ) } end procedure cross_curve(x, y, a, b, steps, lo, hi) local incr, theta /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do suspend Point( x + a / cos(theta), y + b / sin(theta), 0 ) end procedure cycloid(x, y, a, b, steps, lo, hi) local incr, theta /steps := 100 lo := dtor(\lo) | 0 hi := dtor(\hi) | (8 * &pi) incr := (hi - lo) / steps every theta := step(lo, hi, incr) do suspend Point( x + a * theta - b * sin(theta), y + a - b * cos(theta), 0 ) end procedure deltoid(x, y, a, steps, lo, hi) local incr, theta /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do suspend Point( x + a * (2 * cos(theta) + cos(2 * theta)), y + a * (2 * sin(theta) - sin(2 * theta)), 0 ) end procedure ellipse(x, y, a, b, steps, lo, hi) local incr, theta /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do suspend Point( x + a * cos(theta), y + b * sin(theta), 0 ) end procedure ellipse_evolute(x, y, a, b, steps, lo, hi) local incr, theta /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do suspend Point( x + a * cos(theta) ^ 3, y + b * sin(theta) ^ 3, 0 ) end procedure epitrochoid(x, y, a, b, h, steps, lo, hi) local incr, theta, sum, fact /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps sum := a + b fact := sum / b every theta := step(lo, hi, incr) do suspend Point( x + sum * cos(theta) - h * cos(fact * theta), y + sum * sin(theta) - h * sin(fact * theta), 0 ) end procedure folium(x, y, a, b, steps, lo, hi) local incr, theta, radius /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { radius := (3 * a * sin(theta) * cos(theta)) / (sin(theta) ^ 2 + cos(theta) ^ 2) suspend Point( x + radius * cos(theta), y + radius * sin(theta), 0 ) } end procedure hippopede(x, y, a, b, steps, lo, hi) local incr, theta, mul /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { mul := a * b - b ^ 2 * sin(theta) ^ 2 if mul < 0 then next mul := 2 * sqrt(mul) suspend Point( x + mul * cos(theta), y + mul *sin(theta), 0 ) } end procedure kampyle_exodus(x, y, a, b, steps, lo, hi) local incr, theta, fact /steps := 300 lo := dtor(\lo) | (-&pi / 2) hi := dtor(\hi) | (3 * &pi / 2) incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { fact := a / cos(theta) suspend Point( x + fact, y + fact * tan(theta), 0 ) } end procedure kappa(x, y, a, b, steps, lo, hi) local incr, theta, fact /steps := 300 lo := dtor(\lo) | 0 hi := dtor(\hi) | (2 * &pi) incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { fact := a * cos(theta) suspend Point( x + fact / (0 ~= tan(theta)), y + fact, 0 ) } end procedure lemniscate_bernoulli(x, y, a, steps, lo, hi) local incr, theta, fact /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { fact := a * cos(theta) / (1 + sin(theta) ^ 2) suspend Point( x + fact, y + fact * sin(theta), 0 ) } end procedure lemniscate_gerono(x, y, a, b, steps, lo, hi) local incr, theta, fact /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { fact := a * cos(theta) suspend Point( x + fact, y + sin(theta) * fact, 0 ) } end procedure limacon_pascal(x, y, a, b, steps, lo, hi) local incr, theta, fact /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { fact := b + 2 * a * cos(theta) suspend Point( x + fact * cos(theta), y + fact * sin(theta), 0 ) } end procedure line(x, y, x1, y1, steps) local xincr, yincr /steps := 100 xincr := (x1 - x) / (steps - 1) yincr := (y1 - y) / (steps - 1) every 1 to steps do { suspend Point(x, y, 0) x +:= xincr y +:= yincr } end procedure lissajous(x, y, a, b, r, delta, steps, lo, hi) local incr, theta /steps := 300 lo := dtor(\lo) | 0 hi := dtor(\hi) | (16 * &pi) incr := (hi - lo) / steps r := dtor(r) every theta := step(lo, hi, incr) do suspend Point( x + a * sin(r * theta + delta), y + b * sin(theta), 0 ) end procedure nephroid(x, y, a, steps, lo, hi) local incr, theta /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do suspend Point( x + a * (3 * cos(theta) - cos(3 * theta)), y + a * (3 * sin(theta) - sin(3 * theta)), 0 ) end # Needs to be checked out procedure parabola(x, y, a, steps, lo, hi) local incr, theta, denom, radius /steps := 300 lo := dtor(\lo) | -&pi hi := dtor(\hi) | &pi incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { denom := 1 - cos(theta) if denom = 0 then next radius := 2 * a / denom suspend Point( radius * cos(theta), radius * sin(theta), 0 ) } end procedure piriform(x, y, a, b, steps, lo, hi) local incr, theta, fact /steps := 300 lo := dtor(\lo) | (-&pi / 2) hi := dtor(\hi) | (3 * &pi / 2) incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { fact := 1 + sin(theta) suspend Point( x + a * fact, y + b * cos(theta) * fact, 0 ) } end procedure trisectrix_catalan(x, y, a, steps, lo, hi) local incr, theta, radius /steps := 300 lo := dtor(\lo) | (-2 * &pi) hi := dtor(\hi) | (2 * &pi) incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { radius := a / cos(theta / 3) ^ 3 suspend Point( x + radius * cos(theta), y + radius * sin(theta), 0 ) } end procedure trisectrix_maclaurin(x, y, a, b, steps, lo, hi) local incr, theta, fact /steps := 300 lo := dtor(\lo) | (-&pi / 2) hi := dtor(\hi) | (&pi / 2) incr := (hi - lo) / steps every theta := step(lo, hi, incr) do { fact := a * (1 - 4 * cos(theta) ^ 2) suspend Point( x + fact, y + fact * tan(theta), 0 ) } end procedure witch_agnesi(x, y, a, steps, lo, hi) local incr, theta, fact /steps := 300 lo := dtor(\lo) | (-&pi /2) hi := dtor(\hi) | (&pi / 2) incr := (hi - lo) / steps fact := 2 * a every theta := step(lo, hi, incr) do suspend Point( x + fact * tan(theta), y - fact * cos(theta) ^ 2, 0 ) end