/**
* 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.List;
import chunmap.model.algorithm.LineSegmentAlgorithm;
import chunmap.model.coord.Coordinate2D;
import chunmap.model.coord.CPoint;
import chunmap.model.geom.LineString;
import chunmap.util.math.MyDouble;
/**
* 线段
*
* @author chunquedong
*
*/
public class LineSegment {
private final CPoint startPoint;
private final CPoint endPoint;
//------------------------------------------------------------------------getter
/**
* @param 起点
* @param 终点
*/
public LineSegment(CPoint startPoint, CPoint endPoint) {
if (startPoint.equals(endPoint))
throw new IllegalArgumentException(
"need tow different points to make one line");
this.startPoint = startPoint;
this.endPoint = endPoint;
}
public CPoint getStartPoint() {
return startPoint;
}
public CPoint getEndPoint() {
return endPoint;
}
public double getDistance() {
return startPoint.distance2D(endPoint);
}
public double getDistance3D() {
double x1 = startPoint.getX();
double y1 = startPoint.getY();
double z1 = startPoint.getZ();
double x2 = endPoint.getX();
double y2 = endPoint.getY();
double z2 = endPoint.getZ();
double d1 = Math.pow((x1 - x2), 2.0);
double d2 = Math.pow((y1 - y2), 2.0);
double d3 = Math.pow((z1 - z2), 2.0);
double dis = Math.sqrt(d1 + d2 + d3);
return dis;
}
public double taxiDistance() {
double x1 = startPoint.getX();
double y1 = startPoint.getY();
double x2 = endPoint.getX();
double y2 = endPoint.getY();
return Math.abs(x1 - x2) + Math.abs(y1 - y2);
}
public Envelope getEnvelop() {
return new Envelope(startPoint, endPoint);
}
public CPoint getMiddlePoint() {
double x = (startPoint.getX() + endPoint.getX()) / 2d;
double y = (startPoint.getY() + endPoint.getY()) / 2d;
return new Coordinate2D(x, y);
}
//------------------------------------------------------------------------Intersect
public boolean hasIntersect(LineSegment other) {
if (!this.getEnvelop().hasIntersect(other.getEnvelop()))
return false;
if (this.kuaLi(other) && other.kuaLi(this))
return true;
return false;
}
/**
* 计算两点交集,没有交集是返回null,交集可能是Point,PointArray
*
* @param other
* @return
*/
public Object intersection(LineSegment other) {
Object r=LineSegmentAlgorithm.intersection(this, other);
return r;
}
/**
* 是否跨立另一条线
*
* @param other
* @return
*/
private boolean kuaLi(LineSegment other) {
Vector v1 = new Vector(this.startPoint,other.startPoint);
Vector v2 = new Vector(other.endPoint, other.startPoint);
Vector v3 = new Vector(this.endPoint, other.startPoint);
double ji1 = v1.get2DCrossProduct(v2);
double ji2 = v3.get2DCrossProduct(v2);
double he = ji1 * ji2;
return he <= 0;
}
//------------------------------------------------------------------------util
/**
* 点是否在线段上
*
* @param p
* @return
*/
public boolean onLineSegment(CPoint p) {
if (!this.getEnvelop().contain(p))
return false;
if (onBorder(p))
return true;
Vector v1 = new Vector(p, startPoint);
Vector v2 = new Vector(endPoint, startPoint);
double ji = v1.get2DCrossProduct(v2);
if (MyDouble.approximateEquals(ji, 0))
return true;
return false;
}
public boolean onBorder(CPoint p) {
if (p.equals(startPoint) || p.equals(endPoint))
return true;
return false;
}
/**
* 包含另一条线吗
*
* @param lseg2
* @return
*/
public boolean containLineSegment(LineSegment lseg2) {
boolean hasI = this.getEnvelop().hasIntersect(lseg2.getEnvelop());
if (!hasI)
return false;
if (this.onLineSegment(lseg2.getStartPoint())
&& this.onLineSegment(lseg2.getEndPoint())) {
return true;
}
return false;
}
public boolean equalsIgnoreOrder(LineSegment lseg) {
if (this.equals(lseg))
return true;
if (this.startPoint.equals(lseg.endPoint)
&& this.endPoint.equals(lseg.startPoint))
return true;
return false;
}
public Line toLine() {
return new Line(startPoint, endPoint);
}
public Vector toVector() {
return new Vector(startPoint, endPoint);
}
public LineString toLineString() {
List<CPoint> pointList = new ArrayList<CPoint>();
pointList.add(startPoint);
pointList.add(endPoint);
return new LineString(pointList);
}
/**
* 线段的定比分点
*
* @param lamuda
* @return
*/
public CPoint dingBiFenDian(double lamuda) {
if (lamuda == -1)
new IllegalArgumentException();
double x = (startPoint.getX() + endPoint.getX() * lamuda)
/ (1 + lamuda);
double y = (startPoint.getY() + endPoint.getY() * lamuda)
/ (1 + lamuda);
return new Coordinate2D(x, y);
}
@Override
public String toString() {
return "LineSegment [startPoint=" + startPoint + ",endPoint="
+ endPoint + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((endPoint == null) ? 0 : endPoint.hashCode());
result = prime * result
+ ((startPoint == null) ? 0 : startPoint.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LineSegment other = (LineSegment) obj;
if (endPoint == null) {
if (other.endPoint != null)
return false;
} else if (!endPoint.equals(other.endPoint))
return false;
if (startPoint == null) {
if (other.startPoint != null)
return false;
} else if (!startPoint.equals(other.startPoint))
return false;
return true;
}
}