Changeset 1086 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2008-11-19T02:25:08+01:00 (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
r999 r1086 12 12 import java.awt.GridBagLayout; 13 13 import java.awt.Point; 14 import java.awt.Rectangle; 14 15 import java.awt.event.ActionEvent; 15 16 import java.awt.event.ActionListener; 17 import java.awt.geom.Area; 18 import java.awt.geom.Rectangle2D; 16 19 import java.io.BufferedReader; 17 20 import java.io.File; … … 28 31 import java.util.LinkedList; 29 32 import java.util.Date; 33 import java.util.List; 30 34 import java.text.DateFormat; 31 35 import java.text.DecimalFormat; … … 39 43 import javax.swing.JFileChooser; 40 44 import javax.swing.JLabel; 45 import javax.swing.JList; 41 46 import javax.swing.JMenuItem; 42 47 import javax.swing.JOptionPane; … … 51 56 import org.openstreetmap.josm.actions.SaveAction; 52 57 import org.openstreetmap.josm.actions.SaveAsAction; 58 import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask; 53 59 import org.openstreetmap.josm.data.coor.EastNorth; 54 60 import org.openstreetmap.josm.data.gpx.GpxData; … … 63 69 import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 64 70 import org.openstreetmap.josm.gui.dialogs.LayerListPopup; 71 import org.openstreetmap.josm.gui.download.DownloadDialog.DownloadTask; 65 72 import org.openstreetmap.josm.gui.layer.markerlayer.AudioMarker; 66 73 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer; … … 266 273 markersFromNamedTrackpoints, 267 274 new JMenuItem(new ConvertToDataLayerAction()), 275 new JMenuItem(new DownloadAlongTrackAction()), 268 276 new JSeparator(), 269 277 new JMenuItem(new RenameLayerAction(associatedFile, this)), … … 731 739 } 732 740 741 /** 742 * Action that issues a series of download requests to the API, following the GPX track. 743 * 744 * @author fred 745 */ 746 public class DownloadAlongTrackAction extends AbstractAction { 747 public DownloadAlongTrackAction() { 748 super(tr("Download from OSM along this track"), ImageProvider.get("downloadalongtrack")); 749 } 750 public void actionPerformed(ActionEvent e) { 751 JPanel msg = new JPanel(new GridBagLayout()); 752 JList buffer = new JList(new String[] { "50 metres", "500 metres", "5000 metres" }); 753 JList maxRect = new JList(new String[] { "1 sq km", "5 sq km", "10 sq km", "20 sq km" }); 754 755 msg.add(new JLabel(tr("Download everything within:")), GBC.eol()); 756 msg.add(buffer, GBC.eol()); 757 msg.add(new JLabel(tr("Maximum area per request:")), GBC.eol()); 758 msg.add(maxRect, GBC.eol()); 759 760 if (JOptionPane.showConfirmDialog(Main.parent, msg, 761 tr("Download from OSM along this track"), 762 JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) { 763 return; 764 765 } 766 767 /* 768 * Find the average latitude for the data we're contemplating, so we can 769 * know how many metres per degree of longitude we have. 770 */ 771 double latsum = 0; 772 int latcnt = 0; 773 774 for (GpxTrack trk : data.tracks) { 775 for (Collection<WayPoint> segment : trk.trackSegs) { 776 for (WayPoint p : segment) { 777 latsum += p.latlon.lat(); 778 latcnt ++; 779 } 780 } 781 } 782 783 double avglat = latsum / latcnt; 784 double scale = Math.cos(Math.toRadians(avglat)); 785 786 /* 787 * Compute buffer zone extents and maximum bounding box size. Note how the 788 * maximum we ever offer is a bbox area of 0.002, while the API theoretically 789 * supports 0.25, but as soon as you touch any built-up area, that kind of 790 * bounding box will download forever and then stop because it has more than 791 * 50k nodes. 792 */ 793 double buffer_y; 794 double buffer_x; 795 switch(buffer.getSelectedIndex()) { 796 case 0: buffer_y = .0005; break; 797 case 1: buffer_y = .005; break; 798 default: buffer_y = .05; 799 } 800 buffer_x = buffer_y / scale; 801 802 double max_area; 803 switch(maxRect.getSelectedIndex()) { 804 case 0: max_area = 0.0001 / scale; break; 805 case 1: max_area = 0.0005 / scale; break; 806 case 2: max_area = 0.001 / scale; break; 807 default: max_area = 0.002 / scale; 808 } 809 810 Area a = new Area(); 811 Rectangle2D r = new Rectangle2D.Double(); 812 813 /* 814 * Collect the combined area of all gpx points plus buffer zones around them. 815 * This is rather inefficient (may take 20 seconds and more for large tracks); 816 * maybe it could be improved by disregarding points that lie really close to 817 * the previous point. 818 */ 819 for (GpxTrack trk : data.tracks) { 820 for (Collection<WayPoint> segment : trk.trackSegs) { 821 for (WayPoint p : segment) { 822 // we add a buffer around the point. 823 r.setRect(p.latlon.lon()-buffer_x, p.latlon.lat()-buffer_y, 2*buffer_x, 2*buffer_y); 824 a.add(new Area(r)); 825 } 826 } 827 } 828 829 /* 830 * Area "a" now contains the hull that we would like to download data for. 831 * however we can only download rectangles, so the following is an attemt at 832 * finding a number of rectangles to download. 833 * 834 * The idea is simply: Start out with the full bounding box. If it is too large, 835 * then split it in half and repeat recursively for each half until you arrive 836 * at something small enough to download. The algorithm is improved 837 * by always using the intersection between the rectangle and the actual desired 838 * area. For example, if you have a track that goes like this: 839 * +----+ 840 * | /| 841 * | / | 842 * | / | 843 * |/ | 844 * +----+ 845 * then we would first look at downloading the whole rectangle (assume it's too big), 846 * after that we split it in half (upper and lower half), but we do *not* request the 847 * full upper and lower rectangle, only the part of the upper/lower rectangle that 848 * actually has something in it. 849 */ 850 851 List<Rectangle2D> toDownload = new ArrayList<Rectangle2D>(); 852 853 addToDownload(a, a.getBounds(), toDownload, max_area); 854 855 msg = new JPanel(new GridBagLayout()); 856 857 msg.add(new JLabel(tr("<html>This action will require {0} individual<br>download requests. Do you wish<br>to continue?</html>", 858 toDownload.size())), GBC.eol()); 859 860 if (JOptionPane.showConfirmDialog(Main.parent, msg, 861 tr("Download from OSM along this track"), 862 JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) { 863 return; 864 } 865 866 // FIXME: DownloadTask's "please wait" dialog should display the number of 867 // downloads left, and "cancel" needs to be honoured. An error along the way 868 // should abort the whole process. 869 DownloadTask osmTask = new DownloadOsmTask(); 870 for (Rectangle2D td : toDownload) { 871 osmTask.download(null, td.getMinY(), td.getMinX(), td.getMaxY(), td.getMaxX()); 872 } 873 } 874 } 875 876 private static void addToDownload(Area a, Rectangle2D r, Collection<Rectangle2D> results, double max_area) { 877 Area tmp = new Area(r); 878 // intersect with sought-after area 879 tmp.intersect(a); 880 if (tmp.isEmpty()) return; 881 Rectangle2D bounds = tmp.getBounds2D(); 882 if (bounds.getWidth() * bounds.getHeight() > max_area) { 883 // the rectangle gets too large; split it and make recursive call. 884 Rectangle2D r1; 885 Rectangle2D r2; 886 if (bounds.getWidth() > bounds.getHeight()) { 887 // rectangles that are wider than high are split into a left and right half, 888 r1 = new Rectangle2D.Double(bounds.getX(), bounds.getY(), bounds.getWidth()/2, bounds.getHeight()); 889 r2 = new Rectangle2D.Double(bounds.getX()+bounds.getWidth()/2, bounds.getY(), bounds.getWidth()/2, bounds.getHeight()); 890 } else { 891 // others into a top and bottom half. 892 r1 = new Rectangle2D.Double(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight()/2); 893 r2 = new Rectangle2D.Double(bounds.getX(), bounds.getY()+bounds.getHeight()/2, bounds.getWidth(), bounds.getHeight()/2); 894 } 895 addToDownload(a, r1, results, max_area); 896 addToDownload(a, r2, results, max_area); 897 } else { 898 results.add(bounds); 899 } 900 } 901 733 902 /** 734 903 * Makes a new marker layer derived from this GpxLayer containing at least one
Note:
See TracChangeset
for help on using the changeset viewer.