/*
* Created on 05.01.2005
*
* SVN header information:
* $Author: LBST-PF-3\orahn $
* $Rev: 2509 $
* $Date: 2006-10-06 12:01:50 +0200 (Fr, 06 Okt 2006) $
* $Id: PirolEdge.java 2509 2006-10-06 10:01:50Z LBST-PF-3\orahn $s
*/
package org.openjump.core.graph.pirolProject;
import java.util.Vector;
import com.vividsolutions.jts.geom.Envelope;
/**
*
* Class that describes a single line, specified by it's starting and
* end point. If offers methods e.g. to find intersection points with other
* Kante objects or to determine on which side of the Kante object a given
* punkt object resides.
*
* @author Ole Rahn
* <br>
* <br>FH Osnabrück - University of Applied Sciences Osnabrück,
* <br>Project: PIROL (2005),
* <br>Subproject: Daten- und Wissensmanagement
*
* @version $Rev: 2509 $
*
* @see PirolPoint
* modified: [sstein]: 16.Feb.2009 changed logger-entries to comments
*/
public class PirolEdge {
public static PirolEdge KANTE_X0Y0ToX0Y1 = new PirolEdge( PirolPoint.NULLPUNKT, new PirolPoint(new double[]{0,1}), true, true);
public static PirolEdge KANTE_X0Y0ToX1Y0 = new PirolEdge( PirolPoint.NULLPUNKT, new PirolPoint(new double[]{1,0}), true, true);
protected PirolPoint anfang = null, ende = null;
protected int punktIndexA = -1, punktIndexB = -1;
protected boolean anfangUnbegrenzt = true, endeUnbegrenzt = true;
protected boolean gueltig = true;
protected static double infinityFaktor = Math.pow(10,10);
//protected static PersonalLogger logger = new PersonalLogger(DebugUserIds.OLE);
public PirolEdge(PirolPoint anfang, PirolPoint ende, boolean anfangUnbegrenzt, boolean endeUnbegrenzt){
this.anfang = anfang;
this.ende = ende;
this.anfangUnbegrenzt = anfangUnbegrenzt;
this.endeUnbegrenzt = endeUnbegrenzt;
}
public PirolEdge(PirolPoint anfang, PirolPoint ende){
this.anfang = anfang;
this.ende = ende;
this.anfangUnbegrenzt = false;
this.endeUnbegrenzt = false;
}
public PirolEdge(PirolPoint anfang, double steigung, double laenge){
this.anfang = anfang;
double alpha = Math.atan(steigung);
double dx = Math.cos(alpha) * laenge;
double dy = Math.sin(alpha) * laenge;
try {
this.ende = new PirolPoint( new double[]{anfang.getX()+dx, anfang.getY()+dy});
} catch (Exception e) {
// this should not happen!
this.setGueltig(false);
e.printStackTrace();
}
this.anfangUnbegrenzt = false;
this.endeUnbegrenzt = false;
}
/**
* creates a new {@link PirolEdge} object, that has a length
* equal to <code>lineToShift</code>'s length and is parallel to
* <code>lineToShift</code>.
*@param lineToShift the line to be shifted
*@param shiftingVector x,y,z component for the shifting (will be added to <code>lineToShift</code>'s starting and end point).
*@return a new, shifted {@link PirolEdge} object
* @throws Exception
*/
public final static PirolEdge shiftLine(PirolEdge lineToShift, PirolPoint shiftingVector) throws Exception{
PirolPoint spkt = null, epkt = null;
PirolPoint currPkt = null;
double[] coords = new double[shiftingVector.getDimension()];
for (int i=0; i<2; i++){
if (i==0)
currPkt = lineToShift.getAnfang();
else
currPkt = lineToShift.getEnde();
for (int dim=0; dim<coords.length; dim++){
coords[dim] = currPkt.getCoordinate(dim) + shiftingVector.getCoordinate(dim);
}
if (i==0)
spkt = new PirolPoint((double[])coords.clone());
else
epkt = new PirolPoint((double[])coords.clone());
}
return new PirolEdge(spkt, epkt, lineToShift.isAnfangUnbegrenzt(), lineToShift.isEndeUnbegrenzt());
}
/**
* switch starting and end point of <code>this</code> {@link PirolEdge} instance.
*
*/
public void switchPoints(){
PirolPoint tmp = this.getEnde();
this.setEnde(this.getAnfang());
this.setAnfang(tmp);
}
public static PirolEdge kreiereKanteDurchPunktInnerhalbBegrenzung( PirolPoint p, double steigung, Envelope begrenzung ) throws Exception {
PirolPoint p1 = null, p2 = null;
if (steigung==0){
p1 = new PirolPoint(new double[]{begrenzung.getMinX(), p.getY()} );
p2 = new PirolPoint(new double[]{begrenzung.getMaxX(), p.getY()} );
} else if (steigung==Double.POSITIVE_INFINITY) {
p1 = new PirolPoint(new double[]{p.getX(), begrenzung.getMinY()} );
p2 = new PirolPoint(new double[]{p.getX(), begrenzung.getMaxY()} );
} else if (steigung==Double.NEGATIVE_INFINITY) {
p2 = new PirolPoint(new double[]{p.getX(), begrenzung.getMinY()} );
p1 = new PirolPoint(new double[]{p.getX(), begrenzung.getMaxY()} );
} else {
double minX = begrenzung.getMinX();
double maxX = begrenzung.getMaxX();
double minY = begrenzung.getMinY();
double maxY = begrenzung.getMaxY();
PirolPoint upperLeft = new PirolPoint(new double[]{minX, maxY});
PirolPoint lowerLeft = new PirolPoint(new double[]{minX, minY});
PirolPoint upperRight = new PirolPoint(new double[]{maxX, maxY});
PirolPoint lowerRight = new PirolPoint(new double[]{maxX, minY});
PirolEdge top = new PirolEdge(upperLeft,upperRight);
PirolEdge right = new PirolEdge(upperRight,lowerRight);
PirolEdge bottom = new PirolEdge(lowerRight,lowerLeft);
PirolEdge left = new PirolEdge(lowerLeft,upperLeft);
PirolEdge toBeCut = new PirolEdge(p, steigung, 5.0);
toBeCut.setAnfangUnbegrenzt(true);
toBeCut.setEndeUnbegrenzt(true);
PirolEdge[] kanten = new PirolEdge[]{top, right, bottom, left};
Vector schnittPunkte = new Vector();
PirolPoint sp;
for (int i=0; i<kanten.length; i++){
sp = toBeCut.getSchnittpunkt(kanten[i]);
if (sp != null){
schnittPunkte.add(sp);
}
}
if (schnittPunkte.size() == 2){
// this should happen!!
PirolPoint tmp1 = (PirolPoint)schnittPunkte.get(0);
PirolPoint tmp2 = (PirolPoint)schnittPunkte.get(1);
if (steigung > 0){
if (tmp1.getY()<tmp2.getY()){
p1 = tmp1;
p2 = tmp2;
} else {
p1 = tmp2;
p2 = tmp1;
}
} else {
if (tmp1.getY()>tmp2.getY()){
p1 = tmp1;
p2 = tmp2;
} else {
p1 = tmp2;
p2 = tmp1;
}
}
}
}
return new PirolEdge(p1, p2);
}
public boolean isParallelZu(PirolEdge k) throws Exception{
return this.isParallelZu(k, infinityFaktor);
}
public boolean isParallelZu(PirolEdge k, double infinityFactor) throws Exception{
PirolPoint sp = this.getSchnittpunkt(k);
if (sp==null){
return true;
}
double thisLaenge = this.getAnfang().distanceTo(this.getEnde());
double andereLaenge = k.getAnfang().distanceTo(k.getEnde());
double laenge = (thisLaenge+andereLaenge) / 2.0;
double infiniteDistance = laenge * infinityFactor;
if (this.getAnfang().distanceTo(sp) > infiniteDistance && this.getEnde().distanceTo(sp) > infiniteDistance){
// as good as parallel
return true;
}
//logger.printDebug("not parallel: " + this.getAnfang().distanceTo(sp) + ", " + this.getEnde().distanceTo(sp) + ", infinity: " + infiniteDistance);
return false;
}
public double getSteigung() throws Exception {
double x1 = this.getAnfang().getX();
double x2 = this.getEnde().getX();
double y1 = this.getAnfang().getY();
double y2 = this.getEnde().getY();
double deltaX = x2 - x1;
double deltaY = y2 - y1;
if (deltaX!=0){
return deltaY/deltaX;
}
if (deltaY>0)
return Double.POSITIVE_INFINITY;
else if (deltaY<0)
return Double.NEGATIVE_INFINITY;
else
throw new Exception("wasn't able to calculate the increase of line (starting point == end point)");
}
public static PirolPoint getSchnittpunkt( PirolEdge k1, PirolEdge k2 ) throws Exception {
PirolPoint a = k1.getAnfang();
PirolPoint ab = new PirolPoint(new double[]{k1.getEnde().getX()-a.getX(), k1.getEnde().getY()-a.getY()});
PirolPoint c = k2.getAnfang();
PirolPoint cd = new PirolPoint(new double[]{k2.getEnde().getX()-c.getX(), k2.getEnde().getY()-c.getY()});
if (a.distanceTo(k1.getEnde())==0){
throw new Exception("zero length!");
}
double m = 0.0;
if (ab.getX()==0 && cd.getX()!=0){
m = (a.getX()-c.getX())/cd.getX();
} else if (ab.getX()==0 && cd.getX()==0){
if ( a.getX() != c.getX() )
return null;
else if ( (c.getY() >= a.getY() && c.getY() <= a.getY() + ab.getY()) || (c.getY() <= a.getY() && c.getY() >= a.getY() + ab.getY()) )
return new PirolPoint( new double[]{a.getX(), c.getY()} );
else if ( (a.getY() >= c.getY() && a.getY() <= c.getY() + cd.getY()) || (a.getY() <= c.getY() && a.getY() >= c.getY() + cd.getY()) )
return new PirolPoint( new double[]{a.getX(), a.getY()} );
else
return null;
} else if ( ab.getY()==0 && cd.getY()!=0 ){
m = (a.getY()-c.getY())/cd.getY();
}
/*
else if ( ab.getY() && cd.getY()==0 ){
// sollte nicht auftreten
m = 0;
}
*/
else if ( ab.getX()!=0 && (cd.getX()*ab.getY()/ab.getX())!=cd.getY() ){
m = ( a.getY()-c.getY()+((c.getX()-a.getX())*ab.getY())/ab.getX() )/( cd.getY()-(cd.getX()*ab.getY()/ab.getX()) );
} else {
return null;
}
if ( !k2.isAnfangUnbegrenzt() && m<=0 ){
return null;
}
if ( !k2.isEndeUnbegrenzt() && m>=1 ){
return null;
}
double n = 0.0;
if (ab.getX()==0 && ab.getY()!=0 && cd.getX()!=0){
n = (a.getY()-c.getY()-((a.getX()-c.getX())*cd.getY()/cd.getX()))/(-ab.getY());
} else if (ab.getX()!=0) {
n = (c.getX()+m*cd.getX()-a.getX())/ab.getX();
} else if (cd.getY()==0 && ab.getY()!=0){
n = (c.getY()-a.getY())/ab.getY();
} else {
return null;
}
if ( !k1.isAnfangUnbegrenzt() && n<=0 )
return null;
if ( !k1.isEndeUnbegrenzt() && n>=1 )
return null;
PirolPoint schnittpunkt = new PirolPoint( new double[]{a.getX() + n*ab.getX(), a.getY() + n*ab.getY()} );
return schnittpunkt;
}
public PirolPoint getSchnittpunkt( PirolEdge k2 ) throws Exception{
return PirolEdge.getSchnittpunkt(this, k2);
}
public int vorzeichenDesNormalenFaktors( PirolPoint pkt ) throws Exception{
double fact = this.getNormalenFaktorZu(pkt);
if (fact > 0) return 1;
if (fact < 0) return -1;
return 0;
}
public double getABFaktorZumNormalenFaktor( PirolPoint pkt ) throws Exception{
double normalenFaktor = this.getNormalenFaktorZu(pkt);
PirolPoint a = this.getAnfang();
PirolPoint b = this.getEnde();
PirolPoint c = pkt;
PirolPoint ab = new PirolPoint( new double[]{b.getX()-a.getX(), b.getY()-a.getY()} );
// N ist normale zu ab
PirolPoint N = new PirolPoint( new double[]{ab.getY(), -ab.getX()} );
// berechne faktor y mit dem N multipliziert werden muss, um punkt3 zu erreichen
if (ab.getX()!=0){
double Xx = ( c.getX() - a.getX() - normalenFaktor*N.getX() ) / ab.getX();
return Xx;
}
double Yx = ( c.getY() - a.getY() - normalenFaktor*N.getY() ) / ab.getY();
return Yx;
}
public double getNormalenFaktorZu( PirolPoint pkt ) throws Exception{
PirolPoint punkt1 = this.getAnfang();
PirolPoint punkt2 = this.getEnde();
PirolPoint punkt3 = pkt;
/*
# (C)
# / | \
# / | \
# / |y*N \
# (A)______|_________(B)
# ab ist vektor punkt1 -> punkt2 = a -> b
*/
PirolPoint ab = PirolPoint.createVector(punkt1,punkt2);
// N ist normale zu ab
PirolPoint N = new PirolPoint( new double[]{ab.getY(), -ab.getX()} );
// berechne faktor y mit dem N multipliziert werden muss, um punkt3 zu erreichen
double ergebnis = 0;
try {
if (ab.getX() != 0 && ab.getY() != 0)
ergebnis = ((punkt1.getY()- punkt3.getY())-( punkt1.getX() - punkt3.getX()) * ab.getY() / ab.getX() )/ (N.getX() * ab.getY() / ab.getX() - N.getY());
else if (ab.getX() == 0 )
ergebnis = (punkt3.getX() - punkt1.getX()) / N.getX();
else
ergebnis = (punkt3.getY() - punkt1.getY()) / N.getY();
} catch (Exception e) {
// faengt division durch null fehler ab, die hier aber nicht auftauchen koennen sollten
ergebnis = 1;
//logger.printError(e.getMessage());
}
/*
if (Double.isNaN(ergebnis)){
logger.printError("got Nan!");
logger.printDebug(this.toString());
logger.printDebug(pkt.toString());
logger.printDebug(ab.toString());
logger.printDebug("---");
}
*/
return ergebnis;
}
public PirolEdge getNormalenKante( double laenge ) throws Exception{
PirolPoint punkt1 = this.getAnfang();
PirolPoint punkt2 = this.getEnde();
PirolPoint ab = new PirolPoint( new double[]{punkt2.getX()-punkt1.getX(), punkt2.getY()-punkt1.getY()} );
PirolPoint N = new PirolPoint( new double[]{ab.getY(), -ab.getX()} );
PirolPoint nullPunkt = PirolPoint.NULLPUNKT;
double nLaenge = nullPunkt.distanceTo( N );
double faktor;
try{
faktor = laenge / nLaenge * -1.0;
} catch ( Exception e ) {
faktor = -1.0;
}
N.setX( N.getX()*faktor );
N.setY( N.getY()*faktor );
PirolEdge nKante = new PirolEdge( new PirolPoint( new double[]{punkt2.getX(), punkt2.getY()} ), new PirolPoint( new double[]{punkt2.getX()+N.getX(), punkt2.getY()+N.getY()} ), false, false );
return nKante;
}
public String toString() {
return "Kante<"+this.punktIndexA+","+this.punktIndexB+">["+this.getAnfang().toString()+","+this.getEnde().toString()+"]";
}
public double getLaenge() throws Exception {
if (this.anfang!=null && this.ende!=null){
if (this.anfangUnbegrenzt || this.isEndeUnbegrenzt()) return Double.POSITIVE_INFINITY;
return anfang.distanceTo(ende);
}
throw new Exception(PirolEdge.class.getName()+": Starting point or end point not specified!");
}
public PirolPoint getAnfang() {
return anfang;
}
public void setAnfang(PirolPoint anfang) {
this.anfang = anfang;
}
public boolean isAnfangUnbegrenzt() {
return anfangUnbegrenzt;
}
public void setAnfangUnbegrenzt(boolean anfangUnbegrenzt) {
this.anfangUnbegrenzt = anfangUnbegrenzt;
}
public PirolPoint getEnde() {
return ende;
}
public void setEnde(PirolPoint ende) {
this.ende = ende;
}
public boolean isEndeUnbegrenzt() {
return endeUnbegrenzt;
}
public void setEndeUnbegrenzt(boolean endeUnbegrenzt) {
this.endeUnbegrenzt = endeUnbegrenzt;
}
public boolean isGueltig() {
return gueltig;
}
public void setGueltig(boolean gueltig) {
this.gueltig = gueltig;
}
public int getPunktIndexA() {
return punktIndexA;
}
public void setPunktIndexA(int punktIndexA) {
this.punktIndexA = punktIndexA;
}
public int getPunktIndexB() {
return punktIndexB;
}
public void setPunktIndexB(int punktIndexB) {
this.punktIndexB = punktIndexB;
}
}