/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. */ package org.geogebra.common.kernel.algos; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoPoint3D; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.Matrix.Coords; import org.geogebra.common.kernel.commands.Commands; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoList; import org.geogebra.common.kernel.geos.GeoNumeric; import org.geogebra.common.kernel.geos.GeoPoint; /** * Converts a list into a Point (or Points) adapted from AlgoRootsPolynomial * * @author Michael */ public class AlgoPointsFromList extends AlgoElement { private GeoList list; // input private GeoPoint[] points; // output private GeoPoint3D[] points3D; // output for 3D private String[] labels; private boolean initLabels, setLabels; public AlgoPointsFromList(Construction cons, String[] labels, boolean setLabels, GeoList list) { super(cons); this.list = list; this.labels = labels; this.setLabels = setLabels; // should labels be used? // make sure root points is not null int number = labels == null ? 1 : Math.max(1, labels.length); if ((list.get(0).isGeoNumeric() && list.size() == 2) || (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 2)) { points = new GeoPoint[0]; initPoints(number); initLabels = true; setInputOutput(); // for AlgoElement compute(); // show at least one root point in algebra view // this is enforced here: if (!points[0].isDefined()) { points[0].setCoords(0, 0, 1); points[0].update(); points[0].setUndefined(); points[0].update(); } } else if ((list.get(0).isGeoNumeric() && list.size() == 3) || (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 3)) { points3D = new GeoPoint3D[0]; initPoints3D(number); initLabels = true; setInputOutput(); compute(); // show at least one root point in algebra view // this is enforced here: if (!points3D[0].isDefined()) { points3D[0].setCoords(0, 0, 1); points3D[0].update(); points3D[0].setUndefined(); points3D[0].update(); } } } /** * The given labels will be used for the resulting points. */ public void setLabels(String[] labels) { this.labels = labels; setLabels = true; // make sure that there are at least as many // points as labels if (labels != null) { initPoints(labels.length); } update(); } @Override public Commands getClassName() { return Commands.Point; } // for AlgoElement @Override protected void setInputOutput() { input = new GeoElement[1]; input[0] = list; if ((list.get(0).isGeoNumeric() && list.size() == 2) || (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 2)) { super.setOutput(points); for (int i = 1; i < points.length; i++) { points[i].showUndefinedInAlgebraView(false); } setDependencies(); } else if ((list.get(0).isGeoNumeric() && list.size() == 3) || (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 3)) { super.setOutput(points3D); for (int i = 1; i < points3D.length; i++) { points3D[i].showUndefinedInAlgebraView(false); } setDependencies(); } } public GeoPoint[] getPoints() { return points; } public GeoPoint3D[] getPoints3D() { return points3D; } @Override public void compute() { int n; if (!list.isDefined() || (n = list.size()) == 0) { setPoints(null, null, 0); return; } int length = -1; double[] x = new double[n]; double[] y = new double[n]; double[] z = new double[n]; // handle Point[ {1,2} ] case if (list.get(0).isGeoNumeric() && list.size() == 2) { GeoElement arg0, arg1; if ((arg0 = list.get(0)).isGeoNumeric() && (arg1 = list.get(1)).isGeoNumeric()) { x[0] = ((GeoNumeric) arg0).getDouble(); y[0] = ((GeoNumeric) arg1).getDouble(); length = 1; } } // handle Point[ {1,2,3} ] case if (list.get(0).isGeoNumeric() && list.size() == 3) { GeoElement arg0, arg1, arg2; if ((arg0 = list.get(0)).isGeoNumeric() && (arg1 = list.get(1)).isGeoNumeric() && (arg2 = list.get(2)).isGeoNumeric()) { x[0] = ((GeoNumeric) arg0).getDouble(); y[0] = ((GeoNumeric) arg1).getDouble(); z[0] = ((GeoNumeric) arg2).getDouble(); length = 1; } } if (length == -1) { if (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 2) { // handle Point[ { {1,2}, {3,4} } ] case for (int i = 0; i < n; i++) { GeoElement geo = list.get(i); if (geo.isGeoList()) { GeoList geoList = ((GeoList) geo); if (geoList.size() < 2) { x[i] = Double.NaN; y[i] = Double.NaN; } else { GeoElement geoX = geoList.get(0); GeoElement geoY = geoList.get(1); x[i] = ((GeoNumeric) geoX).getDouble(); y[i] = ((GeoNumeric) geoY).getDouble(); } } } length = x.length; } else if (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 3) { // handle Point[ { {1,2,3}, {4,5,6} } ] case for (int i = 0; i < n; i++) { GeoElement geo = list.get(i); if (geo.isGeoList()) { GeoList geoList = ((GeoList) geo); if (geoList.size() < 3) { x[i] = Double.NaN; y[i] = Double.NaN; z[i] = Double.NaN; } else { GeoElement geoX = geoList.get(0); GeoElement geoY = geoList.get(1); GeoElement geoZ = geoList.get(2); x[i] = ((GeoNumeric) geoX).getDouble(); y[i] = ((GeoNumeric) geoY).getDouble(); z[i] = ((GeoNumeric) geoZ).getDouble(); } } } length = x.length; } } if (length > 0) { if ((list.get(0).isGeoNumeric() && list.size() == 2) || (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 2)) { setPoints(x, y, length); } else if ((list.get(0).isGeoNumeric() && list.size() == 3) || (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 3)) { setPoints3D(x, y, z, length); } } } // roots array and number of roots final void setPoints(double[] x, double[] y, int number) { initPoints(number); // now set the new values of the roots for (int i = 0; i < number; i++) { points[i].setCoords(x[i], y[i], 1.0); } // all other roots are undefined for (int i = number; i < points.length; i++) { points[i].setUndefined(); } if (setLabels) { updateLabels(number); } } // roots array and number of roots final void setPoints3D(double[] x, double[] y, double[] z, int number) { initPoints3D(number); // now set the new values of the roots for (int i = 0; i < number; i++) { Coords coords = new Coords(x[i], y[i], z[i]); points3D[i].setCoords(coords); } // all other roots are undefined for (int i = number; i < points3D.length; i++) { points3D[i].setUndefined(); } if (setLabels) { updateLabels(number); } } // number is the number of current roots private void updateLabels(int number) { if (list == null || list.size() == 0) { return; } if ((list.get(0).isGeoNumeric() && list.size() == 2) || (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 2)) { if (initLabels) { GeoElement.setLabels(labels, points); initLabels = false; } else { for (int i = 0; i < number; i++) { // check labeling if (!points[i].isLabelSet()) { // use user specified label if we have one String newLabel = (labels != null && i < labels.length) ? labels[i] : null; points[i].setLabel(newLabel); } } } // all other roots are undefined for (int i = number; i < points.length; i++) { points[i].setUndefined(); } } else if ((list.get(0).isGeoNumeric() && list.size() == 3) || (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 3)) { if (initLabels) { GeoElement.setLabels(labels, points3D); initLabels = false; } else { for (int i = 0; i < number; i++) { // check labeling if (!points3D[i].isLabelSet()) { // use user specified label if we have one String newLabel = (labels != null && i < labels.length) ? labels[i] : null; points3D[i].setLabel(newLabel); } } } // all other roots are undefined for (int i = number; i < points3D.length; i++) { points3D[i].setUndefined(); } } } /** * Removes only one single output element if possible. If this is not * possible the whole algorithm is removed. */ @Override public void remove(GeoElement output) { // only single undefined points may be removed if ((list.get(0).isGeoNumeric() && list.size() == 2) || (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 2)) { for (int i = 0; i < points.length; i++) { if (points[i] == output && !points[i].isDefined()) { removeRootPoint(i); return; } } } else if ((list.get(0).isGeoNumeric() && list.size() == 3) || (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 3)) { for (int i = 0; i < points3D.length; i++) { if (points3D[i] == output && !points3D[i].isDefined()) { removeRootPoint(i); return; } } } // if we get here removing output was not possible // so we remove the whole algorithm super.remove(); } private void initPoints(int number) { // make sure that there are enough points if (points.length < number) { GeoPoint[] temp = new GeoPoint[number]; for (int i = 0; i < points.length; i++) { temp[i] = points[i]; temp[i].setCoords(0, 0, 1); // init as defined } for (int i = points.length; i < temp.length; i++) { temp[i] = new GeoPoint(cons); temp[i].setCoords(0, 0, 1); // init as defined temp[i].setParentAlgorithm(this); } points = temp; super.setOutput(points); } } private void initPoints3D(int number) { // make sure that there are enough points if (points3D.length < number) { GeoPoint3D[] temp = new GeoPoint3D[number]; for (int i = 0; i < points3D.length; i++) { temp[i] = points3D[i]; temp[i].setCoords(0, 0, 1); // init as defined } for (int i = points3D.length; i < temp.length; i++) { temp[i] = new GeoPoint3D(cons); temp[i].setCoords(0, 0, 1); // init as defined temp[i].setParentAlgorithm(this); } points3D = temp; super.setOutput(points3D); } } private void removeRootPoint(int pos) { if ((list.get(0).isGeoNumeric() && list.size() == 2) || (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 2)) { points[pos].doRemove(); // build new rootPoints array without the removed point GeoPoint[] temp = new GeoPoint[points.length - 1]; int i; for (i = 0; i < pos; i++) { temp[i] = points[i]; } for (i = pos + 1; i < points.length; i++) { temp[i - 1] = points[i]; } points = temp; } else if ((list.get(0).isGeoNumeric() && list.size() == 3) || (list.get(0).isGeoList() && ((GeoList) list.get(0)).size() == 3)) { points3D[pos].doRemove(); // build new rootPoints array without the removed point GeoPoint3D[] temp = new GeoPoint3D[points3D.length - 1]; int i; for (i = 0; i < pos; i++) { temp[i] = points3D[i]; } for (i = pos + 1; i < points3D.length; i++) { temp[i - 1] = points3D[i]; } points3D = temp; } } }