Polygon label position (minor improvements) (#204), #80

This commit is contained in:
Emux 2016-10-15 20:43:21 +03:00
parent ca841f5181
commit cbd0ac01df
5 changed files with 35 additions and 30 deletions

View File

@ -402,7 +402,8 @@
<m e="way"> <m e="way">
<m closed="yes" k="natural" v="water"> <m closed="yes" k="natural" v="water">
<area use="water" /> <area use="water" />
<caption k="name" fill="#777744" size="16" stroke="#aaffffff" stroke-width="2.0" area-size="0.4" /> <caption area-size="0.4" fill="#777744" k="name" size="16" stroke="#aaffffff"
stroke-width="2.0" />
<!--<line use="water:outline" />--> <!--<line use="water:outline" />-->
</m> </m>
@ -527,8 +528,8 @@
<area fill="#e8ecde" /> <area fill="#e8ecde" />
</m> </m>
<m zoom-min="12"> <m zoom-min="12">
<caption dy="18" fill="#000000" k="name" priority="5" size="19" stroke="#ffffff" <caption area-size="0.1" dy="18" fill="#000000" k="name" priority="5" size="19"
stroke-width="2.0" area-size="0.1"/> stroke="#ffffff" stroke-width="2.0" />
</m> </m>
<m zoom-max="11"> <m zoom-max="11">
<caption dy="18" fill="#000000" k="ref" priority="5" size="19" stroke="#ffffff" <caption dy="18" fill="#000000" k="ref" priority="5" size="19" stroke="#ffffff"
@ -997,7 +998,7 @@
<!-- place --> <!-- place -->
<m k="place"> <m k="place">
<circle radius="5.0" fill="#ff0000"/> <circle fill="#ff0000" radius="5.0" />
<m v="suburb" zoom-max="14"> <m v="suburb" zoom-max="14">
<caption style="italic" fill="#606060" k="name" priority="4" size="17" <caption style="italic" fill="#606060" k="name" priority="4" size="17"
stroke="#ffffff" stroke-width="2.0" /> stroke="#ffffff" stroke-width="2.0" />

View File

@ -426,9 +426,9 @@ public class GeometryBuffer {
int n = index[0]; int n = index[0];
for (int i = 0; i < n - 2; i += 2) { for (int i = 0; i < n - 2; i += 2) {
area = area + (points[i] * points[i+3]) - (points[i+1] * points[i+2]); area = area + (points[i] * points[i + 3]) - (points[i + 1] * points[i + 2]);
} }
area = area + (points[n-2] * points[1]) - (points[n-1] * points[0]); area = area + (points[n - 2] * points[1]) - (points[n - 1] * points[0]);
return 0.5f * area; return 0.5f * area;
} }

View File

@ -1,5 +1,6 @@
/* /*
* Copyright 2012 Hannes Janetzek * Copyright 2012 Hannes Janetzek
* Copyright 2016 Andrey Novikov
* *
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org). * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
* *
@ -26,6 +27,8 @@ package org.oscim.core;
*/ */
public class MapElement extends GeometryBuffer { public class MapElement extends GeometryBuffer {
public PointF labelPosition;
/** /**
* layer of the element (0-10) overrides the theme drawing order * layer of the element (0-10) overrides the theme drawing order
*/ */
@ -33,8 +36,6 @@ public class MapElement extends GeometryBuffer {
public final TagSet tags = new TagSet(); public final TagSet tags = new TagSet();
public PointF labelPosition;
public MapElement() { public MapElement() {
super(1024, 16); super(1024, 16);
} }
@ -43,14 +44,14 @@ public class MapElement extends GeometryBuffer {
super(points, indices); super(points, indices);
} }
public void setLayer(int layer) {
this.layer = layer;
}
public void setLabelPosition(float x, float y) { public void setLabelPosition(float x, float y) {
labelPosition = new PointF(x, y); labelPosition = new PointF(x, y);
} }
public void setLayer(int layer) {
this.layer = layer;
}
@Override @Override
public MapElement clear() { public MapElement clear() {
layer = 5; layer = 5;

View File

@ -86,7 +86,7 @@ public class LabelTileLoaderHook implements TileLoaderThemeHook {
PointF label = element.labelPosition; PointF label = element.labelPosition;
if (label == null) if (label == null)
label = PolyLabel.get(element, 5f); label = PolyLabel.get(element);
if (label.x < 0 || label.x > Tile.SIZE || label.y < 0 || label.y > Tile.SIZE) if (label.x < 0 || label.x > Tile.SIZE || label.y < 0 || label.y > Tile.SIZE)
return false; return false;

View File

@ -1,15 +1,14 @@
/** /**
* Copyright 2016 Andrey Novikov * Copyright 2016 Andrey Novikov
* Java implementation of * Java implementation of https://github.com/mapbox/polylabel
* https://github.com/mapbox/polylabel * <p>
*
* ISC License * ISC License
* Copyright (c) 2016 Mapbox * Copyright (c) 2016 Mapbox
* * <p>
* Permission to use, copy, modify, and/or distribute this software for any purpose * Permission to use, copy, modify, and/or distribute this software for any purpose
* with or without fee is hereby granted, provided that the above copyright notice * with or without fee is hereby granted, provided that the above copyright notice
* and this permission notice appear in all copies. * and this permission notice appear in all copies.
* * <p>
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. * THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
* IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR * IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
@ -27,15 +26,20 @@ import java.util.Comparator;
import java.util.PriorityQueue; import java.util.PriorityQueue;
public class PolyLabel { public class PolyLabel {
private static float SQRT2 = (float) Math.sqrt(2); /**
* Calculation precision.
*/
public static float PRECISION = 5f;
private static final float SQRT2 = (float) Math.sqrt(2);
/** /**
* Returns pole of inaccessibility, the most distant internal point from the polygon outline. * Returns pole of inaccessibility, the most distant internal point from the polygon outline.
*
* @param polygon polygon geometry * @param polygon polygon geometry
* @param precision calculation precision
* @return optimal label placement point * @return optimal label placement point
*/ */
public static PointF get(GeometryBuffer polygon, float precision) { public static PointF get(GeometryBuffer polygon) {
// find the bounding box of the outer ring // find the bounding box of the outer ring
float minX = Float.MAX_VALUE, minY = Float.MAX_VALUE, maxX = Float.MIN_VALUE, maxY = Float.MIN_VALUE; float minX = Float.MAX_VALUE, minY = Float.MAX_VALUE, maxX = Float.MIN_VALUE, maxY = Float.MIN_VALUE;
@ -81,7 +85,7 @@ public class PolyLabel {
bestCell = cell; bestCell = cell;
// do not drill down further if there's no chance of a better solution // do not drill down further if there's no chance of a better solution
if (cell.max - bestCell.d <= precision) continue; if (cell.max - bestCell.d <= PRECISION) continue;
// split the cell into four cells // split the cell into four cells
h = cell.h / 2; h = cell.h / 2;
@ -94,8 +98,7 @@ public class PolyLabel {
return new PointF(bestCell.x, bestCell.y); return new PointF(bestCell.x, bestCell.y);
} }
private static class MaxComparator implements Comparator<Cell> private static class MaxComparator implements Comparator<Cell> {
{
@Override @Override
public int compare(Cell a, Cell b) { public int compare(Cell a, Cell b) {
return Float.compare(b.max, a.max); return Float.compare(b.max, a.max);
@ -132,10 +135,10 @@ public class PolyLabel {
continue; continue;
for (int i = 0, n = polygon.index[k], j = n - 2; i < n; j = i, i += 2) { for (int i = 0, n = polygon.index[k], j = n - 2; i < n; j = i, i += 2) {
float ax = polygon.points[pos+i]; float ax = polygon.points[pos + i];
float ay = polygon.points[pos+i+1]; float ay = polygon.points[pos + i + 1];
float bx = polygon.points[pos+j]; float bx = polygon.points[pos + j];
float by = polygon.points[pos+j+1]; float by = polygon.points[pos + j + 1];
if (((ay > y) ^ (by > y)) && if (((ay > y) ^ (by > y)) &&
(x < (bx - ax) * (y - ay) / (by - ay) + ax)) inside = !inside; (x < (bx - ax) * (y - ay) / (by - ay) + ax)) inside = !inside;
@ -157,9 +160,9 @@ public class PolyLabel {
for (int i = 0, n = polygon.index[0], j = n - 2; i < n; j = i, i += 2) { for (int i = 0, n = polygon.index[0], j = n - 2; i < n; j = i, i += 2) {
float ax = polygon.points[i]; float ax = polygon.points[i];
float ay = polygon.points[i+1]; float ay = polygon.points[i + 1];
float bx = polygon.points[j]; float bx = polygon.points[j];
float by = polygon.points[j+1]; float by = polygon.points[j + 1];
float f = ax * by - bx * ay; float f = ax * by - bx * ay;
x += (ax + bx) * f; x += (ax + bx) * f;
y += (ay + by) * f; y += (ay + by) * f;