/*
This file is part of RouteConverter.
RouteConverter 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; either version 2 of the License, or
(at your option) any later version.
RouteConverter is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RouteConverter; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2007 Christian Pesch. All Rights Reserved.
*/
package slash.navigation.converter.gui.models;
import org.jfree.data.xy.XYSeries;
import slash.navigation.base.BaseRoute;
import slash.navigation.common.NavigationPosition;
import slash.navigation.common.UnitSystem;
import slash.navigation.converter.gui.profileview.XAxisMode;
import slash.navigation.converter.gui.profileview.YAxisMode;
import static java.lang.String.format;
import static slash.navigation.common.UnitConversion.METERS_OF_A_KILOMETER;
import static slash.navigation.converter.gui.profileview.XAxisMode.Distance;
/**
* Provides a {@link XYSeries} model by extracting profile information from a {@link PositionsModel}.
*
* @author Christian Pesch
*/
public class ProfileModel extends PositionsModelToXYSeriesSynchronizer {
private UnitSystem unitSystem;
private XAxisMode xAxisMode;
private YAxisMode yAxisMode;
public ProfileModel(PositionsModel positions, PatchedXYSeries series, UnitSystem unitSystem, XAxisMode xAxisMode, YAxisMode yAxisMode) {
super(positions, series);
this.unitSystem = unitSystem;
this.xAxisMode = xAxisMode;
this.yAxisMode = yAxisMode;
}
protected void handleAdd(int firstRow, int lastRow) {
recomputeEverythingAfter(firstRow);
}
protected void handleFullUpdate() {
recomputeEverythingAfter(0);
}
protected void handleIntervalXUpdate(int firstRow, int lastRow) {
recomputeEverythingAfter(firstRow);
}
protected void handleIntervalYUpdate(int firstRow, int lastRow) {
getSeries().setFireSeriesChanged(false);
for (int i = firstRow; i < lastRow + 1; i++) {
getSeries().updateByIndex(i, formatYValue(getPositions().getPosition(i)));
}
getSeries().setFireSeriesChanged(true);
getSeries().fireSeriesChanged();
}
protected void handleRemove(int firstRow, int lastRow) {
recomputeEverythingAfter(firstRow);
}
private void recomputeEverythingAfter(int firstRow) {
getSeries().setFireSeriesChanged(false);
int itemCount = getSeries().getItemCount();
if (itemCount > 0 && firstRow < itemCount - 1)
getSeries().delete(firstRow, itemCount - 1);
BaseRoute route = getPositions().getRoute();
if (route == null)
return;
int lastRow = getPositions().getRowCount() - 1;
if (firstRow <= lastRow && lastRow >= 0) {
if(getXAxisMode().equals(Distance)) {
double[] distances = route.getDistancesFromStart(firstRow, lastRow);
for (int i = firstRow; i < lastRow + 1; i++) {
getSeries().add(formatDistance(distances[i - firstRow]), formatYValue(getPositions().getPosition(i)), false);
}
} else {
long[] times = route.getTimesFromStart(firstRow, lastRow);
for (int i = firstRow; i < lastRow + 1; i++) {
getSeries().add(formatTime(times[i - firstRow]), formatYValue(getPositions().getPosition(i)), false);
}
}
}
getSeries().setFireSeriesChanged(true);
getSeries().fireSeriesChanged();
}
private Double formatYValue(NavigationPosition position) {
switch(yAxisMode) {
case Elevation:
return formatElevation(position.getElevation());
case Speed:
return formatSpeed(position.getSpeed());
default:
throw new IllegalArgumentException(format("X-Axis mode %s is not supported", yAxisMode));
}
}
public double formatDistance(double distance) {
return unitSystem.distanceToUnit(distance / METERS_OF_A_KILOMETER);
}
public long formatTime(long time) {
return time / 1000;
}
private Double formatElevation(Double elevation) {
return unitSystem.valueToUnit(elevation);
}
private Double formatSpeed(Double speed) {
return unitSystem.distanceToUnit(speed);
}
public UnitSystem getUnitSystem() {
return unitSystem;
}
public void setUnitSystem(UnitSystem unitSystem) {
this.unitSystem = unitSystem;
handleFullUpdate();
}
public XAxisMode getXAxisMode() {
return xAxisMode;
}
public YAxisMode getYAxisMode() {
return yAxisMode;
}
public void setProfileMode(XAxisMode xAxisMode, YAxisMode yAxisMode) {
this.xAxisMode = xAxisMode;
this.yAxisMode = yAxisMode;
handleFullUpdate();
}
}