    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}