001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.plugins.streetside.cubemap; 003 004import java.text.MessageFormat; 005import java.util.HashMap; 006import java.util.Map; 007import java.util.stream.Stream; 008 009import org.apache.log4j.Logger; 010import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties; 011 012public class CubemapUtils { 013 014 final static Logger logger = Logger.getLogger(CubemapUtils.class); 015 016 private CubemapUtils() { 017 // Private constructor to avoid instantiation 018 } 019 020 public enum CubefaceType { 021 ONE(1), 022 FOUR(4), 023 SIXTEEN(16); 024 025 private final int value; 026 private static Map<Integer, CubefaceType> map = new HashMap<>(); 027 028 private CubefaceType(int value) { 029 this.value = value; 030 } 031 032 static { 033 for (CubefaceType cubefaceType : CubefaceType.values()) { 034 map.put(cubefaceType.value, cubefaceType); 035 } 036 } 037 038 public static CubefaceType valueOf(int cubefaceType) { 039 return map.get(cubefaceType); 040 } 041 042 public int getValue() { 043 return value; 044 } 045 } 046 047 public static enum CubemapFaces { 048 FRONT("01"), 049 RIGHT("02"), 050 BACK("03"), 051 LEFT("10"), 052 UP("11"), 053 DOWN("12"); 054 055 public static Stream<CubemapFaces> stream() { 056 return Stream.of(CubemapFaces.values()); 057 } 058 059 private final String value; 060 061 CubemapFaces(String value) { 062 this.value = value; 063 } 064 065 public String getValue() { 066 return value; 067 } 068 } 069 070 public static Map<String[],String> directionConversion = new HashMap<>(); 071 072 // numerical base for decimal conversion (quaternary in the case of Streetside) 073 private static final int NUM_BASE = 4; 074 public static final String TEST_IMAGE_ID = "00000000"; 075 public static final int NUM_SIDES = 6; 076 public static Map<String,String> rowCol2StreetsideCellAddressMap = null; 077 078 // Intialize utility map for storing row to Streetside cell number conversions 079 static { 080 081 CubemapUtils.rowCol2StreetsideCellAddressMap = new HashMap<>(); 082 CubemapUtils.rowCol2StreetsideCellAddressMap.put("00","00"); 083 CubemapUtils.rowCol2StreetsideCellAddressMap.put("01","01"); 084 CubemapUtils.rowCol2StreetsideCellAddressMap.put("02","10"); 085 CubemapUtils.rowCol2StreetsideCellAddressMap.put("03","11"); 086 CubemapUtils.rowCol2StreetsideCellAddressMap.put("10","02"); 087 CubemapUtils.rowCol2StreetsideCellAddressMap.put("11","03"); 088 CubemapUtils.rowCol2StreetsideCellAddressMap.put("12","12"); 089 CubemapUtils.rowCol2StreetsideCellAddressMap.put("13","13"); 090 CubemapUtils.rowCol2StreetsideCellAddressMap.put("20","20"); 091 CubemapUtils.rowCol2StreetsideCellAddressMap.put("21","21"); 092 CubemapUtils.rowCol2StreetsideCellAddressMap.put("22","30"); 093 CubemapUtils.rowCol2StreetsideCellAddressMap.put("23","31"); 094 CubemapUtils.rowCol2StreetsideCellAddressMap.put("30","22"); 095 CubemapUtils.rowCol2StreetsideCellAddressMap.put("31","23"); 096 CubemapUtils.rowCol2StreetsideCellAddressMap.put("32","32"); 097 CubemapUtils.rowCol2StreetsideCellAddressMap.put("33","33"); 098 } 099 100 public static int getMaxCols() { 101 return StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?4:2; 102 } 103 104 public static int getMaxRows() { 105 return getMaxCols(); 106 } 107 108 public static String convertDecimal2Quaternary(long inputNum) { 109 String res = null; 110 final StringBuilder sb = new StringBuilder(); 111 112 if (StreetsideProperties.DEBUGING_ENABLED.get()) { 113 logger.debug(MessageFormat.format("convertDecimal2Quaternary input: {0}", Long.toString(inputNum))); 114 } 115 116 while (inputNum > 0) { 117 sb.append(inputNum % CubemapUtils.NUM_BASE); 118 inputNum /= CubemapUtils.NUM_BASE; 119 } 120 121 res = sb.reverse().toString(); 122 123 if (StreetsideProperties.DEBUGING_ENABLED.get()) { 124 logger.debug(MessageFormat.format("convertDecimal2Quaternary output: {0}", res)); 125 } 126 127 return res; 128 } 129 130 public static String convertQuaternary2Decimal(String inputNum) { 131 132 final String res; 133 134 if (StreetsideProperties.DEBUGING_ENABLED.get()) { 135 logger.debug(MessageFormat.format("convertQuaternary2Decimal input: {0}", inputNum)); 136 } 137 138 int len = inputNum.length(); 139 int power = 1; 140 int num = 0; 141 int i; 142 143 for (i = len - 1; i >= 0; i--) 144 { 145 if (Integer.parseInt(inputNum.substring(i,i+1)) >= CubemapUtils.NUM_BASE) 146 { 147 logger.error("Error converting quadkey " + inputNum + " to decimal."); 148 return "000000000"; 149 } 150 151 num += Integer.parseInt(inputNum.substring(i,i+1)) * power; 152 power = power * CubemapUtils.NUM_BASE; 153 } 154 155 res = Integer.toString(num); 156 157 if (StreetsideProperties.DEBUGING_ENABLED.get()) { 158 logger.debug(MessageFormat.format("convertQuaternary2Decimal output: {0}", res)); 159 } 160 161 return res; 162 } 163 164 public static String getFaceNumberForCount(int count) { 165 final String res; 166 167 switch (count) { 168 case 0: 169 res = CubemapFaces.FRONT.getValue(); 170 break; 171 case 1: 172 res = CubemapFaces.RIGHT.getValue(); 173 break; 174 case 2: 175 res = CubemapFaces.BACK.getValue(); 176 break; 177 case 3: 178 res = CubemapFaces.LEFT.getValue(); 179 break; 180 case 4: 181 res = CubemapFaces.UP.getValue(); 182 break; 183 case 5: 184 res = CubemapFaces.DOWN.getValue(); 185 break; 186 default: 187 res = null; 188 break; 189 } 190 return res; 191 } 192 193 public static int getTileWidth() { 194 // 4-tiled cubemap imagery has a 2-pixel overlap; 16-tiled has a 1-pixel 195 // overlap 196 if (!StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) { 197 return 255; 198 } else { 199 return 254; 200 } 201 } 202 203 public static int getTileHeight() { 204 // 4-tiled cubemap imagery has a 2-pixel overlap; 16-tiled has a 1-pixel 205 // overlap 206 if(!StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) { 207 return 255; 208 } else { 209 return 254; 210 } 211 } 212 213 public static int getCount4FaceNumber(String faceString) { 214 215 final int tileAddress; 216 217 switch (faceString) { 218 // back 219 case "03": tileAddress = 0; 220 break; 221 // down 222 case "12": tileAddress = 1; 223 break; 224 // front 225 case "01": tileAddress = 2; 226 break; 227 // left 228 case "10": tileAddress = 3; 229 break; 230 // right 231 case "02": tileAddress = 4; 232 break; 233 // up 234 case "11": tileAddress = 5; 235 break; 236 default: tileAddress = 6; 237 break; 238 } 239 240 return tileAddress; 241 } 242 243 public static String getFaceIdFromTileId(String tileId) { 244 // magic numbers - the face id is contained in the 16th and 17th positions 245 return tileId.substring(16, 18); 246 } 247 248 public static String convertDoubleCountNrto16TileNr(String countNr) { 249 String tileAddress; 250 251 switch (countNr) { 252 case "00": tileAddress = "00"; 253 break; 254 case "01": tileAddress = "01"; 255 break; 256 case "02": tileAddress = "10"; 257 break; 258 case "03": tileAddress = "11"; 259 break; 260 case "10": tileAddress = "02"; 261 break; 262 case "11": tileAddress = "03"; 263 break; 264 case "12": tileAddress = "12"; 265 break; 266 case "13": tileAddress = "13"; 267 break; 268 case "20": tileAddress = "20"; 269 break; 270 case "21": tileAddress = "21"; 271 break; 272 case "22": tileAddress = "30"; 273 break; 274 case "23": tileAddress = "31"; 275 break; 276 case "30": tileAddress = "22"; 277 break; 278 case "31": tileAddress = "23"; 279 break; 280 case "32": tileAddress = "32"; 281 break; 282 case "33": tileAddress = "33"; 283 break; 284 // shouldn't happen 285 default: tileAddress = null; 286 break; 287 } 288 289 return tileAddress; 290 } 291}