/* * Copyright (c) 2016 Martin Davis. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v. 1.0 which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * * http://www.eclipse.org/org/documents/edl-v10.php. */ package org.locationtech.jts.algorithm; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Point; import junit.framework.TestCase; import junit.textui.TestRunner; public class RectangleLineIntersectorTest extends TestCase { public static void main(String args[]) { TestRunner.run(RectangleLineIntersectorTest.class); } public RectangleLineIntersectorTest(String name) { super(name); } public void test300Points() { RectangleLineIntersectorValidator test = new RectangleLineIntersectorValidator(); test.init(300); assertTrue(test.validate()); } } /** * Tests optimized RectangleLineIntersector against * a brute force approach (which is assumed to be correct). * * @author Martin Davis * */ class RectangleLineIntersectorValidator { private GeometryFactory geomFact = new GeometryFactory(); private double baseX = 0; private double baseY = 0; private double rectSize = 100; private Envelope rectEnv; private Coordinate[] pts; private boolean isValid = true; public RectangleLineIntersectorValidator() { } public void init(int nPts) { rectEnv = createRectangle(); pts = createTestPoints(nPts); } public boolean validate() { run(true, true); return isValid; } public void run(boolean useSegInt, boolean useSideInt) { RectangleLineIntersector rectSegIntersector = new RectangleLineIntersector(rectEnv); SimpleRectangleIntersector rectSideIntersector = new SimpleRectangleIntersector(rectEnv); for (int i = 0; i < pts.length; i++) { for (int j = 0; j < pts.length; j++) { if (i == j) continue; boolean segResult = false; if (useSegInt) segResult = rectSegIntersector.intersects(pts[i], pts[j]); boolean sideResult = false; if (useSideInt) sideResult = rectSideIntersector.intersects(pts[i], pts[j]); if (useSegInt && useSideInt) { if (segResult != sideResult) isValid = false; } } } } private Coordinate[] createTestPoints(int nPts) { Point pt = geomFact.createPoint(new Coordinate(baseX, baseY)); Geometry circle = pt.buffer(2 * rectSize, nPts/4); return circle.getCoordinates(); } private Envelope createRectangle() { Envelope rectEnv = new Envelope( new Coordinate(baseX, baseY), new Coordinate(baseX + rectSize, baseY + rectSize)); return rectEnv; } } class SimpleRectangleIntersector { // for intersection testing, don't need to set precision model private LineIntersector li = new RobustLineIntersector(); private Envelope rectEnv; /** * The corners of the rectangle, in the order: * 10 * 23 */ private Coordinate[] corner = new Coordinate[4]; public SimpleRectangleIntersector(Envelope rectEnv) { this.rectEnv = rectEnv; initCorners(rectEnv); } private void initCorners(Envelope rectEnv) { corner[0] = new Coordinate(rectEnv.getMaxX(), rectEnv.getMaxY()); corner[1] = new Coordinate(rectEnv.getMinX(), rectEnv.getMaxY()); corner[2] = new Coordinate(rectEnv.getMinX(), rectEnv.getMinY()); corner[3] = new Coordinate(rectEnv.getMaxX(), rectEnv.getMinY()); } public boolean intersects(Coordinate p0, Coordinate p1) { Envelope segEnv = new Envelope(p0, p1); if (! rectEnv.intersects(segEnv)) return false; li.computeIntersection(p0, p1, corner[0], corner[1]); if (li.hasIntersection()) return true; li.computeIntersection(p0, p1, corner[1], corner[2]); if (li.hasIntersection()) return true; li.computeIntersection(p0, p1, corner[2], corner[3]); if (li.hasIntersection()) return true; li.computeIntersection(p0, p1, corner[3], corner[0]); if (li.hasIntersection()) return true; return false; } }