/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2016, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/
package org.geotools.polylabel;
import java.util.logging.Level;
import org.geotools.geometry.jts.GeometryBuilder;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.operation.distance.DistanceOp;
/**
* Based on Vladimir Agafonkin's Algorithm https://www.mapbox.com/blog/polygon-center/
*
* Implementation of quadtree cells for "Pole of inaccessibility".
*
* @author Ian Turton
* @author Casper Børgesen
*
*/
public class Cell implements Comparable<Cell> {
static final private GeometryBuilder gb = new GeometryBuilder();
private static final double SQRT2 = 1.4142135623730951;
private double x;
private double y;
private double h;
private double d;
private double max;
Cell(double x, double y, double h, MultiPolygon polygon) {
this.setX(x); // cell center x
this.setY(y); // cell center y
this.setH(h); // half the cell size
Point p = gb.point(x, y);
// distance from cell center to polygon
this.setD(pointToPolygonDist(p, polygon));
// max distance to polygon within a cell
this.setMax(this.getD() + this.getH() * SQRT2);
}
@Override
public int compareTo(Cell o) {
return (int) (o.getMax() - getMax());
}
public Point getPoint() {
return gb.point(x, y);
}
// signed distance from point to polygon outline (negative if point is
// outside)
private double pointToPolygonDist(Point point, MultiPolygon polygon) {
boolean inside = polygon.contains(point);
double dist = DistanceOp.distance(point, polygon.getBoundary());
// Points outside has a negative distance and thus will be weighted down later.
return (inside ? 1 : -1) * dist;
}
public double getMax() {
return max;
}
public void setMax(double max) {
this.max = max;
}
public double getD() {
return d;
}
public void setD(double d) {
this.d = d;
}
public double getH() {
return h;
}
public void setH(double h) {
this.h = h;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}