/*
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.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.GeoLocusND;
import org.geogebra.common.kernel.geos.GeoNumeric;
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 where P is a slider
*/
public class AlgoLocusSlider extends AlgoLocusSliderND<MyPoint> {
public AlgoLocusSlider(Construction cons, String label, GeoPoint Q,
GeoNumeric P) {
super(cons, label, Q, P);
}
@Override
protected GeoLocusND<MyPoint> newGeoLocus(Construction cons2) {
return new GeoLocus(cons2);
}
@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);
}
}
protected 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 distanceOK(GeoPointND QND, int i) {
double[] min = { farXmin[i], farYmin[i] };
double[] max = { farXmax[i], farYmax[i] };
GeoPoint Q = (GeoPoint) QND;
// 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 QND, boolean orInsteadOfAnd) {
GeoPoint Q = (GeoPoint) QND;
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 boolean areEqual(GeoPointND A, GeoPointND B) {
return ((GeoPoint) A).isEqual(B.toGeoElement(), Kernel.MIN_PRECISION);
}
@Override
protected boolean differentFromLast(GeoPointND qcopy2) {
GeoPoint Qcopy = (GeoPoint) qcopy2;
return Qcopy.inhomX != lastX || Qcopy.inhomY != lastY;
}
@Override
protected MyPoint newCache() {
return new MyPoint();
}
@Override
protected MyPoint[] createQCopyCache() {
return new MyPoint[paramCache.length];
}
@Override
protected void createStartPos(Construction cons1) {
this.startQPos = new GeoPoint(cons1);
}
@Override
protected void setQCopyCache(MyPoint t, GeoPointND qCopy2) {
t.setX(((GeoPoint) qCopy2).inhomX);
t.setY(((GeoPoint) qCopy2).inhomY);
}
@Override
protected boolean isFarAway(GeoPointND point, int i) {
return isFarAway(((GeoPoint) point).inhomX, ((GeoPoint) point).inhomY,
i);
}
}