/**
* Copyright (c) 2009-2011, chunquedong(YangJiandong)
*
* This file is part of ChunMap project
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE(Version >=3)
*
* History:
* 2010-05-05 Jed Young Creation
*/
package chunmap.model.coord;
import java.util.ArrayList;
import java.util.List;
import chunmap.model.elem.Envelope;
import chunmap.model.elem.EnvelopeBuf;
import chunmap.model.elem.LineSegment;
public class CoordSeqEditor {
private List<CPoint> points;
public CoordSeqEditor()
{
points = new ArrayList<CPoint>();
}
public CoordSeqEditor(CPoint[] pointList)
{
points = new ArrayList<CPoint>();
for (CPoint p : pointList)
{
points.add(p);
}
}
public CoordSeqEditor(List<CPoint> pointList)
{
points = new ArrayList<CPoint>();
for (CPoint p : pointList)
{
points.add(p);
}
}
public CoordSeqEditor(CoordinateSeq coordSeq)
{
points = new ArrayList<CPoint>();
for (CPoint p : coordSeq)
{
points.add(p);
}
}
@Override
public String toString()
{
return "LineStringEditor [" + points + "]";
}
private Envelope getEnvelop()
{
EnvelopeBuf env = new EnvelopeBuf();
for (CPoint p : points)
{
env.extendEnvelop(p);
}
return env.toEnvelop();
}
//------------------------------------------------------------------------
//#region get
public CPoint firstPoint()
{
return getPoint(0);
}
public CPoint lastPoint()
{
return getPoint(size() - 1);
}
public LineSegment getLineSegment(int i)
{
return new LineSegment(getPoint(i), getPoint(i + 1));
}
public int size()
{
return points.size();
}
public CPoint getPoint(int index)
{
return points.get(index);
}
public CoordinateSeq toCoordinateSeq()
{
return new CoordinateArray(points.toArray(new CPoint[0]));
}
//#endregion
//------------------------------------------------------------------------
//#region edit
/**
* if point is not on the line ,do nothing
*
* @param p
* @return
*/
public void tryInsertPoint(CPoint p)
{
if (!this.getEnvelop().contain(p))
{
return;
}
for (int i = 0, n = size() - 1; i < n; i++)
{
LineSegment lseg = getLineSegment(i);
if (lseg.onLineSegment(p))
{
if (lseg.onBorder(p))
return;
else
{
addAt(i + 1, p);
break;
}
}
}
}
public void deletePointAt(int index)
{
points.remove(index);
}
/**
* 强制闭合
*
* @return
*/
public void close()
{
if (!isClose())
{
CPoint lastPoint = points.get(size() - 1);
if (points.get(0).approximateEquals(lastPoint))
{
points.remove(size() - 1);
}
addPointToLast(points.get(0));
}
}
public void deleteOverPoint()
{
List<CPoint> ps = new ArrayList<CPoint>();
for (CPoint p : points)
{
if (!containPoint(ps, p))
{
ps.add(p);
}
}
points = ps;
}
private boolean containPoint(List<CPoint> ps, CPoint point)
{
for (CPoint p : ps)
{
if (p.approximateEquals(point))
return true;
}
return false;
}
public boolean isClose()
{
CPoint lastPoint = points.get(size() - 1);
return points.get(0).equals(lastPoint);
}
public void addPointToLast(CPoint p)
{
points.add(p);
}
public void addAt(int index, CPoint p)
{
points.add(index, p);
}
public boolean isEmpty()
{
if (size() == 0)
return true;
return false;
}
public void addAll(CoordinateSeq lineString)
{
for(CPoint p: lineString){
points.add(p);
}
}
public void insertAll(CoordinateSeq lineString)
{
List<CPoint> tpoints = new ArrayList<CPoint>();
for (CPoint p : lineString)
{
tpoints.add(p);
}
points.addAll(0, tpoints);
}
public void tryInsertAll(CoordinateSeq lineString){
for (CPoint p : lineString)
{
this.tryInsertPoint(p);
}
}
/**
* 反向
*
* @return
*/
public void reverse()
{
List<CPoint> pointList = new ArrayList<CPoint>();
for (int i = size() - 1; i >= 0; i--)
{
pointList.add(getPoint(i));
}
points = pointList;
}
//#endregion
//------------------------------------------------------------------------
/**
* 是否能和另一条线首尾相接,然后调用join方法就不会出错了。
*
* @param l2
* @return
*/
public boolean canJoin(CoordinateSeq l2)
{
if (isEmpty()) return true;
CPoint endPoint = l2.endPoint();
if ((lastPoint().equals(l2.startPoint()))
|| (this.lastPoint().equals(endPoint))
|| (this.firstPoint().equals(l2.startPoint()))
|| (this.firstPoint().equals(endPoint)))
{
return true;
}
else
{
return false;
}
}
/**
* 和另一条线连接在一起
*
* @param l2
* @return
*/
public void join(CoordinateSeq l2)
{
if (this.isEmpty())
{
addAll(l2);
}
else if (lastPoint().equals(l2.startPoint()))
{
directAddJoin(l2);
}
else if (this.lastPoint().equals(l2.endPoint()))
{
directAddJoin(reverse(l2));
}
else if (this.firstPoint().equals(l2.startPoint()))
{
this.reverse();
directAddJoin(l2);
}
else if (this.firstPoint().equals(l2.endPoint()))
{
directInsertJoin(l2);
}
else
{
throw new IllegalArgumentException("no join part");
}
}
private CoordinateSeq reverse(CoordinateSeq ls)
{
CoordSeqEditor le = new CoordSeqEditor(ls);
le.reverse();
return le.toCoordinateSeq();
}
private void directAddJoin(CoordinateSeq line)
{
for (int i = 1, n = line.size(); i < n; i++)
{
CPoint point = line.getCoordinate(i);
points.add(point);
}
}
private void directInsertJoin(CoordinateSeq line)
{
List<CPoint> pointList = new ArrayList<CPoint>();
for (int i = 0, n = line.size() - 1; i < n; i++)
{
CPoint point = line.getCoordinate(i);
pointList.add(point);
}
points.addAll(0, pointList);
}
}