Chapitre 18. Données spatiales avec MySQL
Précédent |  | Suivant

## Chapitre 18. Données spatiales avec MySQL

MySQL 4.1 propose une extension de gestion des données spatiales, et des capacités de génération, stockage et analyse des données spatiales. Actuellement, ces fonctionnalités ne sont possibles qu'avec les tables MyISAM.

Ce chapitre couvre les sujets suivants :

- La base de l'extension de gestion des données spatiales est le modèle géométrique OpenGIS

- Formats de données pour représenter les données spatiales.

- Comme manipuler les données spatiales avec MySQL.

- Indexer les données spatiales avec MySQL.

- Différences avec les spécifications OpenGIS

## 18.1. Introduction à GIS

MySQL implémente l'extension spatiale en suivant les spécifications du `Open GIS Consortium` (`OGC`). C'est un consortium international de plus de 250 personnes, agences et universités qui participent au développement public des concepts de gestions des données spatiales. L'OGC dispose d'un site web http://www.opengis.org/.

En 1997, l'Open GIS Consortium a publié un document intitulé OpenGIS (R) Simple Features Specifications For SQL : ce document propose plusieurs concepts pour ajouter le support des données spatiales aux serveurs de base de données SQL. Ces spécifications sont disponibles sur le site de Open GIS à l'adresse http://www.opengis.org/techno/implementation.htm : elle contient encore d'autres informations connexes à ce chapitre.

MySQL implémente une sous-partie de l'environnement SQL avec des types géométriques, proposé par OGC. Ce terme fait référence à un environnement SQL, disposant d'un jeu de types géométriques. Une colonne SQL géométrique est une colonne avec un type de données géométrique. Ces spécifications décrivent l'ensemble des types géométriques, ainsi que des fonctions permettant leur création et leur analyse.

Un lieu géographique représente tout ce qui dispose d'une localisation dans le monde. Un lieu peut être :

- Un entité. Par exemple, une montagne, un lac, une ville.

- Une région. Par exemple, les tropiques, une zone postale.

- Un endroit définissable. Par exemple, un carrefour, une place à la rencontre de deux rues.

Vous pouvez aussi rencontrer des documents qui utilisent le terme de lieu géospatial pour désigner les lieux géographiques.

Géométrie est un autre mot qui décrit un lieu géographique. Le sens original du mot géométrie se rapporte à une branche des mathématiques. Un autre sens se rapporte à la cartographie, désignant les lieux géométriques que les cartographes utilisent pour dessiner le monde.

Ce chapitre utiliser tous ces termes de manières synonyme : lieu géographique, lieu géospatial, lieu, or géométrie. Le terme le plus couramment utilisé ici sera géométrie.

Nous définirons une géométrie comme un point ou un ensemble de points représentant un endroit dans le monde.

## 18.2. Le modèle géométrique OpenGIS

Le jeu de types géométriques proposé par OGC dans ses spécifications `SQL with Geometry Types`, est basé sur le modèle géométrique OpenGIS. Dans ce modèle, chaque objet géométrique dispose des propriétés générales suivantes :

- Il est associé à un système de référence spatiales (`Spatial Reference System`), qui décrit l'origine des coordonnées de l'espace.

- Il appartient à une classe géométrique.

### 18.2.1. La hiérarchie des classes géométriques

La hiérarchie des classes géométriques est définie comme ceci :

- `Geometry` (non-instanciable)

  - `Point` (instanciable)

  - `Curve` (non-instanciable)

    - `LineString` (instanciable)

      - `Line`

      - `LinearRing`

  - `Surface` (non-instanciable)

    - `Polygon` (instanciable)

  - `GeometryCollection` (instanciable)

    - `MultiPoint` (instanciable)

    - `MultiCurve` (non-instanciable)

      - `MultiLineString` (instanciable)

    - `MultiSurface` (non-instanciable)

      - `MultiPolygon` (instanciable)

Certaines classes sont abstraites et non-instanciables. C'est à dire, il n'est pas possible de créer un objet de cette classe. Les autres classes sont instanciables, et on peut en créer des objets. Chaque classe a des propriétés, et les classes instanciables ont des assertions (des règles qui définissent des instances valides).

`Geometry` est la classe de base. C'est une classe abstraite. Les sous-classes instanciables de `Geometry` sont limitées à des objets de zéro, une ou deux dimensions, qui existent dans un espace bidimensionnel. Toutes les classes géométriques instanciables sont définies de fa¸on à ce que les instances valides d'une classe géométrique soient topologiquement fermées (c'est à dire que l'objet géométrique inclut ses frontières).

La classe `Geometry` a les sous-classes de `Point`, `Curve`, `Surface` et `GeometryCollection` :

- `Point` représente un objet sans dimension.

- `Curve` représente un objet à une dimension, et a pour sous-classe `LineString`, avec les sous-classes `Line` et `LinearRing`.

- `Surface` représente les objets bidimensionnels, et a pour sous-classe `Polygon`.

- `GeometryCollection` dispose des classes de regroupement `MultiPoint`, `MultiLineString` et `MultiPolygon`, destinées aux groupes d'objets de zéro, une ou deux dimensions. Elle permet de modéliser les groupes de points `Points`, de lignes `LineStrings` et de polygones `Polygons`, respectivement. `MultiCurve` et `MultiSurface` sont présentées comme des super-classes abstraites, qui généralisent les interfaces de regroupements, pour gérer les courbes `Curves` et les surfaces `Surfaces`.

`Geometry`, `Curve`, `Surface`, `MultiCurve`, et `MultiSurface` sont définies comme non-instanciables. Elles définissent un jeu de méthodes communes à leurs sous-classes, et sont inclues ici pour des raisons d'extensibilité.

`Point`, `LineString`, `Polygon`, `GeometryCollection`, `MultiPoint`, `MultiLineString` et `MultiPolygon` sont des classes instanciables.

### 18.2.2. Classe `Geometry`

`Geometry` est la classe racine de la hiérarchie. C'est une classe non-instanciable, mais elle dispose d'un grand nombre de propriétés qui sont communes à toutes les formes géométriques, dérivées de `Geometry`. Ces propriétés sont décrites dans la liste suivante. Les sous-classes ont leur propres propriétés spécifiques, définies ultérieurement.

propriétés de la classe `Geometry`

Un objet `Geometry` a les propriétés suivantes :

- Son type. Chaque objet `Geometry` appartient à une des classes instanciables de la hiérarchie.

- Son SRID, ou identifiant de référence spatiale : `Spatial Reference Identifier`. Cette valeur spécifie le système de référence spatial (`Spatial Reference System`), qui décrit l'espace de coordonnées dans lequel l'objet est défini.

- Ses coordonnées `coordinates` dans le système de référence spatial, représentées par des nombres à virgule flottante en double précision (8 octets). Tous les objets non-vides contiennent au moins une paire de coordonnées (X,Y). Les formes géométriques vides ne contiennent pas de coordonnées.

  Les coordonnées sont relatives au `SRID`. Par exemple, dans différents systèmes de coordonnées, la distance entre deux objets peut varier même si les objets ont les mêmes coordonnées, car les distances planes et les distances géocentriques (système de coordonnées à la surface de la Terre) suivent deux géométries différentes.

- Son intérieur `interior`, sa frontière `boundary` et son extérieur `exterior`.

  Toutes les formes géométriques occupe une position dans l'espace. L'extérieur de la forme est l'espace qui n'est pas occupé par la forme. L'intérieur de la géométrie est l'espace occupé par la géométrie. La frontière est l'interface entre l'extérieur de la forme et son intérieur.

- Son `MBR` (Rectangle minimal d'enveloppe, `Minimum Bounding Rectangle`), appelé aussi enveloppe. C'est la forme géométrique la plus petite, formée par les coordonnées minimales et maximales (X,Y) :

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

- L'attribut simple ou non-simple. Les objets géométriques de certains types, comme `LineString`, `MultiPoint`, `MultiLineString` sont simple ou non-simple. Chaque type dispose de ses propres assertions.

- L'attribut fermé (`closed`) ou non-fermé (`not closed`). Les objets géométriques de certains types, comme `LineString`, `MultiString` sont fermés ou non-fermés. Chaque type dispose de ses propres assertions.

- L'attribut vide (`empty`) ou non-vide(`not empty`). Une forme est vide si elle ne contient aucun point. L'extérieur, l'intérieur et la frontière d'une forme vide ne sont pas définis (ils sont représentés par la valeur `NULL`). Une forme vide est toujours simple, et a une surface de 0.

- Sa dimension. Une forme a une dimension de −1, 0, 1, ou 2 :

  - −1 représente une forme vide.

  - 0 représente les formes sans surface ni dimension.

  - 1 représente les formes avec une dimension non nulle, mais sans surface.

  - 2 représente les formes avec une dimension et une surface non-nulles.

  Les `Point` sont de dimension zéro. Les lignes `LineString` sont de dimension un. Les polygones `Polygon` sont de dimension deux. Les dimensions des objets `MultiPoint`, `MultiLineString` et `MultiPolygon` sont les mêmes que les dimensions des objets dont ils sont composés.

### 18.2.3. Classe `Point`

Un `Point` est une forme géométrique qui représente un endroit dans un espace de coordonnées.

Exemples de `Point`

- Imaginez une carte à grande échelle, avec de nombreuses villes. Un point représentera une ville.

- Sur une carte de ville, un point peut représenter un arrêt de bus.

Propriété du `Point`

- Abscisse, ou coordonnées X.

- Ordonnée, ou coordonnée Y.

- Un point `Point` est défini comme une forme avec zéro dimension.

- Le rectangle d'encadrement d'un `Point` est un rectangle vide.

### 18.2.4. Classe `Curve`

Une courbe `Curve` est une forme géométrique à une dimension, qui représente généralement une séquence de points. Une sous-classe particulière de `Curve` est l'interpolation entre deux points. `Curve` est une classe non-instanciable.

Propriétés de la classe `Curve`

- Les coordonnées de ses points.

- `Curve` est définie comme une forme à une dimension.

- Un objet `Curve` est simple si elle ne passe pas par le même point deux fois.

- Un objet `Curve` est fermé si son point de départ est le même que son point d'arrivée.

- La frontière d'un objet `Curve` est vide.

- La frontière d'un objet `Curve` non-fermé est ses deux points terminaux.

- Un objet `Curve` qui est simple et fermé est un objet `LinearRing`.

### 18.2.5. Classe `LineString`

Un objet `LineString` est un objet `Curve` avec une interpolation linéaire entre ses points.

Exemples de `LineString`

- Sur une carte du monde, un objet `LineString` peut représenter les rivières.

- Sur une carte de ville, un objet `LineString` peut représenter les rues.

Propriété des objets `LineString`

- Coordonnées des segments de `LineString`, définis par des paires de points consécutifs.

- Un objet `LineString` est un objet `Line` s'il est constitué de deux points.

- Un objet `LineString` est un objet `LinearRing` s'il est fermé et simple.

### 18.2.6. Classe `Surface`

Un objet `Surface` est une forme géométrique à deux dimensions. C'est une classe non-instanciable. Sa seule sous-classe instanciable est la classe `Polygon`.

Propriété de `Surface`

- Un objet `Surface` est défini comme une forme géométrique à deux dimensions.

- Les spécifications OpenGIS définissent un objet `Surface` comme une forme géométrique simple si elle est d'un seul tenant, qui est associé avec un seul extérieur, et aucune frontière intérieure.

- La frontière d'un objet `Surface` est l'ensemble des courbes fermées qui correspondent à ses frontières extérieures et intérieures.

### 18.2.7. Classe `Polygon`

Un polygone `Polygon` est une surface `Surface` plane avec plusieurs côtés. Il est défini par une seule frontière extérieure, au aucune ou plusieurs frontières intérieures. Chaque frontière intérieure définit un trou dans le polygone `Polygon`.

Exemple avec `Polygon`

- Sur une carte régionale, un objet `Polygon` peut représenter une forêt, un département, etc.

Assertions de `Polygon`

- La frontière d'un `Polygon` est constituée d'un ensemble d'objets `LinearRing` (c'est dire, des objets `LineString` qui sont simples et fermés), et qui forme sa frontière intérieure et extérieure.

- Deux frontières intérieures ne se coupent pas. Les courbes d'une frontière d'un objet `Polygon` peuvent se couper en un `Point`, mais uniquement en un point de tangence.

- Un polygone `Polygon` ne peut pas avoir de lignes coupées, d'extrusions ou de trous.

- L'intérieur de tous les `Polygon` est un ensemble de point connectés.

- L'extérieur d'un objet `Polygon` ayant un ou plusieurs trou n'est pas connecté. Chaque trou défini un composant connecté de l'extérieur.

Dans les assertions ci-dessus, les polygones sont des formes géométriques simples. Ces assertions font d'un objet `Polygon` une forme simple.

### 18.2.8. Classe `GeometryCollection`

Un objet `GeometryCollection` est une forme géométrique, représentée par le regroupement d'autres formes géométriques.

Tous les éléments dans un objet `GeometryCollection` doivent être placés dans le même système de référence spatiale (c'est à dire dans le même système de coordonnées). `GeometryCollection` n'impose aucune autre contrainte à ses éléments, même si les sous-classes de `GeometryCollection` décrites plus loin, en imposent d'autres. Les restrictions peuvent être basée sur :

- Le type d'élément (par exemple, un objet `MultiPoint` ne peut contenir que des objets `Point`).

- Dimension

- Contraintes sur le degré de recouvrement entre deux éléments.

### 18.2.9. Classe `MultiPoint`

Un objet `MultiPoint` est un regroupement d'objets de type `Point`. Les points ne sont pas connectés ou ordonnées de quelque manière que ce soit.

Exemples avec `MultiPoint`

- Sur une carte du monde, un objet `Multipoint` peut représenter un archipel.

- Sur une carte de ville, un objet `Multipoint` peut représenter les différentes succursales d'une entreprise.

Propriétés de `MultiPoint`

- Un objet `MultiPoint` est un objet sans dimension.

- Un objet `MultiPoint` est simple si tous les points `Point` sont tous distincts (les paires de coordonnées sont toutes distinctes).

- La frontière d'un objet `MultiPoint` est vide.

### 18.2.10. Classe `MultiCurve`

Un objet `MultiCurve` est une forme géométrique composée d'objets `Curve`. `MultiCurve` est une classe non-instanciable.

Propriété de `MultiCurve`

- Un objet `MultiCurve` est défini comme une forme géométrique a une dimension.

- Un objet `MultiCurve` est dit simple si et seulement si tous ses éléments sont simples, et que les seules intersections entre deux éléments interviennent sur les frontières des deux éléments.

- La frontière d'un objet `MultiCurve` est obtenue en appliquant la ``règle de l'union modulo 2'' (dite aussi, règle pair / impair) : Un point est une frontière d'un objet `MultiCurve` s'il fait partie d'un nombre impair de frontière d'élément de l'objet `MultiCurve`.

- Un objet `MultiCurve` est fermé si tous ses éléments sont fermés.

- La frontière d'un objet `MultiCurve` fermé est toujours vide.

### 18.2.11. Classe `MultiLineString`

Un objet `MultiLineString` est une forme géométrique de classe `MultiCurve`, composé uniquement d'objets `LineString`.

Exemples avec `MultiLineString`

- Sur une carte régionales, un objet `MultiLineString` représente un système de rivières, ou un autoroute.

### 18.2.12. Classe `MultiSurface`

Un objet `MultiSurface` est un groupe de surfaces. `MultiSurface` est une classe non-instanciable. Sa seule sous-classe instanciable est la classe `MultiPolygon`.

Assertions `MultiSurface`

- Les intérieurs de deux surfaces d'un objet `MultiSurface` doivent avoir des intersections nulles.

- La frontière de deux éléments de l'objet `MultiSurface` doivent avoir en commun un nombre fini de points.

### 18.2.13. Classe `MultiPolygon`

Un objet `MultiPolygon` est un objet `MultiSurface` composé d'objets `Polygon`.

Exemple avec `MultiPolygon`

- Sur une carte régionale, un objet `MultiPolygon` peut représenter un système de lacs.

Assertions `MultiPolygon`

- Les intérieurs de deux objets `Polygon` qui sont éléments d'un même objet `MultiPolygon` n'ont pas d'intersection.

- Les frontières de deux objets `Polygon` qui sont éléments d'un objet `MultiPolygon` ne peuvent que se toucher en un nombre fini de points, et non pas se recouvrir. Le recouvrement est déjà interdit par l'assertion précédente.

- Un objet `MultiPolygon` ne peut pas avoir de lignes coupées, d'extrusions ou de trous. Un objet `MultiPolygon` est un ensemble de point régulier, et fermé.

- L'intérieur d'un objet `MultiPolygon` composé de plus d'un objet `Polygon` n'est pas connecté. Le nombre de composants connectés de l'intérieur d'un objet `MultiPolygon` est égal au nombre d'objets `Polygon` dans l'objet `MultiPolygon`.

Propriétés `MultiPolygon`

- Un objet `MultiPolygon` est défini comme une forme géométrique à deux dimensions.

- La frontière d'un objet `MultiPolygon` est un ensemble de courbes fermées (des objets `LineString`) correspondants aux limites de ses objets `Polygon` composants.

- Chaque objet `Curve` de la frontière de l'objet `MultiPolygon` est dans la frontière d'un seul objet `Polygon`.

- Chaque objet `Curve` de la frontière d'un élément `Polygon` est dans la frontière de l'objet `MultiPolygon`.

## 18.3. Formats géométriques supportés

Cette section décrit les formats de données géométriques standard qui sont utilisés pour représenter des objets géométriques dans les requêtes. Il s'agit de :

- Le format Well-Known Text (WKT)

- Le format Well-Known binaire (WKB)

En interne, MySQL stocke les valeurs géométriques dans un format indépendant des formats WKT et WKB.

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

La représentation Well-Known Text (WKT) est con¸ue pour faire des échanges au format ASCII.

Exemple de représentation d'objets WKT :

- Un `Point`:

      POINT(15 20)

  Notez que les coordonnées du point n'ont pas de séparateur virgule.

- Une ligne `LineString` de quatre points :

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

- Un polygone `Polygon` avec un anneau extérieur et un anneau intérieur :

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

- Un groupe de points `MultiPoint` avec trois `Point` :

      MULTIPOINT(0 0, 20 20, 60 60)

- Un groupe de lignes `MultiLineString` avec deux lignes `LineString` :

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

- Un groupe de polygone `MultiPolygon` avec deux polygones `Polygon` :

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

- Un groupe géométrique `GeometryCollection` constitué de deux `Point` et d'une ligne `LineString` :

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

Une grammaire Backus-Naur qui spécifie les règles de générations formelles pour écrire des valeurs WKT est disponible dans les spécifications OGC, qui sont référencées au début de ce chapitre.

### 18.3.2. Le format Well-Known Binary (WKB)

La représentation Well-Known Binary (WKB) des valeurs géométriques est définies par les spécifications OpenGIS. Il est aussi défini comme le standard ISO ``SQL/MM Part 3: Spatial''.

WKB sert à échanger des données géométriques sous forme de flux binaires représenté par des `BLOB` contenant des données WKB.

WKB utilise des entiers non-signés d'un octet, de quatre octets et des nombres à virgules flottantes de précision double (IEEE 754 format). Un octet fait 8 bits.

Par exemple, la valeur WKB qui correspond à `POINT(1 1)` est constituée de la séquence suivante de 21 octets, représentée ici en code hexadécimal :

    0101000000000000000000F03F000000000000F03F

La séquence peut être décomposée comme ceci :

    Byte order : 01
    WKB type   : 01000000
    X          : 000000000000F03F
    Y          : 000000000000F03F

Voici le détail des composants :

- L'ordre des octets peut être 0 ou 1, pour indiquer un stockage little-endian ou big-endian. Les ordres little-endian et big-endian sont aussi connus sous le nom de `Network Data Representation` (NDR) et `External Data Representation` (XDR), respectivement.

- Le type WKB est un code qui indique le type géométrique. Les valeurs de 1 à 7 indiquent : `Point`, Ligne `LineString`, Polygone `Polygon`, Plusieurs points `MultiPoint`, Plusieurs lignes `MultiLineString`, Plusieurs polygones `MultiPolygon`, et Groupe géométrique `GeometryCollection`.

- Une valeur `Point` a des coordonnées X et Y, représentées par un nombre à virgule flottante, en double précision.

Les valeurs WKB des formes géométriques plus complexes sont représentées par des structures biens plus complexes, comme présenté dans les spécifications OpenGIS.

## 18.4. Créer une base de données avec les fonctionnalités géographiques

Cette section décrit les types de données que vous pouvez utiliser pour représenter des données géographiques dans MySQL, et les fonctions disponibles pour créer et lire les données spatiales.

### 18.4.1. Types de données géographiques MySQL

MySQL fournit un jeu de types de données qui correspondent aux classes du modèle géométrique OpenGIS. Certains de ces types contiennent des valeurs géométriques simples :

- `GEOMETRY`

- `POINT`

- `LINESTRING`

- `POLYGON`

`GEOMETRY` est le type le plus général. Il peut stocker une forme géométrique de n'importe quel type. Les autres types se restreignent a un type particulier de forme.

Les autres types de données permettent de gérer les groupes de formes géométriques :

- `MULTIPOINT`

- `MULTILINESTRING`

- `MULTIPOLYGON`

- `GEOMETRYCOLLECTION`

`GEOMETRYCOLLECTION` peut stocker un groupe quelconque de formes géométriques. Les autres types se restreignent à des formes géométriques particulières.

### 18.4.2. Créer des objets géographiques

Cette section décrit comment créer des valeurs en utilisant les fonctions Well-Known Text et Well-Known Binary qui sont définies dans le standard OpenGIS, et les fonctions spécifiques de MySQL.

#### 18.4.2.1. Créer des objets géométriques avec les fonctions WKT

MySQL fournit de nombreuses fonctions qui prennent en arguments un `BLOB` contenant la représentation au format Well-Known Text et optionnellement, un système de référence (SRID), et retourne la forme géométrique correspondante.

`GeomFromText()` accepte des données WKT de n'importe quelle type de données géométriques comme premier argument. L'implémentation fournit aussi des fonctions de construction spécifiques à chaque forme géométrique.

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

  Construit une forme géométrique à partir de sa représentation WKT et du SRID.

- `PointFromText(wkt[,srid])`

  Construit un objet `POINT` à partir de sa représentation WKT et du SRID.

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

  Construit un objet `LINESTRING` à partir de sa représentation WKT et du SRID.

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

  Construit un objet `POLYGON` à partir de sa représentation WKT et du SRID.

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

  Construit un objet `MULTIPOINT` à partir de sa représentation WKT et du SRID.

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

  Construit un objet `MULTILINESTRING` à partir de sa représentation WKT et du SRID.

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

  Construit un objet `MULTIPOLYGON` à partir de sa représentation WKT et du SRID.

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

  Construit un objet `GEOMETRYCOLLECTION` à partir de sa représentation WKT et du SRID.

Les spécifications OpenGIS décrivent aussi des fonctions optionnelles pour construire des `Polygon` et `MultiPolygon` basées sur les représentations WKT d'une collection d'anneaux ou d'objets `LineString` fermés. Ces objets peuvent avoir des intersections non vides. MySQL ne supporte pas encore ces fonctions :

- `BdPolyFromText(wkt,srid)`

  Construit un objet `Polygon` à partir de la représentation WKT d'un objet `MultiLineString`, contenant un ensemble d'objets `LineString` fermés.

- `BdMPolyFromText(wkt,srid)`

  Construit un objet `MultiPolygon` à partir de la représentation WKT d'un objet `MultiLineString`, contenant un ensemble d'objets `LineString` fermés.

#### 18.4.2.2. Créer des objets géométriques avec les fonctions WKB

MySQL fournit de nombreuses fonctions qui prennent en arguments un `BLOB` contenant la représentation au format Well-Known Binary et optionnellement, un système de référence (SRID), et retourne la forme géométrique correspondante.

`GeomFromWKT()` accepte des données WKB de n'importe quelle type de données géométriques comme premier argument. L'implémentation fournit aussi des fonctions de construction spécifiques à chaque forme géométrique.

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

  Construit une forme géométrique à partir de sa représentation WKB et du SRID.

- `PointFromWKB(wkb[,srid])`

  Construit un objet `POINT` à partir de sa représentation WKB et du SRID.

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

  Construit un objet `LINESTRING` à partir de sa représentation WKB et du SRID.

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

  Construit un objet `POLYGON` à partir de sa représentation WKB et du SRID.

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

  Construit un objet `MULTIPOINT` à partir de sa représentation WKB et du SRID.

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

  Construit un objet `MULTILINESTRING` à partir de sa représentation WKB et du SRID.

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

  Construit un objet `MULTIPOLYGON` à partir de sa représentation WKB et du SRID.

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

  Construit un objet `GEOMETRYCOLLECTION` à partir de sa représentation WKB et du SRID.

Les spécifications OpenGIS décrivent aussi des fonctions optionnelles pour construire des `Polygon` et `MultiPolygon` basées sur les représentations WKB d'une collection d'anneaux ou d'objets `LineString` fermés. Ces objets peuvent avoir des intersections non vides. MySQL ne supporte pas encore ces fonctions :

- `BdPolyFromWKB(wkb,srid)`

  Construit un objet `Polygon` à partir de la représentation WKB d'un objet `MultiLineString`, contenant un ensemble d'objets `LineString` fermés.

- `BdMPolyFromWKB(wkb,srid)`

  Construit un objet `MultiPolygon` à partir de la représentation WKB d'un objet `MultiLineString`, contenant un ensemble d'objets `LineString` fermés.

#### 18.4.2.3. Création de formes géométriques avec les fonctions spécifiques de MySQL

Note : MySQL ne dispose pas encore de toutes les fonctions listées dans cette section.

MySQL fournit un jeu de fonction pratiques pour créer des représentations WKB. Ces fonctions sont décrites dans cette section, et sont spécifiques à MySQL : ce sont des extensions aux spécifications OpenGIS. Le résultat de ces fonctions sont des valeurs de type `BLOB` qui contiennent la représentation au format WKB des objets géométriques, sans leur SRID. Le résultat de ces fonctions peut être utilisé comme premier argument de toute fonction de la famille `GeomFromWKB()`.

- `Point(x,y)`

  Construit un `Point` au format WKB, en utilisant ses coordonnées.

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

  Construit un objet `MultiPoint` au format WKB, en utilisant les arguments `Point` WKB. Si aucun argument n'est au format `WKBPoint`, la valeur retournée est `NULL`.

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

  Construit un objet `LineString` au format WKB, à partir d'arguments `Point` WKB. Si aucun argument n'est au format `WKBPoint`, la valeur retournée est `NULL`. Si moins de deux arguments est fourni, la valeur retournée est `NULL`.

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

  Construit un objet `MultiLineString` au format WKB, en utilisant les objets `LineString` WBK. Si aucun argument n'est de classe `LineString`, la valeur retournée alors `NULL`.

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

  Construit un objet `Polygon` au format WKB, en utilisant les objets `LineString` WBK. Si aucun argument n'est de classe `LinearRing`, (c'est à dire, un objet `LineString` fermé et simple), la valeur retournée alors `NULL`.

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

  Construit un objet `MultiPolygon` au format WKB, en utilisant les objets `Polygon` WBK. Si aucun argument n'est de classe `Polygon`, la valeur retournée alors `NULL`.

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

  Construit un objet `GeometryCollection` au format WKB. Si aucun argument n'est au format valide WBK, la valeur retournée alors `NULL`.

### 18.4.3. Créer des colonnes géométriques

MySQL fournit une méthode standard pour créer des colonnes géographiques, avec les commandes `CREATE TABLE` ou `ALTER TABLE`, etc. Actuellement, les colonnes géométriques ne sont supportées que par les tables `MyISAM`.

- Utilisez la commande `CREATE TABLE` pour créer une colonne géométrique :

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

- Utilisez la commande `ALTER TABLE` pour ajouter ou effacer une colonne géométrique dans une table existante :

      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. Remplir des colonnes géométriques

Une fois que vous avez créé des colonnes géométriques, vous pouvez les remplir avec des données géographiques.

Les valeurs doivent être stockées dans un format géométrique interne, mais vous pouvez les convertir à ce format à partir des formats Well-Known Text (WKT) et Well-Known Binary (WKB). Les exemples suivants vous montre comment insérer des valeurs géométriques dans une table, en convertissant des valeurs WKT en un format géométrique.

Vous pouvez faire la conversion directement avec la commande `INSERT` :

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

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

Au besoin, la conversion peut avoir lieur avant la commande `INSERT` :

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

Les exemples suivants illustre l'insertion de données plus complexes dans la table :

    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));

Les exemples précédents utilisent tous la fonction `GeomFromText()` pour créer des valeurs géométriques. Vous pouvez aussi utiliser des fonctions spécifiques à chaque forme géométrique :

    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));

Notez que si une application cliente veut utiliser des représentations WKB de valeur géométrique, elle est responsable d'envoyer des requêtes avec des valeurs WKB valides au serveur. Sinon, il y a de nombreux moyens de passer cette contrainte. Par exemple :

- Insertion d'un point `POINT(1 1)` avec sa valeur littérale héxadécimale :

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

- Une application ODBC veut envoyer une représentation WKB, en l'associant à une variable de requête en utilisant un argument de type `BLOB` :

      INSERT INTO geom VALUES (GeomFromWKB(?))

  D'autres interfaces de programmation peuvent supporter des mécanismes similaires.

- Dans un programme C, vous pouvez protéger les valeurs binaires en utilisant la fonction `mysql_real_escape_string()` et inclure le résultat dans une chaîne de requête, qui sera envoyée au serveur. See Section 24.2.3.47, « `mysql_real_escape_string()` ».

### 18.4.5. Lire des données géométriques

Les formes géométriques sont stockées dans une table, et peuvent être lues dans différents formats. Vous pouvez les convertir au format interne, WBK ou WBT.

#### 18.4.5.1. Lire des données géométriques au format interne

Lire des données géométriques au format interne peut être utile lors des transferts de tables en tables :

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

#### 18.4.5.2. Lire des données géométriques au format WBT

La fonction `AsText()` fournit une représentation textuelle d'une forme géométrique. Elle convertit la forme depuis le format interne en une chaîne au format WKT.

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

#### 18.4.5.3. Lire des données géométriques au format WBK

La fonction `AsBinary()` fournit l'accès binaire aux formes géométriques. Elle convertit une forme géométrique, depuis le format interne en un `BLOB` contenant la représentation WKB.

    SELECT AsBinary(g) FROM geom;

## 18.5. Analyser des données géographiques

Après avoir remplies les colonnes géographiques avec des valeurs, vous êtes prêts à les analyser. MySQL propose un jeu de fonctions pour effectuer différentes opérations sur des données géographiques. Ces fonctions peuvent être regroupées en plusieurs catégories principales, suivant le type de manipulations :

- Les fonctions qui convertissent les données géométriques en différents formats.

- Les fonctions qui fournissent des accès aux données qualitatives ou quantitatives d'un objet géométrique.

- Les fonctions qui décrivent les relations entre deux objets géométriques.

- Les fonctions qui créent des objets à partir d'autres objets existants.

Les fonctions d'analyse de données géographiques peuvent être utilisées dans plusieurs contextes, comme :

- Un programme SQL interactif, comme `mysql` ou `MySQLCC`

- Une application écrite dans un langage qui dispose du support des bibliothèques clientes MySQL.

### 18.5.1. Fonctions pour convertir les formes de format

MySQL supporte les fonctions suivantes pour convertir des formes géométriques entre les formats internes, WKT et WKB :

- `GeomFromText(wkt[,srid])`

  Convertit une chaîne au format WKT vers le format interne, et retourne le résultat. Des fonctions adaptées au type sont supportées comme `PointFromText()` et `LineFromText()`; voyez Section 18.4.2.1, « Créer des objets géométriques avec les fonctions WKT ».

- `GeomFromWKB(wkb[,srid])`

  Convertit une chaîne au format WKB vers le format interne, et retourne le résultat. Des fonctions adaptées au type sont supportées comme `PointFromWKB()` et `LineFromWKB()`; voyez Section 18.4.2.2, « Créer des objets géométriques avec les fonctions WKB ».

- `AsText(g)`

  Convertit une chaîne au format interne vers le format WKT, et retourne le résultat.

      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)  |
      +--------------------------+

- `AsBinary(g)`

  Convertit une chaîne au format interne vers le format WKB, et retourne le résultat.

### 18.5.2. Fonction d'analyse des propriétés des formes `Geometry`

Chaque fonction de ce groupe prend une forme géométrique comme argument et représente un attribut qualitatif ou quantitatif de cette forme. Certaines fonctions sont spécifiques à une forme particulière. Certaines fonctions retournent `NULL` si l'argument n'est pas d'un type valide. Par exemple, `Area()` retourne `NULL` si le type de l'objet est ni `Polygon` ni `MultiPolygon`.

#### 18.5.2.1. Fonctions générales d'analyse géométrique

Les fonctions de cette section n'ont pas de restriction sur les arguments, et acceptent toutes sortes de formes.

- `GeometryType(g)`

  Retourne le type de forme de `g`, sous forme de chaîne. Le nom correspond à l'une des sous-classes instanciable `Geometry`.

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

- `Dimension(g)`

  Retourne le nombre de dimensions de l'objet `g`. Le résultat peut être −1, 0, 1 ou 2. La signification de ces valeurs est expliqué dans la section Section 18.2.2, « Classe `Geometry` ».

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

- `SRID(g)`

  Retourne un entier indiquant l'identifiant du système de coordonnées de la forme `g`.

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

- `Envelope(g)`

  Retourne le rectangle enveloppe (`Minimum Bounding Rectangle`, ou `MBR`) de la forme `g`. Le résultat est retourné sous forme de polygone.

      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))                        |
      +-------------------------------------------------------+

  Le polygone est défini par ses sommets :

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

Les spécifications OpenGIS définissent les fonctions suivantes, que MySQL n'implémente pas :

- `Boundary(g)`

  Retourne une forme qui représente la frontière de `g`.

- `IsEmpty(g)`

  Retourne 1 si la forme `g` est vide, et 0 si elle n'est pas vide. Elle retourne −1 si l'argument est `NULL`. Si la forme est vide, elle représente un ensemble de points vide.

- `IsSimple(g)`

  Actuellement, cette fonction est un inutilisable et ne doit pas être employée. Lorsqu'elle sera fonctionnelle, elle suivra la définition du prochain paragraphe.

  Retourne 1 si la forme géométrique `g` n'au aucune anomalie géométrique, telle que l'auto-intersection ou l'auto-tangence. `IsSimple()` retourne 0 si l'argument n'est pas simple, −1 si l'objet est `NULL`.

  La description de chaque classe géométrique instanciable est donnée plus tôt dans ce chapitre, et inclut les conditions qui font qu'une forme est considérée comme simple ou pas.

#### 18.5.2.2. Fonctions d'analyse des `Point`

Un objet `Point` est constitué de ses coordonnées X et Y, qui peuvent être obtenues comme ceci :

- `X(p)`

  Retourne l'absisse du point `p` sous forme d'un nombre à virgule en double précision.

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

- `Y(p)`

  Retourne l'ordonnée du point `p` sous forme d'un nombre à virgule en double précision.

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

#### 18.5.2.3. Fonctions d'analyse des lignes `LineString`

Une ligne `LineString` est constituée de `Point`. Vous pouvez extraire des points particuliers d'une ligne `LineString`, compter le nombre de point qu'elle contient, ou encore calculer sa longueur.

- `EndPoint(ls)`

  Retourne le `Point` terminal de la ligne `LineString` `ls`.

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

- `GLength(ls)`

  Retourne la longueur de la ligne `ls` sous forme d'un nombre à virgule et double précision.

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

- `IsClosed(ls)`

  Retourne 1 si `ls` est fermée : c'est à dire si `StartPoint()` et `EndPoint()` sont identiques. Retourne 0 si `ls` n'est pas fermée, et −1 si l'argument passé est `NULL`.

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

- `NumPoints(ls)`

  Retourne le nombre de points dans la ligne `ls`.

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

- `PointN(ls,n)`

  Retourne le `n`-ième point de la ligne `ls`. La numérotation des points commence à 1.

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

- `StartPoint(ls)`

  Retourne le premier `Point` de la ligne `ls`.

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

Les spécifications OpenGIS définissent aussi les fonctions suivantes, que MySQL n'implémente pas encore :

- `IsRing(ls)`

  Retourne 1 si `ls` est un anneau : il faut que `ls` soit fermée (c'est à dire que `StartPoint()` et `EndPoint()` sont identiques), et qu'elle soit simple (ne passe pas par le même point plusieurs fois). Retourne 0 si `ls` n'est pas un anneau, et −1 si elle vaut `NULL`.

#### 18.5.2.4. Fonctions d'analyse des lignes `MultiLineString`

- `GLength(mls)`

  Retourne la longueur de l'objet `mls`. La longueur de l'objet `mls` est égale à la somme des longueur de ses éléments.

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

- `IsClosed(mls)`

  Retourne 1 si `mls` est fermée (c'est à dire que `StartPoint()` et `EndPoint()` sont identique pour chaque objet `LineString` de `mls`). Retourne 0 si `mls` n'est pas fermée et −1 si l'objet est `NULL`.

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

#### 18.5.2.5. Fonctions d'analyse des lignes `Polygon`

- `Area(poly)`

  Retourne un nombre à virgule en double précision représentant l'aire de l'objet `Polygon` `poly`, tel que mesuré dans son référentiel.

      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 |
      +---------------------------+

- `NumInteriorRings(poly)`

  Retourne le nombre d'anneau intérieurs de `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 AsText(ExteriorRing(GeomFromText(@poly)));
      +-------------------------------------------+
      | AsText(ExteriorRing(GeomFromText(@poly))) |
      +-------------------------------------------+
      | LINESTRING(0 0,0 3,3 3,3 0,0 0)           |
      +-------------------------------------------+

- `InteriorRingN(poly,n)`

  Retourne le `n`-ième anneau intérieur de l'objet `Polygon` `poly` sous forme d'un objet `LineString`. Ring numbers begin at 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)              |
      +----------------------------------------------+

- `InteriorRingN(poly,n)`

  Retourne le nombre d'anneaux intérieurs dans l'objet `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. Fonctions d'analyse des lignes `MultiPolygon`

- `Area(mpoly)`

  Retourne la surface de l'objet `MultiPolygon` `mpoly`, mesuré dans son référentiel.

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

Les spécifications OpenGIS définissent aussi les fonctions suivantes, que MySQL n'implémente pas encore :

- `Centroid(mpoly)`

  Retourne le centre mathématique de l'objet `MultiPolygon` `mpoly`, sous la forme d'un `Point`. Le résultat n'est pas forcément dans l'objet `MultiPolygon`.

- `PointOnSurface(mpoly)`

  Retourne un point `Point` qui est dans l'objet `MultiPolygon` `mpoly`.

#### 18.5.2.7. Fonctions d'analyse des lignes `GeometryCollection`

- `NumGeometries(gc)`

  Retourne le nombre de formes géométriques qui constituent l'objet `GeometryCollection` `gc`.

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

- `GeometryN(gc,n)`

  Retourne le `n`-ième objet constituant l'objet `GeometryCollection` `gc`. La numérotation commence à 1.

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

### 18.5.3. Fonctions qui génèrent des formes géométriques à partir d'autres formes

#### 18.5.3.1. Fonctions géométriques qui génèrent de nouvelles formes

Dans la section Section 18.5.2, « Fonction d'analyse des propriétés des formes `Geometry` », nous avons déjà discuté de certaines fonctions qui génèrent de nouvelles formes à partir de formes existantes :

- `Envelope(g)`

- `StartPoint(ls)`

- `EndPoint(ls)`

- `PointN(ls,n)`

- `ExteriorRing(poly)`

- `InteriorRingN(poly,n)`

- `GeometryN(gc,n)`

#### 18.5.3.2. Opérateurs géométriques

OpenGIS propose d'autres fonctions qui génèrent des formes géométriques. Elles sont con¸ues pour servir d'opérateurs géométriques.

Ces fonctions ne sont pas encore implémentées par MySQL. Elles devraient arriver dans les prochaines versions.

- `Intersection(g1,g2)`

  Retourne l'ensemble des points qui représentent l'intersection des deux formes `g1` et `g2`.

- `Union(g1,g2)`

  Retourne l'ensemble des points qui représentent l'union des deux formes `g1` et `g2`.

- `Difference(g1,g2)`

  Retourne l'ensemble des points qui représentent la différence des deux formes `g1` et `g2`.

- `SymDifference(g1,g2)`

  Retourne l'ensemble des points qui représentent la différence symétrique des deux formes `g1` et `g2`.

- `Buffer(g,d)`

  Retourne l'ensemble des points dont la distance à la forme `g` est inférieure ou égale à `d`.

- `ConvexHull(g)`

  Retourne l'enveloppe convexe de la forme géométrique `g`.

### 18.5.4. Fonctions de tests des relations géométriques entre les formes

Les fonctions décrites dans ces fonctions prennent deux formes géométriques comme argument, et retourne des informations qualitatives ou quantitatives sur leur relation.

### 18.5.5. Relations avec les Rectangles enveloppes (MBRs)

MySQL fournit des fonctions qui permettent de tester les relations entre les rectangles enveloppes de deux formes géométriques `g1` et `g2`. Il s'agit de :

- `MBRContains(g1,g2)`

  Retourne 1 ou 0 pour indiquer le rectangle enveloppe de `g1` contient celui de `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 |
      +----------------------+----------------------+

- `MBRWithin(g1,g2)`

  Retourne 1 ou 0 pour indiquer le rectangle enveloppe de `g1` est à l'intérieur de `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 |
      +--------------------+--------------------+

- `MBRDisjoint(g1,g2)`

  Retourne 1 ou 0 pour indiquer les rectangles enveloppe de `g1` et `g2` sont disjoints (ils n'ont pas d'intersection).

- `MBREquals(g1,g2)`

  Retourne 1 ou 0 pour indiquer le rectangle enveloppe de `g1` est le même que celui de `g2`.

- `MBRIntersects(g1,g2)`

  Retourne 1 ou 0 pour indiquer le rectangle enveloppe de `g1` et celui de `g2` ont une intersection non vide.

- `MBROverlaps(g1,g2)`

  Retourne 1 ou 0 pour indiquer le rectangle enveloppe de `g1` recouvre une partie de celui de `g2`.

- `MBRTouches(g1,g2)`

  Retourne 1 ou 0 pour indiquer le rectangle enveloppe de `g1` touche celui de `g2`.

### 18.5.6. Fonctions qui testent les relations géométriques entre les formes

Les spécifications OpenGIS définissent les fonctions suivantes, que MySQL n'implémente pas encore. Elles devraient apparaître prochainement, dans les prochaines versions. Lorsqu'elles seront implémentées, elles fourniront le support complet des fonctions d'analyse spatiales, et non pas un simple support de la géométrie des enveloppes.

Ces fonctions opèrent toujours sur deux formes géométriques `g1` et `g2`.

- `Contains(g1,g2)`

  Retourne 1 ou 0 suivant que `g1` contient complètement `g2` ou pas.

- `Crosses(g1,g2)`

  Retourne 1 si `g1` rencontre `g2`. Retourne `NULL` si `g1` est un `Polygon` ou un `MultiPolygon`, ou si `g2` est un `Point` ou un groupe `MultiPoint`. Otherwise, returns 0.

  ''rencontre'' indique une relation entre deux formes, ayant les propriétés suivantes :

  - Les deux formes ont une intersection non vide.

  - Leur intersection est une forme géométrique qui a une dimension de moins que le nombre maximum de dimensions des deux formes `g1` et `g2`.

  - L'intersection n'est pas égale à `g1` ou `g2`.

- `Disjoint(g1,g2)`

  Retourne 1 ou 0 pour indiquer si `g1` est géométriquement disjoint de `g2` ou non.

- `Equals(g1,g2)`

  Retourne 1 ou 0 pour indiquer que `g1` est géométriquement égal à `g2`, ou non.

- `Intersects(g1,g2)`

  Retourne 1 ou 0, pour indiquer si `g1` a une intersection non vide avec `g2` ou pas.

- `Overlaps(g1,g2)`

  Retourne 1 ou 0 pour indiquer sir `g1` recouvre `g2` ou pas. Le terme recouvre signifie que deux formes géométriques ont une intersection de même dimension que les formes initiales, mais différentes de ces formes.

- `Touches(g1,g2)`

  Retourne 1 ou 0 pour indiquer si `g1` touche `g2` ou pas. Deux formes se touchent si leurs intérieurs ont une intersection vide, mais que l'une des deux frontières a une intersection non vide avec la frontière ou l'intérieur de l'autre.

- `Within(g1,g2)`

  Retourne 1 ou 0 pour indiquer si `g1` est à l'intérieur de `g2`.

- `Distance(g1,g2)`

  Retourne la distance la plus faible entre deux points des deux formes, sous forme d'un nombre à virgule et double précision.

- `Related(g1,g2,pattern_matrix)`

  Retourne 1 ou 0, pour indiquer si la relation géométrique spécifiée par `pattern_matrix` existe entre les formes `g1` et `g2`. Retourne −1 si les arguments sont `NULL`. Le paramètre `pattern_matrix` est une chaîne. Ses spécifications seront détaillées lorsque la fonction sera codée.

## 18.6. Optimiser l'analyse géographique

Il est connu que les index accélèrent les recherches dans les bases de données non-géographiques. C'est aussi vrai avec les bases de données géographiques. Avec l'aide d'une grande variété d'index multi-dimensionnels qui ont été con¸u pour cela, il est possible d'optimiser les recherches avec des index. Le plus classique est :

- Les requêtes de points, où on recherche les objets qui contiennent un point donné.

- Les requêtes de région, qui recherchent tous les objets ont des zones communes.

MySQL utilise des R-Trees avec répartition quadratique pour indexer les colonnes géographiques. Un index géographique est constitué en utilisant le MBR d'une forme géométrique. Dans la plupart des cas, le MBR est le rectangle minimum qui entoure une région. Pour les lignes horizontales ou verticales, le MBR est un rectangle généré dans les chaînes. Pour un point, le MBR est un rectangle dégénéré en un point.

### 18.6.1. Créer un index géométrique

MySQL peut créer des index géométriques en utilisant une syntaxe similaire à celle utilisée avec les index classiques, mais étendue avec l'attribut `SPATIAL`. Les colonnes géographiques doivent être déclarées comme `NOT NULL`. L'exemple suivant montre comment créer un index géographique :

- Avec `CREATE TABLE`:

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

- Avec `ALTER TABLE`:

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

- Avec `CREATE INDEX`:

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

Pour effacer un index géométrique, utilisez `ALTER TABLE` ou `DROP INDEX`:

- Avec `ALTER TABLE`:

      mysql> ALTER TABLE geom DROP INDEX g;

- Avec `DROP INDEX`:

      mysql> DROP INDEX sp_index ON geom;

Exemple : supposons que la table `geom` contient plus de 32000 formes, qui sont stockées dans la colonne `g`, avec le type `GEOMETRY`. La table dispose aussi d'une colonne d'identifiant `fid`, de type `AUTO_INCREMENT` pour stocker des identifiants d'objet.

    mysql> SHOW FIELDS FROM 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)

Pour ajouter un index géométrique à la colonne `g`, utilisez cette commande :

    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. Utiliser un index géométrique

L'optimiseur vérifie si un index géométrique est disponible et peut être utilisé pour accélérer les requêtes qui utilisent des fonctions comme `MBRContains()` ou `MBRWithin()` dans les clauses `WHERE`. Par exemple, imaginons que vous devons trouver les objets qui sont dans un rectangle donné :

    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)

Maintenant, vérifions comment cette requête est exécutée, avec la commande `EXPLAIN` :

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

Voyons ce qui se passe si nous n'avions pas utilisé d'index spatial :

    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);
    +----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
    | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
    +----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
    |  1 | SIMPLE      | geom  | ALL  | NULL          | NULL |    NULL | NULL | 32376 | Using where |
    +----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
    1 row in set (0.00 sec)

Exécutons la requête ci-dessus, en ignorant l'index spatial disponible :

    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)

Lorsque l'index n'est pas utilisé, le temps d'exécution de la requête passe de 0.00 seconde à 0.46 second.

Dans les prochaines versions, les index spatiaux seront aussi utilisés pour optimiser d'autres fonctions. See Section 18.5.4, « Fonctions de tests des relations géométriques entre les formes ».

## 18.7. MySQL compatibilité avec GIS

### 18.7.1. Les fonctionnalités de GIS que nous n'avons pas encore implémenté

- Vues de meta-données

  Les spécifications OpenGIS proposent plusieurs meta-données supplémentaires. Par exemple, un système de vue appelé `GEOMETRY_COLUMNS` contient une description les colonnes géométriques, une ligne pour chaque colonne géométrique dans la base.

- Les fonctions OpenGIS `Length()` sur les `LineString` et `MultiLineString` sont appelées `GLength()` en MySQL

  Le problème est que ce nom est en conflit avec la fonction SQL existante `Length()` qui calcule la taille d'une chaîne de caractères, et il n'est pas possible de faire la différence entre le contexte géographique ou textuel. Nous devons résoudre ce problème, ou trouver un autre nom à cette fonction.

This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.

Précédent |  | Suivant
Chapitre 17. Introduction à MaxDB | Sommaire | Chapitre 19. Procédures stockées et fonctions