new plotter
This commit is contained in:
parent
3f76f61c4b
commit
cc5d74b54b
@ -19,6 +19,7 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import com.actionbarsherlock.app.ActionBar;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -31,7 +32,7 @@ import org.solovyev.common.equals.EqualsTool;
|
||||
import org.solovyev.common.history.HistoryAction;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
public class CalculatorActivity extends SherlockFragmentActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
public class CalculatorActivity extends SherlockFragmentActivity implements SharedPreferences.OnSharedPreferenceChangeListener, CalculatorEventListener {
|
||||
|
||||
@NotNull
|
||||
public static final String TAG = CalculatorActivity.class.getSimpleName();
|
||||
@ -57,7 +58,7 @@ public class CalculatorActivity extends SherlockFragmentActivity implements Shar
|
||||
super.onCreate(savedInstanceState);
|
||||
activityHelper.logDebug("super.onCreate");
|
||||
|
||||
if (findViewById(R.id.main_second_pane) != null) {
|
||||
if (isMultiPane()) {
|
||||
activityHelper.addTab(this, CalculatorFragmentType.history, null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.saved_history, null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.variables, null, R.id.main_second_pane);
|
||||
@ -89,6 +90,10 @@ public class CalculatorActivity extends SherlockFragmentActivity implements Shar
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMultiPane() {
|
||||
return findViewById(R.id.main_second_pane) != null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private AndroidCalculator getCalculator() {
|
||||
return ((AndroidCalculator) Locator.getInstance().getCalculator());
|
||||
@ -321,4 +326,28 @@ public class CalculatorActivity extends SherlockFragmentActivity implements Shar
|
||||
buttonPressed(CalculatorSpecialButton.like);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
switch (calculatorEventType) {
|
||||
case plot_graph:
|
||||
Threads.tryRunOnUiThread(this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if ( isMultiPane() ) {
|
||||
final ActionBar.Tab selectedTab = getSupportActionBar().getSelectedTab();
|
||||
if ( selectedTab != null && CalculatorFragmentType.plotter.getFragmentTag().equals(selectedTab.getTag()) ) {
|
||||
// do nothing - fragment shown and already registered for plot updates
|
||||
} else {
|
||||
// otherwise - open fragment
|
||||
activityHelper.selectTab(CalculatorActivity.this, CalculatorFragmentType.plotter);
|
||||
}
|
||||
} else {
|
||||
// start new activity
|
||||
CalculatorActivityLauncher.plotGraph(CalculatorActivity.this);
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -61,4 +61,6 @@ public interface CalculatorActivityHelper {
|
||||
void processButtons(@NotNull Activity activity, @NotNull View root);
|
||||
|
||||
void logError(@NotNull String message);
|
||||
|
||||
void selectTab(@NotNull SherlockFragmentActivity activity, @NotNull CalculatorFragmentType fragmentType);
|
||||
}
|
||||
|
@ -228,6 +228,18 @@ public class CalculatorActivityHelperImpl extends AbstractCalculatorHelper imple
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectTab(@NotNull SherlockFragmentActivity activity, @NotNull CalculatorFragmentType fragmentType) {
|
||||
final ActionBar actionBar = activity.getSupportActionBar();
|
||||
for (int i = 0; i < actionBar.getTabCount(); i++) {
|
||||
final ActionBar.Tab tab = actionBar.getTabAt(i);
|
||||
if ( tab != null && CalculatorFragmentType.plotter.getFragmentTag().equals(tab.getTag()) ) {
|
||||
actionBar.setSelectedNavigationItem(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
return layoutId;
|
||||
|
@ -233,14 +233,6 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
|
||||
}
|
||||
});
|
||||
break;
|
||||
case plot_graph:
|
||||
App.getInstance().getUiThreadExecutor().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
plotGraph(context);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case show_evaluation_error:
|
||||
final String errorMessage = (String) data;
|
||||
if (errorMessage != null) {
|
||||
|
@ -136,14 +136,14 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
||||
Threads.tryRunOnUiThread(activity, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
activity.invalidateOptionsMenu();
|
||||
|
||||
createChart(plotData);
|
||||
|
||||
final View view = getView();
|
||||
if (view != null) {
|
||||
createGraphicalView(view, plotData);
|
||||
}
|
||||
|
||||
activity.invalidateOptionsMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -231,6 +231,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
||||
};
|
||||
menuItems.add(captureScreenshotMenuItem);
|
||||
|
||||
final boolean plotRangeVisible = !plotData.isPlot3d();
|
||||
final boolean plot3dVisible = !plotData.isPlot3d() && is3dPlotSupported();
|
||||
final boolean plot2dVisible = plotData.isPlot3d() && Locator.getInstance().getPlotter().is2dPlotPossible();
|
||||
final boolean captureScreenshotVisible = isScreenshotSupported();
|
||||
@ -243,7 +244,10 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
|
||||
return !plot2dVisible;
|
||||
} else if ( menuItem == captureScreenshotMenuItem ) {
|
||||
return !captureScreenshotVisible;
|
||||
}
|
||||
} else if ( menuItem == PlotMenu.range ) {
|
||||
return !plotRangeVisible;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
@ -145,6 +145,11 @@ public class CalculatorGraph2dView extends View implements GraphView {
|
||||
return this.graphViewHelper.getPlotFunctions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
onPause();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Bitmap captureScreenshot() {
|
||||
final Bitmap result = Bitmap.createBitmap(dimensions.getVWidthPxs(), dimensions.getVHeightPxs(), Bitmap.Config.RGB_565);
|
||||
|
@ -8,7 +8,6 @@ import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.ZoomButtonsController;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.App;
|
||||
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import javax.microedition.khronos.opengles.GL11;
|
||||
@ -18,16 +17,32 @@ import java.util.List;
|
||||
|
||||
public class CalculatorGraph3dView extends GLView implements GraphView {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private boolean useHighQuality3d = Build.VERSION.SDK_INT >= 5;
|
||||
|
||||
private float lastTouchX, lastTouchY;
|
||||
private TouchHandler touchHandler;
|
||||
private ZoomButtonsController zoomController = new ZoomButtonsController(this);
|
||||
private float zoomLevel = 1, targetZoom, zoomStep = 0, currentZoom;
|
||||
private FPS fps = new FPS();
|
||||
|
||||
@NotNull
|
||||
private GLText glText;
|
||||
private float zoomLevel = 1;
|
||||
private float zoomTarget;
|
||||
private float zoomStep = 0;
|
||||
private float currentZoom;
|
||||
|
||||
@NotNull
|
||||
private List<Graph3d> graphs = new ArrayList<Graph3d>();
|
||||
@ -35,6 +50,17 @@ public class CalculatorGraph3dView extends GLView implements GraphView {
|
||||
@NotNull
|
||||
private GraphViewHelper graphViewHelper = GraphViewHelper.newDefaultInstance();
|
||||
|
||||
@NotNull
|
||||
private Graph2dDimensions dimensions = new Graph2dDimensions(this);
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTRUCTORS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public CalculatorGraph3dView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
@ -54,6 +80,235 @@ public class CalculatorGraph3dView extends GLView implements GraphView {
|
||||
Matrix.rotateM(matrix1, 0, -75, 1, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* METHODS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
protected void onSizeChanged(int w, int h, int ow, int oh) {
|
||||
dimensions.setViewDimensions(w, h);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void glDraw() {
|
||||
|
||||
if (zoomStep < 0 && zoomLevel > zoomTarget) {
|
||||
zoomLevel += zoomStep;
|
||||
} else if (zoomStep > 0 && zoomLevel < zoomTarget) {
|
||||
zoomLevel += zoomStep;
|
||||
} else if (zoomStep != 0) {
|
||||
zoomStep = 0;
|
||||
zoomLevel = zoomTarget;
|
||||
dirty = true;
|
||||
if (!shouldRotate()) {
|
||||
stopLooping();
|
||||
}
|
||||
}
|
||||
|
||||
super.glDraw();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromWindow() {
|
||||
zoomController.setVisible(false);
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
private float[] matrix1 = new float[16], matrix2 = new float[16], matrix3 = new float[16];
|
||||
private float angleX, angleY;
|
||||
private boolean dirty;
|
||||
|
||||
private static final float DISTANCE = 15f;
|
||||
|
||||
void setRotation(float x, float y) {
|
||||
angleX = x;
|
||||
angleY = y;
|
||||
}
|
||||
|
||||
boolean shouldRotate() {
|
||||
final float limit = .5f;
|
||||
return angleX < -limit || angleX > limit || angleY < -limit || angleY > limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(@NotNull PlotViewDef plotViewDef) {
|
||||
this.graphViewHelper = GraphViewHelper.newInstance(plotViewDef, Collections.<PlotFunction>emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlotFunctions(@NotNull List<PlotFunction> plotFunctions) {
|
||||
for (PlotFunction plotFunction: plotFunctions) {
|
||||
final int arity = plotFunction.getXyFunction().getArity();
|
||||
if (arity != 0 && arity != 1 && arity != 2) {
|
||||
throw new IllegalArgumentException("Function must have arity 0 or 1 or 2 for 3d plot!");
|
||||
}
|
||||
}
|
||||
|
||||
this.graphViewHelper = this.graphViewHelper.copy(plotFunctions);
|
||||
zoomLevel = 1;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<PlotFunction> getPlotFunctions() {
|
||||
return this.graphViewHelper.getPlotFunctions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setXRange(float xMin, float xMax) {
|
||||
dimensions.setXRange(PlotBoundaries.DEFAULT_MIN_NUMBER, PlotBoundaries.DEFAULT_MAX_NUMBER);
|
||||
|
||||
zoomLevel = 1;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getXMin() {
|
||||
return dimensions.getXMin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getXMax() {
|
||||
return dimensions.getXMax();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getYMin() {
|
||||
return dimensions.getYMin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getYMax() {
|
||||
return dimensions.getYMax();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateGraphs() {
|
||||
//To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceCreated(GL10 gl, int width, int height) {
|
||||
gl.glDisable(GL10.GL_DITHER);
|
||||
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
|
||||
|
||||
final int backgroundColor = graphViewHelper.getPlotViewDef().getBackgroundColor();
|
||||
gl.glClearColor(Color.red(backgroundColor) / 255f, Color.green(backgroundColor) / 255f, Color.blue(backgroundColor) / 255f, Color.alpha(backgroundColor) / 255f);
|
||||
|
||||
gl.glShadeModel(useHighQuality3d ? GL10.GL_SMOOTH : GL10.GL_FLAT);
|
||||
gl.glDisable(GL10.GL_LIGHTING);
|
||||
ensureGraphsSize((GL11) gl);
|
||||
dirty = true;
|
||||
angleX = .5f;
|
||||
angleY = 0;
|
||||
|
||||
gl.glViewport(0, 0, width, height);
|
||||
initFrustum(gl, DISTANCE * zoomLevel);
|
||||
currentZoom = zoomLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawFrame(GL10 gl10) {
|
||||
GL11 gl = (GL11) gl10;
|
||||
if (currentZoom != zoomLevel) {
|
||||
initFrustum(gl, DISTANCE * zoomLevel);
|
||||
currentZoom = zoomLevel;
|
||||
}
|
||||
if (dirty) {
|
||||
ensureGraphsSize(gl);
|
||||
|
||||
final Graph2dDimensions dimensionsCopy = dimensions.copy();
|
||||
dimensionsCopy.setGWidth(dimensions.getGWidth() * zoomLevel / 4);
|
||||
|
||||
for (int i = 0; i < graphViewHelper.getPlotFunctions().size(); i++) {
|
||||
graphs.get(i).update(gl, graphViewHelper.getPlotFunctions().get(i), dimensionsCopy);
|
||||
|
||||
}
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
/*if (fps.incFrame()) {
|
||||
Calculator.log("f/s " + fps.getValue());
|
||||
}*/
|
||||
|
||||
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
|
||||
gl.glMatrixMode(GL10.GL_MODELVIEW);
|
||||
gl.glLoadIdentity();
|
||||
|
||||
gl.glTranslatef(0, 0, -DISTANCE * zoomLevel);
|
||||
|
||||
Matrix.setIdentityM(matrix2, 0);
|
||||
float ax = Math.abs(angleX);
|
||||
float ay = Math.abs(angleY);
|
||||
if (ay * 3 < ax) {
|
||||
Matrix.rotateM(matrix2, 0, angleX, 0, 1, 0);
|
||||
} else if (ax * 3 < ay) {
|
||||
Matrix.rotateM(matrix2, 0, angleY, 1, 0, 0);
|
||||
} else {
|
||||
if (ax > ay) {
|
||||
Matrix.rotateM(matrix2, 0, angleX, 0, 1, 0);
|
||||
Matrix.rotateM(matrix2, 0, angleY, 1, 0, 0);
|
||||
} else {
|
||||
Matrix.rotateM(matrix2, 0, angleY, 1, 0, 0);
|
||||
Matrix.rotateM(matrix2, 0, angleX, 0, 1, 0);
|
||||
}
|
||||
}
|
||||
Matrix.multiplyMM(matrix3, 0, matrix2, 0, matrix1, 0);
|
||||
gl.glMultMatrixf(matrix3, 0);
|
||||
System.arraycopy(matrix3, 0, matrix1, 0, 16);
|
||||
for (Graph3d graph : graphs) {
|
||||
graph.draw(gl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void ensureGraphsSize(@NotNull GL11 gl) {
|
||||
while (graphViewHelper.getPlotFunctions().size() > graphs.size()) {
|
||||
graphs.add(new Graph3d(gl, useHighQuality3d));
|
||||
}
|
||||
}
|
||||
|
||||
private void initFrustum(GL10 gl, float distance) {
|
||||
gl.glMatrixMode(GL10.GL_PROJECTION);
|
||||
gl.glLoadIdentity();
|
||||
float near = distance * (1 / 3f);
|
||||
float far = distance * 3f;
|
||||
float dimen = near / 5f;
|
||||
float h = dimen * height / width;
|
||||
gl.glFrustumf(-dimen, dimen, -h, h, near, far);
|
||||
gl.glMatrixMode(GL10.GL_MODELVIEW);
|
||||
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
|
||||
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
private void printMatrix(float[] m, String name) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
b.append(m[i]).append(' ');
|
||||
}
|
||||
//Calculator.log(name + ' ' + b.toString());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* ZOOM
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public void onVisibilityChanged(boolean visible) {
|
||||
}
|
||||
|
||||
@ -61,20 +316,21 @@ public class CalculatorGraph3dView extends GLView implements GraphView {
|
||||
boolean changed = false;
|
||||
if (zoomIn) {
|
||||
if (canZoomIn(zoomLevel)) {
|
||||
targetZoom = zoomLevel * .625f;
|
||||
zoomTarget = zoomLevel * .625f;
|
||||
zoomStep = -zoomLevel / 40;
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
if (canZoomOut(zoomLevel)) {
|
||||
targetZoom = zoomLevel * 1.6f;
|
||||
zoomTarget = zoomLevel * 1.6f;
|
||||
zoomStep = zoomLevel / 20;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
zoomController.setZoomInEnabled(canZoomIn(targetZoom));
|
||||
zoomController.setZoomOutEnabled(canZoomOut(targetZoom));
|
||||
zoomController.setZoomInEnabled(canZoomIn(zoomTarget));
|
||||
zoomController.setZoomOutEnabled(canZoomOut(zoomTarget));
|
||||
if (!shouldRotate()) {
|
||||
setRotation(0, 0);
|
||||
}
|
||||
@ -82,22 +338,6 @@ public class CalculatorGraph3dView extends GLView implements GraphView {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void glDraw() {
|
||||
if ((zoomStep < 0 && zoomLevel > targetZoom) ||
|
||||
(zoomStep > 0 && zoomLevel < targetZoom)) {
|
||||
zoomLevel += zoomStep;
|
||||
} else if (zoomStep != 0) {
|
||||
zoomStep = 0;
|
||||
zoomLevel = targetZoom;
|
||||
isDirty = true;
|
||||
if (!shouldRotate()) {
|
||||
stopLooping();
|
||||
}
|
||||
}
|
||||
super.glDraw();
|
||||
}
|
||||
|
||||
private boolean canZoomIn(float zoom) {
|
||||
return true;
|
||||
}
|
||||
@ -106,11 +346,13 @@ public class CalculatorGraph3dView extends GLView implements GraphView {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromWindow() {
|
||||
zoomController.setVisible(false);
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* TOUCH
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public void onTouchDown(float x, float y) {
|
||||
zoomController.setVisible(true);
|
||||
@ -151,195 +393,4 @@ public class CalculatorGraph3dView extends GLView implements GraphView {
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return touchHandler != null ? touchHandler.handleTouchEvent(event) : super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
private float[] matrix1 = new float[16], matrix2 = new float[16], matrix3 = new float[16];
|
||||
private float angleX, angleY;
|
||||
private boolean isDirty;
|
||||
private static final float DISTANCE = 15f;
|
||||
|
||||
void setRotation(float x, float y) {
|
||||
angleX = x;
|
||||
angleY = y;
|
||||
}
|
||||
|
||||
boolean shouldRotate() {
|
||||
final float limit = .5f;
|
||||
return angleX < -limit || angleX > limit || angleY < -limit || angleY > limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(@NotNull PlotViewDef plotViewDef) {
|
||||
this.graphViewHelper = GraphViewHelper.newInstance(plotViewDef, Collections.<PlotFunction>emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlotFunctions(@NotNull List<PlotFunction> plotFunctions) {
|
||||
for (PlotFunction plotFunction: plotFunctions) {
|
||||
final int arity = plotFunction.getXyFunction().getArity();
|
||||
if (arity != 0 && arity != 1 && arity != 2) {
|
||||
throw new IllegalArgumentException("Function must have arity 0 or 1 or 2 for 3d plot!");
|
||||
}
|
||||
}
|
||||
|
||||
this.graphViewHelper = this.graphViewHelper.copy(plotFunctions);
|
||||
zoomLevel = 1;
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<PlotFunction> getPlotFunctions() {
|
||||
return this.graphViewHelper.getPlotFunctions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setXRange(float xMin, float xMax) {
|
||||
//To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getXMin() {
|
||||
return 0; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getXMax() {
|
||||
return 0; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getYMin() {
|
||||
return 0; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getYMax() {
|
||||
return 0; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateGraphs() {
|
||||
//To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceCreated(GL10 gl, int width, int height) {
|
||||
gl.glDisable(GL10.GL_DITHER);
|
||||
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
|
||||
|
||||
final int backgroundColor = graphViewHelper.getPlotViewDef().getBackgroundColor();
|
||||
gl.glClearColor(Color.red(backgroundColor) / 255f, Color.green(backgroundColor) / 255f, Color.blue(backgroundColor) / 255f, Color.alpha(backgroundColor) / 255f);
|
||||
|
||||
gl.glShadeModel(useHighQuality3d ? GL10.GL_SMOOTH : GL10.GL_FLAT);
|
||||
gl.glDisable(GL10.GL_LIGHTING);
|
||||
ensureGraphsSize((GL11) gl);
|
||||
isDirty = true;
|
||||
angleX = .5f;
|
||||
angleY = 0;
|
||||
|
||||
gl.glViewport(0, 0, width, height);
|
||||
initFrustum(gl, DISTANCE * zoomLevel);
|
||||
currentZoom = zoomLevel;
|
||||
|
||||
glText = new GLText( gl, App.getInstance().getApplication().getAssets() );
|
||||
glText.load("Roboto-Regular.ttf", 32, 2, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawFrame(GL10 gl10) {
|
||||
GL11 gl = (GL11) gl10;
|
||||
if (currentZoom != zoomLevel) {
|
||||
initFrustum(gl, DISTANCE * zoomLevel);
|
||||
currentZoom = zoomLevel;
|
||||
}
|
||||
if (isDirty) {
|
||||
ensureGraphsSize(gl);
|
||||
for (int i = 0; i < graphViewHelper.getPlotFunctions().size(); i++) {
|
||||
graphs.get(i).update(gl, graphViewHelper.getPlotFunctions().get(i), zoomLevel);
|
||||
|
||||
}
|
||||
isDirty = false;
|
||||
}
|
||||
|
||||
/*if (fps.incFrame()) {
|
||||
Calculator.log("f/s " + fps.getValue());
|
||||
}*/
|
||||
|
||||
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
|
||||
gl.glMatrixMode(GL10.GL_MODELVIEW);
|
||||
gl.glLoadIdentity();
|
||||
|
||||
gl.glTranslatef(0, 0, -DISTANCE * zoomLevel);
|
||||
|
||||
Matrix.setIdentityM(matrix2, 0);
|
||||
float ax = Math.abs(angleX);
|
||||
float ay = Math.abs(angleY);
|
||||
if (ay * 3 < ax) {
|
||||
Matrix.rotateM(matrix2, 0, angleX, 0, 1, 0);
|
||||
} else if (ax * 3 < ay) {
|
||||
Matrix.rotateM(matrix2, 0, angleY, 1, 0, 0);
|
||||
} else {
|
||||
if (ax > ay) {
|
||||
Matrix.rotateM(matrix2, 0, angleX, 0, 1, 0);
|
||||
Matrix.rotateM(matrix2, 0, angleY, 1, 0, 0);
|
||||
} else {
|
||||
Matrix.rotateM(matrix2, 0, angleY, 1, 0, 0);
|
||||
Matrix.rotateM(matrix2, 0, angleX, 0, 1, 0);
|
||||
}
|
||||
}
|
||||
Matrix.multiplyMM(matrix3, 0, matrix2, 0, matrix1, 0);
|
||||
gl.glMultMatrixf(matrix3, 0);
|
||||
System.arraycopy(matrix3, 0, matrix1, 0, 16);
|
||||
for (Graph3d graph : graphs) {
|
||||
graph.draw(gl);
|
||||
}
|
||||
|
||||
//updateText(gl, glText);
|
||||
|
||||
}
|
||||
|
||||
public void drawText(@NotNull GLText glText) {
|
||||
glText.begin(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glText.draw( "Test!", 0, 0 );
|
||||
glText.end();
|
||||
}
|
||||
|
||||
private void updateText(@NotNull GL11 gl, @NotNull GLText glText) {
|
||||
gl.glEnable( GL10.GL_TEXTURE_2D );
|
||||
gl.glEnable( GL10.GL_BLEND );
|
||||
gl.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA );
|
||||
drawText(glText);
|
||||
gl.glDisable( GL10.GL_BLEND );
|
||||
gl.glDisable( GL10.GL_TEXTURE_2D );
|
||||
}
|
||||
|
||||
private void ensureGraphsSize(@NotNull GL11 gl) {
|
||||
while (graphViewHelper.getPlotFunctions().size() > graphs.size()) {
|
||||
graphs.add(new Graph3d(gl, useHighQuality3d));
|
||||
}
|
||||
}
|
||||
|
||||
private void initFrustum(GL10 gl, float distance) {
|
||||
gl.glMatrixMode(GL10.GL_PROJECTION);
|
||||
gl.glLoadIdentity();
|
||||
float near = distance * (1 / 3f);
|
||||
float far = distance * 3f;
|
||||
float dimen = near / 5f;
|
||||
float h = dimen * height / width;
|
||||
gl.glFrustumf(-dimen, dimen, -h, h, near, far);
|
||||
gl.glMatrixMode(GL10.GL_MODELVIEW);
|
||||
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
|
||||
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
private void printMatrix(float[] m, String name) {
|
||||
StringBuffer b = new StringBuffer();
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
b.append(m[i]).append(' ');
|
||||
}
|
||||
//Calculator.log(name + ' ' + b.toString());
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
@ -21,7 +21,7 @@ public class CalculatorPlotFragment extends AbstractCalculatorPlotFragment {
|
||||
@Nullable
|
||||
@Override
|
||||
protected PlotBoundaries getPlotBoundaries() {
|
||||
if ( graphView != null ) {
|
||||
if ( graphView instanceof CalculatorGraph2dView ) {
|
||||
return PlotBoundaries.newInstance(graphView.getXMin(), graphView.getXMax(), graphView.getYMin(), graphView.getYMax());
|
||||
} else {
|
||||
return null;
|
||||
@ -35,6 +35,7 @@ public class CalculatorPlotFragment extends AbstractCalculatorPlotFragment {
|
||||
final ViewGroup graphContainer = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
|
||||
|
||||
if (graphView instanceof View) {
|
||||
graphView.onDestroy();
|
||||
graphContainer.removeView((View) graphView);
|
||||
}
|
||||
|
||||
@ -44,8 +45,6 @@ public class CalculatorPlotFragment extends AbstractCalculatorPlotFragment {
|
||||
graphView = new CalculatorGraph2dView(getActivity());
|
||||
}
|
||||
|
||||
// todo serso: investigate (after switching from 3d to 2d - blank screen)
|
||||
|
||||
graphView.init(PlotViewDef.newInstance(Color.WHITE, Color.WHITE, Color.DKGRAY, getBgColor()));
|
||||
graphView.setXRange(plotData.getBoundaries().getXMin(), plotData.getBoundaries().getXMax());
|
||||
graphView.setPlotFunctions(plotData.getFunctions());
|
||||
@ -104,4 +103,14 @@ public class CalculatorPlotFragment extends AbstractCalculatorPlotFragment {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (this.graphView != null) {
|
||||
this.graphView.onDestroy();
|
||||
}
|
||||
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -194,4 +194,17 @@ public class Graph2dDimensions {
|
||||
this.x0 += dx;
|
||||
this.y0 += dy;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Graph2dDimensions copy() {
|
||||
final Graph2dDimensions copy = new Graph2dDimensions(this.graphView);
|
||||
|
||||
copy.vWidthPxs = this.vWidthPxs;
|
||||
copy.vHeightPxs = this.vHeightPxs;
|
||||
copy.x0 = this.x0;
|
||||
copy.y0 = this.y0;
|
||||
copy.gWidth = this.gWidth;
|
||||
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
@ -91,20 +91,18 @@ class Graph3d {
|
||||
return bb;
|
||||
}
|
||||
|
||||
public void update(@NotNull GL11 gl, @NotNull PlotFunction fpd, float zoom) {
|
||||
public void update(@NotNull GL11 gl, @NotNull PlotFunction fpd, @NotNull Graph2dDimensions dimensions) {
|
||||
final XyFunction function = fpd.getXyFunction();
|
||||
final PlotLineDef lineDef = fpd.getPlotLineDef();
|
||||
final int NTICK = useHighQuality3d ? 5 : 0;
|
||||
|
||||
final float size = 4 * zoom;
|
||||
|
||||
//Calculator.log("update VBOs " + vertexVbo + ' ' + colorVbo + ' ' + vertexElementVbo);
|
||||
polygonsⁿ = n * n + 6 + 8 + NTICK * 6;
|
||||
|
||||
// triangle polygon => 3 vertices per polygon
|
||||
final float vertices[] = new float[polygonsⁿ * VERTICES_COUNT];
|
||||
|
||||
float maxAbsZ = fillFunctionPolygonVertices(function, size, vertices);
|
||||
float maxAbsZ = fillFunctionPolygonVertices(function, dimensions, vertices);
|
||||
final byte[] colors = prepareFunctionPolygonColors(lineDef, vertices, maxAbsZ);
|
||||
|
||||
|
||||
@ -229,19 +227,20 @@ class Graph3d {
|
||||
}
|
||||
}
|
||||
|
||||
private float fillFunctionPolygonVertices(XyFunction function, float size, float[] vertices) {
|
||||
private float fillFunctionPolygonVertices(XyFunction function, @NotNull Graph2dDimensions dimensions, float[] vertices) {
|
||||
final int arity = function.getArity();
|
||||
|
||||
final float minX = -size;
|
||||
final float maxX = size;
|
||||
final float minY = -size;
|
||||
final float maxY = size;
|
||||
final float xMin = dimensions.getXMin();
|
||||
final float xMax = dimensions.getXMax();
|
||||
|
||||
float Δx = (maxX - minX) / (n - 1);
|
||||
float Δy = (maxY - minY) / (n - 1);
|
||||
final float yMin = dimensions.getXMin();
|
||||
final float yMax = dimensions.getXMax();
|
||||
|
||||
float y = minY;
|
||||
float x = minX - Δx;
|
||||
float Δx = (xMax - xMin) / (n - 1);
|
||||
float Δy = (yMax - yMin) / (n - 1);
|
||||
|
||||
float y = yMin;
|
||||
float x = xMin - Δx;
|
||||
|
||||
float maxAbsZ = 0;
|
||||
|
||||
|
@ -15,6 +15,7 @@ public interface GraphView extends ZoomButtonsController.OnZoomListener, TouchHa
|
||||
@NotNull
|
||||
public List<PlotFunction> getPlotFunctions();
|
||||
|
||||
public void onDestroy();
|
||||
public void onPause();
|
||||
public void onResume();
|
||||
|
||||
|
@ -11,9 +11,9 @@ import java.io.Serializable;
|
||||
*/
|
||||
public final class PlotBoundaries implements Serializable {
|
||||
|
||||
private static final float DEFAULT_MIN_NUMBER = -10f;
|
||||
public static final float DEFAULT_MIN_NUMBER = -10f;
|
||||
|
||||
private static final float DEFAULT_MAX_NUMBER = 10f;
|
||||
public static final float DEFAULT_MAX_NUMBER = 10f;
|
||||
|
||||
|
||||
private float xMin;
|
||||
|
Loading…
Reference in New Issue
Block a user