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 closed="yes" k="natural" v="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" />-->
</m>
@ -527,8 +528,8 @@
<area fill="#e8ecde" />
</m>
<m zoom-min="12">
<caption dy="18" fill="#000000" k="name" priority="5" size="19" stroke="#ffffff"
stroke-width="2.0" area-size="0.1"/>
<caption area-size="0.1" dy="18" fill="#000000" k="name" priority="5" size="19"
stroke="#ffffff" stroke-width="2.0" />
</m>
<m zoom-max="11">
<caption dy="18" fill="#000000" k="ref" priority="5" size="19" stroke="#ffffff"
@ -997,7 +998,7 @@
<!-- place -->
<m k="place">
<circle radius="5.0" fill="#ff0000"/>
<circle fill="#ff0000" radius="5.0" />
<m v="suburb" zoom-max="14">
<caption style="italic" fill="#606060" k="name" priority="4" size="17"
stroke="#ffffff" stroke-width="2.0" />

View File

@ -426,9 +426,9 @@ public class GeometryBuffer {
int n = index[0];
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;
}

View File

@ -1,5 +1,6 @@
/*
* Copyright 2012 Hannes Janetzek
* Copyright 2016 Andrey Novikov
*
* 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 PointF labelPosition;
/**
* 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 PointF labelPosition;
public MapElement() {
super(1024, 16);
}
@ -43,14 +44,14 @@ public class MapElement extends GeometryBuffer {
super(points, indices);
}
public void setLayer(int layer) {
this.layer = layer;
}
public void setLabelPosition(float x, float y) {
labelPosition = new PointF(x, y);
}
public void setLayer(int layer) {
this.layer = layer;
}
@Override
public MapElement clear() {
layer = 5;

View File

@ -86,7 +86,7 @@ public class LabelTileLoaderHook implements TileLoaderThemeHook {
PointF label = element.labelPosition;
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)
return false;

View File

@ -1,15 +1,14 @@
/**
* Copyright 2016 Andrey Novikov
* Java implementation of
* https://github.com/mapbox/polylabel
*
* Java implementation of https://github.com/mapbox/polylabel
* <p>
* ISC License
* Copyright (c) 2016 Mapbox
*
* <p>
* 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
* and this permission notice appear in all copies.
*
* <p>
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
* 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;
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.
*
* @param polygon polygon geometry
* @param precision calculation precision
* @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
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;
// 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
h = cell.h / 2;
@ -94,8 +98,7 @@ public class PolyLabel {
return new PointF(bestCell.x, bestCell.y);
}
private static class MaxComparator implements Comparator<Cell>
{
private static class MaxComparator implements Comparator<Cell> {
@Override
public int compare(Cell a, Cell b) {
return Float.compare(b.max, a.max);
@ -132,10 +135,10 @@ public class PolyLabel {
continue;
for (int i = 0, n = polygon.index[k], j = n - 2; i < n; j = i, i += 2) {
float ax = polygon.points[pos+i];
float ay = polygon.points[pos+i+1];
float bx = polygon.points[pos+j];
float by = polygon.points[pos+j+1];
float ax = polygon.points[pos + i];
float ay = polygon.points[pos + i + 1];
float bx = polygon.points[pos + j];
float by = polygon.points[pos + j + 1];
if (((ay > y) ^ (by > y)) &&
(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) {
float ax = polygon.points[i];
float ay = polygon.points[i+1];
float ay = polygon.points[i + 1];
float bx = polygon.points[j];
float by = polygon.points[j+1];
float by = polygon.points[j + 1];
float f = ax * by - bx * ay;
x += (ax + bx) * f;
y += (ay + by) * f;