viernes, 29 de abril de 2016

Disolver polígonos en MapInfo (con MapBasic)

En este mes se presenta un ejemplo de disolver polígonos por un campo con MapBasic. Para ello usamos como archivo de entrada “LIMITE DEPARTAMENTOS.TAB” cuyos polígonos representan los departamentos del Perú y “DISOLVER_LIMITE DEPARTAMENTOS.TAB” (los pueden descargar de este ENLACE) donde se guardara el resultado producto de disolverlo por un campo.
El archivo de entrada “LIMITE DEPARTAMENTOS.TAB” tiene los siguientes campos:

NAME: donde están los nombres de los departamentos
REGION: donde está la región natural por cada departamento (COSTA, SIERRA, SELVA) y también  el valor de LAGO para los polígonos que representen dichos cuerpos de agua. Este campo lo usaremos para disolver los polígonos.

Debe ser como la imagen siguiente:












Para realizar esto, se utiliza la función Combine (Object1, Object2), donde Object1 y Object2 para este ejemplo son polígonos que se deseen combinar. El resultado de esta función (para este ejemplo) es un nuevo polígono. Para más información pueden consultar el Help de MapBasic. Para la ejecución de este ejemplo, deben estar los dos archivos mencionados arriba (“LIMITE DEPARTAMENTOS.TAB” y “DISOLVER_LIMITE DEPARTAMENTOS.TAB”) en la misma vista.

El código con comentarios es el siguiente:
Include "Mapbasic.def"

Dim CampoMerge as String
Dim Valor as String
Dim i as Integer

CampoMerge = "REGION"

Select REGION, Count(*) From LIMITE_DEPARTAMENTOS  Group By CampoMerge Order By CampoMerge  into MiCuenta NoSelect 'CUENTA LOS VALORES EN EL CAMPO REGION

Fetch First From MiCuenta 
Do While Not EOT (MiCuenta) 'RECORREMOS LOS VALORES DE MiCuenta
 Valor = MiCuenta.col1 'LEO EL VALOR DEL CAMPO REGION
 i = 0
 
 Select * From LIMITE_DEPARTAMENTOS where REGION = Valor 'SELECCIONA SEGUN EL Valor EN EL CAMPO REGION
 Fetch First From Selection 'RECORREMOS LOS VALORES DE CADA SELECCION
 Do While Not EOT (Selection)
  If (i = 0) Then
   Dim Poligono as Object
   Poligono = Selection.obj 'EN LA VARIABLE Poligono GUARDO EL PRIMER POLIGONO DE CADA SERIE DE Valor
  Else
   Poligono = Combine(Poligono, Selection.obj) 'LUEGO COMBINO CADA POLIGONO QUE LEE CON EL ANTERIOR
  End If
  i = i + 1
 Fetch Next From Selection
 Loop
 
 Insert Into DISOLVER_LIMITE_DEPARTAMENTOS (obj, REGION) Values (Poligono, Valor) 'INSERTAMOS LOS POLIGONOS EN LA TABLA DISOLVER_LIMITE_DEPARTAMENTOS
 Fetch Nex

Solo indicar que se utiliza un valor centinela (también conocido como flag) en cada momento que la variable i sea 0, en ese momento se crea una variable llamada Poligono de tipo Object y se guarda el polígono de dicho registró. Cuando la variable i tome otro valor se ejecuta la función Combine (Object1, Object2) que en este caso sería Combine (Poligono, Selection.obj) y el resultado es guardado en la misma variable Poligono (se actualiza dicha variable). Ademas que falta las funciones de guardar los cambios para  “DISOLVER_LIMITE DEPARTAMENTOS.TAB”.

En la siguiente imagen vemos el resultado:












Esperando que sea útil este ejemplo sencillo, será hasta el otro mes. Saludos

martes, 29 de marzo de 2016

Sentencias SQL y Postgresql

En este mes vamos a realizar unos pequeños ejemplos del uso de sentencias SQL en Postgresql para visualizar información proveniente de una tabla de datos. Para lo cual usaremos una tabla que tengan los departamentos del Perú (llamada PERU_DEPARTAMENTOS) y que está conformada por las siguientes columnas:

gid: que es la columna numérica que incrementa su valor al añadir un nuevo registro.
nombre: es el nombre del departamento. Columna de tipo character varying(50).
num_prov: número de provincias por departamento. Columna de tipo smallint.
num_dist: número de distritos por departamento. Columna de tipo smallint.
región_nat: región natural en que cada departamento está ubicado. Columna de tipo character varying(50).
Poblac: número de habitantes de cada departamento. Columna de tipo double precision.
The_geom: columna de tipo geometry donde están los polígonos que representan cada departamento. Estos polígonos están en coordenadas geográficas.

Tenemos por lo tanto siete columnas y 25 registros en esta tabla.

























1. Para ver todas las columnas y registros de la tabla PERU_DEPARTAMENTOS y ordenados de menor a mayor usamos:

select * from "PERU_DEPARTAMENTOS" order by nombre



























Si queremos ordenarlos de mayor por la columna nombre a menor usamos:
select * from "PERU_DEPARTAMENTOS" order by nombre DESC

























Esto es lo mismo que hacer:

select gid, nombre, num_prov, num_dist, región_nat, poblac, the_geom from "PERU_DEPARTAMENTOS" order by nombre DESC

Donde el asterisco (*) reemplaza a TODOS los nombres de las columnas.

DESC sirve para ordenar descendentemente una columna. ASC se usa para hacerlo ascendentemente. Cuando se usa order by por defecto se usa el ASC:

select * from "PERU_DEPARTAMENTOS" order by nombre

es lo mismo que usar
select * from "PERU_DEPARTAMENTOS" order by nombre ASC

2.  Si queremos agrupar los departamentos por región natural (región_nat), calcular la población por dichas regiones y ordenar el resultado por población de mayor a menor, usamos:

select distinct(region_nat), sum(poblac) as poblacion from "PERU_DEPARTAMENTOS" group by region_nat order by poblacion DESC














cabe resaltar que se puede cambiar el nombre de una columna en la consulta usando el as:
Select nombre_columna_original as nombre_columna_nueva
distinct sirve para eliminar los registros con igual valor, sum es para sumar los registros de una columna numérica. Si se usa distinct en una columna se debe usar group by para la misma columna.

3. Si queremos tener los nombres, la región natural, la población y el área en km2 de cada departamento, usamos:


select
nombre, region_nat, poblac, area(st_transform(the_geom,32718)) * 0.000001 as
area_km2 from "PERU_DEPARTAMENTOS"




















Para hallar el área en km2, usamos la columna the_geom, dicha columna están en coordenadas geográficas y se usa la función st_transform(columna_geometria,proyección a proyectar) y luego a este resultado se calcula el área con la función area(), y finalmente se multiplica por  0.000001 para pasar de m2 a km2 para después renombrar el resultado como area_km2.

4.Para calcular la densidad de cada departamento, usamos:

select a.nombre, a.poblac, a.area_km2 ,a.poblac / a.area_km2 as densidad
from
(select nombre, poblac, area(st_transform(the_geom,32718)) * 0.000001 as area_km2 from "PERU_DEPARTAMENTOS")a
order by nombre






















donde se observa una consulta anidada formada por dos subconsultas. Si se separaran por colores tenemos:

select a.nombre, a.poblac, a.area_km2 ,a.poblac / a.area_km2 as densidad
from
(select nombre, poblac, area(st_transform(the_geom,32718)) * 0.000001 as area_km2 from "PERU_DEPARTAMENTOS")a
order by nombre

Lo señalado en rojo es una consulta, cuyo resultado lo usamos como fuente para obtener el nombre, población y área (en km2). Necesariamente esta consulta anidada debe tener un nombre y se le ha llamado arbitrariamente como a. Luego en la consulta superior (marcado en negro) se hace el cálculo de la densidad poblacional (a.poblac/a.area_km2). Para llamar los campos de la consulta llamada a, se escribe: a.nombre_columna, donde nombre_columna es una columna que está en a.

5. Si se quiere ahora la densidad poblacional por región natural, usamos:

select a.region_nat, a.poblacion, a.area_km2 ,a.poblacion / a.area_km2 as densidad
from
(select distinct(region_nat) as region_nat, sum(poblac) as poblacion, sum(area(st_transform(the_geom,32718)) * 0.000001) as area_km2  from "PERU_DEPARTAMENTOS" group by region_nat) a











Es otra consulta anidada que al separarla en colores tenemos:

select a.region_nat, a.poblacion, a.area_km2 ,a.poblacion / a.area_km2 as densidad
from
(select distinct(region_nat) as region_nat, sum(poblac) as poblacion, sum(area(st_transform(the_geom,32718)) * 0.000001) as area_km2  from "PERU_DEPARTAMENTOS" group by region_nat) a

Lo señalado en rojo es parecido en el ejemplo número 2, solo que se ha agregado el área y a esta misma consulta se la ha llamado arbitrariamente como a.  Luego a la consulta a sirve para obtener la densidad como en el ejemplo 4.

Esperando que sea de ayuda este post. Sera hasta el otro mes. Saludos.

jueves, 25 de febrero de 2016

Barra de menú Ingeografos para MapInfo

En esta oportunidad comparto una barra de herramientas para MapInfo, con algunas funciones que permiten la edición, selección y dibujo de geometrías. Para descargar la aplicación y un manual pueden usar ESTE ENLACE. Si tienen algún comentario o reporte de error por favor mandar un correo a info@ingeografos.com.pe. Saludos.

viernes, 29 de enero de 2016

Exportar un TAB de MapInfo según los valores de un campo a varios DXFs

En este mes se presentara una rutina en MapBasic que al escoger un campo de un archivo TAB se exportara a tantos archivos DXFs como valores tenga dicho campo escogido.
Para nuestro ejemplo, tenemos un archivo TAB con las regiones del Perú y se desea exportar tantos archivos DXFs como valores hay en  este TAB. Si abrimos este TAB observamos que hay 35 filas y dos columnas. La columna a escoger es NOMB donde están los nombres de las  25 regiones del Perú y algunos lagos (con el valor de LAGO en dicha columna).
El código para hacer esto, es el siguiente:



Include "MapBasic.def"

Dim MiTabla as String
Dim MiDXF as String
Dim Columna as Alias
Dim Valor as String

MiTabla = "LIMITE_DEPARTAMENTOS" ' Nombre del archivo TAB a exportar
Columna = "NOMB" ' Nombre de la columna escogida para exportar segun sus valores
Fetch First From MiTabla ' Posicionamos el cursor de lectura de los valores del TAB en la primera fila de la tabla del TAB
Do While Not EOT (MiTabla) ' Bucle que permite leer los valores del TAB
 Columna = MiTabla & ".NOMB" 'Guardo el valor de la fila actual en el campo NAME (donde estan los valores a exportar)
 Valor = Columna 'Guardo el valor de Columna (variable tipo Alias) a otra variable de tipo String
 Select * From MiTabla Where NOMB =  Valor Into Valor NoSelect 'Seleccion de las filas segun nombre de la region
 MiDXF = "C:\MapInfo\" & Valor & ".dxf" 'Ruta donde el DXF va ser guardado con el nombre de la region

 'Comienza a exportar a DXF
 Export Valor 'Nombre de la seleccion con nombre de la region
  Into MiDXF 'archivo DXF que se guardara la seleccion
  Type "DXF" 'tipo de exportacion
  Overwrite 'permitir sobre escritura
  ASCII 'tipo de DXF, en este caso ASCII (permite ver el contenido con un notepad)
  Version 12 'version del DXF

 Fetch Next From MiTabla 'pasa a leer la siguiente fila
Loop

Note "Exportado..."


El código esta explicado en los comentarios, solo hacer algunas aclaraciones:

Este TAB tiene 35 valores y se explicó que son 25 regiones del Perú más un valor de lagos que suman 26 valores distintos, haciendo suponer que hay duplicidad de valores y esto hará que se haga tantas veces la selección (función Select) de valores como valores duplicados existan. En el código está el parámetro Overwrite que permite sobreescribir archivos, esto último ayuda a prevenir algún problema por la duplicidad de valores y haciendo que solo se creen 26 archivos DXFs (25 regiones del Perú y los lagos). Esperando que sea de ayuda, será hasta el otro mes. Saludos.
ª