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(new LineSegment(new Vertex(v[i][j]), 118 new Vertex(v[i][j+1]))); 119 } 120 } 121 122 // Create the vertical line segments. 123 for (int j = 0; j < k; j++) 124 { 125 for (int i = 0; i < n - 1; i++) 126 { 127 addLineSegment(new LineSegment(new Vertex(v[i][j]), 128 new Vertex(v[i+1][j]))); 129 } 130 } 131 } 132}//ParametricSurface