JTS Topology Suite

To work with spatial objects we use HelperJTS. According to Vivid Solutions, JTS Topology Suite (JTS) is an API providing 2D spatial object model and fundamental geometric functions. It implements the geometry model defined in the OpenGIS Consortium Simple Features Specification for SQL. Functions provided include:

and It has the following design goals:

However, to be viable afford even millions of checks per minute, we perform some optimizations, but basic functions remain the same.

Some summary information is available:

Geometry relationships are represented by the following functions returning true or false:

To actually determine a shape based on two geometry:

Some of the most helpful functions are:

The three most difficult methods are here :

There are some book keeping methods to help discovery how the geometry was constructed:

A couple of methods are there to store your developer information:

The code below is based on this two polygons. Its coordinates can be viewed in GerarPoligonoA and GerarPoligonoB methods.

The operations results of the main methods follows in the table below:

AB BA
Equals F F
Disjoint F F
Intersects T T
Touches F F
Crosses F F
Within F F
Contains F F
Overlaps T T
Polygon.java
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
 
import ContextNetGeo.CtxCoordinate;
import ContextNetGeo.Polygon;
 
public class Execute {
 
  /**
   * @param args
   * @throws Exception
   */
 
  public static void main(String[] args) throws Exception {
    Polygon polygonA = GerarPoligonoA();
    Polygon polygonB = GerarPoligonoB();
    testeOperacoes(polygonA, polygonB);
    System.out.println("\nCalculando média do tempo de consulta no poligono sem cache...");
    testeCache(false, polygonA, polygonB);
    polygonA = GerarPoligonoA();
    polygonB = GerarPoligonoB();
    System.out.println("\nCalculando média do tempo de consulta no poligono com cache...");
    testeCache(true, polygonA, polygonB);
 
  }
 
  private static void testeCache(boolean isCached, Polygon polygonA, Polygon polygonB) throws Exception {
    long startTime = System.currentTimeMillis();
    long iterations = 0;
    //Random rdn = new Random();
    polygonA.setCache(isCached, 15000);
    List<CtxCoordinate> listaPontos = gerarPontosAleatorios(1000000);
    polygonA.setCache(isCached, 15000);
    polygonB.setCache(isCached, 15000);
    while (System.currentTimeMillis() - startTime < 30000) {
      // Incrementa a quantidade de iterações feitas dentro de 5 segundos.
      iterations++;
      for (CtxCoordinate ctxCoordinate : listaPontos) {
        polygonA.isPointWithin(ctxCoordinate);
 
        // Incrementa a quantidade de iterações feitas dentro de 5 segundos.
        iterations++;
      }
    }
    long finishTime = System.currentTimeMillis() - startTime;
    // Calcula a média de tempo de cada iteração.
    float media = (float) finishTime / iterations;
 
    if (isCached)
      System.out.println("Média do tempo para consultas aleatórias com cache (ms):" + media);
    else
      System.out.println("Média do tempo para consultas aleatórias sem cache (ms):" + media);
 
    System.out.println("Quantidade de Iterações: " + iterations);
  }
 
  private static List<CtxCoordinate> gerarPontosAleatorios(int quantidade) {
 
    ArrayList<CtxCoordinate> list = new ArrayList<CtxCoordinate>(quantidade);
    Random rdn = new Random();
    for (int i = 0; i < 50; i++) {
      list.add(new CtxCoordinate(rdn.nextInt(100), rdn.nextInt(700)));
    }
 
    return list;
  }
 
  private static void testeOperacoes(Polygon polygonA, Polygon polygonB) {
    System.out.println("AB");
    System.out.println("Equals    : " + polygonA.GetData().equals(polygonB.GetData()));
    System.out.println("disjoint  : " + polygonA.GetData().disjoint(polygonB.GetData()));
    System.out.println("intersects: " + polygonA.GetData().intersects(polygonB.GetData()));
    System.out.println("touches   : " + polygonA.GetData().touches(polygonB.GetData()));
    System.out.println("crosses   : " + polygonA.GetData().crosses(polygonB.GetData()));
    System.out.println("within    : " + polygonA.GetData().within(polygonB.GetData()));
    System.out.println("contains  : " + polygonA.GetData().contains(polygonB.GetData()));
    System.out.println("overlaps  : " + polygonA.GetData().overlaps(polygonB.GetData()));
 
    System.out.println("\n");
    System.out.println("BA");
    System.out.println("Equals    : " + polygonB.GetData().equals(polygonA.GetData()));
    System.out.println("disjoint  : " + polygonB.GetData().disjoint(polygonA.GetData()));
    System.out.println("intersects: " + polygonB.GetData().intersects(polygonA.GetData()));
    System.out.println("touches   : " + polygonB.GetData().touches(polygonA.GetData()));
    System.out.println("crosses   : " + polygonB.GetData().crosses(polygonA.GetData()));
    System.out.println("within    : " + polygonB.GetData().within(polygonA.GetData()));
    System.out.println("contains  : " + polygonB.GetData().contains(polygonA.GetData()));
    System.out.println("overlaps  : " + polygonB.GetData().overlaps(polygonA.GetData()));
  }
 
  private static Polygon GerarPoligonoA() {
    // Poligono 1 - Externa
    ArrayList<CtxCoordinate> listaCoordenadasMaster = new ArrayList<CtxCoordinate>();
 
    listaCoordenadasMaster.add(new CtxCoordinate(30, 260));
    listaCoordenadasMaster.add(new CtxCoordinate(130, 350));
    listaCoordenadasMaster.add(new CtxCoordinate(250, 330));
    listaCoordenadasMaster.add(new CtxCoordinate(320, 180));
    listaCoordenadasMaster.add(new CtxCoordinate(250, 50));
    listaCoordenadasMaster.add(new CtxCoordinate(70, 60));
    listaCoordenadasMaster.add(new CtxCoordinate(30, 260));
 
    // Poligono 1 - Interna
    ArrayList<CtxCoordinate> listaCoordenadasEscravo = new ArrayList<CtxCoordinate>();
    listaCoordenadasEscravo.add(new CtxCoordinate(140, 260));
    listaCoordenadasEscravo.add(new CtxCoordinate(110, 150));
    listaCoordenadasEscravo.add(new CtxCoordinate(230, 210));
    listaCoordenadasEscravo.add(new CtxCoordinate(140, 210));
    listaCoordenadasEscravo.add(new CtxCoordinate(140, 260));
 
    return new Polygon(listaCoordenadasMaster, listaCoordenadasEscravo);
  }
 
  private static Polygon GerarPoligonoB() {
    // Poligono 1 - Externa
    ArrayList<CtxCoordinate> listaCoordenadasMaster = new ArrayList<CtxCoordinate>();
    listaCoordenadasMaster.add(new CtxCoordinate(210, 390));
    listaCoordenadasMaster.add(new CtxCoordinate(180, 290));
    listaCoordenadasMaster.add(new CtxCoordinate(170, 210));
    listaCoordenadasMaster.add(new CtxCoordinate(190, 140));
    listaCoordenadasMaster.add(new CtxCoordinate(360, 60));
    listaCoordenadasMaster.add(new CtxCoordinate(470, 220));
    listaCoordenadasMaster.add(new CtxCoordinate(440, 390));
    listaCoordenadasMaster.add(new CtxCoordinate(210, 390));
 
    // Poligono 1 - Interna
    ArrayList<CtxCoordinate> listaCoordenadasEscravo = new ArrayList<CtxCoordinate>();
    listaCoordenadasEscravo.add(new CtxCoordinate(340, 310));
    listaCoordenadasEscravo.add(new CtxCoordinate(250, 260));
    listaCoordenadasEscravo.add(new CtxCoordinate(270, 140));
    listaCoordenadasEscravo.add(new CtxCoordinate(360, 130));
    listaCoordenadasEscravo.add(new CtxCoordinate(390, 230));
    listaCoordenadasEscravo.add(new CtxCoordinate(340, 310));
 
    return new Polygon(listaCoordenadasMaster, listaCoordenadasEscravo);
  }
}