IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MS SQL Server Discussion :

Manipuler un curseur - Créer des POLYGON à partir d'une table de POINT


Sujet :

MS SQL Server

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2013
    Messages : 10
    Points : 5
    Points
    5
    Par défaut Manipuler un curseur - Créer des POLYGON à partir d'une table de POINT
    Bonjour tout le monde.

    Je manipule des données de type 'geography' et je rencontre un problème dans l'éxécution de mon code. J'ai une erreur spécifiant :
    "System.FormatException : 24115 : l'entrée WKB (well-know binary) n'est pas valide".
    J'ai compris que je rentre un type de données non valide, mais j'arrive pas à identifier ce qui cloche.


    Pour vous situer mon travail.
    J'ai une base de fichier texte contenant des couvertures satellites définient par tous les points formant leur contours (des sortes de cercles, patatoïdes). J'ai coupé le fichier pour voir à quoi y ressemble :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    beam_id;sat_name;gain;lon;sat 
    1;906z41downlink;-3.00;125.091;-20.655
    1;906z41downlink;-3.00;125.299;-20.632
    1;906z41downlink;-3.00;126.144;-20.593
    1;906z41downlink;-3.00;127.337;-20.494
    1;906z41downlink;-3.00;130.851;-20.147
    1;906z41downlink;-3.00;131.301;-20.022
    1;906z41downlink;-3.00;132.011;-19.896
    1;906z41downlink;-3.00;133.043;-19.654
    1;906z41downlink;-3.00;134.155;-19.499
    1;906z41downlink;-3.00;134.841;-19.253
    (... d autres points avec le même beam_id ...)
    2;906z41downlink;-1.00;141.187;24.476
    2;906z41downlink;-1.00;141.298;24.487
    2;906z41downlink;-1.00;141.443;24.501
    2;906z41downlink;-1.00;142.351;24.596
    2;906z41downlink;-1.00;144.550;25.075
    2;906z41downlink;-1.00;144.529;25.332
    (... d autres points avec le même beam_id ...)
    3;906z41downlink;-4.00;105.037;-20.751
    3;906z41downlink;-4.00;104.821;-20.626
    3;906z41downlink;-4.00;104.589;-20.499
    3;906z41downlink;-4.00;103.952;-20.091
    3;906z41downlink;-4.00;103.279;-19.693
    3;906z41downlink;-4.00;103.102;-19.571
    3;906z41downlink;-4.00;102.946;-19.467
    (... d autres points avec le même beam_id ...)
    (... etc ...)
    J'importe tous ces points dans ma base de données. Et les convertit en POINT de type 'geography' via :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    CREATE TABLE sat_beam (
    	beam_id int NOT NULL,
    	sat_ref char(50) NOT NULL,
    	gain real,	
    	longitude real,
    	latitude real
    );
     
    -- Add coordinates to sat_beam
    ALTER TABLE [sat_beam] ADD coordinate geography;
     
    UPDATE [dbo].[sat_beam]
       SET [coordinate] = geography::STPointFromText('POINT(' + CAST([longitude] AS VARCHAR(20)) + ' ' + 
                        CAST([latitude] AS VARCHAR(20)) + ')', 4326);
    GO
    Jusque là ça marche.
    J'ai donc un table remplie de plein de points. Les différentes couvertures sont identifiées par le beam_id.
    Je souhaite donc parcourir cette table et créer autant de POLYGON qu'il y a de couverture différentes. Ici ça se visualise par, dès que le beam_id change on a un nouveau polygon.

    Voici le code que j'ai mis en place (très très fortement inspiré d'ici)
    Mon bon ça marche pas. Il semblerait que je génère pas bien les @CoordinateStream de type "varbinary(max)", ce qu'y ferait que le WKB n'est pas valide.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    --- Init variables
    DECLARE @Point geography
    DECLARE @CoordinateStream varbinary(max)
    DECLARE @i int
    DECLARE @valb int
    -- 
    DECLARE @Bid int
    DECLARE @RefS char(50)
    DECLARE @Gain real
    DECLARE @PrevRefS char(50)
    DECLARE @PrevGain real
    DECLARE @Cpt int
    --
    SET @i = 0
    SET @valb = 2 -- comparing to b_id
    SET @Cpt = 0
     
    -- Cursor : check every row from sat_beam TABLE
    -- Insert each polygon in the stream
    DECLARE GeomCursor CURSOR FOR SELECT beam_id,sat_ref,gain,coordinate FROM sat_beam WITH (NOLOCK);
    OPEN GeomCursor;
    FETCH NEXT FROM GeomCursor INTO @Bid,@RefS,@Gain,@Point;
    WHILE @@FETCH_STATUS = 0
        BEGIN
    	-- First time the cursor look for the table
           IF (@i=0) BEGIN
                SET @CoordinateStream = SUBSTRING(@Point.STAsBinary(),6,16)
            END
            -- Change of beam ID value
            IF @valb = @Bid BEGIN
    	INSERT INTO ListOfBeam ( nb_points ,sat_ref, gain, stream ) VALUES ( @i-@Cpt,@PrevRefS,@PrevGain,@CoordinateStream )
     
    	-- Init and update for new beam
    	SET @CoordinateStream = NULL
    	SET @CoordinateStream = SUBSTRING(@Point.STAsBinary(),6,16)
    	SET @valb = @valb + 1
    	SET @Cpt = @i
            END
            ELSE BEGIN
    	SET @CoordinateStream = @CoordinateStream + SUBSTRING(@Point.STAsBinary(),6,16)
            END;
            SET @i = @i+1
            SET @PrevRefS = @RefS
            SET @PrevGain = @Gain
            FETCH NEXT FROM GeomCursor INTO @Bid,@RefS,@Gain,@Point;
    END;
    CLOSE GeomCursor;
    DEALLOCATE GeomCursor;
    GO
     
     
    -- To build a polygon from this 'coordinatestream'
    ALTER TABLE ListOfBeam ADD perimeter geography;
    GO
     
    -- Visualize polygon created
    SELECT geography::STPolyFromWKB(
     0x01 -- Again, sepcify big-endian byte order
     + 0x03000000 -- This is a 4-byte value showing that we are building a polygon
     + 0x01000000 -- The number of rings in the polygon. Let's keep it simple and assume we only have an exterior ring
     + CONVERT(varbinary,REVERSE(CONVERT(varbinary,[nb_points]+1))) -- There is one more point in the polygon definition than in the original set of points, since we repeat the start/end point
     + stream + SUBSTRING(stream,1,16) -- We take the co-ordinate stream, and repeat the first point co-ordinates to close the ring
     ,4326).STAsText()
    FROM ListOfBeam;
    GO
    Quelqu'un aurait une idée de mon problème?? J'intuite un MakeValid() quelque part mais je ne sais pas trop où, quand, comment l'utiliser...
    Merci à vous!

  2. #2
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2013
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Bon j'ai finalement réussit à résoudre mon problème par moi-même!!

    Il s'agissait en fait de la définition pure de mon POLYGON. Y faut bien avoir le même POINT en début et en fin de définition. Il se trouve que mon fichier source (sous format txt) le fait aléatoirement. Si j'attrape celui qui les a créé!!
    Donc il me suffit juste de garde en mémoire le premier point du POLYGON, de le répéter en fin de POLYGON et ça passe.

    Je le fais dans la définition du stream, dans le curseur. Il aime pas quand on le fait dans le geography::STPolyFromWKB (aucune idée du pourquoi...)

    Résultat des courses ça donne pour ceux que ça intéresse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    --- Create polygon perimeters with sat_beal Point data
    DECLARE @Point geography
    DECLARE @CoordinateStream varbinary(max)
    DECLARE @i int
    DECLARE @valb int
     
    DECLARE @Bid int
    DECLARE @RefS char(50)
    DECLARE @Gain real
    DECLARE @PrevRefS char(50)
    DECLARE @PrevGain real
    DECLARE @Cpt int
    DECLARE @FirstPoint varbinary(max)
     
    SET @i = 0
    SET @valb = 2 -- comparing to b_id
    SET @Cpt = 0
     
    DECLARE GeomCursor CURSOR FOR SELECT beam_id,sat_ref,gain,coordinate FROM sat_beam WITH (NOLOCK);
    OPEN GeomCursor;
    FETCH NEXT FROM GeomCursor INTO @Bid,@RefS,@Gain,@Point;
    WHILE @@FETCH_STATUS = 0
        BEGIN
    		-- First time the cursor look for the table
    		IF (@i=0) BEGIN
                SET @CoordinateStream = SUBSTRING(@Point.STAsBinary(),6,16)
    			SET @FirstPoint = @CoordinateStream
            END
    		-- Change of beam ID value
    		IF @valb = @Bid BEGIN
    			SET @CoordinateStream = @CoordinateStream + @FirstPoint
    			INSERT INTO ListOfBeam ( nb_points ,sat_ref, gain, stream ) VALUES ( @i-@Cpt+1,@PrevRefS,@PrevGain,@CoordinateStream )
     
    			-- Init and update for new beam
    			SET @CoordinateStream = SUBSTRING(@Point.STAsBinary(),6,16)
    			SET @FirstPoint = @CoordinateStream
    			SET @CoordinateStream = @CoordinateStream + SUBSTRING(@Point.STAsBinary(),6,16)
     
    			-- Modify var for new beam
    			SET @valb = @valb + 1
    			SET @Cpt = @i
    		END
    		ELSE BEGIN
    				SET @CoordinateStream = @CoordinateStream + SUBSTRING(@Point.STAsBinary(),6,16)
    		END
    		SET @i = @i+1
    		SET @PrevRefS = @RefS
    		SET @PrevGain = @Gain
    		FETCH NEXT FROM GeomCursor INTO @Bid,@RefS,@Gain,@Point;
        END;
    CLOSE GeomCursor;
    DEALLOCATE GeomCursor;
    --Insert last beam that is out of cursor
    INSERT INTO ListOfBeam ( nb_points ,sat_ref, gain, stream ) VALUES ( @i-@Cpt,@RefS,@Gain,@CoordinateStream );
    GO
     
     
    -- To build a WKB polygon from this 'coordinatestream'
    ALTER TABLE ListOfBeam ADD perimeter geography;
    GO
     
     
    -- Insert the created beam perimeter to ListOfBeam
    UPDATE [dbo].[ListOfBeam]
       SET [perimeter] = geography::STPolyFromWKB(
     0x01 -- specify big-endian byte order
     + 0x03000000 -- This is a 4-byte value showing that we are building a polygon
     + 0x01000000 -- The number of rings in the polygon. 
     + CONVERT(varbinary,REVERSE(CONVERT(varbinary,[nb_points]+1))) -- There is one more point in the polygon definition than in the original set of points, since we repeat the start/end point
     + [stream] -- We take the co-ordinate stream
     ,4326).MakeValid(); --MakeValid() for futur using
    GO

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 29/09/2014, 12h43
  2. Créer des raccourcis à partir d'une liste d'url
    Par bernardh dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 18/12/2013, 20h41
  3. Réponses: 5
    Dernier message: 15/04/2009, 15h38
  4. [Lazarus] Créer des fiches à partir d'une fiche modèle
    Par Louis Griffont dans le forum Lazarus
    Réponses: 4
    Dernier message: 19/03/2009, 13h10
  5. Comment créer des relances à partir d'1 table
    Par Rod_75 dans le forum Access
    Réponses: 9
    Dernier message: 01/03/2006, 15h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo