/*
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;
import org.geogebra.common.kernel.geos.GeoNumeric;
/**
* Slider mover for GeoNumeric and AlgoLocusSlider
*/
public class SliderMover extends PathMoverGeneric {
private static final int BOUNDS_FIXED = 1;
private static final int BOUNDS_INFINITE = 2;
private static final int BOUNDS_FIXED_INFINITE = 3;
private static final int BOUNDS_INFINITE_FIXED = 4;
/** slider */
private GeoNumeric slider;
/**
* Creates new path mover for given path
*
* @param path
* slider
*/
public SliderMover(GeoNumeric path) {
this.slider = path;
}
/**
* @param p
* initial value
*/
public void init(GeoNumeric p) {
init(p.getValue());
}
private void init(double param) {
start_param = param;
min_param = slider.getIntervalMin();
max_param = slider.getIntervalMax();
// make sure start_param is between min and max
if (start_param < min_param || start_param > max_param) {
param_extent = max_param - min_param;
start_param = (start_param - min_param) % param_extent;
if (start_param < min_param) {
start_param += param_extent;
}
}
if (min_param == Double.NEGATIVE_INFINITY) {
if (max_param == Double.POSITIVE_INFINITY) {
// (-infinite, +infinite)
mode = BOUNDS_INFINITE;
// infFunction(-1, 1)
min_param = -1 + OPEN_BORDER_OFFSET;
max_param = 1 - OPEN_BORDER_OFFSET;
// transform start parameter to be in (-1, 1)
start_param = PathNormalizer.inverseInfFunction(start_param);
} else {
// (-infinite, max_param]
mode = BOUNDS_INFINITE_FIXED;
start_param = 0;
// max_param + infFunction(-1 ... 0)
offset = max_param;
min_param = -1 + OPEN_BORDER_OFFSET;
max_param = 0;
}
} else {
if (max_param == Double.POSITIVE_INFINITY) {
// [min_param, +infinite)
mode = BOUNDS_FIXED_INFINITE;
start_param = 0;
// min_param + infFunction(0 ... 1)
offset = min_param;
min_param = 0;
max_param = 1 - OPEN_BORDER_OFFSET;
} else {
// [min_param, max_param]
mode = BOUNDS_FIXED;
}
}
param_extent = max_param - min_param;
start_paramUP = start_param + param_extent;
start_paramDOWN = start_param - param_extent;
max_step_width = param_extent / MIN_STEPS;
posOrientation = true;
resetStartParameter();
// System.out.println("init Path mover");
// System.out.println(" min_param : " + min_param);
// System.out.println(" max_param : " + max_param);
// System.out.println(" start_param : " + start_param);
// System.out.println(" max_step_width : " + max_step_width);
}
/**
* @param p
* store current position to p
*/
public void getCurrentPosition(GeoNumeric p) {
calcPoint(p);
}
/**
* @param p
* number to store result
* @return true if it was possible
*/
public boolean getNext(GeoNumeric p) {
// check if we are in our interval
boolean lineTo = true;
last_param = curr_param;
lastMaxBorderSet = maxBorderSet;
lastMinBorderSet = minBorderSet;
// in the last step we got outside a border and stopped there
// now continue at the other border
if (maxBorderSet) {
curr_param = min_param;
lineTo = false; // path.isClosedPath();
maxBorderSet = false;
} else if (minBorderSet) {
curr_param = max_param;
lineTo = false; // path.isClosedPath();
minBorderSet = false;
}
// STANDARD CASE
else {
double new_param = curr_param + step_width;
// new_param too big
if (new_param >= max_param) {
// slow down by making smaller steps
while (new_param >= max_param && smallerStep()) {
new_param = curr_param + step_width;
}
// max border reached
if (new_param >= max_param) {
new_param = max_param;
maxBorderSet = true;
}
}
// new_param too small
else if (new_param <= min_param) {
// slow down by making smaller steps
while (new_param <= min_param && smallerStep()) {
new_param = curr_param + step_width;
}
// min border reached
if (new_param <= min_param) {
new_param = min_param;
minBorderSet = true;
}
}
// set parameter
curr_param = new_param;
}
// calculate point for current parameter
calcPoint(p);
return lineTo;
}
/**
* Updates path parameter of point p from curr_param
*
* @param p
* point to store result
*/
protected void calcPoint(GeoNumeric p) {
double param;
switch (mode) {
case BOUNDS_FIXED:
param = curr_param;
break;
case BOUNDS_INFINITE:
param = PathNormalizer.infFunction(curr_param);
break;
case BOUNDS_FIXED_INFINITE:
case BOUNDS_INFINITE_FIXED:
param = offset + PathNormalizer.infFunction(curr_param);
break;
default:
param = Double.NaN;
}
// PathParameter pp = p.getPathParameter();
// pp.t = param;
// path.pathChanged(p);
// p.updateCoords();
p.setValue(param);
}
}