/*
* Copyright (c) 2016 Martin Davis.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
*
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
package org.locationtech.jts.operation.buffer;
import java.util.ArrayList;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.PrecisionModel;
/**
* A dynamic list of the vertices in a constructed offset curve.
* Automatically removes adjacent vertices
* which are closer than a given tolerance.
*
* @author Martin Davis
*
*/
class OffsetSegmentString
{
private static final Coordinate[] COORDINATE_ARRAY_TYPE = new Coordinate[0];
private ArrayList ptList;
private PrecisionModel precisionModel = null;
/**
* The distance below which two adjacent points on the curve
* are considered to be coincident.
* This is chosen to be a small fraction of the offset distance.
*/
private double minimimVertexDistance = 0.0;
public OffsetSegmentString()
{
ptList = new ArrayList();
}
public void setPrecisionModel(PrecisionModel precisionModel)
{
this.precisionModel = precisionModel;
}
public void setMinimumVertexDistance(double minimimVertexDistance)
{
this.minimimVertexDistance = minimimVertexDistance;
}
public void addPt(Coordinate pt)
{
Coordinate bufPt = new Coordinate(pt);
precisionModel.makePrecise(bufPt);
// don't add duplicate (or near-duplicate) points
if (isRedundant(bufPt))
return;
ptList.add(bufPt);
//System.out.println(bufPt);
}
public void addPts(Coordinate[] pt, boolean isForward)
{
if (isForward) {
for (int i = 0; i < pt.length; i++) {
addPt(pt[i]);
}
}
else {
for (int i = pt.length - 1; i >= 0; i--) {
addPt(pt[i]);
}
}
}
/**
* Tests whether the given point is redundant
* relative to the previous
* point in the list (up to tolerance).
*
* @param pt
* @return true if the point is redundant
*/
private boolean isRedundant(Coordinate pt)
{
if (ptList.size() < 1)
return false;
Coordinate lastPt = (Coordinate) ptList.get(ptList.size() - 1);
double ptDist = pt.distance(lastPt);
if (ptDist < minimimVertexDistance)
return true;
return false;
}
public void closeRing()
{
if (ptList.size() < 1) return;
Coordinate startPt = new Coordinate((Coordinate) ptList.get(0));
Coordinate lastPt = (Coordinate) ptList.get(ptList.size() - 1);
Coordinate last2Pt = null;
if (ptList.size() >= 2)
last2Pt = (Coordinate) ptList.get(ptList.size() - 2);
if (startPt.equals(lastPt)) return;
ptList.add(startPt);
}
public void reverse()
{
}
public Coordinate[] getCoordinates()
{
/*
// check that points are a ring - add the startpoint again if they are not
if (ptList.size() > 1) {
Coordinate start = (Coordinate) ptList.get(0);
Coordinate end = (Coordinate) ptList.get(ptList.size() - 1);
if (! start.equals(end) ) addPt(start);
}
*/
Coordinate[] coord = (Coordinate[]) ptList.toArray(COORDINATE_ARRAY_TYPE);
return coord;
}
public String toString()
{
GeometryFactory fact = new GeometryFactory();
LineString line = fact.createLineString(getCoordinates());
return line.toString();
}
}