/*
* Polygon.java
*
* Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
*
* This file is part of BEAST.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership and licensing.
*
* BEAST 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; either version 2
* of the License, or (at your option) any later version.
*
* BEAST 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BEAST; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
package dr.geo;
import org.jdom.Element;
import java.util.StringTokenizer;
import java.util.List;
import dr.xml.XMLParseException;
/**
* Created by IntelliJ IDEA.
* User: phil
* Date: Feb 19, 2009
* Time: 5:15:25 PM
* To change this template use File | Settings | File Templates.
*/
public class Polygon {
public static final String POLYGON = "polygon";
public static final String CLOSED = "closed";
public static final String COORDINATES = "coordinates";
// includes a density value
//public static final String DENSITY = "density";
public Polygon(Element e) {
boolean closed = Boolean.valueOf(e.getAttributeValue(CLOSED));
List children = e.getChildren();
for (int a = 0; a < children.size(); a++) {
Element childElement = (Element)children.get(a);
if (childElement.getName().equals(COORDINATES)) {
String value = childElement.getTextTrim();
StringTokenizer st1 = new StringTokenizer(value, "\n");
int count = st1.countTokens(); //System.out.println(count);
x = new double[count];
y = new double[count];
z = new double[count];
// assumes closed!
length = x.length - 1;
for (int i = 0; i < count; i++) {
String line = st1.nextToken();
StringTokenizer st2 = new StringTokenizer(line, ",");
if (st2.countTokens() != 3)
throw new IllegalArgumentException("All KML coordinates must contain (X,Y,Z) values. Three dimensions not found in element '" + line + "'");
x[i] = Double.valueOf(st2.nextToken());
y[i] = Double.valueOf(st2.nextToken());
z[i] = Double.valueOf(st2.nextToken());
}
//gets the density value
//String densityValue = e.getChild(DENSITY).getTextTrim();
//d = Double.valueOf(densityValue);
}
}
planarInZ = isPlanarInZ();
}
protected double[] x;
protected double[] y;
protected double[] z;
protected double[] t;
// declares dernsity double
//protected double d;
protected int length;
private boolean planarInZ;
//returns density value
//public double getDensity(){
//return d;
//}
private boolean isPlanarInZ() {
double z0 = z[0];
boolean planar = true;
for (int i = 0; i < length; i++) {
if (z0 != z[i]) {
planar = false;
break;
}
}
return planar;
}
public boolean contains2DPoint(double inX, double inY) {
// System.err.print("contains (" + inX + "," + inY + ") = ");
if (!planarInZ)
throw new RuntimeException("Only 2D polygons are currently implemented");
boolean contains = false;
// Take a horizontal ray from (inX,inY) to the right.
// If ray across the polygon edges an odd # of times, the point is inside.
for (int i = 0, j = length - 1; i < length; j = i++) {
if ((((y[i] <= inY) && (inY < y[j])) ||
((y[j] <= inY) && (inY < y[i]))) &&
(inX < (x[j] - x[i]) * (inY - y[i]) / (y[j] - y[i]) + x[i]))
contains = !contains;
}
// System.err.println(contains);
return contains;
}
}