/*
* Copyright (c) 2014 tabletoptool.com team.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* rptools.com team - initial implementation
* tabletoptool.com team - further development
*/
package com.t3.client.ui.zone.vbl;
import java.awt.BasicStroke;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.LinkedList;
import java.util.List;
import com.t3.util.GraphicsUtil;
public class VisibleAreaSegment implements Comparable<VisibleAreaSegment> {
private final Point2D origin;
private final List<AreaFace> faceList = new LinkedList<AreaFace>();
private final double EPSILON = 0.01;
private Point2D centerPoint;
private Area pathArea;
public VisibleAreaSegment(Point2D origin) {
this.origin = origin;
}
public void addAtEnd(AreaFace face) {
faceList.add(face);
}
public void addAtFront(AreaFace face) {
faceList.add(0, face);
}
public double getDistanceFromOrigin() {
// return GeometryUtil.getDistance(getCenterPoint(), origin);
return getCenterPoint().distance(origin);
}
public Point2D getCenterPoint() {
if (centerPoint == null) {
Area path = getPath();
Rectangle2D bounds = path.getBounds2D();
centerPoint = new Point2D.Double(bounds.getX() + bounds.getWidth() / 2.0, bounds.getY() + bounds.getHeight() / 2.0);
}
return centerPoint;
}
public Area getPath() {
if (pathArea == null) {
List<Point2D> pathPoints = new LinkedList<Point2D>();
for (AreaFace face : faceList) {
// Initial point
if (pathPoints.size() == 0) {
pathPoints.add(face.getP1());
}
pathPoints.add(face.getP2());
}
GeneralPath path = null;
for (Point2D p : pathPoints) {
if (path == null) {
path = new GeneralPath();
path.moveTo((float) p.getX(), (float) p.getY());
continue;
}
path.lineTo((float) p.getX(), (float) p.getY());
}
BasicStroke stroke = new BasicStroke(1);
pathArea = new Area(stroke.createStrokedShape(path));
}
return pathArea;
}
public Area getArea() {
if (faceList.isEmpty()) {
return new Area();
}
List<Point2D> pathPoints = new LinkedList<Point2D>();
for (AreaFace face : faceList) {
// Initial point
if (pathPoints.size() == 0) {
pathPoints.add(face.getP1());
pathPoints.add(0, GraphicsUtil.getProjectedPoint(origin, face.getP1(), Integer.MAX_VALUE / 2));
}
// Add to the path
pathPoints.add(face.getP2());
pathPoints.add(0, GraphicsUtil.getProjectedPoint(origin, face.getP2(), Integer.MAX_VALUE / 2));
}
// System.out.println("Skipped: " + skipCount);
GeneralPath path = null;
for (Point2D p : pathPoints) {
if (path == null) {
path = new GeneralPath();
path.moveTo((float) p.getX(), (float) p.getY());
continue;
}
path.lineTo((float) p.getX(), (float) p.getY());
}
return new Area(path);
}
////
// COMPARABLE
@Override
public int compareTo(VisibleAreaSegment o) {
if (o != this) {
double odist = o.getDistanceFromOrigin();
double val = getDistanceFromOrigin() - odist; // separate variable for debugging
return (int) val;
// return val < EPSILON && val > -EPSILON ? 0 : (int) val; // Should we use an EPSILON value?
// return getDistanceFromOrigin() < odist ? -1 : getDistanceFromOrigin() > odist ? 1 : 0;
}
return 0;
}
}