jueves, 17 de octubre de 2013

Programa MapBasic para estimacion de distancias promedio

Antes que hablar de distancia media, cabe mencionar que la media es un promedio, lo mismo que la mediana y la moda. Un promedio es un estadígrafo que me da una aproximación de una sola variable al conjunto. Así, promedio no es sinónimo de media. La distancia promedio es un indicador de concentración.

La distancia media se define como el promedio de todos los promedios de distancias de cada punto contra los otros. En términos numéricos:


Si P es un conjunto de puntos p1,p2…pn, tales que existen en un plano de tal modo que hay una xi y una yi tales que son coordenadas de pi, entonces la distancia promedio de pi a P será para un j



Y la distancia promedio total será





La distancia promedio nos dará una idea, en un espacio isomorfo de que puntos tienen la cercanía óptima en el conjunto. Tiene diversas aplicaciones. Por ejemplo, si los puntos son escuelas, y se desea que una de las escuelas sea un centro de zona, la que tenga menor distancia promedio será aquella en la que la suma de los viajes es menor.



En el cálculo de la distancia promedio hay dos opciones, contar o no la distancia de cada punto contra si mismo. Normalmente no se cuenta.
El algoritmo para programación geográfica en MapBasic es el que sigue. Algoritmos muy similares pueden escribirse en Avenue, Autolisp u otros lenguajes de objetos geográficos. Para correrlo debe haber una tabla de puntos en MapInfo que contengan una columna llamada DistanciaPromAlRest donde se almacenarán los datos de distancia promedio.
Dim Fin, NumeroDePuntos, M As Integer
Dim X,Y,SUMA,Distancia,DistanciaPromedio As Float
Dim PuntoAEvaluar As Object                        ‘es posible definir variables
                                               ‘objeto, las comillas son remakes
                                               ‘que permiten ignorar el comentario
                                               ‘siguiente como en este caso

Fin=TableInfo(Puntos,8)’ la variable fin es el número de renglones en la tabla
Select * From Puntos Where RowId=1                 ‘selecciona el primer registro de
                                               ‘ la tabla


For NumeroDePuntos =1 To FIN                       ‘se inicia un ciclo para recorrer
                                                    ‘todos los objetos de la tabla, son
                                                    ‘puntos sobre los cuales se medirá
                                                    ‘ la distancia al resto

Select Obj From Puntos Where RowId=NumeroDePuntos ‘selecciona el renglón que va en el ciclo

PuntoAEvaluar= Selection.Obj ‘se define un objeto a examinar

   X=ObjectGeography(PuntoAEvaluar,1)          ‘se extraen las coordenadas del
                                                    ‘punto
   y=ObjectGeography(PuntoAEvaluar,2)

   Suma=0                                      ‘Se inicia acumulador donde se
                                               ‘añade distancia total

   For M=1 To FIN
       Select * From Puntos Where RowId=M          ‘Se inicia ciclo para medir la
                                               ‘distancia al segundo punto

       Distancia=Distance(X,Y,CentroidX(Selection.Obj),CentroidY(Selection.Obj),"cm")
                                               ‘se estima la distancia

       Suma=Suma+Distancia                     ‘se suma la distancia
   Next

DistanciaPromedio=Suma/FIN                     ‘se promedia

Update Puntos
   Set DistanciaPromAlResto = DistanciaPromedio    ‘se almacena
   Where Rowid = NumeroDePuntos


Next


Si interpolamos el resultado sale algo como lo siguiente:


Programa en MapBasic para convertir distancia euclidiana a distancia Manhattan

En muchas ocasiones en problemas de cartografía numérica, tenemos un archivo con líneas. Pueden referirse por ejemplo a líneas de deseo de una encuesta origen destino. La apariencia es esta:


Es muy probable que estemos interesados no en conocer la distancia euclidiana o la loxodrómica sino la distancia Manhattan. A veces por la contabilidad cartográfica no es posible conocer el trayecto exacto de un objeto, pero si puntos origen destino. Entonces la distancia entre estos puntos es una aproximación al recorrido real. En la figura de abajo se muestra como representamos normalmente el recorrido entre dos puntos. 


Sin embargo el recorrido real puede ser como el que se muestra abajo. Cabe mencionar que entre más cercanos sean los puntos se tenderá a mayor tensión de línea, es decir, a tener una línea más  cercana a la recta euclidiana.


Una aproximación que no refleja el recorrido exacto pero tampoco es tan generalizado como el euclidiano, es la distancia Manhattan, que por definición es la distancia resultante entre dos puntos de sumar los lados que resultan del tríángulo que tiene esa distancia por hipotenusa en un ángulo recto con lados paralelos a los ejes cartesianos.



Además esta distancia tiene la propiedad de que será igual en cualquier trayecto a base de ángulos rectos que se haga. Tal como se muestra en la figura de abajo. Será lo mismo caminar del punto superior al inferior con cualquier combinación, siempre y cuando el trayecto forme ángulos rectos.


Bien, ahora, como se cálcula la distancia?. Simplemente hay que extraer el objeto, estimar las coordenadas del punto origen (X1,Y1) y las del punto destino (X2,Y2) , y estimar las ditancias de los lados.

Si tenemos un archivo en MapInfo de rectas, llamado "Lineas" con una columna llamada Manhhatan, solamente vamos extrayendo cada recta. Y obtenemos la distancia del punto X1,Y1 al punto X2,Y1 que es el lado paralelo a las X, y luego, de X1,Y1 a X1,Y2. Y se suman.

He aquí el programa para correr en MapBasic:

Dim Fin,N As Integer
Dim X1,X2,Y1,Y2,DistH,DistV,Hipo,Manhatan As Float
Dim Tp As String
Dim MyLine As Object
Dim Tabla As String
Tabla="Lineas"
Fin=TableInfo(Tabla,8)

For N=1 To Fin
Select Obj From Tabla Where RowId=N Into Provi
MyLine=Provi.Obj

X1=ObjectGeography(MyLine,1)
X2=ObjectGeography(MyLine,3)
Y1=ObjectGeography(MyLine,2)
Y2=ObjectGeography(MyLine,4)

DistH=Distance(X1,Y1,X2,Y1,"km")
DistV=Distance(X1,Y1,X1,Y2,"km")
Hipo=Sqr(DistH*DistH+DistV*DistV)
Manhatan=DistH+DistV
Print N
Print Manhatan

UpDate Tabla
Set DistanciaManhattan=Manhatan
Where RowId=N


Next


martes, 15 de octubre de 2013

Programa para transformar nodos de rutas en líneas de rutas

Programa en MapBasic para realizar rutas a partir de puntos. Esto puede ser útil en muchas circunstancias, por ejemplo en una encuesta origen destino donde se tienen los nodos pero se quiere representar la ruta.

Este programa para un archivo de 400 puntos, genera una linea secuencial entre ellos. Es decir, une el primer punto con el segundo, el segundo con el tercero, etc.

Es decir, desde algo como esto:


Genera esto:

El resultado lo almacena en un archivo llamado Rutas.

Para correrlo se necesita tener un archivo en Mapinfo que se llame Puntos donde se almacenan los 400 puntos (pueden ser más siempre y cuando se modifique la línea del for N=1 to 400. Otro archivo vacío se debe llamar rutas.

'Programa para dibujo de rutas Tona Mini

Dim PuntoACrecer               As Object                           'define variable objeto donde estará siguiente pto.
Dim N                                  As Integer                           'se almacena contador
Dim CurrentX,CurrentY        As Float                              'se almacena coordenadas 1
Dim CurrentX2,CurrentY2    As Float                              'coordenadas siguientes


Select Obj From Puntos Where RowId=1                        'se selecciona el primer punto
PuntoACrecer=Selection.Obj                                           'se almacena en una variable objeto
CurrentX=CentroidX(PuntoACrecer)                               'se extraen sus coordenadas
CurrentY=CentroidY(PuntoACrecer)



For N=2 To 400                                                               'se inicia el conteo para el total de puntos

Select Obj From Puntos Where RowId=N Into Sel   'almacena punto en archivo dedicado a puntos

PuntoACrecer=Sel.Obj                                            'se almacena en punto variable objeto
CurrentX2=CentroidX(PuntoACrecer)                     'se extraen coordenadas
CurrentY2=CentroidY(PuntoACrecer)


Insert Into Rutas (Obj)                                              'se realiza el dibujo
Values (CreateLine (CurrentX,CurrentY,CurrentX2,CurrentY2))   'se almacena en geobase

CurrentX=CurrentX2    'almacenan segundas coords. en las primeras para repetir operacion
CurrentY=CurrentY2

Next