Changeset 31328 in osm for applications


Ignore:
Timestamp:
2015-07-01T22:11:56+02:00 (9 years ago)
Author:
nokutu
Message:

#11619, trying to fix the concurrency issues and some toher bugs

Location:
applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryAbstractImage.java

    r31311 r31328  
    66import java.util.Calendar;
    77import java.util.TimeZone;
     8import java.util.concurrent.locks.Lock;
     9import java.util.concurrent.locks.ReentrantLock;
    810
    911import org.openstreetmap.josm.Main;
     
    1820 */
    1921public abstract class MapillaryAbstractImage {
     22   
     23    public static Lock lock = new ReentrantLock();
    2024
    2125    private long capturedAt;
     
    147151        else
    148152            format += "dd/MM/yyyy";
    149         if (Main.pref.getBoolean("mapillary.display-hour", true)){
     153        if (Main.pref.getBoolean("mapillary.display-hour", true)) {
    150154            if (Main.pref.getBoolean("mapillary.format-24"))
    151155                format += " - HH:mm:ss (z)";
     
    177181        return formatter.format(date);
    178182    }
    179    
     183
    180184    public long getEpoch(String date, String format) {
    181        
     185
    182186        SimpleDateFormat formatter = new SimpleDateFormat(format);
    183187        try {
    184188            Date dateTime = (Date) formatter.parse(date);
    185             return dateTime.getTime();       
     189            return dateTime.getTime();
    186190        } catch (ParseException e) {
    187191            Main.error(e);
     
    189193        return currentTime();
    190194    }
    191    
     195
    192196    private long currentTime() {
    193197        Calendar cal = Calendar.getInstance();
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java

    r31315 r31328  
    2020 */
    2121public class MapillaryData implements ICachedLoaderListener {
    22         public volatile static MapillaryData INSTANCE;
    23         public static boolean TEST_MODE = false;
    24 
    25         private final List<MapillaryAbstractImage> images;
    26         private MapillaryAbstractImage selectedImage;
    27         private MapillaryAbstractImage hoveredImage;
    28         private final List<MapillaryAbstractImage> multiSelectedImages;
    29 
    30         private List<MapillaryDataListener> listeners = new ArrayList<>();
    31 
    32         public MapillaryData() {
    33                 images = new CopyOnWriteArrayList<>();
    34                 multiSelectedImages = new ArrayList<>();
    35                 selectedImage = null;
    36         }
    37 
    38         public static MapillaryData getInstance() {
    39                 if (INSTANCE == null) {
    40                         INSTANCE = new MapillaryData();
    41                 }
    42                 return INSTANCE;
    43         }
    44 
    45         /**
    46         * Adds a set of MapillaryImages to the object, and then repaints mapView.
    47         *
    48         * @param images
    49         *            The set of images to be added.
    50         */
    51         public synchronized void add(List<MapillaryAbstractImage> images) {
    52                 for (MapillaryAbstractImage image : images) {
    53                         add(image);
    54                 }
    55         }
    56 
    57         /**
    58         * Adds an MapillaryImage to the object, and then repaints mapView.
    59         *
    60         * @param image
    61         *            The image to be added.
    62         */
    63         public synchronized void add(MapillaryAbstractImage image) {
    64                 if (!images.contains(image)) {
    65                         this.images.add(image);
    66                 }
    67                 dataUpdated();
    68                 fireImagesAdded();
    69         }
    70 
    71         public void addListener(MapillaryDataListener lis) {
    72                 listeners.add(lis);
    73         }
    74 
    75         public void removeListener(MapillaryDataListener lis) {
    76                 listeners.remove(lis);
    77         }
    78 
    79         /**
    80         * Adds a set of MapillaryImages to the object, but doesn't repaint mapView.
    81         * This is needed for concurrency.
    82         *
    83         * @param images
    84         *            The set of images to be added.
    85         */
    86         public synchronized void addWithoutUpdate(
    87                         List<MapillaryAbstractImage> images) {
    88                 for (MapillaryAbstractImage image : images) {
    89                         addWithoutUpdate(image);
    90                 }
    91         }
    92 
    93         /**
    94         * Sets the image under the mouse cursor.
    95         *
    96         * @param image
    97         */
    98         public void setHoveredImage(MapillaryAbstractImage image) {
    99                 hoveredImage = image;
    100         }
    101 
    102         /**
    103         * Returns the image under the mouse cursor.
    104         *
    105         * @return
    106         */
    107         public MapillaryAbstractImage getHoveredImage() {
    108                 return hoveredImage;
    109         }
    110 
    111         /**
    112         * Adds a MapillaryImage to the object, but doesn't repaint mapView. This is
    113         * needed for concurrency.
    114         *
    115         * @param image
    116         *            The image to be added.
    117         */
    118         public synchronized void addWithoutUpdate(MapillaryAbstractImage image) {
    119                 if (!images.contains(image)) {
    120                         this.images.add(image);
    121                 }
    122                 fireImagesAdded();
    123         }
    124 
    125         /**
    126         * Repaints mapView object.
    127         */
    128         public synchronized void dataUpdated() {
    129                 if (!TEST_MODE)
    130                         Main.map.mapView.repaint();
    131         }
    132 
    133         /**
    134         * Returns a List containing all images.
    135         *
    136         * @return A List object containing all images.
    137         */
    138         public List<MapillaryAbstractImage> getImages() {
    139                 return images;
    140         }
    141 
    142         /**
    143         * Returns the MapillaryImage object that is currently selected.
    144         *
    145         * @return The selected MapillaryImage object.
    146         */
    147         public MapillaryAbstractImage getSelectedImage() {
    148                 return selectedImage;
    149         }
    150 
    151         private void fireImagesAdded() {
    152                 if (listeners.isEmpty())
    153                         return;
    154                 for (MapillaryDataListener lis : listeners)
    155                         lis.imagesAdded();
    156         }
    157 
    158         /**
    159         * If the selected MapillaryImage is part of a MapillarySequence then the
    160         * following visible MapillaryImage is selected. In case there is none, does
    161         * nothing.
    162         */
    163         public void selectNext() {
    164                 if (getSelectedImage() instanceof MapillaryImage) {
    165                         if (getSelectedImage() == null)
    166                                 return;
    167                         if (((MapillaryImage) getSelectedImage()).getSequence() == null)
    168                                 return;
    169                         if (selectedImage instanceof MapillaryImage
    170                                         && ((MapillaryImage) selectedImage).getSequence() != null) {
    171                                 MapillaryImage tempImage = (MapillaryImage) selectedImage;
    172                                 while (tempImage.next() != null) {
    173                                         tempImage = tempImage.next();
    174                                         if (tempImage.isVisible()) {
    175                                                 setSelectedImage(tempImage, Main.pref.getBoolean(
    176                                                                 "mapillary.move-to-picture", true));
    177                                                 break;
    178                                         }
    179                                 }
    180                         }
    181                 }
    182         }
    183 
    184         /**
    185         * If the selected MapillaryImage is part of a MapillarySequence then the
    186         * previous visible MapillaryImage is selected. In case there is none, does
    187         * nothing.
    188         */
    189         public void selectPrevious() {
    190                 if (getSelectedImage() instanceof MapillaryImage) {
    191                         if (getSelectedImage() == null)
    192                                 return;
    193                         if (((MapillaryImage) getSelectedImage()).getSequence() == null)
    194                                 throw new IllegalStateException();
    195                         if (selectedImage instanceof MapillaryImage
    196                                         && ((MapillaryImage) selectedImage).getSequence() != null) {
    197                                 MapillaryImage tempImage = (MapillaryImage) selectedImage;
    198                                 while (tempImage.previous() != null) {
    199                                         tempImage = tempImage.previous();
    200                                         if (tempImage.isVisible()) {
    201                                                 setSelectedImage(tempImage, Main.pref.getBoolean(
    202                                                                 "mapillary.move-to-picture", true));
    203                                                 break;
    204                                         }
    205                                 }
    206                         }
    207                 }
    208         }
    209 
    210         /**
    211         * Selects a new image and then starts a new MapillaryImageDownloadThread
    212         * thread in order to download its surrounding thumbnails. If the user does
    213         * ctrl+click, this isn't triggered.
    214         *
    215         * @param image
    216         *            The MapillaryImage which is going to be selected
    217         */
    218         public void setSelectedImage(MapillaryAbstractImage image) {
    219                 setSelectedImage(image, false);
    220         }
    221 
    222         /**
    223         * Selects a new image and then starts a new MapillaryImageDownloadThread
    224         * thread in order to download its surrounding thumbnails. If the user does
    225         * ctrl+click, this isn't triggered. You can choose whether to center the
    226         * view on the new image or not.
    227         *
    228         * @param image
    229         * @param zoom
    230         */
    231         public void setSelectedImage(MapillaryAbstractImage image, boolean zoom) {
    232                 MapillaryAbstractImage oldImage = selectedImage;
    233                 selectedImage = image;
    234                 multiSelectedImages.clear();
    235                 multiSelectedImages.add(image);
    236                 if (image != null) {
    237                         if (image instanceof MapillaryImage) {
    238                                 MapillaryImage mapillaryImage = (MapillaryImage) image;
    239                                 if (mapillaryImage.next() != null) {
    240                                         new MapillaryCache(mapillaryImage.next().getKey(),
    241                                                         MapillaryCache.Type.THUMBNAIL).submit(this, false);
    242                                         if (mapillaryImage.next().next() != null)
    243                                                 new MapillaryCache(mapillaryImage.next().next()
    244                                                                 .getKey(), MapillaryCache.Type.THUMBNAIL)
    245                                                                 .submit(this, false);
    246                                 }
    247                                 if (mapillaryImage.previous() != null) {
    248                                         new MapillaryCache(mapillaryImage.previous().getKey(),
    249                                                         MapillaryCache.Type.THUMBNAIL).submit(this, false);
    250                                         if (mapillaryImage.previous().previous() != null)
    251                                                 new MapillaryCache(mapillaryImage.previous().previous()
    252                                                                 .getKey(), MapillaryCache.Type.THUMBNAIL)
    253                                                                 .submit(this, false);
    254                                 }
    255                         }
    256                 }
    257                 if (zoom)
    258                         Main.map.mapView.zoomTo(MapillaryData.getInstance()
    259                                         .getSelectedImage().getLatLon());
    260                 if (Main.map != null)
    261                         Main.map.mapView.repaint();
    262                 fireSelectedImageChanged(oldImage, selectedImage);
    263         }
    264 
    265         private void fireSelectedImageChanged(MapillaryAbstractImage oldImage,
    266                         MapillaryAbstractImage newImage) {
    267                 if (listeners.isEmpty())
    268                         return;
    269                 for (MapillaryDataListener lis : listeners)
    270                         lis.selectedImageChanged(oldImage, newImage);
    271         }
    272 
    273         /**
    274         * Adds a MapillaryImage object to the list of selected images, (when ctrl +
    275         * click)
    276         *
    277         * @param image
    278         *            The MapillaryImage object to be added.
    279         */
    280         public void addMultiSelectedImage(MapillaryAbstractImage image) {
    281                 if (!this.multiSelectedImages.contains(image)) {
    282                         if (this.getSelectedImage() != null)
    283                                 this.multiSelectedImages.add(image);
    284                         else
    285                                 this.setSelectedImage(image);
    286                 }
    287                 Main.map.mapView.repaint();
    288         }
    289 
    290         /**
    291         * Adds a set of MapillaryImage objects to the list of selected images.
    292         *
    293         * @param images
    294         */
    295         public void addMultiSelectedImage(List<MapillaryAbstractImage> images) {
    296                 for (MapillaryAbstractImage image : images)
    297                         if (!this.multiSelectedImages.contains(image)) {
    298                                 if (this.getSelectedImage() != null)
    299                                         this.multiSelectedImages.add(image);
    300                                 else
    301                                         this.setSelectedImage(image);
    302                         }
    303                 Main.map.mapView.repaint();
    304         }
    305 
    306         /**
    307         * Returns a list containing all MapillaryImage objects selected with ctrl +
    308         * click
    309         *
    310         * @return
    311         */
    312         public List<MapillaryAbstractImage> getMultiSelectedImages() {
    313                 return multiSelectedImages;
    314         }
    315 
    316         /**
    317         * This is empty because it is used just to make sure that certain images
    318         * have already been downloaded.
    319         */
    320         @Override
    321         public void loadingFinished(CacheEntry data,
    322                         CacheEntryAttributes attributes, LoadResult result) {
    323                 // DO NOTHING
    324         }
    325 
    326         /**
    327         * Returns the amount of images contained by this object.
    328         *
    329         * @return
    330         */
    331         public int size() {
    332                 return images.size();
    333         }
     22    public volatile static MapillaryData INSTANCE;
     23    public static boolean TEST_MODE = false;
     24
     25    private final List<MapillaryAbstractImage> images;
     26    private MapillaryAbstractImage selectedImage;
     27    private MapillaryAbstractImage hoveredImage;
     28    private final List<MapillaryAbstractImage> multiSelectedImages;
     29
     30    private List<MapillaryDataListener> listeners = new ArrayList<>();
     31
     32    public MapillaryData() {
     33        images = new CopyOnWriteArrayList<>();
     34        multiSelectedImages = new ArrayList<>();
     35        selectedImage = null;
     36    }
     37
     38    public static MapillaryData getInstance() {
     39        if (INSTANCE == null) {
     40            INSTANCE = new MapillaryData();
     41        }
     42        return INSTANCE;
     43    }
     44
     45    /**
     46    * Adds a set of MapillaryImages to the object, and then repaints mapView.
     47    *
     48    * @param images
     49    *            The set of images to be added.
     50    */
     51    public synchronized void add(List<MapillaryAbstractImage> images) {
     52        for (MapillaryAbstractImage image : images) {
     53            add(image);
     54        }
     55    }
     56
     57    /**
     58    * Adds an MapillaryImage to the object, and then repaints mapView.
     59    *
     60    * @param image
     61    *            The image to be added.
     62    */
     63    public synchronized void add(MapillaryAbstractImage image) {
     64        if (!images.contains(image)) {
     65            this.images.add(image);
     66        }
     67        dataUpdated();
     68        fireImagesAdded();
     69    }
     70
     71    public void addListener(MapillaryDataListener lis) {
     72        listeners.add(lis);
     73    }
     74
     75    public void removeListener(MapillaryDataListener lis) {
     76        listeners.remove(lis);
     77    }
     78
     79    /**
     80    * Adds a set of MapillaryImages to the object, but doesn't repaint mapView.
     81    * This is needed for concurrency.
     82    *
     83    * @param images
     84    *            The set of images to be added.
     85    */
     86    public synchronized void addWithoutUpdate(
     87            List<MapillaryAbstractImage> images) {
     88        for (MapillaryAbstractImage image : images) {
     89            addWithoutUpdate(image);
     90        }
     91    }
     92
     93    /**
     94    * Sets the image under the mouse cursor.
     95    *
     96    * @param image
     97    */
     98    public void setHoveredImage(MapillaryAbstractImage image) {
     99        hoveredImage = image;
     100    }
     101
     102    /**
     103    * Returns the image under the mouse cursor.
     104    *
     105    * @return
     106    */
     107    public MapillaryAbstractImage getHoveredImage() {
     108        return hoveredImage;
     109    }
     110
     111    /**
     112    * Adds a MapillaryImage to the object, but doesn't repaint mapView. This is
     113    * needed for concurrency.
     114    *
     115    * @param image
     116    *            The image to be added.
     117    */
     118    public synchronized void addWithoutUpdate(MapillaryAbstractImage image) {
     119        if (!images.contains(image)) {
     120            this.images.add(image);
     121        }
     122        fireImagesAdded();
     123    }
     124
     125    /**
     126    * Repaints mapView object.
     127    */
     128    public synchronized void dataUpdated() {
     129        if (!TEST_MODE)
     130            Main.map.mapView.repaint();
     131    }
     132
     133    /**
     134    * Returns a List containing all images.
     135    *
     136    * @return A List object containing all images.
     137    */
     138    public List<MapillaryAbstractImage> getImages() {
     139        return images;
     140    }
     141
     142    /**
     143    * Returns the MapillaryImage object that is currently selected.
     144    *
     145    * @return The selected MapillaryImage object.
     146    */
     147    public MapillaryAbstractImage getSelectedImage() {
     148        return selectedImage;
     149    }
     150
     151    private void fireImagesAdded() {
     152        if (listeners.isEmpty())
     153            return;
     154        for (MapillaryDataListener lis : listeners)
     155            lis.imagesAdded();
     156    }
     157
     158    /**
     159    * If the selected MapillaryImage is part of a MapillarySequence then the
     160    * following visible MapillaryImage is selected. In case there is none, does
     161    * nothing.
     162    */
     163    public void selectNext() {
     164        if (getSelectedImage() instanceof MapillaryImage) {
     165            if (getSelectedImage() == null)
     166                return;
     167            if (((MapillaryImage) getSelectedImage()).getSequence() == null)
     168                return;
     169            if (selectedImage instanceof MapillaryImage
     170                    && ((MapillaryImage) selectedImage).getSequence() != null) {
     171                MapillaryImage tempImage = (MapillaryImage) selectedImage;
     172                while (tempImage.next() != null) {
     173                    tempImage = tempImage.next();
     174                    if (tempImage.isVisible()) {
     175                        setSelectedImage(tempImage, Main.pref.getBoolean(
     176                                "mapillary.move-to-picture", true));
     177                        break;
     178                    }
     179                }
     180            }
     181        }
     182    }
     183
     184    /**
     185    * If the selected MapillaryImage is part of a MapillarySequence then the
     186    * previous visible MapillaryImage is selected. In case there is none, does
     187    * nothing.
     188    */
     189    public void selectPrevious() {
     190        if (getSelectedImage() instanceof MapillaryImage) {
     191            if (getSelectedImage() == null)
     192                return;
     193            if (((MapillaryImage) getSelectedImage()).getSequence() == null)
     194                throw new IllegalStateException();
     195            if (selectedImage instanceof MapillaryImage
     196                    && ((MapillaryImage) selectedImage).getSequence() != null) {
     197                MapillaryImage tempImage = (MapillaryImage) selectedImage;
     198                while (tempImage.previous() != null) {
     199                    tempImage = tempImage.previous();
     200                    if (tempImage.isVisible()) {
     201                        setSelectedImage(tempImage, Main.pref.getBoolean(
     202                                "mapillary.move-to-picture", true));
     203                        break;
     204                    }
     205                }
     206            }
     207        }
     208    }
     209
     210    /**
     211    * Selects a new image and then starts a new MapillaryImageDownloadThread
     212    * thread in order to download its surrounding thumbnails. If the user does
     213    * ctrl+click, this isn't triggered.
     214    *
     215    * @param image
     216    *            The MapillaryImage which is going to be selected
     217    */
     218    public void setSelectedImage(MapillaryAbstractImage image) {
     219        setSelectedImage(image, false);
     220    }
     221
     222    /**
     223    * Selects a new image and then starts a new MapillaryImageDownloadThread
     224    * thread in order to download its surrounding thumbnails. If the user does
     225    * ctrl+click, this isn't triggered. You can choose whether to center the
     226    * view on the new image or not.
     227    *
     228    * @param image
     229    * @param zoom
     230    */
     231    public void setSelectedImage(MapillaryAbstractImage image, boolean zoom) {
     232        MapillaryAbstractImage oldImage = selectedImage;
     233        selectedImage = image;
     234        multiSelectedImages.clear();
     235        multiSelectedImages.add(image);
     236        if (image != null) {
     237            if (image instanceof MapillaryImage) {
     238                MapillaryImage mapillaryImage = (MapillaryImage) image;
     239                if (mapillaryImage.next() != null) {
     240                    new MapillaryCache(mapillaryImage.next().getKey(),
     241                            MapillaryCache.Type.THUMBNAIL).submit(this, false);
     242                    if (mapillaryImage.next().next() != null)
     243                        new MapillaryCache(mapillaryImage.next().next()
     244                                .getKey(), MapillaryCache.Type.THUMBNAIL)
     245                                .submit(this, false);
     246                }
     247                if (mapillaryImage.previous() != null) {
     248                    new MapillaryCache(mapillaryImage.previous().getKey(),
     249                            MapillaryCache.Type.THUMBNAIL).submit(this, false);
     250                    if (mapillaryImage.previous().previous() != null)
     251                        new MapillaryCache(mapillaryImage.previous().previous()
     252                                .getKey(), MapillaryCache.Type.THUMBNAIL)
     253                                .submit(this, false);
     254                }
     255            }
     256        }
     257        if (zoom)
     258            Main.map.mapView.zoomTo(MapillaryData.getInstance()
     259                    .getSelectedImage().getLatLon());
     260        if (Main.map != null)
     261            Main.map.mapView.repaint();
     262        fireSelectedImageChanged(oldImage, selectedImage);
     263    }
     264
     265    private void fireSelectedImageChanged(MapillaryAbstractImage oldImage,
     266            MapillaryAbstractImage newImage) {
     267        if (listeners.isEmpty())
     268            return;
     269        for (MapillaryDataListener lis : listeners)
     270            lis.selectedImageChanged(oldImage, newImage);
     271    }
     272
     273    /**
     274    * Adds a MapillaryImage object to the list of selected images, (when ctrl +
     275    * click)
     276    *
     277    * @param image
     278    *            The MapillaryImage object to be added.
     279    */
     280    public void addMultiSelectedImage(MapillaryAbstractImage image) {
     281        if (!this.multiSelectedImages.contains(image)) {
     282            if (this.getSelectedImage() != null)
     283                this.multiSelectedImages.add(image);
     284            else
     285                this.setSelectedImage(image);
     286        }
     287        Main.map.mapView.repaint();
     288    }
     289
     290    /**
     291    * Adds a set of MapillaryImage objects to the list of selected images.
     292    *
     293    * @param images
     294    */
     295    public void addMultiSelectedImage(List<MapillaryAbstractImage> images) {
     296        for (MapillaryAbstractImage image : images)
     297            if (!this.multiSelectedImages.contains(image)) {
     298                if (this.getSelectedImage() != null)
     299                    this.multiSelectedImages.add(image);
     300                else
     301                    this.setSelectedImage(image);
     302            }
     303        Main.map.mapView.repaint();
     304    }
     305
     306    /**
     307    * Returns a list containing all MapillaryImage objects selected with ctrl +
     308    * click
     309    *
     310    * @return
     311    */
     312    public List<MapillaryAbstractImage> getMultiSelectedImages() {
     313        return multiSelectedImages;
     314    }
     315
     316    /**
     317    * This is empty because it is used just to make sure that certain images
     318    * have already been downloaded.
     319    */
     320    @Override
     321    public void loadingFinished(CacheEntry data,
     322            CacheEntryAttributes attributes, LoadResult result) {
     323        // DO NOTHING
     324    }
     325
     326    /**
     327    * Returns the amount of images contained by this object.
     328    *
     329    * @return
     330    */
     331    public int size() {
     332        return images.size();
     333    }
    334334}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryDataListener.java

    r31284 r31328  
    22
    33public interface MapillaryDataListener {
    4    
     4
    55    public void imagesAdded();
    6    
     6
    77    /**
    88     * Fired when the selected image is changed by something different from
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java

    r31322 r31328  
    1212 */
    1313public class MapillaryImage extends MapillaryAbstractImage {
    14         /** Unique identifier of the object */
    15         private final String key;
    16         /** Sequence of pictures containing this object */
    17         private MapillarySequence sequence;
     14    /** Unique identifier of the object */
     15    private final String key;
     16    /** Sequence of pictures containing this object */
     17    private MapillarySequence sequence;
    1818
    19         /** Epoch time when the image was taken. */
    20         /** The user that made the image */
    21         private String user;
    22         /** Set of traffic signs in the image */
    23         private List<String> signs;
    24         private String location;
     19    /** Epoch time when the image was taken. */
     20    /** The user that made the image */
     21    private String user;
     22    /** Set of traffic signs in the image */
     23    private List<String> signs;
     24    private String location;
    2525
    26         public String getLocation() {
    27                 return location;
    28         }
     26    public String getLocation() {
     27        return location;
     28    }
    2929
    30         public void setLocation(String location) {
    31                 this.location = location;
    32         }
     30    public void setLocation(String location) {
     31        this.location = location;
     32    }
    3333
    34         /**
    35         * Main contructor of the class MapillaryImage
    36         *
    37         * @param key
    38         *            The unique identifier of the image.
    39         * @param lat
    40         *            The latitude where it is positioned.
    41         * @param lon
    42         *            The longitude where it is positioned.
    43         * @param ca
    44         *            The direction of the images in degrees, meaning 0 north.
    45         */
    46         public MapillaryImage(String key, double lat, double lon, double ca) {
    47                 super(lat, lon, ca);
    48                 this.key = key;
    49                 this.signs = new ArrayList<>();
    50         }
     34    /**
     35    * Main contructor of the class MapillaryImage
     36    *
     37    * @param key
     38    *            The unique identifier of the image.
     39    * @param lat
     40    *            The latitude where it is positioned.
     41    * @param lon
     42    *            The longitude where it is positioned.
     43    * @param ca
     44    *            The direction of the images in degrees, meaning 0 north.
     45    */
     46    public MapillaryImage(String key, double lat, double lon, double ca) {
     47        super(lat, lon, ca);
     48        this.key = key;
     49        this.signs = new ArrayList<>();
     50    }
    5151
    52         /**
    53         * Returns the unique identifier of the object.
    54         *
    55         * @return A String containing the unique identifier of the object.
    56         */
    57         public String getKey() {
    58                 return this.key;
    59         }
     52    /**
     53    * Returns the unique identifier of the object.
     54    *
     55    * @return A String containing the unique identifier of the object.
     56    */
     57    public String getKey() {
     58        return this.key;
     59    }
    6060
    61         /**
    62         * Adds a new sign to the set of signs.
    63         *
    64         * @param sign
    65         */
    66         public void addSign(String sign) {
    67                 signs.add(sign);
    68         }
     61    /**
     62    * Adds a new sign to the set of signs.
     63    *
     64    * @param sign
     65    */
     66    public void addSign(String sign) {
     67        signs.add(sign);
     68    }
    6969
    70         public List<String> getSigns() {
    71                 return signs;
    72         }
     70    public List<String> getSigns() {
     71        return signs;
     72    }
    7373
    74         public void setUser(String user) {
    75                 this.user = user;
    76         }
     74    public void setUser(String user) {
     75        this.user = user;
     76    }
    7777
    78         public String getUser() {
    79                 return user;
    80         }
     78    public String getUser() {
     79        return user;
     80    }
    8181
    82         /**
    83         * Sets the MapillarySequence object which contains the MapillaryImage.
    84         *
    85         * @param sequence
    86         *            The MapillarySequence that contains the MapillaryImage.
    87         */
    88         public void setSequence(MapillarySequence sequence) {
    89                 this.sequence = sequence;
    90         }
     82    /**
     83    * Sets the MapillarySequence object which contains the MapillaryImage.
     84    *
     85    * @param sequence
     86    *            The MapillarySequence that contains the MapillaryImage.
     87    */
     88    public void setSequence(MapillarySequence sequence) {
     89        this.sequence = sequence;
     90    }
    9191
    92         /**
    93         * Returns the sequence which contains this image.
    94         *
    95         * @return The MapillarySequence object that contains this MapillaryImage.
    96         */
    97         public MapillarySequence getSequence() {
    98                 return this.sequence;
    99         }
     92    /**
     93    * Returns the sequence which contains this image.
     94    *
     95    * @return The MapillarySequence object that contains this MapillaryImage.
     96    */
     97    public MapillarySequence getSequence() {
     98        return this.sequence;
     99    }
    100100
    101         public String toString() {
    102                 return "Image[key=" + this.key + ";lat=" + this.latLon.lat() + ";lon="
    103                                 + this.latLon.lon() + ";ca=" + this.ca + "]";
    104         }
     101    public String toString() {
     102        return "Image[key=" + this.key + ";lat=" + this.latLon.lat() + ";lon="
     103                + this.latLon.lon() + ";ca=" + this.ca + "]";
     104    }
    105105
    106         /**
    107          * If the MapillaryImage belongs to a MapillarySequence, returns the next
    108          * MapillarySequence in it.
    109          *
    110          * @return The following MapillaryImage, or null if there is none.
    111          */
    112         public MapillaryImage next() {
    113                 if (this.getSequence() == null)
    114                         return null;
    115                 return this.getSequence().next(this);
    116         }
     106    /**
     107     * If the MapillaryImage belongs to a MapillarySequence, returns the next
     108     * MapillarySequence in it.
     109     *
     110     * @return The following MapillaryImage, or null if there is none.
     111     */
     112    public MapillaryImage next() {
     113        synchronized (lock) {
     114            if (this.getSequence() == null)
     115                return null;
     116            return this.getSequence().next(this);
     117        }
     118    }
    117119
    118         /**
    119          * If the MapillaryImage belongs to a MapillarySequence, returns the
    120          * previous MapillarySequence in it.
    121          *
    122          * @return The previous MapillaryImage, or null if there is none.
    123          */
    124         public MapillaryImage previous() {
    125                 if (this.getSequence() == null)
    126                         return null;
    127                 return this.getSequence().previous(this);
    128         }
     120    /**
     121     * If the MapillaryImage belongs to a MapillarySequence, returns the
     122     * previous MapillarySequence in it.
     123     *
     124     * @return The previous MapillaryImage, or null if there is none.
     125     */
     126    public MapillaryImage previous() {
     127        synchronized (lock) {
     128            if (this.getSequence() == null)
     129                return null;
     130            return this.getSequence().previous(this);
     131        }
     132    }
    129133
    130         @Override
    131         public boolean equals(Object object) {
    132                 if (object instanceof MapillaryImage)
    133                         return this.key.equals(((MapillaryImage) object).getKey());
    134                 return false;
    135         }
     134    @Override
     135    public boolean equals(Object object) {
     136        if (object instanceof MapillaryImage)
     137            return this.key.equals(((MapillaryImage) object).getKey());
     138        return false;
     139    }
    136140
    137         @Override
    138         public int hashCode() {
    139                 return this.key.hashCode();
    140         }
     141    @Override
     142    public int hashCode() {
     143        return this.key.hashCode();
     144    }
    141145}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImportedImage.java

    r31319 r31328  
    1616    protected File file;
    1717    public final long datetimeOriginal;
    18    
     18
    1919    public MapillaryImportedImage(double lat, double lon, double ca, File file) {
    20         this(lat, lon, ca, file, currentDate());
     20        this(lat, lon, ca, file, currentDate());
    2121    }
    2222
     
    2525        super(lat, lon, ca);
    2626        this.file = file;
    27         this.datetimeOriginal = getEpoch(datetimeOriginal, "yyyy:MM:dd hh:mm:ss");
     27        this.datetimeOriginal = getEpoch(datetimeOriginal,
     28                "yyyy:MM:dd hh:mm:ss");
    2829    }
    2930
     
    5354        return this.file.hashCode();
    5455    }
    55    
     56
    5657    private static String currentDate() {
    5758        Calendar cal = Calendar.getInstance();
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java

    r31322 r31328  
    5959
    6060public class MapillaryLayer extends AbstractModifiableLayer implements
    61                 DataSetListener, EditLayerChangeListener, LayerChangeListener {
    62 
    63         public final static int SEQUENCE_MAX_JUMP_DISTANCE = Main.pref.getInteger(
    64                         "mapillary.sequence-max-jump-distance", 100);
    65 
    66         public static MapillaryLayer INSTANCE;
    67         public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
    68         public static MapillaryImage BLUE;
    69         public static MapillaryImage RED;
    70 
    71         public final MapillaryData data = MapillaryData.getInstance();
    72 
    73         public ArrayList<Bounds> bounds;
    74 
    75         private MouseAdapter mouseAdapter;
    76 
    77         private int highlightPointRadius = Main.pref.getInteger(
    78                         "mappaint.highlight.radius", 7);
    79         private int highlightStep = Main.pref.getInteger("mappaint.highlight.step",
    80                         4);
    81 
    82         private volatile TexturePaint hatched;
    83 
    84         public MapillaryLayer() {
    85                 super(tr("Mapillary Images"));
    86                 bounds = new ArrayList<>();
    87                 init();
    88         }
    89 
    90         /**
    91          * Initializes the Layer.
    92          */
    93         private void init() {
    94                 MapillaryLayer.INSTANCE = this;
    95                 startMouseAdapter();
    96                 try {
    97                         CACHE = JCSCacheManager.getCache("Mapillary");
    98                 } catch (IOException e) {
    99                         Main.error(e);
    100                 }
    101                 if (Main.map != null && Main.map.mapView != null) {
    102                         Main.map.mapView.addMouseListener(mouseAdapter);
    103                         Main.map.mapView.addMouseMotionListener(mouseAdapter);
    104                         Main.map.mapView.addLayer(this);
    105                         MapView.addEditLayerChangeListener(this, false);
    106                         MapView.addLayerChangeListener(this);
    107                         if (Main.map.mapView.getEditLayer() != null)
    108                                 Main.map.mapView.getEditLayer().data.addDataSetListener(this);
    109                 }
    110                 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true);
    111                 if (!MapillaryToggleDialog.getInstance().isShowing())
    112                         MapillaryToggleDialog.getInstance().getButton().doClick();
    113                 createHatchTexture();
    114                 data.dataUpdated();
    115         }
    116 
    117         private void startMouseAdapter() {
    118                 mouseAdapter = new MapillaryMouseAdapter();
    119         }
    120 
    121         public synchronized static MapillaryLayer getInstance() {
    122                 if (MapillaryLayer.INSTANCE == null)
    123                         MapillaryLayer.INSTANCE = new MapillaryLayer();
    124                 return MapillaryLayer.INSTANCE;
    125         }
    126 
    127         /**
    128          * Downloads all images of the area covered by the OSM data. This is only
    129          * just for automatic download.
    130          */
    131         public void download() {
    132                 checkBigAreas();
    133                 if (Main.pref.getBoolean("mapillary.download-manually"))
    134                         return;
    135                 for (Bounds bounds : Main.map.mapView.getEditLayer().data
    136                                 .getDataSourceBounds()) {
    137                         if (!this.bounds.contains(bounds)) {
    138                                 this.bounds.add(bounds);
    139                                 new MapillaryDownloader().getImages(bounds.getMin(),
    140                                                 bounds.getMax());
    141                         }
    142                 }
    143         }
    144 
    145         /**
    146          * Checks if the area of the OSM data is too big. This means that probably
    147          * lots of Mapillary images are going to be downloaded, slowing down the
    148          * program too much. To solve this the automatic is stopped, an alert is
    149          * shown and you will have to download areas manually.
    150          */
    151         private void checkBigAreas() {
    152                 double area = 0;
    153                 for (Bounds bounds : Main.map.mapView.getEditLayer().data
    154                                 .getDataSourceBounds()) {
    155                         area += bounds.getArea();
    156                 }
    157                 if (area > MapillaryDownloadViewAction.MAX_AREA) {
    158                         Main.pref.put("mapillary.download-manually", true);
    159                         JOptionPane
    160                                         .showMessageDialog(
    161                                                         Main.parent,
    162                                                         tr("The downloaded OSM area is too big. Download mode has been change to manual. You can change this back to automatic in preferences settings."));
    163                 }
    164         }
    165 
    166         /**
    167          * Returns the MapillaryData object, which acts as the database of the
    168          * Layer.
    169          *
    170          * @return
    171          */
    172         public MapillaryData getMapillaryData() {
    173                 return data;
    174         }
    175 
    176         /**
    177          * Method invoked when the layer is destroyed.
    178          */
    179         @Override
    180         public void destroy() {
    181                 MapillaryToggleDialog.getInstance().mapillaryImageDisplay
    182                                 .setImage(null);
    183                 MapillaryToggleDialog.getInstance().updateImage();
    184                 data.getImages().clear();
    185                 MapillaryLayer.INSTANCE = null;
    186                 MapillaryData.INSTANCE = null;
    187                 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, false);
    188                 MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, false);
    189                 Main.map.mapView.removeMouseListener(mouseAdapter);
    190                 Main.map.mapView.removeMouseMotionListener(mouseAdapter);
    191                 MapView.removeEditLayerChangeListener(this);
    192                 if (Main.map.mapView.getEditLayer() != null)
    193                         Main.map.mapView.getEditLayer().data.removeDataSetListener(this);
    194                 super.destroy();
    195         }
    196 
    197         /**
    198          * Returns true any of the images from the database has been modified.
    199          */
    200         @Override
    201         public boolean isModified() {
    202                 for (MapillaryAbstractImage image : data.getImages())
    203                         if (image.isModified())
    204                                 return true;
    205                 return false;
    206         }
    207 
    208         @Override
    209         public void setVisible(boolean visible) {
    210                 super.setVisible(visible);
    211                 for (MapillaryAbstractImage img : data.getImages())
    212                         img.setVisible(visible);
    213                 MapillaryFilterDialog.getInstance().refresh();
    214         }
    215 
    216         /**
    217          * Replies background color for downloaded areas.
    218          *
    219          * @return background color for downloaded areas. Black by default
    220          */
    221         private Color getBackgroundColor() {
    222                 return Main.pref.getColor(marktr("background"), Color.BLACK);
    223         }
    224 
    225         /**
    226          * Replies background color for non-downloaded areas.
    227          *
    228          * @return background color for non-downloaded areas. Yellow by default
    229          */
    230         private Color getOutsideColor() {
    231                 return Main.pref.getColor(marktr("outside downloaded area"),
    232                                 Color.YELLOW);
    233         }
    234 
    235         /**
    236          * Initialize the hatch pattern used to paint the non-downloaded area
    237          */
    238         private void createHatchTexture() {
    239                 BufferedImage bi = new BufferedImage(15, 15,
    240                                 BufferedImage.TYPE_INT_ARGB);
    241                 Graphics2D big = bi.createGraphics();
    242                 big.setColor(getBackgroundColor());
    243                 Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
    244                                 0.3f);
    245                 big.setComposite(comp);
    246                 big.fillRect(0, 0, 15, 15);
    247                 big.setColor(getOutsideColor());
    248                 big.drawLine(0, 15, 15, 0);
    249                 Rectangle r = new Rectangle(0, 0, 15, 15);
    250                 hatched = new TexturePaint(bi, r);
    251         }
    252 
    253         /**
    254          * Paints the database in the map.
    255          */
    256         @Override
    257         public synchronized void paint(Graphics2D g, MapView mv, Bounds box) {
    258                 if (Main.map.mapView.getActiveLayer() == this) {
    259                         Rectangle b = mv.getBounds();
    260                         // on some platforms viewport bounds seem to be offset from the
    261                         // left,
    262                         // over-grow it just to be sure
    263                         b.grow(100, 100);
    264                         Area a = new Area(b);
    265                         // now successively subtract downloaded areas
    266                         for (Bounds bounds : this.bounds) {
    267                                 Point p1 = mv.getPoint(bounds.getMin());
    268                                 Point p2 = mv.getPoint(bounds.getMax());
    269                                 Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min(
    270                                                 p1.y, p2.y), Math.abs(p2.x - p1.x), Math.abs(p2.y
    271                                                 - p1.y));
    272                                 a.subtract(new Area(r));
    273                         }
    274                         // paint remainder
    275                         g.setPaint(hatched);
    276                         g.fill(a);
    277                 }
    278 
    279                 // Draw colored lines
    280                 MapillaryLayer.BLUE = null;
    281                 MapillaryLayer.RED = null;
    282                 MapillaryToggleDialog.getInstance().blueButton.setEnabled(false);
    283                 MapillaryToggleDialog.getInstance().redButton.setEnabled(false);
    284 
    285                 // Sets blue and red lines and enables/disables the buttons
    286                 if (data.getSelectedImage() != null) {
    287                         MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences();
    288                         Point selected = mv.getPoint(data.getSelectedImage().getLatLon());
    289                         if (closestImages[0] != null) {
    290                                 MapillaryLayer.BLUE = closestImages[0];
    291                                 g.setColor(Color.BLUE);
    292                                 g.drawLine(mv.getPoint(closestImages[0].getLatLon()).x,
    293                                                 mv.getPoint(closestImages[0].getLatLon()).y,
    294                                                 selected.x, selected.y);
    295                                 MapillaryToggleDialog.getInstance().blueButton.setEnabled(true);
    296                         }
    297                         if (closestImages[1] != null) {
    298                                 MapillaryLayer.RED = closestImages[1];
    299                                 g.setColor(Color.RED);
    300                                 g.drawLine(mv.getPoint(closestImages[1].getLatLon()).x,
    301                                                 mv.getPoint(closestImages[1].getLatLon()).y,
    302                                                 selected.x, selected.y);
    303                                 MapillaryToggleDialog.getInstance().redButton.setEnabled(true);
    304                         }
    305                 }
    306                 g.setColor(Color.WHITE);
    307                 for (MapillaryAbstractImage imageAbs : data.getImages()) {
    308                         if (!imageAbs.isVisible())
    309                                 continue;
    310                         Point p = mv.getPoint(imageAbs.getLatLon());
    311                         if (imageAbs instanceof MapillaryImage) {
    312                                 MapillaryImage image = (MapillaryImage) imageAbs;
    313                                 Point nextp = null;
    314                                 // Draw sequence line
    315                                 if (image.getSequence() != null) {
    316                                         MapillaryImage tempImage = image;
    317                                         while (tempImage.next() != null) {
    318                                                 tempImage = tempImage.next();
    319                                                 if (tempImage.isVisible()) {
    320                                                         nextp = mv.getPoint(tempImage.getLatLon());
    321                                                         break;
    322                                                 }
    323                                         }
    324                                         if (nextp != null)
    325                                                 g.drawLine(p.x, p.y, nextp.x, nextp.y);
    326                                 }
    327 
    328                                 ImageIcon icon;
    329                                 if (!data.getMultiSelectedImages().contains(image))
    330                                         icon = MapillaryPlugin.MAP_ICON;
    331                                 else
    332                                         icon = MapillaryPlugin.MAP_ICON_SELECTED;
    333                                 draw(g, image, icon, p);
    334                                 if (!image.getSigns().isEmpty()) {
    335                                         g.drawImage(MapillaryPlugin.MAP_SIGN.getImage(),
    336                                                         p.x + icon.getIconWidth() / 2,
    337                                                         p.y - icon.getIconHeight() / 2, Main.map.mapView);
    338                                 }
    339                         } else if (imageAbs instanceof MapillaryImportedImage) {
    340                                 MapillaryImportedImage image = (MapillaryImportedImage) imageAbs;
    341                                 ImageIcon icon;
    342                                 if (!data.getMultiSelectedImages().contains(image))
    343                                         icon = MapillaryPlugin.MAP_ICON_IMPORTED;
    344                                 else
    345                                         icon = MapillaryPlugin.MAP_ICON_SELECTED;
    346                                 draw(g, image, icon, p);
    347                         }
    348                 }
    349         }
    350 
    351         /**
    352          * Draws the highlight of the icon.
    353          *
    354          * @param g
    355          * @param p
    356          * @param size
    357          */
    358         private void drawPointHighlight(Graphics2D g, Point p, int size) {
    359                 Color oldColor = g.getColor();
    360                 Color highlightColor = PaintColors.HIGHLIGHT.get();
    361                 Color highlightColorTransparent = new Color(highlightColor.getRed(),
    362                                 highlightColor.getGreen(), highlightColor.getBlue(), 100);
    363                 g.setColor(highlightColorTransparent);
    364                 int s = size + highlightPointRadius;
    365                 while (s >= size) {
    366                         int r = (int) Math.floor(s / 2d);
    367                         g.fillRoundRect(p.x - r, p.y - r, s, s, r, r);
    368                         s -= highlightStep;
    369                 }
    370                 g.setColor(oldColor);
    371         }
    372 
    373         /**
    374          * Draws the given icon of an image. Also checks if the mouse is over the
    375          * image.
    376          *
    377          * @param g
    378          * @param image
    379          * @param icon
    380          * @param p
    381          */
    382         private void draw(Graphics2D g, MapillaryAbstractImage image,
    383                         ImageIcon icon, Point p) {
    384                 Image imagetemp = icon.getImage();
    385                 BufferedImage bi = (BufferedImage) imagetemp;
    386                 int width = icon.getIconWidth();
    387                 int height = icon.getIconHeight();
    388 
    389                 // Rotate the image
    390                 double rotationRequired = Math.toRadians(image.getCa());
    391                 double locationX = width / 2;
    392                 double locationY = height / 2;
    393                 AffineTransform tx = AffineTransform.getRotateInstance(
    394                                 rotationRequired, locationX, locationY);
    395                 AffineTransformOp op = new AffineTransformOp(tx,
    396                                 AffineTransformOp.TYPE_BILINEAR);
    397 
    398                 g.drawImage(op.filter(bi, null), p.x - (width / 2), p.y - (height / 2),
    399                                 Main.map.mapView);
    400                 if (data.getHoveredImage() == image) {
    401                         drawPointHighlight(g, p, 16);
    402                 }
    403         }
    404 
    405         @Override
    406         public Icon getIcon() {
    407                 return MapillaryPlugin.ICON16;
    408         }
    409 
    410         @Override
    411         public boolean isMergable(Layer other) {
    412                 return false;
    413         }
    414 
    415         @Override
    416         public void mergeFrom(Layer from) {
    417                 throw new UnsupportedOperationException(
    418                                 "This layer does not support merging yet");
    419         }
    420 
    421         @Override
    422         public Action[] getMenuEntries() {
    423                 List<Action> actions = new ArrayList<>();
    424                 actions.add(LayerListDialog.getInstance().createShowHideLayerAction());
    425                 actions.add(LayerListDialog.getInstance().createDeleteLayerAction());
    426                 actions.add(new LayerListPopup.InfoAction(this));
    427                 return actions.toArray(new Action[actions.size()]);
    428         }
    429 
    430         /**
    431          * Returns the 2 closest images belonging to a different sequence.
    432          *
    433          * @return
    434          */
    435         private MapillaryImage[] getClosestImagesFromDifferentSequences() {
    436                 if (!(data.getSelectedImage() instanceof MapillaryImage))
    437                         return new MapillaryImage[2];
    438                 MapillaryImage selected = (MapillaryImage) data.getSelectedImage();
    439                 MapillaryImage[] ret = new MapillaryImage[2];
    440                 double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE,
    441                                 SEQUENCE_MAX_JUMP_DISTANCE };
    442                 LatLon selectedCoords = data.getSelectedImage().getLatLon();
    443                 for (MapillaryAbstractImage imagePrev : data.getImages()) {
    444                         if (!(imagePrev instanceof MapillaryImage))
    445                                 continue;
    446                         if (!imagePrev.isVisible())
    447                                 continue;
    448                         MapillaryImage image = (MapillaryImage) imagePrev;
    449                         if (image.getLatLon().greatCircleDistance(selectedCoords) < SEQUENCE_MAX_JUMP_DISTANCE
    450                                         && selected.getSequence() != image.getSequence()) {
    451                                 if ((ret[0] == null && ret[1] == null)
    452                                                 || (image.getLatLon().greatCircleDistance(
    453                                                                 selectedCoords) < distances[0] && (ret[1] == null || image
    454                                                                 .getSequence() != ret[1].getSequence()))) {
    455                                         ret[0] = image;
    456                                         distances[0] = image.getLatLon().greatCircleDistance(
    457                                                         selectedCoords);
    458                                 } else if ((ret[1] == null || image.getLatLon()
    459                                                 .greatCircleDistance(selectedCoords) < distances[1])
    460                                                 && image.getSequence() != ret[0].getSequence()) {
    461                                         ret[1] = image;
    462                                         distances[1] = image.getLatLon().greatCircleDistance(
    463                                                         selectedCoords);
    464                                 }
    465                         }
    466                 }
    467                 // Predownloads the thumbnails
    468                 if (ret[0] != null)
    469                         new MapillaryCache(ret[0].getKey(), MapillaryCache.Type.THUMBNAIL)
    470                                         .submit(data, false);
    471                 if (ret[1] != null)
    472                         new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL)
    473                                         .submit(data, false);
    474                 return ret;
    475         }
    476 
    477         @Override
    478         public Object getInfoComponent() {
    479                 StringBuilder sb = new StringBuilder();
    480                 sb.append(tr("Mapillary layer"));
    481                 sb.append("\n");
    482                 sb.append(tr("Total images:"));
    483                 sb.append(" ");
    484                 sb.append(data.size());
    485                 sb.append("\n");
    486                 return sb.toString();
    487         }
    488 
    489         @Override
    490         public String getToolTipText() {
    491                 return data.size() + " " + tr("images");
    492         }
    493 
    494         // EditDataLayerChanged
    495         @Override
    496         public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
    497                 if (oldLayer == null && newLayer != null) {
    498                         newLayer.data.addDataSetListener(this);
    499 
    500                 } else if (oldLayer != null && newLayer == null) {
    501                         oldLayer.data.removeDataSetListener(this);
    502                 }
    503         }
    504 
    505         /**
    506          * When more data is downloaded, a delayed update is thrown, in order to
    507          * wait for the data bounds to be set.
    508          *
    509          * @param event
    510          */
    511         @Override
    512         public void dataChanged(DataChangedEvent event) {
    513                 Main.worker.submit(new delayedDownload());
    514         }
    515 
    516         private class delayedDownload extends Thread {
    517 
    518                 @Override
    519                 public void run() {
    520                         try {
    521                                 sleep(1000);
    522                         } catch (InterruptedException e) {
    523                                 Main.error(e);
    524                         }
    525                         MapillaryLayer.getInstance().download();
    526                 }
    527         }
    528 
    529         @Override
    530         public void primitivesAdded(PrimitivesAddedEvent event) {
    531         }
    532 
    533         @Override
    534         public void primitivesRemoved(PrimitivesRemovedEvent event) {
    535         }
    536 
    537         @Override
    538         public void tagsChanged(TagsChangedEvent event) {
    539         }
    540 
    541         @Override
    542         public void nodeMoved(NodeMovedEvent event) {
    543         }
    544 
    545         @Override
    546         public void wayNodesChanged(WayNodesChangedEvent event) {
    547         }
    548 
    549         @Override
    550         public void relationMembersChanged(RelationMembersChangedEvent event) {
    551         }
    552 
    553         @Override
    554         public void otherDatasetChange(AbstractDatasetChangedEvent event) {
    555         }
    556 
    557         @Override
    558         public void visitBoundingBox(BoundingXYVisitor v) {
    559         }
    560 
    561         @Override
    562         public void activeLayerChange(Layer oldLayer, Layer newLayer) {
    563                 if (newLayer == this) {
    564                         if (data.size() > 0)
    565                                 Main.map.statusLine.setHelpText(tr("Total images: {0}",
    566                                                 data.size()));
    567                         else
    568                                 Main.map.statusLine.setHelpText(tr("No images found"));
    569                 }
    570         }
    571 
    572         @Override
    573         public void layerAdded(Layer newLayer) {
    574         }
    575 
    576         @Override
    577         public void layerRemoved(Layer oldLayer) {
    578         }
     61        DataSetListener, EditLayerChangeListener, LayerChangeListener {
     62
     63    public final static int SEQUENCE_MAX_JUMP_DISTANCE = Main.pref.getInteger(
     64            "mapillary.sequence-max-jump-distance", 100);
     65
     66    public static MapillaryLayer INSTANCE;
     67    public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
     68    public static MapillaryImage BLUE;
     69    public static MapillaryImage RED;
     70
     71    public final MapillaryData data = MapillaryData.getInstance();
     72
     73    public ArrayList<Bounds> bounds;
     74
     75    private MouseAdapter mouseAdapter;
     76
     77    private int highlightPointRadius = Main.pref.getInteger(
     78            "mappaint.highlight.radius", 7);
     79    private int highlightStep = Main.pref.getInteger("mappaint.highlight.step",
     80            4);
     81
     82    private volatile TexturePaint hatched;
     83
     84    public MapillaryLayer() {
     85        super(tr("Mapillary Images"));
     86        bounds = new ArrayList<>();
     87        init();
     88    }
     89
     90    /**
     91     * Initializes the Layer.
     92     */
     93    private void init() {
     94        MapillaryLayer.INSTANCE = this;
     95        startMouseAdapter();
     96        try {
     97            CACHE = JCSCacheManager.getCache("Mapillary");
     98        } catch (IOException e) {
     99            Main.error(e);
     100        }
     101        if (Main.map != null && Main.map.mapView != null) {
     102            Main.map.mapView.addMouseListener(mouseAdapter);
     103            Main.map.mapView.addMouseMotionListener(mouseAdapter);
     104            Main.map.mapView.addLayer(this);
     105            MapView.addEditLayerChangeListener(this, false);
     106            MapView.addLayerChangeListener(this);
     107            if (Main.map.mapView.getEditLayer() != null)
     108                Main.map.mapView.getEditLayer().data.addDataSetListener(this);
     109        }
     110        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true);
     111        if (!MapillaryToggleDialog.getInstance().isShowing())
     112            MapillaryToggleDialog.getInstance().getButton().doClick();
     113        createHatchTexture();
     114        data.dataUpdated();
     115    }
     116
     117    private void startMouseAdapter() {
     118        mouseAdapter = new MapillaryMouseAdapter();
     119    }
     120
     121    public synchronized static MapillaryLayer getInstance() {
     122        if (MapillaryLayer.INSTANCE == null)
     123            MapillaryLayer.INSTANCE = new MapillaryLayer();
     124        return MapillaryLayer.INSTANCE;
     125    }
     126
     127    /**
     128     * Downloads all images of the area covered by the OSM data. This is only
     129     * just for automatic download.
     130     */
     131    public void download() {
     132        checkBigAreas();
     133        if (Main.pref.getBoolean("mapillary.download-manually"))
     134            return;
     135        for (Bounds bounds : Main.map.mapView.getEditLayer().data
     136                .getDataSourceBounds()) {
     137            if (!this.bounds.contains(bounds)) {
     138                this.bounds.add(bounds);
     139                new MapillaryDownloader().getImages(bounds.getMin(),
     140                        bounds.getMax());
     141            }
     142        }
     143    }
     144
     145    /**
     146     * Checks if the area of the OSM data is too big. This means that probably
     147     * lots of Mapillary images are going to be downloaded, slowing down the
     148     * program too much. To solve this the automatic is stopped, an alert is
     149     * shown and you will have to download areas manually.
     150     */
     151    private void checkBigAreas() {
     152        double area = 0;
     153        for (Bounds bounds : Main.map.mapView.getEditLayer().data
     154                .getDataSourceBounds()) {
     155            area += bounds.getArea();
     156        }
     157        if (area > MapillaryDownloadViewAction.MAX_AREA) {
     158            Main.pref.put("mapillary.download-manually", true);
     159            JOptionPane
     160                    .showMessageDialog(
     161                            Main.parent,
     162                            tr("The downloaded OSM area is too big. Download mode has been change to manual. You can change this back to automatic in preferences settings."));
     163        }
     164    }
     165
     166    /**
     167     * Returns the MapillaryData object, which acts as the database of the
     168     * Layer.
     169     *
     170     * @return
     171     */
     172    public MapillaryData getMapillaryData() {
     173        return data;
     174    }
     175
     176    /**
     177     * Method invoked when the layer is destroyed.
     178     */
     179    @Override
     180    public void destroy() {
     181        MapillaryToggleDialog.getInstance().setImage(null);
     182        MapillaryToggleDialog.getInstance().updateImage();
     183        data.getImages().clear();
     184        MapillaryLayer.INSTANCE = null;
     185        MapillaryData.INSTANCE = null;
     186        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, false);
     187        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, false);
     188        Main.map.mapView.removeMouseListener(mouseAdapter);
     189        Main.map.mapView.removeMouseMotionListener(mouseAdapter);
     190        MapView.removeEditLayerChangeListener(this);
     191        if (Main.map.mapView.getEditLayer() != null)
     192            Main.map.mapView.getEditLayer().data.removeDataSetListener(this);
     193        super.destroy();
     194    }
     195
     196    /**
     197     * Returns true any of the images from the database has been modified.
     198     */
     199    @Override
     200    public boolean isModified() {
     201        for (MapillaryAbstractImage image : data.getImages())
     202            if (image.isModified())
     203                return true;
     204        return false;
     205    }
     206
     207    @Override
     208    public void setVisible(boolean visible) {
     209        super.setVisible(visible);
     210        for (MapillaryAbstractImage img : data.getImages())
     211            img.setVisible(visible);
     212        MapillaryFilterDialog.getInstance().refresh();
     213    }
     214
     215    /**
     216     * Replies background color for downloaded areas.
     217     *
     218     * @return background color for downloaded areas. Black by default
     219     */
     220    private Color getBackgroundColor() {
     221        return Main.pref.getColor(marktr("background"), Color.BLACK);
     222    }
     223
     224    /**
     225     * Replies background color for non-downloaded areas.
     226     *
     227     * @return background color for non-downloaded areas. Yellow by default
     228     */
     229    private Color getOutsideColor() {
     230        return Main.pref.getColor(marktr("outside downloaded area"),
     231                Color.YELLOW);
     232    }
     233
     234    /**
     235     * Initialize the hatch pattern used to paint the non-downloaded area
     236     */
     237    private void createHatchTexture() {
     238        BufferedImage bi = new BufferedImage(15, 15,
     239                BufferedImage.TYPE_INT_ARGB);
     240        Graphics2D big = bi.createGraphics();
     241        big.setColor(getBackgroundColor());
     242        Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
     243                0.3f);
     244        big.setComposite(comp);
     245        big.fillRect(0, 0, 15, 15);
     246        big.setColor(getOutsideColor());
     247        big.drawLine(0, 15, 15, 0);
     248        Rectangle r = new Rectangle(0, 0, 15, 15);
     249        hatched = new TexturePaint(bi, r);
     250    }
     251
     252    /**
     253     * Paints the database in the map.
     254     */
     255    @Override
     256    public synchronized void paint(Graphics2D g, MapView mv, Bounds box) {
     257        if (Main.map.mapView.getActiveLayer() == this) {
     258            Rectangle b = mv.getBounds();
     259            // on some platforms viewport bounds seem to be offset from the
     260            // left,
     261            // over-grow it just to be sure
     262            b.grow(100, 100);
     263            Area a = new Area(b);
     264            // now successively subtract downloaded areas
     265            for (Bounds bounds : this.bounds) {
     266                Point p1 = mv.getPoint(bounds.getMin());
     267                Point p2 = mv.getPoint(bounds.getMax());
     268                Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min(
     269                        p1.y, p2.y), Math.abs(p2.x - p1.x), Math.abs(p2.y
     270                        - p1.y));
     271                a.subtract(new Area(r));
     272            }
     273            // paint remainder
     274            g.setPaint(hatched);
     275            g.fill(a);
     276        }
     277
     278        // Draw colored lines
     279        MapillaryLayer.BLUE = null;
     280        MapillaryLayer.RED = null;
     281        MapillaryToggleDialog.getInstance().blueButton.setEnabled(false);
     282        MapillaryToggleDialog.getInstance().redButton.setEnabled(false);
     283
     284        // Sets blue and red lines and enables/disables the buttons
     285        if (data.getSelectedImage() != null) {
     286            MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences();
     287            Point selected = mv.getPoint(data.getSelectedImage().getLatLon());
     288            if (closestImages[0] != null) {
     289                MapillaryLayer.BLUE = closestImages[0];
     290                g.setColor(Color.BLUE);
     291                g.drawLine(mv.getPoint(closestImages[0].getLatLon()).x,
     292                        mv.getPoint(closestImages[0].getLatLon()).y,
     293                        selected.x, selected.y);
     294                MapillaryToggleDialog.getInstance().blueButton.setEnabled(true);
     295            }
     296            if (closestImages[1] != null) {
     297                MapillaryLayer.RED = closestImages[1];
     298                g.setColor(Color.RED);
     299                g.drawLine(mv.getPoint(closestImages[1].getLatLon()).x,
     300                        mv.getPoint(closestImages[1].getLatLon()).y,
     301                        selected.x, selected.y);
     302                MapillaryToggleDialog.getInstance().redButton.setEnabled(true);
     303            }
     304        }
     305        g.setColor(Color.WHITE);
     306        for (MapillaryAbstractImage imageAbs : data.getImages()) {
     307            if (!imageAbs.isVisible())
     308                continue;
     309            Point p = mv.getPoint(imageAbs.getLatLon());
     310            if (imageAbs instanceof MapillaryImage) {
     311                MapillaryImage image = (MapillaryImage) imageAbs;
     312                Point nextp = null;
     313                // Draw sequence line
     314                if (image.getSequence() != null) {
     315                    MapillaryImage tempImage = image.next();
     316                    while (tempImage != null) {
     317                        if (tempImage.isVisible()) {
     318                            nextp = mv.getPoint(tempImage.getLatLon());
     319                            break;
     320                        }
     321                        tempImage = tempImage.next();
     322                    }
     323                    if (nextp != null)
     324                        g.drawLine(p.x, p.y, nextp.x, nextp.y);
     325                }
     326
     327                ImageIcon icon;
     328                if (!data.getMultiSelectedImages().contains(image))
     329                    icon = MapillaryPlugin.MAP_ICON;
     330                else
     331                    icon = MapillaryPlugin.MAP_ICON_SELECTED;
     332                draw(g, image, icon, p);
     333                if (!image.getSigns().isEmpty()) {
     334                    g.drawImage(MapillaryPlugin.MAP_SIGN.getImage(),
     335                            p.x + icon.getIconWidth() / 2,
     336                            p.y - icon.getIconHeight() / 2, Main.map.mapView);
     337                }
     338            } else if (imageAbs instanceof MapillaryImportedImage) {
     339                MapillaryImportedImage image = (MapillaryImportedImage) imageAbs;
     340                ImageIcon icon;
     341                if (!data.getMultiSelectedImages().contains(image))
     342                    icon = MapillaryPlugin.MAP_ICON_IMPORTED;
     343                else
     344                    icon = MapillaryPlugin.MAP_ICON_SELECTED;
     345                draw(g, image, icon, p);
     346            }
     347        }
     348    }
     349
     350    /**
     351     * Draws the highlight of the icon.
     352     *
     353     * @param g
     354     * @param p
     355     * @param size
     356     */
     357    private void drawPointHighlight(Graphics2D g, Point p, int size) {
     358        Color oldColor = g.getColor();
     359        Color highlightColor = PaintColors.HIGHLIGHT.get();
     360        Color highlightColorTransparent = new Color(highlightColor.getRed(),
     361                highlightColor.getGreen(), highlightColor.getBlue(), 100);
     362        g.setColor(highlightColorTransparent);
     363        int s = size + highlightPointRadius;
     364        while (s >= size) {
     365            int r = (int) Math.floor(s / 2d);
     366            g.fillRoundRect(p.x - r, p.y - r, s, s, r, r);
     367            s -= highlightStep;
     368        }
     369        g.setColor(oldColor);
     370    }
     371
     372    /**
     373     * Draws the given icon of an image. Also checks if the mouse is over the
     374     * image.
     375     *
     376     * @param g
     377     * @param image
     378     * @param icon
     379     * @param p
     380     */
     381    private void draw(Graphics2D g, MapillaryAbstractImage image,
     382            ImageIcon icon, Point p) {
     383        Image imagetemp = icon.getImage();
     384        BufferedImage bi = (BufferedImage) imagetemp;
     385        int width = icon.getIconWidth();
     386        int height = icon.getIconHeight();
     387
     388        // Rotate the image
     389        double rotationRequired = Math.toRadians(image.getCa());
     390        double locationX = width / 2;
     391        double locationY = height / 2;
     392        AffineTransform tx = AffineTransform.getRotateInstance(
     393                rotationRequired, locationX, locationY);
     394        AffineTransformOp op = new AffineTransformOp(tx,
     395                AffineTransformOp.TYPE_BILINEAR);
     396
     397        g.drawImage(op.filter(bi, null), p.x - (width / 2), p.y - (height / 2),
     398                Main.map.mapView);
     399        if (data.getHoveredImage() == image) {
     400            drawPointHighlight(g, p, 16);
     401        }
     402    }
     403
     404    @Override
     405    public Icon getIcon() {
     406        return MapillaryPlugin.ICON16;
     407    }
     408
     409    @Override
     410    public boolean isMergable(Layer other) {
     411        return false;
     412    }
     413
     414    @Override
     415    public void mergeFrom(Layer from) {
     416        throw new UnsupportedOperationException(
     417                "This layer does not support merging yet");
     418    }
     419
     420    @Override
     421    public Action[] getMenuEntries() {
     422        List<Action> actions = new ArrayList<>();
     423        actions.add(LayerListDialog.getInstance().createShowHideLayerAction());
     424        actions.add(LayerListDialog.getInstance().createDeleteLayerAction());
     425        actions.add(new LayerListPopup.InfoAction(this));
     426        return actions.toArray(new Action[actions.size()]);
     427    }
     428
     429    /**
     430     * Returns the 2 closest images belonging to a different sequence.
     431     *
     432     * @return
     433     */
     434    private MapillaryImage[] getClosestImagesFromDifferentSequences() {
     435        if (!(data.getSelectedImage() instanceof MapillaryImage))
     436            return new MapillaryImage[2];
     437        MapillaryImage selected = (MapillaryImage) data.getSelectedImage();
     438        MapillaryImage[] ret = new MapillaryImage[2];
     439        double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE,
     440                SEQUENCE_MAX_JUMP_DISTANCE };
     441        LatLon selectedCoords = data.getSelectedImage().getLatLon();
     442        for (MapillaryAbstractImage imagePrev : data.getImages()) {
     443            if (!(imagePrev instanceof MapillaryImage))
     444                continue;
     445            if (!imagePrev.isVisible())
     446                continue;
     447            MapillaryImage image = (MapillaryImage) imagePrev;
     448            if (image.getLatLon().greatCircleDistance(selectedCoords) < SEQUENCE_MAX_JUMP_DISTANCE
     449                    && selected.getSequence() != image.getSequence()) {
     450                if ((ret[0] == null && ret[1] == null)
     451                        || (image.getLatLon().greatCircleDistance(
     452                                selectedCoords) < distances[0] && (ret[1] == null || image
     453                                .getSequence() != ret[1].getSequence()))) {
     454                    ret[0] = image;
     455                    distances[0] = image.getLatLon().greatCircleDistance(
     456                            selectedCoords);
     457                } else if ((ret[1] == null || image.getLatLon()
     458                        .greatCircleDistance(selectedCoords) < distances[1])
     459                        && image.getSequence() != ret[0].getSequence()) {
     460                    ret[1] = image;
     461                    distances[1] = image.getLatLon().greatCircleDistance(
     462                            selectedCoords);
     463                }
     464            }
     465        }
     466        // Predownloads the thumbnails
     467        if (ret[0] != null)
     468            new MapillaryCache(ret[0].getKey(), MapillaryCache.Type.THUMBNAIL)
     469                    .submit(data, false);
     470        if (ret[1] != null)
     471            new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL)
     472                    .submit(data, false);
     473        return ret;
     474    }
     475
     476    @Override
     477    public Object getInfoComponent() {
     478        StringBuilder sb = new StringBuilder();
     479        sb.append(tr("Mapillary layer"));
     480        sb.append("\n");
     481        sb.append(tr("Total images:"));
     482        sb.append(" ");
     483        sb.append(data.size());
     484        sb.append("\n");
     485        return sb.toString();
     486    }
     487
     488    @Override
     489    public String getToolTipText() {
     490        return data.size() + " " + tr("images");
     491    }
     492
     493    // EditDataLayerChanged
     494    @Override
     495    public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
     496        if (oldLayer == null && newLayer != null) {
     497            newLayer.data.addDataSetListener(this);
     498
     499        } else if (oldLayer != null && newLayer == null) {
     500            oldLayer.data.removeDataSetListener(this);
     501        }
     502    }
     503
     504    /**
     505     * When more data is downloaded, a delayed update is thrown, in order to
     506     * wait for the data bounds to be set.
     507     *
     508     * @param event
     509     */
     510    @Override
     511    public void dataChanged(DataChangedEvent event) {
     512        Main.worker.submit(new delayedDownload());
     513    }
     514
     515    private class delayedDownload extends Thread {
     516
     517        @Override
     518        public void run() {
     519            try {
     520                sleep(1000);
     521            } catch (InterruptedException e) {
     522                Main.error(e);
     523            }
     524            MapillaryLayer.getInstance().download();
     525        }
     526    }
     527
     528    @Override
     529    public void primitivesAdded(PrimitivesAddedEvent event) {
     530    }
     531
     532    @Override
     533    public void primitivesRemoved(PrimitivesRemovedEvent event) {
     534    }
     535
     536    @Override
     537    public void tagsChanged(TagsChangedEvent event) {
     538    }
     539
     540    @Override
     541    public void nodeMoved(NodeMovedEvent event) {
     542    }
     543
     544    @Override
     545    public void wayNodesChanged(WayNodesChangedEvent event) {
     546    }
     547
     548    @Override
     549    public void relationMembersChanged(RelationMembersChangedEvent event) {
     550    }
     551
     552    @Override
     553    public void otherDatasetChange(AbstractDatasetChangedEvent event) {
     554    }
     555
     556    @Override
     557    public void visitBoundingBox(BoundingXYVisitor v) {
     558    }
     559
     560    @Override
     561    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
     562        if (newLayer == this) {
     563            if (data.size() > 0)
     564                Main.map.statusLine.setHelpText(tr("Total images: {0}",
     565                        data.size()));
     566            else
     567                Main.map.statusLine.setHelpText(tr("No images found"));
     568        }
     569    }
     570
     571    @Override
     572    public void layerAdded(Layer newLayer) {
     573    }
     574
     575    @Override
     576    public void layerRemoved(Layer oldLayer) {
     577    }
    579578}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java

    r31319 r31328  
    3333public class MapillaryPlugin extends Plugin implements EditLayerChangeListener {
    3434
    35         public static final ImageIcon ICON24 = new ImageProvider("icon24.png")
    36                         .get();
    37         public static final ImageIcon ICON16 = new ImageProvider("icon16.png")
    38                         .get();
    39         public static final ImageIcon MAP_ICON = new ImageProvider("mapicon.png")
    40                         .get();
    41         public static final ImageIcon MAP_ICON_SELECTED = new ImageProvider(
    42                         "mapiconselected.png").get();
    43         public static final ImageIcon MAP_ICON_IMPORTED = new ImageProvider(
    44                         "mapiconimported.png").get();
    45         public static final ImageIcon MAP_SIGN = new ImageProvider("sign.png")
    46                         .get();
    47         public static final int ICON_SIZE = 24;
     35    public static final ImageIcon ICON24 = new ImageProvider("icon24.png")
     36            .get();
     37    public static final ImageIcon ICON16 = new ImageProvider("icon16.png")
     38            .get();
     39    public static final ImageIcon MAP_ICON = new ImageProvider("mapicon.png")
     40            .get();
     41    public static final ImageIcon MAP_ICON_SELECTED = new ImageProvider(
     42            "mapiconselected.png").get();
     43    public static final ImageIcon MAP_ICON_IMPORTED = new ImageProvider(
     44            "mapiconimported.png").get();
     45    public static final ImageIcon MAP_SIGN = new ImageProvider("sign.png")
     46            .get();
     47    public static final int ICON_SIZE = 24;
    4848
    49         public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
     49    public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
    5050
    51         private final MapillaryDownloadAction downloadAction;
    52         private final MapillaryExportAction exportAction;
    53         private final MapillaryImportAction importAction;
    54         private final MapillaryZoomAction zoomAction;
    55         private final MapillaryDownloadViewAction downloadViewAction;
     51    private final MapillaryDownloadAction downloadAction;
     52    private final MapillaryExportAction exportAction;
     53    private final MapillaryImportAction importAction;
     54    private final MapillaryZoomAction zoomAction;
     55    private final MapillaryDownloadViewAction downloadViewAction;
    5656
    57         public static JMenuItem DOWNLOAD_MENU;
    58         public static JMenuItem EXPORT_MENU;
    59         public static JMenuItem IMPORT_MENU;
    60         public static JMenuItem ZOOM_MENU;
    61         public static JMenuItem DOWNLOAD_VIEW_MENU;
     57    public static JMenuItem DOWNLOAD_MENU;
     58    public static JMenuItem EXPORT_MENU;
     59    public static JMenuItem IMPORT_MENU;
     60    public static JMenuItem ZOOM_MENU;
     61    public static JMenuItem DOWNLOAD_VIEW_MENU;
    6262
    63         public MapillaryPlugin(PluginInformation info) {
    64                 super(info);
    65                 downloadAction = new MapillaryDownloadAction();
    66                 exportAction = new MapillaryExportAction();
    67                 importAction = new MapillaryImportAction();
    68                 zoomAction = new MapillaryZoomAction();
    69                 downloadViewAction = new MapillaryDownloadViewAction();
     63    public MapillaryPlugin(PluginInformation info) {
     64        super(info);
     65        downloadAction = new MapillaryDownloadAction();
     66        exportAction = new MapillaryExportAction();
     67        importAction = new MapillaryImportAction();
     68        zoomAction = new MapillaryZoomAction();
     69        downloadViewAction = new MapillaryDownloadViewAction();
    7070
    71                 DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu,
    72                                 downloadAction, false);
    73                 EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction,
    74                                 false, 14);
    75                 IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction,
    76                                 false, 14);
    77                 ZOOM_MENU = MainMenu
    78                                 .add(Main.main.menu.viewMenu, zoomAction, false, 15);
    79                 DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu,
    80                                 downloadViewAction, false, 14);
     71        DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu,
     72                downloadAction, false);
     73        EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction,
     74                false, 14);
     75        IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction,
     76                false, 14);
     77        ZOOM_MENU = MainMenu
     78                .add(Main.main.menu.viewMenu, zoomAction, false, 15);
     79        DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu,
     80                downloadViewAction, false, 14);
    8181
    82                 EXPORT_MENU.setEnabled(false);
    83                 DOWNLOAD_MENU.setEnabled(false);
    84                 IMPORT_MENU.setEnabled(false);
    85                 ZOOM_MENU.setEnabled(false);
    86                 DOWNLOAD_VIEW_MENU.setEnabled(false);
     82        EXPORT_MENU.setEnabled(false);
     83        DOWNLOAD_MENU.setEnabled(false);
     84        IMPORT_MENU.setEnabled(false);
     85        ZOOM_MENU.setEnabled(false);
     86        DOWNLOAD_VIEW_MENU.setEnabled(false);
    8787
    88                 MapView.addEditLayerChangeListener(this);
    89                 try {
    90                         CACHE = JCSCacheManager.getCache("mapillary", 10, 10000,
    91                                         this.getPluginDir() + "/cache/");
    92                 } catch (IOException e) {
    93                         Main.error(e);
    94                 }
    95         }
     88        MapView.addEditLayerChangeListener(this);
     89        try {
     90            CACHE = JCSCacheManager.getCache("mapillary", 10, 10000,
     91                    this.getPluginDir() + "/cache/");
     92        } catch (IOException e) {
     93            Main.error(e);
     94        }
     95    }
    9696
    97         /**
    98         * Called when the JOSM map frame is created or destroyed.
    99         */
    100         @Override
    101         public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
    102                 if (oldFrame == null && newFrame != null) { // map frame added
    103                         Main.map.addToggleDialog(MapillaryToggleDialog.getInstance(), false);
    104                         Main.map.addToggleDialog(MapillaryHistoryDialog.getInstance(),
    105                                         false);
    106                         Main.map.addToggleDialog(MapillaryFilterDialog.getInstance(), false);
    107                         setMenuEnabled(DOWNLOAD_MENU, true);
    108                         if (Main.pref.getBoolean("mapillary.download-manually"))
    109                                 setMenuEnabled(DOWNLOAD_VIEW_MENU, true);
    110                         setMenuEnabled(IMPORT_MENU, true);
    111                 }
    112                 if (oldFrame != null && newFrame == null) { // map frame destroyed
    113                         MapillaryToggleDialog.destroyInstance();
    114                         MapillaryHistoryDialog.destroyInstance();
    115                         MapillaryFilterDialog.destroyInstance();
    116                         setMenuEnabled(DOWNLOAD_MENU, false);
    117                         setMenuEnabled(DOWNLOAD_VIEW_MENU, false);
    118                         setMenuEnabled(IMPORT_MENU, false);
    119                 }
    120         }
     97    /**
     98    * Called when the JOSM map frame is created or destroyed.
     99    */
     100    @Override
     101    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
     102        if (oldFrame == null && newFrame != null) { // map frame added
     103            Main.map.addToggleDialog(MapillaryToggleDialog.getInstance(), false);
     104            Main.map.addToggleDialog(MapillaryHistoryDialog.getInstance(),
     105                    false);
     106            Main.map.addToggleDialog(MapillaryFilterDialog.getInstance(), false);
     107            setMenuEnabled(DOWNLOAD_MENU, true);
     108            if (Main.pref.getBoolean("mapillary.download-manually"))
     109                setMenuEnabled(DOWNLOAD_VIEW_MENU, true);
     110            setMenuEnabled(IMPORT_MENU, true);
     111        }
     112        if (oldFrame != null && newFrame == null) { // map frame destroyed
     113            MapillaryToggleDialog.destroyInstance();
     114            MapillaryHistoryDialog.destroyInstance();
     115            MapillaryFilterDialog.destroyInstance();
     116            setMenuEnabled(DOWNLOAD_MENU, false);
     117            setMenuEnabled(DOWNLOAD_VIEW_MENU, false);
     118            setMenuEnabled(IMPORT_MENU, false);
     119        }
     120    }
    121121
    122         public static void setMenuEnabled(JMenuItem menu, boolean value) {
    123                 menu.setEnabled(value);
    124                 menu.getAction().setEnabled(value);
    125         }
     122    public static void setMenuEnabled(JMenuItem menu, boolean value) {
     123        menu.setEnabled(value);
     124        menu.getAction().setEnabled(value);
     125    }
    126126
    127         @Override
    128         public PreferenceSetting getPreferenceSetting() {
    129                 return new MapillaryPreferenceSetting();
    130         }
     127    @Override
     128    public PreferenceSetting getPreferenceSetting() {
     129        return new MapillaryPreferenceSetting();
     130    }
    131131
    132         @Override
    133         public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
    134                 if (oldLayer == null && newLayer != null) {
    135                 } else if (oldLayer != null && newLayer == null) {
    136                 }
    137         }
     132    @Override
     133    public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
     134        if (oldLayer == null && newLayer != null) {
     135        } else if (oldLayer != null && newLayer == null) {
     136        }
     137    }
    138138}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java

    r31319 r31328  
    2323public class MapillaryDownloadAction extends JosmAction {
    2424
    25         public MapillaryDownloadAction() {
    26                 super(tr("Mapillary"), new ImageProvider("icon24.png"),
    27                                 tr("Create Mapillary layer"), Shortcut.registerShortcut(
    28                                                 "Mapillary", tr("Start Mapillary layer"),
    29                                                 KeyEvent.VK_COMMA, Shortcut.SHIFT), false,
    30                                 "mapillaryDownload", false);
    31                 this.setEnabled(false);
    32         }
     25    public MapillaryDownloadAction() {
     26        super(tr("Mapillary"), new ImageProvider("icon24.png"),
     27                tr("Create Mapillary layer"), Shortcut.registerShortcut(
     28                        "Mapillary", tr("Start Mapillary layer"),
     29                        KeyEvent.VK_COMMA, Shortcut.SHIFT), false,
     30                "mapillaryDownload", false);
     31        this.setEnabled(false);
     32    }
    3333
    34         @Override
    35         public void actionPerformed(ActionEvent arg0) {
    36                 if (MapillaryLayer.INSTANCE == null) {
    37                         if (Main.map.mapView.getEditLayer() != null)
    38                                 MapillaryLayer.getInstance().download();
    39                 } else {
    40                         if (Main.map.mapView.getActiveLayer() != MapillaryLayer
    41                                         .getInstance())
    42                                 Main.map.mapView.setActiveLayer(MapillaryLayer.getInstance());
    43                         else
    44                                 Main.map.mapView
    45                                                 .setActiveLayer(Main.map.mapView.getEditLayer());
    46                 }
    47         }
     34    @Override
     35    public void actionPerformed(ActionEvent arg0) {
     36        if (MapillaryLayer.INSTANCE == null) {
     37            if (Main.map.mapView.getEditLayer() != null)
     38                MapillaryLayer.getInstance().download();
     39        } else {
     40            if (Main.map.mapView.getActiveLayer() != MapillaryLayer
     41                    .getInstance())
     42                Main.map.mapView.setActiveLayer(MapillaryLayer.getInstance());
     43            else
     44                Main.map.mapView
     45                        .setActiveLayer(Main.map.mapView.getEditLayer());
     46        }
     47    }
    4848}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryImportAction.java

    r31319 r31328  
    7070
    7171                } else {
    72                         MapillaryLayer.getInstance();
     72                    MapillaryLayer.getInstance();
    7373                    if (file.getPath().substring(file.getPath().length() - 4)
    7474                            .equals(".jpg")
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/cache/MapillaryCache.java

    r31306 r31328  
    1111
    1212public class MapillaryCache extends
    13                 JCSCachedTileLoaderJob<String, BufferedImageCacheEntry> {
     13        JCSCachedTileLoaderJob<String, BufferedImageCacheEntry> {
    1414
    15         private volatile URL url;
    16         private volatile String key;
     15    private volatile URL url;
     16    private volatile String key;
    1717
    18         public static enum Type {
    19                 FULL_IMAGE, THUMBNAIL
    20         }
     18    public static enum Type {
     19        FULL_IMAGE, THUMBNAIL
     20    }
    2121
    22         public MapillaryCache(String key, Type type) {
    23                 super(MapillaryPlugin.CACHE, 50000, 50000,
    24                                 new HashMap<String, String>());
    25                 this.key = key;
    26                 try {
    27                         if (type == Type.FULL_IMAGE) {
    28                                 url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key
    29                                                 + "/thumb-2048.jpg");
    30                                 this.key += ".FULL_IMAGE";
     22    public MapillaryCache(String key, Type type) {
     23        super(MapillaryPlugin.CACHE, 50000, 50000,
     24                new HashMap<String, String>());
     25        this.key = key;
     26        try {
     27            if (type == Type.FULL_IMAGE) {
     28                url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key
     29                        + "/thumb-2048.jpg");
     30                this.key += ".FULL_IMAGE";
    3131
    32                         } else if (type == Type.THUMBNAIL) {
    33                                 url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key
    34                                                 + "/thumb-320.jpg");
    35                                 this.key += ".THUMBNAIL";
    36                         }
    37                 } catch (MalformedURLException e) {
    38                         Main.error(e);
    39                 }
    40         }
     32            } else if (type == Type.THUMBNAIL) {
     33                url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key
     34                        + "/thumb-320.jpg");
     35                this.key += ".THUMBNAIL";
     36            }
     37        } catch (MalformedURLException e) {
     38            Main.error(e);
     39        }
     40    }
    4141
    42         @Override
    43         public String getCacheKey() {
    44                 return key;
    45         }
     42    @Override
     43    public String getCacheKey() {
     44        return key;
     45    }
    4646
    47         @Override
    48         public URL getUrl() {
    49                 return url;
    50         }
     47    @Override
     48    public URL getUrl() {
     49        return url;
     50    }
    5151
    52         @Override
    53         protected BufferedImageCacheEntry createCacheEntry(byte[] content) {
    54                 return new BufferedImageCacheEntry(content);
    55         }
     52    @Override
     53    protected BufferedImageCacheEntry createCacheEntry(byte[] content) {
     54        return new BufferedImageCacheEntry(content);
     55    }
    5656
    57         @Override
    58         protected boolean isObjectLoadable() {
    59                 if (cacheData == null)
    60                         return false;
    61                 byte[] content = cacheData.getContent();
    62                 return content != null && content.length > 0;
    63         }
     57    @Override
     58    protected boolean isObjectLoadable() {
     59        if (cacheData == null)
     60            return false;
     61        byte[] content = cacheData.getContent();
     62        return content != null && content.length > 0;
     63    }
    6464
    65         // @Override
    66         protected boolean handleNotFound() {
    67                 return false;
    68         }
     65    // @Override
     66    protected boolean handleNotFound() {
     67        return false;
     68    }
    6969}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryDownloader.java

    r31322 r31328  
    1818public class MapillaryDownloader {
    1919
    20         public final static String BASE_URL = "https://a.mapillary.com/v2/";
    21         public final static String CLIENT_ID = "NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1YTA2NmNlODhlNWMwOTBm";
    22         public final static Executor EXECUTOR = Executors.newSingleThreadExecutor();
     20    public final static String BASE_URL = "https://a.mapillary.com/v2/";
     21    public final static String CLIENT_ID = "NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1YTA2NmNlODhlNWMwOTBm";
     22    public final static Executor EXECUTOR = Executors.newSingleThreadExecutor();
    2323
    24         private String[] parameters = { "lat", "lon", "distance", "limit",
    25                         "min_lat", "min_lon", "max_lat", "max_lon" };
     24    private String[] parameters = { "lat", "lon", "distance", "limit",
     25            "min_lat", "min_lon", "max_lat", "max_lon" };
    2626
    27         public MapillaryDownloader() {
    28         }
     27    public MapillaryDownloader() {
     28    }
    2929
    30         /**
    31         * Gets all the images in a square. It downloads all the images of all the
    32         * sequences that pass through the given rectangle.
    33         *
    34         * @param minLatLon
    35         *            The minimum latitude and longitude of the rectangle.
    36         * @param maxLatLon
    37         *            The maximum latitude and longitude of the rectangle
    38         */
    39         public void getImages(LatLon minLatLon, LatLon maxLatLon) {
    40                 String url1 = BASE_URL;
    41                 String url2 = BASE_URL;
    42                 String url3 = BASE_URL;
    43                 url1 += "search/im/";
    44                 url2 += "search/s/";
    45                 url3 += "search/im/or";
    46                 ConcurrentHashMap<String, Double> hash = new ConcurrentHashMap<>();
    47                 hash.put("min_lat", minLatLon.lat());
    48                 hash.put("min_lon", minLatLon.lon());
    49                 hash.put("max_lat", maxLatLon.lat());
    50                 hash.put("max_lon", maxLatLon.lon());
    51                 url1 += buildParameters(hash);
    52                 url2 += buildParameters(hash);
    53                 url3 += buildParameters(hash);
     30    /**
     31    * Gets all the images in a square. It downloads all the images of all the
     32    * sequences that pass through the given rectangle.
     33    *
     34    * @param minLatLon
     35    *            The minimum latitude and longitude of the rectangle.
     36    * @param maxLatLon
     37    *            The maximum latitude and longitude of the rectangle
     38    */
     39    public void getImages(LatLon minLatLon, LatLon maxLatLon) {
     40        String url1 = BASE_URL;
     41        String url2 = BASE_URL;
     42        String url3 = BASE_URL;
     43        url1 += "search/im/";
     44        url2 += "search/s/";
     45        url3 += "search/im/or";
     46        ConcurrentHashMap<String, Double> hash = new ConcurrentHashMap<>();
     47        hash.put("min_lat", minLatLon.lat());
     48        hash.put("min_lon", minLatLon.lon());
     49        hash.put("max_lat", maxLatLon.lat());
     50        hash.put("max_lon", maxLatLon.lon());
     51        url1 += buildParameters(hash);
     52        url2 += buildParameters(hash);
     53        url3 += buildParameters(hash);
    5454
    55                 try {
    56                         Main.info("GET " + url2 + " (Mapillary plugin)");
    57                         EXECUTOR.execute(new MapillarySquareDownloadManagerThread(url1, url2,
    58                                         url3, MapillaryLayer.getInstance()));
    59                 } catch (Exception e) {
    60                         Main.error(e);
    61                 }
    62         }
     55        try {
     56            Main.info("GET " + url2 + " (Mapillary plugin)");
     57            EXECUTOR.execute(new MapillarySquareDownloadManagerThread(url1,
     58                    url2, url3, MapillaryLayer.getInstance()));
     59        } catch (Exception e) {
     60            Main.error(e);
     61        }
     62    }
    6363
    64         public void getImages(Bounds bounds) {
    65                 getImages(bounds.getMin(), bounds.getMax());
    66         }
     64    public void getImages(Bounds bounds) {
     65        getImages(bounds.getMin(), bounds.getMax());
     66    }
    6767
    68         private String buildParameters(ConcurrentHashMap<String, Double> hash) {
    69                 String ret = "?client_id=" + CLIENT_ID;
    70                 for (int i = 0; i < parameters.length; i++)
    71                         if (hash.get(parameters[i]) != null)
    72                                 ret += "&" + parameters[i] + "=" + hash.get(parameters[i]);
    73                 return ret;
    74         }
     68    private String buildParameters(ConcurrentHashMap<String, Double> hash) {
     69        String ret = "?client_id=" + CLIENT_ID;
     70        for (int i = 0; i < parameters.length; i++)
     71            if (hash.get(parameters[i]) != null)
     72                ret += "&" + parameters[i] + "=" + hash.get(parameters[i]);
     73        return ret;
     74    }
    7575}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportWriterThread.java

    r31284 r31328  
    8787                    exifDirectory.add(
    8888                            ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
    89                             ((MapillaryImportedImage) mimg).getDate("yyyy/MM/dd hh:mm:ss"));
     89                            ((MapillaryImportedImage) mimg)
     90                                    .getDate("yyyy/MM/dd hh:mm:ss"));
    9091                } else if (mimg instanceof MapillaryImage)
    9192                    exifDirectory.add(
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryImageInfoDownloaderThread.java

    r31319 r31328  
    2525 */
    2626public class MapillaryImageInfoDownloaderThread implements Runnable {
    27         private final String url;
    28         private final ExecutorService ex;
    29         private final MapillaryLayer layer;
     27    private final String url;
     28    private final ExecutorService ex;
     29    private final MapillaryLayer layer;
    3030
    31         public MapillaryImageInfoDownloaderThread(ExecutorService ex, String url,
    32                         MapillaryLayer layer) {
    33                 this.ex = ex;
    34                 this.url = url;
    35                 this.layer = layer;
    36         }
     31    public MapillaryImageInfoDownloaderThread(ExecutorService ex, String url,
     32            MapillaryLayer layer) {
     33        this.ex = ex;
     34        this.url = url;
     35        this.layer = layer;
     36    }
    3737
    38         public void run() {
    39                 try {
    40                         BufferedReader br = new BufferedReader(new InputStreamReader(
    41                                         new URL(url).openStream()));
    42                         JsonObject jsonobj = Json.createReader(br).readObject();
    43                         if (!jsonobj.getBoolean("more"))
    44                                 ex.shutdown();
    45                         JsonArray jsonarr = jsonobj.getJsonArray("ims");
    46                         JsonObject data;
    47                         for (int i = 0; i < jsonarr.size(); i++) {
    48                                 data = jsonarr.getJsonObject(i);
    49                                 String key = data.getString("key");
    50                                 for (MapillaryAbstractImage image : layer.data.getImages()) {
    51                                         if (image instanceof MapillaryImage) {
    52                                                 if (((MapillaryImage) image).getKey().equals(key)
    53                                                                 && ((MapillaryImage) image).getUser() == null) {
    54                                                         ((MapillaryImage) image).setUser(data
    55                                                                         .getString("user"));
    56                                                         ((MapillaryImage) image).setCapturedAt(data
    57                                                                         .getJsonNumber("captured_at").longValue());
    58                                                 }
    59                                         }
    60                                 }
    61                         }
    62                 } catch (MalformedURLException e) {
    63                         Main.error(e);
    64                 } catch (IOException e) {
    65                         Main.error(e);
    66                 }
    67         }
     38    public void run() {
     39        try {
     40            BufferedReader br = new BufferedReader(new InputStreamReader(
     41                    new URL(url).openStream()));
     42            JsonObject jsonobj = Json.createReader(br).readObject();
     43            if (!jsonobj.getBoolean("more"))
     44                ex.shutdown();
     45            JsonArray jsonarr = jsonobj.getJsonArray("ims");
     46            JsonObject data;
     47            for (int i = 0; i < jsonarr.size(); i++) {
     48                data = jsonarr.getJsonObject(i);
     49                String key = data.getString("key");
     50                for (MapillaryAbstractImage image : layer.data.getImages()) {
     51                    if (image instanceof MapillaryImage) {
     52                        if (((MapillaryImage) image).getKey().equals(key)
     53                                && ((MapillaryImage) image).getUser() == null) {
     54                            ((MapillaryImage) image).setUser(data
     55                                    .getString("user"));
     56                            ((MapillaryImage) image).setCapturedAt(data
     57                                    .getJsonNumber("captured_at").longValue());
     58                        }
     59                    }
     60                }
     61            }
     62        } catch (MalformedURLException e) {
     63            Main.error(e);
     64        } catch (IOException e) {
     65            Main.error(e);
     66        }
     67    }
    6868}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySequenceDownloadThread.java

    r31326 r31328  
    9090
    9191                boolean imagesAdded = false;
     92                MapillaryImage.lock.lock();
    9293                for (MapillaryImage img : finalImages) {
    9394                    if (layer.data.getImages().contains(img)) {
     95                        sequence.add(img);
    9496                        ((MapillaryImage) layer.data.getImages().get(
    9597                                layer.data.getImages().indexOf(img)))
     
    99101                                (MapillaryImage) layer.data.getImages().get(
    100102                                        layer.data.getImages().indexOf(img)));
    101                         sequence.add(img);
    102103                    } else {
    103104                        img.setSequence(sequence);
     
    106107                    }
    107108                }
     109                MapillaryImage.lock.unlock();
    108110                manager.imagesAdded = imagesAdded;
    109111                layer.data
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySignDownloaderThread.java

    r31319 r31328  
    1919public class MapillarySignDownloaderThread implements Runnable {
    2020
    21         private final String url;
    22         private final ExecutorService ex;
    23         private final MapillaryLayer layer;
     21    private final String url;
     22    private final ExecutorService ex;
     23    private final MapillaryLayer layer;
    2424
    25         public MapillarySignDownloaderThread(ExecutorService ex, String url,
    26                         MapillaryLayer layer) {
    27                 this.ex = ex;
    28                 this.url = url;
    29                 this.layer = layer;
    30         }
     25    public MapillarySignDownloaderThread(ExecutorService ex, String url,
     26            MapillaryLayer layer) {
     27        this.ex = ex;
     28        this.url = url;
     29        this.layer = layer;
     30    }
    3131
    32         @Override
    33         public void run() {
    34                 BufferedReader br;
    35                 try {
    36                         br = new BufferedReader(new InputStreamReader(
    37                                         new URL(url).openStream()));
    38                         JsonObject jsonobj = Json.createReader(br).readObject();
    39                         if (!jsonobj.getBoolean("more")) {
    40                                 ex.shutdown();
    41                         }
    42                         JsonArray jsonarr = jsonobj.getJsonArray("ims");
    43                         for (int i = 0; i < jsonarr.size(); i++) {
    44                                 JsonArray rects = jsonarr.getJsonObject(i)
    45                                                 .getJsonArray("rects");
    46                                 JsonArray rectversions = jsonarr.getJsonObject(i).getJsonArray(
    47                                                 "rectversions");
    48                                 String key = jsonarr.getJsonObject(i).getString("key");
    49                                 if (rectversions != null) {
    50                                         for (int j = 0; j < rectversions.size(); j++) {
    51                                                 rects = rectversions.getJsonObject(j).getJsonArray(
    52                                                                 "rects");
    53                                                 for (int k = 0; k < rects.size(); k++) {
    54                                                         JsonObject data = rects.getJsonObject(k);
    55                                                         for (MapillaryAbstractImage image : layer.data
    56                                                                         .getImages())
    57                                                                 if (image instanceof MapillaryImage
    58                                                                                 && ((MapillaryImage) image).getKey()
    59                                                                                                 .equals(key))
    60                                                                         ((MapillaryImage) image).addSign(data
    61                                                                                         .getString("type"));
    62                                                 }
    63                                         }
    64                                 }
     32    @Override
     33    public void run() {
     34        BufferedReader br;
     35        try {
     36            br = new BufferedReader(new InputStreamReader(
     37                    new URL(url).openStream()));
     38            JsonObject jsonobj = Json.createReader(br).readObject();
     39            if (!jsonobj.getBoolean("more")) {
     40                ex.shutdown();
     41            }
     42            JsonArray jsonarr = jsonobj.getJsonArray("ims");
     43            for (int i = 0; i < jsonarr.size(); i++) {
     44                JsonArray rects = jsonarr.getJsonObject(i)
     45                        .getJsonArray("rects");
     46                JsonArray rectversions = jsonarr.getJsonObject(i).getJsonArray(
     47                        "rectversions");
     48                String key = jsonarr.getJsonObject(i).getString("key");
     49                if (rectversions != null) {
     50                    for (int j = 0; j < rectversions.size(); j++) {
     51                        rects = rectversions.getJsonObject(j).getJsonArray(
     52                                "rects");
     53                        for (int k = 0; k < rects.size(); k++) {
     54                            JsonObject data = rects.getJsonObject(k);
     55                            for (MapillaryAbstractImage image : layer.data
     56                                    .getImages())
     57                                if (image instanceof MapillaryImage
     58                                        && ((MapillaryImage) image).getKey()
     59                                                .equals(key))
     60                                    ((MapillaryImage) image).addSign(data
     61                                            .getString("type"));
     62                        }
     63                    }
     64                }
    6565
    66                                 // Just one sign on the picture
    67                                 else if (rects != null) {
    68                                         for (int j = 0; j < rects.size(); j++) {
    69                                                 JsonObject data = rects.getJsonObject(j);
    70                                                 for (MapillaryAbstractImage image : layer.data.getImages())
    71                                                         if (image instanceof MapillaryImage
    72                                                                         && ((MapillaryImage) image).getKey()
    73                                                                                         .equals(key))
    74                                                                 ((MapillaryImage) image).addSign(data
    75                                                                                 .getString("type"));
    76                                         }
    77                                 }
    78                         }
    79                 } catch (MalformedURLException e) {
    80                         Main.error(e);
    81                 } catch (IOException e) {
    82                         Main.error(e);
    83                 }
    84         }
     66                // Just one sign on the picture
     67                else if (rects != null) {
     68                    for (int j = 0; j < rects.size(); j++) {
     69                        JsonObject data = rects.getJsonObject(j);
     70                        for (MapillaryAbstractImage image : layer.data
     71                                .getImages())
     72                            if (image instanceof MapillaryImage
     73                                    && ((MapillaryImage) image).getKey()
     74                                            .equals(key))
     75                                ((MapillaryImage) image).addSign(data
     76                                        .getString("type"));
     77                    }
     78                }
     79            }
     80        } catch (MalformedURLException e) {
     81            Main.error(e);
     82        } catch (IOException e) {
     83            Main.error(e);
     84        }
     85    }
    8586}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySquareDownloadManagerThread.java

    r31324 r31328  
    1414/**
    1515 * This Class is needed to create an indeterminate amount of downloads, because
    16  * the Mapillary API has a paramameter called page which is needed when the amount of
    17  * requested images is quite big.
     16 * the Mapillary API has a parameter called page which is needed when the
     17 * amount of requested images is quite big.
    1818 *
    1919 * @author nokutu
     
    2323public class MapillarySquareDownloadManagerThread implements Runnable {
    2424
    25         private final String urlImages;
    26         private final String urlSequences;
    27         private final String urlSigns;
    28         private final MapillaryLayer layer;
    29         public boolean imagesAdded = false;
    30        
    31         public MapillarySquareDownloadManagerThread(String urlImages,
    32                         String urlSequences, String urlSigns, MapillaryLayer layer) {
    33                 this.urlImages = urlImages;
    34                 this.urlSequences = urlSequences;
    35                 this.urlSigns = urlSigns;
    36                 this.layer = layer;
    37         }
     25    private final String urlImages;
     26    private final String urlSequences;
     27    private final String urlSigns;
     28    private final MapillaryLayer layer;
     29    public boolean imagesAdded = false;
    3830
    39         public void run() {
    40                 Main.map.statusLine.setHelpText("Downloading images from Mapillary");
    41                 try {
    42                         downloadSequences();
    43                         if (imagesAdded) {
    44                                 Main.map.statusLine
    45                                                 .setHelpText("Downloading image's information");
    46                                 completeImages();
    47                                 MapillaryToggleDialog.getInstance().updateTitle();
    48                                 Main.map.statusLine.setHelpText("Downloading signs");
    49                                 downloadSigns();
    50                         }
    51                 } catch (InterruptedException e) {
    52                         Main.error(e);
    53                 }
    54                 if (layer.data.getImages().size() > 0)
    55                         Main.map.statusLine.setHelpText(tr("Total images: ")
    56                                         + layer.data.getImages().size());
    57                 else
    58                         Main.map.statusLine.setHelpText(tr("No images found"));
    59                 layer.data.dataUpdated();
    60                 MapillaryFilterDialog.getInstance().refresh();
    61                 MapillaryToggleDialog.getInstance().updateImage();
    62         }
     31    public MapillarySquareDownloadManagerThread(String urlImages,
     32            String urlSequences, String urlSigns, MapillaryLayer layer) {
     33        this.urlImages = urlImages;
     34        this.urlSequences = urlSequences;
     35        this.urlSigns = urlSigns;
     36        this.layer = layer;
     37    }
    6338
    64         private void downloadSequences() throws InterruptedException {
    65                 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
    66                                 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
    67                 int page = 0;
    68                 while (!ex.isShutdown()) {
    69                         ex.execute(new MapillarySequenceDownloadThread(ex, urlSequences
    70                                         + "&page=" + page + "&limit=1", layer, this));
    71                         while (ex.getQueue().remainingCapacity() == 0)
    72                                 Thread.sleep(100);
    73                         page++;
    74                 }
    75                 ex.awaitTermination(15, TimeUnit.SECONDS);
    76                 layer.data.dataUpdated();
    77         }
     39    public void run() {
     40        Main.map.statusLine.setHelpText("Downloading images from Mapillary");
     41        try {
     42            downloadSequences();
     43            if (imagesAdded) {
     44                Main.map.statusLine
     45                        .setHelpText("Downloading image's information");
     46                completeImages();
     47                MapillaryToggleDialog.getInstance().updateTitle();
     48                Main.map.statusLine.setHelpText("Downloading signs");
     49                downloadSigns();
     50            }
     51        } catch (InterruptedException e) {
     52            Main.error(e);
     53        }
     54        if (layer.data.getImages().size() > 0)
     55            Main.map.statusLine.setHelpText(tr("Total images: ")
     56                    + layer.data.getImages().size());
     57        else
     58            Main.map.statusLine.setHelpText(tr("No images found"));
     59        layer.data.dataUpdated();
     60        MapillaryFilterDialog.getInstance().refresh();
     61        MapillaryToggleDialog.getInstance().updateImage();
     62    }
    7863
    79         private void completeImages() throws InterruptedException {
    80                 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
    81                                 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
    82                 int page = 0;
    83                 while (!ex.isShutdown()) {
    84                         ex.execute(new MapillaryImageInfoDownloaderThread(ex, urlImages
    85                                         + "&page=" + page + "&limit=20", layer));
    86                         while (ex.getQueue().remainingCapacity() == 0)
    87                                 Thread.sleep(100);
    88                         page++;
    89                 }
    90                 ex.awaitTermination(15, TimeUnit.SECONDS);
    91         }
     64    private void downloadSequences() throws InterruptedException {
     65        ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
     66                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
     67        int page = 0;
     68        while (!ex.isShutdown()) {
     69            ex.execute(new MapillarySequenceDownloadThread(ex, urlSequences
     70                    + "&page=" + page + "&limit=1", layer, this));
     71            while (ex.getQueue().remainingCapacity() == 0)
     72                Thread.sleep(100);
     73            page++;
     74        }
     75        ex.awaitTermination(15, TimeUnit.SECONDS);
     76        layer.data.dataUpdated();
     77    }
    9278
    93         private void downloadSigns() throws InterruptedException {
    94                 ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
    95                                 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
    96                 int page = 0;
    97                 while (!ex.isShutdown()) {
    98                         ex.execute(new MapillarySignDownloaderThread(ex, urlSigns
    99                                         + "&page=" + page + "&limit=20", layer));
    100                         while (ex.getQueue().remainingCapacity() == 0)
    101                                 Thread.sleep(100);
    102                         page++;
    103                 }
    104                 ex.awaitTermination(15, TimeUnit.SECONDS);
    105         }
     79    private void completeImages() throws InterruptedException {
     80        ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
     81                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
     82        int page = 0;
     83        while (!ex.isShutdown()) {
     84            ex.execute(new MapillaryImageInfoDownloaderThread(ex, urlImages
     85                    + "&page=" + page + "&limit=20", layer));
     86            while (ex.getQueue().remainingCapacity() == 0)
     87                Thread.sleep(100);
     88            page++;
     89        }
     90        ex.awaitTermination(15, TimeUnit.SECONDS);
     91    }
     92
     93    private void downloadSigns() throws InterruptedException {
     94        ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
     95                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
     96        int page = 0;
     97        while (!ex.isShutdown()) {
     98            ex.execute(new MapillarySignDownloaderThread(ex, urlSigns
     99                    + "&page=" + page + "&limit=20", layer));
     100            while (ex.getQueue().remainingCapacity() == 0)
     101                Thread.sleep(100);
     102            page++;
     103        }
     104        ex.awaitTermination(15, TimeUnit.SECONDS);
     105    }
    106106}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterChooseSigns.java

    r31315 r31328  
    1414
    1515public class MapillaryFilterChooseSigns extends JPanel implements
    16                 ActionListener {
     16        ActionListener {
    1717
    18         public final JCheckBox maxspeed = new JCheckBox();
    19         public final JCheckBox stop = new JCheckBox();
    20         public final JCheckBox giveWay = new JCheckBox();
    21         public final JCheckBox roundabout = new JCheckBox();
    22         public final JCheckBox access = new JCheckBox();
    23         public final JCheckBox intersection = new JCheckBox();
    24         public final JCheckBox direction = new JCheckBox();
    25         public final JCheckBox uneven = new JCheckBox();
    26         public final JCheckBox noParking = new JCheckBox();
    27         public final JCheckBox noOvertaking = new JCheckBox();
    28         public final JCheckBox crossing = new JCheckBox();
    29         public final JCheckBox noTurn = new JCheckBox();
     18    public final JCheckBox maxspeed = new JCheckBox();
     19    public final JCheckBox stop = new JCheckBox();
     20    public final JCheckBox giveWay = new JCheckBox();
     21    public final JCheckBox roundabout = new JCheckBox();
     22    public final JCheckBox access = new JCheckBox();
     23    public final JCheckBox intersection = new JCheckBox();
     24    public final JCheckBox direction = new JCheckBox();
     25    public final JCheckBox uneven = new JCheckBox();
     26    public final JCheckBox noParking = new JCheckBox();
     27    public final JCheckBox noOvertaking = new JCheckBox();
     28    public final JCheckBox crossing = new JCheckBox();
     29    public final JCheckBox noTurn = new JCheckBox();
    3030
    31         private static MapillaryFilterChooseSigns INSTANCE;
     31    private static MapillaryFilterChooseSigns INSTANCE;
    3232
    33         public MapillaryFilterChooseSigns() {
    34                 maxspeed.setSelected(true);
    35                 stop.setSelected(true);
    36                 giveWay.setSelected(true);
    37                 roundabout.setSelected(true);
    38                 access.setSelected(true);
    39                 intersection.setSelected(true);
    40                 direction.setSelected(true);
    41                 uneven.setSelected(true);
    42                 noParking.setSelected(true);
    43                 noOvertaking.setSelected(true);
    44                 crossing.setSelected(true);
    45                 noTurn.setSelected(true);
     33    public MapillaryFilterChooseSigns() {
     34        maxspeed.setSelected(true);
     35        stop.setSelected(true);
     36        giveWay.setSelected(true);
     37        roundabout.setSelected(true);
     38        access.setSelected(true);
     39        intersection.setSelected(true);
     40        direction.setSelected(true);
     41        uneven.setSelected(true);
     42        noParking.setSelected(true);
     43        noOvertaking.setSelected(true);
     44        crossing.setSelected(true);
     45        noTurn.setSelected(true);
    4646
    47                 // Max speed sign
    48                 JPanel maxspeedPanel = new JPanel();
    49                 JLabel maxspeedLabel = new JLabel(tr("Speed limit"));
    50                 maxspeedLabel.setIcon(new ImageProvider("signs/speed.png").get());
    51                 maxspeedPanel.add(maxspeedLabel);
    52                 maxspeedPanel.add(maxspeed);
    53                 this.add(maxspeedPanel);
     47        // Max speed sign
     48        JPanel maxspeedPanel = new JPanel();
     49        JLabel maxspeedLabel = new JLabel(tr("Speed limit"));
     50        maxspeedLabel.setIcon(new ImageProvider("signs/speed.png").get());
     51        maxspeedPanel.add(maxspeedLabel);
     52        maxspeedPanel.add(maxspeed);
     53        this.add(maxspeedPanel);
    5454
    55                 // Stop sign
    56                 JPanel stopPanel = new JPanel();
    57                 JLabel stopLabel = new JLabel(tr("Stop"));
    58                 stopLabel.setIcon(new ImageProvider("signs/stop.png").get());
    59                 stopPanel.add(stopLabel);
    60                 stopPanel.add(stop);
    61                 this.add(stopPanel);
     55        // Stop sign
     56        JPanel stopPanel = new JPanel();
     57        JLabel stopLabel = new JLabel(tr("Stop"));
     58        stopLabel.setIcon(new ImageProvider("signs/stop.png").get());
     59        stopPanel.add(stopLabel);
     60        stopPanel.add(stop);
     61        this.add(stopPanel);
    6262
    63                 // Give way sign
    64                 JPanel giveWayPanel = new JPanel();
    65                 JLabel giveWayLabel = new JLabel(tr("Give way"));
    66                 giveWayLabel.setIcon(new ImageProvider("signs/right_of_way.png").get());
    67                 giveWayPanel.add(giveWayLabel);
    68                 giveWayPanel.add(giveWay);
    69                 this.add(giveWayPanel);
     63        // Give way sign
     64        JPanel giveWayPanel = new JPanel();
     65        JLabel giveWayLabel = new JLabel(tr("Give way"));
     66        giveWayLabel.setIcon(new ImageProvider("signs/right_of_way.png").get());
     67        giveWayPanel.add(giveWayLabel);
     68        giveWayPanel.add(giveWay);
     69        this.add(giveWayPanel);
    7070
    71                 // Roundabout sign
    72                 JPanel roundaboutPanel = new JPanel();
    73                 JLabel roundaboutLabel = new JLabel(tr("Give way"));
    74                 roundaboutLabel.setIcon(new ImageProvider("signs/roundabout_right.png")
    75                                 .get());
    76                 roundaboutPanel.add(roundaboutLabel);
    77                 roundaboutPanel.add(roundabout);
    78                 this.add(roundaboutPanel);
     71        // Roundabout sign
     72        JPanel roundaboutPanel = new JPanel();
     73        JLabel roundaboutLabel = new JLabel(tr("Give way"));
     74        roundaboutLabel.setIcon(new ImageProvider("signs/roundabout_right.png")
     75                .get());
     76        roundaboutPanel.add(roundaboutLabel);
     77        roundaboutPanel.add(roundabout);
     78        this.add(roundaboutPanel);
    7979
    80                 // No entry sign
    81                 JPanel noEntryPanel = new JPanel();
    82                 JLabel noEntryLabel = new JLabel(tr("No entry"));
    83                 noEntryLabel.setIcon(new ImageProvider("signs/no_entry.png").get());
    84                 noEntryPanel.add(noEntryLabel);
    85                 noEntryPanel.add(access);
    86                 this.add(noEntryPanel);
     80        // No entry sign
     81        JPanel noEntryPanel = new JPanel();
     82        JLabel noEntryLabel = new JLabel(tr("No entry"));
     83        noEntryLabel.setIcon(new ImageProvider("signs/no_entry.png").get());
     84        noEntryPanel.add(noEntryLabel);
     85        noEntryPanel.add(access);
     86        this.add(noEntryPanel);
    8787
    88                 // Danger intersection
    89                 JPanel intersectionPanel = new JPanel();
    90                 JLabel intersectionLabel = new JLabel(tr("Intersection danger"));
    91                 intersectionLabel.setIcon(new ImageProvider(
    92                                 "signs/intersection_danger.png").get());
    93                 intersectionPanel.add(intersectionLabel);
    94                 intersectionPanel.add(intersection);
    95                 this.add(intersectionPanel);
     88        // Danger intersection
     89        JPanel intersectionPanel = new JPanel();
     90        JLabel intersectionLabel = new JLabel(tr("Intersection danger"));
     91        intersectionLabel.setIcon(new ImageProvider(
     92                "signs/intersection_danger.png").get());
     93        intersectionPanel.add(intersectionLabel);
     94        intersectionPanel.add(intersection);
     95        this.add(intersectionPanel);
    9696
    97                 // Mandatory direction
    98                 JPanel directionPanel = new JPanel();
    99                 JLabel directionLabel = new JLabel(tr("Mandatory direction (any)"));
    100                 directionLabel.setIcon(new ImageProvider("signs/only_straight_on.png")
    101                                 .get());
    102                 directionPanel.add(directionLabel);
    103                 directionPanel.add(direction);
    104                 this.add(directionPanel);
     97        // Mandatory direction
     98        JPanel directionPanel = new JPanel();
     99        JLabel directionLabel = new JLabel(tr("Mandatory direction (any)"));
     100        directionLabel.setIcon(new ImageProvider("signs/only_straight_on.png")
     101                .get());
     102        directionPanel.add(directionLabel);
     103        directionPanel.add(direction);
     104        this.add(directionPanel);
    105105
    106                 // No turn
    107                 JPanel noTurnPanel = new JPanel();
    108                 JLabel noTurnLabel = new JLabel(tr("No turn"));
    109                 noTurnLabel.setIcon(new ImageProvider("signs/no_turn.png").get());
    110                 noTurnPanel.add(noTurnLabel);
    111                 noTurnPanel.add(noTurn);
    112                 this.add(noTurnPanel);
     106        // No turn
     107        JPanel noTurnPanel = new JPanel();
     108        JLabel noTurnLabel = new JLabel(tr("No turn"));
     109        noTurnLabel.setIcon(new ImageProvider("signs/no_turn.png").get());
     110        noTurnPanel.add(noTurnLabel);
     111        noTurnPanel.add(noTurn);
     112        this.add(noTurnPanel);
    113113
    114                 // Uneven road
    115                 JPanel unevenPanel = new JPanel();
    116                 JLabel unevenLabel = new JLabel(tr("Uneven road"));
    117                 unevenLabel.setIcon(new ImageProvider("signs/uneaven.png").get());
    118                 unevenPanel.add(unevenLabel);
    119                 unevenPanel.add(uneven);
    120                 this.add(unevenPanel);
     114        // Uneven road
     115        JPanel unevenPanel = new JPanel();
     116        JLabel unevenLabel = new JLabel(tr("Uneven road"));
     117        unevenLabel.setIcon(new ImageProvider("signs/uneaven.png").get());
     118        unevenPanel.add(unevenLabel);
     119        unevenPanel.add(uneven);
     120        this.add(unevenPanel);
    121121
    122                 // No parking
    123                 JPanel noParkingPanel = new JPanel();
    124                 JLabel noParkingLabel = new JLabel(tr("No parking"));
    125                 noParkingLabel.setIcon(new ImageProvider("signs/no_parking.png").get());
    126                 noParkingPanel.add(noParkingLabel);
    127                 noParkingPanel.add(noParking);
    128                 this.add(noParkingPanel);
     122        // No parking
     123        JPanel noParkingPanel = new JPanel();
     124        JLabel noParkingLabel = new JLabel(tr("No parking"));
     125        noParkingLabel.setIcon(new ImageProvider("signs/no_parking.png").get());
     126        noParkingPanel.add(noParkingLabel);
     127        noParkingPanel.add(noParking);
     128        this.add(noParkingPanel);
    129129
    130                 // No overtaking
    131                 JPanel noOvertakingPanel = new JPanel();
    132                 JLabel noOvertakingLabel = new JLabel(tr("No overtaking"));
    133                 noOvertakingLabel.setIcon(new ImageProvider("signs/no_overtaking.png")
    134                                 .get());
    135                 noOvertakingPanel.add(noOvertakingLabel);
    136                 noOvertakingPanel.add(noOvertaking);
    137                 this.add(noOvertakingPanel);
     130        // No overtaking
     131        JPanel noOvertakingPanel = new JPanel();
     132        JLabel noOvertakingLabel = new JLabel(tr("No overtaking"));
     133        noOvertakingLabel.setIcon(new ImageProvider("signs/no_overtaking.png")
     134                .get());
     135        noOvertakingPanel.add(noOvertakingLabel);
     136        noOvertakingPanel.add(noOvertaking);
     137        this.add(noOvertakingPanel);
    138138
    139                 // Pedestrian crossing
    140                 JPanel crossingPanel = new JPanel();
    141                 JLabel crossingLabel = new JLabel(tr("Pedestrian crossing"));
    142                 crossingLabel.setIcon(new ImageProvider("signs/crossing.png").get());
    143                 crossingPanel.add(crossingLabel);
    144                 crossingPanel.add(crossing);
    145                 this.add(crossingPanel);
     139        // Pedestrian crossing
     140        JPanel crossingPanel = new JPanel();
     141        JLabel crossingLabel = new JLabel(tr("Pedestrian crossing"));
     142        crossingLabel.setIcon(new ImageProvider("signs/crossing.png").get());
     143        crossingPanel.add(crossingLabel);
     144        crossingPanel.add(crossing);
     145        this.add(crossingPanel);
    146146
    147                 this.setPreferredSize(new Dimension(600, 150));
    148         }
     147        this.setPreferredSize(new Dimension(600, 150));
     148    }
    149149
    150         public static MapillaryFilterChooseSigns getInstance() {
    151                 if (INSTANCE == null)
    152                         INSTANCE = new MapillaryFilterChooseSigns();
    153                 return INSTANCE;
    154         }
     150    public static MapillaryFilterChooseSigns getInstance() {
     151        if (INSTANCE == null)
     152            INSTANCE = new MapillaryFilterChooseSigns();
     153        return INSTANCE;
     154    }
    155155
    156         @Override
    157         public void actionPerformed(ActionEvent arg0) {
    158                 // TODO Auto-generated method stub
     156    @Override
     157    public void actionPerformed(ActionEvent arg0) {
     158        // TODO Auto-generated method stub
    159159
    160         }
     160    }
    161161
    162162}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java

    r31319 r31328  
    3737 */
    3838public class MapillaryFilterDialog extends ToggleDialog implements
    39                 MapillaryDataListener {
    40 
    41         public static MapillaryFilterDialog INSTANCE;
    42 
    43         private final static String[] TIME_LIST = { tr("All time"),
    44                         tr("This year"), tr("This month"), tr("This week") };
    45 
    46         private final static int ROWS = 0;
    47         private final static int COLUMNS = 3;
    48 
    49         private final JPanel panel = new JPanel(new GridLayout(ROWS, COLUMNS));
    50 
    51         public final JCheckBox imported = new JCheckBox("Imported images");
    52         public final JCheckBox downloaded = new JCheckBox(
    53                         new downloadCheckBoxAction());
    54         public final JCheckBox onlySigns = new JCheckBox(new OnlySignsAction());
    55         public final JComboBox<String> time;
    56         public final JTextField user;
    57 
    58         public final SideButton updateButton = new SideButton(new UpdateAction());
    59         public final SideButton resetButton = new SideButton(new ResetAction());
    60         public final JButton signChooser = new JButton(new SignChooserAction());
    61 
    62         public final MapillaryFilterChooseSigns signFilter = MapillaryFilterChooseSigns
    63                         .getInstance();
    64 
    65         private final String[] SIGN_TAGS = { "prohibitory_speed_limit",
    66                         "priority_stop", "other_give_way", "mandatory_roundabout",
    67                         "other_no_entry", "prohibitory_no_traffic_both_ways",
    68                         "danger_intersection", "mandatory_go", "mandatory_keep",
    69                         "danger_priority_next_intersection", "danger_uneven_road",
    70                         "prohibitory_no_parking", "prohibitory_on_overtaking",
    71                         "danger_pedestrian_crossing", "prohibitory_no_u_turn",
    72                         "prohibitory_noturn" };
    73         private final JCheckBox[] SIGN_CHECKBOXES = { signFilter.maxspeed,
    74                         signFilter.stop, signFilter.giveWay, signFilter.roundabout,
    75                         signFilter.access, signFilter.access, signFilter.intersection,
    76                         signFilter.direction, signFilter.direction,
    77                         signFilter.intersection, signFilter.uneven, signFilter.noParking,
    78                         signFilter.noOvertaking, signFilter.crossing, signFilter.noTurn,
    79                         signFilter.noTurn };
    80 
    81         public MapillaryFilterDialog() {
    82                 super(tr("Mapillary filter"), "mapillaryfilter.png",
    83                                 tr("Open Mapillary filter dialog"), Shortcut.registerShortcut(
    84                                                 tr("Mapillary filter"),
    85                                                 tr("Open Mapillary filter dialog"), KeyEvent.VK_M,
    86                                                 Shortcut.NONE), 200);
    87 
    88                 signChooser.setEnabled(false);
    89                 JPanel signChooserPanel = new JPanel();
    90                 signChooserPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
    91                 signChooserPanel.add(signChooser);
    92 
    93                 JPanel fromPanel = new JPanel();
    94                 fromPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
    95                 fromPanel.add(new JLabel("From"));
    96                 time = new JComboBox<>(TIME_LIST);
    97                 fromPanel.add(time);
    98 
    99                 JPanel userSearchPanel = new JPanel();
    100                 userSearchPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
    101                 user = new JTextField(10);
    102                 user.addActionListener(new UpdateAction());
    103                 userSearchPanel.add(new JLabel("User"));
    104                 userSearchPanel.add(user);
    105 
    106                 imported.setSelected(true);
    107                 downloaded.setSelected(true);
    108 
    109                 panel.add(downloaded);
    110                 panel.add(imported);
    111                 panel.add(onlySigns);
    112                 panel.add(fromPanel);
    113                 panel.add(userSearchPanel);
    114                 panel.add(signChooserPanel);
    115 
    116                 createLayout(panel, true,
    117                                 Arrays.asList(new SideButton[] { updateButton, resetButton }));
    118         }
    119 
    120         public static MapillaryFilterDialog getInstance() {
    121                 if (INSTANCE == null)
    122                         INSTANCE = new MapillaryFilterDialog();
    123                 return INSTANCE;
    124         }
    125 
    126         @Override
    127         public void imagesAdded() {
    128                 refresh();
    129         }
    130 
    131         @Override
    132         public void selectedImageChanged(MapillaryAbstractImage oldImage,
    133                         MapillaryAbstractImage newImage) {
    134         }
    135 
    136         public void reset() {
    137                 imported.setSelected(true);
    138                 downloaded.setSelected(true);
    139                 onlySigns.setEnabled(true);
    140                 onlySigns.setSelected(false);
    141                 user.setText("");
    142                 time.setSelectedItem(TIME_LIST[0]);
    143                 refresh();
    144         }
    145 
    146         public synchronized void refresh() {
    147                 boolean imported = this.imported.isSelected();
    148                 boolean downloaded = this.downloaded.isSelected();
    149                 boolean onlySigns = this.onlySigns.isSelected();
    150 
    151                 for (MapillaryAbstractImage img : MapillaryData.getInstance()
    152                                 .getImages()) {
    153                         img.setVisible(true);
    154                         if (img instanceof MapillaryImportedImage) {
    155                                 if (!imported)
    156                                         img.setVisible(false);
    157                                 continue;
    158                         } else if (img instanceof MapillaryImage) {
    159                                 if (!downloaded) {
    160                                         img.setVisible(false);
    161                                         continue;
    162                                 }
    163                                 if (onlySigns) {
    164                                         if (((MapillaryImage) img).getSigns().isEmpty()) {
    165                                                 img.setVisible(false);
    166                                                 continue;
    167                                         }
    168                                         if (!checkSigns((MapillaryImage) img)) {
    169                                                 img.setVisible(false);
    170                                                 continue;
    171                                         }
    172                                 }
    173                                 if (!user.getText().equals("")
    174                                                 && !user.getText().equals(
    175                                                                 ((MapillaryImage) img).getUser())) {
    176                                         img.setVisible(false);
    177                                         continue;
    178                                 }
    179                         }
    180                         // Calculates the amount of days since the image was taken
    181                         Long currentTime = currentTime();
    182                         if (time.getSelectedItem() == TIME_LIST[1]) {
    183                                 if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 365) {
    184                                         img.setVisible(false);
    185                                         continue;
    186                                 }
    187                         }
    188                         if (time.getSelectedItem() == TIME_LIST[2]) {
    189                                 if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 30) {
    190                                         img.setVisible(false);
    191                                         continue;
    192                                 }
    193                         }
    194                         if (time.getSelectedItem() == TIME_LIST[3]) {
    195                                 if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 7) {
    196                                         img.setVisible(false);
    197                                         continue;
    198                                 }
    199                         }
    200                 }
    201                 Main.map.repaint();
    202         }
    203 
    204         private boolean checkSigns(MapillaryImage img) {
    205                 for (int i = 0; i < SIGN_TAGS.length; i++) {
    206                         if (checkSign(img, SIGN_CHECKBOXES[i], SIGN_TAGS[i]))
    207                                 return true;
    208                 }
    209                 return false;
    210         }
    211 
    212         private boolean checkSign(MapillaryImage img, JCheckBox signCheckBox,
    213                         String singString) {
    214                 boolean contains = false;
    215                 for (String sign : img.getSigns()) {
    216                         if (sign.contains(singString))
    217                                 contains = true;
    218                 }
    219                 if (contains == signCheckBox.isSelected() && contains)
    220                         return true;
    221                 return false;
    222         }
    223 
    224         private long currentTime() {
    225                 Calendar cal = Calendar.getInstance();
    226                 return cal.getTimeInMillis();
    227         }
    228 
    229         private class downloadCheckBoxAction extends AbstractAction {
    230 
    231                 public downloadCheckBoxAction() {
    232                         putValue(NAME, tr("Downloaded images"));
    233                 }
    234 
    235                 @Override
    236                 public void actionPerformed(ActionEvent arg0) {
    237                         onlySigns.setEnabled(downloaded.isSelected());
    238                 }
    239         }
    240 
    241         private class UpdateAction extends AbstractAction {
    242                 public UpdateAction() {
    243                         putValue(NAME, tr("Update"));
    244                 }
    245 
    246                 @Override
    247                 public void actionPerformed(ActionEvent arg0) {
    248                         MapillaryFilterDialog.getInstance().refresh();
    249                 }
    250         }
    251 
    252         private class ResetAction extends AbstractAction {
    253                 public ResetAction() {
    254                         putValue(NAME, tr("Reset"));
    255                 }
    256 
    257                 @Override
    258                 public void actionPerformed(ActionEvent arg0) {
    259                         MapillaryFilterDialog.getInstance().reset();
    260                 }
    261         }
    262 
    263         private class OnlySignsAction extends AbstractAction {
    264                 public OnlySignsAction() {
    265                         putValue(NAME, tr("Only images with signs"));
    266                 }
    267 
    268                 @Override
    269                 public void actionPerformed(ActionEvent arg0) {
    270                         signChooser.setEnabled(onlySigns.isSelected());
    271                 }
    272         }
    273 
    274         /**
    275         * Opens a new window where you can specifically filter signs.
    276         *
    277         * @author nokutu
    278         *
    279         */
    280         private class SignChooserAction extends AbstractAction {
    281                 public SignChooserAction() {
    282                         putValue(NAME, tr("Choose signs"));
    283                 }
    284 
    285                 @Override
    286                 public void actionPerformed(ActionEvent arg0) {
    287                         JPanel dialog = MapillaryFilterChooseSigns.getInstance();
    288                         JOptionPane pane = new JOptionPane(dialog,
    289                                         JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
    290                         JDialog dlg = pane.createDialog(Main.parent, tr("Choose signs"));
    291                         dlg.setVisible(true);
    292                         if ((int) pane.getValue() == JOptionPane.OK_OPTION)
    293                                 MapillaryFilterDialog.getInstance().refresh();
    294                         dlg.dispose();
    295                 }
    296         }
    297 
    298         public static void destroyInstance() {
    299                 MapillaryFilterDialog.INSTANCE = null;
    300         }
     39        MapillaryDataListener {
     40
     41    public static MapillaryFilterDialog INSTANCE;
     42
     43    private final static String[] TIME_LIST = { tr("All time"),
     44            tr("This year"), tr("This month"), tr("This week") };
     45
     46    private final static int ROWS = 0;
     47    private final static int COLUMNS = 3;
     48
     49    private final JPanel panel = new JPanel(new GridLayout(ROWS, COLUMNS));
     50
     51    public final JCheckBox imported = new JCheckBox("Imported images");
     52    public final JCheckBox downloaded = new JCheckBox(
     53            new downloadCheckBoxAction());
     54    public final JCheckBox onlySigns = new JCheckBox(new OnlySignsAction());
     55    public final JComboBox<String> time;
     56    public final JTextField user;
     57
     58    public final SideButton updateButton = new SideButton(new UpdateAction());
     59    public final SideButton resetButton = new SideButton(new ResetAction());
     60    public final JButton signChooser = new JButton(new SignChooserAction());
     61
     62    public final MapillaryFilterChooseSigns signFilter = MapillaryFilterChooseSigns
     63            .getInstance();
     64
     65    private final String[] SIGN_TAGS = { "prohibitory_speed_limit",
     66            "priority_stop", "other_give_way", "mandatory_roundabout",
     67            "other_no_entry", "prohibitory_no_traffic_both_ways",
     68            "danger_intersection", "mandatory_go", "mandatory_keep",
     69            "danger_priority_next_intersection", "danger_uneven_road",
     70            "prohibitory_no_parking", "prohibitory_on_overtaking",
     71            "danger_pedestrian_crossing", "prohibitory_no_u_turn",
     72            "prohibitory_noturn" };
     73    private final JCheckBox[] SIGN_CHECKBOXES = { signFilter.maxspeed,
     74            signFilter.stop, signFilter.giveWay, signFilter.roundabout,
     75            signFilter.access, signFilter.access, signFilter.intersection,
     76            signFilter.direction, signFilter.direction,
     77            signFilter.intersection, signFilter.uneven, signFilter.noParking,
     78            signFilter.noOvertaking, signFilter.crossing, signFilter.noTurn,
     79            signFilter.noTurn };
     80
     81    public MapillaryFilterDialog() {
     82        super(tr("Mapillary filter"), "mapillaryfilter.png",
     83                tr("Open Mapillary filter dialog"), Shortcut.registerShortcut(
     84                        tr("Mapillary filter"),
     85                        tr("Open Mapillary filter dialog"), KeyEvent.VK_M,
     86                        Shortcut.NONE), 200);
     87
     88        signChooser.setEnabled(false);
     89        JPanel signChooserPanel = new JPanel();
     90        signChooserPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
     91        signChooserPanel.add(signChooser);
     92
     93        JPanel fromPanel = new JPanel();
     94        fromPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
     95        fromPanel.add(new JLabel("From"));
     96        time = new JComboBox<>(TIME_LIST);
     97        fromPanel.add(time);
     98
     99        JPanel userSearchPanel = new JPanel();
     100        userSearchPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
     101        user = new JTextField(10);
     102        user.addActionListener(new UpdateAction());
     103        userSearchPanel.add(new JLabel("User"));
     104        userSearchPanel.add(user);
     105
     106        imported.setSelected(true);
     107        downloaded.setSelected(true);
     108
     109        panel.add(downloaded);
     110        panel.add(imported);
     111        panel.add(onlySigns);
     112        panel.add(fromPanel);
     113        panel.add(userSearchPanel);
     114        panel.add(signChooserPanel);
     115
     116        createLayout(panel, true,
     117                Arrays.asList(new SideButton[] { updateButton, resetButton }));
     118    }
     119
     120    public static MapillaryFilterDialog getInstance() {
     121        if (INSTANCE == null)
     122            INSTANCE = new MapillaryFilterDialog();
     123        return INSTANCE;
     124    }
     125
     126    @Override
     127    public void imagesAdded() {
     128        refresh();
     129    }
     130
     131    @Override
     132    public void selectedImageChanged(MapillaryAbstractImage oldImage,
     133            MapillaryAbstractImage newImage) {
     134    }
     135
     136    public void reset() {
     137        imported.setSelected(true);
     138        downloaded.setSelected(true);
     139        onlySigns.setEnabled(true);
     140        onlySigns.setSelected(false);
     141        user.setText("");
     142        time.setSelectedItem(TIME_LIST[0]);
     143        refresh();
     144    }
     145
     146    public synchronized void refresh() {
     147        boolean imported = this.imported.isSelected();
     148        boolean downloaded = this.downloaded.isSelected();
     149        boolean onlySigns = this.onlySigns.isSelected();
     150
     151        for (MapillaryAbstractImage img : MapillaryData.getInstance()
     152                .getImages()) {
     153            img.setVisible(true);
     154            if (img instanceof MapillaryImportedImage) {
     155                if (!imported)
     156                    img.setVisible(false);
     157                continue;
     158            } else if (img instanceof MapillaryImage) {
     159                if (!downloaded) {
     160                    img.setVisible(false);
     161                    continue;
     162                }
     163                if (onlySigns) {
     164                    if (((MapillaryImage) img).getSigns().isEmpty()) {
     165                        img.setVisible(false);
     166                        continue;
     167                    }
     168                    if (!checkSigns((MapillaryImage) img)) {
     169                        img.setVisible(false);
     170                        continue;
     171                    }
     172                }
     173                if (!user.getText().equals("")
     174                        && !user.getText().equals(
     175                                ((MapillaryImage) img).getUser())) {
     176                    img.setVisible(false);
     177                    continue;
     178                }
     179            }
     180            // Calculates the amount of days since the image was taken
     181            Long currentTime = currentTime();
     182            if (time.getSelectedItem() == TIME_LIST[1]) {
     183                if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 365) {
     184                    img.setVisible(false);
     185                    continue;
     186                }
     187            }
     188            if (time.getSelectedItem() == TIME_LIST[2]) {
     189                if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 30) {
     190                    img.setVisible(false);
     191                    continue;
     192                }
     193            }
     194            if (time.getSelectedItem() == TIME_LIST[3]) {
     195                if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 7) {
     196                    img.setVisible(false);
     197                    continue;
     198                }
     199            }
     200        }
     201        Main.map.repaint();
     202    }
     203
     204    private boolean checkSigns(MapillaryImage img) {
     205        for (int i = 0; i < SIGN_TAGS.length; i++) {
     206            if (checkSign(img, SIGN_CHECKBOXES[i], SIGN_TAGS[i]))
     207                return true;
     208        }
     209        return false;
     210    }
     211
     212    private boolean checkSign(MapillaryImage img, JCheckBox signCheckBox,
     213            String singString) {
     214        boolean contains = false;
     215        for (String sign : img.getSigns()) {
     216            if (sign.contains(singString))
     217                contains = true;
     218        }
     219        if (contains == signCheckBox.isSelected() && contains)
     220            return true;
     221        return false;
     222    }
     223
     224    private long currentTime() {
     225        Calendar cal = Calendar.getInstance();
     226        return cal.getTimeInMillis();
     227    }
     228
     229    private class downloadCheckBoxAction extends AbstractAction {
     230
     231        public downloadCheckBoxAction() {
     232            putValue(NAME, tr("Downloaded images"));
     233        }
     234
     235        @Override
     236        public void actionPerformed(ActionEvent arg0) {
     237            onlySigns.setEnabled(downloaded.isSelected());
     238        }
     239    }
     240
     241    private class UpdateAction extends AbstractAction {
     242        public UpdateAction() {
     243            putValue(NAME, tr("Update"));
     244        }
     245
     246        @Override
     247        public void actionPerformed(ActionEvent arg0) {
     248            MapillaryFilterDialog.getInstance().refresh();
     249        }
     250    }
     251
     252    private class ResetAction extends AbstractAction {
     253        public ResetAction() {
     254            putValue(NAME, tr("Reset"));
     255        }
     256
     257        @Override
     258        public void actionPerformed(ActionEvent arg0) {
     259            MapillaryFilterDialog.getInstance().reset();
     260        }
     261    }
     262
     263    private class OnlySignsAction extends AbstractAction {
     264        public OnlySignsAction() {
     265            putValue(NAME, tr("Only images with signs"));
     266        }
     267
     268        @Override
     269        public void actionPerformed(ActionEvent arg0) {
     270            signChooser.setEnabled(onlySigns.isSelected());
     271        }
     272    }
     273
     274    /**
     275    * Opens a new window where you can specifically filter signs.
     276    *
     277    * @author nokutu
     278    *
     279    */
     280    private class SignChooserAction extends AbstractAction {
     281        public SignChooserAction() {
     282            putValue(NAME, tr("Choose signs"));
     283        }
     284
     285        @Override
     286        public void actionPerformed(ActionEvent arg0) {
     287            JPanel dialog = MapillaryFilterChooseSigns.getInstance();
     288            JOptionPane pane = new JOptionPane(dialog,
     289                    JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
     290            JDialog dlg = pane.createDialog(Main.parent, tr("Choose signs"));
     291            dlg.setVisible(true);
     292            if ((int) pane.getValue() == JOptionPane.OK_OPTION)
     293                MapillaryFilterDialog.getInstance().refresh();
     294            dlg.dispose();
     295        }
     296    }
     297
     298    public static void destroyInstance() {
     299        MapillaryFilterDialog.INSTANCE = null;
     300    }
    301301}
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryPreferenceSetting.java

    r31313 r31328  
    2020    private JCheckBox downloadMode = new JCheckBox(
    2121            tr("Download images manually"));
    22     private JCheckBox displayHour = new JCheckBox(tr("Display hour when the picture was taken"));
     22    private JCheckBox displayHour = new JCheckBox(
     23            tr("Display hour when the picture was taken"));
    2324    private JCheckBox format24 = new JCheckBox(tr("Use 24 hour format"));
    24     private JCheckBox moveTo = new JCheckBox(tr("Move to picture's location with next/previous buttons"));
     25    private JCheckBox moveTo = new JCheckBox(
     26            tr("Move to picture's location with next/previous buttons"));
    2527
    2628    @Override
     
    3739        downloadMode.setSelected(Main.pref
    3840                .getBoolean("mapillary.download-manually"));
    39         displayHour.setSelected(Main.pref.getBoolean("mapillary.display-hour", true));
     41        displayHour.setSelected(Main.pref.getBoolean("mapillary.display-hour",
     42                true));
    4043        format24.setSelected(Main.pref.getBoolean("mapillary.format-24"));
    41         moveTo.setSelected(Main.pref.getBoolean("mapillary.move-to-picture", true));
     44        moveTo.setSelected(Main.pref.getBoolean("mapillary.move-to-picture",
     45                true));
    4246
    4347        panel.setLayout(new FlowLayout(FlowLayout.LEFT));
     
    5559        Main.pref.put("mapillary.reverse-buttons", reverseButtons.isSelected());
    5660        Main.pref.put("mapillary.download-manually", downloadMode.isSelected());
    57         MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU, downloadMode.isSelected());
    58        
     61        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU,
     62                downloadMode.isSelected());
     63
    5964        Main.pref.put("mapillary.display-hour", displayHour.isSelected());
    6065        Main.pref.put("mapillary.format-24", format24.isSelected());
Note: See TracChangeset for help on using the changeset viewer.