/* * Copyright 2013 Serdar. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.fub.maps.gpx.analysis.models; import de.fub.agg2graph.gpseval.data.Waypoint; import de.fub.agg2graph.gpseval.features.AvgAccelerationFeature; import de.fub.agg2graph.gpseval.features.AvgVelocityFeature; import de.fub.agg2graph.gpseval.features.ErrorRateFeature; import de.fub.agg2graph.gpseval.features.HeadingChangeRateFeature; import de.fub.agg2graph.gpseval.features.MaxNAccelerationFeature; import de.fub.agg2graph.gpseval.features.MaxNVelocityFeature; import de.fub.agg2graph.gpseval.features.MeanVelocityFeature; import de.fub.agg2graph.gpseval.features.TrackLengthFeature; import de.fub.agg2graph.gpseval.features.VarianceOfVelocityFeature; import de.fub.gpxmodule.xml.Trkseg; import de.fub.gpxmodule.xml.Wpt; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.PropertySupport; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; /** * * @author Serdar */ public class GpxTrackSegmentStatistic implements Statistic { private Double totalLength; private Double averageVelocity; private Double meanVelocity; private Double maxVelocity; private Double max2Velocity; private Double max3Velocity; private Double varianceOfVelocity; private Double averageAcceleration; private Double maxAcceleration; private Double max2Acceleration; private Double max3Acceleration; private Double errorRate; private Double headingChangeRate; private final ArrayList<Waypoint> list; private StatisticNode node; private Trkseg gpxTrackSegment = null; public GpxTrackSegmentStatistic(Trkseg trkseg) { this.gpxTrackSegment = trkseg; this.list = new ArrayList<Waypoint>(trkseg.getTrkpt().size()); for (Wpt wpt : trkseg.getTrkpt()) { this.list.add(new CustomWaypoint(wpt)); } } public Trkseg getGpxTrackSegment() { return gpxTrackSegment; } @Override public Node getNodeDelegate() { if (node == null) { node = new StatisticNode(this); } return node; } public List<Waypoint> getTrackSegment() { return Collections.unmodifiableList(list); } public Double getMax2Velocity() { if (max2Velocity == null) { MaxNVelocityFeature feature = new MaxNVelocityFeature(2); for (Waypoint waypoint : this.list) { feature.addWaypoint(waypoint); } max2Velocity = feature.getResult(); } return max2Velocity; } public Double getMax3Velocity() { if (max3Velocity == null) { MaxNVelocityFeature feature = new MaxNVelocityFeature(3); for (Waypoint waypoint : this.list) { feature.addWaypoint(waypoint); } max3Velocity = feature.getResult(); } return max3Velocity; } public Double getVarianceOfVelocity() { if (varianceOfVelocity == null) { VarianceOfVelocityFeature varianceOfVelocityFeature = new VarianceOfVelocityFeature(); for (Waypoint waypoint : this.list) { varianceOfVelocityFeature.addWaypoint(waypoint); } varianceOfVelocity = varianceOfVelocityFeature.getResult(); } return varianceOfVelocity; } public Double getMax2Acceleration() { if (max2Acceleration == null) { MaxNAccelerationFeature feature = new MaxNAccelerationFeature(2); for (Waypoint waypoint : this.list) { feature.addWaypoint(waypoint); } max2Acceleration = feature.getResult(); } return max2Acceleration; } public Double getMax3Acceleration() { if (max3Acceleration == null) { MaxNAccelerationFeature feature = new MaxNAccelerationFeature(3); for (Waypoint waypoint : this.list) { feature.addWaypoint(waypoint); } max3Acceleration = feature.getResult(); } return max3Acceleration; } public Double getErrorRate() { if (errorRate == null) { ErrorRateFeature feature = new ErrorRateFeature(); for (Waypoint waypoint : this.list) { feature.addWaypoint(waypoint); } errorRate = feature.getResult(); } return errorRate; } public Double getHeadingChangeRate() { if (headingChangeRate == null) { HeadingChangeRateFeature feature = new HeadingChangeRateFeature(); for (Waypoint waypoint : this.list) { feature.addWaypoint(waypoint); } headingChangeRate = feature.getResult(); } return headingChangeRate; } public double getTotalLength() { if (totalLength == null) { TrackLengthFeature trackLengthFeature = new TrackLengthFeature(); for (Waypoint waypoint : this.list) { trackLengthFeature.addWaypoint(waypoint); } totalLength = trackLengthFeature.getResult(); } return totalLength; } public int getTotalPointCount() { return this.list.size(); } public double getAverageVelocity() { if (averageVelocity == null) { AvgVelocityFeature avgSpeedFeature = new AvgVelocityFeature(); for (Waypoint waypoint : this.list) { avgSpeedFeature.addWaypoint(waypoint); } averageVelocity = avgSpeedFeature.getResult(); } return averageVelocity; } public double getMeanVelocity() { if (meanVelocity == null) { MeanVelocityFeature meanVelocityFeature = new MeanVelocityFeature(); for (Waypoint waypoint : this.list) { meanVelocityFeature.addWaypoint(waypoint); } meanVelocity = meanVelocityFeature.getResult(); } return meanVelocity; } public double getMaxVelocity() { if (maxVelocity == null) { MaxNVelocityFeature maxVelocityFeature = new MaxNVelocityFeature(1); for (Waypoint waypoint : this.list) { maxVelocityFeature.addWaypoint(waypoint); } maxVelocity = maxVelocityFeature.getResult(); } return maxVelocity; } public double getAverageAcceleration() { if (averageAcceleration == null) { AvgAccelerationFeature avgAccelerationFeature = new AvgAccelerationFeature(); for (Waypoint waypoint : this.list) { avgAccelerationFeature.addWaypoint(waypoint); } averageAcceleration = avgAccelerationFeature.getResult(); } return averageAcceleration; } public double getMaxAcceleration() { if (maxAcceleration == null) { MaxNAccelerationFeature maxAccelerationFeature = new MaxNAccelerationFeature(1); for (Waypoint waypoint : this.list) { maxAccelerationFeature.addWaypoint(waypoint); } maxAcceleration = maxAccelerationFeature.getResult(); } return maxAcceleration; } private static class CustomWaypoint extends Waypoint { private final Wpt gpxWpt; public CustomWaypoint(Wpt gpxWpt) { this.gpxWpt = gpxWpt; init(); } private void init() { this.lon = gpxWpt.getLon() != null ? gpxWpt.getLon().doubleValue() : 0; this.lat = gpxWpt.getLat() != null ? gpxWpt.getLat().doubleValue() : 9; this.timestamp = gpxWpt.getTime(); } } private static class StatisticNode extends AbstractNode { private final GpxTrackSegmentStatistic statistics; private static final String MESSAGE_PATTERN = "{0, number, 0.00}"; // private static final MessageFormat MESSAGE_FORMAT = new MessageFormat(MESSAGE_PATTERN, Locale.ENGLISH); private static final double KILOMETER_PER_HOUR_FACTOR = 3.6; private static final String SUPPRESS_CUSTOM_EDITOR_PROPERTY = "suppressCustomEditor"; public StatisticNode(GpxTrackSegmentStatistic statistics) { super(Children.LEAF); this.statistics = statistics; } @NbBundle.Messages({ "avgAcceleration_Name=Average Acceleration", "avgAcceleration_Description=The average acceleration of this track segment in meter per square second", "maxAcceleration_Name=Maximum Acceleration", "maxAcceleration_Description=The maximum acceleration of this track segment in meter per square second", "max2Acceleration_Name=2nd Maximum Acceleration", "max2Acceleration_Description=The 2nd maximum acceleration of this track segment in meter per square second", "max3Acceleration_Name=3rd Maximum Acceleration", "max3Acceleration_Description=The 3rd maximum acceleration of this track segment in meter per sequare seconds", "avgVelocity_Name=Average Velocity", "avgVelocity_Description=The average velocity of this track segment in Km/h", "maxVelocity_Name=Maximum Velocity", "maxVelocity_Description=The maximum velocity of this track segment in Km/h", "max2Velocity_Name=2nd Maximum Velocity", "max2Velocity_Description=The 2nd maximum velocity of this track segment in Km/h", "max3Velocity_Name=3rd Maximum Velocity", "max3Velocity_Description=The 3rd maximum velocity of this track segment in Km/h", "meanVelocity_Name=Mean Velocity", "meanVelocity_Description=The mean velocity of this track segment in Km/h", "totalLength_Name=Segment Length", "totalLength_Description=The total track segment length in kilometer", "headingChangeRate_Name=Heading Change Rate", "headingChangeRate_Description=The frequency the heading exceeds a predefined default angle in degree", "errorRate_Name=Error Rate", "errorRate_Description=determines the number of error measurement that occurs within this track segment.", "waypointCount_Name=Waypoint Count", "waypointCount_Description=The number of gps coordinates which this track segment contains." }) @Override protected Sheet createSheet() { Sheet sheet = Sheet.createDefault(); Sheet.Set set = Sheet.createPropertiesSet(); sheet.put(set); Node.Property<?> property = new PropertySupport.ReadOnly<String>("avgAcceleration", String.class, Bundle.avgAcceleration_Name(), Bundle.avgAcceleration_Description()) { private String value; @Override public String getValue() throws IllegalAccessException, InvocationTargetException { if (value == null) { value = MessageFormat.format(MessageFormat.format("{0} m/s\u00b2", MESSAGE_PATTERN), statistics.getAverageAcceleration()); } return value; } }; property.setValue(SUPPRESS_CUSTOM_EDITOR_PROPERTY, Boolean.TRUE); set.put(property); property = new PropertySupport.ReadOnly<String>("avgVelocity", String.class, Bundle.avgVelocity_Name(), Bundle.avgVelocity_Description()) { private String value; @Override public String getValue() throws IllegalAccessException, InvocationTargetException { if (value == null) { value = MessageFormat.format(MessageFormat.format("{0} Km/h", MESSAGE_PATTERN), statistics.getAverageVelocity() * KILOMETER_PER_HOUR_FACTOR); } return value; } }; property.setValue(SUPPRESS_CUSTOM_EDITOR_PROPERTY, Boolean.TRUE); set.put(property); property = new PropertySupport.ReadOnly<String>("maxAcceleration", String.class, Bundle.maxAcceleration_Name(), Bundle.maxAcceleration_Description()) { private String value; @Override public String getValue() throws IllegalAccessException, InvocationTargetException { if (value == null) { value = MessageFormat.format(MessageFormat.format("{0} m/s\u00b2", MESSAGE_PATTERN), statistics.getMaxAcceleration()); } return value; } }; property.setValue(SUPPRESS_CUSTOM_EDITOR_PROPERTY, Boolean.TRUE); set.put(property); property = new PropertySupport.ReadOnly<String>("max2Accelection", String.class, Bundle.max2Acceleration_Name(), Bundle.max2Acceleration_Description()) { private String value; @Override public String getValue() throws IllegalAccessException, InvocationTargetException { if (value == null) { value = MessageFormat.format(MessageFormat.format("{0} m/s\u00b2", MESSAGE_PATTERN), statistics.getMax2Acceleration()); } return value; } }; property.setValue(SUPPRESS_CUSTOM_EDITOR_PROPERTY, Boolean.TRUE); set.put(property); property = new PropertySupport.ReadOnly<String>("max3Accelection", String.class, Bundle.max3Acceleration_Name(), Bundle.max3Acceleration_Description()) { private String value; @Override public String getValue() throws IllegalAccessException, InvocationTargetException { if (value == null) { value = MessageFormat.format(MessageFormat.format("{0} m/s\u00b2", MESSAGE_PATTERN), statistics.getMax3Acceleration()); } return value; } }; property.setValue(SUPPRESS_CUSTOM_EDITOR_PROPERTY, Boolean.TRUE); set.put(property); property = new PropertySupport.ReadOnly<String>("maxVelocity", String.class, Bundle.maxVelocity_Name(), Bundle.maxVelocity_Description()) { private String value; @Override public String getValue() throws IllegalAccessException, InvocationTargetException { if (value == null) { value = MessageFormat.format(MessageFormat.format("{0} Km/h", MESSAGE_PATTERN), statistics.getMaxVelocity() * KILOMETER_PER_HOUR_FACTOR); } return value; } }; property.setValue(SUPPRESS_CUSTOM_EDITOR_PROPERTY, Boolean.TRUE); set.put(property); property = new PropertySupport.ReadOnly<String>("max2Velocity", String.class, Bundle.max2Velocity_Name(), Bundle.max2Velocity_Description()) { private String value; @Override public String getValue() throws IllegalAccessException, InvocationTargetException { if (value == null) { value = MessageFormat.format(MessageFormat.format("{0} Km/h", MESSAGE_PATTERN), statistics.getMax2Velocity() * KILOMETER_PER_HOUR_FACTOR); } return value; } }; property.setValue(SUPPRESS_CUSTOM_EDITOR_PROPERTY, Boolean.TRUE); set.put(property); property = new PropertySupport.ReadOnly<String>("max3Velocity", String.class, Bundle.max3Velocity_Name(), Bundle.max3Velocity_Description()) { private String value; @Override public String getValue() throws IllegalAccessException, InvocationTargetException { if (value == null) { value = MessageFormat.format(MessageFormat.format("{0} Km/h", MESSAGE_PATTERN), statistics.getMax3Velocity() * KILOMETER_PER_HOUR_FACTOR); } return value; } }; property.setValue(SUPPRESS_CUSTOM_EDITOR_PROPERTY, Boolean.TRUE); set.put(property); property = new PropertySupport.ReadOnly<String>("meanVelocity", String.class, Bundle.meanVelocity_Name(), Bundle.meanVelocity_Description()) { private String value; @Override public String getValue() throws IllegalAccessException, InvocationTargetException { if (value == null) { value = MessageFormat.format(MessageFormat.format("{0} Km/h", MESSAGE_PATTERN), statistics.getMeanVelocity() * KILOMETER_PER_HOUR_FACTOR); } return value; } }; property.setValue(SUPPRESS_CUSTOM_EDITOR_PROPERTY, Boolean.TRUE); set.put(property); property = new PropertySupport.ReadOnly<String>("headingChangeRate", String.class, Bundle.headingChangeRate_Name(), Bundle.headingChangeRate_Description()) { private String value; @Override public String getValue() throws IllegalAccessException, InvocationTargetException { if (value == null) { value = MessageFormat.format("{0}", statistics.getHeadingChangeRate()); } return value; } }; property.setValue(SUPPRESS_CUSTOM_EDITOR_PROPERTY, Boolean.TRUE); set.put(property); property = new PropertySupport.ReadOnly<String>("errorRate", String.class, Bundle.errorRate_Name(), Bundle.errorRate_Description()) { private String value; @Override public String getValue() throws IllegalAccessException, InvocationTargetException { if (value == null) { value = MessageFormat.format("{0}", statistics.getErrorRate()); } return value; } }; property.setValue(SUPPRESS_CUSTOM_EDITOR_PROPERTY, Boolean.TRUE); set.put(property); property = new PropertySupport.ReadOnly<String>("totalLength", String.class, Bundle.totalLength_Name(), Bundle.totalLength_Description()) { private String value; @Override public String getValue() throws IllegalAccessException, InvocationTargetException { if (value == null) { value = MessageFormat.format(MessageFormat.format("{0} Km", MESSAGE_PATTERN), statistics.getTotalLength() / 1000); } return value; } }; property.setValue(SUPPRESS_CUSTOM_EDITOR_PROPERTY, Boolean.TRUE); set.put(property); property = new PropertySupport.ReadOnly<Integer>("pointCount", Integer.class, Bundle.waypointCount_Name(), Bundle.waypointCount_Description()) { @Override public Integer getValue() throws IllegalAccessException, InvocationTargetException { return statistics.getTotalPointCount(); } }; set.put(property); return sheet; } } }