Uso de funciones de datos GeoJSON

La especificación GeoJson define la estructura y el contenido de los objetos JSON que se supone que representan formas geográficas en la tierra (llamadas geometrías). Según la especificación GeoJson, para que un objeto JSON sea un objeto de geometría, debe tener dos campos denominados type y coordinates, donde el valor del campo type especifica el tipo de geometría y el valor de las coordenadas debe ser una matriz cuyos elementos definan la forma geométrica.

Todo tipo de geometrías se especifican en términos de un conjunto de posiciones. Sin embargo, para las cuerdas de línea y polígonos, la forma geométrica real está formada por las líneas que conectan sus posiciones. La especificación GeoJson define una línea entre dos puntos como la línea recta que conecta los puntos en el sistema de coordenadas cartesianas (plano) cuyos ejes horizontal y vertical son la longitud y la latitud, respectivamente.

Hay varias funciones incorporadas que interpretan los objetos JSON como geometrías y permiten buscar las filas que contienen geometrías que cumplen ciertas condiciones.

Para seguir los ejemplos, cree una tabla desde la consola de OCI mediante el modo de entrada DDL avanzada. La sentencia DDL se proporciona a continuación.
CREATE TABLE IF NOT EXISTS PointsOfInterest (
    id INTEGER, poi JSON, 
PRIMARY KEY(id));

Consulte Creación de tablas únicas: modo Entrada de DDL avanzada para conocer los pasos para crear una tabla con una sentencia DDL.

Para cargar datos en la tabla creada desde la consola de OCI, haga clic en el nombre de la tabla. Se muestran los detalles de la tabla. Haga clic en Cargar datos. Haga clic en Seleccionar archivo para cargar y proporcione el archivo JSON que desea cargar. Puede descargar el archivo DDL y JSON para los datos GeoJSON aquí.

geo_inside

Determina las geometrías dentro de una geometría de límite GeoJSON.
boolean geo_inside(any*, any*)
  • El primer parámetro any* puede ser cualquier objeto geométrico.
  • El segundo parámetro any* debe ser un polígono.

La función determina si la geometría apuntando por el primer parámetro está completamente contenida dentro del polígono apuntando por el segundo parámetro.

Si alguno de los dos parámetros no devuelve un solo objeto de geometría válido, y si se puede detectar en tiempo de compilación, la función emite un error.

El comportamiento del tiempo de ejecución es el siguiente:
  • Devuelve false si algún parámetro devuelve 0 o más de 1 elemento.
  • Devuelve NULL si algún parámetro devuelve NULL.
  • Devuelve false si cualquier parámetro (en tiempo de ejecución) devuelve un elemento que no es un objeto de geometría válido.
  • Devuelve false si el segundo parámetro devuelve un objeto de geometría que no es un polígono.
  • Si ambos parámetros devuelven un único objeto de geometría cada uno y la segunda geometría es un polígono.
    • Devuelve verdadero si la primera geometría está completamente contenida dentro del segundo polígono, es decir, todos sus puntos pertenecen al interior del polígono.
    • De lo contrario, devuelve false.

Note:

El interior de un polígono es todos los puntos en el área del polígono, excepto los puntos en el anillo lineal que definen el límite del polígono.
Ejemplo: busque parques naturales en el norte de California.
SELECT t.poi.name AS park_name, 
t.poi.address.street AS park_location
FROM PointsOfInterest t
WHERE t.poi.kind = "nature park"
AND geo_inside(t.poi.location,
              { "type" : "polygon",
                "coordinates": [[
                  [-120.1135253906249, 36.99816565700228],
                  [-119.0972900390625, 37.391981943533544],
                  [-119.2840576171875, 37.97451499202459],
                  [-120.2069091796874, 38.035112420612975],
                  [-122.3822021484375, 37.74031329210266],
                  [-122.2283935546875, 37.15156050223665],
                  [-121.5362548828124, 36.85325222344018],
                  [-120.1135253906249, 36.99816565700228]
                ]]
             });
Explicación:
  • Consulte la tabla PointsOfInterest para filtrar las filas de parque de naturaleza.
  • Especifique un polígono como segundo parámetro de la función geo_inside.
  • Las coordenadas del polígono que especifique corresponden a las coordenadas de la parte norte del estado de California en los Estados Unidos.
  • La función geo_inside solo devuelve filas cuando la ubicación del parque natural está completamente contenida dentro de los puntos de ubicación especificados.
Resultado:
{"park_name":"portola redwoods state park",
"park_location":"15000 Skyline Blvd"}

geo_intersect

Determina las geometrías que se cruzan con una geometría GeoJSON.
boolean geo_intersect(any*, any*)

El primer y el segundo parámetro any* pueden ser cualquier objeto geométrico.

La función determina si dos geometrías que se especifican como parámetros tienen puntos en común. Si alguno de los dos parámetros no devuelve un solo objeto de geometría válido, y si se puede detectar en tiempo de compilación, la función emite un error.

El comportamiento del tiempo de ejecución es el siguiente:
  • Devuelve false si algún parámetro devuelve 0 o más de 1 elemento.
  • Devuelve NULL si algún parámetro devuelve NULL.
  • Devuelve false si cualquier parámetro (en tiempo de ejecución) devuelve un elemento que no es un objeto de geometría válido.

Si ambos parámetros devuelven un único objeto de geometría cada uno, la función devuelve true si las 2 geometrías tienen puntos en común; de lo contrario, false.

Ejemplo: Texas está considerando regular el acceso al suministro de agua subterránea. Un acuífero es una capa subterránea de roca permeable portadora de agua, fracturas de roca o materiales no consolidados. El gobierno quiere imponer nuevas regulaciones para lugares que están muy cerca de un acuífero.

Las coordenadas del acuífero ya han sido mapeadas. Desea conocer todos los condados en el estado de Texas que se cruzan con ese acuífero para que pueda notificar al gobierno del condado para que cada condado afectado participe en conversaciones para las nuevas regulaciones.
SELECT t.poi.county AS County_needs_regulation,
t.poi.contact AS Contact_phone
FROM PointsOfInterest t WHERE
geo_intersect(
    t.poi.location,
    { 

     "type" : "polygon",
      "coordinates": [
          [
            [-97.668457031249, 29.34387539941801],
            [-95.207519531258, 29.19053283229458],
            [-92.900390625653, 30.37287518811801],
            [-94.636230468752, 32.21280106801518],
            [-97.778320312522, 32.45415593941475],
            [-99.799804687541, 31.18460913574325],
            [-97.668457031249, 29.34387539941801]
          ]
        ]
    }
);
Explicación:
  • La consulta anterior recupera las ubicaciones que se cruzan con la ubicación del acuífero. Es decir, si las coordenadas de ubicación tienen algún punto en común con la ubicación del acuífero.
  • Utilice geo_intersect para ver si las coordenadas de la ubicación tienen puntos comunes con las coordenadas del acuífero especificadas.
Resultado:
{"County_needs_regulation":"Tarrant","Contact_phone":"469 745 5687"}
{"County_needs_regulation":"Kinga","Contact_phone":"469 384 7612"}

geo_distance

Determina la distancia entre dos objetos geoespaciales.
double geo_distance(any*, any*)

El primer y el segundo parámetro any* pueden ser cualquier objeto geométrico.

La función devuelve la distancia geodésica entre las dos geometrías de entrada. La distancia devuelta es la mínima entre las distancias de cualquier par de puntos donde el primer punto pertenece a la primera geometría y el segundo punto a la segunda geometría. Entre dos de estos puntos, su distancia es la longitud de la línea geodésica que conecta los puntos.

Visión general de la línea geodésica

Una línea geodésica entre 2 puntos es la línea más corta que se puede trazar entre los 2 puntos en la superficie elipsoidal de la tierra. Para una definición simplificada, pero más ilustrativa, supongamos por un momento que la superficie de la Tierra es una esfera. Entonces, la línea geodésica entre dos puntos en la tierra es el arco menor entre los dos puntos en el gran círculo correspondiente a los puntos, es decir, el círculo que se forma por la intersección de la esfera y el plano definido por el centro de la tierra y los dos puntos.

La siguiente figura muestra la diferencia entre las líneas geodésicas y rectas entre Los Ángeles y Londres.


Si alguno de los dos parámetros no devuelve un solo objeto de geometría válido, y si se puede detectar en tiempo de compilación, la función emite un error.

El comportamiento del tiempo de ejecución es el siguiente:
  • Devuelve -1 si algún parámetro devuelve cero o más de 1 elemento.
  • Devuelve NULL si algún parámetro devuelve NULL.
  • Devuelve -1 si alguno de los parámetros no es un objeto de geometría.
De lo contrario, la función devuelve la distancia geodésica en metros entre las 2 geometrías de entrada.

Note:

Los resultados se ordenan de forma ascendente por distancia (mostrando primero la distancia más corta).
Ejemplo: ¿A qué distancia está el restaurante más cercano de la ubicación indicada?
SELECT 
t.poi.name AS restaurant_name,
t.poi.address.street AS street_name,
geo_distance(
    t.poi.location,
    { 
       "type" : "point",
       "coordinates": [-121.94034576416016,37.2812239247177]
    }
) AS distance_in_meters
FROM PointsOfInterest t
WHERE t.poi.kind = "restaurant" ;
Explicación:
  • Consulte la tabla PointsOfInterest para filtrar las filas de restaurante.
  • Proporcione el punto de ubicación correcto y determine la distancia mediante la función geo_distance.
Resultado:
{"restaurant_name":"Coach Sports Bar & Grill","street_name":"80 Edward St","distance_in_meters":799.2645323337218}
{"restaurant_name":"Ricos Taco","street_name":"80 East Boulevard St","distance_in_meters":976.5361117138553}
{"restaurant_name":"Effie's Restaurant and Bar","street_name":"80 Woodeard St","distance_in_meters":2891.0508307646282}    

La distancia entre la ubicación actual y el restaurante más cercano es de 799 metros.

geo_within_distance

Determina los objetos geoespaciales en proximidad a un punto.
boolean geo_within_distance(any*, any*,double)

El primer y el segundo parámetro any* pueden ser cualquier objeto geométrico.

La función determina si la primera geometría está a una distancia de N metros de la segunda geometría.

Si alguno de los dos parámetros no devuelve un solo objeto de geometría válido, y si se puede detectar en tiempo de compilación, la función emite un error.

El comportamiento del tiempo de ejecución es el siguiente:
  • Devuelve false si algún parámetro devuelve 0 o más de 1 elemento.
  • Devuelve NULL si cualquiera de los dos primeros parámetros devuelve NULL.
  • Devuelve false si alguno de los dos primeros parámetros devuelve un elemento que no es un objeto de geometría válido.

Finalmente, si ambos parámetros devuelven un solo objeto de geometría cada uno, devuelve verdadero si la primera geometría está a una distancia de N metros de la segunda geometría, donde N es el número devuelto por el tercer parámetro; de lo contrario, falso. La distancia entre 2 geometrías se define como el mínimo entre las distancias de cualquier par de puntos donde el primer punto pertenece a la primera geometría y el segundo punto a la segunda geometría. Si N es un número negativo, se establece en 0.

Ejemplo: ¿Hay un ayuntamiento en los próximos 5 km? ¿Hasta dónde llega?
SELECT t.poi.address.street AS city_hall_address,
geo_distance(
    t.poi.location,
    { 
        "type" : "point",
        "coordinates" : [-120.653828125,38.85682013474361]
    }

) AS distance_in_meters
FROM PointsOfInterest t
WHERE t.poi.kind = "city hall" AND
geo_within_distance( 
    t.poi.location,
    { 
        "type" : "point",
        "coordinates" : [-120.653828125,38.85682013474361]
    },
    5000
);
Explicación:
  • Consulte la tabla PointsOfInterest para filtrar las filas del sala de la ciudad.
  • Utilice la función geo_within_distance para filtrar el ayuntamiento a menos de 5 km (5000m) de la ubicación indicada.
  • También puede recuperar la distancia real entre su ubicación y el ayuntamiento mediante la función geo_distance.
Resultado:
{"city_hall_address":"70 North 1st street","distance_in_meters":1736.0144040331768}

El ayuntamiento está a 1736 m (1,73 km) de la ubicación actual.

geo_near

Determina los objetos geoespaciales en proximidad a un punto.
boolean geo_near(any*, any*, double)

El primer y el segundo parámetro any* pueden ser cualquier objeto geométrico.

La función determina si la primera geometría está a una distancia de N metros de la segunda geometría.

Si alguno de los dos parámetros no devuelve un solo objeto de geometría válido, y si se puede detectar en tiempo de compilación, la función emite un error.

El comportamiento del tiempo de ejecución es el siguiente:
  • Devuelve false si algún parámetro devuelve 0 o más de 1 elemento.
  • Devuelve NULL si cualquiera de los dos primeros parámetros devuelve NULL.
  • Devuelve false si alguno de los dos primeros parámetros devuelve un elemento que no es un objeto de geometría válido.
Finalmente, si ambos de los dos primeros parámetros devuelven un solo objeto de geometría cada uno, devuelve true si la primera geometría está a una distancia de N metros de la segunda geometría, donde N es el número devuelto por el tercer parámetro; de lo contrario, false.

Note:

geo_near se convierte internamente a geo_within_distance más un orden (implícito) por la distancia entre las dos geometrías. Sin embargo, si la consulta ya tiene un order-by (explícito), no se realiza ningún order-by por distancia. La función geo_near solo puede aparecer en la cláusula WHERE, donde debe ser un predicado de nivel superior, es decir, no anidado bajo un operador OR o NOT.
Ejemplo 1: ¿hay un hospital a 3 km de la ubicación indicada?
SELECT 
t.poi.name AS hospital_name,
t.poi.address.street AS hospital_address
FROM PointsOfInterest t
WHERE t.poi.kind = "hospital" 
AND
geo_near( 
    t.poi.location,
    {"type" : "point",
     "coordinates" : [-122.03493933105469,37.32949164059004]  
    },
    3000
);
Explicación:
  • Consulte la tabla PointsOfInterest para filtrar las filas de hospital.
  • Utilice la función geo_near para filtrar hospitales dentro de 3000m de la ubicación especificada.
Resultado:
{"hospital_name":"St. Marthas hospital","hospital_address":"18000 West Blvd"}
{"hospital_name":"Memorial hospital","hospital_address":"10500 South St"}
Ejemplo 2: ¿A qué distancia hay una gasolinera en la siguiente milla de la ubicación indicada?
SELECT 
t.poi.address.street AS gas_station_address,
geo_distance(
    t.poi.location,
    { 
        "type" : "point",
        "coordinates" : [-121.90768646240233,37.292081740702365] 
    }
) AS distance_in_meters
FROM PointsOfInterest t
WHERE t.poi.kind = "gas station" AND
geo_near( 
    t.poi.location,
    { 
        "type" : "point",
        "coordinates" : [-121.90768646240233,37.292081740702365]
    },
    1600
);
Explicación:
  • Consulte la tabla PointsOfInterest para filtrar las filas de la estación de servicio.
  • Utilice la función geo_near para filtrar estaciones de servicio en una milla (1600m) de la ubicación indicada.
  • También puede recuperar la distancia real entre su ubicación y la gasolinera mediante la función geo_distance.
Resultado:
{"gas_station_address":"33 North Avenue","distance_in_meters":886.7004173859665}

La distancia real a la gasolinera más cercana en la siguiente milla es 886m.

geo_is_geometry

Valida un objeto geoespacial.
boolean geo_is_geometry(any*)

El parámetro any* puede ser cualquier objeto geométrico.

La función determina si la entrada indicada es un objeto de geometría válido.
  • Devuelve false si el parámetro devuelve cero o más de 1 elemento.
  • Devuelve NULL si el parámetro devuelve NULL.
  • Devuelve true si la entrada es un único objeto de geometría válido. De lo contrario, false.
Ejemplo: determinar si la ubicación que apunta al sala de la ciudad es un objeto geométrico válido.
SELECT geo_is_geometry(t.poi.location) AS city_hall
FROM PointsOfInterest t
WHERE t.poi.kind = "city hall" 

Explicación: utilice la función geo_is_geometry para determinar si una ubicación determinada es un objeto geométrico válido o no.

Resultado:
{ "city_hall" : true}