/* Copyright (C) 2006 Christian Schneider
*
* This file is part of Nomad.
*
* Nomad is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Nomad is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Nomad; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Created on Feb 10, 2006
*/
package net.sf.nmedit.jtheme.cable;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.QuadCurve2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
public class SimpleCableGeometrie extends QuadCurve2D.Float
implements CableGeometrie
{
/**
*
*/
private static final long serialVersionUID = 2686151817733494025L;
private boolean boundaryChanged = true;
private transient Rectangle2D cachedBounds;
private final static int hangingMin = 4;
private final static int hangingMax = 55;
private final static float hangingWeight = 0.3F;
public SimpleCableGeometrie()
{
this(0, 0, 0, 0);
}
public SimpleCableGeometrie(float x1, float y1, float x2, float y2)
{
setCurve(x1, y1, x2, y2);
}
public SimpleCableGeometrie(Point2D p1, Point2D p2)
{
setCurve((float)p1.getX(), (float)p1.getY(), (float)p2.getX(), (float)p2.getY());
}
public Point getP1() { return new Point(getXi(), getYi()); }
public Point getP2() { return new Point(getXi(), getYi()); }
public Point getCtrlP1() { return new Point(getCtrlXi(), getCtrlYi()); }
public int getXi() { return (int) getX1(); }
public int getYi() { return (int) getY1(); }
public int getCtrlXi() { return (int) getCtrlX(); }
public int getCtrlYi() { return (int) getCtrlY(); }
public void setCurve(QuadCurve2D curve)
{
setCurve((float)curve.getX1(), (float)curve.getY1(), (float)curve.getX2(), (float)curve.getY2());
}
public void setCurve(Point p1, Point p2)
{
setCurve(p1.x, p1.y, p2.x, p2.y);
}
public void setCurve(float x1, float y1, float ctrlx1, float ctrly1, float ctrlx2, float ctrly2, float x2, float y2)
{
setCurve(x1, y1, x2, y2);
}
public void setCurve(float x1, float y1, float x2, float y2)
{
if (this.x1!=x1||this.y1!=y1||this.x2!=x2||this.y2!=y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
updateControlPoints();
}
}
private double shake = 0; // default: no shaking
private void updateControlPoints()
{
float length = (float) Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
int isLeft = ((x1<x2 && y1<y2) || (x1>x2 && y1>y2)) ? -1 : +1;
float shakeDepLen = (float) ((shake / 5) * (length / 2));
ctrlx = ((x1+x2) / 2) + (hangingMin + shakeDepLen) * isLeft;
ctrly = ((y1+y2) / 2) + Math.min(hangingMax, ((hangingWeight) * length) + shakeDepLen);
boundaryChanged = true;
}
public Rectangle getBounds()
{
return getBounds(null);
}
public Rectangle getBounds(Rectangle r)
{
if (r == null)
r = new Rectangle();
r.setFrame(getCachedBounds());
return r;
}
public boolean intersects(int x, int y, int width, int height)
{
return super.intersects(x, y, width, height);
}
public boolean intersects(Rectangle r)
{
return super.intersects(r.x, r.y, r.width, r.height);
}
private final Rectangle2D getCachedBounds()
{
// cachedBounds==null => boundaryChanged = true
if (boundaryChanged || (cachedBounds == null))
{
cachedBounds = super.getBounds2D();
boundaryChanged = false;
}
return cachedBounds;
}
public void setEndPoints(int x1, int y1, int x2, int y2)
{
setCurve(x1, y1, x2, y2);
}
public void setEndPoints(Point p1, Point p2)
{
setCurve(p1, p2);
}
public Shape getShape()
{
return this;
}
public Point getStart()
{
return new Point((int)getX1(), (int)getY1());
}
public Point getStop()
{
return new Point((int)getX2(), (int)getY2());
}
public double getShake()
{
return shake;
}
public void setShake(double shake)
{
this.shake = shake;
updateControlPoints();
}
public void shake()
{
setShake(Math.random());
}
}