001/*
002
003*/
004
005package renderer.models;
006import  renderer.scene.*;
007
008import java.util.function.DoubleFunction;
009import java.util.function.ToDoubleFunction;    // could use this instead
010import java.util.function.DoubleUnaryOperator; // could use this instead
011//https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
012
013/**
014   Create a wireframe model of a parametric curve in space.
015<p>
016   See <a href="https://en.wikipedia.org/wiki/Parametric_equation" target="_top">
017                https://en.wikipedia.org/wiki/Parametric_equation</a>
018
019   @see ParametricSurface
020*/
021public class ParametricCurve extends Model
022{
023   /**
024      Create a trefoil knot as a parametric curve in space.
025   <p>
026      See <a href="https://en.wikipedia.org/wiki/Trefoil_knot#Descriptions" target="_top">
027                   https://en.wikipedia.org/wiki/Trefoil_knot#Descriptions</a>
028   */
029   public ParametricCurve()
030   {
031      this(t ->  0.5*Math.sin(t) + Math.sin(2*t),
032           t ->  0.5*Math.cos(t) - Math.cos(2*t),
033           t -> -0.5*Math.sin(3*t),
034           0, 2*Math.PI, 60);
035   }
036
037
038   /**
039      Create a parametric curve in the xy-plane,
040      <pre>{@code
041         x = x(t)
042         y = y(t)
043      }</pre>
044      with the parameter {@code  t} having the given parameter
045      range and the given number of line segments.
046
047      @param x   component function in the x-direction
048      @param y   component function in the y-direction
049      @param t1  beginning value of parameter range
050      @param t2  ending value of parameter range
051      @param n   number of line segments in the curve
052   */
053   public ParametricCurve(DoubleFunction<Double> x,
054                          DoubleFunction<Double> y,
055                          double t1, double t2, int n)
056   {
057      this(x, y, t->0.0, t1, t2, n);
058   }
059
060
061   /**
062      Create a parametric curve in space,
063      <pre>{@code
064         x = x(t)
065         y = y(t)
066         z = z(t)
067      }</pre>
068      with the parameter {@code t} having the given parameter
069      range and the given number of line segments.
070
071      @param x   component function in the x-direction
072      @param y   component function in the y-direction
073      @param z   component function in the z-direction
074      @param t1  beginning value of parameter range
075      @param t2  ending value of parameter range
076      @param n   number of line segments in the curve
077   */
078   public ParametricCurve(DoubleFunction<Double> x,
079                          DoubleFunction<Double> y,
080                          DoubleFunction<Double> z,
081                          double t1, double t2, int n)
082   {
083      super();
084
085      if (n < 1) n = 1;
086
087      // Create the curve's geometry.
088
089      double deltaT = (t2 - t1) / n;
090
091      // An array of vertices to be used to create the line segments.
092      Vertex[] v = new Vertex[n+1];
093
094      // Create all the vertices.
095      for (int i = 0; i < n + 1; i++)
096      {
097         v[i] = new Vertex( x.apply(t1 + i * deltaT),
098                            y.apply(t1 + i * deltaT),
099                            z.apply(t1 + i * deltaT) );
100      }
101
102      // Create the line segments along the curve.
103      for (int i = 0; i < n; i++)
104      {
105         addLineSegment(v[i], v[i+1]);
106      }
107/*
108      // Or, we could build the curve the
109      // following, more efficient, way.
110      addVertex(v);
111      for (int i = 0; i < n; i++)
112      {
113         addLineSegment(i, i+1);
114      }
115*/
116   }
117}//ParametricCurve