Suite

Fusion de lignes (qui peuvent se croiser) aux extrémités communes sans caractéristiques en plusieurs parties dans le résultat

Fusion de lignes (qui peuvent se croiser) aux extrémités communes sans caractéristiques en plusieurs parties dans le résultat


J'ai un jeu de données de polylignes que j'essaie de fusionner / dissoudre des segments en fonction d'un attribut en lignes simples continues. Le problème est que certains de ces segments se croisent mais doivent être représentés comme une seule pièce dans le résultat final. Les segments partagent, au plus, un point de terminaison avec un autre segment de même valeur et devraient tous s'emboîter correctement puisqu'ils ont été numérisés de cette façon. (Les données seront éventuellement utilisées dans un réseau géométrique et nous ne voulons pas que les jonctions nettes détournent les traces.)

Quelqu'un a-t-il réussi à automatiser ce processus avec mes critères ? J'ai essayé diverses combinaisons des outils Dissolve, Unsplit Line et Merge dans ArcGIS Desktop 10.3, sans parvenir à créer les lignes continues. Les solutions non basées sur ArcGIS sont les bienvenues si cela permet de faire le travail.

Mettre à jour:

L'objectif final est donc de connecter des entités séparées et de produire une entité continue qui se boucle sur elle-même sans inclure le sommet a où les lignes se croisent.

Caractéristiques avant dissolution Après dissolution - Pas de multipart, Unsplit (selon la suggestion de Michael). Trois entités sont créées en conséquence (l'entité sélectionnée, plus les entités juste au nord et à l'ouest de l'intersection indiquée.)


Il s'agit du code VB.net pour fusionner des lignes qui partagent un point de terminaison commun, la fonction à appeler est UnsplitAllLayer0 avec les fonctions utilitaires fFlipPC et fJoinPC. La première étape consiste à trouver tous les emplacements où deux lignes partagent un point de terminaison, puis à utiliser ces emplacements pour revenir en arrière et fusionner les deux fonctionnalités (étendre l'une et supprimer l'autre)… une ligne peut être prolongée plusieurs fois, ce que j'ai trouvé est le plus simple moyen de ne pas perdre de vue les multiples opérations de dissolution :

Fonction privée fFlipPC(ByRef InPointColl As IPointCollection) As IPointCollection Dim pOutPC As IPointCollection Dim cnt As Long pOutPC = Nouveau chemin 'pOutPc.RemovePoints 0, InPointColl.PointCount - 1 For cnt = InPointColl.PointCount - 1 à 0 AddPoint -1 pOutPC. (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 Second For cnt = 1PointCollection - 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) Sinon (TypeOf pLayer Is IFeatureLayer) Ensuite, Exit Sub ' doit être une couche d'entités Dim pFtLayer As IFeatureLayer = CType(pLayer, IFeatureLayer) ' première étape : recherchez les emplacements probables… Dim pLikelyLocations As IMultipoint = New MultipointClass() Dim pLikel yPC As IPointCollection = CType(pLikelyLocations, IPointCollection) ' obtient un curseur sur toutes vos lignes Dim pFtCur As IFeatureCursor = pFtLayer.Search(Nothing, True) Dim pFeat As IFeature = pFtCur.NextFeature() Dim pTopOp As ITopologicalOperator Dim pBoundaryPC As IPointCollection Dim pSpatFlt As ISpatialFilter = New SpatialFilterClass() pSpatFlt.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects Dim pSrchGeom As IGeometry Do jusqu'à ce que pBound Is Nothing pTopary pPntCnt As Integer = 0 To pBoundaryPC.PointCount - 1 pTopOp = pBoundaryPC.Point(pPntCnt) pSpatFlt.Geometry = pTopOp.Buffer(0.01) ' utilise un petit nombre approprié ici Si pFtLayer.FeatureClass.FeatureCount(pSpatFlt) = 2 Alors pLikely AddPoint(pBoundaryPC.Point(pPntCnt)) ' stocker ce point pour y revenir plus tard ' ajouter du code ici pour vérifier les attributs ' si cela est important pour votre réseau End If Next pFeat = pFtCur.NextFeature() ' aller ensuite… Loop Dim pEd As IEditor = pApplication.FindExtensionByName("ESRI Object Editor") 'http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index. html#//00010000004nn000000 pEd.StartOperation() ' parcourez maintenant les emplacements probables et dissolvez For pLikelyCnt As Integer = 0 To pLikelyPC.PointCount - 1 pTopOp = pLikelyPC.Point(pLikelyCnt) pSpatFlt.Geometry = pTopOp.Buffer(0.01) ' utilisez un petit nombre approprié ici Dim pUpCur As IFeatureCursor = pFtLayer.FeatureClass.Update(pSpatFlt, False) ' doit être false ici Dim pFtInto As IFeature = pUpCur.NextFeature() ' celui qui obtiendra la forme Dim pFtRem As IFeature = pUpCur .NextFeature() ' celui qui sera supprimé Dim pIntoPC As IPointCollection = pFtInto.ShapeCopy Dim pRemPC As IPointCollection = pFtRem.ShapeCopy ' il y a 4 possibilités pour l'orientation de la ligne : Dim pProxOp As IProximityOperator = pInto' point de départ(0) Dim pFromFromDist = pProxOp.ReturnDistance(pRemPC.Point(0)) 'dist ance start-start Dim pFromToDist = pProxOp.ReturnDistance(pRemPC.Point(pRemPC.PointCount - 1)) ' distance start-end pProxOp = pIntoPC.Point(pIntoPC.PointCount - 1) Dim pToFromDist = pProxOp.ReturnDistance(pRemPC.Point( 0)) 'distance end-start Dim pToToDist = pProxOp.ReturnDistance(pRemPC.Point(pRemPC.PointCount - 1)) ' distance end-end Dim pOutPolyLine As IGeometryCollection = New PolylineClass() Dim pOutPath As IPointCollection = New PathClass() Dim pHasUpdated As Boolean = False If pToFromDist < 0.01 Then ' le cas le plus simple étend simplement pOutPath.AddPointCollection(fJoinPC(pIntoPC, pRemPC)) pHasUpdated = True ElseIf pFromFromDist < 0.01 Then ' flip first then join pOutPath.JolipInPC pIntoPC)) pHasUpdated = True ElseIf pFromToDist < 0.01 Then ' Extend first pOutPath.AddPointCollection(fJoinPC(pRemPC, pIntoPC)) pHasUpdated = True ElseIf pToToDist < 0.01 Then ' flip second then join PC pOutPath.AddPointCollection(fPCInFJoinPC(pInFJoinPC) )) pHasUpdated = True End If If pHasUpdated Then pOutPolyLine.AddGeometry(pOutPath) Dim pOutShape As IGeometry = pOutPolyLine pOutShape.SpatialReference = pFtInto.ShapeCopy.SpatialReference ' met à jour un et supprime l'autre pFtInto.Shape = pOutShape pUpdate.UpCur() End If Next pEd.StopOperation("Unsplit") End Sub

Avis de non-responsabilité : c'est très ancien code, je n'ai rien écrit dans VB.net depuis quelques années maintenant et peut être ou non la version de travail actuelle… J'ai dû extraire celle-ci d'une sauvegarde.


C'est ma pratique de supprimer les nœuds «parasites».

Réseau d'origine avec la direction des liens indiquée. Liens étiquetés par FID :

Décidez où se trouvera l'évier et retournez le lien pertinent si nécessaire. Dans ce cas, j'ai choisi le n ° 2.

La prochaine étape que j'appelle "créer un réseau". Le script prend le lien sélectionné, trace tout en amont et les retourne en déplacement si nécessaire. Dans le cas illustré, il ne retourne qu'un seul lien, c'est-à-dire le n ° 5.

Attribuez des types de nœuds en fonction de la combinaison de liens d'entrée/sortie - un autre script. Pour un réseau simple sans détournement, le nœud "Source" est celui où inCount=0 et outCount=1, le nœud redondant (transition) a inCount=1 et outCount=1 :

Tracez tous les liens en aval de la source (script). La liste des FID dans ce cas [3,0,5,1,4,2]. Construisez une seule polyligne en fusionnant les géométries dans cet ordre (script).

Je ne pense pas du tout que l'approche sans script fera l'affaire ici.