package edu.stanford.rsl.conrad.geometry.shapes.simple;
import java.util.ArrayList;
import edu.stanford.rsl.conrad.geometry.AbstractCurve;
import edu.stanford.rsl.conrad.geometry.AbstractShape;
import edu.stanford.rsl.conrad.geometry.transforms.Transform;
import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
import edu.stanford.rsl.conrad.numerics.SimpleOperators;
import edu.stanford.rsl.conrad.numerics.SimpleVector;
import edu.stanford.rsl.conrad.numerics.Solvers;
import edu.stanford.rsl.conrad.utils.CONRAD;
public class StraightLine extends AbstractCurve {
private static final long serialVersionUID = 4615305861839196846L;
protected SimpleVector direction;
protected PointND point;
/**
* Creates a StraightLine from point with direction dir
* @param point the point
* @param dir the direction
*/
public StraightLine(PointND point, SimpleVector dir){
this.direction = dir;
this.point = point;
}
public StraightLine(StraightLine sl){
super(sl);
direction = (sl.direction != null) ? sl.direction.clone() : null;
point = (sl.point != null) ? sl.point.clone() : null;
}
public void init(PointND point, SimpleVector dir){
this.direction = dir;
this.point = point;
}
/**
* Creates a new Straight line passing from point to point2
* @param point the base point
* @param point2 the other point
*/
public StraightLine(PointND point, PointND point2){
this.direction = SimpleOperators.subtract(point2.getAbstractVector(), point.getAbstractVector());
this.point = point;
}
public void init(PointND point, PointND point2){
this.direction = SimpleOperators.subtract(point2.getAbstractVector(), point.getAbstractVector());
this.point = point;
}
public void normalize(){
direction.normalizeL2();
}
@Override
public PointND evaluate(double u) {
return new PointND(SimpleOperators.add(point.getAbstractVector(), direction.multipliedBy(u)));
}
@Override
public int getDimension() {
return point.getDimension();
}
protected SimpleVector computeIntersectionCoefficients(StraightLine l2){
SimpleVector b = SimpleOperators.subtract(l2.point.getAbstractVector(), point.getAbstractVector());
SimpleMatrix A = new SimpleMatrix(3, 2);
A.setColValue(0, direction);
A.setColValue(1, l2.direction);
return Solvers.solveLinearLeastSquares(A, b);
}
@Override
public ArrayList<PointND> intersect(AbstractCurve other) {
if (other instanceof StraightLine) {
StraightLine l2 = (StraightLine) other;
ArrayList<PointND> list = new ArrayList<PointND>();
PointND i = intersect(l2);
if (i != null)
list.add(i);
return list;
} else {
throw new RuntimeException("This curve is not supported yet");
}
}
public PointND intersect(StraightLine line){
return intersect(line, CONRAD.SMALL_VALUE*1000);
}
public PointND intersect(StraightLine line, double threshold){
SimpleVector lambda = computeIntersectionCoefficients(line);
PointND p1 = evaluate(lambda.getElement(0));
PointND p2 = line.evaluate(-lambda.getElement(1));
if (p1 != null) {
if (p1.euclideanDistance(p2) < threshold){
return p1;
}
}
return null;
}
/**
* @return the direction
*/
public SimpleVector getDirection() {
return direction;
}
/**
* @param direction the direction to set
*/
public void setDirection(SimpleVector direction) {
this.direction = direction;
}
/**
* @return the point
*/
public PointND getPoint() {
return new PointND(point);
}
/**
* @param point the point to set
*/
public void setPoint(PointND point) {
this.point = point;
}
@Override
public boolean isBounded() {
return false;
}
/**
* Computes the closest distance between the line and the point p.
* @param p the point p
* @return the distance
*/
public double computeDistanceTo(PointND p) {
SimpleVector vector = SimpleOperators.subtract(point.getAbstractVector(), p.getAbstractVector());
double projectionValue = SimpleOperators.multiplyInnerProd(vector, direction);
return p.euclideanDistance(evaluate(projectionValue));
}
@Override
public void applyTransform(Transform t) {
point = t.transform(point);
direction = t.transform(direction);
}
@Override
public PointND[] getRasterPoints(int number) {
return null;
}
@Override
public String toString(){
return point + " + n * " + direction;
}
@Override
public AbstractShape clone() {
return new StraightLine(this);
}
}
/*
* Copyright (C) 2010-2014 Andreas Maier, Rotimi X Ojo
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/