use of uk.me.parabola.mkgmap.general.MapPoint in project mkgmap by openstreetmap.
the class Locator method findCityByIsIn.
private MapPoint findCityByIsIn(MapPoint place) {
if (locationAutofill.contains("is_in") == false) {
return null;
}
String isIn = place.getIsIn();
if (isIn == null) {
return null;
}
String[] cityList = isIn.split(",");
// Go through the isIn string and check if we find a city with this name
// Lets hope we find the next bigger city
double minDist = Double.MAX_VALUE;
Collection<MapPoint> nextCityList = null;
for (String cityCandidate : cityList) {
cityCandidate = cityCandidate.trim();
Collection<MapPoint> candidateCityList = cityMap.get(cityCandidate);
if (candidateCityList.isEmpty() == false) {
if (nextCityList == null) {
nextCityList = new ArrayList<MapPoint>(candidateCityList.size());
}
nextCityList.addAll(candidateCityList);
}
}
if (nextCityList == null) {
// no city name found in the is_in tag
return null;
}
MapPoint nearbyCity = null;
for (MapPoint nextCity : nextCityList) {
double dist = place.getLocation().distance(nextCity.getLocation());
if (dist < minDist) {
minDist = dist;
nearbyCity = nextCity;
}
}
// otherwise don't use it but issue a warning
if (minDist > MAX_CITY_DIST) {
log.warn("is_in of", place.getName(), "is far away from", nearbyCity.getName(), (minDist / 1000.0), "km is_in", place.getIsIn());
log.warn("Number of cities with this name:", nextCityList.size());
}
return nearbyCity;
}
use of uk.me.parabola.mkgmap.general.MapPoint in project mkgmap by openstreetmap.
the class MapArea method split.
/**
* Split this area into several pieces. All the map elements are reallocated
* to the appropriate subarea. Usually this instance would now be thrown
* away and the new sub areas used instead.
* <p>
* This code is dealing with a lot of factors that govern the splitting, eg:
* splitPolygonsIntoArea,
* tooSmallToDivide,
* item.minResolution vs. areaResolution,
* number/size of items and the limits of a subDivision,
* items that exceed maximum subDivision on their own,
* items that extend up to 50% outside the current area,
* items bigger than this.
*
* @param nx The number of pieces in the x (longitude) direction.
* @param ny The number of pieces in the y direction.
* @param bounds the bounding box that is used to create the areas.
* @param tooSmallToDivide the area is small and data overflows; split into overflow areas
*
* @return An array of the new MapArea's or null if can't split.
*/
public MapArea[] split(int nx, int ny, Area bounds, boolean tooSmallToDivide) {
int resolutionShift = MAX_RESOLUTION - areaResolution;
Area[] areas = bounds.split(nx, ny, resolutionShift);
if (areas == null) {
// Failed to split!
if (log.isDebugEnabled()) {
// see what is here
for (MapLine e : this.lines) if (e.getMinResolution() <= areaResolution)
log.debug("line. locn=", e.getPoints().get(0).toOSMURL(), " type=", uk.me.parabola.mkgmap.reader.osm.GType.formatType(e.getType()), " name=", e.getName(), " min=", e.getMinResolution(), " max=", e.getMaxResolution());
for (MapShape e : this.shapes) if (e.getMinResolution() <= areaResolution)
log.debug("shape. locn=", e.getPoints().get(0).toOSMURL(), " type=", uk.me.parabola.mkgmap.reader.osm.GType.formatType(e.getType()), " name=", e.getName(), " min=", e.getMinResolution(), " max=", e.getMaxResolution(), " full=", e.getFullArea(), " calc=", uk.me.parabola.mkgmap.filters.ShapeMergeFilter.calcAreaSizeTestVal(e.getPoints()));
// the main culprits are lots of bits of sea and coastline in an overview map (res 12)
}
return null;
}
MapArea[] mapAreas = new MapArea[nx * ny];
log.info("Splitting area " + bounds + " into " + nx + "x" + ny + " pieces at resolution " + areaResolution, tooSmallToDivide);
List<MapArea> addedAreas = new ArrayList<>();
for (int i = 0; i < mapAreas.length; i++) {
mapAreas[i] = new MapArea(areas[i], areaResolution, splitPolygonsIntoArea);
if (log.isDebugEnabled())
log.debug("area before", mapAreas[i].getBounds());
}
int xbaseHp = areas[0].getMinLong() << Coord.DELTA_SHIFT;
int ybaseHp = areas[0].getMinLat() << Coord.DELTA_SHIFT;
int dxHp = areas[0].getWidth() << Coord.DELTA_SHIFT;
int dyHp = areas[0].getHeight() << Coord.DELTA_SHIFT;
// Some of the work done by PolygonSubdivSizeSplitterFilter now done here
final int maxSize = Math.min((1 << 24) - 1, Math.max(MapSplitter.MAX_DIVISION_SIZE << (MAX_RESOLUTION - areaResolution), 0x8000));
/**
* These constants control when an item (shape unless splitPolygonsIntoArea or line) is shifted into its own MapArea/SubDivision.
* Generally, an item is allowed into the MapArea chosen by centre provided it is no bigger than the MapArea.
* This means that there could be big items near the edges of the MapArea that stick out by almost half, so must
* ensure that this doesn't cause the mapArea to exceed subDivision size limits.
* When the MapArea get small, we don't want to shift lots if items into their own areas;
* The *2 of LARGE_OBJECT_DIM is to keep to the same behaviour as earlier versions.
*/
final int maxWidth = Math.max(Math.min(areas[0].getWidth(), maxSize / 2), LARGE_OBJECT_DIM * 2);
final int maxHeight = Math.max(Math.min(areas[0].getHeight(), maxSize / 2), LARGE_OBJECT_DIM * 2);
// and don't have a good tooSmallToDivide strategy when not splitPolygonsIntoArea.
if (tooSmallToDivide) {
distShapesIntoNewAreas(addedAreas, mapAreas[0]);
} else {
for (MapShape e : this.shapes) {
Area shapeBounds = e.getBounds();
if (splitPolygonsIntoArea || shapeBounds.getMaxDimension() > maxSize) {
splitIntoAreas(mapAreas, e);
continue;
}
int areaIndex = pickArea(mapAreas, e, xbaseHp, ybaseHp, nx, ny, dxHp, dyHp);
if ((shapeBounds.getHeight() > maxHeight || shapeBounds.getWidth() > maxWidth) && !areas[areaIndex].contains(shapeBounds)) {
// use splitIntoAreas to deal with overflow
MapArea largeObjectArea = new MapArea(shapeBounds, areaResolution, true);
largeObjectArea.addShape(e);
addedAreas.add(largeObjectArea);
continue;
}
mapAreas[areaIndex].addShape(e);
}
}
if (tooSmallToDivide) {
distPointsIntoNewAreas(addedAreas, mapAreas[0]);
} else {
for (MapPoint p : this.points) {
int areaIndex = pickArea(mapAreas, p, xbaseHp, ybaseHp, nx, ny, dxHp, dyHp);
mapAreas[areaIndex].addPoint(p);
}
}
if (tooSmallToDivide) {
distLinesIntoNewAreas(addedAreas, mapAreas[0]);
} else {
for (MapLine l : this.lines) {
// Drop any zero sized lines.
if (l instanceof MapRoad == false && l.getRect().height <= 0 && l.getRect().width <= 0)
continue;
Area lineBounds = l.getBounds();
int areaIndex = pickArea(mapAreas, l, xbaseHp, ybaseHp, nx, ny, dxHp, dyHp);
if ((lineBounds.getHeight() > maxHeight || lineBounds.getWidth() > maxWidth) && !areas[areaIndex].contains(lineBounds)) {
MapArea largeObjectArea = new MapArea(lineBounds, areaResolution, false);
largeObjectArea.addLine(l);
addedAreas.add(largeObjectArea);
continue;
}
mapAreas[areaIndex].addLine(l);
}
}
if (!addedAreas.isEmpty()) {
// combine list and array
int pos = mapAreas.length;
mapAreas = Arrays.copyOf(mapAreas, mapAreas.length + addedAreas.size());
for (MapArea ma : addedAreas) {
if (// distShapesIntoNewAreas etc didn't know how big it was going to be
ma.getBounds() == null)
// so set to bounds of all elements
ma.setBounds(ma.getFullBounds());
mapAreas[pos++] = ma;
}
}
return mapAreas;
}
use of uk.me.parabola.mkgmap.general.MapPoint in project mkgmap by openstreetmap.
the class MapBuilder method normalizeCountries.
/**
* Process the country names of all elements and normalize them
* so that one consistent country name is used for the same country
* instead of different spellings.
* @param src the source of elements
*/
private void normalizeCountries(MapDataSource src) {
for (MapPoint p : src.getPoints()) {
String countryStr = p.getCountry();
if (countryStr != null) {
countryStr = locator.normalizeCountry(countryStr);
p.setCountry(countryStr);
}
}
for (MapLine l : src.getLines()) {
String countryStr = l.getCountry();
if (countryStr != null) {
countryStr = locator.normalizeCountry(countryStr);
l.setCountry(countryStr);
}
}
// shapes do not have address information
// untag the following lines if this is wrong
// for (MapShape s : src.getShapes()) {
// String countryStr = s.getCountry();
// if (countryStr != null) {
// countryStr = locator.normalizeCountry(countryStr);
// s.setCountry(countryStr);
// }
// }
}
use of uk.me.parabola.mkgmap.general.MapPoint in project mkgmap by openstreetmap.
the class MapBuilder method makeSubdivision.
/**
* Make an individual subdivision for the map. To do this we need a link
* to its parent and the zoom level that we are working at.
*
* @param map The map to add this subdivision into.
* @param parent The parent division.
* @param ma The area of the map that we are fitting into this division.
* @param z The zoom level.
* @return The new subdivsion.
*/
private Subdivision makeSubdivision(Map map, Subdivision parent, MapArea ma, Zoom z) {
List<MapPoint> points = ma.getPoints();
List<MapLine> lines = ma.getLines();
List<MapShape> shapes = ma.getShapes();
Subdivision div = map.createSubdivision(parent, ma.getFullBounds(), z);
if (ma.hasPoints())
div.setHasPoints(true);
if (ma.hasIndPoints())
div.setHasIndPoints(true);
if (ma.hasLines())
div.setHasPolylines(true);
if (ma.hasShapes())
div.setHasPolygons(true);
div.startDivision();
processPoints(map, div, points);
processLines(map, div, lines);
processShapes(map, div, shapes);
div.endDivision();
return div;
}
use of uk.me.parabola.mkgmap.general.MapPoint in project mkgmap by openstreetmap.
the class MapBuilder method processCities.
/**
* Processing of Cities
*
* Fills the city list in lbl block that is required for find by name
* It also builds up information that is required to get address info
* for the POIs
*
* @param map The map.
* @param src The map data.
*/
private void processCities(Map map, MapDataSource src) {
LBLFile lbl = map.getLblFile();
if (locationAutofill.isEmpty() == false) {
// collect the names of the cities
for (MapPoint p : src.getPoints()) {
if (p.isCity() && p.getName() != null)
// Put the city info the map for missing info
locator.addCityOrPlace(p);
}
// Try to fill missing information that include search of next city
locator.autofillCities();
}
for (MapPoint p : src.getPoints()) {
if (p.isCity() && p.getName() != null) {
String countryStr = p.getCountry();
Country thisCountry;
if (countryStr != null) {
thisCountry = lbl.createCountry(countryStr, locator.getCountryISOCode(countryStr));
} else
thisCountry = getDefaultCountry();
String regionStr = p.getRegion();
Region thisRegion;
if (regionStr != null) {
thisRegion = lbl.createRegion(thisCountry, regionStr, null);
} else
thisRegion = getDefaultRegion(thisCountry);
City thisCity;
if (thisRegion != null)
thisCity = lbl.createCity(thisRegion, p.getName(), true);
else
thisCity = lbl.createCity(thisCountry, p.getName(), true);
cityMap.put(p, thisCity);
}
}
}
Aggregations