📄 dynamictimeseriescollection.java
字号:
*
* @return the series count.
*/
public int getSeriesCount() {
return seriesCount;
}
/**
* Returns the number of items in a series.
* <p>
* For this implementation, all series have the same number of items.
*
* @param series the series index (zero-based).
*
* @return The item count.
*/
public int getItemCount(int series) { // all arrays of equal length, so ignore the argument:
return historyCount;
}
// Methods for managing the FIFO's:
/**
* Re-map an index, for use in retrieving data.
*
* @param toFetch the index.
*
* @return The translated index.
*/
protected int translateGet(int toFetch) {
if (oldestAt == 0) {
return toFetch; // no translation needed
}
// else [implicit here]
int newIndex = toFetch + oldestAt;
if (newIndex >= historyCount) {
newIndex -= historyCount;
}
return newIndex;
}
/**
* Returns the actual index to a time offset by "delta" from newestAt.
*
* @param delta the delta.
*
* @return The offset.
*/
public int offsetFromNewest(int delta) {
return wrapOffset(newestAt + delta);
}
/**
* ??
*
* @param delta ??
*
* @return The offset.
*/
public int offsetFromOldest(int delta) {
return wrapOffset(oldestAt + delta);
}
/**
* ??
*
* @param protoIndex the index.
*
* @return The offset.
*/
protected int wrapOffset(int protoIndex) {
int tmp = protoIndex;
if (tmp >= historyCount) {
tmp -= historyCount;
}
else if (tmp < 0) {
tmp += historyCount;
}
return tmp;
}
/**
* Adjust the array offset as needed when a new time-period is added:
* Increments the indices "oldestAt" and "newestAt", mod(array length),
* zeroes the series values at newestAt, returns the new TimePeriod.
*
* @return The new time period.
*/
public synchronized RegularTimePeriod advanceTime() {
int s = 0; // index to successive 'series'
RegularTimePeriod nextInstant = pointsInTime[newestAt].next();
newestAt = oldestAt; // newestAt takes value previously held by oldestAT
/*** The next 10 lines or so should be expanded if data can be negative ***/
// if the oldest data contained a maximum Y-value, invalidate the stored
// Y-max and Y-range data:
boolean extremaChanged = false;
float oldMax = 0.0f;
if (maxValue != null) {
oldMax = maxValue.floatValue();
}
for (s = 0; s < getSeriesCount(); s++) {
if (valueHistory[s].getData(oldestAt) == oldMax) {
extremaChanged = true;
}
if (extremaChanged) {
break;
}
} /*** If data can be < 0, add code here to check the minimum **/
if (extremaChanged) {
invalidateRangeInfo();
}
// wipe the next (about to be used) set of data slots
float wiper = (float) 0.0;
for (s = 0; s < getSeriesCount(); s++) {
valueHistory[s].enterData(newestAt, wiper);
}
// Update the array of TimePeriods:
pointsInTime[newestAt] = nextInstant;
// Now advance "oldestAt", wrapping at end of the array
oldestAt++;
if (oldestAt >= historyCount) {
oldestAt = 0;
}
// Update the domain limits:
long startL = domainStart.longValue(); //(time is kept in msec)
domainStart = new Long(startL + deltaTime);
long endL = domainEnd.longValue();
domainEnd = new Long(endL + deltaTime);
domainRange = new Range((double) startL, (double) endL);
fireSeriesChanged();
return nextInstant;
}
// If data can be < 0, the next 2 methods should be modified
/**
* Invalidates the range info.
*/
public void invalidateRangeInfo() {
maxValue = null;
valueRange = null;
}
/**
* Returns the maximum value.
*
* @return The maximum value.
*/
protected float findMaxValue() {
float max = 0.0f;
float tmp = 0.0f;
for (int s = 0; s < getSeriesCount(); s++) {
for (int i = 0; i < historyCount; i++) {
tmp = getY(s, i);
if (tmp > max) {
max = tmp;
}
}
}
return max;
}
/** End, positive-data-only code **/
/**
* Returns the index of the oldest data item.
*
* @return The index.
*/
public int getOldestIndex() {
return oldestAt;
}
/**
* Returns the index of the newest data item.
*
* @return The index.
*/
public int getNewestIndex() {
return newestAt;
}
// appendData() writes new data at the index position given by newestAt/
// When adding new data dynamically, use advanceTime(), followed by this:
/**
* Appends new data.
*
* @param newData the data.
*/
public void appendData(float[] newData) {
int nDataPoints = newData.length;
if (nDataPoints > valueHistory.length) {
throw new IllegalArgumentException(
"DynamicTimeSeriesCollection.appendData(...): more data than series to put them in");
}
int s; // index to select the "series"
for (s = 0; s < nDataPoints; s++) {
// check whether the "valueHistory" array member exists; if not, create them:
if (valueHistory[s] == null) {
valueHistory[s] = new ValueSequence(historyCount);
}
valueHistory[s].enterData(newestAt, newData[s]);
}
fireSeriesChanged();
}
/**
* Returns the newest time.
*
* @return The newest time.
*/
public RegularTimePeriod getNewestTime() {
return pointsInTime[newestAt];
}
/**
* Returns the oldest time.
*
* @return The oldest time.
*/
public RegularTimePeriod getOldestTime() {
return pointsInTime[oldestAt];
}
/**
* Returns the x-value.
*
* @param series the series index (zero-based).
* @param item the item index (zero-based).
*
* @return The value.
*/
// getXxx() ftns can ignore the "series" argument:
// Don't synchronize this!! Instead, synchronize the loop that calls it.
public Number getXValue(int series, int item) {
RegularTimePeriod tp = null;
tp = pointsInTime[translateGet(item)];
return new Long(getX(tp));
}
/**
* Returns the y-value.
*
* @param series the series index (zero-based).
* @param item the item index (zero-based).
*
* @return The value.
*/
public float getY(int series, int item) { // Don't synchronize this!!
ValueSequence values = valueHistory[series]; // Instead, synchronize the loop that
return values.getData(translateGet(item)); // calls it.
}
/**
* Returns the y-value.
*
* @param series the series index (zero-based).
* @param item the item index (zero-based).
*
* @return The value.
*/
public Number getYValue(int series, int item) {
return new Float(getY(series, item));
}
/**
* Returns the start x-value.
*
* @param series the series index (zero-based).
* @param item the item index (zero-based).
*
* @return The value.
*/
public Number getStartXValue(int series, int item) {
RegularTimePeriod tp = null;
tp = pointsInTime[translateGet(item)];
return new Long(tp.getFirstMillisecond(workingCalendar));
}
/**
* Returns the end x-value.
*
* @param series the series index (zero-based).
* @param item the item index (zero-based).
*
* @return The value.
*/
public Number getEndXValue(int series, int item) {
RegularTimePeriod tp = pointsInTime[translateGet(item)];
return new Long(tp.getLastMillisecond(workingCalendar));
}
/**
* Returns the start y-value.
*
* @param series the series index (zero-based).
* @param item the item index (zero-based).
*
* @return The value.
*/
public Number getStartYValue(int series, int item) {
return getYValue(series, item);
}
/**
* Returns the end y-value.
*
* @param series the series index (zero-based).
* @param item the item index (zero-based).
*
* @return The value.
*/
public Number getEndYValue(int series, int item) {
return getYValue(series, item);
}
/* // "Extras" found useful when analyzing/verifying class behavior:
public Number getUntranslatedXValue(int series, int item)
{
return super.getXValue(series, item);
}
public float getUntranslatedY(int series, int item)
{
return super.getY(series, item);
} */
/**
* Returns the name of a series.
*
* @param series the series index (zero-based).
*
* @return The name.
*/
public String getSeriesName(int series) {
return seriesNames[series];
}
/**
* Sends a {@link SeriesChangeEvent} to all registered listeners.
*/
protected void fireSeriesChanged() {
seriesChanged(new SeriesChangeEvent(this));
}
// The next 3 functions override the base-class implementation of
// the DomainInfo interface. Using saved limits (updated by
// each updateTime() call), improves performance.
//
/**
* Returns the range of values for the domain.
*
* @return The range.
*/
public Range getDomainRange() {
if (domainRange == null) {
findDomainLimits();
}
return domainRange;
}
/**
* Returns the minimum value in the dataset (or null if all the values in
* the domain are null).
*
* @return the minimum value.
*/
public Number getMinimumDomainValue() {
return domainStart; // a Long kept updated by advanceTime()
}
/**
* Returns the maximum value in the dataset (or null if all the values in
* the domain are null).
*
* @return the maximum value.
*/
public Number getMaximumDomainValue() {
return domainEnd; // a Long kept updated by advanceTime()
}
/**
* Returns the x-value for a time period.
*
* @param period the period.
*
* @return The x-value.
*/
private long getX(RegularTimePeriod period) {
long result = 0L;
switch (position) {
case (START) : result = period.getFirstMillisecond(workingCalendar); break;
case (MIDDLE) : result = period.getMiddleMillisecond(workingCalendar); break;
case (END) : result = period.getLastMillisecond(workingCalendar); break;
default: result = period.getMiddleMillisecond(workingCalendar);
}
return result;
}
// The next 3 functions implement the RangeInfo interface.
// Using saved limits (updated by each updateTime() call) significantly
// improves performance. WARNING: this code makes the simplifying assumption
// that data is never negative. Expand as needed for the general case.
/**
* Returns the minimum range value.
*
* @return The minimum range value.
*/
public Number getMinimumRangeValue() {
return minValue;
}
/**
* Returns the maximum range value.
*
* @return The maximum range value.
*/
public Number getMaximumRangeValue() {
if (maxValue == null) {
maxValue = new Float(findMaxValue());
}
return maxValue;
}
/**
* Returns the value range.
*
* @return The range.
*/
public Range getValueRange() {
if (valueRange == null) {
Float maxV = (Float) getMaximumRangeValue();
double max = maxV.doubleValue();
valueRange = new Range(0.0, max);
}
return valueRange;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -