use of org.eazegraph.lib.models.Point2D in project EazeGraph by blackfizz.
the class ValueLineChart method onDataChanged.
/**
* Should be called after new data is inserted. Will be automatically called, when the view dimensions
* changed.
*
* Calculates various offsets and positions for different overlay features based on the graph settings.
* After the calculation the Path is generated as a normal path or cubic path (Based on 'egUseCubic' attribute).
*/
@Override
protected void onDataChanged() {
if (!mSeries.isEmpty()) {
int seriesCount = mSeries.size();
float maxValue = 0.f;
float minValue = Float.MAX_VALUE;
mNegativeValue = 0.f;
mNegativeOffset = 0.f;
mHasNegativeValues = false;
// calculate the maximum and minimum value present in data
for (ValueLineSeries series : mSeries) {
for (ValueLinePoint point : series.getSeries()) {
if (point.getValue() > maxValue)
maxValue = point.getValue();
if (point.getValue() < mNegativeValue)
mNegativeValue = point.getValue();
if (point.getValue() < minValue)
minValue = point.getValue();
}
}
// check if the standardvalue is greater than all other values
if (mShowStandardValues) {
for (StandardValue value : mStandardValues) {
if (value.getValue() > maxValue)
maxValue = value.getValue();
if (value.getValue() < mNegativeValue)
mNegativeValue = value.getValue();
if (value.getValue() < minValue)
minValue = value.getValue();
}
}
if (!mUseDynamicScaling) {
minValue = 0;
} else {
minValue *= mScalingFactor;
}
// check if values below zero were found
if (mNegativeValue < 0) {
mHasNegativeValues = true;
maxValue += (mNegativeValue * -1);
minValue = 0;
}
float heightMultiplier = mUsableGraphHeight / (maxValue - minValue);
// calculate the offset
if (mHasNegativeValues) {
mNegativeOffset = (mNegativeValue * -1) * heightMultiplier;
}
// calculate the y position for standardValue
if (mShowStandardValues) {
for (StandardValue value : mStandardValues) {
value.setY((int) (mGraphHeight - mNegativeOffset - ((value.getValue() - minValue) * heightMultiplier)));
}
}
for (ValueLineSeries series : mSeries) {
int seriesPointCount = series.getSeries().size();
// check if more than one point is available
if (seriesPointCount <= 1) {
Log.w(LOG_TAG, "More than one point should be available!");
} else {
float widthOffset = (float) mGraphWidth / (float) seriesPointCount;
widthOffset += widthOffset / seriesPointCount;
float currentOffset = 0;
series.setWidthOffset(widthOffset);
// used to store first point and set it later as ending point, if a graph fill is selected
float firstX = currentOffset;
float firstY = mGraphHeight - ((series.getSeries().get(0).getValue() - minValue) * heightMultiplier);
Path path = new Path();
path.moveTo(firstX, firstY);
series.getSeries().get(0).setCoordinates(new Point2D(firstX, firstY));
// If not then just draw basic lines
if (mUseCubic) {
Point2D P1 = new Point2D();
Point2D P2 = new Point2D();
Point2D P3 = new Point2D();
for (int i = 0; i < seriesPointCount - 1; i++) {
int i3 = (seriesPointCount - i) < 3 ? i + 1 : i + 2;
float offset2 = (seriesPointCount - i) < 3 ? mGraphWidth : currentOffset + widthOffset;
float offset3 = (seriesPointCount - i) < 3 ? mGraphWidth : currentOffset + (2 * widthOffset);
P1.setX(currentOffset);
P1.setY(mGraphHeight - ((series.getSeries().get(i).getValue() - minValue) * heightMultiplier));
P2.setX(offset2);
P2.setY(mGraphHeight - ((series.getSeries().get(i + 1).getValue() - minValue) * heightMultiplier));
Utils.calculatePointDiff(P1, P2, P1, mSecondMultiplier);
P3.setX(offset3);
P3.setY(mGraphHeight - ((series.getSeries().get(i3).getValue() - minValue) * heightMultiplier));
Utils.calculatePointDiff(P2, P3, P3, mFirstMultiplier);
currentOffset += widthOffset;
series.getSeries().get(i + 1).setCoordinates(new Point2D(P2.getX(), P2.getY()));
path.cubicTo(P1.getX(), P1.getY(), P2.getX(), P2.getY(), P3.getX(), P3.getY());
}
} else {
boolean first = true;
int count = 1;
for (ValueLinePoint point : series.getSeries()) {
if (first) {
first = false;
continue;
}
currentOffset += widthOffset;
if (count == seriesPointCount - 1) {
// to prevent a graph drop
if (currentOffset < mGraphWidth) {
currentOffset = mGraphWidth;
}
}
point.setCoordinates(new Point2D(currentOffset, mGraphHeight - ((point.getValue() - minValue) * heightMultiplier)));
path.lineTo(point.getCoordinates().getX(), point.getCoordinates().getY());
count++;
}
}
if (mUseOverlapFill) {
path.lineTo(mGraphWidth, mGraphHeight);
path.lineTo(0, mGraphHeight);
path.lineTo(firstX, firstY);
}
series.setPath(path);
}
}
if (calculateLegendBounds())
Utils.calculateLegendInformation(mSeries.get(0).getSeries(), 0, mGraphWidth, mLegendPaint);
// set the first point for the indicator
if (mShowIndicator && mSeries.size() == 1) {
int size = mSeries.get(0).getSeries().size();
int index;
// Only calculate if more than one point is available
if (size > 1) {
// position the indicator in the middle at the nearest value
if (size == 3) {
index = size / 2;
} else {
index = (size / 2) - 1;
}
mFocusedPoint = mSeries.get(0).getSeries().get(index);
mTouchedArea = mFocusedPoint.getCoordinates();
calculateValueTextHeight();
}
}
resetZoom(false);
}
super.onDataChanged();
}
Aggregations