dynamictimeseriescollection.java
来自「JfreeChart 常用图表例子」· Java 代码 · 共 974 行 · 第 1/3 页
JAVA
974 行
this.workingCalendar ); long nextL = this.pointsInTime[1].getFirstMillisecond( this.workingCalendar ); this.deltaTime = nextL - oldestL; this.oldestAt = 0; this.newestAt = this.historyCount - 1; findDomainLimits(); return this.deltaTime; } /** * Finds the domain limits. Note: this doesn't need to be synchronized * because it's called from within another method that already is. */ protected void findDomainLimits() { long startL = getOldestTime().getFirstMillisecond(this.workingCalendar); long endL; if (this.domainIsPointsInTime) { endL = getNewestTime().getFirstMillisecond(this.workingCalendar); } else { endL = getNewestTime().getLastMillisecond(this.workingCalendar); } this.domainStart = new Long(startL); this.domainEnd = new Long(endL); this.domainRange = new Range(startL, endL); } /** * Returns the x position type (START, MIDDLE or END). * * @return The x position type. */ public int getPosition() { return this.position; } /** * Sets the x position type (START, MIDDLE or END). * * @param position The x position type. */ public void setPosition(int position) { this.position = position; } /** * Adds a series to the dataset. Only the y-values are supplied, the * x-values are specified elsewhere. * * @param values the y-values. * @param seriesNumber the series index (zero-based). * @param seriesKey the series key. * * Use this as-is during setup only, or add the synchronized keyword around * the copy loop. */ public void addSeries(float[] values, int seriesNumber, Comparable seriesKey) { invalidateRangeInfo(); int i; if (values == null) { throw new IllegalArgumentException("TimeSeriesDataset.addSeries(): " + "cannot add null array of values."); } if (seriesNumber >= this.valueHistory.length) { throw new IllegalArgumentException("TimeSeriesDataset.addSeries(): " + "cannot add more series than specified in c'tor"); } if (this.valueHistory[seriesNumber] == null) { this.valueHistory[seriesNumber] = new ValueSequence(this.historyCount); this.seriesCount++; } // But if that series array already exists, just overwrite its contents // Avoid IndexOutOfBoundsException: int srcLength = values.length; int copyLength = this.historyCount; boolean fillNeeded = false; if (srcLength < this.historyCount) { fillNeeded = true; copyLength = srcLength; } //{ for (i = 0; i < copyLength; i++) { // deep copy from values[], caller // can safely discard that array this.valueHistory[seriesNumber].enterData(i, values[i]); } if (fillNeeded) { for (i = copyLength; i < this.historyCount; i++) { this.valueHistory[seriesNumber].enterData(i, 0.0f); } } //} if (seriesKey != null) { this.seriesKeys[seriesNumber] = seriesKey; } fireSeriesChanged(); } /** * Sets the name of a series. If planning to add values individually. * * @param seriesNumber the series. * @param key the new key. */ public void setSeriesKey(int seriesNumber, Comparable key) { this.seriesKeys[seriesNumber] = key; } /** * Adds a value to a series. * * @param seriesNumber the series index. * @param index ??. * @param value the value. */ public void addValue(int seriesNumber, int index, float value) { invalidateRangeInfo(); if (seriesNumber >= this.valueHistory.length) { throw new IllegalArgumentException( "TimeSeriesDataset.addValue(): series #" + seriesNumber + "unspecified in c'tor" ); } if (this.valueHistory[seriesNumber] == null) { this.valueHistory[seriesNumber] = new ValueSequence(this.historyCount); this.seriesCount++; } // But if that series array already exists, just overwrite its contents //synchronized(this) //{ this.valueHistory[seriesNumber].enterData(index, value); //} fireSeriesChanged(); } /** * Returns the number of series in the collection. * * @return The series count. */ public int getSeriesCount() { return this.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 equal length, // so ignore argument: return this.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 (this.oldestAt == 0) { return toFetch; // no translation needed } // else [implicit here] int newIndex = toFetch + this.oldestAt; if (newIndex >= this.historyCount) { newIndex -= this.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(this.newestAt + delta); } /** * ?? * * @param delta ?? * * @return The offset. */ public int offsetFromOldest(int delta) { return wrapOffset(this.oldestAt + delta); } /** * ?? * * @param protoIndex the index. * * @return The offset. */ protected int wrapOffset(int protoIndex) { int tmp = protoIndex; if (tmp >= this.historyCount) { tmp -= this.historyCount; } else if (tmp < 0) { tmp += this.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() { RegularTimePeriod nextInstant = this.pointsInTime[this.newestAt].next(); this.newestAt = this.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 (this.maxValue != null) { oldMax = this.maxValue.floatValue(); } for (int s = 0; s < getSeriesCount(); s++) { if (this.valueHistory[s].getData(this.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 (int s = 0; s < getSeriesCount(); s++) { this.valueHistory[s].enterData(this.newestAt, wiper); } // Update the array of TimePeriods: this.pointsInTime[this.newestAt] = nextInstant; // Now advance "oldestAt", wrapping at end of the array this.oldestAt++; if (this.oldestAt >= this.historyCount) { this.oldestAt = 0; } // Update the domain limits: long startL = this.domainStart.longValue(); //(time is kept in msec) this.domainStart = new Long(startL + this.deltaTime); long endL = this.domainEnd.longValue(); this.domainEnd = new Long(endL + this.deltaTime); this.domainRange = new Range(startL, endL); fireSeriesChanged(); return nextInstant; } // If data can be < 0, the next 2 methods should be modified /** * Invalidates the range info. */ public void invalidateRangeInfo() { this.maxValue = null; this.valueRange = null; } /** * Returns the maximum value. * * @return The maximum value. */ protected double findMaxValue() { double max = 0.0f; for (int s = 0; s < getSeriesCount(); s++) { for (int i = 0; i < this.historyCount; i++) { double tmp = getYValue(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 this.oldestAt; } /**
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?