package org.geogebra.common.kernel; import java.util.ArrayList; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.kernelND.GeoElementND; /** * @author mathieu * * Class that stores an ordered set of ConstructionElements, beginning * with the minor ceID value, and going in the direction of the second * minor ceID value. * * This allow to compare cycles between each others. * * Warning: the cycle supposes that there's no ConstructionElement that * appears twice; but there's no test to ensure this when using add() * method. * * Use setDirection() when the cycle is fed to ensure good direction * comparison. * * This class is used e.g. for describing points of polygons. */ public class ConstructionElementCycle extends ArrayList<GeoElementND> implements Comparable<ConstructionElementCycle> { private static final long serialVersionUID = -880160148856127100L; /** minimum ceID of elements contained */ private long minID = Long.MAX_VALUE; /** index of the minimum element */ private int minIndex = 0; /** direction to the second minimum element */ private int direction = 1; /** index to read through the cycle */ private int cycleIndex; /** * return the cycle constituted of P1 and P2 * * @param P1 * first element * @param P2 * second element * @return the cycle constituted of P1 and P2 */ static final public ConstructionElementCycle segmentDescription( GeoElement P1, GeoElement P2) { ConstructionElementCycle cycle = new ConstructionElementCycle(); cycle.add(P1); cycle.add(P2); return cycle; } @Override public boolean add(GeoElementND ce) { if (minID > ce.getID()) { minID = ce.getID(); minIndex = size(); } return super.add(ce); } /** * set the direction to the second minimum element */ public void setDirection() { if (size() < 3) { direction = 1; } else { int before = minIndex - 1; if (before == -1) { before = size() - 1; } int after = minIndex + 1; if (after == size()) { after = 0; } // if element before first minimum element is less than the element // after, // then the direction is ascendant, else the direction is descendant if (get(before).getID() < get(after).getID()) { direction = -1; } else { direction = 1; } } } @Override public int compareTo(ConstructionElementCycle cycle) { if (this == cycle) { return 0; } if (size() < cycle.size()) { return -1; } if (size() > cycle.size()) { return 1; } setCycleFirst(); cycle.setCycleFirst(); int diff = 0; // find the first two different elements, return the difference or 0 for (int i = 0; diff == 0 && i < size(); i++) { diff = getCycleNext() .compareTo(cycle.getCycleNext().toGeoElement()); } return diff; } @Override public boolean equals(Object obj) { if (!(obj instanceof ConstructionElementCycle)) { return false; } return compareTo((ConstructionElementCycle) obj) == 0; } private void setCycleFirst() { cycleIndex = minIndex; } private GeoElementND getCycleNext() { GeoElementND ret = get(cycleIndex); // update cycleIndex cycleIndex += direction; if (cycleIndex == -1) { cycleIndex = size() - 1; } else if (cycleIndex == size()) { cycleIndex = 0; } return ret; } @Override public String toString() { StringBuilder sb = new StringBuilder(); setCycleFirst(); for (int i = 0; i < size(); i++) { sb.append(getCycleNext().toString(StringTemplate.defaultTemplate)); sb.append(" - "); } return sb.toString(); } }