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