using System.Diagnostics;
namespace LibNoise.Operator
{
///
/// Provides a noise module that outputs the value selected from one of two source
/// modules chosen by the output value from a control module. [OPERATOR]
///
public class Select : ModuleBase
{
#region Fields
private double _fallOff;
private double _raw;
private double _min = -1.0;
private double _max = 1.0;
#endregion
#region Constructors
///
/// Initializes a new instance of Select.
///
public Select()
: base(3)
{
}
///
/// Initializes a new instance of Select.
///
/// The first input module.
/// The second input module.
/// The controller module.
public Select(ModuleBase inputA, ModuleBase inputB, ModuleBase controller)
: base(3)
{
Modules[0] = inputA;
Modules[1] = inputB;
Modules[2] = controller;
}
///
/// Initializes a new instance of Select.
///
/// The minimum value.
/// The maximum value.
/// The falloff value at the edge transition.
/// The first input module.
/// The second input module.
public Select(double min, double max, double fallOff, ModuleBase inputA, ModuleBase inputB)
: this(inputA, inputB, null)
{
_min = min;
_max = max;
FallOff = fallOff;
}
#endregion
#region Properties
///
/// Gets or sets the controlling module.
///
public ModuleBase Controller
{
get { return Modules[2]; }
set
{
Debug.Assert(value != null);
Modules[2] = value;
}
}
///
/// Gets or sets the falloff value at the edge transition.
///
///
/// Called SetEdgeFallOff() on the original LibNoise.
///
public double FallOff
{
get { return _fallOff; }
set
{
var bs = _max - _min;
_raw = value;
_fallOff = (value > bs / 2) ? bs / 2 : value;
}
}
///
/// Gets or sets the maximum, and re-calculated the fall-off accordingly.
///
public double Maximum
{
get { return _max; }
set
{
_max = value;
FallOff = _raw;
}
}
///
/// Gets or sets the minimum, and re-calculated the fall-off accordingly.
///
public double Minimum
{
get { return _min; }
set
{
_min = value;
FallOff = _raw;
}
}
#endregion
#region Methods
///
/// Sets the bounds.
///
/// The minimum value.
/// The maximum value.
public void SetBounds(double min, double max)
{
Debug.Assert(min < max);
_min = min;
_max = max;
FallOff = _fallOff;
}
#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(Modules[1] != null);
Debug.Assert(Modules[2] != null);
var cv = Modules[2].GetValue(x, y, z);
if (_fallOff > 0.0)
{
double a;
if (cv < (_min - _fallOff))
{
return Modules[0].GetValue(x, y, z);
}
if (cv < (_min + _fallOff))
{
var lc = (_min - _fallOff);
var uc = (_min + _fallOff);
a = Utils.MapCubicSCurve((cv - lc) / (uc - lc));
return Utils.InterpolateLinear(Modules[0].GetValue(x, y, z),
Modules[1].GetValue(x, y, z), a);
}
if (cv < (_max - _fallOff))
{
return Modules[1].GetValue(x, y, z);
}
if (cv < (_max + _fallOff))
{
var lc = (_max - _fallOff);
var uc = (_max + _fallOff);
a = Utils.MapCubicSCurve((cv - lc) / (uc - lc));
return Utils.InterpolateLinear(Modules[1].GetValue(x, y, z),
Modules[0].GetValue(x, y, z), a);
}
return Modules[0].GetValue(x, y, z);
}
if (cv < _min || cv > _max)
{
return Modules[0].GetValue(x, y, z);
}
return Modules[1].GetValue(x, y, z);
}
#endregion
}
}