@Override public String toString() { return new StringBuilder().append("{f(x) = ") .append(getAmplitude()).append(" * ") .append("sin(x * ").append(getFrequency()) .append(" * 2pi - pi * ").append(getPhaseShift()) .append(") + ").append(getHeight()).append("}") .toString(); }
@Override public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof IntensityFunctions.SineIntensity) { IntensityFunctions.SineIntensity that = (IntensityFunctions.SineIntensity) o; return (Double.doubleToLongBits(this.amplitude) == Double.doubleToLongBits(that.getAmplitude())) && (Double.doubleToLongBits(this.frequency) == Double.doubleToLongBits(that.getFrequency())) && (Double.doubleToLongBits(this.height) == Double.doubleToLongBits(that.getHeight())) && (Double.doubleToLongBits(this.phaseShift) == Double.doubleToLongBits(that.getPhaseShift())); } return false; }
@Override public Double apply(@Nullable Double x) { if (x == null) { throw new IllegalArgumentException(); } return Math.max(0d, getAmplitude() * Math.sin(x * getFrequency() * TWO_PI - Math.PI * getPhaseShift()) + getHeight()); }
IntensityFunction build(long seed) { if (area.isPresent()) { final SineIntensity ins = SineIntensity.create(this, seed); // first compute current area final double a = ins.area(); // compute factor to adapt amplitude and height final double factor = area.get() / a; // store values final StochasticSupplier<Double> ampl = amplitudeSup; final StochasticSupplier<Double> hei = heightSup; // temporarily overwrite values amplitudeSup = constant(ins.getAmplitude() * factor); heightSup = constant(ins.getHeight() * factor); final SineIntensity si = SineIntensity.create(this, seed); // restore values amplitudeSup = ampl; heightSup = hei; return si; } return SineIntensity.create(this, seed); }
/** * Computes the area under this sine function and above y=0 in the range * [0,period). Where period is defined as <code>1/frequency</code>. * @return The computed area. */ public double area() { // in this computation the phase shift is ignored as it doesn't have any // effect for one period. final double a = getAmplitude(); final double b = getHeight(); final double c = getFrequency(); final double[] roots = roots(); final double d = roots[0]; final double e = roots[1]; return a * Math.sin(Math.PI * c * (d - e)) * Math.sin(HALF_PI - Math.PI * c * (d + e)) / (Math.PI * c) + b * (e - d); }
double[] roots() { final double a = getAmplitude(); // we need to cap height since if it is higher there are no roots final double b = Math.min(getHeight(), a); final double c = getFrequency(); final double n1 = -1; final double n2 = 0; final double common = Math.asin(b / a) / (TWO_PI * c); final double rootA = -ONE_FOURTH / c + common - n1 / c; final double rootB = ONE_FOURTH / c - common - n2 / c; if (rootA > rootB) { return new double[] {rootB, rootA}; } return new double[] {rootA, rootB}; }
@Override public double getMax() { return getAmplitude() + getHeight(); }