Changeset 29371 in osm for applications
- Timestamp:
- 2013-03-18T21:58:17+01:00 (11 years ago)
- Location:
- applications/editors/josm/plugins/imagery_offset_db/src/iodb
- Files:
-
- 10 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/imagery_offset_db/src/iodb/CalibrationObject.java
r28008 r29371 18 18 19 19 public CalibrationObject(OsmPrimitive object) { 20 this(object, getLastUserId(object));20 this(object, 0); 21 21 } 22 22 … … 29 29 } 30 30 31 private static long getLastUserId( OsmPrimitive object ) {32 return object.getUser() == null ? -1 : object.getUser().getId(); // todo?33 }34 35 31 @Override 36 32 public void putServerParams( Map<String, String> map ) { … … 38 34 map.put("object", object instanceof Node ? "node" : "way"); 39 35 map.put("id", String.valueOf(object.getId())); 40 map.put("lastuser", String.valueOf(lastUserId));41 36 } 42 37 38 @Override 39 public String toString() { 40 return "CalibrationObject{" + "object=" + object + ", lastUserId=" + lastUserId + "position=" + position + ", date=" + date + ", author=" + author + ", description=" + description + ", abandonDate=" + abandonDate + '}'; 41 } 43 42 } -
applications/editors/josm/plugins/imagery_offset_db/src/iodb/DeprecateOffsetAction.java
r29361 r29371 2 2 3 3 import java.awt.event.ActionEvent; 4 import java.awt.event.KeyEvent;5 import java.io.IOException;6 import java.io.InputStream;7 4 import java.io.UnsupportedEncodingException; 8 5 import java.net.*; 9 import java.util.ArrayList; 10 import java.util.Collections; 11 import java.util.HashMap; 12 import java.util.List; 13 import java.util.concurrent.Future; 14 import java.util.logging.Level; 15 import java.util.logging.Logger; 16 import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTMSTileSource; 6 import javax.swing.AbstractAction; 7 import javax.swing.JOptionPane; 17 8 import org.openstreetmap.josm.Main; 18 import org.openstreetmap.josm.actions.JosmAction; 19 import org.openstreetmap.josm.data.coor.LatLon; 20 import org.openstreetmap.josm.data.projection.Projection; 21 import org.openstreetmap.josm.gui.MapView; 22 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 23 import org.openstreetmap.josm.gui.layer.ImageryLayer; 24 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 25 import org.openstreetmap.josm.io.OsmTransferException; 9 import org.openstreetmap.josm.gui.JosmUserIdentityManager; 26 10 import static org.openstreetmap.josm.tools.I18n.tr; 27 import org.openstreetmap.josm.tools.Shortcut; 28 import org.xml.sax.SAXException; 11 import org.openstreetmap.josm.tools.ImageProvider; 29 12 30 13 /** … … 33 16 * @author zverik 34 17 */ 35 public class GetImageryOffsetAction extends JosmAction { 18 public class DeprecateOffsetAction extends AbstractAction { 19 private ImageryOffsetBase offset; 36 20 37 private List<ImageryOffsetBase> offsets; 38 39 public GetImageryOffsetAction() { 40 super(tr("Get Imagery Offset..."), "getoffset", tr("Download offsets for current imagery from a server"), 41 Shortcut.registerShortcut("imageryoffset:get", tr("Imagery: {0}", tr("Get Imagery Offset...")), KeyEvent.VK_I, Shortcut.ALT+Shortcut.CTRL), true); 42 offsets = Collections.emptyList(); 21 public DeprecateOffsetAction( ImageryOffsetBase offset ) { 22 super(tr("Deprecate Offset")); 23 putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete")); 24 this.offset = offset; 25 setEnabled(offset != null && !offset.isDeprecated()); 43 26 } 44 27 45 28 public void actionPerformed(ActionEvent e) { 46 Projection proj = Main.map.mapView.getProjection(); 47 LatLon center = proj.eastNorth2latlon(Main.map.mapView.getCenter()); 48 ImageryLayer layer = ImageryOffsetTools.getTopImageryLayer(); 49 String imagery = ImageryOffsetTools.getImageryID(layer); 50 if( imagery == null ) 29 if( Main.map == null || Main.map.mapView == null || !Main.map.isVisible() ) 51 30 return; 52 31 53 List<ImageryOffsetBase> offsets = download(center, imagery); // todo: async 54 /*DownloadOffsets download = new DownloadOffsets(); 55 Future<?> future = Main.worker.submit(download); 56 try { 57 future.get(); 58 } catch( Exception ex ) { 59 ex.printStackTrace(); 32 if( JOptionPane.showConfirmDialog(Main.parent, 33 tr("Warning: deprecation is irreversible"), // todo: expand 34 ImageryOffsetTools.DIALOG_TITLE, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) != JOptionPane.YES_OPTION ) { 60 35 return; 61 }*/ 62 63 // todo: show a dialog for selecting one of the offsets (without "update" flag) 64 ImageryOffsetBase offset = new OffsetDialog(offsets).showDialog(); 65 if( offset != null ) { 66 // todo: use the chosen offset 67 if( offset instanceof ImageryOffset ) { 68 ImageryOffsetTools.applyLayerOffset(layer, (ImageryOffset)offset); 69 } else if( offset instanceof CalibrationObject ) { 70 // todo: select object 36 } 37 deprecateOffset(offset); 38 } 39 40 public static void deprecateOffset( ImageryOffsetBase offset ) { 41 String userName = JosmUserIdentityManager.getInstance().getUserName(); 42 if( userName == null ) { 43 JOptionPane.showMessageDialog(Main.parent, tr("To store imagery offsets you must be a registered OSM user."), ImageryOffsetTools.DIALOG_TITLE, JOptionPane.ERROR_MESSAGE); 44 return; 45 } 46 47 String message = "Please enter the reason why you mark this " 48 + (offset instanceof ImageryOffset ? "imagery offset" : "calibraion object") + " as deprecated:"; 49 String reason = null; 50 boolean iterated = false; 51 while( reason == null ) { 52 reason = JOptionPane.showInputDialog(Main.parent, message, ImageryOffsetTools.DIALOG_TITLE, JOptionPane.PLAIN_MESSAGE); 53 if( reason == null || reason.length() == 0 ) { 54 return; 55 } 56 if( reason.length() < 3 || reason.length() > 200 ) { 57 reason = null; 58 if( !iterated ) { 59 message = message + "\n" + tr("Reason text should be 3 to 200 letters long."); 60 iterated = true; 61 } 71 62 } 72 63 } 73 } 74 75 private List<ImageryOffsetBase> download( LatLon center, String imagery ) { 76 String base = Main.pref.get("iodb.server.url", "http://offsets.textual.ru/"); 77 String query = "get?lat=" + center.getX() + "&lon=" + center.getY(); 78 List<ImageryOffsetBase> result = null; 64 79 65 try { 80 query = query + "&imagery=" + URLEncoder.encode(imagery, "utf-8"); 81 URL url = new URL(base + query); 82 System.out.println("url=" + url); 83 HttpURLConnection connection = (HttpURLConnection)url.openConnection(); 84 connection.connect(); 85 int retCode = connection.getResponseCode(); 86 InputStream inp = connection.getInputStream(); 87 if( inp != null ) { 88 result = new IODBReader(inp).parse(); 89 System.out.println("result.size() = " + result.size()); 90 } 91 connection.disconnect(); 92 } catch( MalformedURLException ex ) { 93 // ? 94 } catch( UnsupportedEncodingException e ) { 95 // do nothing. WTF is that? 96 } catch( IOException e ) { 97 e.printStackTrace(); 98 // ? 99 } catch( SAXException e ) { 100 e.printStackTrace(); 101 // ? 102 } 103 if( result == null ) 104 result = new ArrayList<ImageryOffsetBase>(); 105 return result; 106 } 107 108 class DownloadOffsets extends PleaseWaitRunnable { 109 110 private boolean cancelled; 111 112 public DownloadOffsets() { 113 super(tr("Downloading calibration data")); 114 cancelled = false; 115 } 116 117 @Override 118 protected void realRun() throws SAXException, IOException, OsmTransferException { 119 // todo: open httpconnection to server and read xml 120 if( cancelled ) 121 return; 122 123 } 124 125 @Override 126 protected void finish() { 127 if( cancelled ) 128 return; 129 // todo: parse xml and return an array of ImageryOffsetBase 130 } 131 132 @Override 133 protected void cancel() { 134 cancelled = true; 66 String query = "deprecate?id=" + offset.getId() 67 + "&author=" + URLEncoder.encode(userName, "UTF8") 68 + "&reason=" + URLEncoder.encode(reason, "UTF8"); 69 SimpleOffsetQueryTask depTask = new SimpleOffsetQueryTask(query, tr("Notifying the server of the deprecation...")); 70 Main.worker.submit(depTask); 71 } catch( UnsupportedEncodingException ex ) { 72 // WTF 135 73 } 136 74 } -
applications/editors/josm/plugins/imagery_offset_db/src/iodb/GetImageryOffsetAction.java
r28008 r29371 3 3 import java.awt.event.ActionEvent; 4 4 import java.awt.event.KeyEvent; 5 import java.io.IOException;6 5 import java.io.InputStream; 7 6 import java.io.UnsupportedEncodingException; 8 7 import java.net.*; 9 import java.util.ArrayList; 10 import java.util.Collections; 11 import java.util.HashMap; 12 import java.util.List; 13 import java.util.concurrent.Future; 14 import java.util.logging.Level; 15 import java.util.logging.Logger; 16 import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTMSTileSource; 8 import java.util.*; 9 import javax.swing.JOptionPane; 17 10 import org.openstreetmap.josm.Main; 11 import org.openstreetmap.josm.actions.AutoScaleAction; 12 import org.openstreetmap.josm.actions.DownloadPrimitiveAction; 18 13 import org.openstreetmap.josm.actions.JosmAction; 19 14 import org.openstreetmap.josm.data.coor.LatLon; 15 import org.openstreetmap.josm.data.osm.*; 20 16 import org.openstreetmap.josm.data.projection.Projection; 21 import org.openstreetmap.josm.gui.MapView;22 import org.openstreetmap.josm.gui.PleaseWaitRunnable;23 17 import org.openstreetmap.josm.gui.layer.ImageryLayer; 24 import org.openstreetmap.josm.gui.progress.ProgressMonitor;25 import org.openstreetmap.josm.io.OsmTransferException;26 18 import static org.openstreetmap.josm.tools.I18n.tr; 27 19 import org.openstreetmap.josm.tools.Shortcut; 28 import org.xml.sax.SAXException;29 20 30 21 /** … … 35 26 public class GetImageryOffsetAction extends JosmAction { 36 27 37 private List<ImageryOffsetBase> offsets;38 39 28 public GetImageryOffsetAction() { 40 29 super(tr("Get Imagery Offset..."), "getoffset", tr("Download offsets for current imagery from a server"), 41 Shortcut.registerShortcut("imageryoffset:get", tr("Imagery: {0}", tr("Get Imagery Offset...")), KeyEvent.VK_I, Shortcut.ALT+Shortcut.CTRL), true);42 offsets = Collections.emptyList();30 Shortcut.registerShortcut("imageryoffset:get", tr("Imagery: {0}", tr("Get Imagery Offset...")), 31 KeyEvent.VK_I, Shortcut.ALT_CTRL), true); 43 32 } 44 33 45 34 public void actionPerformed(ActionEvent e) { 35 if( Main.map == null || Main.map.mapView == null || !Main.map.isVisible() ) 36 return; 46 37 Projection proj = Main.map.mapView.getProjection(); 47 38 LatLon center = proj.eastNorth2latlon(Main.map.mapView.getCenter()); … … 51 42 return; 52 43 53 List<ImageryOffsetBase> offsets = download(center, imagery); // todo: async 54 /*DownloadOffsets download = new DownloadOffsets(); 55 Future<?> future = Main.worker.submit(download); 56 try { 57 future.get(); 58 } catch( Exception ex ) { 59 ex.printStackTrace(); 44 DownloadOffsetsTask download = new DownloadOffsetsTask(center, layer, imagery); 45 Main.worker.submit(download); 46 } 47 48 @Override 49 protected void updateEnabledState() { 50 boolean state = true; 51 if( Main.map == null || Main.map.mapView == null || !Main.map.isVisible() ) 52 state = false; 53 ImageryLayer layer = ImageryOffsetTools.getTopImageryLayer(); 54 if( ImageryOffsetTools.getImageryID(layer) == null ) 55 state = false; 56 setEnabled(state); 57 } 58 59 private void showOffsetDialog( List<ImageryOffsetBase> offsets, ImageryLayer layer ) { 60 if( offsets.isEmpty() ) { 61 JOptionPane.showMessageDialog(Main.parent, 62 tr("No data for this region. Please adjust imagery layer and upload an offset."), 63 ImageryOffsetTools.DIALOG_TITLE, JOptionPane.INFORMATION_MESSAGE); 60 64 return; 61 }*/ 62 63 // todo: show a dialog for selecting one of the offsets (without "update" flag) 64 ImageryOffsetBase offset = new OffsetDialog(offsets).showDialog(); 65 } 66 final ImageryOffsetBase offset = new OffsetDialog(offsets).showDialog(); 65 67 if( offset != null ) { 66 // todo: use the chosen offset67 68 if( offset instanceof ImageryOffset ) { 68 69 ImageryOffsetTools.applyLayerOffset(layer, (ImageryOffset)offset); 70 Main.map.repaint(); 69 71 } else if( offset instanceof CalibrationObject ) { 70 // todo: select object 72 OsmPrimitive obj = ((CalibrationObject)offset).getObject(); 73 final List<PrimitiveId> ids = new ArrayList<PrimitiveId>(1); 74 ids.add(obj); 75 DownloadPrimitiveAction.processItems(false, ids, false, true); 76 Main.worker.submit(new AfterCalibrationDownloadTask((CalibrationObject)offset)); 77 } 78 } 79 } 80 81 class AfterCalibrationDownloadTask implements Runnable { 82 private CalibrationObject offset; 83 84 public AfterCalibrationDownloadTask( CalibrationObject offset ) { 85 this.offset = offset; 86 } 87 88 @Override 89 public void run() { 90 OsmPrimitive p = getCurrentDataSet().getPrimitiveById(offset.getObject()); 91 if( p == null ) { 92 return; 93 } 94 // check for last user 95 if( offset.getLastUserId() > 0 ) { 96 long uid = p.getUser().getId(); 97 Date ts = p.getTimestamp(); 98 if( p instanceof Way ) { 99 for( Node n : ((Way)p).getNodes() ) { 100 if( n.getTimestamp().after(ts) ) { 101 ts = n.getTimestamp(); 102 uid = n.getUser().getId(); 103 } 104 } 105 } 106 if( uid != offset.getLastUserId() ) { 107 int result = JOptionPane.showConfirmDialog(Main.parent, 108 tr("The calibration object has been changed in unknown way.\n" 109 + "It may be moved or extended, thus ceasing to be a reliable mark\n" 110 + "for imagery calibration. Do you want to notify the server of this?"), 111 ImageryOffsetTools.DIALOG_TITLE, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); 112 if( result == JOptionPane.YES_OPTION ) { 113 DeprecateOffsetAction.deprecateOffset(offset); 114 return; 115 } 116 } 117 } 118 Main.main.getCurrentDataSet().setSelected(p); 119 AutoScaleAction.zoomTo(Collections.singleton(p)); 120 if( !Main.pref.getBoolean("iodb.calibration.message", false) ) { 121 JOptionPane.showMessageDialog(Main.parent, 122 tr("An object has been selected on the map. Find the corresponding feature\n" 123 + "on the imagery layer and move that layer accordingly.\n" 124 + "DO NOT touch the selected object, so it can be used by others later."), 125 ImageryOffsetTools.DIALOG_TITLE, JOptionPane.INFORMATION_MESSAGE); 126 Main.pref.put("iodb.calibration.message", true); 71 127 } 72 128 } 73 129 } 74 130 75 private List<ImageryOffsetBase> download( LatLon center, String imagery ) { 76 String base = Main.pref.get("iodb.server.url", "http://offsets.textual.ru/"); 77 String query = "get?lat=" + center.getX() + "&lon=" + center.getY(); 78 List<ImageryOffsetBase> result = null; 79 try { 80 query = query + "&imagery=" + URLEncoder.encode(imagery, "utf-8"); 81 URL url = new URL(base + query); 82 System.out.println("url=" + url); 83 HttpURLConnection connection = (HttpURLConnection)url.openConnection(); 84 connection.connect(); 85 int retCode = connection.getResponseCode(); 86 InputStream inp = connection.getInputStream(); 87 if( inp != null ) { 88 result = new IODBReader(inp).parse(); 89 System.out.println("result.size() = " + result.size()); 131 class DownloadOffsetsTask extends SimpleOffsetQueryTask { 132 private ImageryLayer layer; 133 private List<ImageryOffsetBase> offsets; 134 135 public DownloadOffsetsTask( LatLon center, ImageryLayer layer, String imagery ) { 136 super(null, tr("Loading imagery offsets...")); 137 try { 138 String query = "get?lat=" + center.lat() + "&lon=" + center.lon() 139 + "&imagery=" + URLEncoder.encode(imagery, "UTF8"); 140 setQuery(query); 141 } catch( UnsupportedEncodingException e ) { 142 throw new IllegalArgumentException(e); 90 143 } 91 connection.disconnect(); 92 } catch( MalformedURLException ex ) { 93 // ? 94 } catch( UnsupportedEncodingException e ) { 95 // do nothing. WTF is that? 96 } catch( IOException e ) { 97 e.printStackTrace(); 98 // ? 99 } catch( SAXException e ) { 100 e.printStackTrace(); 101 // ? 102 } 103 if( result == null ) 104 result = new ArrayList<ImageryOffsetBase>(); 105 return result; 106 } 107 108 class DownloadOffsets extends PleaseWaitRunnable { 109 110 private boolean cancelled; 111 112 public DownloadOffsets() { 113 super(tr("Downloading calibration data")); 114 cancelled = false; 144 this.layer = layer; 115 145 } 116 146 117 147 @Override 118 protected void realRun() throws SAXException, IOException, OsmTransferException { 119 // todo: open httpconnection to server and read xml 120 if( cancelled ) 121 return; 122 123 } 124 125 @Override 126 protected void finish() { 127 if( cancelled ) 128 return; 129 // todo: parse xml and return an array of ImageryOffsetBase 148 protected void afterFinish() { 149 if( !cancelled && offsets != null ) 150 showOffsetDialog(offsets, layer); 130 151 } 131 152 132 153 @Override 133 protected void cancel() { 134 cancelled = true; 154 protected void processResponse( InputStream inp ) throws UploadException { 155 offsets = null; 156 try { 157 offsets = new IODBReader(inp).parse(); 158 } catch( Exception e ) { 159 throw new UploadException("Error processing XML response: " + e.getMessage()); 160 } 135 161 } 136 162 } -
applications/editors/josm/plugins/imagery_offset_db/src/iodb/IODBReader.java
r27986 r29371 59 59 if( qName.equals("object") ) { 60 60 fields.isNode = attributes.getValue("type").equals("node"); 61 } else if( qName.equals("last-user") ) { 62 fields.lastUserId = Integer.parseInt(attributes.getValue("id")); 61 63 } else if( qName.equals("imagery-position") ) { 62 64 fields.imageryPos = parseLatLon(attributes); … … 102 104 } else if( qName.equals("object") ) { 103 105 fields.objectId = Integer.parseInt(accumulator.toString()); 104 } else if( qName.equals("last-user") ) {105 fields.lastUserId = Integer.parseInt(accumulator.toString());106 106 } else if( qName.equals("offset") || qName.equals("calibration-object") ) { 107 107 // store offset -
applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffset.java
r28008 r29371 57 57 map.put("maxzoom", String.valueOf(maxZoom)); 58 58 } 59 60 @Override 61 public String toString() { 62 return "ImageryOffset{" + "imageryPos=" + imageryPos + ", imagery=" + imagery + "position=" + position + ", date=" + date + ", author=" + author + ", description=" + description + ", abandonDate=" + abandonDate + '}'; 63 } 59 64 } -
applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffsetBase.java
r28008 r29371 12 12 */ 13 13 public class ImageryOffsetBase { 14 private LatLon position; 15 private Date date; 16 private String author; 17 private String description; 18 private Date abandonDate; 14 protected long offsetId; 15 protected LatLon position; 16 protected Date date; 17 protected String author; 18 protected String description; 19 protected Date abandonDate; 20 protected String abandonAuthor; 21 protected String abandonReason; 19 22 20 23 public void setBasicInfo( LatLon position, String author, String description, Date date ) { … … 26 29 } 27 30 31 public void setId( long id ) { 32 this.offsetId = id; 33 } 34 35 public long getId() { 36 return offsetId; 37 } 38 28 39 public void setAbandonDate(Date abandonDate) { 29 40 this.abandonDate = abandonDate; … … 33 44 return abandonDate; 34 45 } 46 47 public String getAbandonAuthor() { 48 return abandonAuthor; 49 } 50 51 public String getAbandonReason() { 52 return abandonReason; 53 } 35 54 36 public boolean is Abandoned() {55 public boolean isDeprecated() { 37 56 return abandonDate != null; 38 57 } … … 50 69 } 51 70 71 public void setDescription( String description ) { 72 this.description = description; 73 } 74 52 75 public LatLon getPosition() { 53 76 return position; … … 60 83 map.put("description", description); 61 84 } 85 86 @Override 87 public String toString() { 88 return "ImageryOffsetBase{" + "position=" + position + ", date=" + date + ", author=" + author + ", description=" + description + ", abandonDate=" + abandonDate + '}'; 89 } 62 90 } -
applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffsetPlugin.java
r27986 r29371 20 20 storeAction = new StoreImageryOffsetAction(); 21 21 22 Main.main.menu.imageryMenu.addSeparator(); 23 Main.main.menu.imageryMenu.add(getAction); 24 Main.main.menu.imageryMenu.add(storeAction); 25 26 // todo: make MapMode for viewing and updating imagery offsets 22 // todo: correct menu 23 Main.main.menu.viewMenu.addSeparator(); 24 Main.main.menu.viewMenu.add(getAction); 25 Main.main.menu.viewMenu.add(storeAction); 26 27 // todo: add a button on toolbar 28 // todo: make MapMode for viewing and updating imagery offsets (is it needed?) 27 29 } 28 30 } -
applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffsetTools.java
r28008 r29371 1 1 package iodb; 2 2 3 import java.util.HashMap; 4 import java.util.List; 3 import java.util.*; 5 4 import org.openstreetmap.josm.Main; 6 5 import org.openstreetmap.josm.data.coor.EastNorth; 7 6 import org.openstreetmap.josm.data.coor.LatLon; 7 import org.openstreetmap.josm.data.imagery.ImageryInfo; 8 8 import org.openstreetmap.josm.data.projection.Projection; 9 9 import org.openstreetmap.josm.gui.MapView; 10 10 import org.openstreetmap.josm.gui.layer.ImageryLayer; 11 import static org.openstreetmap.josm.tools.I18n.tr; 11 12 12 13 /** … … 16 17 */ 17 18 public class ImageryOffsetTools { 18 p rivate static HashMap<String, String> imageryAliases;19 public static final String DIALOG_TITLE = tr("Imagery Offset"); 19 20 20 21 public static ImageryLayer getTopImageryLayer() { 22 if( Main.map == null || Main.map.mapView == null ) 23 return null; 21 24 List<ImageryLayer> layers = Main.map.mapView.getLayersOfType(ImageryLayer.class); 22 25 for( ImageryLayer layer : layers ) { … … 28 31 } 29 32 30 p rivatestatic LatLon getMapCenter() {33 public static LatLon getMapCenter() { 31 34 Projection proj = Main.getProjection(); 32 35 return Main.map == null || Main.map.mapView == null … … 37 40 Projection proj = Main.getProjection(); 38 41 EastNorth offsetCenter = proj.latlon2eastNorth(center); 39 EastNorth centerOffset = offsetCenter.add( layer.getDx(),layer.getDy()); // todo: add or substract?42 EastNorth centerOffset = offsetCenter.add(-layer.getDx(), -layer.getDy()); // todo: add or substract? 40 43 LatLon offsetLL = proj.eastNorth2latlon(centerOffset); 41 44 return offsetLL; … … 46 49 EastNorth center = proj.latlon2eastNorth(offset.getPosition()); 47 50 EastNorth offsetPos = proj.latlon2eastNorth(offset.getImageryPos()); 48 layer.setOffset( offsetPos.getX() - center.getX(), offsetPos.getY() - center.getY()); // todo: + or -?51 layer.setOffset(center.getX() - offsetPos.getX(), center.getY() - offsetPos.getY()); 49 52 } 50 53 … … 57 60 return null; 58 61 59 if( imageryAliases == null ) 60 loadImageryAliases(); 61 for( String substr : imageryAliases.keySet() ) 62 if( url.contains(substr) ) 63 return imageryAliases.get(substr); 64 65 return url; // todo: strip parametric parts, etc 66 } 67 68 private static void loadImageryAliases() { 69 if( imageryAliases == null ) 70 imageryAliases = new HashMap<String, String>(); 71 else 72 imageryAliases.clear(); 73 74 // { substring, alias } 75 imageryAliases.put("bing", "bing"); 76 // todo: load from a resource? 62 // predefined layers 63 if( layer.getInfo().getImageryType().equals(ImageryInfo.ImageryType.BING) || url.contains("tiles.virtualearth.net") ) 64 return "bing"; 65 66 if( layer.getInfo().getImageryType().equals(ImageryInfo.ImageryType.SCANEX) && url.toLowerCase().equals("irs") ) 67 return "scanex_irs"; 68 69 boolean isWMS = layer.getInfo().getImageryType().equals(ImageryInfo.ImageryType.WMS); 70 71 System.out.println(url); 72 73 // Remove protocol 74 int i = url.indexOf("://"); 75 url = url.substring(i + 3); 76 77 // Split URL into address and query string 78 i = url.indexOf('?'); 79 String query = ""; 80 if( i > 0 ) { 81 query = url.substring(i); 82 url = url.substring(0, i); 83 } 84 85 // Parse query parameters into a sorted map 86 Map<String, String> qparams = new TreeMap<String, String>(); 87 String[] qparamsStr = query.length() > 1 ? query.substring(1).split("&") : new String[0]; 88 for( String param : qparamsStr ) { 89 String[] kv = param.split("="); 90 kv[0] = kv[0].toLowerCase(); 91 // WMS: if this is WMS, remove all parameters except map and layers 92 if( isWMS && !(kv[0].equals("map") || kv[0].equals("layers")) ) 93 continue; 94 // TMS: skip parameters with variable values 95 if( kv.length > 1 && kv[1].indexOf('{') >= 0 && kv[1].indexOf('}') > 0 ) 96 continue; 97 qparams.put(kv[0].toLowerCase(), kv.length > 1 ? kv[1] : null); 98 } 99 100 // Reconstruct query parameters 101 StringBuilder sb = new StringBuilder(); 102 for( String qk : qparams.keySet() ) { 103 if( sb.length() > 0 ) 104 sb.append('&'); 105 else if( query.length() > 0 ) 106 sb.append('?'); 107 sb.append(qk).append('=').append(qparams.get(qk)); 108 } 109 query = sb.toString(); 110 111 // TMS: remove /{zoom} and /{y}.png parts 112 url = url.replaceAll("\\/\\{[^}]+\\}(?:\\.\\w+)?", ""); 113 // TMS: remove variable parts 114 url = url.replaceAll("\\{[^}]+\\}", ""); 115 while( url.contains("..") ) 116 url = url.replace("..", "."); 117 if( url.startsWith(".") ) 118 url = url.substring(1); 119 120 System.out.println("-> " + url + query); 121 return url + query; 77 122 } 78 123 … … 110 155 return intResult; 111 156 } 157 158 public static String getServerURL() { 159 return Main.pref.get("iodb.server.url", "http://offsets.textual.ru/"); 160 } 112 161 } -
applications/editors/josm/plugins/imagery_offset_db/src/iodb/OffsetDialog.java
r28008 r29371 29 29 OffsetDialogButton button = new OffsetDialogButton(offset); 30 30 button.addActionListener(this); 31 /* JPopupMenu popupMenu = new JPopupMenu(); 32 popupMenu.add(new OffsetInfoAction(offset)); 33 if( !offset.isDeprecated() ) 34 popupMenu.add(new DeprecateOffsetAction(offset)); 35 button.add(popupMenu);*/ 31 36 buttonPanel.add(button); 32 37 } 38 // todo: calibration objects and deprecated offsets button 33 39 JButton cancelButton = new JButton("Cancel"); 34 40 cancelButton.addActionListener(this); -
applications/editors/josm/plugins/imagery_offset_db/src/iodb/OffsetDialogButton.java
r28008 r29371 13 13 14 14 public OffsetDialogButton( ImageryOffsetBase offset ) { 15 super(offset.getDescription() + " (" + offset.getPosition().lat() + ", " + offset.getPosition().lon() + ")");15 super(offset.getDescription() + " (" + Math.round(offset.getPosition().greatCircleDistance(ImageryOffsetTools.getMapCenter())) + " m)"); 16 16 this.offset = offset; 17 17 } -
applications/editors/josm/plugins/imagery_offset_db/src/iodb/OffsetInfoAction.java
r29361 r29371 2 2 3 3 import java.awt.event.ActionEvent; 4 import java.awt.event.KeyEvent; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.UnsupportedEncodingException; 8 import java.net.*; 9 import java.util.ArrayList; 10 import java.util.Collections; 11 import java.util.HashMap; 12 import java.util.List; 13 import java.util.concurrent.Future; 14 import java.util.logging.Level; 15 import java.util.logging.Logger; 16 import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTMSTileSource; 4 import javax.swing.AbstractAction; 5 import javax.swing.JOptionPane; 17 6 import org.openstreetmap.josm.Main; 18 import org.openstreetmap.josm.actions.JosmAction;19 import org.openstreetmap.josm.data.coor.LatLon;20 import org.openstreetmap.josm.data.projection.Projection;21 import org.openstreetmap.josm.gui.MapView;22 import org.openstreetmap.josm.gui.PleaseWaitRunnable;23 import org.openstreetmap.josm.gui.layer.ImageryLayer;24 import org.openstreetmap.josm.gui.progress.ProgressMonitor;25 import org.openstreetmap.josm.io.OsmTransferException;26 7 import static org.openstreetmap.josm.tools.I18n.tr; 27 import org.openstreetmap.josm.tools.Shortcut; 28 import org.xml.sax.SAXException; 8 import org.openstreetmap.josm.tools.ImageProvider; 29 9 30 10 /** … … 33 13 * @author zverik 34 14 */ 35 public class GetImageryOffsetAction extends JosmAction { 15 public class OffsetInfoAction extends AbstractAction { 16 private ImageryOffsetBase offset; 36 17 37 private List<ImageryOffsetBase> offsets; 38 39 public GetImageryOffsetAction() { 40 super(tr("Get Imagery Offset..."), "getoffset", tr("Download offsets for current imagery from a server"), 41 Shortcut.registerShortcut("imageryoffset:get", tr("Imagery: {0}", tr("Get Imagery Offset...")), KeyEvent.VK_I, Shortcut.ALT+Shortcut.CTRL), true); 42 offsets = Collections.emptyList(); 18 public OffsetInfoAction( ImageryOffsetBase offset ) { 19 super(tr("Offset Information")); 20 putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete")); 21 this.offset = offset; 22 setEnabled(offset != null); 43 23 } 44 24 45 25 public void actionPerformed(ActionEvent e) { 46 Projection proj = Main.map.mapView.getProjection(); 47 LatLon center = proj.eastNorth2latlon(Main.map.mapView.getCenter()); 48 ImageryLayer layer = ImageryOffsetTools.getTopImageryLayer(); 49 String imagery = ImageryOffsetTools.getImageryID(layer); 50 if( imagery == null ) 51 return; 52 53 List<ImageryOffsetBase> offsets = download(center, imagery); // todo: async 54 /*DownloadOffsets download = new DownloadOffsets(); 55 Future<?> future = Main.worker.submit(download); 56 try { 57 future.get(); 58 } catch( Exception ex ) { 59 ex.printStackTrace(); 60 return; 61 }*/ 62 63 // todo: show a dialog for selecting one of the offsets (without "update" flag) 64 ImageryOffsetBase offset = new OffsetDialog(offsets).showDialog(); 65 if( offset != null ) { 66 // todo: use the chosen offset 67 if( offset instanceof ImageryOffset ) { 68 ImageryOffsetTools.applyLayerOffset(layer, (ImageryOffset)offset); 69 } else if( offset instanceof CalibrationObject ) { 70 // todo: select object 71 } 72 } 73 } 74 75 private List<ImageryOffsetBase> download( LatLon center, String imagery ) { 76 String base = Main.pref.get("iodb.server.url", "http://offsets.textual.ru/"); 77 String query = "get?lat=" + center.getX() + "&lon=" + center.getY(); 78 List<ImageryOffsetBase> result = null; 79 try { 80 query = query + "&imagery=" + URLEncoder.encode(imagery, "utf-8"); 81 URL url = new URL(base + query); 82 System.out.println("url=" + url); 83 HttpURLConnection connection = (HttpURLConnection)url.openConnection(); 84 connection.connect(); 85 int retCode = connection.getResponseCode(); 86 InputStream inp = connection.getInputStream(); 87 if( inp != null ) { 88 result = new IODBReader(inp).parse(); 89 System.out.println("result.size() = " + result.size()); 90 } 91 connection.disconnect(); 92 } catch( MalformedURLException ex ) { 93 // ? 94 } catch( UnsupportedEncodingException e ) { 95 // do nothing. WTF is that? 96 } catch( IOException e ) { 97 e.printStackTrace(); 98 // ? 99 } catch( SAXException e ) { 100 e.printStackTrace(); 101 // ? 102 } 103 if( result == null ) 104 result = new ArrayList<ImageryOffsetBase>(); 105 return result; 106 } 107 108 class DownloadOffsets extends PleaseWaitRunnable { 109 110 private boolean cancelled; 111 112 public DownloadOffsets() { 113 super(tr("Downloading calibration data")); 114 cancelled = false; 115 } 116 117 @Override 118 protected void realRun() throws SAXException, IOException, OsmTransferException { 119 // todo: open httpconnection to server and read xml 120 if( cancelled ) 121 return; 122 123 } 124 125 @Override 126 protected void finish() { 127 if( cancelled ) 128 return; 129 // todo: parse xml and return an array of ImageryOffsetBase 130 } 131 132 @Override 133 protected void cancel() { 134 cancelled = true; 135 } 26 JOptionPane.showMessageDialog(Main.parent, "TODO", ImageryOffsetTools.DIALOG_TITLE, JOptionPane.PLAIN_MESSAGE); 136 27 } 137 28 } -
applications/editors/josm/plugins/imagery_offset_db/src/iodb/StoreImageryOffsetAction.java
r28008 r29371 2 2 3 3 import java.awt.event.ActionEvent; 4 import java.util.HashMap; 5 import java.util.Map; 4 import java.io.UnsupportedEncodingException; 5 import java.net.*; 6 import java.util.*; 7 import javax.swing.JOptionPane; 6 8 import org.openstreetmap.josm.Main; 7 9 import org.openstreetmap.josm.actions.JosmAction; 8 10 import org.openstreetmap.josm.data.coor.LatLon; 9 import org.openstreetmap.josm.data.projection.Projection; 11 import org.openstreetmap.josm.data.osm.*; 12 import org.openstreetmap.josm.gui.JosmUserIdentityManager; 13 import org.openstreetmap.josm.gui.layer.ImageryLayer; 10 14 import static org.openstreetmap.josm.tools.I18n.tr; 11 15 … … 18 22 19 23 public StoreImageryOffsetAction() { 20 super(tr("Store Imagery Offset..."), "storeoffset", tr("Upload an offset for current imagery (or calibration object information) to a server"), null, false); 24 super(tr("Store Imagery Offset..."), "storeoffset", 25 tr("Upload an offset for current imagery (or calibration object information) to a server"), 26 null, false); 21 27 } 22 28 23 29 public void actionPerformed(ActionEvent e) { 24 // todo: check that there is an imagery 25 // and that it is moved 26 Projection proj = Main.map.mapView.getProjection(); 27 LatLon center = proj.eastNorth2latlon(Main.map.mapView.getCenter()); 28 // todo: open an upload window 29 // todo: if an object was selected, ask if the user wants to upload it 30 // todo: enter all metadata (that is, a description) 31 // todo: upload object info to server 30 if( Main.map == null || Main.map.mapView == null || getCurrentDataSet() == null ) 31 return; 32 33 ImageryLayer layer = ImageryOffsetTools.getTopImageryLayer(); 34 if( layer == null ) 35 return; 36 37 String userName = JosmUserIdentityManager.getInstance().getUserName(); 38 if( userName == null ) { 39 JOptionPane.showMessageDialog(Main.parent, tr("To store imagery offsets you must be a registered OSM user."), ImageryOffsetTools.DIALOG_TITLE, JOptionPane.ERROR_MESSAGE); 40 return; 41 } 42 43 // check if an object suitable for calibration is selected 44 OsmPrimitive calibration = null; 45 Collection<OsmPrimitive> selectedObjects = getCurrentDataSet().getSelected(); 46 if( selectedObjects.size() == 1 ) { 47 OsmPrimitive selection = selectedObjects.iterator().next(); 48 if( selection instanceof Node || selection instanceof Way ) { 49 boolean suitable = !selection.isNewOrUndeleted() && !selection.isDeleted() && !selection.isModified(); 50 if( selection instanceof Way ) { 51 for( Node n : ((Way)selection).getNodes() ) 52 if( n.isNewOrUndeleted() || n.isDeleted() || n.isModified() ) 53 suitable = false; 54 } else if( selection.isReferredByWays(1) ) { 55 suitable = false; 56 } 57 if( suitable ) { 58 String[] options = new String[] {tr("Store calibration object"), tr("Store imagery offset"), tr("Cancel")}; 59 int result = JOptionPane.showOptionDialog(Main.parent, 60 tr("The selected object can be used as a calibration object. What do you intend to do?"), ImageryOffsetTools.DIALOG_TITLE, JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, 61 null, options, options[0]); 62 if( result == 2 || result == JOptionPane.CLOSED_OPTION ) 63 return; 64 if( result == 0 ) 65 calibration = selection; 66 } else { 67 String[] options = new String[] {tr("Store imagery offset"), tr("Cancel")}; 68 int result = JOptionPane.showOptionDialog(Main.parent, 69 tr("You have an object selected and might want to use it as a calibration object.\n" 70 + "But in this case it should be uploaded to OSM server first."), ImageryOffsetTools.DIALOG_TITLE, JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, 71 null, options, options[1]); 72 if( result == 1 || result == JOptionPane.CLOSED_OPTION ) 73 return; 74 } 75 } 76 } 77 78 Object message = ""; 79 LatLon center = ImageryOffsetTools.getMapCenter(); 80 ImageryOffsetBase offsetObj; 81 if( calibration == null ) { 82 // register imagery offset 83 if( Math.abs(layer.getDx()) < 1e-8 && Math.abs(layer.getDy()) < 1e-8 ) { 84 if( JOptionPane.showConfirmDialog(Main.parent, 85 tr("The topmost imagery layer has no offset. Are you sure you want to upload it?"), ImageryOffsetTools.DIALOG_TITLE, JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION ) 86 return; 87 } 88 LatLon offset = ImageryOffsetTools.getLayerOffset(layer, center); 89 offsetObj = new ImageryOffset(ImageryOffsetTools.getImageryID(layer), offset); 90 message = "You are registering an imagery offset.\n" 91 + "Other users in this area will be able to use it for mapping.\n" 92 + "Please make sure it is as precise as possible, and\n" 93 + "describe a region this offset is applicable to."; 94 } else { 95 // register calibration object 96 offsetObj = new CalibrationObject(calibration); 97 message = "You are registering calibration object.\n" 98 + "It should be the most precisely positioned object,\n" 99 + "with clearly visible boundaries on various satellite imagery.\n" 100 + "Please describe a region where this object is located."; 101 } 102 offsetObj.setBasicInfo(center, userName, null, null); 103 String description = null; 104 boolean iterated = false; 105 while( description == null ) { 106 description = JOptionPane.showInputDialog(Main.parent, message, ImageryOffsetTools.DIALOG_TITLE, JOptionPane.PLAIN_MESSAGE); 107 if( description == null || description.length() == 0 ) 108 return; 109 if( description.length() < 3 || description.length() > 200 ) { 110 description = null; 111 if( !iterated ) { 112 message = message + "\n" + tr("Description should be 3 to 200 letters long."); 113 iterated = true; 114 } 115 } 116 } 117 offsetObj.setDescription(description); 118 119 // upload object info to server 120 try { 121 Map<String, String> params = new HashMap<String, String>(); 122 offsetObj.putServerParams(params); 123 StringBuilder query = null; 124 for( String key : params.keySet() ) { 125 if( query == null ) { 126 query = new StringBuilder("store?"); 127 } else { 128 query.append('&'); 129 } 130 query.append(key).append('=').append(URLEncoder.encode(params.get(key), "UTF8")); 131 } 132 Main.main.worker.submit(new SimpleOffsetQueryTask(query.toString(), tr("Uploading the new offset..."))); 133 } catch( UnsupportedEncodingException ex ) { 134 // WTF 135 } 32 136 } 33 34 private static void upload( ImageryOffsetBase offset ) { 35 String base = Main.pref.get("iodb.server.url", "http://offsets.textual.ru/"); 36 Map<String, String> params = new HashMap<String, String>(); 37 offset.putServerParams(params); 38 // todo 137 138 @Override 139 protected void updateEnabledState() { 140 boolean state = true; 141 if( Main.map == null || Main.map.mapView == null || !Main.map.isVisible() ) 142 state = false; 143 if( ImageryOffsetTools.getTopImageryLayer() == null ) 144 state = false; 145 setEnabled(state); 39 146 } 40 147 }
Note:
See TracChangeset
for help on using the changeset viewer.