/**
* 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.algorithm;
import java.util.ArrayList;
import java.util.List;
import chunmap.model.coord.CoordinateArray;
import chunmap.model.coord.CoordinateSeq;
import chunmap.model.coord.CPoint;
import chunmap.model.elem.LineSegment;
public class LinearReference {
/// <summary>
/// 指定距离处的点
/// </summary>
/// <param name="points"></param>
/// <param name="distance"></param>
/// <returns></returns>
public static CPoint refPoint(CoordinateSeq points, double distance)
{
checkArgument(points, distance);
double len = 0;
int i = 0;
LineSegment lseg = null;
for (int n = points.size() - 1; i < n; i++)
{
lseg = new LineSegment(points.getCoordinate(i), points.getCoordinate(i+1));
len += lseg.getDistance();
if (len > distance)
{
break;
}
}
double l2 = len - distance;
double d = lseg.getDistance();
double l1 = d - l2;
double lamuda = l1 / l2;
return lseg.dingBiFenDian(lamuda);
}
/// <summary>
/// 子线串
/// </summary>
/// <param name="points"></param>
/// <param name="start"></param>
/// <param name="end"></param>
/// <returns></returns>
public static CoordinateSeq subLineString(CoordinateSeq points, double start, double end)
{
checkArgument(points, start);
checkArgument(points, end);
CPoint sp = refPoint(points, start);
CPoint ep = refPoint(points, end);
if (start < end)
{
return middleLineString(points, sp, ep);
}
else if (start > end)
{
return middleLineString(points, ep, sp);
}
else
{
return null;
}
}
//------------------------------------------------------------------------helper
// 两点中间的线
private static CoordinateSeq middleLineString(CoordinateSeq points, CPoint start, CPoint end)
{
List<CoordinateSeq> ml = splitLine(points, start);
if (ml.size() == 0)
{
throw new IllegalArgumentException("IllegalArgument exist");
}
int i = (ml.size() == 1) ? 0 : 1;
CoordinateSeq tl = ml.get(i);
List<CoordinateSeq> ml2 = splitLine(tl, end);
return ml2.get(0);
}
public static List<CoordinateSeq> splitLine(CoordinateSeq points, CPoint p)
{
CoordinateSeq lineString = (CoordinateSeq)points.clone();
if (!LineAlgorithm.onLineString(points, p))
{
return new ArrayList<CoordinateSeq>();
}
if (onBorder(lineString, p))
{
List<CoordinateSeq> lines = new ArrayList<CoordinateSeq>();
lines.add(points);
return lines;
}
// 分裂
List<CPoint> points1 = new ArrayList<CPoint>();
List<CPoint> points2 = new ArrayList<CPoint>();
for (int i = 0, n = points.size() - 1; i < n; i++)
{
LineSegment lseg = new LineSegment(points.getCoordinate(i), points.getCoordinate(i+1));
if (lseg.onLineSegment(p))
{
List<CPoint> tpoints = subList(points, 0, i + 1);
points1.addAll(tpoints);
points1.add(p);
if (!lseg.onBorder(p))
{
points2.add(p);
}
List<CPoint> tpoints2 = subList(points, i + 1, n + 1);
points2.addAll(tpoints2);
break;
}
}
// 构造多线
CoordinateSeq l1 = new CoordinateArray(points1.toArray(new CPoint[0]));
CoordinateSeq l2 = new CoordinateArray(points2.toArray(new CPoint[0]));
List<CoordinateSeq> lines2 = new ArrayList<CoordinateSeq>();
lines2.add(l1);
lines2.add(l2);
return lines2;
//return null;
}
private static boolean onBorder(CoordinateSeq points, CPoint p)
{
if (p.equals(points.startPoint()) || p.equals(points.endPoint()))
return true;
return false;
}
private static List<CPoint> subList(CoordinateSeq points, int start, int end)
{
List<CPoint> sub = new ArrayList<CPoint>();
for (int i = start; i < end; i++)
{
sub.add(points.getCoordinate(i));
}
return sub;
}
private static void checkArgument(CoordinateSeq points, double distance)
{
if (distance < 0 || distance > getLength(points))
{
throw new IllegalArgumentException();
}
}
public static double getLength(CoordinateSeq points)
{
double len = 0;
for (int i = 0, n = points.size() - 1; i < n; i++)
{
len += points.getCoordinate(i).distance2D(points.getCoordinate(i+1));
}
return len;
}
}