Plotter
This commit is contained in:
parent
828f9fa07b
commit
13f12d5d14
@ -22,8 +22,6 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator.functions;
|
package org.solovyev.android.calculator.functions;
|
||||||
|
|
||||||
import static org.solovyev.android.calculator.functions.CppFunction.NO_ID;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
@ -59,9 +57,6 @@ import org.solovyev.android.calculator.keyboard.FloatingKeyboardWindow;
|
|||||||
import org.solovyev.android.calculator.view.EditTextCompat;
|
import org.solovyev.android.calculator.view.EditTextCompat;
|
||||||
import org.solovyev.common.math.MathRegistry;
|
import org.solovyev.common.math.MathRegistry;
|
||||||
|
|
||||||
import butterknife.Bind;
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -72,6 +67,11 @@ import javax.annotation.Nonnull;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import butterknife.Bind;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
|
import static org.solovyev.android.calculator.functions.CppFunction.NO_ID;
|
||||||
|
|
||||||
public abstract class BaseFunctionFragment extends BaseDialogFragment implements View.OnClickListener, View.OnFocusChangeListener, View.OnKeyListener {
|
public abstract class BaseFunctionFragment extends BaseDialogFragment implements View.OnClickListener, View.OnFocusChangeListener, View.OnKeyListener {
|
||||||
|
|
||||||
protected static final String ARG_FUNCTION = "function";
|
protected static final String ARG_FUNCTION = "function";
|
||||||
@ -274,12 +274,6 @@ public abstract class BaseFunctionFragment extends BaseDialogFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean validateName() {
|
protected boolean validateName() {
|
||||||
final String name = nameView.getText().toString();
|
|
||||||
if (!Engine.isValidName(name)) {
|
|
||||||
setError(nameLabel, getString(R.string.function_name_is_not_valid));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
clearError(nameLabel);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,14 +12,15 @@ import android.support.v7.app.AlertDialog;
|
|||||||
import org.solovyev.android.Activities;
|
import org.solovyev.android.Activities;
|
||||||
import org.solovyev.android.Check;
|
import org.solovyev.android.Check;
|
||||||
import org.solovyev.android.calculator.App;
|
import org.solovyev.android.calculator.App;
|
||||||
|
import org.solovyev.android.calculator.Engine;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.android.calculator.entities.EntityRemovalDialog;
|
import org.solovyev.android.calculator.entities.EntityRemovalDialog;
|
||||||
|
|
||||||
import jscl.math.function.Function;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import jscl.math.function.Function;
|
||||||
|
|
||||||
public class EditFunctionFragment extends BaseFunctionFragment {
|
public class EditFunctionFragment extends BaseFunctionFragment {
|
||||||
|
|
||||||
public EditFunctionFragment() {
|
public EditFunctionFragment() {
|
||||||
@ -103,10 +104,11 @@ public class EditFunctionFragment extends BaseFunctionFragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean validateName() {
|
protected boolean validateName() {
|
||||||
if (!super.validateName()) {
|
final String name = nameView.getText().toString();
|
||||||
|
if (!Engine.isValidName(name)) {
|
||||||
|
setError(nameLabel, getString(R.string.function_name_is_not_valid));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final String name = nameView.getText().toString();
|
|
||||||
final Function existingFunction = functionsRegistry.get(name);
|
final Function existingFunction = functionsRegistry.get(name);
|
||||||
if (existingFunction != null) {
|
if (existingFunction != null) {
|
||||||
if (!existingFunction.isIdDefined()) {
|
if (!existingFunction.isIdDefined()) {
|
||||||
|
@ -1,46 +1,46 @@
|
|||||||
package org.solovyev.android.calculator.plot;
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import org.solovyev.android.plotter.Function;
|
import org.solovyev.android.plotter.Function;
|
||||||
|
|
||||||
import jscl.math.Expression;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import jscl.math.Generic;
|
import jscl.math.Generic;
|
||||||
import jscl.math.JsclInteger;
|
import jscl.math.JsclInteger;
|
||||||
import jscl.math.NumericWrapper;
|
import jscl.math.NumericWrapper;
|
||||||
import jscl.math.function.Constant;
|
import jscl.math.function.CustomFunction;
|
||||||
import jscl.math.numeric.Complex;
|
import jscl.math.numeric.Complex;
|
||||||
import jscl.math.numeric.Numeric;
|
import jscl.math.numeric.Numeric;
|
||||||
import jscl.math.numeric.Real;
|
import jscl.math.numeric.Real;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class ExpressionFunction extends Function {
|
public class ExpressionFunction extends Function {
|
||||||
private static final Complex NaN = Complex.valueOf(Double.NaN, 0d);
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public final jscl.math.function.Function function;
|
public final jscl.math.function.Function function;
|
||||||
public final Constant xVariable;
|
|
||||||
public final Constant yVariable;
|
|
||||||
public final boolean imaginary;
|
public final boolean imaginary;
|
||||||
public final int arity;
|
public final int arity;
|
||||||
|
private final Generic[] parameters;
|
||||||
|
|
||||||
public ExpressionFunction(@Nonnull jscl.math.function.Function function, @Nullable Constant x,
|
public ExpressionFunction(@Nonnull jscl.math.function.Function function,
|
||||||
@Nullable Constant y, boolean imaginary) {
|
boolean imaginary) {
|
||||||
super(imaginary ? "Im(" + function.toString() + ")" : function.toString());
|
super(makeFunctionName(function, imaginary));
|
||||||
this.function = function;
|
this.function = function;
|
||||||
this.xVariable = x;
|
|
||||||
this.yVariable = y;
|
|
||||||
this.imaginary = imaginary;
|
this.imaginary = imaginary;
|
||||||
this.arity = countArity(x, y);
|
this.arity = function.getMaxParameters();
|
||||||
|
this.parameters = new Generic[this.arity];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int countArity(@Nullable Constant x, @Nullable Constant y) {
|
@Nonnull
|
||||||
if (x != null && y != null) {
|
private static String makeFunctionName(@Nonnull jscl.math.function.Function function, boolean imaginary) {
|
||||||
return 2;
|
String name = function.getName();
|
||||||
} else if (x == null && y == null) {
|
if (TextUtils.isEmpty(name)) {
|
||||||
return 0;
|
if (function instanceof CustomFunction) {
|
||||||
|
name = ((CustomFunction) function).getContent();
|
||||||
|
} else {
|
||||||
|
name = function.toString();
|
||||||
}
|
}
|
||||||
return 1;
|
}
|
||||||
|
return imaginary ? "Im(" + name + ")" : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -50,81 +50,53 @@ public class ExpressionFunction extends Function {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float evaluate() {
|
public float evaluate() {
|
||||||
final Complex value = calculate(function);
|
try {
|
||||||
if (imaginary) {
|
return unwrap(function.numeric());
|
||||||
return (float) value.imaginaryPart();
|
} catch (RuntimeException e) {
|
||||||
|
return Float.NaN;
|
||||||
}
|
}
|
||||||
return (float) value.realPart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float evaluate(float x) {
|
public float evaluate(float x) {
|
||||||
final Complex value = calculate(function, xVariable, x);
|
try {
|
||||||
if (imaginary) {
|
parameters[0] = new NumericWrapper(Real.valueOf(x));
|
||||||
return (float) value.imaginaryPart();
|
function.setParameters(parameters);
|
||||||
|
return unwrap(function.numeric());
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
return Float.NaN;
|
||||||
}
|
}
|
||||||
return (float) value.realPart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float evaluate(float x, float y) {
|
public float evaluate(float x, float y) {
|
||||||
final Complex value = calculate(function, xVariable, x, yVariable, y);
|
|
||||||
if (imaginary) {
|
|
||||||
return (float) value.imaginaryPart();
|
|
||||||
}
|
|
||||||
return (float) value.realPart();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
public static Complex calculate(jscl.math.function.Function function, Constant xVar,
|
|
||||||
float x, Constant yVar, float y) {
|
|
||||||
try {
|
|
||||||
Generic tmp = function.substitute(xVar, Expression.valueOf((double) x));
|
|
||||||
tmp = tmp.substitute(yVar, Expression.valueOf((double) y));
|
|
||||||
return unwrap(tmp.numeric());
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
return NaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
public static Complex calculate(jscl.math.function.Function function, Constant xVar,
|
|
||||||
float x) {
|
|
||||||
try {
|
|
||||||
return unwrap(function.substitute(xVar, Expression.valueOf((double) x)).numeric());
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
return NaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
public static Complex calculate(jscl.math.function.Function function) {
|
|
||||||
try {
|
try {
|
||||||
|
parameters[0] = new NumericWrapper(Real.valueOf(x));
|
||||||
|
parameters[1] = new NumericWrapper(Real.valueOf(y));
|
||||||
|
function.setParameters(parameters);
|
||||||
return unwrap(function.numeric());
|
return unwrap(function.numeric());
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
return NaN;
|
return Float.NaN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
public float unwrap(Generic numeric) {
|
||||||
public static Complex unwrap(Generic numeric) {
|
|
||||||
if (numeric instanceof JsclInteger) {
|
if (numeric instanceof JsclInteger) {
|
||||||
return Complex.valueOf(((JsclInteger) numeric).intValue(), 0d);
|
return ((JsclInteger) numeric).intValue();
|
||||||
} else if (numeric instanceof NumericWrapper) {
|
|
||||||
return unwrap(((NumericWrapper) numeric).content());
|
|
||||||
} else {
|
|
||||||
return NaN;
|
|
||||||
}
|
}
|
||||||
|
if (numeric instanceof NumericWrapper) {
|
||||||
|
return unwrap(((NumericWrapper) numeric).content());
|
||||||
|
}
|
||||||
|
return Float.NaN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
public float unwrap(Numeric content) {
|
||||||
public static Complex unwrap(Numeric content) {
|
|
||||||
if (content instanceof Real) {
|
if (content instanceof Real) {
|
||||||
return Complex.valueOf(((Real) content).doubleValue(), 0d);
|
return (float) ((Real) content).doubleValue();
|
||||||
} else if (content instanceof Complex) {
|
|
||||||
return ((Complex) content);
|
|
||||||
} else {
|
|
||||||
throw new ArithmeticException();
|
|
||||||
}
|
}
|
||||||
|
if (content instanceof Complex) {
|
||||||
|
return (float) (imaginary ? ((Complex) content).imaginaryPart() : ((Complex) content).realPart());
|
||||||
|
}
|
||||||
|
return Float.NaN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,6 @@ import android.view.View;
|
|||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
|
|
||||||
import org.solovyev.android.calculator.App;
|
import org.solovyev.android.calculator.App;
|
||||||
import org.solovyev.android.calculator.AppComponent;
|
import org.solovyev.android.calculator.AppComponent;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
@ -23,18 +21,18 @@ import org.solovyev.android.plotter.PlotIconView;
|
|||||||
import org.solovyev.android.plotter.Plotter;
|
import org.solovyev.android.plotter.Plotter;
|
||||||
import org.solovyev.android.plotter.meshes.MeshSpec;
|
import org.solovyev.android.plotter.meshes.MeshSpec;
|
||||||
|
|
||||||
import butterknife.Bind;
|
|
||||||
import jscl.math.function.Constant;
|
|
||||||
import jscl.math.function.CustomFunction;
|
|
||||||
import uz.shift.colorpicker.LineColorPicker;
|
|
||||||
import uz.shift.colorpicker.OnColorChangedListener;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import butterknife.Bind;
|
||||||
|
import jscl.math.function.Constant;
|
||||||
|
import jscl.math.function.CustomFunction;
|
||||||
|
import uz.shift.colorpicker.LineColorPicker;
|
||||||
|
import uz.shift.colorpicker.OnColorChangedListener;
|
||||||
|
|
||||||
public class PlotEditFunctionFragment extends BaseFunctionFragment
|
public class PlotEditFunctionFragment extends BaseFunctionFragment
|
||||||
implements SeekBar.OnSeekBarChangeListener {
|
implements SeekBar.OnSeekBarChangeListener {
|
||||||
@Inject
|
@Inject
|
||||||
@ -67,18 +65,10 @@ public class PlotEditFunctionFragment extends BaseFunctionFragment
|
|||||||
final PlotEditFunctionFragment fragment = new PlotEditFunctionFragment();
|
final PlotEditFunctionFragment fragment = new PlotEditFunctionFragment();
|
||||||
if (pf != null && pf.function instanceof ExpressionFunction) {
|
if (pf != null && pf.function instanceof ExpressionFunction) {
|
||||||
final Bundle args = new Bundle();
|
final Bundle args = new Bundle();
|
||||||
final String name =
|
|
||||||
pf.function.hasName() ? Strings.nullToEmpty(pf.function.getName()) : "";
|
|
||||||
final List<String> parameters = new ArrayList<>();
|
|
||||||
final ExpressionFunction ef = (ExpressionFunction) pf.function;
|
final ExpressionFunction ef = (ExpressionFunction) pf.function;
|
||||||
if (ef.xVariable != null) {
|
final List<String> parameters = new ArrayList<>(((CustomFunction) ef.function).getParameterNames());
|
||||||
parameters.add(ef.xVariable.getName());
|
|
||||||
}
|
|
||||||
if (ef.yVariable != null) {
|
|
||||||
parameters.add(ef.yVariable.getName());
|
|
||||||
}
|
|
||||||
args.putParcelable(ARG_FUNCTION, CppFunction
|
args.putParcelable(ARG_FUNCTION, CppFunction
|
||||||
.builder(name,
|
.builder(ef.function.getName(),
|
||||||
((CustomFunction) ef.function).getContent())
|
((CustomFunction) ef.function).getContent())
|
||||||
.withParameters(parameters)
|
.withParameters(parameters)
|
||||||
.withId(pf.function.getId())
|
.withId(pf.function.getId())
|
||||||
@ -168,7 +158,7 @@ public class PlotEditFunctionFragment extends BaseFunctionFragment
|
|||||||
final Constant x = parameters.size() > 0 ? new Constant(parameters.get(0)) : null;
|
final Constant x = parameters.size() > 0 ? new Constant(parameters.get(0)) : null;
|
||||||
final Constant y = parameters.size() > 1 ? new Constant(parameters.get(1)) : null;
|
final Constant y = parameters.size() > 1 ? new Constant(parameters.get(1)) : null;
|
||||||
final ExpressionFunction expressionFunction =
|
final ExpressionFunction expressionFunction =
|
||||||
new ExpressionFunction(function.toJsclBuilder().create(), x, y, false);
|
new ExpressionFunction(function.toJsclBuilder().create(), false);
|
||||||
final PlotFunction plotFunction = PlotFunction.create(expressionFunction,
|
final PlotFunction plotFunction = PlotFunction.create(expressionFunction,
|
||||||
applyMeshSpec());
|
applyMeshSpec());
|
||||||
final int id = function.getId();
|
final int id = function.getId();
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
package jscl.math;
|
package jscl.math;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import jscl.JsclMathEngine;
|
import jscl.JsclMathEngine;
|
||||||
import jscl.math.function.Constant;
|
import jscl.math.function.Constant;
|
||||||
import jscl.math.function.Constants;
|
import jscl.math.function.Constants;
|
||||||
@ -11,12 +17,6 @@ import jscl.math.numeric.Real;
|
|||||||
import jscl.math.numeric.Vector;
|
import jscl.math.numeric.Vector;
|
||||||
import jscl.mathml.MathML;
|
import jscl.mathml.MathML;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
public final class NumericWrapper extends Generic implements INumeric<NumericWrapper> {
|
public final class NumericWrapper extends Generic implements INumeric<NumericWrapper> {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@ -185,7 +185,7 @@ public final class NumericWrapper extends Generic implements INumeric<NumericWra
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Generic substitute(@Nonnull Variable variable, Generic generic) {
|
public Generic substitute(@Nonnull Variable variable, Generic generic) {
|
||||||
return null;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Generic expand() {
|
public Generic expand() {
|
||||||
|
Loading…
Reference in New Issue
Block a user