Good afternoon,
Create a Procedure that verifies if a point is inside or outside a Polygon.
I have a polygon table and a point table (Float)
I do all the conversions due.
To be able to do it, use the GOEMETRY data types.
When I execute the Procedure, it executes correctly until a certain point where I get the following error:
I use the Geometric data in this way:
DECLARE @ArrayPtosEncontrados GEOMETRY;
DECLARE @Puntos GEOMETRY;
SET @ArrayPtosEncontrados = GEOMETRY::STGeomFromText('LINESTRING('+@ArrayPtosPoligono+')', 0)
SET @Puntos = GEOMETRY::STGeomFromText('POINT('+REPLACE(FORMAT(@LatitudPto,'G'),',','.')+' '+REPLACE(FORMAT(@LongitudPto,'G'),',','.') +')', 0)
I add a complete example:
USE [BASE]
GO
/****** Object: StoredProcedure [dbo].[GeoUbicacion] Script Date: 13/12/2017 10:15:16 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GeoUbicacion] AS
DECLARE PUNTOS CURSOR FOR
SELECT LATITUD,LONGITUD FROM Automatizacion.dbo.geo_Puntos
DECLARE POLIGONOS CURSOR STATIC SCROLL FOR
SELECT NOMBRE_AREA,LATITUD, LONGITUD FROM Automatizacion.dbo.geo_Poligonos
ORDER BY NOMBRE_AREA,ORDEN
BEGIN TRY
SET NOCOUNT ON;
DECLARE @ArrayPtosEncontrados GEOMETRY;
DECLARE @ArrayPtosEncontrados2 GEOMETRY;
DECLARE @Puntos GEOMETRY;
DECLARE @PuntoPoligonoLat float;
DECLARE @PuntoPoligonoLon float;
DECLARE @NombrePoligono varchar(30);
DECLARE @Orden int;
DECLARE @Area varchar(30);
DECLARE @PrimerLat float;
DECLARE @PrimerLon float;
DECLARE @ArrayPtosPoligono VARCHAR(2000);
DECLARE @Primero int;
DECLARE @LatitudPto float;
DECLARE @LongitudPto float;
DECLARE @Pertenece varchar(2);
DECLARE @mensajeError VARCHAR(2000);
DECLARE @Diferente int;
--// SE ABRE EL CURSOR DE POLIGONOS \--
OPEN POLIGONOS;
--// POR CADA AREA DEL POLIGONO SE VERIFICA SI EL PUNTO PERTENECE A ELLA \--
--// SE TOMA EL PRIMER REGISTRO Y SE GUARDA EL AREA \--
FETCH NEXT FROM POLIGONOS INTO @NombrePoligono, @PuntoPoligonoLat, @PuntoPoligonoLon;
--// SE GUARDA EL PRIMER PUNTO PARA LUEGO AGREGARLO AL FINAL Y PODER CERRAR EL POLIGONO \--
SET @PrimerLat = @PuntoPoligonoLat
SET @PrimerLon = @PuntoPoligonoLon
SET @ArrayPtosPoligono = REPLACE(FORMAT(@PrimerLat,'G'),',','.')+' '+REPLACE(FORMAT(@PrimerLon,'G'),',','.')+','
SET @Primero = 0;
SET @Diferente = 0
WHILE (@@FETCH_STATUS = 0)
BEGIN
--// SE GUARDA EL AREA PARA EL CORTE DE CONTROL \--
SET @Area = @NombrePoligono;
--// MIENTRAS SIGA LA MISMA AREA, SE AGREGA LOS PUNTOS DEL POLIGONO \--
WHILE (@Area = @NombrePoligono)
BEGIN
if (@Primero = 0)
BEGIN
--// SE VUELVE A SETEAR EL PRIMER REGISTRO PARA EL NUEVO POLIGONO \--
SET @PrimerLat = @PuntoPoligonoLat
SET @PrimerLon = @PuntoPoligonoLon
SET @ArrayPtosPoligono = null
SET @ArrayPtosPoligono = REPLACE(FORMAT(@PrimerLat,'G'),',','.')+' '+REPLACE(FORMAT(@PrimerLon,'G'),',','.')+','
SET @ArrayPtosPoligono = @ArrayPtosPoligono
SET @Primero = 1
END
ELSE
BEGIN
SET @ArrayPtosPoligono = @ArrayPtosPoligono + REPLACE(FORMAT(@PuntoPoligonoLat,'G'),',','.')+' '+REPLACE(FORMAT(@PuntoPoligonoLon,'G'),',','.')+','
END
IF @Area <> @NombrePoligono or @@FETCH_STATUS <> 0
BEGIN
BREAK
END
ELSE
BEGIN
FETCH NEXT FROM POLIGONOS INTO @NombrePoligono, @PuntoPoligonoLat, @PuntoPoligonoLon;
IF (@Area <> @NombrePoligono)
BEGIN
BREAK;
END
END
END;
SET @Primero = 0
--// SE AGREGA EL PRIMER PUNTO PARA CERRAR EL POLIGONO \--
SET @ArrayPtosPoligono = @ArrayPtosPoligono + REPLACE(FORMAT(@PrimerLat,'G'),',','.')+' '+REPLACE(FORMAT(@PrimerLon,'G'),',','.')
--// TODOS LOS PUNTOS PARA UN AREA DETERMINADA \--
SET @ArrayPtosEncontrados = GEOMETRY::STGeomFromText('POLYGON(('+@ArrayPtosPoligono+'))', 0)
SET @ArrayPtosEncontrados2 = GEOMETRY::STGeomFromText('LINESTRING('+@ArrayPtosPoligono+')', 0)
PRINT 'POLIGONO: ' + @ArrayPtosPoligono
--// SE INSERTA EN TABLA TODOS LOS PUNTOS DEL POLIGONO RECORRIENDO EL CURSOR DE PUNTOS \--
--// SE ABRE EL CURSOR DE PUNTOS \--
OPEN PUNTOS;
FETCH PUNTOS INTO @LatitudPto, @LongitudPto;
WHILE(@@FETCH_STATUS = 0)
BEGIN
SET @Puntos = GEOMETRY::STGeomFromText('POINT('+REPLACE(FORMAT(@LatitudPto,'G'),',','.')+' '+REPLACE(FORMAT(@LongitudPto,'G'),',','.') +')', 0)
--// VERIFICA LOS PUNTOS QUE ESTAN EN EL POLIGONO \--
IF ((SELECT @ArrayPtosEncontrados2.STIntersects(@Puntos)) = 1)
BEGIN
SET @Pertenece = 'SI'
END
ELSE
BEGIN
SET @Pertenece = 'NO'
END
IF ((SELECT @ArrayPtosEncontrados.STContains(@Puntos)) = 1 and @Pertenece = 'NO')
BEGIN
SET @Pertenece = 'SI'
END
ELSE
BEGIN
SET @Pertenece = 'NO'
END
INSERT INTO dbo.GEO_Puntos_Poligonos (Nombre_Area,PuntosPoligono,PuntoX,PuntoY,PertenecePoligono)
VALUES (@Area,@ArrayPtosPoligono,REPLACE(FORMAT(@LatitudPto,'G'),',','.'),REPLACE(FORMAT(@LongitudPto,'G'),',','.'),@Pertenece)
FETCH PUNTOS INTO @LatitudPto, @LongitudPto;
END;
CLOSE PUNTOS
FETCH PRIOR FROM POLIGONOS INTO @NombrePoligono, @PuntoPoligonoLat, @PuntoPoligonoLon;
FETCH NEXT FROM POLIGONOS INTO @NombrePoligono, @PuntoPoligonoLat, @PuntoPoligonoLon;
END
--// SE CIERRA EL CURSOR DE POLIGONOS Y SE LIBERA LA MEMORIA \--
CLOSE POLIGONOS
DEALLOCATE POLIGONOS
--// SE CIERRA EL CURSOR DE PUNTOS Y SE LIBERA LA MEMORIA \--
CLOSE PUNTOS
DEALLOCATE PUNTOS
END TRY
BEGIN CATCH
SELECT @mensajeError = ERROR_MESSAGE();
PRINT 'SE PRODUJO EL SIGUIENTE ERROR: ' + @mensajeError
--// SE CIERRA EL CURSOR DE POLIGONOS Y SE LIBERA LA MEMORIA \--
CLOSE POLIGONOS
DEALLOCATE POLIGONOS
--// SE CIERRA EL CURSOR DE PUNTOS Y SE LIBERA LA MEMORIA \--
CLOSE PUNTOS
DEALLOCATE PUNTOS
END CATCH
ACLARACION:Si no agrego:
FETCH PRIOR FROM POLIGONOS INTO @NombrePoligono, @PuntoPoligonoLat, @PuntoPoligonoLon;
FETCH NEXT FROM POLIGONOS INTO @NombrePoligono, @PuntoPoligonoLat, @PuntoPoligonoLon;
At the end of the Loop, I lose a record.
Thank you very much.