001/*
002
003*/
004
005package renderer.models;
006import  renderer.scene.*;
007
008import java.util.function.DoubleBinaryOperator;
009import java.util.function.ToDoubleBiFunction; // could use this instead
010//https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
011
012/**
013   Create a wireframe model of a parametric surface in space.
014<p>
015   See <a href="https://en.wikipedia.org/wiki/Parametric_surface" target="_top">
016                https://en.wikipedia.org/wiki/Parametric_surface</a>
017
018   @see ParametricCurve
019*/
020public class ParametricSurface extends Model
021{
022   /**
023      Create a graph of the function with the following formula,
024      <pre>{@code
025          f(x,z) = sin(PI*x) * sin(PI*z)
026      }</pre>
027      as a parametric surface.
028   */
029   public ParametricSurface()
030   {
031      this((s,t) -> Math.sin(Math.PI*s) * Math.sin(Math.PI*t),
032           -1.0, 1.0, -1.0, 1.0,
033            49, 49);
034   }
035
036
037   /**
038      Create a graph of a function of two variables
039      {@code y = f(x, z)} as a parametric surface with
040      the given parameter ranges in the {@code x} and
041      {@code z} directions.
042
043      @param f   function of x and z
044      @param x1  beginning value of x-parameter range
045      @param x2  ending value of x-parameter range
046      @param z1  beginning value of y-parameter range
047      @param z2  ending value of z-parameter range
048      @param n   number of mesh lines in x-range
049      @param k   number of mesh lines in y-range
050   */
051   public ParametricSurface(DoubleBinaryOperator f,
052                            double x1, double x2,
053                            double z1, double z2,
054                            int n, int k)
055   {
056      this((x,z) -> x, f, (x,z) -> z, x1, x2, z1, z2, n, k);
057   }
058
059
060   /**
061      Create a parametric surface in space,
062      <pre>{@code
063         x = x(s,t)
064         y = y(s,t)
065         z = z(s,t)
066      }</pre>
067      with the parameters {@code s} and {@code t} having
068      the given parameter ranges and the given number of
069      mesh lines in each parametric direction.
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 s1  beginning value of first parameter range
075      @param s2  ending value of first parameter range
076      @param t1  beginning value of second parameter range
077      @param t2  ending value of second parameter range
078      @param n   number of mesh lines in first range
079      @param k   number of mesh lines in second range
080   */
081   public ParametricSurface(DoubleBinaryOperator x,
082                            DoubleBinaryOperator y,
083                            DoubleBinaryOperator z,
084                            double s1, double s2,
085                            double t1, double t2,
086                            int n, int k)
087   {
088      super();
089
090      if (n < 2) n = 2;
091      if (k < 2) k = 2;
092
093      // Create the curve's geometry.
094
095      double deltaS = (s2 - s1) / (n - 1);
096      double deltaT = (t2 - t1) / (k - 1);
097
098      // An array of vertices to be used to create the line segments.
099      Vertex[][] v = new Vertex[n][k];
100
101      // Create all the vertices.
102      for (int i = 0; i < n; i++)
103      {
104         for (int j = 0; j < k; j++)
105         {
106            v[i][j] = new Vertex(x.applyAsDouble(s1 + i*deltaS, t1 + j*deltaT),
107                                 y.applyAsDouble(s1 + i*deltaS, t1 + j*deltaT),
108                                 z.applyAsDouble(s1 + i*deltaS, t1 + j*deltaT));
109         }
110      }
111
112      // Create the horizontal line segments.
113      for (int i = 0; i < n; i++)
114      {
115         for (int j = 0; j < k - 1; j++)
116         {
117            addLineSegment(v[i][j], v[i][j+1]);
118         }
119      }
120
121      // Create the vertical line segments.
122      for (int j = 0; j < k; j++)
123      {
124         for (int i = 0; i < n - 1; i++)
125         {
126            addLineSegment(v[i][j], v[i+1][j]);
127         }
128      }
129   }
130}//ParametricSurface