    001// License: GPL. For details, see LICENSE file.
    002package org.openstreetmap.josm.plugins.streetside;
    003
    004import java.text.SimpleDateFormat;
    005import java.util.Calendar;
    006import java.util.Date;
    007import java.util.Locale;
    008
    009import org.openstreetmap.josm.data.coor.LatLon;
    010import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
    011
    012/**
    013 * Abstract superclass for all image objects. At the moment there are 3,
    014 * {@link StreetsideImportedImage}, {@link StreetsideImage}, & {@link StreetsideCubemap}.
    015 *
    016 * @author nokutu
    017 * @author renerr18
    018 *
    019 */
    020public abstract class StreetsideAbstractImage implements Comparable<StreetsideAbstractImage> {
    021        /**
    022         * If two values for field cd differ by less than EPSILON both values are
    023         * considered equal.
    024         */
    025        private static final float EPSILON = 1e-5f;
    026
    027        protected String id;
    028
    029        private long ne;
    030  private long pr;
    031
    032
    033        /** The time the image was captured, in Epoch format. */
    034        protected long cd;
    035        /** Sequence of pictures containing this object. */
    036        private StreetsideSequence sequence;
    037
    038        /** Position of the picture. */
    039        protected LatLon latLon;
    040        /** Direction of the picture. */
    041        protected double he;
    042        /** Temporal position of the picture until it is uploaded. */
    043        private LatLon tempLatLon;
    044        /**
    045         * When the object is being dragged in the map, the temporal position is stored
    046         * here.
    047         */
    048        private LatLon movingLatLon;
    049        /** Temporal direction of the picture until it is uploaded */
    050        private double tempHe;
    051        /**
    052         * When the object direction is being moved in the map, the temporal direction
    053         * is stored here
    054         */
    055        protected double movingHe;
    056        /** Whether the image must be drown in the map or not */
    057        private boolean visible;
    058
    059        /**
    060         * Creates a new object in the given position and with the given direction.
    061         * {@link LatLon}
    062         *
    063         * @param id - the Streetside image id
    064         *
    065         * @param latLon
    066         *            The latitude and longitude of the image.
    067         * @param he
    068         *            The direction of the picture (0 means north im Mapillary
    069         *            camera direction is not yet supported in the Streetside plugin).
    070         */
    071        protected StreetsideAbstractImage(final String id, final LatLon latLon, final double he) {
    072                this.id = id;
    073                this.latLon = latLon;
    074                tempLatLon = this.latLon;
    075                movingLatLon = this.latLon;
    076                this.he = he;
    077                tempHe = he;
    078                movingHe = he;
    079                visible = true;
    080        }
    081
    082        /**
    083         * Creates a new object with the given id.
    084         *
    085         * @param id - the image id (All images require ids in Streetside)
    086         */
    087        protected StreetsideAbstractImage(final String id) {
    088                this.id = id;
    089
    090                visible = true;
    091        }
    092
    093        /**
    094         * @return the id
    095         */
    096        public String getId() {
    097                return id;
    098        }
    099
    100        /**
    101         * @param id
    102         *            the id to set
    103         */
    104        public void setId(String id) {
    105                this.id = id;
    106        }
    107
    108        /**
    109         * Returns the original direction towards the image has been taken.
    110         *
    111         * @return The direction of the image (0 means north and goes clockwise).
    112         */
    113        public double getHe() {
    114                return he;
    115        }
    116
    117        /**
    118         * Returns the Epoch time when the image was captured.
    119         *
    120         * @return The long containing the Epoch time when the image was captured.
    121         */
    122        public long getCd() {
    123                return cd;
    124        }
    125
    126        /**
    127         * Returns the date the picture was taken in DMY format.
    128         *
    129         * @return A String object containing the date when the picture was taken.
    130         */
    131        public String getDate() {
    132                final StringBuilder format = new StringBuilder(26);
    133                format.append("m/d/YYYY");
    134                if (StreetsideProperties.DISPLAY_HOUR.get()) {
    135                        if (StreetsideProperties.TIME_FORMAT_24.get()) {
    136                                format.append(" - HH:mm:ss");
    137                        } else {
    138                                format.append(" - h:mm:ss a");
    139                        }
    140                }
    141                return getDate(format.toString());
    142        }
    143
    144        /**
    145         * Returns the date the picture was taken in the given format.
    146         *
    147         * @param format
    148         *            Format of the date. See {@link SimpleDateFormat}.
    149         * @return A String containing the date the picture was taken using the given
    150         *         format.
    151         * @throws NullPointerException
    152         *             if parameter format is <code>null</code>
    153         */
    154        public String getDate(String format) {
    155                final Date date = new Date(getCd());
    156                final SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.US);
    157                formatter.setTimeZone(Calendar.getInstance().getTimeZone());
    158                return formatter.format(date);
    159        }
    160
    161        /**
    162         * Returns a LatLon object containing the original coordinates of the object.
    163         *
    164         * @return The LatLon object with the position of the object.
    165         */
    166        public LatLon getLatLon() {
    167                return latLon;
    168        }
    169
    170        /**
    171         * Returns the direction towards the image has been taken.
    172         *
    173         * @return The direction of the image (0 means north and goes clockwise).
    174         */
    175        public double getMovingHe() {
    176                return movingHe;
    177        }
    178
    179        /**
    180         * Returns a LatLon object containing the current coordinates of the object.
    181         * When you are dragging the image this changes.
    182         *
    183         * @return The LatLon object with the position of the object.
    184         */
    185        public LatLon getMovingLatLon() {
    186                return movingLatLon;
    187        }
    188
    189        /**
    190         * Returns the sequence which contains this image. Never null.
    191         *
    192         * @return The StreetsideSequence object that contains this StreetsideImage.
    193         */
    194
    195        public StreetsideSequence getSequence() {
    196                synchronized (this) {
    197                        if (sequence == null) {
    198                                sequence = new StreetsideSequence();
    199                                sequence.add(this);
    200                        }
    201                        return sequence;
    202                }
    203        }
    204
    205        /**
    206         * Returns the last fixed direction of the object.
    207         *
    208         * @return The last fixed direction of the object. 0 means north.
    209         */
    210        public double getTempHe() {
    211                return tempHe;
    212        }
    213
    214        /**
    215         * Returns the last fixed coordinates of the object.
    216         *
    217         * @return A LatLon object containing.
    218         */
    219        public LatLon getTempLatLon() {
    220                return tempLatLon;
    221        }
    222
    223        /**
    224         * Returns whether the object has been modified or not.
    225         *
    226         * @return true if the object has been modified; false otherwise.
    227         */
    228        public boolean isModified() {
    229                return !getMovingLatLon().equals(latLon) || Math.abs(getMovingHe() - cd) > EPSILON;
    230        }
    231
    232        /**
    233         * Returns whether the image is visible on the map or not.
    234         *
    235         * @return True if the image is visible; false otherwise.
    236         */
    237        public boolean isVisible() {
    238                return visible;
    239        }
    240
    241        /**
    242         * Moves the image temporally to another position
    243         *
    244         * @param x
    245         *            The movement of the image in longitude units.
    246         * @param y
    247         *            The movement of the image in latitude units.
    248         */
    249        public void move(final double x, final double y) {
    250                movingLatLon = new LatLon(tempLatLon.getY() + y, tempLatLon.getX() + x);
    251        }
    252
    253        /**
    254         * If the StreetsideImage belongs to a StreetsideSequence, returns the next
    255         * image in the sequence.
    256         *
    257         * @return The following StreetsideImage, or null if there is none.
    258         */
    259        public StreetsideAbstractImage next() {
    260                synchronized (this) {
    261                        return getSequence().next(this);
    262                }
    263        }
    264
    265        /**
    266         * If the StreetsideImage belongs to a StreetsideSequence, returns the previous
    267         * image in the sequence.
    268         *
    269         * @return The previous StreetsideImage, or null if there is none.
    270         */
    271        public StreetsideAbstractImage previous() {
    272                synchronized (this) {
    273                        return getSequence().previous(this);
    274                }
    275        }
    276
    277        public void setHe(final double he) {
    278                this.he = he;
    279        }
    280
    281        /**
    282         * Sets the Epoch time when the picture was captured.
    283         *
    284         * @param cd
    285         *            Epoch time when the image was captured.
    286         */
    287        public synchronized void setCd(final long cd) {
    288                this.cd = cd;
    289        }
    290
    291        public void setLatLon(final LatLon latLon) {
    292                if (latLon != null) {
    293                        this.latLon = latLon;
    294                }
    295        }
    296
    297        /**
    298         * Sets the StreetsideSequence object which contains the StreetsideImage.
    299         *
    300         * @param sequence
    301         *            The StreetsideSequence that contains the StreetsideImage.
    302         * @throws IllegalArgumentException
    303         *             if the image is not already part of the
    304         *             {@link StreetsideSequence}. Call
    305         *             {@link StreetsideSequence#add(StreetsideAbstractImage)} first.
    306         */
    307        public void setSequence(final StreetsideSequence sequence) {
    308                synchronized (this) {
    309                        if (sequence != null && !sequence.getImages().contains(this)) {
    310                                throw new IllegalArgumentException();
    311                        }
    312                        this.sequence = sequence;
    313                }
    314        }
    315
    316        /**
    317         * Set's whether the image should be visible on the map or not.
    318         *
    319         * @param visible
    320         *            true if the image is set to be visible; false otherwise.
    321         */
    322        public void setVisible(final boolean visible) {
    323                this.visible = visible;
    324        }
    325
    326        /**
    327         * Called when the mouse button is released, meaning that the picture has
    328         * stopped being dragged, so the temporal values are saved.
    329         */
    330        public void stopMoving() {
    331                tempLatLon = movingLatLon;
    332                tempHe = movingHe;
    333        }
    334
    335        /**
    336         * Turns the image direction.
    337         *
    338         * @param ca
    339         *            The angle the image is moving.
    340         */
    341        public void turn(final double ca) {
    342                movingHe = tempHe + ca;
    343        }
    344
    345        /**
    346   * @return the ne
    347   */
    348  public long getNe() {
    349    return ne;
    350  }
    351
    352  /**
    353   * @param ne the ne to set
    354   */
    355  public void setNe(long ne) {
    356    this.ne = ne;
    357  }
    358
    359  /**
    360   * @return the pr
    361   */
    362  public long getPr() {
    363    return pr;
    364  }
    365
    366  /**
    367   * @param pr the pr to set
    368   */
    369  public void setPr(long pr) {
    370    this.pr = pr;
    371  }
    372
    373}