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