lunes, 18 de febrero de 2013

Extraer “HEIGHT”, “SLOPE” y “ASPECT” de un Tin en ArcGis

 
En este mes se hablara como extraer estas tres propiedades de un Tin. Primero necesitamos un shape / Layer de puntos con no mucha densidad ya que podría poner lento el proceso de extracción, solo si fuera muy necesario seria un shape / Layer con una densidad muy puntos muy grande. Es necesario también que el shape/ Layer tenga tres columnas nombradas “HEIGHT”, “SLOPE” y “ASPECT” (todas estas columnas deben ser de tipo “doublé”), donde serán guardas estas tres propiedades.



Creando columna HEIGHT
 
Creando columna SLOPE

Creando columna ASPECT

Viendo las tres columnas a utilizar

El código del programa sería el siguiente:
Sub LeerDatosTIN()

    Dim MiMxDocument As IMxDocument
    Set MiMxDocument = ThisDocument
    Dim MiMap As IMap
    Set MiMap = MiMxDocument.FocusMap
    
    Dim MiShape As ILayer
    Set MiShape = MiMxDocument.SelectedLayer
    
    Dim MiShapePunto As IFeatureLayer
    Set MiShapePunto = MiShape
    
    Dim NombLayerTIN As String
    NombLayerTIN = "tin"
        
    Dim MiLayerTin As ITinLayer
    Dim MiSurface As ISurface
    Dim MiLayerAux As ILayer
    Dim i As Integer
  
    For i = 0 To MiMap.LayerCount - 1
        Set MiLayerAux = MiMap.Layer(i)
    
        If MiLayerAux.Name = NombLayerTIN Then
            Set MiLayerTin = MiLayerAux
            If MiLayerTin.RendererCount <> 0 Then
                Set MiSurface = MiLayerTin.GetRenderer(0).Tin
            Else
                MsgBox "No hay renders en este TIN. Operación cancelada"
                Exit Sub
            End If
        End If
    Next i
    
Dim MiFeatureClass As IFeatureClass
Dim MiFeature As IFeature
Dim miPunto As IPoint
Dim a, b, c As Integer

Set MiFeatureClass = MiShapePunto.FeatureClass
For i = 0 To MiFeatureClass.FeatureCount(Nothing) - 1
    Set MiFeature = New Feature
    Set MiFeature = MiFeatureClass.GetFeature(i)
    Set miPunto = MiFeature.Shape

    a = MiFeatureClass.FindField("HEIGHT")
    MiFeature.Value(a) = MiSurface.GetElevation(miPunto)
    
    b = MiFeatureClass.FindField("SLOPE")
    MiFeature.Value(b) = MiSurface.GetSlopeDegrees(miPunto)
        
    c = MiFeatureClass.FindField("ASPECT")
    MiFeature.Value(c) = MiSurface.GetAspectDegrees(miPunto)

    MiFeature.Store
Next i
    
End Sub



Explicación del Programa:

1)      Dim MiMxDocument As IMxDocument
2)      Set MiMxDocument = ThisDocument
3)      Dim MiMap As IMap
4)      Set MiMap = MiMxDocument.FocusMap
5)      Dim MiShape As ILayer
6)      Set MiShape = MiMxDocument.SelectedLayer
7)      Dim MiShapePunto As IFeatureLayer
8)      Set MiShapePunto = MiShape
9)      Dim NombLayerTIN As String
10)    NombLayerTIN = "tin"

Donde:

1 ) Se crea un IMxDocument que es MiMxDocument y luego 2) se asigna a MiMxDocument al documento actualmente abierto (ThisDocument).
3) Se crea una variable de tipo IMap que es MiMap y en 4) se asigna el mapa actualmente en la pantalla (MiMxDocument.FocusMap).
5) Se crea una variable de tipo ILayer que es MiShape y sera el Shape / Layer de puntos donde extraeremos los valores de Height, Slope y Aspect del tin. Luego en 6) Este shape / Layer estará seleccionado (MiMxDocument.SelectedLayer) y contenido en la variable MiShape.
7) Creamos una variable de Tipo IFeatureLayer llamado MiShapePunto que nos permita acceder a cada punto del Shape / Layer (eso se verá luego) y en 8) se asigna el IFeatureLayer llamado MiShapePunto a la variable MiShape.
9) Luego creamos una variable de tipo string (texto) llamado NombLayerTIN y en 10) ponemos el nombre de nuestro tin a analizar en la variable NombLayerTIN. Tiene como nombre “tin”.
11)  Dim MiLayerTin As ITinLayer
12)  Dim MiSurface As ISurface
13)  Dim MiLayerAux As ILayer
14)  Dim i As Integer
15)  For i = 0 To MiMap.LayerCount - 1
16)        Set MiLayerAux = MiMap.Layer(i)
17)        If MiLayerAux.Name = NombLayerTIN Then
18)            Set MiLayerTin = MiLayerAux
19)            If MiLayerTin.RendererCount <> 0 Then
20)                Set MiSurface = MiLayerTin.GetRenderer(0).Tin
21)            Else
22)                MsgBox "No hay renders en este TIN. Operación cancelada"
23)                Exit Sub
24)            End If
25)        End If
26)    Next i

Donde:

11)  Se crea la variable MiLayerTin de tipo ITinLayer que tendrá la capa tin a analizar.
12)  Se crea la variable MiSurface que es de tipo ISurface y que tendrá la superficie seleccionada en la variable MiLayerTin.
13)  Se crean la variable MiLayerAux de tipo ILayer que nos servirá de variable auxiliar al buscar el tin a analizar.
14)  Se crea la variable i de tipo Integer que será de contador en la sentencia “For” que viene a continuación.
15)  Se inicia la sentencia “For”, que recorrerá desde i=0 hasta la totalidad de capas en el Mapa visto actualmente y que está en la variable MiMapa. En 26) se finaliza la sentencia “For”.
16)  Se asigna a la variable auxiliar MiLayerAux el Layer que está en el Mapa que está en la variable MiMap en la posición o valor de la variable i.
17)  En este condición “If” se evalúa si el Layer en la variable MiLayerAux tiene el mismo valor que la variable NombLayerTin que en el punto 10 es el nombre de nuestro tin a analizar y tiene por valor (o nombre) “tin”.
18)  Si la condición anterior es afirmativa, entonces la variable MiLayerTin que fue definida en el punto 11 se le asigna el Layer contenido en la variable MiLayerAux.
19)  En esta condición “If” se evalúa si la variable MiLayerTin tiene superficies para analizar.
20)  Si la condición anterior es afirmativa, entonces se asigna a la variable MiSurface la primera superficie o render que hay en el Layer MiLayerTin.
21)  Si la condición “If” en el punto 19 es negativo, en el punto 22) saldrá un mensaje diciendo que la operación ha sido cancelada y en el punto 23) se sale del programa.
24)  Es el fin de la condición “If” que comenzó en el punto 19.
25)  Es el fin de la condición “If” que comenzó en el punto 17.
27) Dim MiFeatureClass As IFeatureClass
28) Dim MiFeature As IFeature
29) Dim miPunto As IPoint
30) Dim a, b, c As Integer
31) Set MiFeatureClass = MiShapePunto.FeatureClass
32) For i = 0 To MiFeatureClass.FeatureCount(Nothing) - 1
33)    Set MiFeature = New Feature
34)    Set MiFeature = MiFeatureClass.GetFeature(i)
35)    Set miPunto = MiFeature.Shape
36)    a = MiFeatureClass.FindField("HEIGHT")
37)    MiFeature.Value(a) = MiSurface.GetElevation(miPunto)
38)    b = MiFeatureClass.FindField("SLOPE")
39)    MiFeature.Value(b) = MiSurface.GetSlopeDegrees(miPunto)
40)    c = MiFeatureClass.FindField("ASPECT")
41)    MiFeature.Value(c) = MiSurface.GetAspectDegrees(miPunto)
42)    MiFeature.Store
43) Next i
 
Donde:

27)  Se crea la variable MiFeatureClass de tipo IFeatureClass que tendrá la colección de registros (o features)  a  analizar del shape / Layer contenido en la variable MiShapePunto.
28)  Se crea la variable MiFeature que es de tipo IFeature y que tendrá solo un registro o feature de la colección de registros de la variable MiFeatureClass.
29)  Se crean la variable miPunto de tipo IPoint  que tendrá el punto asociado al registro que está contenido en la variable MiFeature.
30)  Se crea las variables a, b y c de tipo Integer que serán para localizar las columnas de “HEIGHT”, “SLOPE” y “ASPECT” respectivamente.
31)  Se asigna la colección de registros o features del Layer en la variable MiShapePunto hacia la variable MiFeatureClass.
32)  Se inicia la sentencia “For”, que recorrerá desde i=0 hasta la totalidad de registros o features de la variable MiFeatureClass. En 43) se finaliza la sentencia “For”.
33) Se inicializa la variable MiFeature.
34) Se asigna a la variable MiFeature el registro o feature que está en la colección / variable MiFeatureClass en la posición i.
35)  Luego se asigna a la variable miPunto la geometría o punto que está en el registro o feature MiFeature.
36)  Se busca la columna "HEIGHT" y la posición se guarda en la variable a.
37)  Luego se asigna al registro o feature correspondiente y en la columna en la posición en a, el valor de la elevación según la posición de la variable miPunto.
38)  Se busca la columna " SLOPE " y la posición se guarda en la variable b
39)  Luego se asigna al registro o feature correspondiente y en la columna en la posición en b, el valor de la pendiente (en porcentaje) según la posición de la variable miPunto.
40)  Se busca la columna " ASPECT " y la posición se guarda en la variable c
41)  Luego se asigna al registro o feature correspondiente y en la columna en la posición en c, el valor del aspect  según la posición de la variable miPunto.
42)  Se salva estas modificaciones.
Se ve que ahora las columnas están con las tres propiedades ya mencionadas:
Las tres columnas con los datos de TIN 

Podemos comprobar los valores extraídas con la herramienta “Identify”.



Cabe señalar que los puntos que no están contenidos o superpuestos en el área del Tin, tendrán un valor nulo.




Esperando que sea de ayuda. Sera hasta el otro mes.
ª