private SubArea(int i, /*@Nonnull*/ Territory territory, /*@Nullable*/ SubArea territoryBounds) { minMaxSetup(i); parentTerritory = territory; subAreaID = i; boundedLonRange = new List <Range <int> >(); boundedLatRange = new List <Range <int> >(); // Mapcode areas are inclusive for the minimum bounds and exclusive for the maximum bounds // Trim max by 1, to address boundary cases. Range <int> trimmedLonRange = trimRange(lonRange); Range <int> trimmedLatRange = latRange; // Special handling for latitude +90.0 which should not be trimmed, in order to produce // mapcode AAA Z0000.010G for lat: 90.0 lon:180.0. if (latRange.getMax() != 90000000) { trimmedLatRange = trimRange(latRange); } List <Range <int> > normalisedLonRange = normaliseRange(trimmedLonRange, lonBoundingRange); List <Range <int> > normalisedLatRange = normaliseRange(trimmedLatRange, latBoundingRange); if (territoryBounds == null) { boundedLonRange = normalisedLonRange; boundedLatRange = normalisedLatRange; } else { foreach (Range <int> normalisedRange in normalisedLonRange) { List <Range <int> > boundedRange = normalisedRange.constrain(territoryBounds.boundedLonRange); if (boundedRange != null) { boundedLonRange.AddRange(boundedRange); } } foreach (Range <int> normalisedRange in normalisedLatRange) { List <Range <int> > boundedRange = normalisedRange.constrain(territoryBounds.boundedLatRange); if (boundedRange != null) { boundedLatRange.AddRange(boundedRange); } } } }
private SubArea(int i, /*@Nonnull*/ Territory territory, /*@Nullable*/ SubArea territoryBounds) { minMaxSetup(i); parentTerritory = territory; subAreaID = i; boundedLonRange = new List<Range<int>>(); boundedLatRange = new List<Range<int>>(); // Mapcode areas are inclusive for the minimum bounds and exclusive for the maximum bounds // Trim max by 1, to address boundary cases. Range<int> trimmedLonRange = trimRange(lonRange); Range<int> trimmedLatRange = latRange; // Special handling for latitude +90.0 which should not be trimmed, in order to produce // mapcode AAA Z0000.010G for lat: 90.0 lon:180.0. if (latRange.getMax() != 90000000) { trimmedLatRange = trimRange(latRange); } List<Range<int>> normalisedLonRange = normaliseRange(trimmedLonRange, lonBoundingRange); List<Range<int>> normalisedLatRange = normaliseRange(trimmedLatRange, latBoundingRange); if (territoryBounds == null) { boundedLonRange = normalisedLonRange; boundedLatRange = normalisedLatRange; } else { foreach (Range<int> normalisedRange in normalisedLonRange) { List<Range<int>> boundedRange = normalisedRange.constrain(territoryBounds.boundedLonRange); if (boundedRange != null) { boundedLonRange.AddRange(boundedRange); } } foreach (Range<int> normalisedRange in normalisedLatRange) { List<Range<int>> boundedRange = normalisedRange.constrain(territoryBounds.boundedLatRange); if (boundedRange != null) { boundedLatRange.AddRange(boundedRange); } } } }
/*@Nonnull*/ public SubArea extendBounds(int xExtension, int yExtension) { SubArea result = new SubArea(); result.latRange = new Range<int>(this.getMinY() - yExtension, getMaxY() + yExtension); result.lonRange = new Range<int>(this.getMinX() - xExtension, getMaxX() + xExtension); return result; }
public void dataSetup(int i) { flags = DataAccess.DataFlags(i); codexHi = CalcCodexHi(flags); codexLo = CalcCodexLo(flags); codexLen = CalcCodexLen(codexHi, codexLo); codex = CalcCodex(codexHi, codexLo); nameless = GetIsNameless(i); useless = (flags & 512) != 0; specialShape = GetIsSpecialShape(i); pipeType = (flags >> 5) & 12; // 4=pipe 8=plus 12=star if (pipeType == 4) { pipeLetter = (ENCODE_CHARS[(flags >> 11) & 31]).ToString(); } else { pipeLetter = string.Empty; } if ((codex == 21) && !nameless) { codex++; codexLo++; codexLen++; } starPipe = CalcStarPipe(i); mapcoderRect = SubArea.GetArea(i); initialized = true; }
/*@Nonnull*/ static Point decode(/*@Nonnull*/ string argMapcode, /*@Nonnull*/ Territory argTerritory) // throws UnknownMapcodeException { Trace.TraceInformation("decode: mapcode={0}, territory={1}", argMapcode, argTerritory.ToString()); // JAVA name() string mapcode = argMapcode; Territory territory = argTerritory; // In case of error, result.isDefined() is false. Point result = Point.undefined(); string extrapostfix = string.Empty; int minpos = mapcode.IndexOf('-'); if (minpos > 0) { extrapostfix = mapcode.Substring(minpos + 1).Trim(); if (extrapostfix.Contains("Z")) { throw new UnknownMapcodeException("Invalid character Z"); } mapcode = mapcode.Substring(0, minpos); } mapcode = aeuUnpack(mapcode).Trim(); if (string.IsNullOrEmpty(mapcode)) { return(result); // failed to decode! } int incodexlen = mapcode.Length - 1; // *** long codes in states are handled by the country if (incodexlen >= 9) { territory = Territory.territories[Territory.Territories.AAA]; } else { Territory parentTerritory = territory.getParentTerritory(); if (incodexlen >= 8 && (parentTerritory == Territory.territories[Territory.Territories.USA] || parentTerritory == Territory.territories[Territory.Territories.CAN] || parentTerritory == Territory.territories[Territory.Territories.AUS] || parentTerritory == Territory.territories[Territory.Territories.BRA] || parentTerritory == Territory.territories[Territory.Territories.CHN] || parentTerritory == Territory.territories[Territory.Territories.RUS]) || incodexlen >= 7 && (parentTerritory == Territory.territories[Territory.Territories.IND] || parentTerritory == Territory.territories[Territory.Territories.MEX])) { territory = parentTerritory; } } int ccode = territory.getTerritoryCode(); int from = DataAccess.DataFirstRecord(ccode); if (DataAccess.DataFlags(from) == 0) { return(Point.undefined()); // this territory is not in the current data } int upto = DataAccess.DataLastRecord(ccode); int incodexhi = mapcode.IndexOf('.'); Data mapcoderData = new Data(); for (int i = from; i <= upto; i++) { mapcoderData.dataSetup(i); if (mapcoderData.PipeType == 0 && !mapcoderData.IsNameless && mapcoderData.CodexLen == incodexlen && mapcoderData.CodexHi == incodexhi) { result = decodeGrid(mapcode, mapcoderData.MapcoderRect.getMinX(), mapcoderData.MapcoderRect .getMinY(), mapcoderData.MapcoderRect.getMaxX(), mapcoderData.MapcoderRect.getMaxY(), i, extrapostfix); // RESTRICTUSELESS if (mapcoderData.IsUseless && result.isDefined()) { bool fitssomewhere = false; int j; for (j = upto - 1; j >= from; j--) // look in previous // rects { mapcoderData.dataSetup(j); if (mapcoderData.IsUseless) { continue; } int xdiv8 = Common.XDivider(mapcoderData.MapcoderRect.getMinY(), mapcoderData.MapcoderRect.getMaxY()) / 4; if (mapcoderData.MapcoderRect.extendBounds(xdiv8, 60).containsPoint(result)) { fitssomewhere = true; break; } } if (!fitssomewhere) { result.setUndefined(); } } break; } else if (mapcoderData.PipeType == 4 && mapcoderData.CodexLen + 1 == incodexlen && mapcoderData.CodexHi + 1 == incodexhi && mapcoderData.PipeLetter[0] == mapcode[0]) { result = decodeGrid(mapcode.Substring(1), mapcoderData.MapcoderRect.getMinX(), mapcoderData .MapcoderRect.getMinY(), mapcoderData.MapcoderRect.getMaxX(), mapcoderData .MapcoderRect.getMaxY(), i, extrapostfix); break; } else if (mapcoderData.IsNameless && (mapcoderData.Codex == 21 && incodexlen == 4 && incodexhi == 2 || mapcoderData.Codex == 22 && incodexlen == 5 && incodexhi == 3 || mapcoderData.Codex == 13 && incodexlen == 5 && incodexhi == 2)) { result = decodeNameless(mapcode, i, extrapostfix, mapcoderData); break; } else if (mapcoderData.PipeType > 4 && incodexlen == incodexhi + 3 && mapcoderData.CodexLen + 1 == incodexlen) { result = decodeStarpipe(mapcode, i, extrapostfix, mapcoderData); break; } } if (result.isDefined()) { if (result.getLonMicroDeg() > 180000000) { result = Point.fromMicroDeg(result.getLatMicroDeg(), result.getLonMicroDeg() - 360000000); } else if (result.getLonMicroDeg() < -180000000) { result = Point.fromMicroDeg(result.getLatMicroDeg(), result.getLonMicroDeg() + 360000000); } // LIMIT_TO_OUTRECT : make sure it fits the country if (ccode != CCODE_EARTH) { SubArea mapcoderRect = SubArea.GetArea(upto); // find // encompassing // rect int xdiv8 = Common.XDivider(mapcoderRect.getMinY(), mapcoderRect.getMaxY()) / 4; // should be /8 but there's some extra margin if (!mapcoderRect.extendBounds(xdiv8, 60).containsPoint(result)) { result.setUndefined(); // decodes outside the official territory // limit } } } Trace.TraceInformation("decode: result=({0}, {1})", result.isDefined() ? result.getLatDeg() : Double.NaN, result.isDefined() ? result.getLonDeg() : Double.NaN); result = Point.restrictLatLon(result); return(result); }