LineSegment2DFunctions.java

  1. /*
  2.  * Copyright 2015 gregory.graham.
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *      http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. package nz.co.gregs.dbvolution.internal.sqlite;

  17. import java.sql.Connection;
  18. import java.sql.SQLException;
  19. import java.util.logging.Level;
  20. import java.util.logging.Logger;
  21. import com.vividsolutions.jts.geom.*;
  22. import com.vividsolutions.jts.io.ParseException;
  23. import com.vividsolutions.jts.io.WKTReader;
  24. import org.sqlite.Function;

  25. /**
  26.  *
  27.  *
  28.  * @author gregory.graham
  29.  */
  30. public class LineSegment2DFunctions {

  31.     /**
  32.      *
  33.      */
  34.     public final static String CREATE_FROM_COORDS_FUNCTION = "DBV_CREATE_LINESEGMENT2D_FROM_COORDS";

  35.     /**
  36.      *
  37.      */
  38.     public final static String EQUALS_FUNCTION = "DBV_LINESEGMENT2D_EQUALS";

  39.     /**
  40.      *
  41.      */
  42.     public final static String GETMAXX_FUNCTION = "DBV_LINESEGMENT2D_GETMAXX";

  43.     /**
  44.      *
  45.      */
  46.     public final static String GETMAXY_FUNCTION = "DBV_LINESEGMENT2D_GETMAXY";

  47.     /**
  48.      *
  49.      */
  50.     public final static String GETMINX_FUNCTION = "DBV_LINESEGMENT2D_GETMINX";

  51.     /**
  52.      *
  53.      */
  54.     public final static String GETMINY_FUNCTION = "DBV_LINE2D_GETMINY";

  55.     /**
  56.      *
  57.      */
  58.     public final static String GETDIMENSION_FUNCTION = "DBV_LINESEGMENT2D_GETDIMENSION";

  59.     /**
  60.      *
  61.      */
  62.     public final static String GETBOUNDINGBOX_FUNCTION = "DBV_LINESEGMENT2D_GETBOUNDINGBOX";

  63.     /**
  64.      *
  65.      */
  66.     public final static String ASTEXT_FUNCTION = "DBV_LINESEGMENT2D_ASTEXT";

  67.     /**
  68.      *
  69.      */
  70.     public final static String SPATIAL_LINE_MIN_X_COORD_FUNCTION = "DBV_LINESEGMENT2D_MIN_X2D_COORD";

  71.     /**
  72.      *
  73.      */
  74.     public final static String SPATIAL_LINE_MAX_Y_COORD_FUNCTION = "DBV_LINESEGMENT2D_MAX_Y2D_COORD";

  75.     /**
  76.      *
  77.      */
  78.     public final static String SPATIAL_LINE_MIN_Y_COORD_FUNCTION = "DBV_LINESEGMENT2D_MIN_Y2D_COORD";

  79.     /**
  80.      *
  81.      */
  82.     public final static String SPATIAL_LINE_MAX_X_COORD_FUNCTION = "DBV_LINESEGMENT2D_MAX_X2D_COORD";

  83.     /**
  84.      *
  85.      */
  86.     public final static String INTERSECTS = "DBV_LINESEGMENT2D_INTERSECTS_LINESEGMENT2D";

  87.     /**
  88.      *
  89.      */
  90.     public final static String INTERSECTIONWITH_LINESEGMENT2D = "DBV_LINESEGMENT2D_INTERSECTIONWITH_LINESEGMENT2D";

  91.     private LineSegment2DFunctions() {
  92.     }

  93.     /**
  94.      *
  95.      * @param connection the database to add functions to
  96.      * @throws SQLException database errors
  97.      */
  98.     public static void addFunctions(Connection connection) throws SQLException {
  99.         Function.create(connection, CREATE_FROM_COORDS_FUNCTION, new CreateFromCoords());
  100.         Function.create(connection, EQUALS_FUNCTION, new Equals());
  101.         Function.create(connection, GETMAXX_FUNCTION, new GetMaxX());
  102.         Function.create(connection, GETMAXY_FUNCTION, new GetMaxY());
  103.         Function.create(connection, GETMINX_FUNCTION, new GetMinX());
  104.         Function.create(connection, GETMINY_FUNCTION, new GetMinY());
  105.         Function.create(connection, GETDIMENSION_FUNCTION, new GetDimension());
  106.         Function.create(connection, GETBOUNDINGBOX_FUNCTION, new GetBoundingBox());
  107.         Function.create(connection, ASTEXT_FUNCTION, new AsText());
  108.         Function.create(connection, INTERSECTS, new Intersects());
  109.         Function.create(connection, INTERSECTIONWITH_LINESEGMENT2D, new IntersectionWith());
  110.     }

  111.     private static class CreateFromCoords extends PolygonFunction {
  112. //LINESTRING (2 3, 3 4)

  113.         @Override
  114.         protected void xFunc() throws SQLException {
  115.             Integer numberOfArguments = args();
  116.             if (numberOfArguments != 2) {
  117.                 result();
  118.             } else {
  119.                 StringBuilder resultStr = new StringBuilder("LINESTRING (");
  120.                 String sep = "";
  121.                 for (int i = 0; i < numberOfArguments; i += 2) {
  122.                     Double x = value_double(i);
  123.                     Double y = value_double(i + 1);
  124.                     if (x == null || y == null) {
  125.                         result();
  126.                         return;
  127.                     } else {
  128.                         resultStr.append(sep).append(x).append(" ").append(y);
  129.                         sep = ", ";
  130.                     }
  131.                 }
  132.                 resultStr.append(")");
  133.                 result(resultStr.toString());
  134.             }
  135.         }
  136.     }

  137.     private static class Equals extends PolygonFunction {

  138.         @Override
  139.         protected void xFunc() throws SQLException {
  140.             String firstPoint = value_text(0);
  141.             String secondPoint = value_text(1);
  142.             if (firstPoint == null || secondPoint == null) {
  143.                 result();
  144.             } else {
  145.                 result(firstPoint.equals(secondPoint) ? 1 : 0);
  146.             }
  147.         }
  148.     }

  149.     private static class GetMaxX extends PolygonFunction {

  150.         @Override
  151.         protected void xFunc() throws SQLException {
  152.             String firstLine = value_text(0);
  153.             if (firstLine == null) {
  154.                 result();
  155.             } else {
  156.                 Double maxX = null;
  157.                 String[] split = firstLine.split("[ (),]+");
  158.                 for (int i = 1; i < split.length; i += 2) {
  159.                     double x = Double.parseDouble(split[i]);
  160. //                  double y = Double.parseDouble(split[i + 1]);
  161.                     if (maxX == null || maxX < x) {
  162.                         maxX = x;
  163.                     }
  164.                 }
  165.                 result(maxX);
  166.             }
  167.         }

  168.     }

  169.     private static class GetMaxY extends PolygonFunction {

  170.         @Override
  171.         protected void xFunc() throws SQLException {
  172.             String firstPoint = value_text(0);
  173.             if (firstPoint == null) {
  174.                 result();
  175.             } else {
  176.                 Double maxY = null;
  177.                 String[] split = firstPoint.split("[ (),]+");
  178.                 for (int i = 1; i < split.length; i += 2) {
  179. //                  double x = Double.parseDouble(split[i]);
  180.                     double y = Double.parseDouble(split[i + 1]);
  181.                     if (maxY == null || maxY < y) {
  182.                         maxY = y;
  183.                     }
  184.                 }
  185.                 result(maxY);
  186.             }
  187.         }
  188.     }

  189.     private static class GetMinX extends PolygonFunction {

  190.         @Override
  191.         protected void xFunc() throws SQLException {
  192.             String firstPoint = value_text(0);
  193.             if (firstPoint == null) {
  194.                 result();
  195.             } else {
  196.                 Double minX = null;
  197.                 String[] split = firstPoint.split("[ (),]+");
  198.                 for (int i = 1; i < split.length; i += 2) {
  199.                     double x = Double.parseDouble(split[i]);
  200. //                  double y = Double.parseDouble(split[i + 1]);
  201.                     if (minX == null || minX > x) {
  202.                         minX = x;
  203.                     }
  204.                 }
  205.                 result(minX);
  206.             }
  207.         }

  208.     }

  209.     private static class GetMinY extends PolygonFunction {

  210.         @Override
  211.         protected void xFunc() throws SQLException {
  212.             String firstPoint = value_text(0);
  213.             if (firstPoint == null) {
  214.                 result();
  215.             } else {
  216.                 Double minY = null;
  217.                 String[] split = firstPoint.split("[ (),]+");
  218.                 for (int i = 1; i < split.length; i += 2) {
  219. //                  double x = Double.parseDouble(split[i]);
  220.                     double y = Double.parseDouble(split[i + 1]);
  221.                     if (minY == null || minY > y) {
  222.                         minY = y;
  223.                     }
  224.                 }
  225.                 result(minY);
  226.             }
  227.         }
  228.     }

  229.     private static class Intersects extends PolygonFunction {

  230.         @Override
  231.         protected void xFunc() throws SQLException {
  232.             try {
  233.                 String firstLineStr = value_text(0);
  234.                 String secondLineStr = value_text(1);
  235.                 if (firstLineStr == null) {
  236.                     result();
  237.                 } else if (secondLineStr == null) {
  238.                     result();
  239.                 } else {
  240.                     LineString firstLine = getLineString(firstLineStr);
  241.                     LineString secondLine = getLineString(secondLineStr);
  242.                     if (firstLine == null || secondLine == null) {
  243.                         result();
  244.                     } else {
  245.                         result(firstLine.intersects(secondLine) ? 1 : 0);
  246.                     }
  247.                 }
  248.             } catch (ParseException ex) {
  249.                 Logger.getLogger(Line2DFunctions.class.getName()).log(Level.SEVERE, null, ex);
  250.                 throw new RuntimeException("Failed To Parse SQLite Polygon", ex);
  251.             }
  252.         }
  253.     }

  254.     private static class IntersectionWith extends PolygonFunction {

  255.         @Override
  256.         protected void xFunc() throws SQLException {
  257.             try {
  258.                 String firstLineStr = value_text(0);
  259.                 String secondLineStr = value_text(1);
  260.                 if (firstLineStr == null) {
  261.                     result();
  262.                 } else if (secondLineStr == null) {
  263.                     result();
  264.                 } else {
  265.                     LineString firstLine = getLineString(firstLineStr);
  266.                     LineString secondLine = getLineString(secondLineStr);
  267.                     if (firstLine == null || secondLine == null) {
  268.                         result();
  269.                     } else {
  270.                         final Geometry intersectionPoint = firstLine.intersection(secondLine);
  271.                         if (intersectionPoint instanceof Point) {
  272.                             result(intersectionPoint.toText());
  273.                         } else {
  274.                             result();
  275.                         }
  276.                     }
  277.                 }
  278.             } catch (ParseException ex) {
  279.                 Logger.getLogger(Line2DFunctions.class.getName()).log(Level.SEVERE, null, ex);
  280.                 throw new RuntimeException("Failed To Parse SQLite geometry", ex);
  281.             }
  282.         }
  283.     }

  284.     private static class GetDimension extends PolygonFunction {

  285.         @Override
  286.         protected void xFunc() throws SQLException {
  287.             result(1);
  288.         }
  289.     }

  290.     private static class GetBoundingBox extends PolygonFunction {

  291.         @Override
  292.         protected void xFunc() throws SQLException {
  293.             String firstLine = value_text(0);
  294.             if (firstLine == null) {
  295.                 result();
  296.             } else {
  297.                 Double maxX = null;
  298.                 Double maxY = null;
  299.                 Double minX = null;
  300.                 Double minY = null;
  301.                 String[] split = firstLine.split("[ (),]+");
  302.                 for (int i = 1; i < split.length; i += 2) {
  303.                     double x = Double.parseDouble(split[i]);
  304.                     double y = Double.parseDouble(split[i + 1]);
  305.                     if (maxX == null || maxX < x) {
  306.                         maxX = x;
  307.                     }
  308.                     if (maxY == null || maxY < y) {
  309.                         maxY = y;
  310.                     }
  311.                     if (minX == null || minX > x) {
  312.                         minX = x;
  313.                     }
  314.                     if (minY == null || minY > y) {
  315.                         minY = y;
  316.                     }
  317.                 }
  318.                 String resultString = "POLYGON ((" + minX + " " + minY + ", " + maxX + " " + minY + ", " + maxX + " " + maxY + ", " + minX + " " + maxY + ", " + minX + " " + minY + "))";
  319.                 result(resultString);
  320.             }
  321.         }
  322.     }

  323.     private static class AsText extends Function {

  324.         @Override
  325.         protected void xFunc() throws SQLException {
  326.             String point = value_text(0);
  327.             result(point);
  328.         }
  329.     }

  330.     private static abstract class PolygonFunction extends Function {

  331.         Polygon getPolygon(String possiblePoly) throws ParseException {
  332.             WKTReader wktReader = new WKTReader();
  333.             Geometry firstGeom = wktReader.read(possiblePoly);
  334.             if (firstGeom instanceof Polygon) {
  335.                 return (Polygon) firstGeom;
  336.             }
  337.             return null;
  338.         }

  339.         LineString getLineString(String possiblePoly) throws ParseException {
  340.             WKTReader wktReader = new WKTReader();
  341.             Geometry firstGeom = wktReader.read(possiblePoly);
  342.             if (firstGeom instanceof LineString) {
  343.                 return (LineString) firstGeom;
  344.             }
  345.             return null;
  346.         }

  347.         Point getPoint(String possiblePoly) throws ParseException {
  348.             WKTReader wktReader = new WKTReader();
  349.             Geometry firstGeom = wktReader.read(possiblePoly);
  350.             if (firstGeom instanceof Point) {
  351.                 return (Point) firstGeom;
  352.             }
  353.             return null;
  354.         }
  355.     }

  356. }