From 0116d285c599aeb55c68d04fd96df09053cd57cb Mon Sep 17 00:00:00 2001 From: Mikhail Kulesh Date: Thu, 29 Sep 2022 22:25:57 +0200 Subject: [PATCH] #124 3D plot fails whenever one interval is used twice: fixed --- .../mkulesh/micromath/plots/PlotContour.java | 63 ++++++++++++++++--- .../plots/views/ContourPlotView.java | 5 +- .../plots/views/SurfacePlotView.java | 22 ++++++- 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/mkulesh/micromath/plots/PlotContour.java b/app/src/main/java/com/mkulesh/micromath/plots/PlotContour.java index 58c5e9c8..8f8a503d 100644 --- a/app/src/main/java/com/mkulesh/micromath/plots/PlotContour.java +++ b/app/src/main/java/com/mkulesh/micromath/plots/PlotContour.java @@ -653,11 +653,12 @@ public String[] getLabels() void calculate(CalculaterTask thread) throws CancelException { final CalculatedValue calcVal = new CalculatedValue(); - ArrayList linkedIntervals = getDirectIntervals(); - if (linkedIntervals.size() != 2) + final ArrayList linkedIntervals = getDirectIntervals(); + if (linkedIntervals.size() != 1 && linkedIntervals.size() != 2) { return; } + final boolean isFunction1D = linkedIntervals.size() == 1; // prepare axis and minimum and maximum values minMaxValues[FunctionIf.X][FunctionIf.MIN] = Double.NEGATIVE_INFINITY; @@ -672,7 +673,8 @@ void calculate(CalculaterTask thread) throws CancelException calcVal.processRealTerm(thread, xMax); minMaxValues[FunctionIf.X][FunctionIf.MAX] = calcVal.getReal(); } - xValues = linkedIntervals.get(0).fillBoundedInterval(xValues, minMaxValues[FunctionIf.X]); + final Equation xValuesEq = linkedIntervals.get(0); + xValues = xValuesEq.fillBoundedInterval(xValues, minMaxValues[FunctionIf.X]); if (xValues == null) { return; @@ -690,15 +692,16 @@ void calculate(CalculaterTask thread) throws CancelException calcVal.processRealTerm(thread, yMax); minMaxValues[FunctionIf.Y][FunctionIf.MAX] = calcVal.getReal(); } - yValues = linkedIntervals.get(1).fillBoundedInterval(yValues, minMaxValues[FunctionIf.Y]); + final Equation yValuesEq = isFunction1D ? linkedIntervals.get(0) : linkedIntervals.get(1); + yValues = yValuesEq.fillBoundedInterval(yValues, minMaxValues[FunctionIf.Y]); if (yValues == null) { return; } // labels - labels[FunctionIf.X] = linkedIntervals.get(0).getName(); - labels[FunctionIf.Y] = linkedIntervals.get(1).getName(); + labels[FunctionIf.X] = xValuesEq.getName(); + labels[FunctionIf.Y] = yValuesEq.getName(); labels[FunctionIf.Z] = ""; // calculate z values @@ -708,14 +711,57 @@ void calculate(CalculaterTask thread) throws CancelException argValues[1][0] = new CalculatedValue(); } zValues = new double[xValues.length][yValues.length]; + if (isFunction1D) + { + calculate1D(xValuesEq, thread); + } + else + { + calculate2D(xValuesEq, yValuesEq, thread); + } + updateEqualBorders(minMaxValues[FunctionIf.Z]); + } + + private void calculate1D(Equation xValuesEq, CalculaterTask thread) throws CancelException + { + final CalculatedValue calcVal = new CalculatedValue(); + for (int i = 0; i < xValues.length; i++) + { + for (int j = 0; j < yValues.length; j++) + { + zValues[i][j] = Double.NaN; + } + + argValues[0][0].setValue(xValues[i]); + xValuesEq.setArgumentValues(argValues[0]); + calcVal.processRealTerm(thread, functionTerm); + final double zVal = calcVal.getReal(); + zValues[i][i] = zVal; + if (i == 0) + { + minMaxValues[FunctionIf.Z][FunctionIf.MIN] = minMaxValues[FunctionIf.Z][FunctionIf.MAX] = zVal; + } + else + { + minMaxValues[FunctionIf.Z][FunctionIf.MIN] = Math.min( + minMaxValues[FunctionIf.Z][FunctionIf.MIN], zVal); + minMaxValues[FunctionIf.Z][FunctionIf.MAX] = Math.max( + minMaxValues[FunctionIf.Z][FunctionIf.MAX], zVal); + } + } + } + + private void calculate2D(Equation xValuesEq, Equation yValuesEq, CalculaterTask thread) throws CancelException + { + final CalculatedValue calcVal = new CalculatedValue(); for (int i = 0; i < xValues.length; i++) { argValues[0][0].setValue(xValues[i]); - linkedIntervals.get(0).setArgumentValues(argValues[0]); + xValuesEq.setArgumentValues(argValues[0]); for (int j = 0; j < yValues.length; j++) { argValues[1][0].setValue(yValues[j]); - linkedIntervals.get(1).setArgumentValues(argValues[1]); + yValuesEq.setArgumentValues(argValues[1]); calcVal.processRealTerm(thread, functionTerm); final double zVal = calcVal.getReal(); zValues[i][j] = zVal; @@ -732,7 +778,6 @@ void calculate(CalculaterTask thread) throws CancelException } } } - updateEqualBorders(minMaxValues[FunctionIf.Z]); } } } diff --git a/app/src/main/java/com/mkulesh/micromath/plots/views/ContourPlotView.java b/app/src/main/java/com/mkulesh/micromath/plots/views/ContourPlotView.java index 1578ef0d..24f5047b 100644 --- a/app/src/main/java/com/mkulesh/micromath/plots/views/ContourPlotView.java +++ b/app/src/main/java/com/mkulesh/micromath/plots/views/ContourPlotView.java @@ -15,6 +15,7 @@ import android.content.Context; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; @@ -121,7 +122,9 @@ protected void drawContent(Canvas c, FunctionIf f) // z if (colorMapView != null) { - p.setColor(colorMapView.getPaletteColor(zVal[i][j], f.getMinMaxValues(FunctionIf.Z), 255)); + final int color = Double.isNaN(zVal[i][j]) ? Color.TRANSPARENT : + colorMapView.getPaletteColor(zVal[i][j], f.getMinMaxValues(FunctionIf.Z), 255); + p.setColor(color); } // draw diff --git a/app/src/main/java/com/mkulesh/micromath/plots/views/SurfacePlotView.java b/app/src/main/java/com/mkulesh/micromath/plots/views/SurfacePlotView.java index a1098d1f..cfc88c8a 100644 --- a/app/src/main/java/com/mkulesh/micromath/plots/views/SurfacePlotView.java +++ b/app/src/main/java/com/mkulesh/micromath/plots/views/SurfacePlotView.java @@ -171,6 +171,10 @@ public void renderSurface(FunctionIf function) { final double y = function.getYValues()[j]; double v = function.getZValues()[i][j]; + if (Double.isNaN(v)) + { + v = get1dValue(function.getZValues(), i, j); + } if (Double.isInfinite(v)) { v = Double.NaN; @@ -197,6 +201,19 @@ public void renderSurface(FunctionIf function) function.getMinMaxValues(FunctionIf.Z)[FunctionIf.MAX]); } + private double get1dValue(final double[][] zValues, int i, int j) + { + if (i > 0 && !Double.isNaN(zValues[i - 1][j])) + { + return zValues[i - 1][j]; + } + if (j > 0 && !Double.isNaN(zValues[i][j - 1])) + { + return zValues[i][j - 1]; + } + return Double.NaN; + } + public boolean isRendered() { return vertex != null; @@ -384,14 +401,13 @@ private void drawBoundingBox(Canvas canvas) */ private void drawBoxGridsLabels(Canvas canvas) { - boolean x_left = false, y_left = false; int i; factor_x = factor_y = 1; projector.project(p1, 0, 0, -10); poly_x[0] = p1.x; projector.project(p1, 10.5f, 0, -10); - y_left = p1.x > poly_x[0]; + boolean y_left = p1.x > poly_x[0]; i = p1.y; projector.project(p1, -10.5f, 0, -10); if (p1.y > i) @@ -400,7 +416,7 @@ private void drawBoxGridsLabels(Canvas canvas) y_left = p1.x > poly_x[0]; } projector.project(p1, 0, 10.5f, -10); - x_left = p1.x > poly_x[0]; + boolean x_left = p1.x > poly_x[0]; i = p1.y; projector.project(p1, 0, -10.5f, -10); if (p1.y > i)