package es.iiia.shapegrammar.shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import org.eclipse.ui.views.properties.IPropertySource;
import org.w3c.dom.Element;
import es.iiia.shapegrammar.model.GeometryPropertySource;
import es.iiia.shapegrammar.model.IModifyByPoint;
import es.iiia.shapegrammar.model.PointBasedModel;
import es.iiia.shapegrammar.shape.guides.LineDefinition;
import es.iiia.shapegrammar.utils.MathUtils;
import es.iiia.shapegrammar.utils.ShapeTools;
public class LineModel extends PointBasedModel implements IModifyByPoint {
private static final long serialVersionUID = 9073438114397114154L;
private LineDefinition lineDefinition;
private boolean closed;
public LineModel() {
super();
}
public LineModel(Element config) {
super(config);
// init closed
if (config.getAttribute("closed") != null) {
this.closed = Boolean.parseBoolean(config.getAttribute("closed"));
}
}
public LineModel(Point2D p1, Point2D p2) {
this();
Point2D pt1 = (Point2D) p1.clone();
Point2D pt2 = (Point2D) p2.clone();
ShapeTools.orderPoints(pt1, pt2);
points.add(pt1);
points.add(pt2);
}
public LineModel(double x1, double y1, double x2, double y2) {
this(new Point2D.Double(x1, y1), new Point2D.Double(x2, y2));
}
public Point2D getP1() {
return this.points.get(0);
}
public Point2D setP1(Point2D value) {
return this.points.set(0, value);
}
public Point2D getP2() {
// Maybe last point?
return this.points.get(1);
}
public Point2D setP2(Point2D value) {
return this.points.set(1, value);
}
public LineModel[] getLines() {
LineModel[] lines = new LineModel[this.closed ? this.points.size()
: this.points.size() - 1];
for (int i = 1; i < this.points.size(); i++) {
lines[i-1] = new LineModel(this.points.get(i - 1), this.points.get(i));
}
if (this.closed) {
lines[lines.length-1] =
new LineModel(this.points.get(this.points.size() - 1), this.points.get(0));
}
return lines;
}
public boolean isClosed() {
return this.closed;
}
public void setClosed(boolean closed) {
this.closed = closed;
}
public LineDefinition getDefinition() {
if (this.lineDefinition == null) {
this.lineDefinition = new LineDefinition(this);
}
return lineDefinition;
}
// public methods
public boolean contains(Point2D point) {
Line2D line = new Line2D.Double(
this.getP1().getX(), this.getP1().getY(),
this.getP2().getX(), this.getP2().getY());
return line.ptSegDist(point.getX(), point.getY()) == 0;
}
public boolean contains(double xP1, double yP1, double xP2, double yP2) {
// double thisxP1 = MathUtils.round(this.getP1().getX());
// double thisyP1 = MathUtils.round(this.getP1().getY());
// double thisxP2 = MathUtils.round(this.getP2().getX());
// double thisyP2 = MathUtils.round(this.getP2().getY());
//
// if (thisxP1 == thisxP2) {
// if (thisyP1 > thisyP2) {
// if (yP1 >= thisyP2 && yP1 <= thisyP1 && yP2 >= thisyP2
// && yP2 <= thisyP1) {
// return true;
// }
//
// } else {
// if (yP1 <= thisyP2 && yP1 >= thisyP1 && yP2 <= thisyP2
// && yP2 >= thisyP1) {
// return true;
// }
// }
// // TEST Xs
// } else {
// if (thisxP1 < thisxP2) {
// if (xP1 >= thisxP1 && xP1 <= thisxP2 && xP2 >= thisxP1
// && xP2 <= thisxP2) {
// return true;
// }
//
// } else {
// if (xP1 >= thisxP2 && xP1 <= thisxP1 && xP2 >= thisxP2
// && xP2 <= thisxP1) {
// return true;
// }
// }
// }
// return false;
return this.contains(new Point2D.Double(xP1, yP1)) && this.contains(new Point2D.Double(xP2, yP2));
}
public LineModel clone() {
// Create new model
LineModel model = new LineModel();
// Clone all point
for (Point2D point : this.points) {
model.addPoint((Point2D) point.clone());
}
model.setColor(this.getColor());
model.setId(this.getId());
model.closed = this.closed;
model.setParent(this.getParent());
return model;
}
@Override
public String getName() {
return "Line";
}
protected String getXmlName() {
return "polyLine";
}
public String getLabel() {
return null;
}
@Override
public Object getAdapter(Class adapter) {
if (adapter == IPropertySource.class) {
if (propertySource == null)
propertySource = new GeometryPropertySource(this);
return propertySource;
}
return null;
}
public LineModel sort() {
if (this.points.size() != 2) {
try {
throw new Exception(
"You can sort only polyline with two points!");
} catch (Exception e) {
e.printStackTrace();
}
}
// check if we need to switch points
if (this.getP1().getX() > this.getP2().getX()
|| (this.getP1().getX() == this.getP2().getX() && this.getP1()
.getY() > this.getP2().getY())) {
// reinsert point to first position
this.points.add(0, this.points.remove(1));
}
return this;
}
public double getSize() {
return Math.sqrt((this.getP2().getX() - this.getP1().getX())
* (this.getP2().getX() - this.getP1().getX())
+ (this.getP2().getY() - this.getP1().getY())
* (this.getP2().getY() - this.getP1().getY()));
}
public boolean isEqualTo(LineModel line) {
if (line.points.size() > 2) {
System.out.println("ERROR: Compare works only on simple lines!");
return false;
}
return MathUtils.compare(this.getP1(), line.getP1()) == 0 &&
MathUtils.compare(this.getP2(), line.getP2()) == 0;
}
public LineModel transformTo(AffineTransform transformation) {
LineModel line = this.clone();
line.transform(transformation);
return line;
}
@Override
public Element getXml() {
Element elem = super.getXml();
elem.setAttribute("closed", Boolean.toString(this.closed));
return elem;
}
}