using System.Drawing; using System.Numerics; namespace WebmrAPI.Utils.Sequences { public abstract class OscillationGenerator : BaseGenerator { private int _segments = 1; private double _amplitude = 100.0; public double Amplitude { get => _amplitude; protected set => _amplitude = Math.Abs(value); } public int Segments { get => _segments; protected set => _segments = value < 1 ? 1 : value; } public override double Step { get; protected set; } protected abstract double FOffset { get; } public OscillationGenerator(T min, T max) : base(min, max) { } } public abstract class SawtoothGenerator : OscillationGenerator { protected override double FOffset { get { double s = (Progress * Segments) % 1.0; return (s < 0.5 ? s : (1.0 - s)) * 4.0 - 1.0; } } public SawtoothGenerator(T min, T max) : base(min, max) { } } public abstract class SineWaveGenerator : OscillationGenerator { protected override double FOffset { get => Math.Sin(Progress * (Segments * 2.0) * Math.PI); } public SineWaveGenerator(T min, T max) : base(min, max) { } } public abstract class SquareWaveGenerator : OscillationGenerator { protected override double FOffset { get => (Math.Floor(Progress * Segments) % 2 == 0) ? 1 : -1; } public SquareWaveGenerator(T min, T max) : base(min, max) { } } public sealed class SawtoothNumberGenerator : SawtoothGenerator, INumberGenerator where T : struct, INumber { public INumberGenerator Self { get => this; } public SawtoothNumberGenerator SetShapeFactor(double fShape) { FShape = fShape; return this; } public SawtoothNumberGenerator SetFadeFactor(double fade) { FFade = fade; return this; } public SawtoothNumberGenerator SetSegments(int count) { Segments = count; return this; } public SawtoothNumberGenerator SetAmplitude(double amplitude) { Amplitude = amplitude; return this; } protected override T Calc() { var offs = Amplitude * FOffset * Scale * ((Self.DMax - Self.DMin) / 2.0); return T.CreateChecked(Math.Clamp(Self.Mean + offs, Self.DMin, Self.DMax)); } public SawtoothNumberGenerator(T min, T max, int count = 10) : base(min, max) { Step = CalcStepByCount(count); Amplitude = 1.0; // Set default } } public sealed class SineWaveNumberGenerator : SineWaveGenerator, INumberGenerator where T : struct, INumber { public INumberGenerator Self { get => this; } public SineWaveNumberGenerator SetShapeFactor(double fShape) { FShape = fShape; return this; } public SineWaveNumberGenerator SetFadeFactor(double fade) { FFade = fade; return this; } public SineWaveNumberGenerator SetSegments(int count) { Segments = count; return this; } public SineWaveNumberGenerator SetAmplitude(double amplitude) { Amplitude = amplitude; return this; } protected override T Calc() { var offs = Amplitude * FOffset * Scale * ((Self.DMax - Self.DMin) / 2.0); return T.CreateChecked(Math.Clamp(Self.Mean + offs, Self.DMin, Self.DMax)); } public SineWaveNumberGenerator(T min, T max, int count = 10) : base(min, max) { Step = CalcStepByCount(count); Amplitude = 1.0; // Set default } } public sealed class SquareWaveNumberGenerator : SquareWaveGenerator, INumberGenerator where T : struct, INumber { public INumberGenerator Self { get => this; } public SquareWaveNumberGenerator SetShapeFactor(double fShape) { FShape = fShape; return this; } public SquareWaveNumberGenerator SetFadeFactor(double fade) { FFade = fade; return this; } public SquareWaveNumberGenerator SetSegments(int count) { Segments = count; return this; } public SquareWaveNumberGenerator SetAmplitude(double amplitude) { Amplitude = amplitude; return this; } protected override T Calc() { var offs = Amplitude * FOffset * Scale * ((Self.DMax - Self.DMin) / 2.0); return T.CreateChecked(Math.Clamp(Self.Mean + offs, Self.DMin, Self.DMax)); } public SquareWaveNumberGenerator(T min, T max, int count = 10) : base(min, max) { Step = CalcStepByCount(count); Amplitude = 1.0; // Set default } } public sealed class SawtoothPointGenerator : SawtoothGenerator, IPointGenerator { private readonly double _pAngle; public IPointGenerator Self { get => this; } public SawtoothPointGenerator SetShapeFactor(double fShape) { FShape = fShape; return this; } public SawtoothPointGenerator SetFadeFactor(double fade) { FFade = fade; return this; } public SawtoothPointGenerator SetSegments(int count) { Segments = count; return this; } public SawtoothPointGenerator SetAmplitude(double amplitude) { Amplitude = amplitude; return this; } protected override Point Calc() { return IPointGenerator.CalcPoint(Self.LinearX, Self.LinearY, Amplitude * FOffset * Scale, _pAngle); } public static SawtoothPointGenerator CreateByCount(Point start, Point end, int count) { return new SawtoothPointGenerator(start, end) { Step = CalcStepByCount(count) }; } public static SawtoothPointGenerator CreateByStepSize(Point start, Point end, double pxPerStep = 5) { return new SawtoothPointGenerator(start, end, pxPerStep); } public SawtoothPointGenerator(Point start, Point end, double pxPerStep = 5) : this(start, end) { Step = pxPerStep / IPointGenerator.CalcDistance(start, end); } private SawtoothPointGenerator(Point start, Point end) : base(start, end) { _pAngle = IPointGenerator.CalcAngle(start, end) + Math.PI / 2.0; } } public sealed class SineWavePointGenerator : SineWaveGenerator, IPointGenerator { private readonly double _pAngle; public IPointGenerator Self { get => this; } public SineWavePointGenerator SetShapeFactor(double fShape) { FShape = fShape; return this; } public SineWavePointGenerator SetFadeFactor(double fade) { FFade = fade; return this; } public SineWavePointGenerator SetSegments(int count) { Segments = count; return this; } public SineWavePointGenerator SetAmplitude(double amplitude) { Amplitude = amplitude; return this; } protected override Point Calc() { return IPointGenerator.CalcPoint(Self.LinearX, Self.LinearY, Amplitude * FOffset * Scale, _pAngle); } public static SineWavePointGenerator CreateByCount(Point start, Point end, int count) { return new SineWavePointGenerator(start, end) { Step = CalcStepByCount(count) }; } public static SineWavePointGenerator CreateByStepSize(Point start, Point end, double pxPerStep = 5) { return new SineWavePointGenerator(start, end, pxPerStep); } public SineWavePointGenerator(Point start, Point end, double pxPerStep = 5) : this(start, end) { Step = pxPerStep / IPointGenerator.CalcDistance(start, end); } private SineWavePointGenerator(Point start, Point end) : base(start, end) { _pAngle = IPointGenerator.CalcAngle(start, end) + Math.PI / 2.0; } } public sealed class SquareWavePointGenerator : SquareWaveGenerator, IPointGenerator { private readonly double _pAngle; public IPointGenerator Self { get => this; } public SquareWavePointGenerator SetShapeFactor(double fShape) { FShape = fShape; return this; } public SquareWavePointGenerator SetFadeFactor(double fade) { FFade = fade; return this; } public SquareWavePointGenerator SetSegments(int count) { Segments = count; return this; } public SquareWavePointGenerator SetAmplitude(double amplitude) { Amplitude = amplitude; return this; } protected override Point Calc() { return IPointGenerator.CalcPoint(Self.LinearX, Self.LinearY, Amplitude * FOffset * Scale, _pAngle); } public static SquareWavePointGenerator CreateByCount(Point start, Point end, int count) { return new SquareWavePointGenerator(start, end) { Step = CalcStepByCount(count) }; } public static SquareWavePointGenerator CreateByStepSize(Point start, Point end, double pxPerStep = 5) { return new SquareWavePointGenerator(start, end, pxPerStep); } public SquareWavePointGenerator(Point start, Point end, double pxPerStep = 5) : this(start, end) { Step = pxPerStep / IPointGenerator.CalcDistance(start, end); } private SquareWavePointGenerator(Point start, Point end) : base(start, end) { _pAngle = IPointGenerator.CalcAngle(start, end) + Math.PI / 2.0; } } }