Add Spectrum class with an implementation

This commit is contained in:
kappa 2023-09-23 18:26:49 +02:00
parent 8b512a5604
commit 70f01a69c4
3 changed files with 98 additions and 5 deletions

View file

@ -2,13 +2,13 @@
<library name="google.guava" type="repository"> <library name="google.guava" type="repository">
<properties maven-id="com.google.guava:guava:RELEASE" /> <properties maven-id="com.google.guava:guava:RELEASE" />
<CLASSES> <CLASSES>
<root url="jar://$PROJECT_DIR$/lib/guava-31.1-jre.jar!/" /> <root url="jar://$PROJECT_DIR$/lib/guava-32.1.2-jre.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/failureaccess-1.0.1.jar!/" /> <root url="jar://$PROJECT_DIR$/lib/failureaccess-1.0.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar!/" /> <root url="jar://$PROJECT_DIR$/lib/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/jsr305-3.0.2.jar!/" /> <root url="jar://$PROJECT_DIR$/lib/jsr305-3.0.2.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/checker-qual-3.12.0.jar!/" /> <root url="jar://$PROJECT_DIR$/lib/checker-qual-3.33.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/error_prone_annotations-2.11.0.jar!/" /> <root url="jar://$PROJECT_DIR$/lib/error_prone_annotations-2.18.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/j2objc-annotations-1.3.jar!/" /> <root url="jar://$PROJECT_DIR$/lib/j2objc-annotations-2.8.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES /> <SOURCES />

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_19" default="true" project-jdk-name="liberica-19" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_20" default="true" project-jdk-name="liberica-20" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>

View file

@ -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<Pair<Double, Double>> {
@Override
public int compare(Pair<Double, Double> o1, Pair<Double, Double> 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<Double, Double>[] samples;
double[] m;
public SplineSpectrum(Pair<Double, Double>[] 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, Double>(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;
}
}