From 70f01a69c44f5749c4c79ec6e747de89c30ecfcf Mon Sep 17 00:00:00 2001 From: kappa Date: Sat, 23 Sep 2023 18:26:49 +0200 Subject: [PATCH] Add Spectrum class with an implementation --- .idea/libraries/google_guava.xml | 8 +-- .idea/misc.xml | 2 +- src/xyz/marsavic/gfxlab/Spectrum.java | 93 +++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 src/xyz/marsavic/gfxlab/Spectrum.java diff --git a/.idea/libraries/google_guava.xml b/.idea/libraries/google_guava.xml index 1d726c4..fad994d 100644 --- a/.idea/libraries/google_guava.xml +++ b/.idea/libraries/google_guava.xml @@ -2,13 +2,13 @@ - + - - - + + + diff --git a/.idea/misc.xml b/.idea/misc.xml index a4ad09f..ff07cd4 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/src/xyz/marsavic/gfxlab/Spectrum.java b/src/xyz/marsavic/gfxlab/Spectrum.java new file mode 100644 index 0000000..06d199f --- /dev/null +++ b/src/xyz/marsavic/gfxlab/Spectrum.java @@ -0,0 +1,93 @@ +package xyz.marsavic.gfxlab; + +import javafx.util.Pair; + +import java.util.Arrays; +import java.util.Comparator; + +@FunctionalInterface +public interface Spectrum { + static final double minWavelength = 380; + static final double maxWavelength = 750; + public double at(double wavelength); +} + +class DoublePairKeyComparator implements Comparator> { + @Override + public int compare(Pair o1, Pair o2) { + double k1 = o1.getKey(), k2 = o2.getKey(); + if (k1 > k2) + return 1; + else if (k1 < k2) { + return -1; + } else { + return 0; + } + } +} + +class SplineSpectrum implements Spectrum { + Pair[] samples; + double[] m; + + public SplineSpectrum(Pair[] samples) { + if (samples == null) { + throw new NullPointerException(); + } + this.samples = samples; + int n = samples.length; + + double[] d = new double[n - 1]; + m = new double[n]; + + + for (int i = 1; i < samples.length; i++) { + double h = samples[i].getKey() - samples[i - 1].getKey(); + if (h <= 0.0) + throw new IllegalArgumentException("Samples must have strictly increasing x coordinates."); + d[i] = (samples[i].getValue() - samples[i - 1].getValue()); + } + + m[0] = d[0]; + for (int i = 1; i < n - 1; i++) { + if (d[i] == 0.0) { + m[i] = 0.0; + m[i + 1] = 0.0; + } else { + double a = m[i] / d[i]; + double b = m[i + 1] / d[i]; + double h = a*a+b*b; + if (h > 9.0) { + double t = 3.0 / h; + m[i] = t * a * d[i]; + m[i + 1] = t * b * d[i]; + } + } + } + } + + @Override + public double at(double wavelength) { + final int n = samples.length; + + if (wavelength <= samples[0].getKey()) { + return samples[0].getValue(); + } + if (wavelength >= samples[n-1].getKey()) { + return samples[n-1].getValue(); + } + + Double.valueOf(wavelength); + int i = Arrays.binarySearch(samples, + new Pair(Double.valueOf(wavelength), null), + new DoublePairKeyComparator()); + if (i >= 0) { + return samples[i].getValue(); + } + i = -(i+1); + double h = samples[i+1].getKey() - samples[i].getKey(); + double t = (wavelength - samples[i].getKey()) / h; + return (samples[i].getValue() * (1 + 2*t) + h*m[i]*t) * (1 - t) * (1 - t) + + (samples[i+1].getValue() * (3 - 2*t) + h * m[i+1] * (t - 1)) * t * t; + } +} \ No newline at end of file