Changeset 32066 in osm


Ignore:
Timestamp:
2016-02-11T23:17:32+01:00 (9 years ago)
Author:
floscher
Message:

[mapillary] Let TrafficoSign.getSign() return an object of type TrafficoSign instead of an array of type TrafficoSignElement[]

Location:
applications/editors/josm/plugins/mapillary
Files:
3 edited

Legend:

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

    r31810 r32066  
    2323import org.openstreetmap.josm.gui.layer.Layer;
    2424import org.openstreetmap.josm.plugins.mapillary.traffico.TrafficoSign;
    25 import org.openstreetmap.josm.plugins.mapillary.traffico.TrafficoSignElement;
    2625import org.openstreetmap.josm.tools.I18n;
    2726
     
    3837      throw new IOException(I18n.tr("Traffic sign font at ''{0}'' has wrong format.", TRAFFICO_PATH), e);
    3938    } catch (IOException e) {
    40       throw new IOException(I18n.tr("Could not read font-file from ''{{0}}''.", TRAFFICO_PATH), e);
     39      throw new IOException(I18n.tr("Could not read font-file from ''{0}''.", TRAFFICO_PATH), e);
    4140    }
    4241  }
     
    8180    points[2] = mv.getPoint(new LatLon(49.01038, 8.40636));
    8281
    83     TrafficoSignElement[][] signs = {
     82    TrafficoSign[] signs = {
    8483        TrafficoSign.getSign("europe", "mandatory_cycle_track"),
    8584        TrafficoSign.getSign("de", "information_bus_stop"),
     
    8786
    8887    for (int i = 0; i < signs.length && i < points.length; i++) {
    89       for (TrafficoSignElement layer : signs[i]) { // TODO: NPE
    90         g.setColor(layer.getColor());
    91         g.drawString(Character.toString(layer.getGlyph()), points[i].x - 25, points[i].y + 25);
     88      for (int j = 0; signs[i] != null && j < signs[i].getNumElements(); j++) {
     89        g.setColor(signs[i].getElement(j).getColor());
     90        g.drawString(Character.toString(signs[i].getElement(j).getGlyph()), points[i].x - 25, points[i].y + 25);
    9291      }
    9392    }
     
    10099        if (!((MapillaryImage) img).getSigns().isEmpty()) {
    101100          Point imgLoc = mv.getPoint(img.getLatLon());
    102           for (TrafficoSignElement e : TrafficoSign.getSign("de", ((MapillaryImage) img).getSigns().get(0))) {
    103             g.setColor(e.getColor());
    104             g.drawString(Character.toString(e.getGlyph()), imgLoc.x, imgLoc.y);
    105           }
     101          // TODO: Paint a sign from the image
    106102        }
    107103      }
  • applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/traffico/TrafficoSign.java

    r31988 r32066  
    66import java.io.InputStream;
    77import java.util.ArrayList;
    8 import java.util.HashMap;
    98import java.util.List;
    109import java.util.Map;
    1110import java.util.Set;
     11import java.util.TreeMap;
    1212
    1313import javax.json.Json;
     
    1717import org.openstreetmap.josm.Main;
    1818
     19/**
     20 * <p>
     21 * Representation of a traffico sign, which consists of a country code, a unique name and the individual
     22 * layers of the sign.
     23 * </p><p>
     24 * You can obtain a {@link TrafficoSign} via {@link #getSign(String, String)}. The first call to that method reads
     25 * all sign definition for the queried country from disk and holds them in memory for future access.
     26 * </p><p>
     27 * You can rely on the fact, that two instances of {@link TrafficoSign} with same {@link #getName()} and same
     28 * {@link #getCountry()} that were obtained via {@link #getSign(String, String)} will return <code>true</code> when
     29 * compared with <code>==</code>
     30 * </p>
     31 */
    1932public final class TrafficoSign {
    20   private static Map<String, Map<String, TrafficoSignElement[]>> signs = new HashMap<>();
     33  private static final String SIGN_DEFINITION_PATH = "/data/fonts/traffico/signs/%s.json";
     34  /**
     35   * The signs that are already created from the JSON source file
     36   */
     37  private static final Map<String, Map<String, TrafficoSign>> signs = new TreeMap<>();
    2138
    22   private TrafficoSign() {
    23     // private constructor to avoid instantiation
     39  private final String country;
     40  private final String name;
     41  private final TrafficoSignElement[] elements;
     42
     43  private TrafficoSign(TrafficoSignElement[] elements, String country, String name) {
     44    this.country = country;
     45    this.name = name;
     46    if (elements == null) {
     47      this.elements = new TrafficoSignElement[0];
     48    } else {
     49      this.elements = elements.clone();
     50    }
    2451  }
    2552
    26   public static TrafficoSignElement[] getSign(String country, String signName) {
    27     if (signs.get(country) == null) {
    28       Main.info("Reading signs for country ''{0}''.", country);
    29       try (
    30         InputStream countryStream = TrafficoSign.class
    31             .getResourceAsStream("/data/fonts/traffico/signs/" + country + ".json")) {
    32         if (countryStream == null) {
    33           return null;
    34         }
    35         JsonObject countrySigns = Json.createReader(countryStream).readObject();
    36         Set<String> countrySignNames = countrySigns.keySet();
    37         Main.info(
    38             countrySignNames.size() + " different signs are supported for ''{0}'' by the Mapillary-plugin .",
    39             country
     53  /**
     54   * @return the country of this sign
     55   */
     56  public String getCountry() {
     57    return country;
     58  }
     59
     60  /**
     61   * @return the name of the sign
     62   */
     63  public String getName() {
     64    return name;
     65  }
     66
     67  /**
     68   * @return the number of sign elements (=layers) of which this sign consists
     69   */
     70  public int getNumElements() {
     71    return elements.length;
     72  }
     73
     74  /**
     75   *
     76   * @param index the index which is assigned to the sign element in question
     77   * @return the sign element (=layer) with the given index
     78   * @throws ArrayIndexOutOfBoundsException if index >= {@link #getNumElements()} or index < 0
     79   */
     80  public TrafficoSignElement getElement(int index) {
     81    return elements[index];
     82  }
     83
     84  /**
     85   * <p>
     86   * Returns the sign associated with the given country and name or <code>null</code> if no such sign is available.
     87   * </p><p>
     88   * If you obtain two instances of {@link TrafficoSign} with this method that have the same country and name, you can
     89   * safely assume that a comparison of both objects with <code>==</code> will result in <code>true</code>.
     90   * </p>
     91   * @param country the country to which the sign belongs
     92   * @param signName the name of the sign (unique in a country)
     93   * @return the requested sign or <code>null</code> if this sign is unavailable
     94   */
     95  public static TrafficoSign getSign(String country, String signName) {
     96    synchronized (signs) {
     97      if (!signs.containsKey(country)) {
     98        buildSignsFromJsonDefinition(country);
     99      }
     100      if (signs.containsKey(country) && signs.get(country).containsKey(signName)) {
     101        return signs.get(country).get(signName);
     102      }
     103      return null;
     104    }
     105  }
     106
     107  private static void addSign(TrafficoSign sign) {
     108    synchronized (signs) {
     109      // Create Map for country if not already exists
     110      if (!signs.containsKey(sign.getCountry())) {
     111        signs.put(sign.getCountry(), new TreeMap<String, TrafficoSign>());
     112      }
     113      // Don't overwrite existing sign with same country-name-combination
     114      if (signs.get(sign.getCountry()).containsKey(sign.getName())) {
     115        Main.warn(
     116            "The sign {0}--{1} was found multiple times in the traffico sign-definitions.",
     117            sign.getName(), sign.getCountry()
    40118        );
    41         Map<String, TrafficoSignElement[]> countryMap = new HashMap<>();
    42         for (String name : countrySignNames) {
    43           JsonArray elements = countrySigns.getJsonObject(name).getJsonArray("elements");
    44 
    45           // TODO: Replace by an array when all types of sign elements (text!) are
    46           // supported
    47           List<TrafficoSignElement> layers = new ArrayList<>();
    48 
    49           for (int i = 0; i < elements.size(); i++) {
    50             Character glyph = TrafficoGlyph.getGlyph(elements.getJsonObject(i)
    51                 .getString("type"));
    52             if (glyph != null) {
    53               Color c;
    54               switch (elements.getJsonObject(i).getString("color").toLowerCase()) {
    55                 case "black":
    56                   c = Color.BLACK;
    57                   break;
    58                 case "red":
    59                   c = Color.RED;
    60                   break;
    61                 case "blue":
    62                   c = Color.BLUE;
    63                   break;
    64                 case "white":
    65                   c = Color.WHITE;
    66                   break;
    67                 case "green":
    68                   c = Color.GREEN;
    69                   break;
    70                 case "yellow":
    71                   c = Color.YELLOW;
    72                   break;
    73                 default:
    74                   c = Color.MAGENTA;
    75               }
    76               layers.add(new TrafficoSignElement(glyph, c));
    77             }
    78           }
    79           countryMap.put(name, layers.toArray(new TrafficoSignElement[layers.size()]));
    80         }
    81         signs.put(country, countryMap);
    82       } catch (IOException e) {
    83         Main.error(e);
     119      } else {
     120        signs.get(sign.getCountry()).put(sign.getName(), sign);
    84121      }
    85122    }
    86     if (signs.get(country).get(signName) != null) {
    87       return signs.get(country).get(signName);
     123  }
     124
     125  private static void buildSignsFromJsonDefinition(String country) {
     126    Main.info("Reading signs for country ''{0}''.", country);
     127    try (
     128      InputStream countryStream = TrafficoSign.class.getResourceAsStream(String.format(SIGN_DEFINITION_PATH, country))
     129    ) {
     130      if (countryStream == null) {
     131        return;
     132      }
     133      JsonObject countrySigns = Json.createReader(countryStream).readObject();
     134      Set<String> countrySignNames = countrySigns.keySet();
     135      Main.info(
     136          countrySignNames.size() + " different signs are supported for ''{0}'' by the Mapillary-plugin .",
     137          country
     138      );
     139
     140      // TODO: Replace by an array when all types of sign elements (text!) are supported
     141      List<TrafficoSignElement> signLayers = new ArrayList<>();
     142      for (String name : countrySignNames) {
     143        signLayers.clear();
     144        JsonArray elements = countrySigns.getJsonObject(name).getJsonArray("elements");
     145
     146        for (int i = 0; i < elements.size(); i++) {
     147          Character glyph = TrafficoGlyph.getGlyph(elements.getJsonObject(i).getString("type"));
     148          if (glyph != null) {
     149            Color c;
     150            switch (elements.getJsonObject(i).getString("color").toLowerCase()) {
     151              case "black":
     152                c = Color.BLACK;
     153                break;
     154              case "red":
     155                c = new Color(0xc1121c);
     156                break;
     157              case "blue":
     158                c = new Color(0x154889);
     159                break;
     160              case "white":
     161                c = Color.WHITE;
     162                break;
     163              case "green":
     164                c = new Color(0x008754);
     165                break;
     166              case "yellow":
     167                c = new Color(0xfecf33);
     168                break;
     169              default:
     170                c = Color.MAGENTA;
     171                break;
     172            }
     173            signLayers.add(new TrafficoSignElement(glyph, c));
     174          }
     175        }
     176        addSign(new TrafficoSign(signLayers.toArray(new TrafficoSignElement[signLayers.size()]), country, name));
     177      }
     178    } catch (IOException e) {
     179      Main.error(e);
    88180    }
    89     return null;
    90181  }
    91182}
  • applications/editors/josm/plugins/mapillary/test/unit/org/openstreetmap/josm/plugins/mapillary/traffico/TrafficoSignTest.java

    r31795 r32066  
    11package org.openstreetmap.josm.plugins.mapillary.traffico;
    22
    3 import static org.junit.Assert.assertArrayEquals;
    43import static org.junit.Assert.assertEquals;
    54import static org.junit.Assert.assertNotEquals;
    65
    76import org.junit.Test;
    8 import org.openstreetmap.josm.plugins.mapillary.utils.TestUtil;
    97
    108public class TrafficoSignTest {
    11 
    129  @Test
    1310  public void test() {
    14     assertArrayEquals(null, TrafficoSign.getSign("de", ""));
    15     TrafficoSignElement[] trafficSignals = TrafficoSign.getSign("de", "traffic-signals-ahead");
     11    assertEquals(null, TrafficoSign.getSign("de", ""));
     12    TrafficoSign trafficSignals = TrafficoSign.getSign("de", "traffic-signals-ahead");
    1613    assertNotEquals(null, trafficSignals);
    17     assertEquals(5, trafficSignals.length);
    18     assertArrayEquals(null, TrafficoSign.getSign("us", ""));
    19     assertArrayEquals(null, TrafficoSign.getSign("xyz", ""));
     14    assertEquals(5, trafficSignals.getNumElements());
     15    assertEquals(null, TrafficoSign.getSign("us", ""));
     16    assertEquals(null, TrafficoSign.getSign("xyz", ""));
    2017  }
    21 
    22   @Test
    23   public void testUtilityClass() {
    24     TestUtil.testUtilityClass(TrafficoSign.class);
    25   }
    26 
    2718}
Note: See TracChangeset for help on using the changeset viewer.