code: /*******************************************************************************
   * Copyright (c) 2015 Voyager Search and MITRE
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Apache License, Version 2.0 which
   * accompanies this distribution and is available at
   *    http://www.apache.org/licenses/LICENSE-2.0.txt
   ******************************************************************************/
  
  package org.locationtech.spatial4j.shape;
  
  import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
  import org.locationtech.spatial4j.context.SpatialContext;
  import org.locationtech.spatial4j.context.SpatialContextFactory;
  import org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory;
  import org.locationtech.spatial4j.exception.InvalidShapeException;
  import org.locationtech.spatial4j.shape.impl.*;
  import org.junit.Test;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertFalse;
  import static org.junit.Assert.fail;
  import static org.locationtech.spatial4j.shape.SpatialRelation.CONTAINS;
  import static org.locationtech.spatial4j.shape.SpatialRelation.DISJOINT;
  import static org.locationtech.spatial4j.shape.SpatialRelation.INTERSECTS;
  
  
  public class TestShapes2D extends AbstractTestShapes {
  
    @ParametersFactory
    public static Iterable<Object[]> parameters() {
      final Rectangle WB = new RectangleImpl(-2000, 2000, -300, 300, null);//whatever
  
      List<Object[]> ctxs = new ArrayList<>();
      ctxs.add($(new SpatialContextFactory() {{geo = false; worldBounds = WB;}}.newSpatialContext()));
      ctxs.add($(new JtsSpatialContextFactory() {{geo = false; worldBounds = WB;}}.newSpatialContext()));
      return ctxs;
    }
  
    public TestShapes2D(SpatialContext ctx) {
      super(ctx);
    }
  
    @Test
    public void testSimplePoint() {
      try { ctx.makePoint(2001,0); fail(); } catch (InvalidShapeException e) {}
      try { ctx.makePoint(0, -301); fail(); } catch (InvalidShapeException e) {}
  
      Point pt = ctx.makePoint(0,0);
      String msg = pt.toString();
  
      //test equals & hashcode
      Point pt2 = ctx.makePoint(0,0);
      assertEquals(msg, pt, pt2);
      assertEquals(msg, pt.hashCode(), pt2.hashCode());
  
      assertFalse(msg,pt.hasArea());
      assertEquals(msg,pt.getCenter(),pt);
      Rectangle bbox = pt.getBoundingBox();
      assertFalse(msg,bbox.hasArea());
      assertEquals(msg,pt,bbox.getCenter());
  
      assertRelation(msg, CONTAINS, pt, pt2);
      assertRelation(msg, DISJOINT, pt, ctx.makePoint(0, 1));
      assertRelation(msg, DISJOINT, pt, ctx.makePoint(1, 0));
      assertRelation(msg, DISJOINT, pt, ctx.makePoint(1, 1));
  
      pt.reset(1, 2);
      assertEquals(ctx.makePoint(1, 2), pt);
  
      assertEquals(ctx.makeCircle(pt, 3), pt.getBuffered(3, ctx));
  
      testEmptiness(ctx.makePoint(Double.NaN, Double.NaN));
    }
  
    @Test
    public void testSimpleRectangle() {
      double v = 2001 * (randomBoolean() ? -1 : 1);
      try { ctx.makeRectangle(v,0,0,0); fail(); } catch (InvalidShapeException e) {}
      try { ctx.makeRectangle(0,v,0,0); fail(); } catch (InvalidShapeException e) {}
      try { ctx.makeRectangle(0,0,v,0); fail(); } catch (InvalidShapeException e) {}
      try { ctx.makeRectangle(0,0,0,v); fail(); } catch (InvalidShapeException e) {}
      try { ctx.makeRectangle(0,0,10,-10); fail(); } catch (InvalidShapeException e) {}
      try { ctx.makeRectangle(10,-10,0,0); fail(); } catch (InvalidShapeException e) {}
  
      double[] minXs = new double[]{-1000,-360,-180,-20,0,20,180,1000};
      for (double minX : minXs) {
        double[] widths = new double[]{0,10,180,360,400};
        for (double width : widths) {
          testRectangle(minX, width, 0, 0);
          testRectangle(minX, width, -10, 10);
          testRectangle(minX, width, 5, 10);
        }
      }
  
      Rectangle r = ctx.makeRectangle(0, 0, 0, 0);
      r.reset(1, 2, 3, 4);
      assertEquals(ctx.makeRectangle(1, 2, 3, 4), r);
  
      testRectIntersect();
  
      if (!ctx.isGeo())
        assertEquals(ctx.makeRectangle(0.9, 2.1, 2.9, 4.1), ctx.makeRectangle(1, 2, 3, 4).getBuffered(0.1, ctx));
  
      testEmptiness(ctx.makeRectangle(Double.NaN, Double.NaN, Double.NaN, Double.NaN));
    }
  
    @Test
    public void testSimpleCircle() {
      double[] theXs = new double[]{-10,0,10};
      for (double x : theXs) {
        double[] theYs = new double[]{-20,0,20};
        for (double y : theYs) {
          testCircle(x, y, 0);
          testCircle(x, y, 5);
        }
      }
  
      testCircleReset(ctx);
  
      //INTERSECTION:
      //Start with some static tests that have shown to cause failures at some point:
      assertEquals("getX not getY",INTERSECTS,ctx.makeCircle(107,-81,147).relate(ctx.makeRectangle(92, 121, -89, 74)));
  
      testCircleIntersect();
  
      assertEquals(ctx.makeCircle(1, 2, 10), ctx.makeCircle(1, 2, 6).getBuffered(4, ctx));
  
      testEmptiness(ctx.makeCircle(Double.NaN, Double.NaN, randomBoolean() ? 0 : Double.NaN));
    }
  
    static void testCircleReset(SpatialContext ctx) {
      Circle c = ctx.makeCircle(3, 4, 5);
      Circle c2 = ctx.makeCircle(5, 6, 7);
      c2.reset(3,4,5);// to c1
      assertEquals(c, c2);
      assertEquals(c.getBoundingBox(), c2.getBoundingBox());
    }
  
    @Test
    public void testLineString() {
      //see BufferedLineStringTest & BufferedLineTest for more
      Shape shape = ctx.getShapeFactory().lineString().buffer(randomInt(3)).build();
      testEmptiness(shape);
    }
  
    /** We have this test here but we'll add geo shapes as needed. */
    @Test
    public void testImplementsEqualsAndHash() throws Exception {
      checkShapesImplementEquals( new Class[] {
              PointImpl.class,
              CircleImpl.class,
              //GeoCircle.class  no: its fields are caches, not part of its identity
              RectangleImpl.class,
              ShapeCollection.class,
              BufferedLineString.class,
              BufferedLine.class
      });
    }
  
  }
  