Capítulo 18. Extensiones espaciales de MySQL
Anterior |  | Siguiente

## Capítulo 18. Extensiones espaciales de MySQL

MySQL 4.1 introuce las extensiones espaciales para permitir la generación, almacenamiento, y análisis de elementos geográficos. Actualmente, estas características están solo disponibles para tablas `MyISAM`.

Este capítulo trata los siguientes temas:

- La base de estas extensiones espaciales es el modelo de geometría OpenGIS

- Formatos de datos para representar datos espaciales

- Cómo usar datos espaciales en MySQL

- Uso de indexación para datos espaciales

- Diferencias entre MySQL y la especificación OpenGIS

## 18.1. Introducción

MySQL implementa extensiones espaciales siguiendo la especificación del `Consorcio Open GIS` (OGC), un consorcio internacional de más de 250 compañías, agencias y universidades que participan en el desarrollo de soluciones conceptuales públicamente disponibles y que pueden ser útiles para todo tipo de aplicaciones que manejan datos espaciales. El OGC matiene una web en http://www.opengis.org/.

En 1997, el Consorcio Open GIS publicó las Especificaciones de características simples Open GIS para SQL, un documento que propone diversas maneras conceptuales de extender un Sistema Gestor de Bases de Datos Relacionales para agregar soporte a datos espaciales. Esta especificación está disponible en http://www.opengis.org/docs/99-049.pdf. Contiene información adicional relevante relacionada con este capítulo.

MySQL implementa un subconjunto del entorno SQL con Tipos Geométricos propuesto por el OGC. Este término se refiere a un entorno SQL que ha sido extendido con un conjunto de tipos geométricos. Una columna SQL con valores geométricos se implementa como una columna que tiene un tipo geométrico. Las especificaciones describen un conjunto de tipos geométricos SQL, así como las funciones para analizar y crear valores geométricos sobre esos tipos.

Un elemento geográfico es cualquier cosa en el mundo que tenga una ubicación. Un elemento puede ser:

- Una entidad. Por ejemplo, una montaña, un lago, una ciudad.

- Un espacio. Por ejemplo, un área de código postal, los trópicos.

- Una ubicación definible. Por ejemplo, un cruce de carreteras, como un lugar partícular donde dos calles se interseccionan.

También puede encontrar documentos que utilicen el término elementos geoespaciales para referirse a elementos geográficos.

Geometría es otra palabra que denota un elemento geográfico. Originalmente la palabra geometría significaba medición de la tierra. Otro significado viene de la cartografía, refiriéndose a los elementos geométricos que los cartógrafos utilizan para crear mapas del mundo.

Este capítulo utiliza todos estos términos a modo de sinónimos: This chapter uses all of these terms synonymously: elemento geográfico, elemento geoespacial, elemento, o geometría. El término más comúnmente utilizado aquí es geometría.

Definamos una geometría como un punto o conjunto de puntos representando cualquier cosa en el mundo que tenga una ubicación.

## 18.2. El modelo geométrico OpenGIS

El conjunto de tipos geométricos propuesto por el entorno SQL con Tipos Geométricos de OGC's se basa en el Modelo OpenGIS de Geometría. En este modelo, cada objeto geométrico tiene las siguientes propiedades generales:

- Está asociado con un Sistema de Referencia Espacial, que describe el espacio de coordenadas en que el objeto está definido.

- Pertenece a alguna clase geométrica.

### 18.2.1. La jerarquía de las clases geométricas

Las clases geométricas definen una jerarquía de la siguiente manera:

- `Geometry` (no instanciable)

  - `Point` (instanciable)

  - `Curve` (no instanciable)

    - `LineString` (instanciable)

      - `Line`

      - `LinearRing`

  - `Surface` (no instanciable)

    - `Polygon` (instanciable)

  - `GeometryCollection` (instanciable)

    - `MultiPoint` (instanciable)

    - `MultiCurve` (no instanciable)

      - `MultiLineString` (instanciable)

    - `MultiSurface` (no instanciable)

      - `MultiPolygon` (instanciable)

No es posible crear objetos de clases no instanciables. Se pueden crear objetos de clases instanciables. Todas las clases tienen propiedades, y las clases instanciables pueden tener también aserciones (reglas que definen las instancias de clase válidas).

`Geometry` es la clase base. Es una clase abstracta. Las subclases instanciables de `Geometry` están restringidas a objetos geométricos cero-, uni-, y bi-dimensionales que existen en un espacio de coordenadas bidimensional. Todas las clases geométricas instanciables son definidas de manera que las instancias válidas de una clase geométrica sean topológicamente cerradas (es decir, que todas las geometrías definidas incluyen su límite).

La clase base `Geometry` tiene las subclases `Point`, `Curve`, `Surface`, y `GeometryCollection`:

- `Point` representa objetos de cero dimensiones.

- `Curve` representa objetos unidimensionales, y tiene la subclase `LineString`, con sub-subclases `Line` y `LinearRing`.

- `Surface` está diseñado para objetos bidimensionales y tiene la subclase `Polygon`.

- `GeometryCollection` tiene clases especializadas de cero, una y dos dimensiones llamadas `MultiPoint`, `MultiLineString`, y `MultiPolygon` para modelar geometrías correspondientes a colecciones de `Points`, `LineStrings`, y `Polygons`, respectivamente. `MultiCurve` y `MultiSurface` han sido introducidas como superclases abstractas que generalizan las interfaces de la colección para manejar `Curves` y `Surfaces`.

`Geometry`, `Curve`, `Surface`, `MultiCurve`, y `MultiSurface` están definidas como clases no instanciables. Definen un conjunto común de métodos para sus subclases y se incluyen para ser extendidas.

`Point`, `LineString`, `Polygon`, `GeometryCollection`, `MultiPoint`, `MultiLineString`, y `MultiPolygon` son clases instanciables.

### 18.2.2. La clase `Geometry`

`Geometry` es la clase base de la jerarquía. Es una clase no instanciable, pero tiene unas cuantas propiedades que son comunes para todos los valores geométricos creados con cualquiera de las subclases de `Geometry`. Estas propiedades están descritas en la siguiente lista. (Algunas subclases en concreto tienen sus propiedades específicas, descritas más tarde.)

Propiedades de Geometry

Un valor geométrico tiene las siguientes propiedades:

- Su tipo. Cada geometría pertenece a una de las clases instanciables de la jerarquía.

- Su SRID, o IDentificador de Referencia eSpacial. Este valor identifica el Sistema de Referencia Espacial asociado a la geometría, que describe el espacio de coordenadas en el que la geometría está definida.

  ç En MySQL, el valor SRID es simplemente un entero asociado con el valor de la geometría. Todos los cálculos se hacen asumiendo una geometría euclídea (planar).

- Sus coordenadas en este Sistema de Referencia Espacial, representadas como números de doble precisión (ocho bytes). Todas las geometrías no vacías incluyen al menos un par de coordenadas (X,Y). Las geometrías vacías no contienen coordenadas.

  Las coordenadas están relacionadas con el SRID. Por ejemplo, en diferentes sistemas de coordenadas, la distancia entre dos objetos puede diferir aún cuando los objetos tengan las mismas coordenadas, porque la distancia en sistemas de coordenadas planares y la distancia en sistemas geocéntricos (coordenadas en la superficie de la tierra) son cosas diferentes.

- Su interior, límite, y exterior.

  Cada geometría ocupa una posición en el espacio. El exterior de una geometría es todo el espacio no ocupado por la geometría. El interior es el espacio ocupado por la geometría. El límite es la interfaz entre el interior y el exterior de la geometría.

- Its MBR (Minimum Bounding Rectangle), or Envelope. This is the bounding geometry, formed by the minimum and maximum (X,Y) coordinates:

      ((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))

- Si el valor es simple o no-simple. Los valores geométricos de tipo (`LineString`, `MultiPoint`, `MultiLineString`) son o simples, o no-simples. Cada tipo determina sus propias aserciones para ser simple o no-simple.

- Si el valor es cerrado o no cerrado. Los valores geométricos de tipo (`LineString`, `MultiString`) son o cerrados o no cerrados. Cada tipo determina sus propias aserciones para ser cerrado o no cerrado.

- Si el valor es vacío o no vacío. Una geometría es vacía si no tiene ningún punto. El exterior, interior, y límite de de una geometría vacía no están definidos (es decir, se representan por un valor `NULL`). Una geometría vacía está definida para ser siempre simple, y tiene un área de 0.

- Su dimensión. Una geometría puede tener una dimensión de −1, 0, 1, o 2:

  - −1 para una geometría vacía.

  - 0 para una geometría sin longitud ni área.

  - 1 para una geometría con longitud diferente de cero y área igual a cero.

  - 2 para una geometría con área diferente de cero.

  Los objetos `Point` tienen una dimensión de cero. Los objetos `LineString` tienen una dimensión de 1. Los objetos `Polygon` tienen una dimensión de 2. Las dimensiones de los objetos `MultiPoint`, `MultiLineString`, y `MultiPolygon` son las mismas que las dimensiones de los elementos que los componen.

### 18.2.3. La clase `Point`

Un `Punto` es una geometría que representa una ubicación única en un espacio de coordenadas.

Ejemplos de `Point`

- Imagine un mapa a gran escala del mundo con muchas ciudades. Un objeto `Point` podría representar cada ciudad.

- En un mapa de una ciudad, un objeto `Point` podría representar una parada de bus.

Propiedades de `Point`

- Valor de la coordenada X.

- Valor de la coordenada Y.

- `Point` es definido como una geometría cero-dimensional.

- El límite de un `Point` es el conjunto vacío.

### 18.2.4. La clase `Curve`

Una `Curva` es una geometría unidimensional, normalmente representada por una secuencia de puntos. Las subclases particulares de `Curve` definen el tipo de interpolación entre puntos. `Curve` es una clase no instanciable.

Propiedades de `Curve`

- Una `Curva` tiene las coordenadas de sus puntos.

- Una `Curva` está definida como una geometría unidimensional.

- Una `Curva` es simple si no pasa sobre el mismo punto dos veces.

- Una `Curva` es cerrada si su punto inicial es igual a su punto final.

- El límite de una `Curva` cerrada está vacío.

- El límite de una `Curva` no cerrada consiste en sus dos puntos finales.

- Una `Curva` que es simple y cerrada es un `Anillo Linear (LinearRing)`.

### 18.2.5. La clase `LineString`

Una `LineString` es una `Curva` con interpolación linear entre puntos.

Ejemplos de `LineString`

- En un mapa del mundo, los objetos `LineString` podrían representar ríos.

- En un mapa de una ciudad, los objetos `LineString` podrían representar calles.

Propiedades de `LineString`

- Un `LineString` tiene coordenadas de segmentos, definidos por cada par consecutivo de puntos.

- Un `LineString` es una `Línea (Line)` si consiste exactamente en dos puntos.

- Un `LineString` es un `LinearRing` si es tanto cerrado como simple.

### 18.2.6. La clase `Surface`

Una `Superficie (Surface)` es una geometría bidimensional. Es una clase no instanciable. Su única subclase instanciable es `Polygon`.

Propiedades de `Surface`

- Una `superficie` está definida como una geometría bidimensional.

- La especificación OpenGIS define una `Superficie` simple como una geometría que consiste de un único “trozo” que está asociado a un único límite exterior y cero o más límites interiores.

- El límite de una `Superficie` simple es el conjunto de curvas cerradas correspondientes a sus límites exterior e interior.

### 18.2.7. La clase `Polygon`

Un `Polígono (Polygon)` es una `Superficie` planar que representa una geometría multicara. Se define por un único límite exterior y cero o más límites interiores, donde cada límite interior define un agujero en el `Polígono`.

Ejemplos de `Polygon`

- En un mapa de una región, objetos `Polygon` podrían representar bosques, distritos, etc.

Aserciones de `Polygon`

- El límite de un `Polígono` consiste en un conjunto de objetos `LinearRing` (es decir, objetos `LineString` que son tanto simples como cerrados) que construyen sus límites exterior e interior.

- Un `Polígono` no tiene anillos que se crucen. Los anillos en el límite de un `Polígono` pueden interseccionar un `Punto`, pero sólo como tangente.

- Un `Polígono` no tiene líneas, picos o valles.

- Un `Polígono` tiene un interior que consiste en un conjunto de puntos conectados.

- Un `Polígono` puede tener agujeros. El exterior de un `Polígono` con agujeros no está conectado. Cada agujero define un componente conectado del exterior.

Las aserciones precedentes hacen de un `Polígono` una geometría simple.

### 18.2.8. La clase `GeometryCollection`

Una `ColecciónDeGeometrías (GeometryCollection)` es una geometría que consiste en una colección de una o más geometrías de cualquier clase.

Todos los elementos en una `GeometryCollection` deben estar en el mismo Sistema de Referencia Espacial (es decir, en el mismo sistema de coordenadas). No existe ninguna otra restricción en los elementos de una `GeometryCollection`, aunque las subclases de `GeometryCollection` descritas en las siguientes secciones pueden restringir la membresía. Las restricciones se pueden basar en:

- Tipo de elemento (por ejemplo, un `MultiPoint` puede contener únicamente elementos de tipo `Point`)

- Dimensión

- Restricciones en el grado de sobreposición espacial entre elementos

### 18.2.9. La clase `MultiPoint`

Un `MultiPoint` es una colección de geometrías compuesta de elementos `Point`. Los puntos no están conectados ni ordenados de ningún modo.

Ejemplos de `MultiPoint`

- En un mapa mundial, un `MultiPoint` podría representar una cadena de pequeñas islas.

- En un mapa de una ciudad, un `MultiPoint` podría representar las oficinas de una empresa.

Propiedades de `MultiPoint`

- Un `MultiPoint` es una geometría cerodimensional.

- Un `MultiPoint` es simple si no hay dos de sus valores `Point` que sean iguales (tengan valores de coordenadas idénticos).

- El límite de un `MultiPoint` es el conjunto vacío.

### 18.2.10. La clase `MultiCurve`

Una `MultiCurva (MultiCurve)` es una colección de geometrías que se compone de elementos `Curve`. `MultiCurve` es una clase no instanciable.

Propiedades de `MultiCurve`

- Una `MultiCurva` es una geometría unidimensional.

- Una `MultiCurva` es simple si, y únicamente si, todos sus elementos son simples; las únicas interesecciones entre dos elementos cualquiera ocurren en puntos que están en los límites de ambos elementos.

- El límite de una `MultiCurva` se obtiene aplicando la “regla unión módulo 2 (mod 2 union rule)” (también conocida como la “regla par-impar (odd-even rule)”): Un punto está en el límite de una`MultiCurva` si está en los límites de un número impar de elementos de `MultiCurva`.

- Una `MultiCurva` es cerrada si todos sus elementos son cerrados.

- El límite de una `MultiCurva` cerrada es siempre vacío.

### 18.2.11. La clase `MultiLineString`

Una `MultiLineString` es una colección de geometrías `MultiCurve` compuesta de elementos `LineString`.

Ejemplos de `MultiLineString`

- En el mapa de una región, una `MultiLineString` podría representar un sistema de ríos o de autopistas.

### 18.2.12. La clase `MultiSurface`

Una `MultiSuperficie (MultiSurface)` es una colección de geometrías compuesta de elementos de Superficie. `MultiSurface` es una clase no instanciable. Su única subclase instanciable es `MultiPolygon`.

Aserciones de `MultiSurface`

- Dos superficies de `MultiSurface` no tienen interiores que se interseccionen.

- Dos elementos de `MultiSurface` tienen límites que interseccionan como máximo en un número finito de puntos.

### 18.2.13. La clase `MultiPolygon`

Un `MultiPolígono (MultiPolygon)` es un objeto `MultiSurface` compuesto de elementos `Polygon`.

Ejemplos de `MultiPolygon`

- En el mapa de una región, un `MultiPolygon` podría representar un sistema de lagos.

Aserciones de `MultiPolygon`

- Un `MultiPolygon` no tiene dos elementos `Polygon` con interiores que se interseccionen.

- Un `MultiPolygon` no tiene dos elementos `Polygon` que se crucen (los cruces están también prohibidos por la aserción previa), o que se toquen en un número infinito de puntos.

- Un `MultiPolygon` no debe tener líneas de corte, valles, o picos. Un `MultiPolygon` es un conjunto de puntos regular y cerrado.

- Un `MultiPolygon` que tenga más de un `Polygon` tiene un interior que no está conectado. El número de componentes conectados del interior de un `MultiPolygon` es igual al número de valores `Polygon` en el `MultiPolygon`.

Propiedades de `MultiPolygon`

- Un `MultiPolygon` es una geometría bidimensional.

- El límite de un `MultiPolygon` es un conjunto de curvas cerradas (valores `LineString`) que corresponden a los límites de sus elementos `Polygon`.

- Cada `Curva` en el límite de un `MultiPolygon` está en el límite de exactamente un elemento `Polygon`.

- Cada `Curva` en el límite de un elemento `Polygon` está en el límite del `MultiPolygon`.

## 18.3. Formatos de datos espaciales soportados

Esta sección describe los formatos de datos espaciales estándar que suelen utilizarse para representar objetos geométricos en consultas. Son:

- Formato Well-Known Text (WKT)

- Formato Well-Known Binary (WKB)

Internamente, MySQL almacena los valores de geometría en un formato que no es idéntico a ninguno de los formatos WKT o WKB

### 18.3.1. Formato Well-Known Text (WKT)

La representación Well-Known Text (WKT) de Geometrías está diseñada para intercambiar datos geométricos en formato ASCII.

Ejemplos de representaciones WKT de objetos geométricos son:

- Un `Point`:

      POINT(15 20)

  Nótese que las coordenadas del punto se especifican sin coma separadora.

- Una `LineString` con cuatro puntos:

      LINESTRING(0 0, 10 10, 20 25, 50 60)

  Nótese que los pares de coordenadas de los puntos están separados por comas.

- Un `Polygon` con un anillo exterior y un anillo interior:

      POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))

- Un `MultiPoint` con tres valores `Point`:

      MULTIPOINT(0 0, 20 20, 60 60)

- Una `MultiLineString` con dos valores `LineString`:

      MULTILINESTRING((10 10, 20 20), (15 15, 30 15))

- Un `MultiPolygon` con dos valores `Polygon`:

      MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))

- Una `GeometryCollection` consistente en dos valores `Point` y una `LineString`:

      GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))

Puede encontrar una gramática que especifica las reglas formales para la escritura de valores WKT en el documento de especificación OGC referenciado al principio de este capítulo.

### 18.3.2. Formato Well-Known Binary (WKB)

La representación Well-Known Binary (WKB) de valores geométricos está definida por la especificación OpenGIS. También está definida en el estándar ISO “SQL/MM Part 3: Spatial”.

WKB se utiliza para intercambiar datos como cadenas binarias representadas por valores `BLOB` que contienen información geométrica WKB.

WKB utiliza enteros sin signo de un byte, enteros sin signo de cuatro bytes, y números de ocho bytes de doble precisión (formato IEEE 754). Un byte son ocho bits.

Por ejemplo, un valor WKB que corresponde a un `POINT(1 1)` consiste en esta secuancia de 21 bytes (cada uno representado aquí por dos dígitos hexadecimales):

    0101000000000000000000F03F000000000000F03F

La secuencia puede descomponerse en los siguientes componentes:

    Orden de byte : 01
    Tipo WKB	  : 01000000
    X             : 000000000000F03F
    Y             : 000000000000F03F

La representación de componentes es como sigue:

- El orden de byte puede ser 0 o 1, para indicar almacenamiento tipo little-endian o big-endian. Los órdenes de byte little-endian y big-endian son también conocidos como Representación de Datos de Red (Network Data Representation (NDR)) y Representación Externa de Datos (External Data Representation (XDR)), respectivamente.

- El tipo WKB es un código que indica el tipo de geometría. Los valores del 1 al 7 significan `Point`, `LineString`, `Polygon`, `MultiPoint`, `MultiLineString`, `MultiPolygon`, y `GeometryCollection`.

- Un valor `Point` tiene coordenadas X e Y, cada una representada por un valor de doble precisión.

Los valores WKB que representan valores geométricos más complejos son representados por estructuras de datos más complejas, tal como se detalla en la especificación OpenGIS.

## 18.4. Crear una base de datos MySQL con capacidades espaciales

Esta sección describe los tipos de datos que usted puede utilizar para representar datos espaciales en MySQL, y las funciones disponibles para crear y obtener datos espaciales.

### 18.4.1. Tipos de datos espaciales de MySQL

MySQL tiene tipos de datos que corresponden a las clases OpenGIS. Algunos de estos tipos almacenan valores geométricos simples:

- `GEOMETRY`

- `POINT`

- `LINESTRING`

- `POLYGON`

`GEOMETRY` can store geometry values of any type. The other single-value types, `POINT` and `LINESTRING` and `POLYGON`, restrict their values to a particular geometry type.

The other data types hold collections of values:

- `MULTIPOINT`

- `MULTILINESTRING`

- `MULTIPOLYGON`

- `GEOMETRYCOLLECTION`

`GEOMETRYCOLLECTION` puede almacenar objetos de cualquier tipo. Los otros tipos de colección, `MULTIPOINT` y `MULTILINESTRING` y `MULTIPOLYGON` y `GEOMETRYCOLLECTION`, restringen sus miembros a aquellos que sean de un tipo de geometría particular.

### 18.4.2. Crear valores espaciales

Esta sección explica como crear valores espaciales utilizando funciones Well-Known Text y Well-Known Binary que están definidas en el estándar OpenGIS, y utilizando funciones específicas de MySQL.

#### 18.4.2.1. Crear valores geométricos utilizando funciones WKT

MySQL proporciona algunas funciones que toman como parámetros de entrada una representación Well-Known Text y, opcionalmente, un identificador de sistema de referencia espacial (SRID). Estas funciones retornan la geometía correspondiente.

`GeomFromText()` acepta una representación WKT de cualquier tipo de geometría como primer argumento. Una implementación también provee funciones de construcción específicas de cada tipo para la construcción de valores geométricos de cada tipo de geometría.

- `GeomCollFromText(`wkt`[,`srid`])` , `GeometryCollectionFromText(`wkt`[,`srid`])`

  Construye un valor `GEOMETRYCOLLECTION` utilizando su representación WKT y su SRID.

- `GeomFromText(`wkt`[,`srid`])` , `GeometryFromText(`wkt`[,`srid`])`

  Construye un valor geométrico de cualquier tipo utilizando su representación WKT y su SRID.

- `LineFromText(`wkt`[,`srid`])` , `LineStringFromText(`wkt`[,`srid`])`

  Construye un valor `LINESTRING` utilizando su representación WKT y su SRID.

- `MLineFromText(`wkt`[,`srid`])` , `MultiLineStringFromText(`wkt`[,`srid`])`

  Construye un valor `MULTILINESTRING` utilizando su representación WKT y su SRID.

- `MPointFromText(`wkt`[,`srid`])` , `MultiPointFromText(`wkt`[,`srid`])`

  Construye un valor `MULTIPOINT` utilizando su representación WKT y su SRID.

- `MPolyFromText(`wkt`[,`srid`])` , `MultiPolygonFromText(`wkt`[,`srid`])`

  Construye un valor `MULTIPOLYGON` utilizando su representación WKT y su SRID.

- `PointFromText(`wkt`[,`srid`])`

  Construye un valor `POINT` utilizando su representación WKT y su SRID.

- `PolyFromText(`wkt`[,`srid`])` , `PolygonFromText(`wkt`[,`srid`])`

  Construye un valor `POLYGON` utilizando su representación WKT y su SRID.

La especificación OpenGIS también describe funciones opcionales para construir valores `Polygon` o `MultiPolygon` basados en la representación WKT de una colección de anillos o valores `LineString` cerrados. Estos valores pueden interseccionarse. MySQL no implementa estas funciones:

- `BdMPolyFromText(`wkt`,`srid`)`

  Construye un valor `MultiPolygon` desde un valor `MultiLineString` en formato WKT conteniendo una colección arbitraria de valores `LineString` cerrados.

- `BdPolyFromText(`wkt`,`srid`)`

  Construye un valor `Polygon` desde un valor `MultiLineString` en formato WKT conteniendo una colección arbitraria de valores `LineString` cerrados.

#### 18.4.2.2. Crear valores geométricos utilizando funciones WKB

MySQL provee de varias funciones que toman como parámetros de entrada un `BLOB` que contiene una representación Well-Known Binary y, opcionalmente, un identificador de sistema de referencia espacial (SRID). Éstas retornan la geometría correspondiente.

`GeomFromWKB()` accepts a WKB of any geometry type as its first argument. An implementation also provides type-specific construction functions for construction of geometry values of each geometry type.

- `GeomCollFromWKB(`wkb`[,`srid`])` , `GeometryCollectionFromWKB(`wkb`[,`srid`])`

  Construye un valor `GEOMETRYCOLLECTION` utilizando su representación WKB y su SRID.

- `GeomFromWKB(`wkb`[,`srid`])` , `GeometryFromWKB(`wkb`[,`srid`])`

  Construye un valor geométrico de cualquier tipo utilizando su representación WKB y su SRID.

- `LineFromWKB(`wkb`[,`srid`])` , `LineStringFromWKB(`wkb`[,`srid`])`

  Construye un valor `LINESTRING` utilizando su representación WKB y su SRID.

- `MLineFromWKB(`wkb`[,`srid`])` , `MultiLineStringFromWKB(`wkb`[,`srid`])`

  Construye un valor `MULTILINESTRING` utilizando su representación WKB y su SRID.

- `MPointFromWKB(`wkb`[,`srid`])` , `MultiPointFromWKB(`wkb`[,`srid`])`

  Construye un valor `MULTIPOINT` utilizando su representación WKB y su SRID.

- `MPolyFromWKB(`wkb`[,`srid`])` , `MultiPolygonFromWKB(`wkb`[,`srid`])`

  Construye un valor `MULTIPOLYGON` utilizando su representación WKB y su SRID.

- `PointFromWKB(`wkb`[,`srid`])`

  Construye un valor `POINT` utilizando su representación WKB y su SRID.

- `PolyFromWKB(`wkb`[,`srid`])` , `PolygonFromWKB(`wkb`[,`srid`])`

  Construye un valor `POLYGON` utilizando su representación WKB y su SRID.

La especificación OpenGIS también describe funciones opcionales para construir valores `Polygon` o `MultiPolygon` basándose en la representación WKB de una colección de anillos o valores `LineString` cerrados. Estos valores puede interseccionarse. MySQL no implementa estas funciones:

- `BdMPolyFromWKB(`wkb`,`srid`)`

  Construye un valor `MultiPolygon` desde un valor `MultiLineString` en formato WKB que contiene una colección arbitraria de valores `LineString` cerrados.

- `BdPolyFromWKB(`wkb`,`srid`)`

  Construye un valor `Polygon` desde un valor `MultiLineString` en formato WKB que contiene una colección arbitraria de valores `LineString` cerrados.

#### 18.4.2.3. Crear valores geométricos usando funciones específicas de MySQL

Nota: MySQL no implementa las funciones enumeradas en esta sección.

MySQL le provee de un conjunto de funciones útiles para crear representaciones WKB de geometías. Las funciones descritas en esta sección son extensiones de MySQL a la especificación OpenGIS. Los resultados de estas funciones son valores `BLOB` que contienen representaciones WKB de valores geométricos sin SRID. Los resultados de estas funciones pueden ser sustituidos como primer argumento por cualquier función de la familia de funciones `GeomFromWKB()`.

- `GeometryCollection(`g1`,`g2`,...)`

  Construye una `GeometryCollection` WKB. Si algún argumento no es una representación WKB bien formada de una geometría, el valor retornado es `NULL`.

- `LineString(`pt1`,`pt2`,...)`

  Construye un valor `LineString` WKB desde varios parámetos WKB de tipo `Point`. Si alguno de los argumentos no es un `Point` WKB, el valor retornado es `NULL`. Si el número de parámetros `Point` es menor de dos, el valor retornado es `NULL`.

- `MultiLineString(`ls1`,`ls2`,...)`

  Construye un valor `MultiLineString` WKB desde varios parámetos WKB de tipo `LineString`. Si alguno de los argumentos no es un `LineString` WKB, el valor retornado es `NULL`.

- `MultiPoint(`pt1`,`pt2`,...)`

  Construye un valor `MultiPoint` WKB desde varios parámetos WKB de tipo `Point`. Si alguno de los argumentos no es un `Point` WKB, el valor retornado es `NULL`.

- `MultiPolygon(`poly1`,`poly2`,...)`

  Construye un valor `MultiPolygon` WKB desde varios parámetos WKB de tipo `Polygon`. Si alguno de los argumentos no es un `Polygon` WKB, el valor retornado es `NULL`.

- `Point(`x`,`y`)`

  Construye un `Point` WKB utilizando sus coordenadas.

- `Polygon(`ls1`,`ls2`,...)`

  Construye un valor `Polygon` WKB desde varios parámetros `LineString` WKB. Si alguno de los argumentos no representa el WKB de un `LinearRing` (es decir, un `LineString` que no es cerrado y simple), el valor retornado es `NULL`.

### 18.4.3. Crear columnas espaciales

MySQL le provee de una manera estándar de crear columnas espaciales para tipos geométricos, por ejemplo, con `CREATE TABLE` o `ALTER TABLE`. Actualmente, las columnas espaciales sólo son soportadas por las tablas `MyISAM`.

- Utilice la sentencia `CREATE TABLE` para crear una tabla con una columna espacial:

      mysql> CREATE TABLE geom (g GEOMETRY);
      Query OK, 0 rows affected (0.02 sec)

- Utilice la sentencia `ALTER TABLE` para añadir o eliminar una columna espacial a o de una tabla ya existente:

      mysql> ALTER TABLE geom ADD pt POINT;
      Query OK, 0 rows affected (0.00 sec)
      Records: 0  Duplicates: 0  Warnings: 0
      mysql> ALTER TABLE geom DROP pt;
      Query OK, 0 rows affected (0.00 sec)
      Records: 0  Duplicates: 0  Warnings: 0

### 18.4.4. Poblar columnas espaciales

Tras haber creado columnas espaciales, puede poblarlas con datos espaciales.

Los valores deben ser almacenados en formato de geometría internos, pero usted puede convertirlos a ese formato ya sea desde formato Well-Known Text (WKT) o desde formato Well-Known Binary (WKB). Los siguientes ejemplos demuestran cómo insertar valores geométricos en una tabla convirtiendo valores WKT al formato interno de geometrías.

Puede realizar la conversión directamente en la sentencia `INSERT`:

    INSERT INTO geom VALUES (GeomFromText('POINT(1 1)'));

    SET @g = 'POINT(1 1)';
    INSERT INTO geom VALUES (GeomFromText(@g));

O puede realizar la conversión previamente al `INSERT`:

    SET @g = GeomFromText('POINT(1 1)');
    INSERT INTO geom VALUES (@g);

Los siguientes ejemplos insertan más geometrías complejas en la tabla:

    SET @g = 'LINESTRING(0 0,1 1,2 2)';
    INSERT INTO geom VALUES (GeomFromText(@g));

    SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
    INSERT INTO geom VALUES (GeomFromText(@g));

    SET @g =
    'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
    INSERT INTO geom VALUES (GeomFromText(@g));

Los ejemplos precedentes utilizan todos `GeomFromText()` para crear valores geométricos. También puede utilizar funciones específicas de tipo:

    SET @g = 'POINT(1 1)';
    INSERT INTO geom VALUES (PointFromText(@g));

    SET @g = 'LINESTRING(0 0,1 1,2 2)';
    INSERT INTO geom VALUES (LineStringFromText(@g));

    SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
    INSERT INTO geom VALUES (PolygonFromText(@g));

    SET @g =
    'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
    INSERT INTO geom VALUES (GeomCollFromText(@g));

Tenga en cuenta que si un programa de aplicación cliente quiere utilizar representaciones WKB de valores geométricos, es responsable de enviar dichas representaciones correctamente formadas en las consultas al servidor. De cualquier modo, hay diversas maneras de satisfacer este requerimiento. Por ejemplo:

- Insertar un valor `POINT(1 1)` con sintaxis hexadecimal literal:

      mysql> INSERT INTO geom VALUES
          -> (GeomFromWKB(0x0101000000000000000000F03F000000000000F03F));

- Una aplicación ODBC puede enviar una representación WKB, encapsulándola en un comodín utilizando un argumento de tipo `BLOB`:

      INSERT INTO geom VALUES (GeomFromWKB(?))

  Otras interfaces de programación pueden soportar un sistema de comodines similar.

- En un programa en C, puede marcar un valor binario utilizando `mysql_real_escape_string()` e incluir el resultado en una consulta que se envía al servidor. Consulte Sección 24.3.3.48, “`mysql_real_escape_string()`”.

### 18.4.5. Extraer datos espaciales

Los valores geométricos almacenados en una tabla pueden ser extraídos en formato interno. Además puede también convertirlos al formato WKT o al WKB.

#### 18.4.5.1. Extraer datos espaciales en formato interno

Extraer valroes geométricos utilizando el formato interno puede ser útil en transferencias de tabla a tabla:

    CREATE TABLE geom2 (g GEOMETRY) SELECT g FROM geom;

#### 18.4.5.2. Extraer datos espaciales en formato WKT

La función`AsText()` convierte una geometría desde el formato interno a una cadena WKT.

    mysql> SELECT AsText(g) FROM geom;
    +-------------------------+
    | AsText(p1)              |
    +-------------------------+
    | POINT(1 1)              |
    | LINESTRING(0 0,1 1,2 2) |
    +-------------------------+

#### 18.4.5.3. Recoger datos espaciales en formato WKB

La función `AsBinary()` convierte una geometría desde el formato interno a un `BLOB` que contiene el valor WKB.

    SELECT AsBinary(g) FROM geom;

## 18.5. Analizar información espacial

Tras haber poblado las columnas espaciales con valores, usted está listo para consultarlos y analizarlos. MySQL provee de una serie de funciones para realizar diversas operaciones sobre datos espaciales. Estas funciones pueden ser agrupadas en cuatro categorías principales de acuerdo con el tipo de operación que realizan:

- Funciones que convierten las geometrías a diversos formatos

- Funciones que proveen de acceso a propiedades cuantitativas o cualitativas de una geometría

- Funciones que describen relaciones entre dos geometrías

- Funciones que crean nuevas geometrías desde otras ya existentes

Las funciones de análisis espacial pueden ser utilizadas en muchos y muy diferentes contextos, tales como:

- Cualquier programa SQL interactivo, como mysql o MySQLCC

- Programas de aplicación escritos en cualquier lenguaje que soporte una API cliente de MySQL

### 18.5.1. Funciones de conversión de formato geométrico

MySQL soporta las siguientes funciones para convertir valores geométricos entre formato interno y los formatos WKT o WKB:

- `AsBinary(`g`)`

  Convierte un valor en formato interno a su representación WKB y devuelve el resultado binario.

- `AsText(`g`)`

  Convierte un valor en formato interno a su representación WKT y devuelve la cadena resultante.

      mysql> SET @g = 'LineString(1 1,2 2,3 3)';
      mysql> SELECT AsText(GeomFromText(@g));
      +--------------------------+
      | AsText(GeomFromText(@G)) |
      +--------------------------+
      | LINESTRING(1 1,2 2,3 3)  |
      +--------------------------+

- `GeomFromText(`wkt`[,`srid`])`

  Convierte un valor de texto desde su representación WKT al formato interno de geometría y retorna el resultado. También hay varias funciones específicas de cada tipo que están disponibles, tales como `PointFromText()` y `LineFromText()`; consulte Sección 18.4.2.1, “Crear valores geométricos utilizando funciones WKT”.

- `GeomFromWKB(`wkb`[,`srid`])`

  Convierte un valor binario desde su representación WKB al formato interno de geometría y retorna el resultado. También hay varias funciones específicas de cada tipo que están disponibles, tales como `PointFromWKB()` y `LineFromWKB()`; consulte Sección 18.4.2.2, “Crear valores geométricos utilizando funciones WKB”.

### 18.5.2. Funciones `Geometry`

Cada función que pertenece a este grupo toma un valor geométrico como su primer argumento y retorna alguna propiedad cuantitativa o cualitativa de la geometría. Algunas funciones restringen el tipo de sus argumentos. Dichas funciones retornan `NULL` si el argumento es de un tipo geométrico incorrecto. Por ejemplo, `Area()` retorna `NULL` si el tipo del objeto no es `Polygon` ni `MultiPolygon`.

#### 18.5.2.1. Funciones generales de geometría

Las funciones enumeradas en esta sección no restringen el tipo de sus argumentos y aceptan cualquier tipo de valor geométrico.

- `Dimension(`g`)`

  Retorna la dimensión inherente al valor geométrico `g`. El resultado puede ser -1, 0, 1, o 2 (El significado de estos valores se explica en Sección 18.2.2, “La clase `Geometry`”.)

      mysql> SELECT Dimension(GeomFromText('LineString(1 1,2 2)'));
      +------------------------------------------------+
      | Dimension(GeomFromText('LineString(1 1,2 2)')) |
      +------------------------------------------------+
      |                                              1 |
      +------------------------------------------------+

- `Envelope(`g`)`

  Retorna el rectángulo mínimo que circunscribe (Minimum Bounding Rectangle (MBR)) el valor geométrico `g`. El resultado que se retorna es de tipo `Polygon`.

      mysql> SELECT AsText(Envelope(GeomFromText('LineString(1 1,2 2)')));
      +-------------------------------------------------------+
      | AsText(Envelope(GeomFromText('LineString(1 1,2 2)'))) |
      +-------------------------------------------------------+
      | POLYGON((1 1,2 1,2 2,1 2,1 1))                        |
      +-------------------------------------------------------+

  El polígono está definido por los puntos de la esquina de la caja que lo circunscribe:

      POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))

- `GeometryType(`g`)`

  Retorna en una cadena el nombre del tipo de la geometría de la que la instancia `g` es miembro. El nombre corresponde a una de las subclases instanciables de `Geometry`.

      mysql> SELECT GeometryType(GeomFromText('POINT(1 1)'));
      +------------------------------------------+
      | GeometryType(GeomFromText('POINT(1 1)')) |
      +------------------------------------------+
      | POINT                                    |
      +------------------------------------------+

- `SRID(`g`)`

  Retorna un entero que indica el Identificador de Sistema de Referencia Espacial del valor geométrico `g`.

  En MySQL, el valor SRID es simplemente un entero asociado con el valor geometrico. Todos los cálculos se realizan asumiendo una geometría Euclídea (planar).

      mysql> SELECT SRID(GeomFromText('LineString(1 1,2 2)',101));
      +-----------------------------------------------+
      | SRID(GeomFromText('LineString(1 1,2 2)',101)) |
      +-----------------------------------------------+
      |                                           101 |
      +-----------------------------------------------+

La especificación OpenGIS también define las siguientes funciones, que MySQL no implementa:

- `Boundary(`g`)`

  Retorna una geometría que es el cierre del límite combinacional del valor geométrico `g`.

- `IsEmpty(`g`)`

  Retorna 1 si el valor geométrico `g` corresponde a la geometría vacía, 0 si no está vacía, y -1 si el argumento es `NULL`. Si la geometría está vacía, representa el conjunto de puntos vacío.

- `IsSimple(`g`)`

  Actualmente esta función es un comodín y no debería ser utilizada. Si se implementara, su comportamiento será como el que se detalla en el siguiente párrafo.

  Retorna 1 si el valor geométrico `g` no tiene puntos geométricos anómalos, tales como auto-intersección o auto-tangencia. `IsSimple()` retorna 0 si el argumento no es simple, y -1 si es `NULL`.

  La descripción de cada clase geométrica instanciable mencionada anteriormente en este capítulo incluye las condiciones específicas que provcan que una instancia de una clase sea clasificada como no simple.

#### 18.5.2.2. Funciones `Point`

Un `Point` consiste en sus coordenadas X e Y, que pueden ser obtenidas utilizando las siguientes funciones:

- `X(`p`)`

  Retorna el valor de la coordenada X del punto `p` como un número de doble precisión.

      mysql> SELECT X(GeomFromText('Point(56.7 53.34)'));
      +--------------------------------------+
      | X(GeomFromText('Point(56.7 53.34)')) |
      +--------------------------------------+
      |                                 56.7 |
      +--------------------------------------+

- `Y(`p`)`

  Retorna el valor de la coordenada Y del punto `p` como un número de doble precisión.

      mysql> SELECT Y(GeomFromText('Point(56.7 53.34)'));
      +--------------------------------------+
      | Y(GeomFromText('Point(56.7 53.34)')) |
      +--------------------------------------+
      |                                53.34 |
      +--------------------------------------+

#### 18.5.2.3. Funciones `LineString`

Un `LineString` se compone de valores `Point`. Puede extraer valores particulares de dentro de una `LineString`, contar los puntos que contiene u obtener su longitud.

- `EndPoint(`ls`)`

  Devuelve el `Point` que es el punto final del valor `LineString` `ls`.

      mysql> SET @ls = 'LineString(1 1,2 2,3 3)';
      mysql> SELECT AsText(EndPoint(GeomFromText(@ls)));
      +-------------------------------------+
      | AsText(EndPoint(GeomFromText(@ls))) |
      +-------------------------------------+
      | POINT(3 3)                          |
      +-------------------------------------+

- `GLength(`ls`)`

  Devuelve la longitud del valor `LineString` `ls` como un número de doble precisión en su sistema de referencia espacial asociado.

      mysql> SET @ls = 'LineString(1 1,2 2,3 3)';
      mysql> SELECT GLength(GeomFromText(@ls));
      +----------------------------+
      | GLength(GeomFromText(@ls)) |
      +----------------------------+
      |            2.8284271247462 |
      +----------------------------+

- `IsClosed(`ls`)`

  Retorna 1 si el valor `LineString` `ls` es cerrado (es decir, su punto inicial `StartPoint()` y punto final `EndPoint()` tienen el mismo valor). Retorna 0 si `ls` es no cerrado, y -1 si es `NULL`.

      mysql> SET @ls = 'LineString(1 1,2 2,3 3)';
      mysql> SELECT IsClosed(GeomFromText(@ls));
      +-----------------------------+
      | IsClosed(GeomFromText(@ls)) |
      +-----------------------------+
      |                           0 |
      +-----------------------------+

- `NumPoints(`ls`)`

  Retorna el número de puntos en el valor `LineString` `ls`.

      mysql> SET @ls = 'LineString(1 1,2 2,3 3)';
      mysql> SELECT NumPoints(GeomFromText(@ls));
      +------------------------------+
      | NumPoints(GeomFromText(@ls)) |
      +------------------------------+
      |                            3 |
      +------------------------------+

- `PointN(`ls`,`n`)`

  Retorna el punto e-`n`-ésimo en el valor `Linestring` `ls`. Los números de punto comienzan por 1.

      mysql> SET @ls = 'LineString(1 1,2 2,3 3)';
      mysql> SELECT AsText(PointN(GeomFromText(@ls),2));
      +-------------------------------------+
      | AsText(PointN(GeomFromText(@ls),2)) |
      +-------------------------------------+
      | POINT(2 2)                          |
      +-------------------------------------+

- `StartPoint(`ls`)`

  Retorna el `Point` que es el punto inicial del valor `LineString` `ls`.

      mysql> SET @ls = 'LineString(1 1,2 2,3 3)';
      mysql> SELECT AsText(StartPoint(GeomFromText(@ls)));
      +---------------------------------------+
      | AsText(StartPoint(GeomFromText(@ls))) |
      +---------------------------------------+
      | POINT(1 1)                            |
      +---------------------------------------+

La especificación OpenGIS también define la siguiente función, que MySQL no implementa:

- `IsRing(`ls`)`

  Retorna 1 si el valor `LineString` `ls` es cerrado (es decir, que sus puntos inicial y final tienen el mismo valor) y es simple (no pasa a través del mismo punto más de una vez). Retorna 0 si `ls` no es un anillo, y -1 si es `NULL`.

#### 18.5.2.4. Funciones `MultiLineString`

- `GLength(`mls`)`

  Retorna la longitud del valor `MultiLineString` `mls` como un entero de doble precisión. La longitud de `mls` es igual a la suma de las longitudes de sus elementos.

      mysql> SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))';
      mysql> SELECT GLength(GeomFromText(@mls));
      +-----------------------------+
      | GLength(GeomFromText(@mls)) |
      +-----------------------------+
      |             4.2426406871193 |
      +-----------------------------+

- `IsClosed(`mls`)`

  Retorna 1 si el valor `MultiLineString` `mls` es cerrado (es decir, los valores del punto inicial y el punto final de cada `LineString` en `mls` son iguales entre sí). Retorna 0 si `mls` es no cerrado, y -1 si es `NULL`.

      mysql> SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))';
      mysql> SELECT IsClosed(GeomFromText(@mls));
      +------------------------------+
      | IsClosed(GeomFromText(@mls)) |
      +------------------------------+
      |                            0 |
      +------------------------------+

#### 18.5.2.5. Funciones `Polygon`

- `Area(`poly`)`

  Retorna, como número de doble precisión, el área del valor `Polygon` `poly`, medido en su sistema de referencia espacial.

      mysql> SET @poly = 'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))';
      mysql> SELECT Area(GeomFromText(@poly));
      +---------------------------+
      | Area(GeomFromText(@poly)) |
      +---------------------------+
      |                         4 |
      +---------------------------+

- `ExteriorRing(`poly`)`

  Retorna el anillo exterior del valor `Polygon` `poly` como un `LineString`.

      mysql> SET @poly =
          -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';
      mysql> SELECT AsText(ExteriorRing(GeomFromText(@poly)));
      +-------------------------------------------+
      | AsText(ExteriorRing(GeomFromText(@poly))) |
      +-------------------------------------------+
      | LINESTRING(0 0,0 3,3 3,3 0,0 0)           |
      +-------------------------------------------+

- `InteriorRingN(`poly`,`n`)`

  Retorna el e-`n`-ésimo anillo interior del valor `Polygon` `poly` como un `LineString`. Los números de anillo comienzan en 1.

      mysql> SET @poly =
          -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';
      mysql> SELECT AsText(InteriorRingN(GeomFromText(@poly),1));
      +----------------------------------------------+
      | AsText(InteriorRingN(GeomFromText(@poly),1)) |
      +----------------------------------------------+
      | LINESTRING(1 1,1 2,2 2,2 1,1 1)              |
      +----------------------------------------------+

- `NumInteriorRings(`poly`)`

  Retorna el número de anillos interiores en el valor `Polygon` `poly`.

      mysql> SET @poly =
          -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';
      mysql> SELECT NumInteriorRings(GeomFromText(@poly));
      +---------------------------------------+
      | NumInteriorRings(GeomFromText(@poly)) |
      +---------------------------------------+
      |                                     1 |
      +---------------------------------------+

#### 18.5.2.6. Funciones `MultiPolygon`

- `Area(`mpoly`)`

  Retorna, como un número de doble precisión, el área del valor `MultiPolygon` `mpoly`, medido en su sistema de referencia espacial.

      mysql> SET @mpoly =
          -> 'MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))';
      mysql> SELECT Area(GeomFromText(@mpoly));
      +----------------------------+
      | Area(GeomFromText(@mpoly)) |
      +----------------------------+
      |                          8 |
      +----------------------------+

La especificación OpenGIS también define las siguientes funciones, que MySQL no implementa:

- `Centroid(`mpoly`)`

  Retorna el centroide matemático del valor `MultiPolygon` `mpoly` como un `Point`. Este resultado no está garantizado que esté contenido en el `MultiPolygon`.

- `PointOnSurface(`mpoly`)`

  Retorna un valor `Point` del que se garantiza que está en el valor del `MultiPolygon` `mpoly`.

#### 18.5.2.7. Funciones `GeometryCollection`

- `GeometryN(`gc`,`n`)`

  Retorna la e-`n`-ésima geometría en el valor `GeometryCollection` `gc`. Los números de geometría comienzan por 1.

      mysql> SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))';
      mysql> SELECT AsText(GeometryN(GeomFromText(@gc),1));
      +----------------------------------------+
      | AsText(GeometryN(GeomFromText(@gc),1)) |
      +----------------------------------------+
      | POINT(1 1)                             |
      +----------------------------------------+

- `NumGeometries(`gc`)`

  Retorna el número de geometrías contenidas en la `GeometryCollection` `gc`.

      mysql> SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))';
      mysql> SELECT NumGeometries(GeomFromText(@gc));
      +----------------------------------+
      | NumGeometries(GeomFromText(@gc)) |
      +----------------------------------+
      |                                2 |
      +----------------------------------+

### 18.5.3. Funciones que crean nuevas geometrías a partir de unas existentes

#### 18.5.3.1. Funciones geométricas que producen nuevas geometrías

En la sección Sección 18.5.2, “Funciones `Geometry`”, hemos revisado algunas funciones que pueden construir nuevas geometrías a partir de otras ya existentes:

- `Envelope(`g`)`

- `StartPoint(`ls`)`

- `EndPoint(`ls`)`

- `PointN(`ls`,`n`)`

- `ExteriorRing(`poly`)`

- `InteriorRingN(`poly`,`n`)`

- `GeometryN(`gc`,`n`)`

#### 18.5.3.2. Operadores espaciales

OpenGIS propone varias funciones adicionales que pueden producir geometrías. Están diseñadas para implementar operadores espaciales.

Estas funciones no están implementadas en MySQL. Puede ser que aparezcan en futuras versiones.

- `Buffer(`g`,`d`)`

  Retorna una geometría que representa todos los puntos cuya distancia hasta el valor geométrico `g` es menor o igual a la distancia `d`.

- `ConvexHull(`g`)`

  Retorna una geometría que representa el borde convexo del valor geométrico `g`.

- `Difference(`g1`,`g2`)`

  Retorna una geometría que representa el conjunto de puntos resultado de la resta de los valores geométricos `g1` y `g2`.

- `Intersection(`g1`,`g2`)`

  Retorna una geometría que representa el conjunto de puntos resultado de la intersección de los valores geométricos `g1` y `g2`.

- `SymDifference(`g1`,`g2`)`

  Retorna una geometría que representa el conjunto de puntos resultado de la resta simétrica de los valores geométricos `g1` y `g2`.

- `Union(`g1`,`g2`)`

  Retorna una geometría que representa el conjunto de puntos resultado de la unión de los valores geométricos `g1` y `g2`.

### 18.5.4. Funciones para probar relaciones espaciales entre objetos geométricos

Las funciones descritas en estas secciones toman dos geometrías como parámetros de entrada y retornan una relación cuantitativa o cualitativa entre ellas.

### 18.5.5. Relaciones entre rectángulos MBR (Minimal Bounding Rectangles)

MySQL le provee con algunas funciones que pueden comprobar relaciones entre los rectángulos mínimos que circunscriben a dos geometrías `g1` y `g2`. Entre ellas se incluyen:

- `MBRContains(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si el rectángulo mínimo que circunscribe a `g1` contiene, o no, al rectángulo mínimo que circunscribe a `g2`.

      mysql> SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');
      mysql> SET @g2 = GeomFromText('Point(1 1)');
      mysql> SELECT MBRContains(@g1,@g2), MBRContains(@g2,@g1);
      ----------------------+----------------------+
      | MBRContains(@g1,@g2) | MBRContains(@g2,@g1) |
      +----------------------+----------------------+
      |                    1 |                    0 |
      +----------------------+----------------------+

- `MBRDisjoint(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si los rectángulos mínimos que circunscriben a las geometrías `g1` y `g2` son disjuntas (no se interseccionan), o no.

- `MBREqual(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si el rectángulo mínimo que circunscribe a las dos geometrías `g1` y `g2` es o no es el mismo.

- `MBRIntersects(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si los rectángulos mínimos que circunscriben a las geometrías `g1` y `g2` se interseccionan o no.

- `MBROverlaps(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si los rectángulos mínimos que circunscriben a las geometrías `g1` y `g2` se sobreponen o no.

- `MBRTouches(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si los rectángulos mínimos que circunscriben a las geometrías `g1` y `g2` se tocan o no.

- `MBRWithin(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si el rectángulo mínimo que circunscribe a la geometría `g1` se encuentra o no dentro del rectángulo mínimo que circunscribe a la geometría `g2`.

      mysql> SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');
      mysql> SET @g2 = GeomFromText('Polygon((0 0,0 5,5 5,5 0,0 0))');
      mysql> SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1);
      +--------------------+--------------------+
      | MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) |
      +--------------------+--------------------+
      |                  1 |                  0 |
      +--------------------+--------------------+

### 18.5.6. Funciones que prueban relaciones espaciales entre geometrías

La especificación OpenGIS define las siguientes funciones. Actualmente, MySQL no las implementa de acuerdo a la especificación. Aquéllas que están implementadas retornan el mismo resultado que las funciones basadas en MBR correspondientes. Esto incluye a las funciones de la siguiente lista, además de `Distance()` y `Related()`.

Estas funciones pueden ser implementadas en futuras versiones con soporte completo para análisis espacial, y no sólo soporte basado en MBR.

Estas funciones operan sobre dos valores geométricos `g1` and `g2`.

- `Contains(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si `g1` contiene completamente o no a `g2`.

- `Crosses(`g1`,`g2`)`

  Retorna 1 si `g1` cruza espacialmente a `g2`. Retorna `NULL` si `g1` es un `Polygon` o un `MultiPolygon`, o si `g2` es un `Point` o un `MultiPoint`. En cualquier otro caso, retorna 0.

  El término cruza espacialmente denota una relación espacial entre dos geometrías dadas que tiene las siguientes propiedades:

  - Las dos geometrías se interseccionan

  - La intersección resulta en una geometría que tiene una dimensión que es una unidad menor que la dimensión máxima de las dos geometrías dadas

  - Su intersección no es igual a ninguna de las dos geometrías dadas.

- `Disjoint(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si `g1` es o no espacialmente disjunto (no intersecciona) con `g2`.

- `Distance(`g1`,`g2`)`

  Retorna un número de doble precisión que representa la distancia más corta entre los puntos de ambas geometrías.

- `Equals(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si `g1` es o no igual espacialmente a `g2`.

- `Intersects(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si `g1` intersecciona espacialmente con `g2`.

- `Overlaps(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si `g1` se superpone espacialmente o no a `g2`. El término superpone espacialmente se utiliza si dos geometrías interseccionan y la intersección resultante es una geometría de las mismas dimensiones pero no igual a ninguna de las geometrías dadas.

- `Related(`g1`,`g2`,`pattern_matrix`)`

  Retorna 1 o 0 paa indicar si la relación espacial especificada por `pattern_matrix` existe entre `g1` y `g2`. Retorna -1 si los argumentos son `NULL`. La matriz de patrones (pattern_matrix) es una cadena. Su especificación se explicará aquí si la función llega a ser implementada.

- `Touches(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si `g1` toca espacialmente o no a `g2`. Dos geometrías se tocan espacialmente si los interiores de las dos geometrías no interseccionan, pero el límite de una de ellas intersecciona con el límite o el interior de la otra.

- `Within(`g1`,`g2`)`

  Retorna 1 o 0 para indicar si `g1` está o no espacialmente dentro de `g2`.

## 18.6. Optimización del análisis espacial

Las operaciones de búsqueda en bases de datos no espaciales pueden optimizarse mediante índices. Esto también es aplicable a las bases de datos espaciales. Con la ayuda de una gran variedad de métodos de indexación multidimensional que han sido previamente designados, es posible optimizar las búsquedas espaciales. Los más usuales de estos métodos son:

- Consultas sobre puntos que buscan todos los objetos que contienen un punto dado

- Consultas sobre regiones que buscan todos los objetos que se superponen a una región dada

MySQL utiliza Árboles R con partición cuadrática para indexar las columnas espaciales. Un índice espacial se construye utilizando la MBR de una geometría. Para la mayoría de las geometrías, la MBR es el rectángulo mínimo que la circunscribe. Para una línea vertical u horizontal, la MBR es un rectángulo reducido a una línea. Para un punto, la MBR es un rectángulo reducido a un punto.

### 18.6.1. Crear índices espaciales

MySQL puede crear índices espaciales utilizando una sintaxis similar a la que se utiliza para crear índices normales, pero extendida con la palabra clave `SPATIAL`. Las columnas espaciales que están indexadas, deben ser declaradas, actualmente, como `NOT NULL`. Los siguientes ejemplos demuestran cómo crear índices espaciales.

- Con `CREATE TABLE`:

      mysql> CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g));

- Con `ALTER TABLE`:

      mysql> ALTER TABLE geom ADD SPATIAL INDEX(g);

- Con `CREATE INDEX`:

      mysql> CREATE SPATIAL INDEX sp_index ON geom (g);

Para eliminar índices espaciales, utilice `ALTER TABLE` o `DROP INDEX`:

- Con `ALTER TABLE`:

      mysql> ALTER TABLE geom DROP INDEX g;

- Con `DROP INDEX`:

      mysql> DROP INDEX sp_index ON geom;

Ejemplo: Suponga una tabla `geom` que contiene más de 32000 geometrías, que están almacenadas en la columna `g` del tipo `GEOMETRY`. La tabla también tiene una columna `AUTO_INCREMENT` llamada `fid` para almacenar valores de ID de objetos.

    mysql> DESCRIBE geom;
    +-------+----------+------+-----+---------+----------------+
    | Field | Type     | Null | Key | Default | Extra          |
    +-------+----------+------+-----+---------+----------------+
    | fid   | int(11)  |      | PRI | NULL    | auto_increment |
    | g     | geometry |      |     |         |                |
    +-------+----------+------+-----+---------+----------------+
    2 rows in set (0.00 sec)

    mysql> SELECT COUNT(*) FROM geom;
    +----------+
    | count(*) |
    +----------+
    |    32376 |
    +----------+
    1 row in set (0.00 sec)

Para añadir un índice espacial en la columna `g`, utilice esta sentencia:

    mysql> ALTER TABLE geom ADD SPATIAL INDEX(g);
    Query OK, 32376 rows affected (4.05 sec)
    Records: 32376  Duplicates: 0  Warnings: 0

### 18.6.2. Usar un índice espacial

El optimizador investiga si los índices espaciales disponibles pueden ser utilizados en la búsqueda de consultas que utilicen una función como `MBRContains()` o `MBRWithin()` en la cláusula `WHERE`. Por ejemplo, digamos que queremos encontrar todos los objetos que están en un rectángulo determinado:

    mysql> SELECT fid,AsText(g) FROM geom WHERE
    mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
    +-----+-----------------------------------------------------------------------------+
    | fid | AsText(g)                                                                   |
    +-----+-----------------------------------------------------------------------------+
    |  21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8)     |
    |  22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4)     |
    |  23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2)     |
    |  24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823)     |
    |  25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2) |
    |  26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2)     |
    | 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4) |
    |   1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2)   |
    |   2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121)     |
    |   3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113)           |
    |   4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6)       |
    |   5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2)   |
    |   6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077)         |
    |   7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4)   |
    |  10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019)     |
    |  11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8)   |
    |  13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8)       |
    | 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134)         |
    | 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4)       |
    | 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001)     |
    +-----+-----------------------------------------------------------------------------+
    20 rows in set (0.00 sec)

Utilicemos `EXPLAIN` para comprobar en qué manera se ejecuta esta consulta (la columna `id` ha sido eliminada para que el listado quede mejor maquetado en la página):

    mysql> EXPLAIN SELECT fid,AsText(g) FROM geom WHERE
    mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
    +-------------+-------+-------+---------------+------+---------+------+------+-------------+
    | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
    +-------------+-------+-------+---------------+------+---------+------+------+-------------+
    | SIMPLE      | geom  | range | g             | g    |      32 | NULL |   50 | Using where |
    +-------------+-------+-------+---------------+------+---------+------+------+-------------+
    1 row in set (0.00 sec)

Comprobemos qué ocurriría sin un índice espacial:

    mysql> EXPLAIN SELECT fid,AsText(g) FROM g IGNORE INDEX (g) WHERE
    mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
    +-------------+-------+------+---------------+------+---------+------+-------+-------------+
    | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
    +-------------+-------+------+---------------+------+---------+------+-------+-------------+
    | SIMPLE      | geom  | ALL  | NULL          | NULL |    NULL | NULL | 32376 | Using where |
    +-------------+-------+------+---------------+------+---------+------+-------+-------------+
    1 row in set (0.00 sec)

Ejecutemos la sentencia `SELECT` ignorando la clave espacial que tenemos:

    mysql> SELECT fid,AsText(g) FROM geom IGNORE INDEX (g) WHERE
    mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
    +-----+-----------------------------------------------------------------------------+
    | fid | AsText(g)                                                                   |
    +-----+-----------------------------------------------------------------------------+
    |   1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2)   |
    |   2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121)     |
    |   3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113)           |
    |   4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6)       |
    |   5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2)   |
    |   6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077)         |
    |   7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4)   |
    |  10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019)     |
    |  11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8)   |
    |  13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8)       |
    |  21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8)     |
    |  22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4)     |
    |  23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2)     |
    |  24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823)     |
    |  25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2) |
    |  26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2)     |
    | 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134)         |
    | 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4)       |
    | 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001)     |
    | 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4) |
    +-----+-----------------------------------------------------------------------------+
    20 rows in set (0.46 sec)

Cuando el índice no se utiliza, el tiempo de ejecución de esta consulta crece de 0.00 segundos a 0.46 segundos.

En versiones futuras, los índice espaciales podrán también ser utilizados para optimizar otras funciones. Consulte Sección 18.5.4, “Funciones para probar relaciones espaciales entre objetos geométricos”.

## 18.7. Conformidad y compatibilidad de MySQL

### 18.7.1. Características GIS que todavía no han sido implementadas

- Vistas adicionales de Metadatos

  La especificación OpenGIS propone diversas vistas adicionales de metadatos. Por ejemplo, una vista de sistema llamada `GEOMETRY_COLUMNS` contiene una descripción de las columnas geométricas, una fila por cada columna geométrica en la base de datos.

- La función OpenGIS `Length()` sobre `LineString` y `MultiLineString` actualmente debe llamarse en MySQL como `GLength()`

  El problema es que existe una función SQL `Length()` que calcula la longitud de las cadenas de caracteres, y a veces no es posible distinguir cuándo la función ha sido llamada en un contexto textual o espacial. Necesitamos resolver esto de alguna manera, o decidirnos por cambiar el nombre de la función.

Ésta es una traducción del manual de referencia de MySQL, que puede encontrarse en dev.mysql.com. El manual de referencia original de MySQL está escrito en inglés, y esta traducción no necesariamente está tan actualizada como la versión original. Para cualquier sugerencia sobre la traducción y para señalar errores de cualquier tipo, no dude en dirigirse a mysql-es@vespito.com.

Anterior |  | Siguiente
Capítulo 17. Introducción a MaxDB | Inicio | Capítulo 19. Procedimientos almacenados y funciones