/* 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.kernelND; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.StringTemplate; import org.geogebra.common.kernel.algos.AlgoIntersectAbstract; import org.geogebra.common.kernel.geos.GeoElement; /** * Generic algo for intersection in n dimensions * */ public abstract class AlgoIntersectND extends AlgoIntersectAbstract { // gives the number of intersection algorithms // this algorithm is used by: see AlgoIntersectSingle private int numberOfUsers = 0; // used in setIntersectionPoint to remember all indices that have been set private boolean[] didSetIntersectionPointArray; /** * @param c * construction */ public AlgoIntersectND(Construction c) { super(c); } /** * @param c * construction * @param addToConstructionList * whether to add this to XML */ public AlgoIntersectND(Construction c, boolean addToConstructionList) { super(c, addToConstructionList); } /** * Avoids two intersection points at same position. This is only done as * long as the second intersection point doesn't have a label yet. */ protected void avoidDoubleTangentPoint() { GeoPointND[] points = getIntersectionPoints(); if (!points[1].isLabelSet() && ((GeoElement) points[0]).isEqual(points[1])) { points[1].setUndefined(); } } /** * @return false */ protected boolean showUndefinedPointsInAlgebraView() { return false; } /** * Hide undefined points from algebra view, except first one */ protected void noUndefinedPointsInAlgebraView() { GeoPointND[] points = getIntersectionPoints(); for (int i = 1; i < points.length; i++) { points[i].showUndefinedInAlgebraView(false); } } /** * Increase number of users */ public void addUser() { numberOfUsers++; } /** * Decrease number of users; if zero, remove this algo from kernel */ public void removeUser() { numberOfUsers--; if (numberOfUsers == 0 && !isPrintedInXML()) { // this algorithm has no users and no labeled output super.remove(); kernel.getAlgoDispatcher().removeIntersectionAlgorithm(this); } } /** @return array of all intersection points */ public abstract GeoPointND[] getIntersectionPoints(); /** @return array of last defined intersection points */ protected abstract GeoPointND[] getLastDefinedIntersectionPoints(); /** * Sets the index-th intersection point to the coords of p. This is needed * when loading constructions from a file to make sure the intersection * points remain at their saved positions. * * @param index * index * @param p * point */ public final void setIntersectionPoint(int index, GeoPointND p) { GeoPointND[] points = getIntersectionPoints(); GeoPointND[] defpoints = getLastDefinedIntersectionPoints(); if (!p.isDefined() || index >= points.length) { return; } // init didSetIntersectionPoint array if (didSetIntersectionPointArray == null) { didSetIntersectionPointArray = new boolean[points.length]; } else if (didSetIntersectionPointArray.length < points.length) { boolean[] temp = new boolean[points.length]; for (int i = 0; i < points.length; i++) { if (i < didSetIntersectionPointArray.length) { temp[i] = didSetIntersectionPointArray[i]; } else { temp[i] = false; } } didSetIntersectionPointArray = temp; } // set coords of intersection point to those of p setCoords(points[index], p); if (defpoints != null) { setCoords(defpoints[index], p); } // we only remember setting the point if we used a defined point didSetIntersectionPointArray[index] = true; // all other intersection points should be set undefined // unless they have been set before for (int i = 0; i < points.length; i++) { if (!didSetIntersectionPointArray[i]) { points[i].setUndefined(); if (defpoints != null) { defpoints[i].setUndefined(); } } } // Application.debug("SET INTERSECTION POINT"); // for (int i=0; i < points.length; i++) { // Application.debug(" point " + i + ": " + points[i] + ", defPoint " + // defpoints[i]); // } } /** * set destination coords equals to source coords * * @param destination * destination point * @param source * source point */ abstract protected void setCoords(GeoPointND destination, GeoPointND source); // points[index].setCoords(p); /** * Returns true if setIntersectionPoint was called for index-th point. * * @param index * index of point * @return true if setIntersectionPoint was called for index-th point. */ protected boolean didSetIntersectionPoint(int index) { return didSetIntersectionPointArray != null && didSetIntersectionPointArray[index]; } @Override public String toString(StringTemplate tpl) { // Michael Borcherds 2008-03-30 // simplified to allow better Chinese translation return getLoc().getPlain("IntersectionPointOfAB", input[0].getLabel(tpl), input[1].getLabel(tpl)); } @Override public void remove() { if (removed) { return; } if (numberOfUsers == 0) { // this algorithm has no users and no labeled output super.remove(); kernel.getAlgoDispatcher().removeIntersectionAlgorithm(this); } else { // there are users of this algorithm, so we keep it // remove only output // delete dependent objects for (int i = 0; i < getOutputLength(); i++) { getOutput(i).doRemove(); } setPrintedInXML(false); } } }