// License: GPL. Copyright (C) 2012 Russell Edwards package org.openstreetmap.josm.plugins.gpsblam; import java.awt.Point; import java.util.Calendar; import java.util.Collection; import java.util.GregorianCalendar; import java.util.HashSet; import java.util.LinkedList; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.coor.CachedLatLon; import org.openstreetmap.josm.data.gpx.GpxTrack; import org.openstreetmap.josm.data.gpx.GpxTrackSegment; import org.openstreetmap.josm.data.gpx.WayPoint; import org.openstreetmap.josm.gui.layer.GpxLayer; import org.openstreetmap.josm.gui.layer.Layer; class GPSBlamInputData extends LinkedList<CachedLatLon> { private final Collection<Calendar> datesSeen = new HashSet<>(); public int getNDays() { return datesSeen.size(); } // select a set of GPX points and count how many tracks they have come from, // within given radius of line between given points GPSBlamInputData(Point p1, Point p2, int radius) { Collection<Layer> layers = Main.getLayerManager().getLayers(); for (Layer l : layers) { if (l.isVisible() && l instanceof GpxLayer) { for (GpxTrack track : ((GpxLayer)l).data.tracks) { for (GpxTrackSegment segment: track.getSegments()) { for (WayPoint wayPoint : segment.getWayPoints()) { if (p2.equals(p1)) { // circular selection CachedLatLon cll = new CachedLatLon(wayPoint.getCoor()); Point p = Main.map.mapView.getPoint(cll.getEastNorth()); if (p.distance(p1) < radius) { this.add(cll, wayPoint); } } else { // selection based on distance from line from p1 to p2 // hack to work for zero length double length = Math.sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y))+1e-5; // unit direction vector from p1.x,p1.y to p2.x, p2.y double dirX = (p2.x-p1.x)/length, dirY = (p2.y-p1.y)/length; // unit vector 90deg CW from direction vector double perpdirX = dirY, perpdirY = -dirX; CachedLatLon cll = new CachedLatLon(wayPoint.getCoor()); Point p = Main.map.mapView.getPoint(cll.getEastNorth()); double pX = p.x-p1.x, pY=p.y-p1.y; // vector from point clicked to waypoint double pPar = pX*dirX + pY*dirY; // parallel component double pPerp = pX*perpdirX + pY*perpdirY; // perpendicular component double pardist = 0.0; if (pPar < 0) pardist = -pPar; else if (pPar > length) pardist = pPar-length; double distsq = pardist*pardist + pPerp*pPerp; if (distsq < radius*radius) { this.add(cll, wayPoint); } } // end if circular else line based selection } // end loop over wayponts in segment } // end loop over segments in track } // end loop over tracks in layer } // end if layer visible } // end loop over layers } // end constructor private void add(CachedLatLon cll, WayPoint wayPoint) { this.add(cll); Calendar day = new GregorianCalendar(); day.setTimeInMillis((long)wayPoint.time*1000); day.set(Calendar.HOUR_OF_DAY, 0); day.set(Calendar.MINUTE, 0); day.set(Calendar.SECOND, 0); datesSeen.add(day); } }