001/* 002 * Renderer Models. The MIT License. 003 * Copyright (c) 2022 rlkraft@pnw.edu 004 * See LICENSE for details. 005*/ 006 007package renderer.models_L; 008 009import renderer.scene.*; 010import renderer.scene.primitives.*; 011import renderer.scene.util.MeshMaker; 012 013import java.util.function.DoubleFunction; 014import java.util.function.ToDoubleFunction; // could use this instead 015import java.util.function.DoubleUnaryOperator; // could use this instead 016//https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html 017 018/** 019 Create a wireframe model of a parametric curve in space. 020<p> 021 See <a href="https://en.wikipedia.org/wiki/Parametric_equation" target="_top"> 022 https://en.wikipedia.org/wiki/Parametric_equation</a> 023 024 @see ParametricSurface 025*/ 026public class ParametricCurve extends Model implements MeshMaker 027{ 028 public final DoubleFunction<Double> x; 029 public final DoubleFunction<Double> y; 030 public final DoubleFunction<Double> z; 031 public final double t1; 032 public final double t2; 033 public final int n; 034 035 /** 036 Create a trefoil knot as a parametric curve in space. 037 <p> 038 See <a href="https://en.wikipedia.org/wiki/Trefoil_knot#Descriptions" target="_top"> 039 https://en.wikipedia.org/wiki/Trefoil_knot#Descriptions</a> 040 */ 041 public ParametricCurve() 042 { 043 this(t -> 0.5*Math.sin(t) + Math.sin(2*t), 044 t -> 0.5*Math.cos(t) - Math.cos(2*t), 045 t -> -0.5*Math.sin(3*t), 046 0, 2*Math.PI, 60); 047 } 048 049 050 /** 051 Create a parametric curve in the xy-plane, 052 <pre>{@code 053 x = x(t) 054 y = y(t) 055 }</pre> 056 with the parameter {@code t} having the given parameter 057 range and the given number of line segments. 058 059 @param x component function in the x-direction 060 @param y component function in the y-direction 061 @param t1 beginning value of parameter range 062 @param t2 ending value of parameter range 063 @param n number of line segments in the curve 064 @throws IllegalArgumentException if {@code n} is less than 1 065 */ 066 public ParametricCurve(final DoubleFunction<Double> x, 067 final DoubleFunction<Double> y, 068 final double t1, final double t2, 069 final int n) 070 { 071 this(x, y, t->0.0, t1, t2, n); 072 } 073 074 075 /** 076 Create a parametric curve in space, 077 <pre>{@code 078 x = x(t) 079 y = y(t) 080 z = z(t) 081 }</pre> 082 with the parameter {@code t} having the given parameter 083 range and the given number of line segments. 084 085 @param x component function in the x-direction 086 @param y component function in the y-direction 087 @param z component function in the z-direction 088 @param t1 beginning value of parameter range 089 @param t2 ending value of parameter range 090 @param n number of line segments in the curve 091 @throws IllegalArgumentException if {@code n} is less than 1 092 */ 093 public ParametricCurve(final DoubleFunction<Double> x, 094 final DoubleFunction<Double> y, 095 final DoubleFunction<Double> z, 096 final double t1, final double t2, 097 final int n) 098 { 099 super(String.format("Parametric Curve(%d)", n)); 100 101 if (n < 1) 102 throw new IllegalArgumentException("n must be greater than 0"); 103 104 this.x = x; 105 this.y = y; 106 this.z = z; 107 this.t1 = t1; 108 this.t2 = t2; 109 this.n = n; 110 111 // Create the curve's geometry. 112 final double deltaT = (t2 - t1) / n; 113 114 for (int i = 0; i < n + 1; ++i) 115 { 116 addVertex( new Vertex( x.apply(t1 + i * deltaT), 117 y.apply(t1 + i * deltaT), 118 z.apply(t1 + i * deltaT) ) ); 119 } 120 121 for (int i = 0; i < n; ++i) 122 { 123 addPrimitive(new LineSegment(i, i+1)); 124 } 125 } 126 127 128 129 // Implement the MeshMaker interface (three methods). 130 @Override public int getHorzCount() {return n;} 131 132 @Override public int getVertCount() {return n;} 133 134 @Override 135 public ParametricCurve remake(final int n, final int k) 136 { 137 final int newN; 138 if (n != this.n) 139 newN = n; 140 else 141 newN = k; 142 143 return new ParametricCurve(this.x, this.y, this.z, 144 this.t1, this.t2, 145 newN); 146 } 147}//ParametricCurve