package net.osmand.binary; import gnu.trove.list.array.TIntArrayList; import gnu.trove.map.hash.TIntObjectHashMap; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.Map; import net.osmand.binary.BinaryMapIndexReader.MapIndex; import net.osmand.binary.BinaryMapIndexReader.TagValuePair; import net.osmand.render.RenderingRulesStorage; import net.osmand.util.Algorithms; public class BinaryMapDataObject { protected int[] coordinates = null; protected int[][] polygonInnerCoordinates = null; protected boolean area = false; protected int[] types = null; protected int[] additionalTypes = null; protected int objectType = RenderingRulesStorage.POINT_RULES; protected int labelX; protected int labelY; protected TIntObjectHashMap objectNames = null; protected TIntArrayList namesOrder = null; protected long id = 0; protected MapIndex mapIndex = null; public BinaryMapDataObject(){ } public BinaryMapDataObject(long id, int[] coordinates, int[][] polygonInnerCoordinates, int objectType, boolean area, int[] types, int[] additionalTypes, int labelX, int labelY){ this.polygonInnerCoordinates = polygonInnerCoordinates; this.coordinates = coordinates; this.additionalTypes = additionalTypes; this.types = types; this.id = id; this.objectType = objectType; this.area = area; this.labelX = labelX; this.labelY = labelY; } protected void setCoordinates(int[] coordinates) { this.coordinates = coordinates; } public String getName(){ if(objectNames == null){ return ""; } String name = objectNames.get(mapIndex.nameEncodingType); if(name == null){ return ""; } return name; } public TIntObjectHashMap getObjectNames() { return objectNames; } public Map getOrderedObjectNames() { if (namesOrder == null) { return null; } LinkedHashMap lm = new LinkedHashMap (); for (int i = 0; i < namesOrder.size(); i++) { int nm = namesOrder.get(i); lm.put(nm, objectNames.get(nm)); } return lm; } public void putObjectName(int type, String name){ if(objectNames == null){ objectNames = new TIntObjectHashMap(); namesOrder = new TIntArrayList(); } objectNames.put(type, name); namesOrder.add(type); } public int[][] getPolygonInnerCoordinates() { return polygonInnerCoordinates; } public int[] getTypes(){ return types; } public boolean containsType(int cachedType) { if(cachedType != -1) { for(int i=0; i>7 return false; } private static boolean compareCoordinates(int[] coordinates, int[] coordinates2, int precision) { if(precision == 0) { return Arrays.equals(coordinates, coordinates2); } TIntArrayList cd = simplify(coordinates, precision); TIntArrayList cd2 = simplify(coordinates2, precision); return cd.equals(cd2); } private static TIntArrayList simplify(int[] c, int precision) { int len = c.length / 2; TIntArrayList lt = new TIntArrayList(len * 3); for (int i = 0; i < len; i++) { lt.add(0); lt.add(c[i * 2]); lt.add(c[i * 2 + 1]); } lt.set(0, 1); lt.set((len - 1) * 3, 1); simplifyLine(lt, precision, 0, len - 1); TIntArrayList res = new TIntArrayList(len * 2); for (int i = 0; i < len; i++) { if (lt.get(i * 3) == 1) { res.add(lt.get(i * 3 + 1)); res.add(lt.get(i * 3 + 2)); } } return res; } private static double orthogonalDistance(int x, int y, int x1, int y1, int x2, int y2) { long A = (x - x1); long B = (y - y1); long C = (x2 - x1); long D = (y2 - y1); return Math.abs(A * D - C * B) / Math.sqrt(C * C + D * D); } private static void simplifyLine(TIntArrayList lt, int precision, int start, int end) { if(start == end - 1) { return; } int x = lt.get(start*3 + 1); int y = lt.get(start*3 + 2); int ex = lt.get(end*3 + 1); int ey = lt.get(end*3 + 2); double max = 0; int maxK = -1; for(int k = start + 1; k < end ; k++) { double ld = orthogonalDistance(lt.get(k*3 + 1), lt.get(k*3 + 2), x, y, ex, ey); if(maxK == -1 || max < ld) { maxK = k; max = ld; } } if(max < precision) { return; } lt.set(maxK*3, 1); // keep point simplifyLine(lt, precision, start, maxK); simplifyLine(lt, precision, maxK, end); } public int[] getCoordinates() { return coordinates; } public int getObjectType() { return objectType; } public int[] getLabelCoordinates() { return labelCoordinates; } }