/*******************************************************************************
* Copyright (c) 2011, 2015 itemis AG and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alexander Nyßen (itemis AG) - initial API and implementation
* Matthias Wienand (itemis AG) - IMultiShape semantics for touches()
*
*******************************************************************************/
package org.eclipse.gef.geometry.planar;
/**
* The abstract base class for all {@link IGeometry}s. It provides generic
* support for cloning ({@link Cloneable}) by delegating to {@link #getCopy()},
* which needs to be implemented by subclasses. Further, provides generic
* support for affine transformations by applying the respective
* {@link AffineTransform} to the path representation of this
* {@link AbstractGeometry} (see {@link #toPath()}). Implements overlap
* detection ({@link #touches(IGeometry)}) for all known {@link IGeometry}s.
*
* @author anyssen
* @author mwienand
*
*/
abstract class AbstractGeometry implements IGeometry {
private static final long serialVersionUID = 1L;
/**
* Overridden with public visibility as recommended within {@link Cloneable}
* .
*/
@Override
public Object clone() {
return getCopy();
}
/**
* Default implementation returning a transformed {@link Path}
* representation of this {@link IGeometry}. Subclasses may override this
* method to return a more specific representation.
*
* @return a transformed {@link Path} representation of this
* {@link IGeometry}
*/
@Override
public IGeometry getTransformed(final AffineTransform t) {
return toPath().getTransformed(t);
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public final int hashCode() {
// calculating a better hashCode is not possible, because due to the
// imprecision, equals() is no longer transitive
return 0;
}
@Override
public boolean touches(final IGeometry g) {
if (this instanceof ICurve) {
if (g instanceof ICurve) {
return ((ICurve) this).intersects((ICurve) g)
|| ((ICurve) this).overlaps((ICurve) g);
} else if (g instanceof IShape) {
return ((IShape) g).contains(this)
|| this.touches(((IShape) g).getOutline());
} else if (g instanceof IMultiShape) {
if (((IMultiShape) g).contains(this)) {
return true;
}
for (ICurve c : ((IMultiShape) g).getOutlineSegments()) {
if (this.touches(c)) {
return true;
}
}
return false;
} else {
throw new UnsupportedOperationException(
"Not yet implemented: touches(" + this + ", " + g
+ ")");
}
} else if (this instanceof IShape) {
if (g instanceof ICurve) {
return ((IShape) this).contains(g)
|| ((IShape) this).getOutline().touches(g);
} else if (g instanceof IShape) {
return ((IShape) this).contains(g)
|| ((IShape) g).contains(this)
|| ((IShape) this).getOutline()
.touches(((IShape) g).getOutline());
} else if (g instanceof IMultiShape) {
if (((IShape) this).contains(g)) {
return true;
}
if (((IMultiShape) g).contains(this)) {
return true;
}
ICurve thisOutline = ((IShape) this).getOutline();
for (ICurve c : ((IMultiShape) g).getOutlineSegments()) {
if (thisOutline.touches(c)) {
return true;
}
}
return false;
} else {
throw new UnsupportedOperationException(
"Not yet implemented: touches(" + this + ", " + g
+ ")");
}
} else if (this instanceof IMultiShape) {
IMultiShape thisPolyShape = (IMultiShape) this;
if (g instanceof ICurve) {
ICurve gCurve = (ICurve) g;
if (thisPolyShape.contains(gCurve)) {
return true;
}
for (ICurve c : thisPolyShape.getOutlineSegments()) {
if (gCurve.touches(c)) {
return true;
}
}
return false;
} else if (g instanceof IShape) {
IShape gShape = (IShape) g;
if (thisPolyShape.contains(gShape)
|| gShape.contains(thisPolyShape)) {
return true;
}
ICurve gOutline = gShape.getOutline();
for (ICurve c : thisPolyShape.getOutlineSegments()) {
if (gOutline.touches(c)) {
return true;
}
}
return false;
} else if (g instanceof IMultiShape) {
IMultiShape gMultiShape = (IMultiShape) g;
if (thisPolyShape.contains(gMultiShape)
|| gMultiShape.contains(thisPolyShape)) {
return true;
}
for (ICurve thisOutlineSeg : thisPolyShape
.getOutlineSegments()) {
for (ICurve gOutlineSeg : gMultiShape
.getOutlineSegments()) {
if (thisOutlineSeg.touches(gOutlineSeg)) {
return true;
}
}
}
return false;
} else {
throw new UnsupportedOperationException(
"Not yet implemented: touches(" + this + ", " + g
+ ")");
}
} else {
throw new UnsupportedOperationException(
"Not yet implemented: touches(" + this + ", " + g + ")");
}
}
}