/*
* Trace2DArithmeticMean.java of project jchart2d, a trace
* that accumulates the latest n points added to a single point with the arithmetic
* mean value.
* Copyright 2004 - 2011 (C) Achim Westermann.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA*
* If you modify or optimize the code in a useful way please let me know.
* Achim.Westermann@gmx.de
*
*/
package info.monitorenter.gui.chart.traces.computing;
import info.monitorenter.gui.chart.ITracePoint2D;
import info.monitorenter.gui.chart.traces.ATrace2D;
import info.monitorenter.util.collections.IRingBuffer;
import info.monitorenter.util.collections.RingBufferArrayFast;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* A trace that accumulates the latest n points added to points with the
* arithmetic mean value.
* <p>
*
* This trace will not reduce the amount of n points added to one carrying the arithmetic mean but
* always add a point that has the average of the recent added n points.
* <p>
*
* Please note that this trace scan be used in two modes:
* <ol>
* <li>Stand alone: <br/>
* Add the <code>ITrace2D</code> implementation to a chart and add data points
* to it as normal.</li>
* <li>Computing trace: <br/>
* Add the <code>ITrace2D</code> implementation as a computing trace to an
* existing trace via
* <code>{@link info.monitorenter.gui.chart.ITrace2D#addComputingTrace(info.monitorenter.gui.chart.ITrace2D)}</code>
* and only add data points to the original trace. Add the computing trace to
* the same chart and updates of the original trace will be reflected on the
* computing trace as well.</li>
* </ol>
* <p>
*
* @author Achim Westermann
*
* @version $Revision: 1.15 $
*
* @since 7.0.0
*
*/
public class Trace2DArithmeticMean extends ATrace2D {
/** Generated <code>serialVersionUID</code>. */
private static final long serialVersionUID = -4365986306182830082L;
/** The buffer for the points about to be merged. */
private final IRingBuffer<ITracePoint2D> m_pointBuffer;
/** The internal list of points to render. */
private final List<ITracePoint2D> m_points = new LinkedList<ITracePoint2D>();
/**
* The amount of n recent points to buffer. private int m_pointBufferSize; /**
* Constructor with the given amount of points to merge into one point with
* their arithmetic mean.
* <p>
*
* @param arithmenticMeanSpan
* the amount of points to merge into one point with their arithmetic
* mean.
*/
public Trace2DArithmeticMean(final int arithmenticMeanSpan) {
super();
this.m_pointBuffer = new RingBufferArrayFast<ITracePoint2D>(arithmenticMeanSpan);
}
/**
* @see info.monitorenter.gui.chart.traces.ATrace2D#addPointInternal(info.monitorenter.gui.chart.ITracePoint2D)
*/
@Override
protected boolean addPointInternal(final ITracePoint2D p) {
this.m_pointBuffer.add(p);
final ITracePoint2D cumulate = this.getArithmeticMean();
final boolean result = this.m_points.add(cumulate);
this.firePointAdded(cumulate);
return result;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final Trace2DArithmeticMean other = (Trace2DArithmeticMean) obj;
if (this.m_pointBuffer == null) {
if (other.m_pointBuffer != null) {
return false;
}
} else if (!this.m_pointBuffer.equals(other.m_pointBuffer)) {
return false;
}
if (this.m_points == null) {
if (other.m_points != null) {
return false;
}
} else if (!this.m_points.equals(other.m_points)) {
return false;
}
return true;
}
/**
* Returns a point with the arithmetic mean values for x and y computed of the
* last n added points (n was constructor - given).
* <p>
*
* @return a point with the arithmetic mean values for x and y computed of the
* last n added points (n was constructor - given).
*/
private ITracePoint2D getArithmeticMean() {
double x = 0;
double y = 0;
ITracePoint2D result;
for (final ITracePoint2D point : this.m_pointBuffer) {
result = point;
x += result.getX();
y += result.getY();
}
int divisor = this.m_pointBuffer.size();
if (divisor == 0) {
divisor = 1;
}
y /= divisor;
x /= divisor;
result = this.getRenderer().getTracePointProvider().createTracePoint(x, y);
return result;
}
/**
* @see info.monitorenter.gui.chart.ITrace2D#getMaxSize()
*/
public int getMaxSize() {
return Integer.MAX_VALUE;
}
/**
* @see info.monitorenter.gui.chart.ITrace2D#getSize()
*/
public int getSize() {
return this.m_points.size();
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((this.m_pointBuffer == null) ? 0 : this.m_pointBuffer.hashCode());
result = prime * result + ((this.m_points == null) ? 0 : this.m_points.hashCode());
return result;
}
/**
* @see info.monitorenter.gui.chart.ITrace2D#isEmpty()
*/
public boolean isEmpty() {
return this.m_points.isEmpty();
}
/**
* @see info.monitorenter.gui.chart.ITrace2D#iterator()
*/
public Iterator<ITracePoint2D> iterator() {
return this.m_points.iterator();
}
/**
* @see info.monitorenter.gui.chart.traces.ATrace2D#removeAllPointsInternal()
*/
@Override
protected void removeAllPointsInternal() {
this.m_pointBuffer.clear();
this.m_points.clear();
}
/**
* @see info.monitorenter.gui.chart.traces.ATrace2D#removePointInternal(info.monitorenter.gui.chart.ITracePoint2D)
*/
@Override
protected ITracePoint2D removePointInternal(final ITracePoint2D point) {
final ITracePoint2D result = this.m_points.remove(0);
return result;
}
}