From 28e5b12e619cea5298c2c0cf04dd0878c556879c Mon Sep 17 00:00:00 2001 From: axexlck Date: Sun, 20 Oct 2024 15:22:33 +0200 Subject: [PATCH] WIP #1087 add ECharts implementataion --- .../matheclipse/core/basic/ToggleFeature.java | 5 + .../core/builtin/FunctionDefinitions.java | 1 + .../core/builtin/ManipulateFunction.java | 2 +- .../core/builtin/StructureFunctions.java | 101 ++- .../org/matheclipse/core/eval/Errors.java | 3 +- .../core/form/mathml/MathMLFormFactory.java | 2 +- .../core/form/output/DoubleFormFactory.java | 24 +- .../core/form/output/JSBuilder.java | 86 ++- .../form/output/JavaDoubleFormFactory.java | 17 +- .../form/output/JavaScriptFormFactory.java | 16 +- .../core/form/output/OutputFormFactory.java | 2 +- .../matheclipse/core/graphics/ECharts.java | 610 ++++++++++++++++++ .../core/graphics/GraphicsOptions.java | 64 +- .../core/reflection/system/DiscretePlot.java | 2 +- .../core/reflection/system/ListLinePlot.java | 118 +++- .../reflection/system/ListLogLinearPlot.java | 140 +++- .../reflection/system/ListLogLogPlot.java | 133 +++- .../core/reflection/system/ListLogPlot.java | 144 ++++- .../core/reflection/system/ListPlot.java | 197 +++++- .../core/reflection/system/ListPolarPlot.java | 2 +- .../core/reflection/system/ListStepPlot.java | 143 ++++ .../core/reflection/system/Plot.java | 69 +- .../matheclipse/core/sympy/plotting/Plot.java | 2 +- .../io/servlet/AJAXQueryServlet.java | 17 +- .../matheclipse/io/servlet/JSONBuilder.java | 14 + .../core/mathcell/BasePlotExample.java | 177 ++--- .../core/mathcell/ListLinePlotExample.java | 12 +- .../mathcell/ListLogLinearPlotExample.java | 21 + .../core/mathcell/ListLogLogPlotExample.java | 22 + .../core/mathcell/ListLogPlotExample.java | 22 + .../core/mathcell/ListPlotExample.java | 81 ++- .../core/mathcell/ListStepPlotExample.java | 25 + .../core/mathcell/PlotExample.java | 17 +- 33 files changed, 2057 insertions(+), 234 deletions(-) create mode 100644 symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/graphics/ECharts.java create mode 100644 symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListStepPlot.java create mode 100644 symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLogLinearPlotExample.java create mode 100644 symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLogLogPlotExample.java create mode 100644 symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLogPlotExample.java create mode 100644 symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListStepPlotExample.java diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/basic/ToggleFeature.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/basic/ToggleFeature.java index 38e2259b89..e2ccdecec8 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/basic/ToggleFeature.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/basic/ToggleFeature.java @@ -64,5 +64,10 @@ public class ToggleFeature { */ public static boolean SOLVE_DIOPHANTINE = true; + /** + * Use Apache ECharts for rendering some 2D plot functions. + */ + public static boolean JS_ECHARTS = false; + public static boolean SHOW_STEPS = true; } diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/FunctionDefinitions.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/FunctionDefinitions.java index 2e792f3b3c..087dac65a2 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/FunctionDefinitions.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/FunctionDefinitions.java @@ -80,6 +80,7 @@ private static void init() { S.ListPlot3D.setEvaluator(new org.matheclipse.core.reflection.system.ListPlot3D()); S.ListPointPlot3D.setEvaluator(new org.matheclipse.core.reflection.system.ListPointPlot3D()); S.ListPolarPlot.setEvaluator(new org.matheclipse.core.reflection.system.ListPolarPlot()); + S.ListStepPlot.setEvaluator(new org.matheclipse.core.reflection.system.ListStepPlot()); S.LogPlot.setEvaluator(new org.matheclipse.core.reflection.system.LogPlot()); S.LogLinearPlot.setEvaluator(new org.matheclipse.core.reflection.system.LogLinearPlot()); S.LogLogPlot.setEvaluator(new org.matheclipse.core.reflection.system.LogLogPlot()); diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/ManipulateFunction.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/ManipulateFunction.java index 7177ed50fb..e4f7b7f866 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/ManipulateFunction.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/ManipulateFunction.java @@ -1504,7 +1504,7 @@ private static IExpr boundingBox(IAST ast, double[] boundingbox, String function jsControl.append("board.suspendUpdate();\n"); jsControl.append(js); jsControl.append("board.unsuspendUpdate();\n"); - return F.JSFormData(jsControl.toString(), "jsxgraph"); + return F.JSFormData(jsControl.toString(), JSBuilder.JSXGRAPH_STR); } // private static void range(StringBuilder graphicControl, IAST plotRange, int steps, diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/StructureFunctions.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/StructureFunctions.java index 31535d9084..e127911e98 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/StructureFunctions.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/StructureFunctions.java @@ -7,8 +7,6 @@ import java.util.List; import java.util.Set; import java.util.function.Predicate; - -import org.matheclipse.core.basic.OperationSystem; import org.matheclipse.core.convert.Convert; import org.matheclipse.core.eval.Errors; import org.matheclipse.core.eval.EvalAttributes; @@ -21,12 +19,14 @@ import org.matheclipse.core.eval.interfaces.AbstractCoreFunctionEvaluator; import org.matheclipse.core.eval.interfaces.AbstractCoreFunctionOptionEvaluator; import org.matheclipse.core.eval.interfaces.AbstractFunctionEvaluator; +import org.matheclipse.core.eval.interfaces.AbstractFunctionOptionEvaluator; import org.matheclipse.core.eval.util.Lambda; import org.matheclipse.core.eval.util.OpenFixedSizeMap; import org.matheclipse.core.eval.util.OptionArgs; import org.matheclipse.core.expression.F; import org.matheclipse.core.expression.ImplementationStatus; import org.matheclipse.core.expression.S; +import org.matheclipse.core.generic.Comparators; import org.matheclipse.core.generic.Predicates; import org.matheclipse.core.generic.Predicates.IsBinaryFalse; import org.matheclipse.core.interfaces.IAST; @@ -66,6 +66,7 @@ private static class Initializer { private static void init() { S.Apply.setEvaluator(new Apply()); + S.MapApply.setEvaluator(new MapApply()); S.ByteCount.setEvaluator(new ByteCount()); S.Depth.setEvaluator(new Depth()); S.Exit.setEvaluator(new QuitExit()); @@ -87,6 +88,7 @@ private static void init() { S.ParallelMap.setEvaluator(new ParallelMap()); S.PatternOrder.setEvaluator(new PatternOrder()); S.Quit.setEvaluator(new QuitExit()); + S.ReverseSort.setEvaluator(new ReverseSort()); S.Scan.setEvaluator(new Scan()); S.Sort.setEvaluator(new Sort()); S.SortBy.setEvaluator(new SortBy()); @@ -186,30 +188,35 @@ private static void init() { * Apply(f, {a, b, c}, x + y) * */ - private static final class Apply extends AbstractCoreFunctionEvaluator { - + private static class Apply extends AbstractFunctionOptionEvaluator { @Override - public IExpr evaluate(IAST ast, EvalEngine engine) { - if (ast.argSize() < 2 || ast.argSize() > 4) { - return Errors.printArgMessage(ast, ARGS_2_4, engine); - } - IASTMutable evaledAST = ast.copy(); - evaledAST.setArgs(evaledAST.size(), (int i) -> engine.evaluate(evaledAST.get(i))); + public IExpr evaluate(final IAST ast, final int argSize, final IExpr[] option, + final EvalEngine engine, IAST originalAST) { + return apply(ast, argSize, option, engine); + } - int lastIndex = evaledAST.argSize(); - boolean heads = false; - final OptionArgs options = new OptionArgs(evaledAST.topHead(), evaledAST, lastIndex, engine); - IExpr option = options.getOption(S.Heads); - if (option.isPresent()) { - lastIndex--; - if (option.isTrue()) { - heads = true; - } - } else { - if (ast.argSize() == 4) { - return Errors.printArgMessage(ast, ARGS_2_3, engine); - } + public static IExpr apply(IAST ast, int argSize, IExpr[] option, EvalEngine engine) { + if (argSize < 2 || argSize > 4) { + return Errors.printArgMessage(ast, ARGS_2_4, engine); } + // IASTMutable evaledAST = ast.copy(); + // evaledAST.setArgs(evaledAST.size(), (int i) -> engine.evaluate(evaledAST.get(i))); + IAST evaledAST = ast; + int lastIndex = argSize; + boolean heads = option[0].isTrue(); + // final OptionArgs options = new OptionArgs(evaledAST.topHead(), evaledAST, lastIndex, + // engine); + // IExpr option = options.getOption(S.Heads); + // if (option.isPresent()) { + // lastIndex--; + // if (option.isTrue()) { + // heads = true; + // } + // } else { + // if (ast.argSize() == 4) { + // return Errors.printArgMessage(ast, ARGS_2_3, engine); + // } + // } IExpr arg1 = evaledAST.arg1(); IExpr arg2 = evaledAST.arg2(); @@ -255,6 +262,34 @@ public static IExpr evalApply(IExpr f, IExpr expr, IAST evaledAST, int lastIndex return F.NIL; } + @Override + public void setUp(final ISymbol newSymbol) { + setOptions(newSymbol, S.Heads, S.False); + } + + } + + private static final class MapApply extends Apply { + @Override + public IExpr evaluate(final IAST ast, final int argSize, final IExpr[] option, + final EvalEngine engine, IAST originalAST) { + if (argSize >= 2) { + IASTMutable applyFunction = ast.appendAtClone(3, F.CListC1); + applyFunction.set(0, S.Apply); + return super.evaluate(applyFunction, argSize + 1, option, engine, originalAST); + } + return F.NIL; + } + + @Override + public int[] expectedArgSize(IAST ast) { + return ARGS_1_3_2; + } + + @Override + public void setUp(final ISymbol newSymbol) { + setOptions(newSymbol, S.Heads, S.False); + } } private static class ByteCount extends AbstractCoreFunctionEvaluator { @@ -1763,6 +1798,26 @@ public void setUp(final ISymbol newSymbol) { } } + private static class ReverseSort extends Sort { + + @Override + public IExpr evaluate(final IAST ast, EvalEngine engine) { + IExpr arg2 = F.NIL; + Comparator comparator = Comparators.CANONICAL_COMPARATOR; + if (ast.isAST2()) { + arg2 = ast.arg2(); + comparator = new Predicates.IsBinaryFalse(arg2); + } + comparator = Comparators.reversedComparator(comparator); + return super.sortByComparator(comparator, ast, engine); + } + + @Override + public int[] expectedArgSize(IAST ast) { + return ARGS_1_2; + } + } + /** * * diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/eval/Errors.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/eval/Errors.java index f25f90d9db..76d686f71e 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/eval/Errors.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/eval/Errors.java @@ -7,8 +7,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - -import edu.jas.kern.PreemptingException; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -25,6 +23,7 @@ import org.matheclipse.core.interfaces.ISymbol; import org.matheclipse.core.patternmatching.IPatternMatcher; import org.matheclipse.parser.client.math.MathException; +import edu.jas.kern.PreemptingException; import io.pebbletemplates.pebble.PebbleEngine; import io.pebbletemplates.pebble.cache.PebbleCache; import io.pebbletemplates.pebble.node.BodyNode; diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/mathml/MathMLFormFactory.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/mathml/MathMLFormFactory.java index d217910de4..2bf00f5827 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/mathml/MathMLFormFactory.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/mathml/MathMLFormFactory.java @@ -2145,7 +2145,7 @@ private boolean convertOperator(final org.matheclipse.parser.client.operator.Ope return true; } if (list.size() == 4 && list.arg2().equals(F.CListC1)) { - convertInfixOperator(buf, list, ASTNodeFactory.APPLY_LEVEL_OPERATOR, precedence); + convertInfixOperator(buf, list, ASTNodeFactory.MAPAPPLY_OPERATOR, precedence); return true; } return false; diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/DoubleFormFactory.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/DoubleFormFactory.java index 747007fb0c..b7b9897fe4 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/DoubleFormFactory.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/DoubleFormFactory.java @@ -8,7 +8,6 @@ import org.hipparchus.linear.RealMatrix; import org.hipparchus.linear.RealVector; import org.matheclipse.core.basic.Config; -import org.matheclipse.core.basic.OperationSystem; import org.matheclipse.core.builtin.Algebra; import org.matheclipse.core.convert.AST2Expr; import org.matheclipse.core.eval.Errors; @@ -531,7 +530,7 @@ private void convertPlusOperatorReversed(final StringBuilder buf, final IAST plu IExpr arg1 = timesAST.arg1(); if (arg1.isNumber() && (((INumber) arg1).complexSign() < 0)) { - if (((INumber) arg1).isOne()) { + if (arg1.isOne()) { showOperator = false; } else { if (arg1.isMinusOne()) { @@ -864,11 +863,15 @@ public void convert(final StringBuilder buf, final IExpr o) { convertInternal(buf, expr, Integer.MIN_VALUE, false, true); } + public void convertExpr(final StringBuilder buf, final IExpr expr) { + convertInternal(buf, expr, Integer.MIN_VALUE, false, true); + } + protected void convertInternal(final StringBuilder buf, final IExpr o) { convertInternal(buf, o, Integer.MIN_VALUE, false, true); } - private void convertNumber(final StringBuilder buf, final INumber o, final int precedence, + protected void convertNumber(final StringBuilder buf, final INumber o, final int precedence, boolean caller) { if (o instanceof INum) { convertDouble(buf, (INum) o, precedence, caller); @@ -912,7 +915,7 @@ protected void convertInternal(final StringBuilder buf, final IExpr o, final int } } } - convertAST(buf, list, eval); + convertAST(buf, list, precedence, eval); return; } if (o instanceof IReal) { @@ -965,7 +968,7 @@ protected boolean convertOperator(final Operator operator, final IAST list, return true; } if (list.size() == 4 && list.arg2().equals(F.CListC1)) { - convertInfixOperator(head, buf, list, ASTNodeFactory.APPLY_LEVEL_OPERATOR, precedence); + convertInfixOperator(head, buf, list, ASTNodeFactory.MAPAPPLY_OPERATOR, precedence); return true; } return false; @@ -1253,12 +1256,15 @@ public void convertFunctionArgs(final StringBuilder buf, final IAST list) { * @param eval TODO * @throws IOException */ - public void convertAST(final StringBuilder buf, final IAST function, boolean eval) { + public void convertAST(final StringBuilder buf, final IAST function, final int precedence, + boolean eval) { if (function.isNumericFunction(true)) { try { - double value = EvalEngine.get().evalDouble(function); - buf.append("(" + value + ")"); - return; + INumber value = function.evalNumber(); + if (value != null) { + convertNumber(buf, value, precedence, NO_PLUS_CALL); + return; + } } catch (RuntimeException rex) { Errors.rethrowsInterruptException(rex); // diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/JSBuilder.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/JSBuilder.java index f11d2cd0b5..a67a5aab78 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/JSBuilder.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/JSBuilder.java @@ -49,43 +49,65 @@ public class JSBuilder { + ""; public static final String ECHARTS_IFRAME_TEMPLATE = // - "\n" + "\n" + "\n" + "\n" + "\n" // + + "\n" // + + "\n" // + + "\n" // + "\n" + "\n" + "\n" + "ECharts\n" + "\n" + "\n" // 1 - libraries + "`1`\n" - + "
\n" + + "
\n" + "\n" + + "
\n"// // 3 - JSFiddle string - + "`3`\n" + "
\n" + "\n" + ""; + + "`3`\n" // + + "\n" // + + ""; /** HTML template for Apache ECharts */ public static final String ECHARTS_TEMPLATE = // - "\n" + "\n" + "\n" + "ECharts\n" - // 1 - libraries - + "`1`\n" + "\n" + "\n" - + "
\n" - + "\n" + + "`2`\n" // + + "\n" // // 3 - JSFiddle string - + "`3`\n" // + "
\n"// + + "`3`\n" // + "\n" // + ""; // public static final String GRAPHICS2D_IFRAME_TEMPLATE = // - "\n" + "\n" + "\n" // + + "\n" // + + "\n" + "\n" + "\n" - + "\n" + "\n" + "Graphics 2D\n" + "\n" - + "\n" + "\n" + + "\n" // + + "\n" // + + "Graphics 2D\n"// + + "\n" // + + "\n" // + + "\n" // 1 - libraries + "`1`\n" // // + "\n" @@ -167,9 +189,13 @@ public class JSBuilder { + ""; // public static final String IMAGE_TEMPLATE = // - "\n" + "\n" + "\n" + "Image\n" - + "\n" + "\n" - + "
\n" + "\n" // + + "\n" // + + "\n" // + + "Image\n" // + + "\n" // + + "\n" // + + "
\n" // + " \n" // + "
\n" // + "\n" + ""; // @@ -194,7 +220,9 @@ public class JSBuilder { public static final String JSXGRAPH_TEMPLATE = // "\n" + "\n" + "\n" + "JSXGraph\n" // 1 - libraries - + "`1`\n" + "\n" + "\n" + + "`1`\n" // + + "\n"// + + "\n" // + "
\n" + "\n" // 3 - JSFiddle string - + "`3`\n" + "
" + "\n" + ""; + + "`3`\n" + "
" // + + "\n" // + + ""; public static final String PLOTLY_TEMPLATE = // "\n" + "\n" + "\n" + "Plotly\n" @@ -359,6 +389,21 @@ public class JSBuilder { "\n" + // ""; // + // output formats + public static final String HTML_STR = "html"; + public static final String PLAIN_STR = "plaintext"; + public static final String SYMJA_STR = "sinput"; + public static final String MATHML_STR = "mathml"; + public static final String LATEX_STR = "latex"; + public static final String MARKDOWN_STR = "markdown"; + public static final String MATHCELL_STR = "mathcell"; + public static final String JSXGRAPH_STR = "jsxgraph"; + public static final String PLOTLY_STR = "plotly"; + public static final String TREEFORM_STR = "treeform"; + public static final String TRACEFORM_STR = "traceform"; + public static final String MERMAID_STR = "mermaid"; + public static final String ECHARTS_STR = "echarts"; + private JSBuilder() {} public static String buildMermaid(String pageTemplate, String manipulateStr) { @@ -436,6 +481,7 @@ private static String buildModule(String pageTemplate, String manipulateStr, Str } return Errors.templateRender(pageTemplate, jsxGraphArgs); } + private static String build(String pageTemplate, String manipulateStr, String htmlStr, String[] css, String[] libs) { String[] jsxGraphArgs = new String[3]; diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/JavaDoubleFormFactory.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/JavaDoubleFormFactory.java index b0a125549c..44f362a8bd 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/JavaDoubleFormFactory.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/JavaDoubleFormFactory.java @@ -1,14 +1,12 @@ package org.matheclipse.core.form.output; import java.util.Map; - -import org.matheclipse.core.basic.OperationSystem; import org.matheclipse.core.eval.Errors; -import org.matheclipse.core.eval.EvalEngine; import org.matheclipse.core.expression.F; import org.matheclipse.core.expression.S; import org.matheclipse.core.interfaces.IAST; import org.matheclipse.core.interfaces.IExpr; +import org.matheclipse.core.interfaces.INumber; import org.matheclipse.core.interfaces.ISymbol; import com.google.common.collect.ImmutableMap; @@ -114,14 +112,15 @@ public static JavaDoubleFormFactory get() { } @Override - public void convertAST(final StringBuilder buf, final IAST function, boolean eval) { + public void convertAST(final StringBuilder buf, final IAST function, final int precedence, + boolean eval) { if (function.isNumericFunction(true)) { try { - double value = EvalEngine.get().evalDouble(function); - buf.append("("); - buf.append(value); - buf.append(")"); - return; + INumber value = function.evalNumber(); + if (value != null) { + convertNumber(buf, value, precedence, NO_PLUS_CALL); + return; + } } catch (RuntimeException rex) { Errors.rethrowsInterruptException(rex); // diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/JavaScriptFormFactory.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/JavaScriptFormFactory.java index 86b6fa410a..2190708260 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/JavaScriptFormFactory.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/JavaScriptFormFactory.java @@ -4,10 +4,8 @@ import java.util.List; import java.util.Map; import org.matheclipse.core.basic.Config; -import org.matheclipse.core.basic.OperationSystem; import org.matheclipse.core.builtin.PiecewiseFunctions; import org.matheclipse.core.eval.Errors; -import org.matheclipse.core.eval.EvalEngine; import org.matheclipse.core.eval.exception.ArgumentTypeException; import org.matheclipse.core.expression.F; import org.matheclipse.core.expression.ID; @@ -17,6 +15,7 @@ import org.matheclipse.core.interfaces.IComplex; import org.matheclipse.core.interfaces.IComplexNum; import org.matheclipse.core.interfaces.IExpr; +import org.matheclipse.core.interfaces.INumber; import org.matheclipse.core.interfaces.ISymbol; import org.matheclipse.parser.client.operator.Operator; import org.matheclipse.parser.client.operator.Precedence; @@ -375,12 +374,15 @@ public static JavaScriptFormFactory get() { } @Override - public void convertAST(final StringBuilder buf, final IAST function, boolean eval) { + public void convertAST(final StringBuilder buf, final IAST function, final int precedence, + boolean eval) { if (eval && function.isNumericFunction(true)) { try { - double value = EvalEngine.get().evalDouble(function); - buf.append("(" + value + ")"); - return; + INumber value = function.evalNumber(); + if (value != null) { + convertNumber(buf, value, precedence, NO_PLUS_CALL); + return; + } } catch (RuntimeException rex) { Errors.rethrowsInterruptException(rex); // @@ -780,7 +782,7 @@ protected boolean convertOperator(final Operator operator, final IAST list, final StringBuilder buf, final int precedence, ISymbol head) { if (!super.convertOperator(operator, list, buf, precedence, head)) { if (javascriptFlavor == USE_MATHCELL) { - convertAST(buf, list, true); + convertAST(buf, list, precedence, true); return true; } return false; diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/OutputFormFactory.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/OutputFormFactory.java index 66e75a9059..64ad87770c 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/OutputFormFactory.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/form/output/OutputFormFactory.java @@ -1640,7 +1640,7 @@ private boolean convertOperator(final Operator operator, final IAST list, final return true; } if (list.size() == 4 && list.arg2().equals(F.CListC1)) { - convertInfixOperator(buf, list, ASTNodeFactory.APPLY_LEVEL_OPERATOR, precedence); + convertInfixOperator(buf, list, ASTNodeFactory.MAPAPPLY_OPERATOR, precedence); return true; } return false; diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/graphics/ECharts.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/graphics/ECharts.java new file mode 100644 index 0000000000..eda46ea8c2 --- /dev/null +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/graphics/ECharts.java @@ -0,0 +1,610 @@ +package org.matheclipse.core.graphics; + +import org.matheclipse.core.eval.EvalEngine; +import org.matheclipse.core.eval.exception.ArgumentTypeException; +import org.matheclipse.core.eval.util.OptionArgs; +import org.matheclipse.core.expression.F; +import org.matheclipse.core.expression.S; +import org.matheclipse.core.form.output.JavaScriptFormFactory; +import org.matheclipse.core.interfaces.IAST; +import org.matheclipse.core.interfaces.IExpr; + +public class ECharts { + public final static int X_JSFORM = 0; + + public final static int X_FILLING = 1; + + public final static int X_AXES = 2; + + public final static int X_PLOTRANGE = 3; + + public final static int X_$SCALING = 4; + + public final static int X_JOINED = 5; + + public final static int X_PLOTLEGENDS = 6; + + public final static int X_PLOTLABEL = 7; + + public final static int X_AXESLABEL = 8; + + // public static final String DEFAULT_SERIES_NAME = "Series"; + + public static final String TYPE_CATEGORY = "category"; + + public static final String TYPE_LINE = "line"; + + public static final String TYPE_SCATTER = "scatter"; + + public static final String TYPE_VALUE = "value"; + + private static final String JSON_TEMPLATE = // + "option={\n" // + + " title: {\n" // + + " text: \"`title`\"\n" // + + " },\n" // + + " tooltip: {\n" // + + " trigger: \"axis\"\n" // + + " },\n" // + + " legend: {\n`legend`\n" // "data: ['Step Start', 'Step Middle', 'Step End']\n" // + + " },\n" // + + " grid: {\n" // + + " left: '3%',\n" // + + " right: '4%',\n" // + + " bottom: '3%',\n" // + + " containLabel: true\n" // + + " },\n" // + + " toolbox: {\n" // + + " feature: {\n" // + + " saveAsImage: {}\n" // + + " }\n" // + + " },\n" // + + " xAxis: {\n" // + + " `xaxis`\n" // + + " `xdata`\n" // + + " },\n" // + + " yAxis: {\n" // + + " `yaxis`\n" // + // + " type: 'log',\n" // + // + " name: 'y'" // + + " },\n" // + + " series: [\n`series`\n" // + // + " {\n" // + // + " name: 'Step Start',\n" // + // + " type: 'line',\n" // + // + " step: 'start',\n" // + // + " data: [120, 132, 101, 134, 90, 230, 210]\n" // + // + " },\n" // + + " ]\n" // + + "};"; + + + public static ECharts build(GraphicsOptions graphicsOptions, StringBuilder xAxisCategoryBuffer, + StringBuilder yAxisSeriesBuffer) { + String plotLabel = createPlotLabel(graphicsOptions); + ECharts echarts = new ECharts(graphicsOptions, plotLabel); + // // legend + String legends = createLegends(graphicsOptions); + echarts.setLegend(legends); + // x-axis categories + if (xAxisCategoryBuffer == null || xAxisCategoryBuffer.length() == 0) { + echarts.setXData(null); + } else { + echarts.setXData(xAxisCategoryBuffer.toString()); + } + + // y-axis series + echarts.setSeriesValues(yAxisSeriesBuffer.toString()); + // legend + return echarts; + } + + + protected static IAST getPoint2D(IExpr arg) { + if (arg.isList2()) { + return (IAST) arg; + } + if (arg.isASTSizeGE(S.Style, 1) // + || arg.isASTSizeGE(S.Labeled, 1)) { + if (arg.first().isList2()) { + return (IAST) arg.first(); + } + } + return F.NIL; + } + + protected static IExpr getPointY(IExpr arg) { + if (arg.isASTSizeGE(S.Style, 1) // + || arg.isASTSizeGE(S.Labeled, 1)) { + return arg.first(); + } + return arg; + } + + protected static boolean isNonReal(IExpr point) { + return point.isComplex() || point.isComplexNumeric() || point.isDirectedInfinity() + || point == S.Indeterminate || point == S.None || point.isAST(S.Missing); + } + + protected static boolean isNonReal(IExpr lastPointX, IExpr lastPointY) { + return isNonReal(lastPointX) || isNonReal(lastPointY); + } + + public static void seriesData(StringBuilder yAxisSeriesBuffer, IAST listOfLists, + GraphicsOptions graphicsOptions, String type, String step) { + double[] minMax = new double[] {Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY}; + final int argSize = listOfLists.argSize(); + String[] legends = createLegends(graphicsOptions, argSize); + for (int i = 1; i <= argSize; i++) { + IAST singlePointList = (IAST) listOfLists.get(i); + // y-axis values + StringBuilder yAxisString = new StringBuilder(); + // yAxisString.append( // + // "{\n" // + // + " name: '" + name + i + "',\n" // + // + " type: '" + type + "',\n"); // + String stepI = ""; + if (step != null && step.length() > 0) { + // step must contain a string with length greater than 0 + // yAxisString.append(" step: '" + step + i + "',\n"); + stepI = step + i; + } + ECharts.yAxisSingleSeries(yAxisString, singlePointList, legends[i - 1], type, stepI, minMax); + yAxisSeriesBuffer.append(yAxisString); + if (i < listOfLists.size() - 1) { + yAxisSeriesBuffer.append(",\n"); + } + } + } + + private static String createPlotLabel(GraphicsOptions graphicsOptions) { + IExpr plotLabel = graphicsOptions.plotLabel(); + if (plotLabel != S.None) { + return plotLabel.toString(); + } + return ""; + } + + private static String[] createLegends(GraphicsOptions graphicsOptions, final int argSize) { + String[] legends = new String[argSize]; + for (int i = 0; i < argSize; i++) { + legends[i] = ""; + } + IExpr plotLegends = graphicsOptions.plotLegends(); + if (plotLegends != S.None) { + if (plotLegends == S.Automatic) { + for (int i = 0; i < argSize; i++) { + legends[i] = "" + (i + 1); + } + } else if (plotLegends.isList()) { + IAST list = (IAST) plotLegends; + for (int i = 1; i < list.size(); i++) { + legends[i - 1] = list.get(i).toString(); + } + } else if (argSize == 1) { + legends[0] = plotLegends.toString(); + } + } + return legends; + } + + private static String createLegends(GraphicsOptions graphicsOptions) { + + IExpr plotLegends = graphicsOptions.plotLegends(); + if (plotLegends != S.None) { + if (plotLegends.isList() && plotLegends.argSize() > 0) { + StringBuilder legends = new StringBuilder(); + IAST list = (IAST) plotLegends; + for (int i = 1; i < list.size(); i++) { + legends.append("'"); + legends.append(list.get(i).toString()); + legends.append("'"); + if (i < list.argSize()) { + legends.append(", "); + } + } + return legends.toString(); + } + } + return ""; + } + + public static void setGraphicOptions(GraphicsOptions graphicsOptions, IAST plot, int startIndex, + IExpr[] options, EvalEngine engine) { + final OptionArgs optionArgs = new OptionArgs(plot.topHead(), plot, startIndex, engine, true); + if (!options[X_AXES].isFalse()) { + graphicsOptions.setAxes(options[X_AXES]); + } + if (options[X_AXESLABEL] != S.None) { + graphicsOptions.setAxesLabel(options[X_AXESLABEL]); + } + + if (options[X_JOINED].isTrue()) { + graphicsOptions.setJoined(true); + } + if (options[X_PLOTLEGENDS] != S.None) { + graphicsOptions.setPlotLegends(options[X_PLOTLEGENDS]); + } + if (options[X_PLOTLABEL] != S.None) { + graphicsOptions.setPlotLabel(options[X_PLOTLABEL]); + } + graphicsOptions.setOptions(optionArgs); + graphicsOptions.setScalingFunctions(options); + } + + public static void xAxisCategory(StringBuilder xAxisString, IAST pointList) { + for (int i = 1; i < pointList.size(); i++) { + xAxisString.append("'"); + xAxisString.append(i); + xAxisString.append("'"); + if (i < pointList.size() - 1) { + xAxisString.append(", "); + } + } + } + + public static void xyAxesPoint2D(IAST pointList2D, StringBuilder xAxisBuffer, + StringBuilder yAxisBuffer, GraphicsOptions graphicsOptions) { + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + xyAxesPoint2D(pointList2D, xAxisBuffer, yAxisBuffer, graphicsOptions, type, ""); + } + + public static void xyAxesPoint2D(IAST pointList2D, StringBuilder xAxisBuffer, + StringBuilder yAxisBuffer, GraphicsOptions graphicsOptions, String type, String step) { + + String[] legends = createLegends(graphicsOptions, 1); + yAxisBuffer.append( // + "{\n" // + + " name: '" + legends[0] + "',\n" // + + " showSymbol: false,\n" // + + " type: '" + type + "',\n"); + if (step != null && step.length() > 0) { + // step must contain a string with length greater than 0 + yAxisBuffer.append(" step: '" + step + "',\n"); + } + JavaScriptFormFactory toJS = + new JavaScriptFormFactory(true, false, -1, -1, JavaScriptFormFactory.USE_MATHCELL); + StringBuilder values = new StringBuilder(); + values.append(" data: ["); + // x-axis categories + // StringBuilder xAxisString = new StringBuilder(); + for (int i = 1; i < pointList2D.size(); i++) { + IAST list2 = (IAST) pointList2D.get(i); + IAST currentPointY = getPoint2D(list2); + + IExpr xValue = currentPointY.first(); + if (isNonReal(xValue)) { + xAxisBuffer.append("''"); + values.append("''"); + } else { + xAxisBuffer.append("'"); + toJS.convertExpr(xAxisBuffer, xValue); + xAxisBuffer.append("'"); + + IExpr yValue = currentPointY.second(); + if (isNonReal(yValue)) { + values.append("''"); + } else { + toJS.convertExpr(values, yValue); + } + } + if (i < pointList2D.size() - 1) { + values.append(", "); + xAxisBuffer.append(", "); + } + + } + values.append("]\n"); + yAxisBuffer.append(values); + yAxisBuffer.append("}\n"); + } + + public static void yAxisSingleSeries(StringBuilder yAxisBuffer, IAST pointList, + GraphicsOptions graphicsOptions, double[] minMax) { + String[] legends = createLegends(graphicsOptions, 1); + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + yAxisSingleSeries(yAxisBuffer, pointList, legends[0], type, "", minMax); + } + + public static void yAxisSingleSeries(StringBuilder yAxisBuffer, IAST pointList, + GraphicsOptions graphicsOptions, String type, String step, double[] minMax) { + String[] legends = createLegends(graphicsOptions, 1); + yAxisSingleSeries(yAxisBuffer, pointList, legends[0], type, step, minMax); + } + + public static void yAxisSingleSeries(StringBuilder yAxisBuffer, IAST pointList, String name, + String type, String step, double[] minMax) { + yAxisBuffer.append( // + "{\n" // + + " name: '" + name + "',\n" // + + " showSymbol: false,\n" // + + " type: '" + type + "',\n"); + if (step != null && step.length() > 0) { + // step must contain a string with length greater than 0 + yAxisBuffer.append(" step: '" + step + "',\n"); + } + JavaScriptFormFactory toJS = + new JavaScriptFormFactory(true, false, -1, -1, JavaScriptFormFactory.USE_MATHCELL); + StringBuilder values = new StringBuilder(); + values.append(" data: ["); + yAxisSingleSeriesRecursive(values, pointList, toJS, minMax); + values.append("]\n"); + yAxisBuffer.append(values); + yAxisBuffer.append("}\n"); + } + + + private static void yAxisSingleSeriesRecursive(StringBuilder values, IAST pointList, + JavaScriptFormFactory toJS, double[] minMax) { + if (pointList.isListOfPoints(2)) { + for (int i = 1; i < pointList.size(); i++) { + IExpr arg = pointList.get(i); + IExpr xExpr = arg.first(); + IExpr yExpr = getPointY(arg.second()); + if (isNonReal(xExpr) || isNonReal(yExpr)) { + values.append("''"); + } else { + try { + double xValue = xExpr.evalf(); + if (xValue > minMax[1]) { + minMax[1] = xValue; + } + if (xValue < minMax[0]) { + minMax[0] = xValue; + } + double yValue = yExpr.evalf(); + if (yValue > minMax[3]) { + minMax[3] = yValue; + } + if (yValue < minMax[2]) { + minMax[2] = yValue; + } + } catch (ArgumentTypeException e) { + // yValue isn't real ? + } + toJS.convertExpr(values, arg); + } + if (i < pointList.size() - 1) { + values.append(", "); + } + } + } else { + if (pointList.isListOfLists()) { + for (int i = 1; i < pointList.size(); i++) { + yAxisSingleSeriesRecursive(values, (IAST) pointList.get(i), toJS, minMax); + } + + } else { + // assume a list of values + for (int i = 1; i < pointList.size(); i++) { + IExpr yExpr = getPointY(pointList.get(i)); + if (isNonReal(yExpr)) { + values.append("''"); + } else { + try { + double xValue = i; + if (xValue > minMax[1]) { + minMax[1] = xValue; + } else if (xValue < minMax[0]) { + minMax[0] = xValue; + } + double yValue = yExpr.evalf(); + if (yValue > minMax[3]) { + minMax[3] = yValue; + } else if (yValue < minMax[2]) { + minMax[2] = yValue; + } + } catch (ArgumentTypeException e) { + // yValue isn't real ? + } + toJS.convertExpr(values, yExpr); + } + if (i < pointList.size() - 1) { + values.append(", "); + } + } + } + } + } + + String jsonStr = JSON_TEMPLATE; + + final GraphicsOptions graphicsOptions; + + public ECharts(GraphicsOptions graphicsOptions) { + this.graphicsOptions = graphicsOptions; + } + + public ECharts(GraphicsOptions graphicsOptions, String plotLabel) { + this.graphicsOptions = graphicsOptions; + setTitle(plotLabel); + } + + public String getJSONStr() { + return jsonStr; + } + + public String setLegend(String legend) { + jsonStr = jsonStr.replace("`legend`", "data: [" + legend + "]"); + return jsonStr; + } + + public String setSeriesValues(String ydata) { + jsonStr = jsonStr.replace("`series`", ydata); + return jsonStr; + } + + public String setTitle(String title) { + jsonStr = jsonStr.replace("`title`", title); + return jsonStr; + } + + /** + * Set x-axis to type "category". + * + * @return + */ + public String setXAxis() { + return setXAxis("category"); + } + + /** + * Set x-axis to the specified type. + * + * @param type + * @return + */ + public String setXAxis(String type) { + jsonStr = jsonStr.replace("`xaxis`", // + "type: '" + type + "',\n" // + + " show: " + isXAxis() + ",\n" // show x-axis + + " name: '" + xAxisLabel() + "',"); + return jsonStr; + } + + public String setXAxisPlot() { + jsonStr = jsonStr.replace("`xaxis`", // + "name: '" + xAxisLabel() + "', \n" // + + " minorTick: { \n" // + + " show: true\n" // + + " },\n" // + + " minorSplitLine: { \n" // + + " show: true\n" // + + " }"); // + return jsonStr; + } + + + private boolean isXAxis() { + IExpr axes = graphicsOptions.axes(); + if (axes == S.True) { + return true; + } + if (axes == S.False) { + return false; + } + if (axes.isList() && axes.argSize() > 0) { + return axes.first().isTrue(); + } + return false; + } + + private String xAxisLabel() { + IExpr axesLabel = graphicsOptions.axesLabel(); + if (axesLabel == S.Automatic) { + // TODO + return ""; + } + if (axesLabel == S.None) { + return ""; + } + if (axesLabel.isList() && axesLabel.argSize() > 0) { + IExpr labelX = axesLabel.first(); + if (labelX == S.Automatic) { + // TODO + return ""; + } + if (labelX == S.None) { + return ""; + } + return labelX.toString(); + } + return axesLabel.toString(); + } + + public String setXData(String xdata) { + if (xdata == null) { + jsonStr = jsonStr.replace("`xdata`", ""); + return jsonStr; + } + jsonStr = jsonStr.replace("`xdata`", "data: [" + xdata + "]"); + return jsonStr; + } + + public String setYAxis() { + return setYAxis("value"); + } + + public String setYAxis(String type) { + // + " type: 'log',\n" // + // + " name: 'y'" // + jsonStr = jsonStr.replace(// + "`yaxis`", // + "type: '" + type + "',\n" // + + " show: " + isYAxis() + ",\n" // show y-axis + + " name: '" + yAxisLabel() + "'"); + return jsonStr; + } + + public String setYAxisPlot(double yMin, double yMax) { + if (!Double.isFinite(yMin)) { + yMin = 0.0; + } + if (!Double.isFinite(yMax)) { + yMax = 100.0; + } + if (yMin > yMax) { + yMax = yMin + 1; + } + + + yMin = Math.floor(yMin); + yMax = Math.ceil(yMax); + double diff = yMax - yMin; + if (yMin > 0 && diff < 50 && diff >= 0.0) { + yMin = 0.0; + } else if (yMin < 0 && diff > -50 && diff <= 0.0) { + yMin = 0.0; + } + + jsonStr = jsonStr.replace("`yaxis`", // + "name: '" + yAxisLabel() + "', \n" // + + " min: " + yMin + ",\n" // + + " max: " + yMax + ",\n" // + + " minorTick: {\n" // + + " show: true\n" // + + " },\n" // + + " minorSplitLine: {\n" // + + " show: true\n" // + + " }"); // + return jsonStr; + } + + private boolean isYAxis() { + IExpr axes = graphicsOptions.axes(); + if (axes == S.True) { + return true; + } + if (axes == S.False) { + return false; + } + if (axes.isList() && axes.argSize() > 1) { + return axes.second().isTrue(); + } + return false; + } + + private String yAxisLabel() { + IExpr axesLabel = graphicsOptions.axesLabel(); + if (axesLabel == S.Automatic) { + // TODO + return ""; + } + if (axesLabel == S.None) { + return ""; + } + if (axesLabel.isList() && axesLabel.argSize() > 1) { + IExpr labelY = axesLabel.second(); + if (labelY == S.Automatic) { + // TODO + return ""; + } + if (labelY == S.None) { + return ""; + } + return labelY.toString(); + } + return ""; + } +} diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/graphics/GraphicsOptions.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/graphics/GraphicsOptions.java index d12b64cda6..ac30d0e235 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/graphics/GraphicsOptions.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/graphics/GraphicsOptions.java @@ -2,8 +2,6 @@ import java.util.Locale; import java.util.function.Function; - -import org.matheclipse.core.basic.OperationSystem; import org.matheclipse.core.builtin.GraphicsFunctions; import org.matheclipse.core.convert.Convert; import org.matheclipse.core.convert.RGBColor; @@ -14,6 +12,7 @@ import org.matheclipse.core.expression.F; import org.matheclipse.core.expression.S; import org.matheclipse.core.interfaces.IAST; +import org.matheclipse.core.interfaces.IBuiltInSymbol; import org.matheclipse.core.interfaces.IExpr; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -332,6 +331,14 @@ public boolean setHueColor(ArrayNode arrayNode, IAST hueColor) { */ boolean joined = false; + IExpr axes = S.False; + + IExpr axesLabel = S.None; + + IExpr plotLabel = S.None; + + IExpr plotLegends = S.None; + double[] boundingbox = new double[] {Double.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE, Double.MIN_VALUE}; @@ -601,6 +608,22 @@ public OptionArgs options() { return options; } + public IExpr axes() { + return axes; + } + + public IExpr axesLabel() { + return axesLabel; + } + + public IExpr plotLabel() { + return plotLabel; + } + + public IExpr plotLegends() { + return plotLegends; + } + /** * Return PlotRange (extent) option rule. * @@ -647,6 +670,14 @@ public double pointSize(IAST pointSizeAST) { return pointSize; } + public void setAxes(IExpr axes) { + this.axes = axes; + } + + public void setAxesLabel(IExpr axesLabel) { + this.axesLabel = axesLabel; + } + public void setBoundingBox(double[] boundingbox) { this.boundingbox = boundingbox; } @@ -751,6 +782,14 @@ public void setOptions(OptionArgs options) { this.options = options; } + public void setPlotLabel(IExpr plotLabel) { + this.plotLabel = plotLabel; + } + + public void setPlotLegends(IExpr plotLegends) { + this.plotLegends = plotLegends; + } + public void setPointSize(double pointSize) { this.pointSize = pointSize; } @@ -779,9 +818,10 @@ public void setRGBColor(IAST color) { rgbColor = F.RGBColor(0.0, 0.0, 0.0); } - public void setScalingFunctions() { - OptionArgs options = options(); - IExpr scalingFunctions = options.getOption(S.$Scaling); + public void setScalingFunctions(IExpr[] options) { + // OptionArgs options = options(); + // IExpr scalingFunctions = options.getOption(S.$Scaling); + IExpr scalingFunctions = options[ECharts.X_$SCALING]; if (scalingFunctions.isPresent()) { if (scalingFunctions.isList1()) { setXFunction(getScaling(scalingFunctions.first())); @@ -838,4 +878,18 @@ public Function yFunction() { public String yScale() { return yScale; } + + public static IBuiltInSymbol[] listPlotDefaultOptionKeys() { + return new IBuiltInSymbol[] {// + S.JSForm, S.Filling, S.Axes, S.PlotRange, S.$Scaling, // + S.Joined, // + S.PlotLegends, S.PlotLabel, S.AxesLabel}; + } + + public static IExpr[] listPlotDefaultOptionValues(boolean joined) { + return new IExpr[] {// + S.False, S.None, S.True, S.Automatic, S.Automatic, // + joined ? S.True : S.False, // + S.None, S.None, S.None}; + } } diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/DiscretePlot.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/DiscretePlot.java index 965adc42c9..654c6f716b 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/DiscretePlot.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/DiscretePlot.java @@ -41,7 +41,7 @@ public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, GraphicsOptions graphicsOptions = new GraphicsOptions(engine); IASTMutable listPlot = ast.removeAtCopy(2); listPlot.set(1, tableValues); - IAST graphicsPrimitives = listPlot(listPlot, graphicsOptions, engine); + IAST graphicsPrimitives = listPlot(listPlot, options, graphicsOptions, engine); if (graphicsPrimitives.isPresent()) { graphicsOptions.addPadding(); IAST listOfOptions = F.List(F.Rule(S.Filling, S.Axis), // diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLinePlot.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLinePlot.java index 978fa247ba..8c7f9842f6 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLinePlot.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLinePlot.java @@ -1,26 +1,128 @@ package org.matheclipse.core.reflection.system; +import org.matheclipse.core.basic.ToggleFeature; import org.matheclipse.core.eval.EvalEngine; import org.matheclipse.core.expression.F; import org.matheclipse.core.expression.ID; import org.matheclipse.core.expression.ImplementationStatus; import org.matheclipse.core.expression.S; +import org.matheclipse.core.graphics.ECharts; import org.matheclipse.core.graphics.GraphicsOptions; import org.matheclipse.core.interfaces.IAST; +import org.matheclipse.core.interfaces.IAssociation; import org.matheclipse.core.interfaces.IExpr; +import org.matheclipse.core.interfaces.ISymbol; /** Plot a list of Points as a single line */ public class ListLinePlot extends ListPlot { - /** Constructor for the singleton */ - // public final static ListLinePlot CONST = new ListLinePlot(); - public ListLinePlot() {} + @Override + public IExpr evaluateECharts(IAST ast, final int argSize, final IExpr[] options, + final EvalEngine engine, IAST originalAST) { + if (argSize > 0 && argSize < ast.size()) { + ast = ast.copyUntil(argSize + 1); + } + StringBuilder jsControl = new StringBuilder(); + GraphicsOptions graphicsOptions = new GraphicsOptions(engine); + String graphicsPrimitivesStr = listLinePlot(ast, options, graphicsOptions, engine); + if (graphicsPrimitivesStr != null) { + jsControl.append( + "var eChart = echarts.init(document.getElementById('main'),{width:'100%',height:'100%'});\n"); + jsControl.append(graphicsPrimitivesStr); + jsControl.append("\neChart.setOption(option);"); + + return F.JSFormData(jsControl.toString(), "echarts"); + } + return F.NIL; + } + + protected static String listLinePlot(IAST plot, IExpr[] options, GraphicsOptions graphicsOptions, + EvalEngine engine) { + if (plot.size() < 2) { + return null; + } + ECharts.setGraphicOptions(graphicsOptions, plot, 2, options, engine); + + IExpr arg1 = plot.arg1(); + if (!arg1.isList()) { + arg1 = engine.evaluate(arg1); + } + if (arg1.isAssociation()) { + IAssociation assoc = ((IAssociation) arg1); + arg1 = assoc.matrixOrList(); + } + if (arg1.isNonEmptyList()) { + IAST pointList = (IAST) arg1; + // TODO Labeled lists + if (pointList.isList()) {// x -> x.isList())) { + if (pointList.isListOfPoints(2)) { + return point2DListLinePlot(pointList, graphicsOptions); + } + if (pointList.isListOfLists()) { + IAST listOfLists = pointList; + StringBuilder yAxisSeriesBuffer = new StringBuilder(); + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + ECharts.seriesData(yAxisSeriesBuffer, listOfLists, graphicsOptions, type, ""); + StringBuilder xAxisCategoryBuffer = new StringBuilder(); + ECharts.xAxisCategory(xAxisCategoryBuffer, (IAST) listOfLists.arg1()); + ECharts echarts = ECharts.build(graphicsOptions, xAxisCategoryBuffer, yAxisSeriesBuffer); + echarts.setXAxis(); + echarts.setYAxis("value"); + return echarts.getJSONStr(); + } + + } + return yValueListLinePlot(pointList, graphicsOptions); + } + return null; + } + + /** + * Plot a list of 2D points. + * + * @param pointList2D list of 2D points + * @return + */ + private static String point2DListLinePlot(IAST pointList2D, GraphicsOptions graphicsOptions) { + StringBuilder xAxisString = new StringBuilder(); + StringBuilder yAxisString = new StringBuilder(); + // yAxisString.append( // + // "{\n" // + // + " name: 'List 1',\n" // + // + " type: 'line',\n"); + ECharts.xyAxesPoint2D(pointList2D, xAxisString, yAxisString, graphicsOptions); + + ECharts echarts = ECharts.build(graphicsOptions, xAxisString, yAxisString); + echarts.setXAxis(); + echarts.setYAxis("value"); + return echarts.getJSONStr(); + } + + private static String yValueListLinePlot(IAST pointList, GraphicsOptions graphicsOptions) { + double[] minMax = new double[] {Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY}; + // y-axis values + StringBuilder yAxisString = new StringBuilder(); + ECharts.yAxisSingleSeries(yAxisString, pointList, graphicsOptions, minMax); + + // x-axis categories + StringBuilder xAxisString = new StringBuilder(); + ECharts.xAxisCategory(xAxisString, pointList); + ECharts echarts = ECharts.build(graphicsOptions, xAxisString, yAxisString); + echarts.setXAxis(); + echarts.setYAxis("value"); + return echarts.getJSONStr(); + } + + @Override public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, final EvalEngine engine, IAST originalAST) { - + if (ToggleFeature.JS_ECHARTS) { + return evaluateECharts(ast, argSize, options, engine, originalAST); + } if (argSize > 0 && argSize < ast.size()) { ast = ast.copyUntil(argSize + 1); } @@ -34,7 +136,7 @@ public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, final GraphicsOptions graphicsOptions = new GraphicsOptions(engine); graphicsOptions.setJoined(true); - IAST graphicsPrimitives = listPlot(ast, graphicsOptions, engine); + IAST graphicsPrimitives = listPlot(ast, options, graphicsOptions, engine); if (graphicsPrimitives.isPresent()) { graphicsOptions.addPadding(); IAST listOfOptions = F.List(F.Rule(S.Axes, S.True), // @@ -49,4 +151,10 @@ public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, final public int status() { return ImplementationStatus.PARTIAL_SUPPORT; } + + @Override + public void setUp(final ISymbol newSymbol) { + setOptions(newSymbol, GraphicsOptions.listPlotDefaultOptionKeys(), + GraphicsOptions.listPlotDefaultOptionValues(true)); + } } diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLogLinearPlot.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLogLinearPlot.java index 644efe0201..92fd9d39cc 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLogLinearPlot.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLogLinearPlot.java @@ -1,24 +1,154 @@ package org.matheclipse.core.reflection.system; +import org.matheclipse.core.basic.ToggleFeature; import org.matheclipse.core.eval.EvalEngine; import org.matheclipse.core.expression.F; import org.matheclipse.core.expression.ImplementationStatus; import org.matheclipse.core.expression.S; +import org.matheclipse.core.graphics.ECharts; import org.matheclipse.core.graphics.GraphicsOptions; import org.matheclipse.core.interfaces.IAST; +import org.matheclipse.core.interfaces.IAssociation; import org.matheclipse.core.interfaces.IExpr; +import org.matheclipse.core.interfaces.ISymbol; public class ListLogLinearPlot extends ListPlot { + @Override - public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, + public IExpr evaluateECharts(IAST ast, final int argSize, final IExpr[] options, final EvalEngine engine, IAST originalAST) { if (argSize > 0 && argSize < ast.size()) { ast = ast.copyUntil(argSize + 1); } + StringBuilder jsControl = new StringBuilder(); + GraphicsOptions graphicsOptions = new GraphicsOptions(engine); + String graphicsPrimitivesStr = listLogLinearPlot(ast, options, graphicsOptions, engine); + if (graphicsPrimitivesStr != null) { + jsControl.append("var eChart = echarts.init(document.getElementById('main'));\n"); + jsControl.append(graphicsPrimitivesStr); + jsControl.append("\neChart.setOption(option);"); + + return F.JSFormData(jsControl.toString(), "echarts"); + } + return F.NIL; + } + + protected static String listLogLinearPlot(IAST plot, IExpr[] options, + GraphicsOptions graphicsOptions, EvalEngine engine) { + if (plot.size() < 2) { + return null; + } + ECharts.setGraphicOptions(graphicsOptions, plot, 2, options, engine); + // final OptionArgs optionArgs = new OptionArgs(plot.topHead(), plot, 2, engine, true); + // if (options[ECharts.X_JOINED].isTrue()) { + // graphicsOptions.setJoined(true); + // } + // graphicsOptions.setOptions(optionArgs); + // graphicsOptions.setScalingFunctions(options); + + IExpr arg1 = plot.arg1(); + if (!arg1.isList()) { + arg1 = engine.evaluate(arg1); + } + if (arg1.isAssociation()) { + IAssociation assoc = ((IAssociation) arg1); + arg1 = assoc.matrixOrList(); + } + if (arg1.isNonEmptyList()) { + IAST pointList = (IAST) arg1; + // TODO Labeled lists + if (pointList.isList()) { + if (pointList.isListOfPoints(2)) { + return point2DListLogLinearPlot(pointList, graphicsOptions); + } + if (pointList.isListOfLists()) { + IAST listOfLists = pointList; + + StringBuilder yAxisSeriesBuffer = new StringBuilder(); + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + ECharts.seriesData(yAxisSeriesBuffer, listOfLists, graphicsOptions, type, ""); + StringBuilder xAxisCategoryBuffer = new StringBuilder(); + ECharts.xAxisCategory(xAxisCategoryBuffer, (IAST) listOfLists.arg1()); + ECharts echarts = ECharts.build(graphicsOptions, xAxisCategoryBuffer, yAxisSeriesBuffer); + echarts.setXAxis("log"); + echarts.setYAxis("value"); + return echarts.getJSONStr(); + } + + } + return yValueListLogLinearPlot(pointList, graphicsOptions); + } + return null; + } + + /** + * Plot a list of 2D points. + * + * @param pointList2D list of 2D points + * @return + */ + private static String point2DListLogLinearPlot(IAST pointList2D, + GraphicsOptions graphicsOptions) { + StringBuilder xAxisString = new StringBuilder(); + StringBuilder yAxisString = new StringBuilder(); + // yAxisString.append( // + // "{\n" // + // + " name: 'ListLogLinearPlot',\n" // + // + " type: 'line',\n"); + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + ECharts.xyAxesPoint2D(pointList2D, xAxisString, yAxisString, graphicsOptions, type, ""); + + // ECharts echarts = new ECharts("ListLogPlot"); + // // legend + // echarts.setLegend(""); + // // x-axis categories + // echarts.setXAxis(); + // echarts.setXData(xAxisString.toString()); + // // y-axis series + // echarts.setYAxis("log", ""); + // echarts.setSeriesValues(yAxisString.toString()); + + ECharts echarts = ECharts.build(graphicsOptions, xAxisString, yAxisString); + echarts.setXAxis("log"); + echarts.setYAxis("value"); + return echarts.getJSONStr(); + } + + private static String yValueListLogLinearPlot(IAST pointList, GraphicsOptions graphicsOptions) { + double[] minMax = new double[] {Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY}; + // y-axis values + StringBuilder yAxisString = new StringBuilder(); + // yAxisString.append( // + // "{\n" // + // + " name: 'ListLogLogPlot',\n" // + // + " type: 'line',\n"); + ECharts.yAxisSingleSeries(yAxisString, pointList, graphicsOptions, minMax); + // yAxisSingleSeries(yAxisString, pointList, ""); + + // x-axis categories + StringBuilder xAxisString = new StringBuilder(); + ECharts.xAxisCategory(xAxisString, pointList); + + ECharts echarts = ECharts.build(graphicsOptions, xAxisString, yAxisString); + echarts.setXAxis("log"); + echarts.setYAxis("value"); + return echarts.getJSONStr(); + } + + @Override + public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, final EvalEngine engine, + IAST originalAST) { + if (ToggleFeature.JS_ECHARTS) { + return evaluateECharts(ast, argSize, options, engine, originalAST); + } + if (argSize > 0 && argSize < ast.size()) { + ast = ast.copyUntil(argSize + 1); + } GraphicsOptions graphicsOptions = new GraphicsOptions(engine); graphicsOptions.setXFunction(x -> F.Log10(x)); graphicsOptions.setXScale("Log10"); - IAST graphicsPrimitives = listPlot(ast, graphicsOptions, engine); + IAST graphicsPrimitives = listPlot(ast, options, graphicsOptions, engine); if (graphicsPrimitives.isPresent()) { graphicsOptions.addPadding(); IAST listOfOptions = F.List(// @@ -34,4 +164,10 @@ public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, public int status() { return ImplementationStatus.EXPERIMENTAL; } + + @Override + public void setUp(final ISymbol newSymbol) { + setOptions(newSymbol, GraphicsOptions.listPlotDefaultOptionKeys(), + GraphicsOptions.listPlotDefaultOptionValues(false)); + } } diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLogLogPlot.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLogLogPlot.java index 6e775a5db2..c0b521f5a8 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLogLogPlot.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLogLogPlot.java @@ -1,26 +1,149 @@ package org.matheclipse.core.reflection.system; +import org.matheclipse.core.basic.ToggleFeature; import org.matheclipse.core.eval.EvalEngine; import org.matheclipse.core.expression.F; import org.matheclipse.core.expression.ImplementationStatus; import org.matheclipse.core.expression.S; +import org.matheclipse.core.graphics.ECharts; import org.matheclipse.core.graphics.GraphicsOptions; import org.matheclipse.core.interfaces.IAST; +import org.matheclipse.core.interfaces.IAssociation; import org.matheclipse.core.interfaces.IExpr; +import org.matheclipse.core.interfaces.ISymbol; public class ListLogLogPlot extends ListPlot { + public ListLogLogPlot() {} + @Override - public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, + public IExpr evaluateECharts(IAST ast, final int argSize, final IExpr[] options, final EvalEngine engine, IAST originalAST) { if (argSize > 0 && argSize < ast.size()) { ast = ast.copyUntil(argSize + 1); } + StringBuilder jsControl = new StringBuilder(); + GraphicsOptions graphicsOptions = new GraphicsOptions(engine); + String graphicsPrimitivesStr = listLogLogPlot(ast, options, graphicsOptions, engine); + if (graphicsPrimitivesStr != null) { + jsControl.append("var eChart = echarts.init(document.getElementById('main'));\n"); + jsControl.append(graphicsPrimitivesStr); + jsControl.append("\neChart.setOption(option);"); + + return F.JSFormData(jsControl.toString(), "echarts"); + } + return F.NIL; + } + + protected static String listLogLogPlot(IAST plot, IExpr[] options, + GraphicsOptions graphicsOptions, EvalEngine engine) { + if (plot.size() < 2) { + return null; + } + ECharts.setGraphicOptions(graphicsOptions, plot, 2, options, engine); + // final OptionArgs optionArgs = new OptionArgs(plot.topHead(), plot, 2, engine, true); + // if (options[ECharts.X_JOINED].isTrue()) { + // graphicsOptions.setJoined(true); + // } + // graphicsOptions.setOptions(optionArgs); + // graphicsOptions.setScalingFunctions(options); + + IExpr arg1 = plot.arg1(); + if (!arg1.isList()) { + arg1 = engine.evaluate(arg1); + } + if (arg1.isAssociation()) { + IAssociation assoc = ((IAssociation) arg1); + arg1 = assoc.matrixOrList(); + } + if (arg1.isNonEmptyList()) { + IAST pointList = (IAST) arg1; + // TODO Labeled lists + if (pointList.isList()) { + if (pointList.isListOfPoints(2)) { + return point2DListLogLogPlot(pointList, graphicsOptions); + } + if (pointList.isListOfLists()) { + IAST listOfLists = pointList; + + StringBuilder yAxisSeriesBuffer = new StringBuilder(); + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + ECharts.seriesData(yAxisSeriesBuffer, listOfLists, graphicsOptions, type, ""); + StringBuilder xAxisCategoryBuffer = new StringBuilder(); + ECharts.xAxisCategory(xAxisCategoryBuffer, (IAST) listOfLists.arg1()); + ECharts echarts = ECharts.build(graphicsOptions, xAxisCategoryBuffer, yAxisSeriesBuffer); + echarts.setXAxis("log"); + echarts.setYAxis("log"); + return echarts.getJSONStr(); + } + + } + return yValueListLogLogPlot(pointList, graphicsOptions); + } + return null; + } + + /** + * Plot a list of 2D points. + * + * @param pointList2D list of 2D points + * @return + */ + private static String point2DListLogLogPlot(IAST pointList2D, GraphicsOptions graphicsOptions) { + StringBuilder xAxisString = new StringBuilder(); + StringBuilder yAxisString = new StringBuilder(); + // yAxisString.append( // + // "{\n" // + // + " name: 'ListLogPlot',\n" // + // + " type: 'line',\n"); + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + ECharts.xyAxesPoint2D(pointList2D, xAxisString, yAxisString, graphicsOptions, type, ""); + + ECharts echarts = ECharts.build(graphicsOptions, xAxisString, yAxisString); + echarts.setXAxis("log"); + echarts.setYAxis("log"); + return echarts.getJSONStr(); + } + + private static String yValueListLogLogPlot(IAST pointList, GraphicsOptions graphicsOptions) { + double[] minMax = new double[] {Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY}; + // y-axis values + StringBuilder yAxisString = new StringBuilder(); + // yAxisString.append( // + // "{\n" // + // + " name: 'ListLogLogPlot',\n" // + // + " type: 'line',\n"); + ECharts.yAxisSingleSeries(yAxisString, pointList, graphicsOptions, minMax); + // yAxisSingleSeries(yAxisString, pointList, ""); + + // x-axis categories + StringBuilder xAxisString = new StringBuilder(); + ECharts.xAxisCategory(xAxisString, pointList); + + ECharts echarts = ECharts.build(graphicsOptions, xAxisString, yAxisString); + echarts.setXAxis("log"); + echarts.setYAxis("log"); + return echarts.getJSONStr(); + } + + @Override + public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, final EvalEngine engine, + IAST originalAST) { + if (ToggleFeature.JS_ECHARTS) { + return evaluateECharts(ast, argSize, options, engine, originalAST); + } + if (argSize > 0 && argSize < ast.size()) { + ast = ast.copyUntil(argSize + 1); + } GraphicsOptions graphicsOptions = new GraphicsOptions(engine); graphicsOptions.setXFunction(x -> F.Log(x)); graphicsOptions.setYFunction(y -> F.Log(y)); graphicsOptions.setXScale("Log10"); graphicsOptions.setYScale("Log10"); - IAST graphicsPrimitives = listPlot(ast, graphicsOptions, engine); + if (options[5].isTrue()) { + graphicsOptions.setJoined(true); + } + IAST graphicsPrimitives = listPlot(ast, options, graphicsOptions, engine); if (graphicsPrimitives.isPresent()) { graphicsOptions.addPadding(); IAST listOfOptions = F.List(// @@ -38,4 +161,10 @@ public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, public int status() { return ImplementationStatus.EXPERIMENTAL; } + + @Override + public void setUp(final ISymbol newSymbol) { + setOptions(newSymbol, GraphicsOptions.listPlotDefaultOptionKeys(), + GraphicsOptions.listPlotDefaultOptionValues(false)); + } } diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLogPlot.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLogPlot.java index 2a5471f2e0..91c5cae7c9 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLogPlot.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListLogPlot.java @@ -1,25 +1,159 @@ package org.matheclipse.core.reflection.system; +import org.matheclipse.core.basic.ToggleFeature; import org.matheclipse.core.eval.EvalEngine; import org.matheclipse.core.eval.interfaces.IFunctionEvaluator; import org.matheclipse.core.expression.F; import org.matheclipse.core.expression.ImplementationStatus; import org.matheclipse.core.expression.S; +import org.matheclipse.core.graphics.ECharts; import org.matheclipse.core.graphics.GraphicsOptions; import org.matheclipse.core.interfaces.IAST; +import org.matheclipse.core.interfaces.IAssociation; import org.matheclipse.core.interfaces.IExpr; +import org.matheclipse.core.interfaces.ISymbol; public class ListLogPlot extends ListPlot { + + public ListLogPlot() {} + @Override - public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, + public IExpr evaluateECharts(IAST ast, final int argSize, final IExpr[] options, final EvalEngine engine, IAST originalAST) { if (argSize > 0 && argSize < ast.size()) { ast = ast.copyUntil(argSize + 1); } + StringBuilder jsControl = new StringBuilder(); + GraphicsOptions graphicsOptions = new GraphicsOptions(engine); + String graphicsPrimitivesStr = listLogPlot(ast, options, graphicsOptions, engine); + if (graphicsPrimitivesStr != null) { + jsControl.append("var eChart = echarts.init(document.getElementById('main'));\n"); + jsControl.append(graphicsPrimitivesStr); + jsControl.append("\neChart.setOption(option);"); + + return F.JSFormData(jsControl.toString(), "echarts"); + } + return F.NIL; + } + + protected static String listLogPlot(IAST plot, IExpr[] options, GraphicsOptions graphicsOptions, + EvalEngine engine) { + if (plot.size() < 2) { + return null; + } + ECharts.setGraphicOptions(graphicsOptions, plot, 2, options, engine); + // final OptionArgs optionArgs = new OptionArgs(plot.topHead(), plot, 2, engine, true); + // if (options[ECharts.X_JOINED].isTrue()) { + // graphicsOptions.setJoined(true); + // } + // graphicsOptions.setOptions(optionArgs); + // graphicsOptions.setScalingFunctions(options); + + IExpr arg1 = plot.arg1(); + if (!arg1.isList()) { + arg1 = engine.evaluate(arg1); + } + if (arg1.isAssociation()) { + IAssociation assoc = ((IAssociation) arg1); + arg1 = assoc.matrixOrList(); + } + if (arg1.isNonEmptyList()) { + IAST pointList = (IAST) arg1; + // TODO Labeled lists + if (pointList.isList()) { + if (pointList.isListOfPoints(2)) { + return point2DListLogPlot(pointList, graphicsOptions); + } + if (pointList.isListOfLists()) { + IAST listOfLists = pointList; + + StringBuilder yAxisSeriesBuffer = new StringBuilder(); + + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + ECharts.seriesData(yAxisSeriesBuffer, listOfLists, graphicsOptions, type, ""); + StringBuilder xAxisCategoryBuffer = new StringBuilder(); + ECharts.xAxisCategory(xAxisCategoryBuffer, (IAST) listOfLists.arg1()); + ECharts echarts = ECharts.build(graphicsOptions, xAxisCategoryBuffer, yAxisSeriesBuffer); + echarts.setXAxis(); + echarts.setYAxis("log"); + return echarts.getJSONStr(); + } + + } + return yValueListLogPlot(pointList, graphicsOptions); + } + return null; + } + + /** + * Plot a list of 2D points. + * + * @param pointList2D list of 2D points + * @return + */ + private static String point2DListLogPlot(IAST pointList2D, GraphicsOptions graphicsOptions) { + StringBuilder xAxisString = new StringBuilder(); + StringBuilder yAxisString = new StringBuilder(); + // yAxisString.append( // + // "{\n" // + // + " name: 'ListLogPlot',\n" // + // + " type: 'line',\n"); + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + ECharts.xyAxesPoint2D(pointList2D, xAxisString, yAxisString, graphicsOptions, type, ""); + + // ECharts echarts = new ECharts("ListLogPlot"); + // // legend + // echarts.setLegend(""); + // // x-axis categories + // echarts.setXAxis(); + // echarts.setXData(xAxisString.toString()); + // // y-axis series + // echarts.setYAxis("log", ""); + // echarts.setSeriesValues(yAxisString.toString()); + + ECharts echarts = ECharts.build(graphicsOptions, xAxisString, yAxisString); + echarts.setXAxis(); + echarts.setYAxis("log"); + return echarts.getJSONStr(); + } + + private static String yValueListLogPlot(IAST pointList, GraphicsOptions graphicsOptions) { + double[] minMax = new double[] {Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY}; + // y-axis values + StringBuilder yAxisString = new StringBuilder(); + // yAxisString.append( // + // "{\n" // + // + " name: 'ListLogPlot',\n" // + // + " type: 'line',\n"); + + ECharts.yAxisSingleSeries(yAxisString, pointList, graphicsOptions, minMax); + + // x-axis categories + StringBuilder xAxisString = new StringBuilder(); + ECharts.xAxisCategory(xAxisString, pointList); + + + ECharts echarts = ECharts.build(graphicsOptions, xAxisString, yAxisString); + echarts.setXAxis(); + echarts.setYAxis("log"); + return echarts.getJSONStr(); + } + + + @Override + public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, final EvalEngine engine, + IAST originalAST) { + if (ToggleFeature.JS_ECHARTS) { + return evaluateECharts(ast, argSize, options, engine, originalAST); + } + if (argSize > 0 && argSize < ast.size()) { + ast = ast.copyUntil(argSize + 1); + } GraphicsOptions graphicsOptions = new GraphicsOptions(engine); graphicsOptions.setYFunction(y -> F.Log10(y)); graphicsOptions.setYScale("Log10"); - IAST graphicsPrimitives = listPlot(ast, graphicsOptions, engine); + IAST graphicsPrimitives = listPlot(ast, options, graphicsOptions, engine); if (graphicsPrimitives.isPresent()) { graphicsOptions.addPadding(); IAST listOfOptions = F.List(// @@ -42,4 +176,10 @@ public int status() { public int[] expectedArgSize(IAST ast) { return IFunctionEvaluator.ARGS_1_INFINITY; } + + @Override + public void setUp(final ISymbol newSymbol) { + setOptions(newSymbol, GraphicsOptions.listPlotDefaultOptionKeys(), + GraphicsOptions.listPlotDefaultOptionValues(false)); + } } diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListPlot.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListPlot.java index 867284ae5e..c0008d454a 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListPlot.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListPlot.java @@ -1,8 +1,7 @@ package org.matheclipse.core.reflection.system; import java.util.function.Function; - -import org.matheclipse.core.basic.OperationSystem; +import org.matheclipse.core.basic.ToggleFeature; import org.matheclipse.core.builtin.GraphicsFunctions; import org.matheclipse.core.builtin.LinearAlgebra; import org.matheclipse.core.eval.Errors; @@ -14,12 +13,12 @@ import org.matheclipse.core.expression.ID; import org.matheclipse.core.expression.ImplementationStatus; import org.matheclipse.core.expression.S; +import org.matheclipse.core.graphics.ECharts; import org.matheclipse.core.graphics.GraphicsOptions; import org.matheclipse.core.interfaces.IAST; import org.matheclipse.core.interfaces.IASTAppendable; import org.matheclipse.core.interfaces.IASTMutable; import org.matheclipse.core.interfaces.IAssociation; -import org.matheclipse.core.interfaces.IBuiltInSymbol; import org.matheclipse.core.interfaces.IExpr; import org.matheclipse.core.interfaces.IReal; import org.matheclipse.core.interfaces.ISymbol; @@ -30,13 +29,148 @@ public class ListPlot extends AbstractFunctionOptionEvaluator { public ListPlot() {} - @Override - public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, + public IExpr evaluateECharts(IAST ast, final int argSize, final IExpr[] options, final EvalEngine engine, IAST originalAST) { if (argSize > 0 && argSize < ast.size()) { ast = ast.copyUntil(argSize + 1); } - if (options[0].isTrue()) { + + GraphicsOptions graphicsOptions = new GraphicsOptions(engine); + String graphicsPrimitivesStr = listPlotECharts(ast, options, graphicsOptions, engine); + if (graphicsPrimitivesStr != null) { + StringBuilder jsControl = new StringBuilder(); + jsControl.append("var eChart = echarts.init(document.getElementById('main'));\n"); + jsControl.append(graphicsPrimitivesStr); + jsControl.append("\neChart.setOption(option);"); + + return F.JSFormData(jsControl.toString(), "echarts"); + } + return F.NIL; + } + + protected static String listPlotECharts(IAST plot, IExpr[] options, + GraphicsOptions graphicsOptions, EvalEngine engine) { + if (plot.size() < 2) { + return null; + } + ECharts.setGraphicOptions(graphicsOptions, plot, 2, options, engine); + + IExpr arg1 = plot.arg1(); + if (!arg1.isList()) { + arg1 = engine.evaluate(arg1); + } + if (arg1.isAssociation()) { + IAssociation assoc = ((IAssociation) arg1); + arg1 = assoc.matrixOrList(); + } + return listPlotECharts(arg1, graphicsOptions); + } + + protected static String listPlotECharts(IExpr listData, GraphicsOptions graphicsOptions) { + if (listData.isNonEmptyList()) { + IAST pointList = (IAST) listData; + double[] minMax = new double[] {Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY}; + // IASTAppendable[] pointSets = + // org.matheclipse.core.reflection.system.ListPlot.pointsOfListPlot(pointList, minMax); + // if (pointSets != null) { + if (pointList.isListOfLists()) { + StringBuilder yAxisSeriesBuffer = new StringBuilder(); + // StringBuilder xAxisCategoryBuffer = new StringBuilder(); + if (pointList.isListOfPoints(2)) { + ECharts.yAxisSingleSeries(yAxisSeriesBuffer, pointList, graphicsOptions, minMax); + } else { + for (int i = 1; i < pointList.size(); i++) { + IExpr pointSet = pointList.get(i); + if (pointSet != null && pointSet.isListOfLists()) { + if (i > 1) { + yAxisSeriesBuffer.append(",\n"); + } + ECharts.yAxisSingleSeries(yAxisSeriesBuffer, (IAST) pointSet, graphicsOptions, + minMax); + } + } + } + ECharts echarts = ECharts.build(graphicsOptions, null, yAxisSeriesBuffer); + echarts.setXAxisPlot(); + if (minMax[2] < -1000.0) { + minMax[2] = -50; + } + if (minMax[3] > 1000.0) { + minMax[3] = 50; + } + echarts.setYAxisPlot(minMax[2], minMax[3]); + return echarts.getJSONStr(); + } + + // TODO Labeled lists + if (pointList.isList()) {// x -> x.isList())) { + if (pointList.isListOfPoints(2)) { + return point2DListLinePlot(pointList, graphicsOptions); + } + if (pointList.isListOfLists()) { + IAST listOfLists = pointList; + StringBuilder yAxisSeriesBuffer = new StringBuilder(); + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + ECharts.seriesData(yAxisSeriesBuffer, listOfLists, graphicsOptions, type, ""); + StringBuilder xAxisCategoryBuffer = new StringBuilder(); + ECharts.xAxisCategory(xAxisCategoryBuffer, (IAST) listOfLists.arg1()); + ECharts echarts = ECharts.build(graphicsOptions, xAxisCategoryBuffer, yAxisSeriesBuffer); + echarts.setXAxisPlot(); + echarts.setYAxisPlot(minMax[2], minMax[3]); + return echarts.getJSONStr(); + } + + } + return yValueListLinePlot(pointList, graphicsOptions); + } + return null; + } + + /** + * Plot a list of 2D points. + * + * @param pointList2D list of 2D points + * @return + */ + private static String point2DListLinePlot(IAST pointList2D, GraphicsOptions graphicsOptions) { + StringBuilder xAxisString = new StringBuilder(); + StringBuilder yAxisString = new StringBuilder(); + // yAxisString.append( // + // "{\n" // + // + " name: 'List 1',\n" // + // + " type: 'line',\n"); + ECharts.xyAxesPoint2D(pointList2D, xAxisString, yAxisString, graphicsOptions); + + ECharts echarts = ECharts.build(graphicsOptions, xAxisString, yAxisString); + echarts.setXAxis(); + echarts.setYAxis("value"); + return echarts.getJSONStr(); + } + + private static String yValueListLinePlot(IAST pointList, GraphicsOptions graphicsOptions) { + double[] minMax = new double[] {Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY}; + // y-axis values + StringBuilder yAxisString = new StringBuilder(); + ECharts.yAxisSingleSeries(yAxisString, pointList, graphicsOptions, minMax); + + // x-axis categories + StringBuilder xAxisString = new StringBuilder(); + ECharts.xAxisCategory(xAxisString, pointList); + ECharts echarts = ECharts.build(graphicsOptions, xAxisString, yAxisString); + echarts.setXAxis(); + echarts.setYAxis("value"); + return echarts.getJSONStr(); + } + + @Override + public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, final EvalEngine engine, + IAST originalAST) { + if (ToggleFeature.JS_ECHARTS) { + return evaluateECharts(ast, argSize, options, engine, originalAST); + } + if (options[ECharts.X_JSFORM].isTrue()) { IExpr temp = S.Manipulate.of(engine, ast); if (temp.headID() == ID.JSFormData) { return temp; @@ -44,11 +178,10 @@ public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, return F.NIL; } - GraphicsOptions graphicsOptions = new GraphicsOptions(engine); // boundingbox an array of double values (length 4) which describes the bounding box // [xMin, xMax, yMin, yMax] - IAST graphicsPrimitives = listPlot(ast, graphicsOptions, engine); + IAST graphicsPrimitives = listPlot(ast, options, graphicsOptions, engine); if (graphicsPrimitives.isPresent()) { graphicsOptions.addPadding(); IAST listOfOptions = F.List(F.Rule(S.Axes, S.True), // @@ -76,16 +209,18 @@ protected IExpr createGraphicsFunction(IAST graphicsPrimitives, IAST listOfOptio * @param colour * @return */ - protected static IAST plot(IAST plot, GraphicsOptions graphicsOptions, EvalEngine engine) { + protected static IAST plot(IAST plot, IExpr[] options, GraphicsOptions graphicsOptions, + EvalEngine engine) { if (plot.size() < 2) { return F.NIL; } - final OptionArgs options = new OptionArgs(plot.topHead(), plot, 3, engine, true); - if (options.isTrue(S.Joined)) { - graphicsOptions.setJoined(true); - } - graphicsOptions.setOptions(options); - graphicsOptions.setScalingFunctions(); + ECharts.setGraphicOptions(graphicsOptions, plot, 3, options, engine); + // final OptionArgs optionArgs = new OptionArgs(plot.topHead(), plot, 3, engine, true); + // if (options[ECharts.X_JOINED].isTrue()) { + // graphicsOptions.setJoined(true); + // } + // graphicsOptions.setOptions(optionArgs); + // graphicsOptions.setScalingFunctions(options); IExpr arg1 = plot.arg1(); if (!arg1.isList()) { @@ -118,21 +253,23 @@ protected static IAST plot(IAST plot, GraphicsOptions graphicsOptions, EvalEngin /** * * @param plot + * @param options TODO * @param graphicsOptions TODO * @param engine * @param colour * @return */ - protected static IAST listPlot(IAST plot, GraphicsOptions graphicsOptions, EvalEngine engine) { + protected static IAST listPlot(IAST plot, IExpr[] options, GraphicsOptions graphicsOptions, + EvalEngine engine) { if (plot.size() < 2) { return F.NIL; } - final OptionArgs options = new OptionArgs(plot.topHead(), plot, 2, engine, true); - if (options.isTrue(S.Joined)) { + final OptionArgs optionArgs = new OptionArgs(plot.topHead(), plot, 2, engine, true); + if (options[ECharts.X_JOINED].isTrue()) { graphicsOptions.setJoined(true); } - graphicsOptions.setOptions(options); - graphicsOptions.setScalingFunctions(); + graphicsOptions.setOptions(optionArgs); + graphicsOptions.setScalingFunctions(options); IExpr arg1 = plot.arg1(); if (!arg1.isList()) { @@ -309,7 +446,7 @@ && yBoundingBox(boundingbox, yLast, engine)) { // } } - private static IAST getPoint2D(IExpr arg) { + protected static IAST getPoint2D(IExpr arg) { if (arg.isList2()) { return (IAST) arg; } @@ -322,7 +459,7 @@ private static IAST getPoint2D(IExpr arg) { return F.NIL; } - private static IExpr getPointY(IExpr arg) { + protected static IExpr getPointY(IExpr arg) { if (arg.isASTSizeGE(S.Style, 1) // || arg.isASTSizeGE(S.Labeled, 1)) { return arg.first(); @@ -461,7 +598,7 @@ private static boolean addSinglePoint(IASTAppendable pointPrimitives, return false; } - private static boolean addIndexedYPoint(IASTAppendable pointPrimitives, + protected static boolean addIndexedYPoint(IASTAppendable pointPrimitives, IASTAppendable textPrimitives, double[] boundingbox, EvalEngine engine, IExpr xScaled, IExpr yScaled, IExpr currentYPrimitive) { IReal y = yScaled.evalReal(); @@ -489,7 +626,7 @@ protected static boolean isNonReal(IExpr lastPointX, IExpr lastPointY) { return isNonReal(lastPointX) || isNonReal(lastPointY); } - private static boolean xBoundingBox(double[] boundingbox, IExpr xExpr, EvalEngine engine) { + protected static boolean xBoundingBox(double[] boundingbox, IExpr xExpr, EvalEngine engine) { try { double xValue = engine.evalDouble(xExpr); if (Double.isFinite(xValue)) { @@ -507,7 +644,7 @@ private static boolean xBoundingBox(double[] boundingbox, IExpr xExpr, EvalEngin return false; } - private static boolean yBoundingBox(double[] boundingbox, IExpr yExpr, EvalEngine engine) { + protected static boolean yBoundingBox(double[] boundingbox, IExpr yExpr, EvalEngine engine) { try { double yValue = engine.evalDouble(yExpr); if (Double.isFinite(yValue)) { @@ -545,8 +682,8 @@ public static IASTAppendable[] pointsOfListPlot(final IAST ast, double[] minMax) } } else { if (arg1.isList()) { - IAST list = getPoint2D(arg1); - return pointsOfMatrix(list, minMax); + // IAST list = getPoint2D(arg1); + return pointsOfMatrix((IAST) arg1, minMax); } } return null; @@ -638,9 +775,7 @@ private static IASTAppendable listPlotMatrix(double[][] allPoints, double[] minM @Override public void setUp(final ISymbol newSymbol) { - IBuiltInSymbol[] optionKeys = - new IBuiltInSymbol[] {S.JSForm, S.Filling, S.Axes, S.PlotRange, S.$Scaling}; - IExpr[] optionValues = new IExpr[] {S.False, S.None, S.True, S.Automatic, S.Automatic}; - setOptions(newSymbol, optionKeys, optionValues); + setOptions(newSymbol, GraphicsOptions.listPlotDefaultOptionKeys(), + GraphicsOptions.listPlotDefaultOptionValues(false)); } } diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListPolarPlot.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListPolarPlot.java index ba06ddd8e2..5c4c72734b 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListPolarPlot.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListPolarPlot.java @@ -24,7 +24,7 @@ public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, if (table.isPresent()) { IASTMutable listPlot = ast.setAtCopy(1, table); GraphicsOptions graphicsOptions = new GraphicsOptions(engine); - IAST graphicsPrimitives = listPlot(listPlot, graphicsOptions, engine); + IAST graphicsPrimitives = listPlot(listPlot, options, graphicsOptions, engine); if (graphicsPrimitives.isPresent()) { graphicsOptions.addPadding(); IAST listOfOptions = F.List(// diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListStepPlot.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListStepPlot.java new file mode 100644 index 0000000000..8ba8c92e3c --- /dev/null +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/ListStepPlot.java @@ -0,0 +1,143 @@ +package org.matheclipse.core.reflection.system; + +import org.matheclipse.core.eval.EvalEngine; +import org.matheclipse.core.expression.F; +import org.matheclipse.core.expression.ImplementationStatus; +import org.matheclipse.core.graphics.ECharts; +import org.matheclipse.core.graphics.GraphicsOptions; +import org.matheclipse.core.interfaces.IAST; +import org.matheclipse.core.interfaces.IAssociation; +import org.matheclipse.core.interfaces.IExpr; +import org.matheclipse.core.interfaces.ISymbol; + +/** Plot a list of Points as a single line */ +public class ListStepPlot extends ListPlot { + + public ListStepPlot() {} + + @Override + public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, final EvalEngine engine, + IAST originalAST) { + if (argSize > 0 && argSize < ast.size()) { + ast = ast.copyUntil(argSize + 1); + } + StringBuilder jsControl = new StringBuilder(); + GraphicsOptions graphicsOptions = new GraphicsOptions(engine); + String graphicsPrimitivesStr = listStepPlot(ast, options, graphicsOptions, engine); + if (graphicsPrimitivesStr != null) { + jsControl.append("var eChart = echarts.init(document.getElementById('main'));\n"); + jsControl.append(graphicsPrimitivesStr); + jsControl.append("\neChart.setOption(option);"); + // jsControl.append("var eChart = echarts.init(document.getElementById(\"main\"));\n"); + // jsControl.append("\neChart.setOption("); + // jsControl.append(graphicsPrimitivesStr); + // jsControl.append(");"); + + return F.JSFormData(jsControl.toString(), "echarts"); + } + return F.NIL; + } + + protected static String listStepPlot(IAST plot, IExpr[] options, GraphicsOptions graphicsOptions, + EvalEngine engine) { + if (plot.size() < 2) { + return null; + } + ECharts.setGraphicOptions(graphicsOptions, plot, 2, options, engine); + // final OptionArgs optionArgs = new OptionArgs(plot.topHead(), plot, 2, engine, true); + // if (options[ECharts.X_JOINED].isTrue()) { + // graphicsOptions.setJoined(true); + // } + // graphicsOptions.setOptions(optionArgs); + // graphicsOptions.setScalingFunctions(options); + + IExpr arg1 = plot.arg1(); + if (!arg1.isList()) { + arg1 = engine.evaluate(arg1); + } + if (arg1.isAssociation()) { + IAssociation assoc = ((IAssociation) arg1); + arg1 = assoc.matrixOrList(); + } + if (arg1.isNonEmptyList()) { + IAST pointList = (IAST) arg1; + // TODO Labeled lists + if (pointList.isList()) {// x -> x.isList())) { + if (pointList.isListOfPoints(2)) { + return point2DListStepPlot(pointList, graphicsOptions); + } + if (pointList.isListOfLists()) { + IAST listOfLists = pointList; + StringBuilder yAxisSeriesBuffer = new StringBuilder(); + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + ECharts.seriesData(yAxisSeriesBuffer, listOfLists, graphicsOptions, type, "step"); + StringBuilder xAxisCategoryBuffer = new StringBuilder(); + ECharts.xAxisCategory(xAxisCategoryBuffer, (IAST) listOfLists.arg1()); + ECharts echarts = ECharts.build(graphicsOptions, xAxisCategoryBuffer, yAxisSeriesBuffer); + echarts.setXAxis(); + echarts.setYAxis("value"); + return echarts.getJSONStr(); + } + + } + return yValueListStepPlot(pointList, graphicsOptions); + } + return null; + } + + /** + * Plot a list of 2D points. + * + * @param pointList2D list of 2D points + * @return + */ + private static String point2DListStepPlot(IAST pointList2D, GraphicsOptions graphicsOptions) { + StringBuilder xAxisString = new StringBuilder(); + StringBuilder yAxisString = new StringBuilder(); + // yAxisString.append( // + // "{\n" // + // + " name: 'ListStepPlot',\n" // + // + " type: 'line',\n" // + // + " step: '1',"); // step must contain a string with length greater than 0 + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + ECharts.xyAxesPoint2D(pointList2D, xAxisString, yAxisString, graphicsOptions, type, "1"); + + ECharts echarts = ECharts.build(graphicsOptions, xAxisString, yAxisString); + echarts.setXAxis(); + echarts.setYAxis("value"); + return echarts.getJSONStr(); + } + + private static String yValueListStepPlot(IAST pointList, GraphicsOptions graphicsOptions) { + double[] minMax = new double[] {Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY}; + // y-axis values + StringBuilder yAxisString = new StringBuilder(); + // yAxisString.append( // + // "{\n" // + // + " name: 'ListStepPlot',\n" // + // + " type: 'line',\n" // + // + " step: '1',\n"); // step must contain a string with length greater than 0 + String type = graphicsOptions.isJoined() ? ECharts.TYPE_LINE : ECharts.TYPE_SCATTER; + ECharts.yAxisSingleSeries(yAxisString, pointList, graphicsOptions, type, "1", minMax); + + // x-axis categories + StringBuilder xAxisString = new StringBuilder(); + ECharts.xAxisCategory(xAxisString, pointList); + ECharts echarts = ECharts.build(graphicsOptions, xAxisString, yAxisString); + echarts.setXAxis(); + echarts.setYAxis("value"); + return echarts.getJSONStr(); + } + + @Override + public int status() { + return ImplementationStatus.EXPERIMENTAL; + } + + @Override + public void setUp(final ISymbol newSymbol) { + setOptions(newSymbol, GraphicsOptions.listPlotDefaultOptionKeys(), + GraphicsOptions.listPlotDefaultOptionValues(true)); + } +} diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/Plot.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/Plot.java index 42cdb9b25b..246d82fa22 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/Plot.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/reflection/system/Plot.java @@ -5,7 +5,7 @@ import java.util.List; import org.hipparchus.stat.descriptive.moment.Mean; import org.hipparchus.stat.descriptive.moment.StandardDeviation; -import org.matheclipse.core.basic.OperationSystem; +import org.matheclipse.core.basic.ToggleFeature; import org.matheclipse.core.eval.Errors; import org.matheclipse.core.eval.EvalEngine; import org.matheclipse.core.eval.interfaces.IFunctionEvaluator; @@ -15,11 +15,11 @@ import org.matheclipse.core.expression.ImplementationStatus; import org.matheclipse.core.expression.S; import org.matheclipse.core.generic.UnaryNumerical; +import org.matheclipse.core.graphics.ECharts; import org.matheclipse.core.graphics.GraphicsOptions; import org.matheclipse.core.interfaces.IAST; import org.matheclipse.core.interfaces.IASTAppendable; import org.matheclipse.core.interfaces.IASTMutable; -import org.matheclipse.core.interfaces.IBuiltInSymbol; import org.matheclipse.core.interfaces.IExpr; import org.matheclipse.core.interfaces.INum; import org.matheclipse.core.interfaces.ISymbol; @@ -169,16 +169,18 @@ public Plot() {} @Override - public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, - final EvalEngine engine, IAST originalAST) { - if (options[0].isTrue()) { // JSForm option - IExpr temp = S.Manipulate.of(engine, ast); - if (temp.headID() == ID.JSFormData) { - return temp; - } - return F.NIL; - } - + public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, final EvalEngine engine, + IAST originalAST) { + GraphicsOptions graphicsOptions = new GraphicsOptions(engine); + ECharts.setGraphicOptions(graphicsOptions, ast, 2, options, engine); + // if (options[0].isTrue()) { // JSForm option + // IExpr temp = S.Manipulate.of(engine, ast); + // if (temp.headID() == ID.JSFormData) { + // return temp; + // } + // return F.NIL; + // } + // final OptionArgs optionArgs = new OptionArgs(ast.topHead(), ast, 3, engine, true); if (optionArgs.isTrue(S.JSForm)) { IExpr temp = S.Manipulate.of(engine, ast); @@ -197,7 +199,7 @@ public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, if (variable.isVariable()) { try { if (rangeList.isList3()) { - GraphicsOptions graphicsOptions = new GraphicsOptions(engine); + setGraphicOptions(graphicsOptions); graphicsOptions.setOptions(optionArgs); final IAST listOfLines = @@ -206,16 +208,29 @@ public IExpr evaluate(IAST ast, final int argSize, final IExpr[] options, return F.NIL; } - // simulate ListPlot data - GraphicsOptions listPlotOptions = graphicsOptions.copy(); - IASTMutable listPlot = ast.setAtCopy(1, listOfLines); - IAST graphicsPrimitives = plot(listPlot, listPlotOptions, engine); - if (graphicsPrimitives.isPresent()) { - graphicsOptions.addPadding(); - listPlotOptions.setBoundingBox(graphicsOptions.boundingBox()); - // listPlotOptions.mergeOptions(listPlotOptions.options().getListOfRules()); - IAST listOfOptions = listOfOptionRules(listPlotOptions); - return createGraphicsFunction(graphicsPrimitives, listOfOptions, listPlotOptions); + if (ToggleFeature.JS_ECHARTS) { + String graphicsPrimitivesStr = listPlotECharts(listOfLines, graphicsOptions); + if (graphicsPrimitivesStr != null) { + StringBuilder jsControl = new StringBuilder(); + jsControl.append("var eChart = echarts.init(document.getElementById('main'));\n"); + jsControl.append(graphicsPrimitivesStr); + jsControl.append("\neChart.setOption(option);"); + + return F.JSFormData(jsControl.toString(), "echarts"); + } + return F.NIL; + } else { + // simulate ListPlot data + GraphicsOptions listPlotOptions = graphicsOptions.copy(); + IASTMutable listPlot = ast.setAtCopy(1, listOfLines); + IAST graphicsPrimitives = plot(listPlot, options, listPlotOptions, engine); + if (graphicsPrimitives.isPresent()) { + graphicsOptions.addPadding(); + listPlotOptions.setBoundingBox(graphicsOptions.boundingBox()); + // listPlotOptions.mergeOptions(listPlotOptions.options().getListOfRules()); + IAST listOfOptions = listOfOptionRules(listPlotOptions); + return createGraphicsFunction(graphicsPrimitives, listOfOptions, listPlotOptions); + } } } @@ -425,7 +440,7 @@ private static double[] automaticPlotRange(final double[] values, double[] yMinM } double vmax = yValues[n2] + 0.05 * vrange;// 5% extra looks nice - if (yValues[yValues.length-1] < 10.0) { + if (yValues[yValues.length - 1] < 10.0) { vmax = yValues[yValues.length - 1]; } else if (vmax > yValues[yValues.length - 1]) { vmax = yValues[yValues.length - 1]; @@ -636,7 +651,9 @@ public int[] expectedArgSize(IAST ast) { @Override public void setUp(final ISymbol newSymbol) { newSymbol.setAttributes(ISymbol.HOLDALL); - setOptions(newSymbol, new IBuiltInSymbol[] {S.JSForm, S.Axes, S.PlotRange}, - new IExpr[] {S.False, S.True, S.Automatic}); + // setOptions(newSymbol, new IBuiltInSymbol[] {S.JSForm, S.Axes, S.PlotRange}, + // new IExpr[] {S.False, S.True, S.Automatic}); + setOptions(newSymbol, GraphicsOptions.listPlotDefaultOptionKeys(), + GraphicsOptions.listPlotDefaultOptionValues(true)); } } diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/sympy/plotting/Plot.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/sympy/plotting/Plot.java index db00905937..9f81f2555c 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/sympy/plotting/Plot.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/sympy/plotting/Plot.java @@ -232,7 +232,7 @@ private double evalf(double x) { try { return f.applyAsDouble(x); } catch (ArgumentTypeException ate) { - + // ate.printStackTrace(); } return Double.NaN; } diff --git a/symja_android_library/matheclipse-io/src/main/java/org/matheclipse/io/servlet/AJAXQueryServlet.java b/symja_android_library/matheclipse-io/src/main/java/org/matheclipse/io/servlet/AJAXQueryServlet.java index 0d1a8e3c85..46f597dcc5 100644 --- a/symja_android_library/matheclipse-io/src/main/java/org/matheclipse/io/servlet/AJAXQueryServlet.java +++ b/symja_android_library/matheclipse-io/src/main/java/org/matheclipse/io/servlet/AJAXQueryServlet.java @@ -309,35 +309,42 @@ private String[] evaluateString(EvalEngine engine, final String inputString, } else if (outExpr.isAST(S.JSFormData, 3)) { IAST jsFormData = (IAST) outExpr; String jsLibraryType = jsFormData.arg2().toString(); - if (jsLibraryType.equals("mathcell")) { + if (jsLibraryType.equals(JSBuilder.MATHCELL_STR)) { try { return JSONBuilder.createMathcellIFrame(JSBuilder.MATHCELL_IFRAME_TEMPLATE, jsFormData.arg1().toString()); } catch (Exception ex) { LOGGER.debug("{}.evaluateString() failed", getClass().getSimpleName(), ex); } - } else if (jsLibraryType.equals("jsxgraph")) { + } else if (jsLibraryType.equals(JSBuilder.ECHARTS_STR)) { + try { + return JSONBuilder.createEChartsIFrame(JSBuilder.ECHARTS_IFRAME_TEMPLATE, + jsFormData.arg1().toString()); + } catch (Exception ex) { + LOGGER.debug("{}.evaluateString() failed", getClass().getSimpleName(), ex); + } + } else if (jsLibraryType.equals(JSBuilder.JSXGRAPH_STR)) { try { return JSONBuilder.createJSXGraphIFrame(JSBuilder.JSXGRAPH_IFRAME_TEMPLATE, jsFormData.arg1().toString()); } catch (Exception ex) { LOGGER.debug("{}.evaluateString() failed", getClass().getSimpleName(), ex); } - } else if (jsLibraryType.equals("mermaid")) { + } else if (jsLibraryType.equals(JSBuilder.MERMAID_STR)) { try { return JSONBuilder.createMermaidIFrame(JSBuilder.MERMAID_IFRAME_TEMPLATE, jsFormData.arg1().toString()); } catch (Exception ex) { LOGGER.debug("{}.evaluateString() failed", getClass().getSimpleName(), ex); } - } else if (jsLibraryType.equals("plotly")) { + } else if (jsLibraryType.equals(JSBuilder.PLOTLY_STR)) { try { return JSONBuilder.createPlotlyIFrame(JSBuilder.PLOTLY_IFRAME_TEMPLATE, jsFormData.arg1().toString()); } catch (Exception ex) { LOGGER.debug("{}.evaluateString() failed", getClass().getSimpleName(), ex); } - } else if (jsLibraryType.equals("treeform")) { + } else if (jsLibraryType.equals(JSBuilder.TREEFORM_STR)) { try { String manipulateStr = jsFormData.arg1().toString(); String html = VISJS_IFRAME; diff --git a/symja_android_library/matheclipse-io/src/main/java/org/matheclipse/io/servlet/JSONBuilder.java b/symja_android_library/matheclipse-io/src/main/java/org/matheclipse/io/servlet/JSONBuilder.java index 31ce4f6f21..04f55f3046 100644 --- a/symja_android_library/matheclipse-io/src/main/java/org/matheclipse/io/servlet/JSONBuilder.java +++ b/symja_android_library/matheclipse-io/src/main/java/org/matheclipse/io/servlet/JSONBuilder.java @@ -248,6 +248,13 @@ public static String[] createJSONIFrame(String html, String manipulateStr) { + "\" style=\"display: block; width: 100%; height: 100%; border: none;\" >"); } + public static String[] createJEChartsIFrame(String html, String manipulateStr) { + html = JSBuilder.buildECharts(html, manipulateStr); + html = StringEscapeUtils.escapeHtml4(html); + return createJSONJavaScript(""); + } + public static String[] createGraphics2DIFrame(String html, String manipulateStr) { html = JSBuilder.buildGraphics2D(html, manipulateStr); html = StringEscapeUtils.escapeHtml4(html); @@ -269,6 +276,13 @@ public static String[] createMathcellIFrame(String html, String manipulateStr) { + "\" style=\"display: block; width: 100%; height: 100%; border: none;\">"); } + public static String[] createEChartsIFrame(String html, String manipulateStr) { + html = JSBuilder.buildECharts(html, manipulateStr); + html = StringEscapeUtils.escapeHtml4(html); + return createJSONJavaScript(""); + } + public static String[] createJSXGraphIFrame(String html, String manipulateStr) { html = JSBuilder.buildJSXGraph(html, manipulateStr); html = StringEscapeUtils.escapeHtml4(html); diff --git a/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/BasePlotExample.java b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/BasePlotExample.java index 52878791ba..56584c47fc 100644 --- a/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/BasePlotExample.java +++ b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/BasePlotExample.java @@ -2,6 +2,7 @@ import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.OutputStream; import java.util.Base64; import java.util.Locale; @@ -34,93 +35,42 @@ public abstract class BasePlotExample { Config.USE_VISJS = true; Config.FILESYSTEM_ENABLED = true; ManipulateFunction.AUTOSIZE = false; + try { + F.await(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } IOInit.init(); + } public String exampleFunction() { return "Manipulate(ListPlot(Table({Sin(t), Cos(t*a)}, {t, 100})), {a,1,4,1})"; } + public String[] exampleFunctions() { + return null; + } + public void generateHTML() { try { Config.FILESYSTEM_ENABLED = true; ExprEvaluator util = new ExprEvaluator(); - - IExpr result = util.eval(exampleFunction()); - if (result instanceof ImageExpr) { - ImageExpr imageExpr = (ImageExpr) result; - // https://stackoverflow.com/a/22891895/24819 - BufferedImage bImage = imageExpr.getBufferedImage(); - try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - final OutputStream b64 = Base64.getEncoder().wrap(outputStream)) { - ImageIO.write(bImage, "png", b64); - String html = JSBuilder.IMAGE_TEMPLATE; - String[] argsToRender = new String[3]; - argsToRender[0] = outputStream.toString(); - html = Errors.templateRender(html, argsToRender); - System.out.println(html); - F.openHTMLOnDesktop(html); - } - } else if (result.isAST(F.JSFormData, 3)) { - String js; - if (result.second().toString().equals("mathcell")) { - String manipulateStr = ((IAST) result).arg1().toString(); - js = JSBuilder.buildMathcell(JSBuilder.MATHCELL_TEMPLATE, manipulateStr); - // js = Config.MATHCELL_PAGE; - // js = StringUtils.replace(js, "`1`", manipulateStr); - } else if (result.second().toString().equals("treeform")) { - String manipulateStr = ((IAST) result).arg1().toString(); - js = Config.VISJS_PAGE; - js = StringUtils.replace(js, "`1`", manipulateStr); - js = StringUtils.replace(js, "`2`", // - " var options = {\n" + " edges: {\n" + " smooth: {\n" - + " type: 'cubicBezier',\n" - + " forceDirection: 'vertical',\n" - + " roundness: 0.4\n" + " }\n" + " },\n" - + " layout: {\n" + " hierarchical: {\n" - + " direction: \"UD\"\n" + " }\n" + " },\n" - + " nodes: {\n" + " shape: 'box'\n" + " },\n" - + " physics:false\n" + " }; "); - } else if (result.second().toString().equals("traceform")) { - String jsStr = ((IAST) result).arg1().toString(); - js = Config.TRACEFORM_PAGE; - js = StringUtils.replace(js, "`1`", jsStr); - } else if (result.second().toString().equals("mermaid")) { - String manipulateStr = ((IAST) result).arg1().toString(); - js = JSBuilder.buildMermaid(JSBuilder.MERMAID_TEMPLATE, manipulateStr); - } else if (result.second().toString().equals("plotly")) { - String manipulateStr = ((IAST) result).arg1().toString(); - js = JSBuilder.buildPlotly(JSBuilder.PLOTLY_TEMPLATE, manipulateStr); - // js = Config.PLOTLY_PAGE; - // js = StringUtils.replace(js, "`1`", manipulateStr); - } else { - String manipulateStr = ((IAST) result).arg1().toString(); - js = JSBuilder.buildJSXGraph(JSBuilder.JSXGRAPH_TEMPLATE, manipulateStr); - } - System.out.println(js); - F.openHTMLOnDesktop(js); - } else { - IExpr outExpr = result; - if (result.isAST(S.Graphics)// - || result.isAST(F.Graphics3D)) { - outExpr = F.Show(outExpr); + String exampleFunction = exampleFunction(); + if (exampleFunction != null) { + IExpr result = util.eval(exampleFunction); + showResult(result); + return; + } + String[] exampleFunctions = exampleFunctions(); + if (exampleFunctions != null) { + for (String example : exampleFunctions) { + IExpr result = util.eval(example); + showResult(result); } - String html = F.show(outExpr); - System.out.println(html); - return; - // if (result.isString()) { - // IStringX str = (IStringX) result; - // if (str.getMimeType() == IStringX.TEXT_HTML) { - // String htmlSnippet = str.toString(); - // String htmlPage = Config.HTML_PAGE; - // htmlPage = StringUtils.replace(htmlPage, "`1`", htmlSnippet); - // System.out.println(htmlPage); - // F.openHTMLOnDesktop(htmlPage); - // return; - // } - // } - // System.out.println(result.toString()); } + } catch (SyntaxError e) { // catch Symja parser errors here System.out.println(e.getMessage()); @@ -137,5 +87,84 @@ public void generateHTML() { } } + private void showResult(IExpr result) throws IOException { + if (result instanceof ImageExpr) { + ImageExpr imageExpr = (ImageExpr) result; + // https://stackoverflow.com/a/22891895/24819 + BufferedImage bImage = imageExpr.getBufferedImage(); + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + final OutputStream b64 = Base64.getEncoder().wrap(outputStream)) { + ImageIO.write(bImage, "png", b64); + String html = JSBuilder.IMAGE_TEMPLATE; + String[] argsToRender = new String[3]; + argsToRender[0] = outputStream.toString(); + html = Errors.templateRender(html, argsToRender); + System.out.println(html); + F.openHTMLOnDesktop(html); + } + } else if (result.isAST(F.JSFormData, 3)) { + String js; + if (result.second().toString().equals("mathcell")) { + String manipulateStr = ((IAST) result).arg1().toString(); + js = JSBuilder.buildMathcell(JSBuilder.MATHCELL_TEMPLATE, manipulateStr); + // js = Config.MATHCELL_PAGE; + // js = StringUtils.replace(js, "`1`", manipulateStr); + } else if (result.second().toString().equals("treeform")) { + String manipulateStr = ((IAST) result).arg1().toString(); + js = Config.VISJS_PAGE; + js = StringUtils.replace(js, "`1`", manipulateStr); + js = StringUtils.replace(js, "`2`", // + " var options = {\n" + " edges: {\n" + " smooth: {\n" + + " type: 'cubicBezier',\n" + + " forceDirection: 'vertical',\n" + + " roundness: 0.4\n" + " }\n" + " },\n" + + " layout: {\n" + " hierarchical: {\n" + + " direction: \"UD\"\n" + " }\n" + " },\n" + + " nodes: {\n" + " shape: 'box'\n" + " },\n" + + " physics:false\n" + " }; "); + } else if (result.second().toString().equals("traceform")) { + String jsStr = ((IAST) result).arg1().toString(); + js = Config.TRACEFORM_PAGE; + js = StringUtils.replace(js, "`1`", jsStr); + } else if (result.second().toString().equals("mermaid")) { + String manipulateStr = ((IAST) result).arg1().toString(); + js = JSBuilder.buildMermaid(JSBuilder.MERMAID_TEMPLATE, manipulateStr); + } else if (result.second().toString().equals("plotly")) { + String manipulateStr = ((IAST) result).arg1().toString(); + js = JSBuilder.buildPlotly(JSBuilder.PLOTLY_TEMPLATE, manipulateStr); + // js = Config.PLOTLY_PAGE; + // js = StringUtils.replace(js, "`1`", manipulateStr); + } else if (result.second().toString().equals("echarts")) { + String manipulateStr = ((IAST) result).arg1().toString(); + js = JSBuilder.buildECharts(JSBuilder.ECHARTS_TEMPLATE, manipulateStr); + } else { + String manipulateStr = ((IAST) result).arg1().toString(); + js = JSBuilder.buildJSXGraph(JSBuilder.JSXGRAPH_TEMPLATE, manipulateStr); + } + System.out.println(js); + F.openHTMLOnDesktop(js); + } else { + IExpr outExpr = result; + if (result.isAST(S.Graphics)// + || result.isAST(F.Graphics3D)) { + outExpr = F.Show(outExpr); + } + String html = F.show(outExpr); + System.out.println(html); + // if (result.isString()) { + // IStringX str = (IStringX) result; + // if (str.getMimeType() == IStringX.TEXT_HTML) { + // String htmlSnippet = str.toString(); + // String htmlPage = Config.HTML_PAGE; + // htmlPage = StringUtils.replace(htmlPage, "`1`", htmlSnippet); + // System.out.println(htmlPage); + // F.openHTMLOnDesktop(htmlPage); + // return; + // } + // } + // System.out.println(result.toString()); + } + } + } diff --git a/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLinePlotExample.java b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLinePlotExample.java index 18cab26abd..f0b1995935 100644 --- a/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLinePlotExample.java +++ b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLinePlotExample.java @@ -4,11 +4,19 @@ public class ListLinePlotExample extends BasePlotExample { @Override public String exampleFunction() { - return "ListLinePlot({1, 1, 2, 3, 5, 8})"; - // return "ListLinePlot(Table(ElementData(z, \"MeltingPoint\"), {z, 118}))"; + return null; // return "Manipulate(ListLinePlot(Table({Sin(t), Cos(t*a)}, {t, 50})), {a,1,4,1})"; } + @Override + public String[] exampleFunctions() { + return new String[] {// + "ListLinePlot({1, 1, 2, 3, 5, 8})", // + "ListLinePlot(Table(ElementData(z, \"MeltingPoint\"), {z, 118}))" // + + }; + } + public static void main(String[] args) { ListLinePlotExample p = new ListLinePlotExample(); p.generateHTML(); diff --git a/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLogLinearPlotExample.java b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLogLinearPlotExample.java new file mode 100644 index 0000000000..eadaa3f616 --- /dev/null +++ b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLogLinearPlotExample.java @@ -0,0 +1,21 @@ +package org.matheclipse.core.mathcell; + +public class ListLogLinearPlotExample extends BasePlotExample { + + @Override + public String exampleFunction() { + return null; + } + + @Override + public String[] exampleFunctions() { + return new String[] {// + "ListLogLinearPlot(Table({n, Sqrt[n]}, {n, 100}))" // + }; + } + + public static void main(String[] args) { + ListLogLinearPlotExample p = new ListLogLinearPlotExample(); + p.generateHTML(); + } +} diff --git a/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLogLogPlotExample.java b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLogLogPlotExample.java new file mode 100644 index 0000000000..456f20c816 --- /dev/null +++ b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLogLogPlotExample.java @@ -0,0 +1,22 @@ +package org.matheclipse.core.mathcell; + +public class ListLogLogPlotExample extends BasePlotExample { + + @Override + public String exampleFunction() { + return null; + } + + @Override + public String[] exampleFunctions() { + return new String[] {// + "ListLogLogPlot(Range(20)^3)", // + "ListLogLogPlot({Range(20), Sqrt(Range(20)), Log(Range(20))}, Joined -> True, PlotLegends -> {\"eins\", \"zwei\", \"drei\"})" + }; + } + + public static void main(String[] args) { + ListLogLogPlotExample p = new ListLogLogPlotExample(); + p.generateHTML(); + } +} diff --git a/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLogPlotExample.java b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLogPlotExample.java new file mode 100644 index 0000000000..204ef294c8 --- /dev/null +++ b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListLogPlotExample.java @@ -0,0 +1,22 @@ +package org.matheclipse.core.mathcell; + +public class ListLogPlotExample extends BasePlotExample { + + @Override + public String exampleFunction() { + return null; + } + + @Override + public String[] exampleFunctions() { + return new String[] {// + "ListLogPlot({Range(40), Table(PartitionsQ(n), {n, 50})})", // + "ListLogPlot(Table({n, n!}, {n, 1, 20, .1}), Joined -> True, PlotLabel->\"Table values\")", // + "ListLogPlot(Table(PartitionsQ(n), {n, 50}))"}; + } + + public static void main(String[] args) { + ListLogPlotExample p = new ListLogPlotExample(); + p.generateHTML(); + } +} diff --git a/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListPlotExample.java b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListPlotExample.java index 197196d31d..7463f8cbeb 100644 --- a/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListPlotExample.java +++ b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListPlotExample.java @@ -4,10 +4,11 @@ public class ListPlotExample extends BasePlotExample { @Override public String exampleFunction() { + return null; // return "ListPlot({{3.0,1.0},{67.0,1.0},{163.0,1.0}})"; // return "ListPlot(Table({Sin(t*0.33), Cos(t*1.1)}, {t, 100}))"; // return "ListPlot({3,Sin(1),Pi,3/4,42,1.2})"; - return "ListPlot(Prime(Range(25)))"; + // return "ListPlot(Prime(Range(25)))"; // return "ListPlot(Table({Sin(t), Cos(t)}, {t, 100}))"; // return "Manipulate(ListPlot(Table({Sin(t*b), Cos(t*a)}, {t, 100})), {a,1,4,1}, {b,1,12})"; // return "ListPlot(<|2 -> 1, 3 -> 2, 5 -> 3, 7 -> 4, 11 -> 5, 13 -> 6|>)"; @@ -78,6 +79,84 @@ public String exampleFunction() { */ } + @Override + public String[] exampleFunctions() { + return new String[] {// + "ListPlot(<|2 -> 1, 3 -> 2, 5 -> 3, 7 -> 4, 11 -> 5, 13 -> 6|>)", // + "ListPlot({{3.0,1.0},{67.0,1.0},{163.0,1.0}}, PlotLabel ->\"Line test\", AxesLabel->{x,y})", // + "ListPlot(Table({Sin(t*0.33), Cos(t*1.1)}, {t, 100}))", // + "ListPlot({3,Sin(1),Pi,3/4,42,1.2})", // + "ListPlot(Prime(Range(25)))", // + "ListPlot(Table({Sin(t), Cos(t)}, {t, 100}))", // + + + "ListPlot(FindClusters({{ 83.08303244924173, 58.83387754182331 },\n" + // + "{ 45.05445510940626, 23.469642649637535 },\n" + // + "{ 14.96417921432294, 69.0264096390456 },\n" + // + "{ 73.53189604333602, 34.896145021310076 },\n" + // + "{ 73.28498173551634, 33.96860806993209 },\n" + // + "{ 73.45828098873608, 33.92584423092194 },\n" + // + "{ 73.9657889183145, 35.73191006924026 },\n" + // + "{ 74.0074097183533, 36.81735596177168 },\n" + // + "{ 73.41247541410848, 34.27314856695011 },\n" + // + "{ 73.9156256353017, 36.83206791547127 },\n" + // + "{ 74.81499205809087, 37.15682749846019 },\n" + // + "{ 74.03144880081527, 37.57399178552441 },\n" + // + "{ 74.51870941207744, 38.674258946906775 },\n" + // + "{ 74.50754595105536, 35.58903978415765 },\n" + // + "{ 74.51322752749547, 36.030572259100154 },\n" + // + "{ 59.27900996617973, 46.41091720294207 },\n" + // + "{ 59.73744793841615, 46.20015558367595 },\n" + // + "{ 58.81134076672606, 45.71150126331486 },\n" + // + "{ 58.52225539437495, 47.416083617601544 },\n" + // + "{ 58.218626647023484, 47.36228902172297 },\n" + // + "{ 60.27139669447206, 46.606106348801404 },\n" + // + "{ 60.894962462363765, 46.976924697402865 },\n" + // + "{ 62.29048673878424, 47.66970563563518 },\n" + // + "{ 61.03857608977705, 46.212924720020965 },\n" + // + "{ 60.16916214139201, 45.18193661351688 },\n" + // + "{ 59.90036905976012, 47.555364347063005 },\n" + // + "{ 62.33003634144552, 47.83941489877179 },\n" + // + "{ 57.86035536718555, 47.31117930193432 },\n" + // + "{ 58.13715479685925, 48.985960494028404 },\n" + // + "{ 56.131923963548616, 46.8508904252667 },\n" + // + "{ 55.976329887053, 47.46384037658572 },\n" + // + "{ 56.23245975235477, 47.940035191131756 },\n" + // + "{ 58.51687048212625, 46.622885352699086 },\n" + // + "{ 57.85411081905477, 45.95394361577928 },\n" + // + "{ 56.445776311447844, 45.162093662656844 },\n" + // + "{ 57.36691949656233, 47.50097194337286 },\n" + // + "{ 58.243626387557015, 46.114052729681134 },\n" + // + "{ 56.27224595635198, 44.799080066150054 },\n" + // + "{ 57.606924816500396, 46.94291057763621 },\n" + // + "{ 30.18714230041951, 13.877149710431695 },\n" + // + "{ 30.449448810657486, 13.490778346545994 },\n" + // + "{ 30.295018390286714, 13.264889000216499 },\n" + // + "{ 30.160201832884923, 11.89278262341395 },\n" + // + "{ 31.341509791789576, 15.282655921997502 },\n" + // + "{ 31.68601630325429, 14.756873246748 },\n" + // + "{ 29.325963742565364, 12.097849250072613 },\n" + // + "{ 29.54820742388256, 13.613295356975868 },\n" + // + "{ 28.79359608888626, 10.36352064087987 },\n" + // + "{ 31.01284597092308, 12.788479208014905 },\n" + // + "{ 27.58509216737002, 11.47570110601373 },\n" + // + "{ 28.593799561727792, 10.780998203903437 },\n" + // + "{ 31.356105766724795, 15.080316198524088 },\n" + // + "{ 31.25948503636755, 13.674329151166603 },\n" + // + "{ 32.31590076372959, 14.95261758659035 },\n" + // + "{ 30.460413702763617, 15.88402809202671 },\n" + // + "{ 32.56178203062154, 14.586076852632686 },\n" + // + "{ 32.76138648530468, 16.239837325178087 },\n" + // + "{ 30.1829453331884, 14.709592407103628 },\n" + // + "{ 29.55088173528202, 15.0651247180067 },\n" + // + "{ 29.004155302187428, 14.089665298582986 },\n" + // + "{ 29.339624439831823, 13.29096065578051 },\n" + // + "{ 30.997460327576846, 14.551914158277214 },\n" + // + "{ 30.66784126125276, 16.269703107886016 }},2.0,5,Method->\"DBSCAN\"))" + + }; + } + public static void main(String[] args) { ListPlotExample p = new ListPlotExample(); p.generateHTML(); diff --git a/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListStepPlotExample.java b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListStepPlotExample.java new file mode 100644 index 0000000000..fadf11c476 --- /dev/null +++ b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/ListStepPlotExample.java @@ -0,0 +1,25 @@ +package org.matheclipse.core.mathcell; + +public class ListStepPlotExample extends BasePlotExample { + + @Override + public String exampleFunction() { + return null; + } + + @Override + public String[] exampleFunctions() { + return new String[] {// + "ListStepPlot({{1, 2, 3, 5, 8, 13, 21}, {1, 2, 4, 8, 16, 32, 64}}, " // + + "PlotLabel ->\"Test\", PlotLegends ->Automatic, AxesLabel->{x,y})", // + "ListStepPlot(Table({Prime(n), EulerPhi(n)}, {n, 50})," // + + "Axes->{False, True}, AxesLabel->{x,y})", // + "ListStepPlot({1, 1, 2, 3, 5, 8, 13, 21}, PlotLegends ->\"test\")", // + "ListStepPlot({Fibonacci(Range(10)), Prime(Range(10))}, PlotLabel ->\"Number theory\",PlotLegends -> {\"fibonacci\", \"primes\"})"}; + } + + public static void main(String[] args) { + ListStepPlotExample p = new ListStepPlotExample(); + p.generateHTML(); + } +} diff --git a/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/PlotExample.java b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/PlotExample.java index 6fdbe57d7c..ec59ac798e 100644 --- a/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/PlotExample.java +++ b/symja_android_library/tools/src/main/java/org/matheclipse/core/mathcell/PlotExample.java @@ -4,8 +4,19 @@ public class PlotExample extends BasePlotExample { @Override public String exampleFunction() { - return "model=NDSolve({x'(t) == 10*(y(t) - x(t)), y'(t) == x(t)*(28 - z(t)) - y(t), z'(t) == x(t)*y(t) - 8/3*z(t), x(0)== 0, y(0) == 1, z(0) == 0}, {x, y, z}, {t, 0, 20});" - + "Plot({Evaluate(z(t) /.model)}, {t, 0, 20}, JSForm->True)"; + return null; + + } + + @Override + public String[] exampleFunctions() { + return new String[] {// + "model=NDSolve({x'(t) == 10*(y(t) - x(t)), y'(t) == x(t)*(28 - z(t)) - y(t), z'(t) == x(t)*y(t) - 8/3*z(t), x(0)== 0, y(0) == 1, z(0) == 0}, {x, y, z}, {t, 0, 20});" + + "Plot({Evaluate(z(t) /.model)}, {t, 0, 20})", // + "Plot(Evaluate(Table(BernsteinBasis(3, k, x), {k, 0, 3})), {x, 0, 1})", // + "Plot(Tan(x), {x, -10, 10},PlotStyle->{Purple})", // + "Plot(Evaluate(Table(BesselJ(n, x), {n, 4})), {x, 0, 10})" + }; // return "Plot(Evaluate(Table(BernsteinBasis(3, k, x), {k, 0, 3})), {x, 0, 1})"; @@ -17,6 +28,7 @@ public String exampleFunction() { // return "Plot(Tan(x), {x, -10, 10},PlotStyle->{Purple})"; // PlotRange->{-20,20}, + // TODO very slow: // return "Plot(SinIntegral(x), {x, -20, 20})"; // return "Plot({x, Surd(x, 3), Surd(x, 5), Surd(x, 7)}, {x, -1, 1}, PlotLegends -> @@ -32,7 +44,6 @@ public String exampleFunction() { // return "Plot(Evaluate(Table(BesselJ(n, x), {n, 4})), {x, 0, 10})"; } - public static void main(String[] args) { PlotExample p = new PlotExample(); p.generateHTML();