/* Spatial Operations & Editing Tools for uDig
*
* Axios Engineering under a funding contract with:
* Diputación Foral de Gipuzkoa, Ordenación Territorial
*
* http://b5m.gipuzkoa.net
* http://www.axios.es
*
* (C) 2006, Diputación Foral de Gipuzkoa, Ordenación Territorial (DFG-OT).
* DFG-OT agrees to license under Lesser General Public License (LGPL).
*
* You can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License as published by the Free Software
* Foundation; version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package es.axios.udig.ui.editingtools.internal.geometryoperations.split;
import java.util.TreeMap;
import junit.framework.TestCase;
import com.vividsolutions.jts.algorithm.Angle;
import com.vividsolutions.jts.algorithm.CGAlgorithms;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Location;
import com.vividsolutions.jts.geomgraph.DirectedEdge;
import com.vividsolutions.jts.geomgraph.DirectedEdgeStar;
import com.vividsolutions.jts.geomgraph.Edge;
import com.vividsolutions.jts.geomgraph.EdgeEnd;
import com.vividsolutions.jts.geomgraph.Label;
import com.vividsolutions.jts.geomgraph.Node;
import com.vividsolutions.jts.geomgraph.NodeMap;
/**
* Test suite for {@link SplitEdgeStar}
*
* @author Aritz Davila (www.axios.es)
* @author Mauricio Pazos (www.axios.es)
* @since 1.1.0
*/
public class SplitEdgeStarTest extends TestCase {
/**
* {@link DirectedEdge} subclass only to support testing
*/
private static class TestDirectedEdge extends DirectedEdge {
public TestDirectedEdge( Edge edge, boolean isForward ) {
super(edge, isForward);
}
public int hashCode() {
return getCoordinate().hashCode() * getDirectedCoordinate().hashCode();
}
public boolean equals( Object o ) {
if (!(o instanceof TestDirectedEdge)) {
return false;
}
TestDirectedEdge edge = (TestDirectedEdge) o;
if (getNode() != edge.getNode()) {
return false;
}
if (isForward() != edge.isForward()) {
return false;
}
boolean equals = getEdge().equals(edge.getEdge());
return equals;
}
/**
* Override {@link DirectedEdge#compareTo(Object)} as it seems to be broken, since it
* compares the orientation of both vectors and often returns <code>0</code> avoiding two
* different DirecteEdge's to be inserted in the {@link DirectedEdgeStar}'s internal
* {@link TreeMap} through {@link DirectedEdgeStar#insert(EdgeEnd)}
*/
@Override
public int compareTo( Object o ) {
TestDirectedEdge e = (TestDirectedEdge) o;
Coordinate c1 = getCoordinate();
Coordinate d1 = getDirectedCoordinate();
Coordinate c2 = e.getCoordinate();
Coordinate d2 = e.getDirectedCoordinate();
int comp = c1.compareTo(c2);
if (0 == comp) {
comp = d1.compareTo(d2);
}
return comp;
}
public String toString() {
StringBuffer sb = new StringBuffer("DirectedEdge[");
sb.append("forward=").append(isForward()).append(" ");
sb.append(getCoordinate().x).append(",").append(getCoordinate().y);
sb.append(":");
sb.append(getDirectedCoordinate().x).append(",").append(getDirectedCoordinate().y);
sb.append(", edge=").append(getEdge());
sb.append("]");
return sb.toString();
}
}
NodeMap nodeMap;
Coordinate[] v1;
DirectedEdge edge1;
Coordinate[] v2;
DirectedEdge edge2;
Coordinate[] v3;
DirectedEdge edge3;
Coordinate[] v4;
DirectedEdge edge4;
/**
* Simple test, rectangle splitted by center vertical line
*
* <pre>
* <code>
* v1 v2
* 0,20------o-------20,20
* | |10,20 |
* | | |
* v1| v4| |v2
* | | |
* | |10,0 |
* o_____o______|20,0
* 0,0 v3 v2
* </code>
* </pre>
*
* @throws Exception
*/
// public void setUp() throws Exception {
// super.setUp();
// nodeMap = new NodeMap(new SplitGraphNodeFactory());
// // build boundary vectors clockwise
// v1 = new Coordinate[]{c(0, 0), c(0, 20), c(10, 20)};
// v2 = new Coordinate[]{c(10, 20), c(20, 20), c(20, 0), c(10, 0)};
// v3 = new Coordinate[]{c(10, 0), c(0, 0)};
// v4 = new Coordinate[]{c(10, 0), c(10, 20)};
//
// edge1 = directedEdge(nodeMap, v1, Location.EXTERIOR, Location.INTERIOR);
// edge2 = directedEdge(nodeMap, v2, Location.EXTERIOR, Location.INTERIOR);
// edge3 = directedEdge(nodeMap, v3, Location.EXTERIOR, Location.INTERIOR);
// edge4 = directedEdge(nodeMap, v4, Location.INTERIOR, Location.INTERIOR);
// }
//
// public void tearDown() throws Exception {
// super.tearDown();
// nodeMap = null;
// v1 = null;
// v2 = null;
// v3 = null;
// v4 = null;
// edge1 = null;
// edge2 = null;
// edge3 = null;
// edge4 = null;
// }
//
// private Coordinate c( double x, double y ) {
// return new Coordinate(x, y);
// }
//
// private DirectedEdge directedEdge( NodeMap nodeMap, Coordinate[] coordinates, int leftLoc,
// int rightLoc ) {
// Label label = new Label(Location.BOUNDARY, leftLoc, rightLoc);
// SplitEdge edge = new SplitEdge(coordinates, label);
// Node node = nodeMap.addNode(coordinates[0]);
//
// boolean isForward = true;
// DirectedEdge de1 = new TestDirectedEdge(edge, isForward);
// isForward = false;
// DirectedEdge de2 = new TestDirectedEdge(edge, isForward);
//
// de1.setNode(node);
// de2.setNode(node);
//
// de1.setSym(de2);
// de2.setSym(de1);
//
// return de1;
// }
//
// public void testInsert() {
// SplitEdgeStar star = new SplitEdgeStar();
// try {
// star.insert(null);
// fail("insert should raise NPE on null argument");
// } catch (NullPointerException e) {
// assertTrue(true);
// }
//
// Coordinate p0 = new Coordinate(0, 0);
// Coordinate p1 = new Coordinate(10, 10);
// Label label = new Label(Location.BOUNDARY, Location.EXTERIOR, Location.INTERIOR);
// SplitEdge edge = new SplitEdge(new Coordinate[]{p0, p1}, label);
// EdgeEnd nonValidEdgeClass = new EdgeEnd(edge, p0, p1);
//
// try {
// star.insert(nonValidEdgeClass);
// fail("insert should only allow " + DirectedEdge.class.getName());
// } catch (ClassCastException e) {
// assertTrue(true);
// }
//
// DirectedEdge de = new TestDirectedEdge(edge, true);
// star.insert(de);
// assertEquals(1, star.getEdges().size());
// assertSame(de, star.getEdges().get(0));
// }
//
// /**
// * Verifies that {@link SplitEdgeStar#findClosestEdgeInDirection(DirectedEdge, int)} returns the
// * correct edge by entering to the node through the given edge and looking towards the specified
// * direction.
// *
// * <pre>
// * <code>
// * v1 N2 v2
// * 0,20------o-------20,20
// * | |10,20 |
// * | | |
// * v1| v4| |v2
// * ˆ ˆ |
// * | |10,0 |
// * o__/__o__/___|20,0
// * 0,0 v3 N1 v2
// * </code>
// * </pre>
// *
// * @throws Exception
// */
// public void testFindClosestEdgeInDirection() {
// SplitEdgeStar starN1 = new SplitEdgeStar();
// starN1.insert(edge2.getSym());
// starN1.insert(edge3);
// starN1.insert(edge4);
// assertEquals(3, starN1.getDegree());
//
// try {
// starN1.findClosestEdgeInDirection(null, CGAlgorithms.COUNTERCLOCKWISE);
// fail("Expected NPE");
// } catch (NullPointerException e) {
// assertTrue(true);
// }
//
// DirectedEdge edge;
// edge = starN1.findClosestEdgeInDirection(edge2.getSym(), CGAlgorithms.COUNTERCLOCKWISE);
// assertSame(edge4, edge);
// edge = starN1.findClosestEdgeInDirection(edge2.getSym(), CGAlgorithms.CLOCKWISE);
// assertSame(edge3, edge);
//
// edge = starN1.findClosestEdgeInDirection(edge3, CGAlgorithms.COUNTERCLOCKWISE);
// assertSame(edge2.getSym(), edge);
// edge = starN1.findClosestEdgeInDirection(edge3, CGAlgorithms.CLOCKWISE);
// assertSame(edge4, edge);
//
// edge = starN1.findClosestEdgeInDirection(edge4, CGAlgorithms.COUNTERCLOCKWISE);
// assertSame(edge3, edge);
// edge = starN1.findClosestEdgeInDirection(edge4, CGAlgorithms.CLOCKWISE);
// assertSame(edge2.getSym(), edge);
//
// // try with another node
// SplitEdgeStar starN2 = new SplitEdgeStar();
// starN2.insert(edge1.getSym());
// starN2.insert(edge2);
// starN2.insert(edge4.getSym());
//
// edge = starN2.findClosestEdgeInDirection(edge1, CGAlgorithms.COUNTERCLOCKWISE);
// assertSame(edge4.getSym(), edge);
// edge = starN2.findClosestEdgeInDirection(edge1, CGAlgorithms.CLOCKWISE);
// assertSame(edge2, edge);
// }
//
// /**
// * Write down our understanding of the angle computation
// */
// public void testAngle() {
// SplitEdgeStar star = new SplitEdgeStar();
//
// Coordinate p0;
// Coordinate p1;
// Coordinate p2;
// double angle;
// double degrees;
//
// p0 = new Coordinate(0, 10);
// p1 = new Coordinate(0, 0);
// p2 = new Coordinate(10, 0);
//
// angle = star.computeAngleInDirection(p0, p1, p2, CGAlgorithms.CLOCKWISE);
// degrees = Angle.toDegrees(angle);
// assertEquals(90.0, degrees);
//
// angle = star.computeAngleInDirection(p0, p1, p2, CGAlgorithms.COUNTERCLOCKWISE);
// degrees = Angle.toDegrees(angle);
// assertEquals(270.0, degrees);
//
// p0 = new Coordinate(0, 10);
// p1 = new Coordinate(10, 0);
// p2 = new Coordinate(0, 0);
//
// angle = star.computeAngleInDirection(p0, p1, p2, CGAlgorithms.COUNTERCLOCKWISE);
// degrees = Angle.toDegrees(angle);
// assertEquals(45.0, degrees);
//
// angle = star.computeAngleInDirection(p0, p1, p2, CGAlgorithms.CLOCKWISE);
// degrees = Angle.toDegrees(angle);
// assertEquals(315.0, degrees);
//
// p0 = new Coordinate(-10, 10);
// p1 = new Coordinate(0, 0);
// p2 = new Coordinate(10, -10);
//
// angle = star.computeAngleInDirection(p0, p1, p2, CGAlgorithms.COUNTERCLOCKWISE);
// degrees = Angle.toDegrees(angle);
// assertEquals(180.0, degrees);
//
// angle = star.computeAngleInDirection(p0, p1, p2, CGAlgorithms.CLOCKWISE);
// degrees = Angle.toDegrees(angle);
// assertEquals(180.0, degrees);
// }
}