/**
* 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.elem;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import chunmap.model.algorithm.LinearReference;
import chunmap.model.coord.CoordSeqEditor;
import chunmap.model.coord.CoordinateSeq;
import chunmap.model.coord.CPoint;
import chunmap.model.geom.Geometry;
import chunmap.model.geom.LineString;
import chunmap.model.geom.GeoPoint;
/**
* 线与线的交集结果,经常是既有点又有线。 点和线重叠时,删除点,保留线。
*
* @author chunquedong
*
*/
public class PointLineBag {
private final Set<GeoPoint> points = new HashSet<GeoPoint>();
private final Set<LineString> lines = new HashSet<LineString>();
/**
* 不考虑线线自相交的情况,不考虑线的拓扑相等。
*
* @param g
*/
public void add(Geometry g) {
if (g instanceof GeoPoint) {
GeoPoint p = (GeoPoint) g;
if (!points.contains(p)) {
putPoint(p);
}
} else if (g instanceof LineString) {
LineString line = (LineString) g;
if (!lines.contains(line)) {
putLine(line);
}
} else {
throw new IllegalArgumentException(
"noly supper point an lineString");
}
}
public void add(PointLineBag bag) {
for (GeoPoint p : bag.points) {
this.add(p);
}
for (LineString l : bag.lines) {
this.add(l);
}
}
private void putPoint(GeoPoint p) {
for (LineString line : lines) {
if (line.onLineString(p.getCoordinate()))
return;
}
points.add(p);
}
private void putLine(LineString line) {
// 移除重叠的点
GeoPoint tp = null;
for (GeoPoint p : points) {
if (line.onLineString(p.getCoordinate())) {
tp = p;
break;
}
}
points.remove(tp);
// 合并相连的线
LineString tl = null;
CoordSeqEditor newLine = new CoordSeqEditor(line.getPoints());
for (LineString ls : lines) {
CoordinateSeq l=ls.getPoints();
if (newLine.canJoin(l)) {
newLine.join(l);
tl = ls;
break;
}
}
if (tl != null) {
lines.remove(tl);
lines.add(new LineString(newLine.toCoordinateSeq()));
} else {
lines.add(line);
}
}
public int getPointSize() {
return points.size();
}
public int getLineStringSize() {
return lines.size();
}
public int size() {
return points.size() + lines.size();
}
public boolean isEmpty() {
if ((points.size() == 0) && (lines.size() == 0))
return true;
return false;
}
public List<Geometry> toList() {
List<Geometry> geos = new ArrayList<Geometry>();
for (GeoPoint p : points) {
geos.add(p);
}
for (LineString l : lines) {
geos.add(l);
}
return geos;
}
public List<GeoPoint> getPointList() {
List<GeoPoint> pointList = new ArrayList<GeoPoint>();
for (GeoPoint p : points) {
pointList.add(p);
}
return pointList;
}
public List<LineString> getLineList() {
List<LineString> lineList = new ArrayList<LineString>();
for (LineString l : lines) {
lineList.add(l);
}
return lineList;
}
public List<LineString> breakLine(LineString ls) {
List<LineString> lines = new ArrayList<LineString>();
lines.add(ls);
List<GeoPoint> pointList = this.getPointList();
for (GeoPoint p : pointList) {
breakLine(p.getCoordinate(), lines);
}
List<LineString> lineList = this.getLineList();
for (LineString l : lineList) {
CPoint p1 = l.firstPoint();
CPoint p2 = l.lastPoint();
breakLine(p1, lines);
breakLine(p2, lines);
}
return lines;
}
private void breakLine(CPoint p, List<LineString> lines) {
for (int i = 0, n = lines.size(); i < n; i++) {
LineString ls = lines.get(i);
List<CoordinateSeq> newLines =LinearReference.splitLine(ls.getPoints(),p);
if (newLines.size() == 2) {
lines.remove(i);
lines.add(new LineString(newLines.get(0)));
lines.add(new LineString(newLines.get(1)));
return;
}
}
}
}