package org.geogebra.common.kernel.algos; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.geos.GeoConicPart; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoList; import org.geogebra.common.kernel.geos.GeoPoint; import org.geogebra.common.kernel.geos.GeoPoly; import org.geogebra.common.kernel.geos.GeoRay; import org.geogebra.common.kernel.geos.GeoSegment; import org.geogebra.common.kernel.kernelND.GeoConicPartND; /** * Algorithms for transformations */ public abstract class AlgoTransformation extends AlgoElement { /** * Create new transformation algo * * @param c * construction */ public AlgoTransformation(Construction c) { super(c); } /** * Returns the resulting GeoElement * * @return the resulting GeoElement */ public abstract GeoElement getResult(); /** * @param source * source * @param target * target */ abstract protected void setTransformedObject(GeoElement source, GeoElement target); /** * @param ageo2 * source list * @param bgeo2 * target list */ protected void transformList(GeoList ageo2, GeoList bgeo2) { for (int i = bgeo2.size() - 1; i >= ageo2.size(); i--) { bgeo2.remove(i); } for (int i = 0; i < ageo2.size(); i++) { GeoElement trans = null; if (i < bgeo2.size()) { setTransformedObject(ageo2.get(i), bgeo2.get(i)); compute(); } else { trans = getResultTemplate(ageo2.get(i)); setTransformedObject(ageo2.get(i), trans); compute(); bgeo2.add(trans); } } setTransformedObject(ageo2, bgeo2); } /** * @param geo * source element * @return template element that can be used for result */ protected GeoElement getResultTemplate(GeoElement geo) { if (geo instanceof GeoPoly || geo.isLimitedPath()) { return copyInternal(cons, geo); } if (geo.isGeoList()) { return new GeoList(cons); } return copy(geo); } /** * @param geo * template * @return copy */ protected GeoElement copy(GeoElement geo) { return geo.copy(); } /** * @param cons1 * construction * @param geo * source geo * @return copy */ protected GeoElement copyInternal(Construction cons1, GeoElement geo) { return geo.copyInternal(cons1); } /** * @param a * source * @param b * target */ protected void transformLimitedPath(GeoElement a, GeoElement b) { if (a instanceof GeoRay) { setTransformedObject(((GeoRay) a).getStartPoint(), ((GeoRay) b).getStartPoint()); compute(); setTransformedObject(a, b); } else if (a instanceof GeoSegment) { setTransformedObject(((GeoSegment) a).getStartPoint(), ((GeoSegment) b).getStartPoint()); compute(); setTransformedObject(((GeoSegment) a).getEndPoint(), ((GeoSegment) b).getEndPoint()); compute(); setTransformedObject(a, b); } if (a instanceof GeoConicPartND) { double p = ((GeoConicPartND) a).getParameterStart(); double q = ((GeoConicPartND) a).getParameterEnd(); // Application.debug(p+","+q); ((GeoConicPartND) b).setParameters(p, q, swapOrientation((GeoConicPartND) a)); } } /** * @param arc * arc * @return what orientation should the result have */ public boolean swapOrientation(GeoConicPartND arc) { // Application.debug(positiveOrientation); return arc == null || arc.positiveOrientation(); } private GeoPoint transformedPoint; /** * @param a * source * @param b * target */ protected void transformLimitedConic(GeoElement a, GeoElement b) { GeoConicPart arc = (GeoConicPart) b; if (a instanceof GeoConicPart) { GeoConicPart source = (GeoConicPart) a; arc.setParameters(0, Kernel.PI_2, true); if (transformedPoint == null) { transformedPoint = new GeoPoint(cons); } transformedPoint.removePath(); setTransformedObject(source.getPointParam(0), transformedPoint); compute(); arc.pointChanged(transformedPoint); transformedPoint.updateCoords(); // Application.debug("start"+transformedPoint); double d = transformedPoint.getPathParameter().getT(); transformedPoint.removePath(); setTransformedObject(source.getPointParam(1), transformedPoint); compute(); arc.pointChanged(transformedPoint); transformedPoint.updateCoords(); // Application.debug("end"+transformedPoint); double e = transformedPoint.getPathParameter().getT(); // Application.debug(d+","+e); arc.setParameters(d * Kernel.PI_2, e * Kernel.PI_2, swapOrientation(source)); setTransformedObject(a, b); } } /** * * used when transforming polygons * * @return area scale factor of the transformation (-1 for reflections) */ public abstract double getAreaScaleFactor(); @Override public boolean euclidianViewUpdate() { compute(); return true; } }