Mehr

Zusammenführen von Linien (die sich möglicherweise kreuzen) an gemeinsamen Endpunkten ohne mehrteilige Features im Ergebnis

Zusammenführen von Linien (die sich möglicherweise kreuzen) an gemeinsamen Endpunkten ohne mehrteilige Features im Ergebnis


Ich habe ein Polylinien-Dataset, in dem ich versuche, Segmente basierend auf einem Attribut zu fortlaufenden Einzellinien zusammenzuführen / aufzulösen. Das Problem besteht darin, dass sich einige dieser Segmente kreuzen, aber im Endergebnis als einteiliges Feature dargestellt werden müssen. Die Segmente teilen sich höchstens einen Endpunkt mit einem anderen Segment mit demselben Wert und sollten alle gut zusammenrasten, da sie auf diese Weise digitalisiert wurden. (Die Daten werden schließlich in einem geometrischen Netzwerk verwendet und wir möchten nicht, dass Netzknoten Spuren umleiten.)

Hat es jemand geschafft, diesen Prozess mit meinen Kriterien zu automatisieren? Ich habe verschiedene Kombinationen der Werkzeuge Auflösen, Aufteilen von Linien und Zusammenführen in ArcGIS Desktop 10.3 ausprobiert, bis die durchgehenden Linien nicht erstellt wurden. Nicht-ArcGIS-basierte Lösungen sind willkommen, wenn dies die Arbeit erledigt.

Aktualisieren:

Das Endziel besteht also darin, getrennte Features zu verbinden und ein kontinuierliches Feature zu erzeugen, das sich über sich selbst schlingt, ohne einen Scheitelpunkt einzubeziehen, an dem sich die Linien kreuzen.

Funktionen vor dem Auflösen Nach der Auflösung - Kein Multipart, Unsplit (gemäß Michaels Vorschlag). Als Ergebnis werden drei Features erstellt (das ausgewählte Feature plus Features nördlich und westlich des angegebenen Schnittpunkts).


Dies ist VB.net-Code zum Zusammenführen von Linien, die einen gemeinsamen Endpunkt haben. Die aufzurufende Funktion ist UnsplitAllLayer0 mit den Hilfsfunktionen fFlipPC und fJoinPC. Der erste Schritt besteht darin, alle Orte zu finden, an denen sich zwei Linien einen Endpunkt teilen, und dann mit diesen Orten zurückzugehen und beide Funktionen zusammenzuführen (eines erweitern und das andere löschen). Eine Linie kann mehrmals verlängert werden, dies ist meiner Meinung nach am einfachsten Möglichkeit, bei mehreren Auflösungsvorgängen nicht den Überblick zu verlieren:

Private Funktion fFlipPC(ByRef InPointColl As IPointCollection) As IPointCollection Dim pOutPC As IPointCollection Dim cnt As Long pOutPC = Neuer Pfad 'pOutPc.RemovePoints 0, InPointColl.PointCount - 1 For cnt = InPointColl.PointCount - 1 To 0 Step -1 pOutPC.AddPoint (InPointColl.Point(cnt)) Next cnt fFlipPC = pOutPC End Function Private Function fJoinPC(ByRef FirstPointColl As IPointCollection, ByRef SecondPointColl As IPointCollection) As IPointCollection Dim pOutPC As IPointCollection Dim cnt As Long pOutPC = FirstPointColl For cnt = 1 .To SecondPointCollection - 1 pOutPC.AddPoint(SecondPointColl.Point(cnt)) Next cnt fJoinPC = pOutPC End Function Private Sub UnsplitAllLayer0() Dim pLayer As ILayer = My.ArcMap.Document.FocusMap.Layer(0) Falls nicht (TypeOf pLayer Is IFeatureLayer) Dann muss Exit Sub ' ein Feature-Layer sein Dim pFtLayer As IFeatureLayer = CType(pLayer, IFeatureLayer) ' Schritt eins: Finden Sie die wahrscheinlichen Standorte… Dim pLikelyLocations As IMultipoint = New MultipointClass() Dim pLikel yPC As IPointCollection = CType(pLikelyLocations, IPointCollection) ' einen Cursor auf alle Ihre Zeilen setzen Dim pFtCur As IFeatureCursor = pFtLayer.Search(Nothing, True) Dim pFeat As IFeature = pFtCur.NextFeature() Dim pTopOp As ITopologicalOperator As Im pometryBo Dimm pBoundaryPC As IPointCollection Dim pSpatFlt As ISpatialFilter = New SpatialFilterClass() pSpatFlt.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects Dim pSrchGeom wie IGeometry Do, bis pFeat nichts ist pTopOp = pFeat.ShapeCopy beide IepColleBoundary(e) pPntCnt As Integer = 0 To pBoundaryPC.PointCount - 1 pTopOp = pBoundaryPC.Point(pPntCnt) pSpatFlt.Geometry = pTopOp.Buffer(0.01) ' verwenden Sie hier eine geeignete kleine Zahl Wenn pFtLayer.FeatureClass.FeatureCount(pSpatFlt) = 2 Then pLikelyPC. AddPoint(pBoundaryPC.Point(pPntCnt)) ' speichere diesen Punkt, um später zurückzukehren ' füge hier etwas Code hinzu, um Attribute zu überprüfen ' wenn dies für dein Netzwerk wichtig ist End If Next pFeat = pFtCur.NextFeature() ' go next… Loop Dim pEd As IEditor = pApplication.FindExtensionByName("ESRI Object Editor") 'http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index. html#//0001000004nn000000 pEd.StartOperation() ' gehen jetzt die wahrscheinlichen Stellen durch und lösen für pLikelyCnt As Integer = 0 To pLikelyPC.PointCount - 1 pTopOp = pLikelyPC.Point(pLikelyCnt) pSpatFlt.Geometry = pTopOp.Buffer(0.01) ' verwenden Sie hier eine geeignete kleine Zahl Dim pUpCur As IFeatureCursor = pFtLayer.FeatureClass.Update(pSpatFlt, False) ' muss hier false sein Dim pFtInto As IFeature = pUpCur.NextFeature() ' derjenige, der die Form erhält Dim pFtRem As IFeature = pUpCur .NextFeature() ' diejenige die entfernt wird Dim pIntoPC As IPointCollection = pFtInto.ShapeCopy Dim pRemPC As IPointCollection = pFtRem.ShapeCopy ' gibt es 4 Möglichkeiten für die Linienorientierung: Dim pProxOp As IProximityOperator = pIntoPC.Point(0) Dim pFromFromDist = pProxOp.ReturnDistance(pRemPC.Point(0)) 'dist ance Start-Start Dim pFromToDist = pProxOp.ReturnDistance(pRemPC.Point(pRemPC.PointCount - 1)) ' Distanz Start-Ende pProxOp = pIntoPC.Point(pIntoPC.PointCount - 1) Dim pToFromDist = pProxOp.ReturnDistance(pRemPC.Point( 0)) 'Abstand Ende-Start Dim pToToDist = pProxOp.ReturnDistance(pRemPC.Point(pRemPC.PointCount - 1)) 'Abstand Ende-Ende Dim pOutPolyLine As IGeometryCollection = New PolylineClass() Dim pOutPath As IPointCollection = New PathClass() Dim pHasUpdated As Boolean = False If pToFromDist < 0.01 Then ' einfachster Fall einfach erweitern pOutPath.AddPointCollection(fJoinPC(pIntoPC, pRemPC)) pHasUpdated = True pIntoPC)) pHasUpdated = True ElseIf pFromToDist < 0,01 Then ' Erst erweitern pOutPath.AddPointCollection(fJoinPC(pRemPC, pIntoPC)) pHasUpdated = True ElseIf pToToDist < 0,01 Then ' Zweite spiegeln und dann verbinden pOutPath.AddPointCollection(fJoinPC) )) pHasUpdated = True End If If pHasUpdated Then pOutPolyLine.AddGeometry(pOutPath) Dim pOutShape As IGeometry = pOutPolyLine pOutShape.SpatialReference = pFtInto.ShapeCopy.SpatialReference ' aktualisieren Sie eine und entfernen Sie die andere pFtInto.Shape = pOutShape pUpCur.DeUpdateFeature(pFtInto(). End If Next pEd.StopOperation("Unsplit") End Sub

Haftungsausschluss: das ist sehr alten Code, ich habe seit ein paar Jahren nichts mehr in VB.net geschrieben und kann die aktuelle funktionierende Version sein oder auch nicht ... Ich musste diese aus einem Backup ausgraben.


Dies ist meine Praxis, 'Parasiten'-Knoten zu entfernen.

Ursprüngliches Netzwerk mit angezeigter Linkrichtung. Von FID gekennzeichnete Links:

Entscheiden Sie, wo die Senke sein wird, und drehen Sie ggf. den entsprechenden Link um. In diesem Fall habe ich Nr. 2 gewählt.

Als nächsten Schritt nenne ich 'Netzwerk erstellen'. Das Skript nimmt den ausgewählten Link, verfolgt alle Upstreams und dreht sie bei Bedarf unterwegs um. Im gezeigten Fall wird nur 1 Link umgedreht, das heißt Nr. 5.

Weisen Sie Knotentypen basierend auf der Kombination von Ein-/Aus-Links zu - ein weiteres Skript. Für ein einfaches No-Diversions-Netzwerk ist der "Source"-Knoten derjenige, bei dem inCount=0 und outCount=1, der redundante Knoten (Übergang) hat inCount=1 und outCount=1:

Verfolgen Sie alle Links stromabwärts von Source (Skript). Die Liste der FIDs in diesem Fall [3,0,5,1,4,2]. Erstellen Sie eine einzelne Polylinie, indem Sie Geometrien in dieser Reihenfolge zusammenführen (Skript).

Ich glaube nicht, dass dieser skriptfreie Ansatz hier überhaupt ausreicht.