Conectando características de línea y determinando la longitud de la línea más larga


12

Tengo una función de línea (ver imagen) que representa un río que creé usando la herramienta Stream_to_Feature. La tabla de atributos contiene varios registros que representan diferentes líneas: el problema es que la línea más larga (fácilmente distinguible visualmente) no está representada como una sola línea en la tabla, en realidad está compuesta por muchas líneas más pequeñas. Las líneas parecen estar en contacto, aunque no se cruzan entre sí.

¿Cómo puedo fusionar estas líneas y luego determinar la longitud de la línea más larga usando ArcObjects o métodos manuales que puedo convertir a ArcObjects? Una solución aún mejor implicaría deshacerse de todos los afluentes y dejarme solo con el canal del río como línea.

Característica de línea - río


1
¿Se conectan en absoluto? Dijiste que no se cruzan, pero ¿eso significa que no comparten un vértice?
Nathanus

1
Lo siento, debería haber sido más claro. Comparten vértices, pero no se cruzan completamente entre sí.
Radar

¿Sabes dónde está la desembocadura del río? ¿Es el río siempre un árbol (un camino único desde cada punto de cabecera hasta la desembocadura)?
Kirk Kuykendall

3
En realidad, no quieres la longitud de la "línea más larga". Esa podría ser una ruta de un alcance aguas arriba a otro alcance aguas arriba remoto. Esto sucederá cuando dos ramas principales de la corriente se unan cerca de su boca. En cambio, desea la ruta más larga entre la boca y cualquier otro punto final en la secuencia. (Esta caracterización ni siquiera requiere que la secuencia se represente como un árbol: puede trenzar y tener islas.)
whuber

@whuber: su evaluación es correcta. ¿Alguna idea de cómo puedo lograr esto usando rutas?
Radar

Respuestas:


18

Primero, un poco de antecedentes para indicar por qué esto no es un problema difícil. El flujo a través de un río garantiza que sus segmentos, si se digitalizan correctamente, siempre se pueden orientar para formar un gráfico acíclico dirigido (DAG). A su vez, un gráfico se puede ordenar linealmente si y solo si es un DAG, utilizando una técnica conocida como clasificación topológica . La ordenación topológica es rápida: sus requisitos de tiempo y espacio son O (| E | + | V |) (E = número de aristas, V = número de vértices), lo cual es tan bueno como es posible. La creación de un orden tan lineal facilitaría la búsqueda del lecho principal de la corriente.

Aquí, entonces, hay un bosquejo de un algoritmo . La boca del arroyo yace a lo largo de su lecho principal. Muévase aguas arriba a lo largo de cada rama unida a la boca (puede haber más de una, si la boca es una confluencia) y recursivamente encuentre el lecho principal que conduce a esa rama. Seleccione la rama para la cual la longitud total es mayor: ese es su "vínculo de retroceso" a lo largo de la cama principal.

Para aclarar esto, ofrezco algunos pseudocódigos (no probados) . La entrada es un conjunto de segmentos de línea (o arcos) S (que comprende el flujo digitalizado), cada uno con dos puntos finales distintos, inicio (S) y final (S) y una longitud positiva, longitud (S); y la desembocadura del río p , que es un punto. La salida es una secuencia de segmentos que unen la boca con el punto aguas arriba más distante.

Tendremos que trabajar con "segmentos marcados" (S, p). Estos consisten en uno de los segmentos S junto con uno de sus dos puntos finales, p . Necesitaremos encontrar todos los segmentos S que compartan un punto final con un punto de sonda q , marcar esos segmentos con sus otros puntos finales y devolver el conjunto:

Procedure Extract(q: point, A: set of segments): Set of marked segments.

Cuando no se puede encontrar dicho segmento, Extract debe devolver el conjunto vacío. Como efecto secundario, Extract debe eliminar todos los segmentos que está devolviendo del conjunto A, modificando así A en sí.

No estoy dando una implementación de Extracto: su SIG proporcionará la capacidad de seleccionar segmentos S que comparten un punto final con q . Marcarlos es simplemente una cuestión de comparar tanto el inicio (S) como el final (S) con q y devolver cualquiera de los dos puntos finales que no coincida.

Ahora estamos listos para resolver el problema.

Procedure LongestUpstreamReach(p: point, A: set of segments): (Array of segments, length)
    A0 = A                        // Optional: preserves A
    C = Extract(p, A0)            // Removes found segments from the set A0!
    L = 0; B = empty array
    For each (S,q) in C:          // Loop over the segments meeting point p
        (B0, M) = LongestUpstreamReach(q, A0)
        If (length(S) + M > L) then
            B = append(S, B0)
            L = length(S) + M
        End if
    End for
    Return (B, L)
End LongestUpstreamReach

El procedimiento "append (S, B0)" pega el segmento S al final de la matriz B0 y devuelve la nueva matriz.

(Si la secuencia realmente es un árbol: no hay islas, lagos, trenzas, etc., entonces puede prescindir del paso de copiar A en A0 ).

La pregunta original se responde formando la unión de los segmentos devueltos por LongestUpstreamReach.

Para ilustrar , consideremos la secuencia en el mapa original. Supongamos que está digitalizado como una colección de siete arcos. El arco a va desde la boca en el punto 0 (parte superior del mapa, a la derecha en la figura a continuación, que gira) aguas arriba hasta la primera confluencia en el punto 1. Es un arco largo, digamos 8 unidades de largo. El arco b se ramifica a la izquierda (en el mapa) y es corto, de aproximadamente 2 unidades de largo. El arco c se ramifica a la derecha y tiene aproximadamente 4 unidades de largo, etc. Dejando "b", "d" y "f" denotan las ramas del lado izquierdo a medida que avanzamos de arriba a abajo en el mapa, y "a", "c", "e" y "g" las otras ramas, y numerando los vértices del 0 al 7, podemos representar de manera abstracta el gráfico como la colección de arcos

A = {a=(0,1), b=(1,2), c=(1,3), d=(3,4), e=(3,5), f=(5,6), g=(5,7)}

Supongo que tienen longitudes 8, 2, 4, 1, 2, 2, 2 para a hasta g , respectivamente. La boca es el vértice 0.

Figura

El primer ejemplo es la llamada a Extraer (5, {f, g}). Devuelve el conjunto de segmentos marcados {(f, 6), (g, 7)}. Nota que vértice 5 está en la confluencia de arcos f y g (los dos arcos en la parte inferior del mapa) y que (f, 6) y (g, 7) marcan cada uno de estos arcos con sus aguas arriba puntos finales.

El siguiente ejemplo es la llamada a LongestUpstreamReach (0, A). La primera acción que toma es la llamada a Extraer (0, A). Esto devuelve un conjunto que contiene el segmento marcado (a, 1) y elimina el segmento a del conjunto A0 , que ahora es igual a {b, c, d, e, f, g}. Hay una iteración del ciclo, donde (S, q) = (a, 1). Durante esta iteración, se realiza una llamada a LongestUpstreamReach (1, A0). Recurrentemente, debe devolver la secuencia (g, e, c) o (f, e, c): ambas son igualmente válidas. La longitud (M) que devuelve es 4 + 2 + 2 = 8. (Tenga en cuenta que LongestUpstreamReach no modifica A0 .) Al final del bucle, segmente unse ha agregado al lecho de la corriente y la longitud se ha aumentado a 8 + 8 = 16. Por lo tanto, el primer valor de retorno consiste en la secuencia (g, e, c, a) o (f, e, c, a), con una longitud de 16 en cualquier caso para el segundo valor de retorno. Esto muestra cómo LongestUpstreamReach solo se mueve aguas arriba de la boca, seleccionando en cada confluencia la rama con la distancia más larga aún por recorrer, y realiza un seguimiento de los segmentos recorridos a lo largo de su ruta.

Es posible una implementación más eficiente cuando hay muchas trenzas e islas, pero para la mayoría de los propósitos habrá poco esfuerzo si LongestUpstreamReach se implementa exactamente como se muestra, porque en cada confluencia no hay superposición entre las búsquedas en las diversas ramas: la informática el tiempo (y la profundidad de la pila) serán directamente proporcionales al número total de segmentos.


+1 Ahora, si tan solo hubieran sabido esto antes de nombrar el río Missouri.
Kirk Kuykendall

1
@Kirk La exploración recursiva del oeste americano a principios de 1800 no fue fácil :-).
whuber

¡Esto es increíblemente útil! Veré si puedo obtener esta configuración dentro de mi SIG y compartir algún código útil una vez que lo haga funcionar. ¡Salud!
Radar

Buena respuesta whuber
Ragi Yaser Burhum

2

La herramienta Línea no dividida puede ser útil para lo que está tratando de hacer, aunque necesitará adivinar algún método para diferenciar una rama de flujo de otra (para el campo de disolución). Sin embargo, esto supone que tiene una licencia ArcInfo.

Si no tiene dicha licencia, puede considerar el enfoque de ArcObjects tomando el XY de cada vértice, llenando un IPointCollectioncon ellos y luego creando un IGeometrycomo a PolyLineClass.


1

Podría usar RivEX , es una herramienta ArcGIS 9.1 (que funcionará en 9.3 y 10). Tiene herramientas para identificar problemas topológicos con redes fluviales y muchas herramientas de procesamiento. Una de esas herramientas encuentra el tallo principal .

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.