![JAR search and dependency download from the Maven repository](/logo.png)
com.flowpowered.noise.module.modifier.Curve Maven / Gradle / Ivy
/*
* This file is part of Flow Noise, licensed under the MIT License (MIT).
*
* Copyright (c) 2013 Flow Powered
* Original libnoise in C++ by Jason Bevins
* jlibnoise Java port by Garrett Fleenor
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.flowpowered.noise.module.modifier;
import java.util.ArrayList;
import java.util.List;
import com.flowpowered.noise.Utils;
import com.flowpowered.noise.exception.NoModuleException;
import com.flowpowered.noise.module.Module;
public class Curve extends Module {
private final List controlPoints = new ArrayList<>();
public Curve() {
super(1);
}
public void addControlPoint(double inputValue, double outputValue) {
int index = findInsertionPos(inputValue);
insertAtPos(index, inputValue, outputValue);
}
public ControlPoint[] getControlPoints() {
return (ControlPoint[]) controlPoints.toArray();
}
public void clearAllControlPoints() {
controlPoints.clear();
}
private int findInsertionPos(double inputValue) {
int insertionPos;
for (insertionPos = 0; insertionPos < controlPoints.size(); insertionPos++) {
if (inputValue < controlPoints.get(insertionPos).inputValue) {
// We found the array index in which to insert the new control point.
// Exit now.
break;
} else if (inputValue == controlPoints.get(insertionPos).inputValue) {
// Each control point is required to contain a unique input value, so
// throw an exception.
throw new IllegalArgumentException("inputValue must be unique");
}
}
return insertionPos;
}
private void insertAtPos(int insertionPos, double inputValue, double outputValue) {
ControlPoint newPoint = new ControlPoint();
newPoint.inputValue = inputValue;
newPoint.outputValue = outputValue;
controlPoints.add(insertionPos, newPoint);
}
@Override
public int getSourceModuleCount() {
return 1;
}
@Override
public double getValue(double x, double y, double z) {
if (sourceModule[0] == null) {
throw new NoModuleException();
}
if (controlPoints.size() < 4) {
throw new RuntimeException("Curve module must have at least 4 control points");
}
// Get the output value from the source module.
double sourceModuleValue = sourceModule[0].getValue(x, y, z);
// Find the first element in the control point array that has an input value
// larger than the output value from the source module.
int indexPos;
for (indexPos = 0; indexPos < controlPoints.size(); indexPos++) {
if (sourceModuleValue < controlPoints.get(indexPos).inputValue) {
break;
}
}
// Find the four nearest control points so that we can perform cubic
// interpolation.
int index0 = Utils.clamp(indexPos - 2, 0, controlPoints.size() - 1);
int index1 = Utils.clamp(indexPos - 1, 0, controlPoints.size() - 1);
int index2 = Utils.clamp(indexPos, 0, controlPoints.size() - 1);
int index3 = Utils.clamp(indexPos + 1, 0, controlPoints.size() - 1);
// If some control points are missing (which occurs if the value from the
// source module is greater than the largest input value or less than the
// smallest input value of the control point array), get the corresponding
// output value of the nearest control point and exit now.
if (index1 == index2) {
return controlPoints.get(indexPos).outputValue;
}
// Compute the alpha value used for cubic interpolation.
double input0 = controlPoints.get(indexPos).inputValue;
double input1 = controlPoints.get(indexPos).inputValue;
double alpha = (sourceModuleValue - input0) / (input1 - input0);
// Now perform the cubic interpolation given the alpha value.
return Utils.cubicInterp(controlPoints.get(index0).outputValue, controlPoints.get(index1).outputValue, controlPoints.get(index2).outputValue, controlPoints.get(index3).outputValue, alpha);
}
public static class ControlPoint {
private double inputValue;
private double outputValue;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy