SIG : géometrie, égalité d’objet ou de données, quelle différence ?

Il existe une différence fondamentale entre une géométrie et la représentation objet de ce dernier. Un objet peut être binairement différent d’un autre, malgré que leur géométrie soient égales. Démonstration avec SQL Server et PostGreSQL/PostGIS…

voici donc 3 objets, des carrés pour faire simple. Créons la table et assignons les valeurs :


CREATE TABLE T_GEO  
(geo1 GEOMETRY,
 geo2 GEOMETRY,
 geo3 GEOMETRY)
 
INSERT INTO T_GEO  
VALUES ('POLYGON((1 1, 1 2, 2 2, 2 1, 1 1))',
        'POLYGON((2 1, 1 1, 1 2, 2 2, 2 1))',
        'POLYGON((2 1, 2 2, 1 2, 1 1, 2 1))');

Voici les images de nos carrés :
SIG Géometrie Carré 1
SIG Géometrie Carré 2
SIG Géometrie Carré 3
D’accord je dessine horriblement mal… mais c’est fait exprès !

Testons si l’objet « géo1″ est égal à « go2 et/ou « geo3″

La requête SQL Server :


SELECT 'geo1 comparé à geo2' AS COMPARAISON,  
       CASE WHEN geo1.STEquals(geo2) = 1                
            THEN 'OUI' ELSE 'NON' END AS GEO_EGAL,
       CASE WHEN geo1.STAsBinary() = geo2.STAsBinary()  
            THEN 'OUI' ELSE 'NON' END AS BIN_EGAL
FROM   T_GEO
UNION ALL
SELECT 'geo1 comparé à geo3',  
       CASE WHEN geo1.STEquals(geo3) = 1                
            THEN 'OUI' ELSE 'NON' END AS GEO_EGAL,
       CASE WHEN geo1.STAsBinary() = geo3.STAsBinary()  
            THEN 'OUI' ELSE 'NON' END AS BIN_EGAL
FROM   T_GEO;


La requête PG :


SELECT 'geo1 comparé à geo2' AS COMPARAISON,  
       CASE WHEN ST_Equals(geo1, geo2) = 1                
            THEN 'OUI' ELSE 'NON' END AS GEO_EGAL,  
       CASE WHEN ST_AsBinary(geo1) = ST_AsBinary(geo2)  
            THEN 'OUI' ELSE 'NON' END AS BIN_EGAL  
FROM   T_GEO  
UNION ALL  
SELECT 'geo1 comparé à geo3',  
       CASE WHEN ST_Equals(geo2, geo3) = 1                
            THEN 'OUI' ELSE 'NON' END AS GEO_EGAL,  
       CASE WHEN ST_AsBinary(geo2) = ST_AsBinary(geo3)  
            THEN 'OUI' ELSE 'NON' END AS BIN_EGAL  
FROM   T_GEO;

Le résultat :


COMPARAISON         GEO_EGAL BIN_EGAL
------------------- -------- --------
geo1 comparé à geo2 OUI      NON
geo1 comparé à geo3 OUI      NON

Aucun des objets n’est binairement égal à un autre, car nous n’avons pas pris le même point de départ et tourné différemment. Mais tous sont la même forme géométrique.
Pour vous en convaincre, superposons-les :
SIG Géometrie Carré
Bon, d’accord mes talents de dessinateur sont nuls… mais justement cela vous permet de voir que ce sont bien les mêmes objets… Si j’étais parfait vous n’auriez rien vu !

CQFD

NOTA : Au passage, notez les subtiles différences entre les requêtes :
1) SQL Server ne met pas de blanc souligné entre le préfixe ST et le reste du nom de la fonction.
2) SQL Server utilise une méthode et non une fonction. La méthode étant appliquée à l’objet celle ci est préfixé par l’objet en pointage.
PostGreSQL est parfaitement conforme à la norme SQL tandis que SQL Server ne l’est pas. Le choix MS peut paraître curieux, mais comme dans SQL Server se sont de véritables objets de type CLR (.net) qui sont stockées pour la géométrie et la géographie, et que par conséquent on y applique des méthodes, Microsoft à préférer ne pas induire en erreur en supprimant le blanc souligné et ainsi pourvoir revenir sur une notation normative au cas ou…
Vous pouvez d’ailleurs faire vous même cette compatibilité…

Exemple :


CREATE FUNCTION  dbo.ST_Equals(@G1 GEOMETRY, @G2 GEOMETRY)
RETURNS BIT
AS
BEGIN
    RETURN @G1.STEquals(@G2);
END    
GO
CREATE FUNCTION dbo.ST_AsBinary (@G GEOMETRY)
RETURNS VARBINARY(max)
AS
BEGIN
    RETURN @G.STAsBinary();
END

Mais nous ne sommes pas très avancés, car il faut maintenant utiliser le schéma dbo pour appeler nos fonctions…


SELECT 'geo1 comparé à geo2' AS COMPARAISON,    
       CASE WHEN dbo.ST_Equals(geo1, geo2) = 1                  
            THEN 'OUI' ELSE 'NON' END AS GEO_EGAL,  
       CASE WHEN dbo.ST_AsBinary(geo1) = dbo.ST_AsBinary(geo2)    
            THEN 'OUI' ELSE 'NON' END AS BIN_EGAL  
FROM   T_GEO  
UNION ALL  
SELECT 'geo1 comparé à geo3',    
       CASE WHEN dbo.ST_Equals(geo2, geo3) = 1                  
            THEN 'OUI' ELSE 'NON' END AS GEO_EGAL,  
       CASE WHEN dbo.ST_AsBinary(geo2) = dbo.ST_AsBinary(geo3)    
            THEN 'OUI' ELSE 'NON' END AS BIN_EGAL  
FROM   T_GEO;

--------
Frédéric Brouard, SQLpro - ARCHITECTE DE DONNÉES, http://sqlpro.developpez.com/
Expert bases de données relationnelles et langage SQL. MVP Microsoft SQL Server
www.sqlspot.com : modélisation, conseil, audit, optimisation, tuning, formation
* * * * *  Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence  * * * * *

MVP Microsoft SQL Server

Laisser un commentaire