/* 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.awt.GRectangle2D; import org.geogebra.common.factories.AwtFactory; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.MyPoint; import org.geogebra.common.kernel.SegmentType; import org.geogebra.common.kernel.geos.GeoLocus; import org.geogebra.common.kernel.geos.GeoPoint; import org.geogebra.common.kernel.kernelND.GeoPointND; import org.geogebra.common.util.MyMath; /** * locus line for Q dependent on P */ public class AlgoLocus extends AlgoLocusND<MyPoint> { public AlgoLocus(Construction cons, GeoPointND Q, GeoPointND P, int min_steps, boolean registerCE) { super(cons, Q, P, min_steps, registerCE); } @Override protected void createStartPos(Construction cons1) { startQPos = new GeoPoint(cons1); startPPos = new GeoPoint(cons1); } @Override protected GeoLocus newGeoLocus(Construction cons1) { return new GeoLocus(cons1); } public AlgoLocus(Construction cons, String label, GeoPointND Q, GeoPointND P) { super(cons, label, Q, P); } @Override protected boolean isFarAway(GeoPointND point, int i) { return isFarAway(((GeoPoint) point).inhomX, ((GeoPoint) point).inhomY, i); } @Override protected boolean distanceOK(GeoPointND point, int i) { double[] min = { this.farXmin[i], farYmin[i] }; double[] max = { this.farXmax[i], farYmax[i] }; GRectangle2D rectangle = AwtFactory.getPrototype().newRectangle2D(); rectangle.setRect(min[0], min[1], max[0] - min[0], max[1] - min[1]); GeoPoint Q = (GeoPoint) point; // if last point Q' was far away and Q is far away // then the distance is probably OK (return true), // so we probably don't need smaller step, // except if the rectangle of the segment Q'Q // intersects the near to screen rectangle // (it will probably not be on the screen anyway) double minX = lastX; double minY = lastY; double maxX = Q.inhomX; double maxY = Q.inhomY; if (Q.getInhomX() < minX) { minX = Q.getInhomX(); maxX = lastX; } if (Q.getInhomY() < minY) { minY = Q.getInhomY(); maxY = lastY; } return !MyMath.intervalsIntersect(minX, maxX, min[0], max[0]) || !MyMath.intervalsIntersect(minY, maxY, min[1], max[1]); } @Override protected boolean distanceSmall(GeoPointND point, boolean orInsteadOfAnd) { GeoPoint Q = (GeoPoint) point; boolean[] distSmall = new boolean[3]; for (int i = 0; i < distSmall.length; i++) { distSmall[i] = Math.abs(Q.inhomX - lastX) < maxXdist[i] && Math.abs(Q.inhomY - lastY) < maxYdist[i]; } if (orInsteadOfAnd) { for (int i = 0; i < distSmall.length; i++) { if (distSmall[i] && visibleEV[i]) { return true; } } return false; } for (int i = 0; i < distSmall.length; i++) { if (!distSmall[i] && visibleEV[i]) { return false; } } return true; } @Override protected void insertPoint(GeoPointND point, boolean lineTo) { insertPoint(((GeoPoint) point).inhomX, ((GeoPoint) point).inhomY, lineTo); } private void insertPoint(double x, double y, boolean lineTo) { pointCount++; // Application.debug("insertPoint: " + x + ", " + y + ", lineto: " + // lineTo); ((GeoLocus) locus).insertPoint(x, y, lineTo ? SegmentType.LINE_TO : SegmentType.MOVE_TO); lastX = x; lastY = y; for (int i = 0; i < lastFarAway.length; i++) { lastFarAway[i] = isFarAway(lastX, lastY, i); } } private boolean isFarAway(double x, double y, int i) { boolean farAway = (x > farXmax[i] || x < farXmin[i] || y > farYmax[i] || y < farYmin[i]); return farAway; } @Override protected boolean differentFromLast(GeoPointND point) { return ((GeoPoint) point).inhomX != lastX || ((GeoPoint) point).inhomY != lastY; } @Override protected boolean areEqual(GeoPointND p1, GeoPointND p2) { return ((GeoPoint) p1).isEqual(p2, Kernel.MIN_PRECISION); } @Override protected MyPoint[] createQCopyCache(int length) { return new MyPoint[length]; } @Override protected void setQCopyCache(MyPoint copy, GeoPointND point) { copy.setX(((GeoPoint) point).inhomX); copy.setY(((GeoPoint) point).inhomY); } @Override protected MyPoint newCache() { return new MyPoint(); } }