using System.Collections.Generic;
using UnityEngine;
using Debug = System.Diagnostics.Debug;
namespace LibNoise.Operator
{
///
/// Provides a noise module that maps the output value from a source module onto an
/// arbitrary function curve. [OPERATOR]
///
public class Curve : ModuleBase
{
#region Fields
private readonly List> _data = new List>();
#endregion
#region Constructors
///
/// Initializes a new instance of Curve.
///
public Curve()
: base(1)
{
}
///
/// Initializes a new instance of Curve.
///
/// The input module.
public Curve(ModuleBase input)
: base(1)
{
Modules[0] = input;
}
#endregion
#region Properties
///
/// Gets the number of control points.
///
public int ControlPointCount
{
get { return _data.Count; }
}
///
/// Gets the list of control points.
///
public List> ControlPoints
{
get { return _data; }
}
#endregion
#region Methods
///
/// Adds a control point to the curve.
///
/// The curves input value.
/// The curves output value.
public void Add(double input, double output)
{
var kvp = new KeyValuePair(input, output);
if (!_data.Contains(kvp))
{
_data.Add(kvp);
}
_data.Sort(
delegate(KeyValuePair lhs, KeyValuePair rhs)
{
return lhs.Key.CompareTo(rhs.Key);
});
}
///
/// Clears the control points.
///
public void Clear()
{
_data.Clear();
}
#endregion
#region ModuleBase Members
///
/// Returns the output value for the given input coordinates.
///
/// The input coordinate on the x-axis.
/// The input coordinate on the y-axis.
/// The input coordinate on the z-axis.
/// The resulting output value.
public override double GetValue(double x, double y, double z)
{
Debug.Assert(Modules[0] != null);
Debug.Assert(ControlPointCount >= 4);
var smv = Modules[0].GetValue(x, y, z);
int ip;
for (ip = 0; ip < _data.Count; ip++)
{
if (smv < _data[ip].Key)
{
break;
}
}
var i0 = Mathf.Clamp(ip - 2, 0, _data.Count - 1);
var i1 = Mathf.Clamp(ip - 1, 0, _data.Count - 1);
var i2 = Mathf.Clamp(ip, 0, _data.Count - 1);
var i3 = Mathf.Clamp(ip + 1, 0, _data.Count - 1);
if (i1 == i2)
{
return _data[i1].Value;
}
//double ip0 = _data[i1].Value;
//double ip1 = _data[i2].Value;
var ip0 = _data[i1].Key;
var ip1 = _data[i2].Key;
var a = (smv - ip0) / (ip1 - ip0);
return Utils.InterpolateCubic(_data[i0].Value, _data[i1].Value, _data[i2].Value,
_data[i3].Value, a);
}
#endregion
}
}