Graph height addeed

This commit is contained in:
Sergey Solovyev 2013-01-20 22:01:31 +04:00
parent 41fac69906
commit 1a861b6403
10 changed files with 209 additions and 98 deletions

View File

@ -317,6 +317,8 @@
<string name="cpp_plot_range">Graph range</string>
<string name="cpp_plot_range_x_min">X Min</string>
<string name="cpp_plot_range_x_max">X Max</string>
<string name="cpp_plot_range_y_min">Y Min</string>
<string name="cpp_plot_range_y_max">Y Max</string>
<string name="cpp_invalid_number">Invalid number!</string>
<string name="cpp_plot_boundaries_should_differ">Graph boundaries should not be the same!</string>
<string name="cpp_apply">Apply</string>

View File

@ -53,6 +53,51 @@
</LinearLayout>
</LinearLayout>
<LinearLayout
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:orientation="horizontal"
a:baselineAligned="false">
<LinearLayout
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_weight="1"
a:orientation="vertical">
<TextView
a:text="@string/cpp_plot_range_y_min"
a:layout_width="match_parent"
a:layout_height="wrap_content" />
<EditText
a:id="@+id/cpp_plot_range_y_min_editext"
a:inputType="numberDecimal|numberSigned"
a:layout_width="match_parent"
a:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_weight="1"
a:orientation="vertical">
<TextView
a:text="@string/cpp_plot_range_y_max"
a:layout_width="match_parent"
a:layout_height="wrap_content" />
<EditText
a:id="@+id/cpp_plot_range_y_max_editext"
a:inputType="numberDecimal|numberSigned"
a:layout_width="match_parent"
a:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<Button

View File

@ -9,6 +9,7 @@ import android.view.View;
import android.widget.Scroller;
import android.widget.ZoomButtonsController;
import org.jetbrains.annotations.NotNull;
import org.solovyev.common.definitions.Pair;
import org.solovyev.common.math.Point2d;
import java.text.DecimalFormat;
@ -186,8 +187,9 @@ public class CalculatorGraph2dView extends View implements GraphView {
if (!graphViewHelper.getPlotFunctions().isEmpty()) {
if (scroller.computeScrollOffset()) {
final float ratio = dimensions.getGraphToViewRatio();
dimensions.setXY(scroller.getCurrX() * ratio, scroller.getCurrY() * ratio);
final float xScale = dimensions.getXGraphToViewScale();
final float yScale = dimensions.getYGraphToViewScale();
dimensions.setXY(scroller.getCurrX() * xScale, scroller.getCurrY() * yScale);
if (!scroller.isFinished()) {
invalidate();
}
@ -228,19 +230,20 @@ public class CalculatorGraph2dView extends View implements GraphView {
private void drawGraph(@NotNull Canvas canvas) {
mDrawn = true;
final float graphHeight = dimensions.getGraphHeight();
final float graphWidth = dimensions.getGWidth();
final float graphHeight = dimensions.getGHeight();
final float xMin = dimensions.getXMin();
final float xMax = dimensions.getXMax(xMin);
final float yMin = dimensions.getYMin(graphHeight);
final float yMax = dimensions.getYMax(graphHeight, yMin);
final float yMin = dimensions.getYMin();
final float yMax = dimensions.getYMax(yMin);
final float widthPxs = dimensions.getVWidthPxs();
final float heightPxs = dimensions.getVHeightPxs();
graphsData.checkBoundaries(graphHeight, yMin, yMax);
final int tickDigits = drawGridAndAxis(canvas);
final Pair<Integer, Integer> tickDigits = drawGridAndAxis(canvas);
{
// TOUCH POSITION
@ -253,16 +256,17 @@ public class CalculatorGraph2dView extends View implements GraphView {
canvas.drawLine(0, lastTouchYPxs, widthPxs, lastTouchYPxs, paint);
final Point2d lastTouch = dimensions.toGraphCoordinates(lastTouchXPxs, lastTouchYPxs);
final String touchLabel = "[" + formatTick(lastTouch.getX(), tickDigits + 1) + ", " + formatTick(lastTouch.getY(), tickDigits + 1) + "]";
final String touchLabel = "[" + formatTick(lastTouch.getX(), tickDigits.getFirst() + 1) + ", " + formatTick(lastTouch.getY(), tickDigits.getSecond() + 1) + "]";
canvas.drawText(touchLabel, 0, touchLabel.length(), lastTouchXPxs - 40, lastTouchYPxs - 40, textPaint);
}
}
final float ratio = dimensions.getGraphToViewRatio();
final float xScale = dimensions.getXGraphToViewScale();
final float yScale = dimensions.getYGraphToViewScale();
matrix.reset();
matrix.preTranslate(-dimensions.getX0(), -dimensions.getY0());
matrix.postScale(1/ratio, -1/ratio);
matrix.postScale(1/xScale, -1/yScale);
matrix.postTranslate(widthPxs / 2, heightPxs / 2);
paint.setAntiAlias(false);
@ -296,13 +300,14 @@ public class CalculatorGraph2dView extends View implements GraphView {
graphsData.setLastXMax(xMax);
}
private int drawGridAndAxis(@NotNull Canvas canvas) {
final float graphHeight = dimensions.getGraphHeight();
@NotNull
private Pair<Integer, Integer> drawGridAndAxis(@NotNull Canvas canvas) {
final Pair<Integer, Integer> result = new Pair<Integer, Integer>(1, 1);
final float xMin = dimensions.getXMin();
final float yMin = dimensions.getYMin(graphHeight);
final float yMax = dimensions.getYMax(graphHeight, yMin);
final float yMin = dimensions.getYMin();
final float yMax = dimensions.getYMax(yMin);
final float widthPxs = dimensions.getVWidthPxs();
final float heightPxs = dimensions.getVHeightPxs();
@ -314,26 +319,23 @@ public class CalculatorGraph2dView extends View implements GraphView {
paint.setAntiAlias(false);
paint.setStyle(Paint.Style.STROKE);
final float ratio = dimensions.getGraphToViewRatio();
final float xScale = dimensions.getXGraphToViewScale();
final float yScale = dimensions.getYGraphToViewScale();
float x0px = -xMin / ratio;
float x0px = -xMin / xScale;
if (x0px < 25) {
x0px = 25;
} else if (x0px > widthPxs - 3) {
x0px = widthPxs - 3;
}
float y0px = yMax / ratio;
float y0px = yMax / yScale;
if (y0px < 3) {
y0px = 3;
} else if (y0px > heightPxs - 15) {
y0px = heightPxs - 15;
}
final float tickStep = getTickStep(dimensions.getGWidth());
final int tickDigits = countTickDigits(tickStep);
{
// GRID
@ -344,14 +346,19 @@ public class CalculatorGraph2dView extends View implements GraphView {
textPaint.setTextSize(12);
textPaint.setTextAlign(Paint.Align.CENTER);
{
final float tickStep = getTickStep(dimensions.getGWidth());
final int tickDigits = countTickDigits(tickStep);
result.setFirst(tickDigits);
// round xMin and init first tick
float tick = ((int) (xMin / tickStep)) * tickStep;
final float y2 = y0px + TICK_SIZE_PXS;
final float stepPxs = tickStep / ratio;
float stepPxs = tickStep / xScale;
for (float xPxs = (tick - xMin) / ratio; xPxs <= widthPxs; xPxs += stepPxs, tick += tickStep) {
for (float xPxs = (tick - xMin) / xScale; xPxs <= widthPxs; xPxs += stepPxs, tick += tickStep) {
// draw grid line
canvas.drawLine(xPxs, 0, xPxs, heightPxs, paint);
@ -360,11 +367,20 @@ public class CalculatorGraph2dView extends View implements GraphView {
// draw tick label
canvas.drawText(tickLabel, 0, tickLabel.length(), xPxs, y2 + 10, textPaint);
}
}
{
final float tickStep = getTickStep(dimensions.getGHeight());
final int tickDigits = countTickDigits(tickStep);
result.setSecond(tickDigits);
// round yMin and init first tick
float tick = ((int) (yMin / tickStep)) * tickStep;
final float x1 = x0px - TICK_SIZE_PXS;
tick = ((int) (yMin / tickStep)) * tickStep;
final float stepPxs = tickStep / yScale;
textPaint.setTextAlign(Paint.Align.RIGHT);
for (float y = heightPxs - (tick - yMin) / ratio; y >= 0; y -= stepPxs, tick += tickStep) {
for (float y = heightPxs - (tick - yMin) / yScale; y >= 0; y -= stepPxs, tick += tickStep) {
canvas.drawLine(0, y, widthPxs, y, paint);
final CharSequence tickLabel = formatTick(tick, tickDigits);
@ -372,6 +388,7 @@ public class CalculatorGraph2dView extends View implements GraphView {
// draw tick label
canvas.drawText(tickLabel, 0, tickLabel.length(), x1, y + 4, textPaint);
}
}
paint.setPathEffect(null);
}
@ -383,7 +400,8 @@ public class CalculatorGraph2dView extends View implements GraphView {
canvas.drawLine(x0px, 0, x0px, heightPxs, paint);
canvas.drawLine(0, y0px, widthPxs, y0px, paint);
}
return tickDigits;
return result;
}
/*
@ -480,6 +498,11 @@ public class CalculatorGraph2dView extends View implements GraphView {
this.dimensions.setXRange(xMin, xMax);
}
@Override
public void setYRange(float yMin, float yMax) {
this.dimensions.setYRange(yMin, yMax);
}
/*
**********************************************************************
*
@ -502,11 +525,11 @@ public class CalculatorGraph2dView extends View implements GraphView {
public void onZoom(boolean zoomIn) {
if (zoomIn) {
if (canZoomIn()) {
dimensions.setGWidth(dimensions.getGWidth() / 2);
dimensions.setGraphDimensions(dimensions.getGWidth() / 2, dimensions.getGHeight() / 2);
}
} else {
if (canZoomOut()) {
dimensions.setGWidth(dimensions.getGWidth() * 2);
dimensions.setGraphDimensions(dimensions.getGWidth() * 2, dimensions.getGHeight() * 2);
}
}
zoomController.setZoomInEnabled(canZoomIn());
@ -553,7 +576,8 @@ public class CalculatorGraph2dView extends View implements GraphView {
}
public void onTouchUp(float x, float y) {
final float ratio = dimensions.getGraphToViewRatio();
final float xScale = dimensions.getXGraphToViewScale();
final float yScale = dimensions.getYGraphToViewScale();
lastTouchXPxs = NO_TOUCH;
lastTouchYPxs = NO_TOUCH;
@ -568,22 +592,23 @@ public class CalculatorGraph2dView extends View implements GraphView {
} else if (asy < asx / 3) {
sy = 0;
}
scroller.fling(Math.round(dimensions.getX0() / ratio), Math.round(dimensions.getY0() / ratio), Math.round(sx), Math.round(sy), Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE);
scroller.fling(Math.round(dimensions.getX0() / xScale), Math.round(dimensions.getY0() / yScale), Math.round(sx), Math.round(sy), Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE);
invalidate();
}
public void onTouchZoomDown(float x1, float y1, float x2, float y2) {
zoomTracker.start(dimensions.getGWidth(), x1, y1, x2, y2);
zoomTracker.start(dimensions.getGWidth(), dimensions.getGHeight(), x1, y1, x2, y2);
}
public void onTouchZoomMove(float x1, float y1, float x2, float y2) {
if (!zoomTracker.update(x1, y1, x2, y2)) {
return;
}
float targetGWidth = zoomTracker.value;
if (targetGWidth > .25f && targetGWidth < 200) {
dimensions.setGWidth(targetGWidth);
}
final float targetGWidth = zoomTracker.xValue;
final float targetGHeight = zoomTracker.yValue;
dimensions.setGraphDimensions(targetGWidth, targetGHeight);
}
private void scroll(float deltaX, float deltaY) {

View File

@ -173,6 +173,10 @@ public class CalculatorGraph3dView extends GLView implements GraphView {
dirty = true;
}
@Override
public void setYRange(float yMin, float yMax) {
}
@Override
public float getXMin() {
return dimensions.getXMin();
@ -229,7 +233,7 @@ public class CalculatorGraph3dView extends GLView implements GraphView {
ensureGraphsSize(gl);
final Graph2dDimensions dimensionsCopy = dimensions.copy();
dimensionsCopy.setGWidth(dimensions.getGWidth() * zoomLevel / 4);
dimensionsCopy.setGraphDimensions(dimensions.getGWidth() * zoomLevel / 4, dimensions.getGHeight() * zoomLevel / 4);
for (int i = 0; i < graphViewHelper.getPlotFunctions().size(); i++) {
graphs.get(i).update(gl, graphViewHelper.getPlotFunctions().get(i), dimensionsCopy);

View File

@ -46,7 +46,11 @@ public class CalculatorPlotFragment extends AbstractCalculatorPlotFragment {
}
graphView.init(PlotViewDef.newInstance(Color.WHITE, Color.WHITE, Color.DKGRAY, getBgColor()));
graphView.setXRange(plotData.getBoundaries().getXMin(), plotData.getBoundaries().getXMax());
final PlotBoundaries boundaries = plotData.getBoundaries();
graphView.setXRange(boundaries.getXMin(), boundaries.getXMax());
graphView.setYRange(boundaries.getYMin(), boundaries.getYMax());
graphView.setPlotFunctions(plotData.getFunctions());
if (graphView instanceof View) {

View File

@ -43,12 +43,16 @@ public class CalculatorPlotRangeActivity extends SherlockFragmentActivity {
final EditText xMinEditText = (EditText) root.findViewById(R.id.cpp_plot_range_x_min_editext);
final EditText xMaxEditText = (EditText) root.findViewById(R.id.cpp_plot_range_x_max_editext);
final EditText yMinEditText = (EditText) root.findViewById(R.id.cpp_plot_range_y_min_editext);
final EditText yMaxEditText = (EditText) root.findViewById(R.id.cpp_plot_range_y_max_editext);
final PlotData plotData = plotter.getPlotData();
final PlotBoundaries boundaries = plotData.getBoundaries();
xMinEditText.setText(String.valueOf(boundaries.getXMin()));
xMaxEditText.setText(String.valueOf(boundaries.getXMax()));
yMinEditText.setText(String.valueOf(boundaries.getYMin()));
yMaxEditText.setText(String.valueOf(boundaries.getYMax()));
root.findViewById(R.id.cpp_apply_button).setOnClickListener(new View.OnClickListener() {
@Override
@ -57,12 +61,18 @@ public class CalculatorPlotRangeActivity extends SherlockFragmentActivity {
try {
final Float xMin = Float.valueOf(xMinEditText.getText().toString());
final Float xMax = Float.valueOf(xMaxEditText.getText().toString());
final Float yMin = Float.valueOf(yMinEditText.getText().toString());
final Float yMax = Float.valueOf(yMaxEditText.getText().toString());
if ( xMin.equals(xMax) ) {
throw new IllegalArgumentException();
}
plotter.setPlotBoundaries(PlotBoundaries.newInstance(xMin, xMax));
if ( yMin.equals(yMax) ) {
throw new IllegalArgumentException();
}
plotter.setPlotBoundaries(PlotBoundaries.newInstance(xMin, xMax, yMin, yMax));
CalculatorPlotRangeFragment.this.getActivity().finish();

View File

@ -14,24 +14,25 @@ public class Graph2dDimensions {
// |<--------------gWidth-------------->|
// xMin xMax
// -------------------|------------------------------------|--------------------
// |<-------------vWidthPs------------->|
// |<-------------vWidthPxs------------>|
//
/*
*
*
* 0------------------------------------|--> xPxs
* |
* |
* | y
* | ^
* | |
* | |
* | |
* |------------------0-----------------|--> x
* | |
* | |
* | |
* yMax ------0------------------------------------|--> xPxs
* ^ |
* | |
* v | y
* H | ^
* e | |
* i | |
* g | |
* h |------------------0-----------------|--> x
* t | |
* | | |
* | | |
* v | |
* yMin ------- -
* | |
* v
* yPxs
@ -50,8 +51,9 @@ public class Graph2dDimensions {
private float x0;
private float y0;
// graph width in function units (NOT screen pixels)
// graph width and height in function units (NOT screen pixels)
private float gWidth = 20;
private float gHeight = 20;
public Graph2dDimensions(@NotNull GraphView graphView) {
this.graphView = graphView;
@ -67,11 +69,15 @@ public class Graph2dDimensions {
@NotNull
Point2d toGraphCoordinates(float xPxs, float yPxs) {
return new Point2d( scalePxs(xPxs) + getXMin(), (getGraphHeight() - scalePxs(yPxs)) + getYMin() );
return new Point2d( scaleXPxs(xPxs) + getXMin(), (getGHeight() - scaleYPxs(yPxs)) + getYMin() );
}
private float scalePxs(float pxs) {
return pxs * getGraphToViewRatio();
private float scaleXPxs(float pxs) {
return pxs * getXGraphToViewScale();
}
private float scaleYPxs(float pxs) {
return pxs * getYGraphToViewScale();
}
// X
@ -91,28 +97,18 @@ public class Graph2dDimensions {
// Y
public float getYMin() {
return getYMin(getGraphHeight());
}
public float getYMin(float graphHeight) {
return y0 - graphHeight / 2;
return y0 - gHeight / 2;
}
public float getYMax() {
final float graphHeight = getGraphHeight();
return getYMax(graphHeight, getYMin(graphHeight));
return getYMax(getYMin());
}
public float getYMax(float graphHeight, float yMin) {
return yMin + graphHeight;
public float getYMax(float yMin) {
return yMin + gHeight;
}
float getGraphHeight() {
return gWidth * getAspectRatio();
}
float getGraphToViewRatio() {
float getXGraphToViewScale() {
if (vWidthPxs != 0) {
return gWidth / ((float)vWidthPxs);
} else {
@ -120,7 +116,15 @@ public class Graph2dDimensions {
}
}
private float getAspectRatio() {
float getYGraphToViewScale() {
if (vHeightPxs != 0) {
return gHeight / ((float)vHeightPxs);
} else {
return 0f;
}
}
private float getViewAspectRatio() {
if (vWidthPxs != 0) {
return ((float) vHeightPxs) / vWidthPxs;
} else {
@ -148,6 +152,10 @@ public class Graph2dDimensions {
return gWidth;
}
float getGHeight() {
return gHeight;
}
/*
**********************************************************************
*
@ -159,7 +167,13 @@ public class Graph2dDimensions {
public void setXRange(float xMin, float xMax) {
this.gWidth = xMax - xMin;
this.x0 = xMin + gWidth / 2;
this.y0 = 0;
this.graphView.invalidateGraphs();
}
public void setYRange(float yMin, float yMax) {
this.gHeight = yMax - yMin;
this.y0 = yMin + gHeight / 2;
this.graphView.invalidateGraphs();
}
@ -172,8 +186,9 @@ public class Graph2dDimensions {
}
public void setGWidth(float gWidth) {
public void setGraphDimensions(float gWidth, float gHeight) {
this.gWidth = gWidth;
this.gHeight = gHeight;
this.graphView.invalidateGraphs();
}
@ -204,6 +219,7 @@ public class Graph2dDimensions {
copy.x0 = this.x0;
copy.y0 = this.y0;
copy.gWidth = this.gWidth;
copy.gHeight = this.gHeight;
return copy;
}

View File

@ -19,11 +19,12 @@ public class GraphCalculatorImpl extends AbstractGraphCalculator {
@NotNull Graph2dDimensions dimensions) {
graph.push(xMin, (float)f.eval(xMin));
final float ratio = dimensions.getGraphToViewRatio();
final float maxStep = 15.8976f * ratio;
final float minStep = .05f * ratio;
final float xScale = dimensions.getXGraphToViewScale();
final float yScale = dimensions.getYGraphToViewScale();
final float maxStep = 15.8976f * xScale;
final float minStep = .05f * xScale;
float yTheta = ratio;
float yTheta = yScale;
yTheta = yTheta * yTheta;

View File

@ -23,6 +23,7 @@ public interface GraphView extends ZoomButtonsController.OnZoomListener, TouchHa
public Bitmap captureScreenshot();
void setXRange(float xMin, float xMax);
void setYRange(float yMin, float yMax);
float getXMin();

View File

@ -1,22 +1,24 @@
// Copyright (C) 2010 Mihai Preda
package org.solovyev.android.calculator.plot;
class ZoomTracker {
private float sx1, sy1, sx2, sy2;
private float initialDist;
private float initialValue;
float value;
private float initialXValue;
private float initialYValue;
float xValue;
float yValue;
float moveX, moveY;
void start(float value, float x1, float y1, float x2, float y2) {
void start(float xValue, float yValue, float x1, float y1, float x2, float y2) {
sx1 = x1;
sy1 = y1;
sx2 = x2;
sy2 = y2;
initialDist = distance(x1, y1, x2, y2);
initialValue = value;
initialXValue = xValue;
initialYValue = yValue;
}
boolean update(float x1, float y1, float x2, float y2) {
@ -28,7 +30,8 @@ class ZoomTracker {
moveX = common(x1, sx1, x2, sx2);
moveY = common(y1, sy1, y2, sy2);
float dist = distance(x1, y1, x2, y2);
value = initialDist / dist * initialValue;
xValue = initialDist / dist * initialXValue;
yValue = initialDist / dist * initialYValue;
sx1 = x1;
sx2 = x2;
sy1 = y1;