29
29
import tim.prune.GenericFunction;
30
30
import tim.prune.I18nManager;
31
31
import tim.prune.config.Config;
32
import tim.prune.data.Altitude;
33
32
import tim.prune.data.DataPoint;
34
33
import tim.prune.data.Distance;
35
34
import tim.prune.data.Field;
36
35
import tim.prune.data.Timestamp;
37
36
import tim.prune.data.Track;
38
import tim.prune.data.Distance.Units;
37
import tim.prune.gui.profile.SpeedData;
38
import tim.prune.gui.profile.VerticalSpeedData;
39
39
import tim.prune.load.GenericFileFilter;
219
219
private boolean setupDialog(Track inTrack)
221
221
boolean hasTimes = inTrack.hasData(Field.TIMESTAMP);
222
boolean hasAltitudes = inTrack.getAltitudeRange().hasRange();
222
boolean hasAltitudes = inTrack.hasAltitudeData();
223
223
_timeRadio.setEnabled(hasTimes);
225
225
// Add checks to prevent choosing unavailable combinations
397
397
catch (Exception e) {}
400
// Sort out units to use
401
final String distLabel = I18nManager.getText(Config.getUnitSet().getDistanceUnit().getShortnameKey());
402
final String altLabel = I18nManager.getText(Config.getUnitSet().getAltitudeUnit().getShortnameKey());
403
final String speedLabel = I18nManager.getText(Config.getUnitSet().getSpeedUnit().getShortnameKey());
404
final String vertSpeedLabel = I18nManager.getText(Config.getUnitSet().getVerticalSpeedUnit().getShortnameKey());
400
406
// Set x axis label
401
407
if (inDistance) {
402
inWriter.write("set xlabel '" + I18nManager.getText("fieldname.distance") + " (" + getUnitsLabel("units.kilometres.short", "units.miles.short") + ")'\n");
408
inWriter.write("set xlabel '" + I18nManager.getText("fieldname.distance") + " (" + distLabel + ")'\n");
405
411
inWriter.write("set xlabel '" + I18nManager.getText("fieldname.time") + " (" + I18nManager.getText("units.hours") + ")'\n");
412
418
case 0: // y axis is distance
413
inWriter.write("set ylabel '" + I18nManager.getText("fieldname.distance") + " (" + getUnitsLabel("units.kilometres.short", "units.miles.short") + ")'\n");
419
inWriter.write("set ylabel '" + I18nManager.getText("fieldname.distance") + " (" + distLabel + ")'\n");
414
420
chartTitle = I18nManager.getText("fieldname.distance");
416
422
case 1: // y axis is altitude
417
inWriter.write("set ylabel '" + I18nManager.getText("fieldname.altitude") + " (" + getUnitsLabel("units.metres.short", "units.feet.short") + ")'\n");
423
inWriter.write("set ylabel '" + I18nManager.getText("fieldname.altitude") + " (" + altLabel + ")'\n");
418
424
chartTitle = I18nManager.getText("fieldname.altitude");
420
426
case 2: // y axis is speed
421
inWriter.write("set ylabel '" + I18nManager.getText("fieldname.speed") + " (" + getUnitsLabel("units.kmh", "units.mph") + ")'\n");
427
inWriter.write("set ylabel '" + I18nManager.getText("fieldname.speed") + " (" + speedLabel + ")'\n");
422
428
chartTitle = I18nManager.getText("fieldname.speed");
424
430
case 3: // y axis is vertical speed
425
inWriter.write("set ylabel '" + I18nManager.getText("fieldname.verticalspeed") + " (" + getUnitsLabel("units.metrespersec", "units.feetpersec") + ")'\n");
431
inWriter.write("set ylabel '" + I18nManager.getText("fieldname.verticalspeed") + " (" + vertSpeedLabel + ")'\n");
426
432
chartTitle = I18nManager.getText("fieldname.verticalspeed");
430
436
inWriter.write("plot '" + tempFile.getAbsolutePath() + "' title '" + chartTitle + "' with filledcurve y1=0 lt rgb \"#009000\"\n");
434
* Get the units label for the given keys
435
* @param inMetric key if metric
436
* @param inImperial key if imperial
437
* @return display label with appropriate text
439
private static String getUnitsLabel(String inMetric, String inImperial)
441
String key = Config.getConfigBoolean(Config.KEY_METRIC_UNITS)?inMetric:inImperial;
442
return I18nManager.getText(key);
447
441
* Calculate the distance values for each point in the given track
462
456
totalRads += DataPoint.calculateRadiansBetween(prevPoint, currPoint);
464
if (Config.getConfigBoolean(Config.KEY_METRIC_UNITS)) {
465
values.setData(i, Distance.convertRadiansToDistance(totalRads, Units.KILOMETRES));
467
values.setData(i, Distance.convertRadiansToDistance(totalRads, Units.MILES));
459
// distance values use currently configured units
460
values.setData(i, Distance.convertRadiansToDistance(totalRads));
469
462
prevPoint = currPoint;
506
499
private static ChartSeries getAltitudeValues(Track inTrack)
508
501
ChartSeries values = new ChartSeries(inTrack.getNumPoints());
509
Altitude.Format altFormat = Config.getConfigBoolean(Config.KEY_METRIC_UNITS)?Altitude.Format.METRES:Altitude.Format.FEET;
502
final double multFactor = Config.getUnitSet().getAltitudeUnit().getMultFactorFromStd();
510
503
for (int i=0; i<inTrack.getNumPoints(); i++) {
511
504
if (inTrack.getPoint(i).hasAltitude()) {
512
values.setData(i, inTrack.getPoint(i).getAltitude().getValue(altFormat));
505
values.setData(i, inTrack.getPoint(i).getAltitude().getMetricValue() * multFactor);
523
516
private static ChartSeries getSpeedValues(Track inTrack)
525
// Calculate speeds and fill in in values array
526
ChartSeries values = new ChartSeries(inTrack.getNumPoints());
527
DataPoint prevPoint = null, currPoint = null, nextPoint = null;
528
DataPoint[] points = getDataPoints(inTrack, false);
529
final boolean useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
518
// Calculate speeds using the same formula as the profile chart
519
SpeedData speeds = new SpeedData(inTrack);
521
final int numPoints = inTrack.getNumPoints();
522
ChartSeries values = new ChartSeries(numPoints);
530
523
// Loop over collected points
531
for (int i=1; i<(points.length-1); i++)
524
for (int i=0; i<numPoints; i++)
533
prevPoint = points[i-1];
534
currPoint = points[i];
535
nextPoint = points[i+1];
536
if (prevPoint != null && currPoint != null && nextPoint != null
537
&& nextPoint.getTimestamp().isAfter(currPoint.getTimestamp())
538
&& currPoint.getTimestamp().isAfter(prevPoint.getTimestamp()))
526
if (speeds.hasData(i))
540
// Calculate average speed between prevPoint and nextPoint
541
double rads = DataPoint.calculateRadiansBetween(prevPoint, currPoint)
542
+ DataPoint.calculateRadiansBetween(currPoint, nextPoint);
543
double time = nextPoint.getTimestamp().getSecondsSince(prevPoint.getTimestamp()) / 60.0 / 60.0;
544
// Convert to distance and pass to chartseries
546
values.setData(i, Distance.convertRadiansToDistance(rads, Units.KILOMETRES) / time);
548
values.setData(i, Distance.convertRadiansToDistance(rads, Units.MILES) / time);
528
values.setData(i, speeds.getData(i));
560
539
private static ChartSeries getVertSpeedValues(Track inTrack)
562
// Calculate speeds and fill in in values array
563
ChartSeries values = new ChartSeries(inTrack.getNumPoints());
564
Altitude.Format altFormat = Config.getConfigBoolean(Config.KEY_METRIC_UNITS)?Altitude.Format.METRES:Altitude.Format.FEET;
565
DataPoint prevPoint = null, currPoint = null, nextPoint = null;
566
DataPoint[] points = getDataPoints(inTrack, true); // require that points have altitudes too
541
// Calculate speeds using the same formula as the profile chart
542
VerticalSpeedData speeds = new VerticalSpeedData(inTrack);
544
final int numPoints = inTrack.getNumPoints();
545
ChartSeries values = new ChartSeries(numPoints);
567
546
// Loop over collected points
568
for (int i=1; i<(points.length-1); i++)
547
for (int i=0; i<numPoints; i++)
570
prevPoint = points[i-1];
571
currPoint = points[i];
572
nextPoint = points[i+1];
573
if (prevPoint != null && currPoint != null && nextPoint != null
574
&& nextPoint.getTimestamp().isAfter(currPoint.getTimestamp())
575
&& currPoint.getTimestamp().isAfter(prevPoint.getTimestamp()))
549
if (speeds.hasData(i))
577
// Calculate average vertical speed between prevPoint and nextPoint
578
double vspeed = (nextPoint.getAltitude().getValue(altFormat) - prevPoint.getAltitude().getValue(altFormat))
579
* 1.0 / nextPoint.getTimestamp().getSecondsSince(prevPoint.getTimestamp());
580
values.setData(i, vspeed);
551
values.setData(i, speeds.getData(i));
588
* Get an array of DataPoints with data for the charts
589
* @param inTrack track object containing points
590
* @param inRequireAltitudes true if only points with altitudes are considered
591
* @return array of points with contiguous non-null elements (<= size) with timestamps
593
private static DataPoint[] getDataPoints(Track inTrack, boolean inRequireAltitudes)
595
DataPoint[] points = new DataPoint[inTrack.getNumPoints()];
596
DataPoint currPoint = null;
598
// Loop over all points
599
for (int i=0; i<inTrack.getNumPoints(); i++)
601
currPoint = inTrack.getPoint(i);
602
if (currPoint != null && !currPoint.isWaypoint() && currPoint.hasTimestamp()
603
&& (!inRequireAltitudes || currPoint.hasAltitude()))
605
points[pointNum] = currPoint;
609
// Any elements at the end of the array will stay null
610
// Also note, chronological order is not checked
616
559
* Select a file to write for the SVG output
617
560
* @return selected File object or null if cancelled