3

I have a polyline dataset I'm trying to merge / dissolve segments based on an attribute into continuous single lines. The problem is that some of those segments cross each other but need to be represented as a single-part feature in the end result. The segments share, at most, one endpoint with another segment of the same value and should all snap together nicely since they were digitized that way. (The data will eventually be used in a geometric network and we don't want net junctions diverting traces.)

Has anyone managed to automate this process with my criteria? I've tried various combinations of the Dissolve, Unsplit Line and Merge tools in ArcGIS Desktop 10.3, all to failing to create the continuous lines. Non-ArcGIS based solutions are welcome if that will get the job done.

Update:

So the end goal is to connect separated features and produce continuous feature that loops over itself without the inclusion of the a vertex where the lines cross.

Features before dissolve Features before dissolve Post dissolve - No multipart, Unsplit (per Michael's suggestion). Three features are created as a result (The selected feature, plus features just north and west from the denoted intersection.) Dissolve - No multipart, Unsplit (per Michael's suggestion)

13
  • Do the same attribute segments have common sink? Would you like a single line from very top to sink? Any actual diversions, i.e. 2 segments running out from single node? Commented Jul 23, 2015 at 1:16
  • 1
    Dissolve resources.arcgis.com/en/help/main/10.2/index.html#//… - no multipart, unsplit lines. That will sort the geometries out but as for the fields/values what's up with them? are individual attributes required?... if you have an advanced license you can find them using Feature Vertices to Points (both ends, Dangle) connected endpoints are select all BOTH_ENDS then unselect near DANGLE. That will find the likely places lines will dissolve. Commented Jul 23, 2015 at 3:38
  • I'm not really following the cross but can't be multipart thing. Are you saying the tools are introducing new vertices where they shouldn't? Can you provide a screenshot of a problem area? Commented Jul 23, 2015 at 4:23
  • 1
    @MichaelMiles-Stimson I got that part; what I'm getting at is the planarize lines issue. If two lines cross and the allow multipart option isn't checked with dissolve, they should not become a single entity and no vertex should be introduced where they cross even if they have the same dissolve attribute. OP says merge/dissolve isn't working and that singlepart/multipart is an issue. I just think a graphic example of what the problem is would make it a lot clearer. Your first comment may be the answer, but the question isn't clear on exactly what is being done (and possibly done wrong). Commented Jul 23, 2015 at 17:12
  • 1
    Ok, I've just done some testing and I guess what I say should not happen is what actually does happen. Dissolve, and both Union and Merge on the Editor toolbar are planarizing the lines when run. This means a new vertex is introduced at the point of crossing, No matter what combination of options or methods I use, I can't seem to stop it from doing this. It's hard to see in OP's images (because that's showing vertex editing mode rather than selections), but the loop becomes a closed polyline with the two feeders as separate lines. Wonder if @Vince can help - if that notification even works. Commented Jul 23, 2015 at 19:39

2 Answers 2

1

This is VB.net code for merging lines that share a common end point, the function to call is UnsplitAllLayer0 with utility functions fFlipPC and fJoinPC. First step is to find all the locations where two lines share an endpoint then using those locations go back through and merge both features (extend one and delete the other)... a line may be extended multiple times, this I've found is the simplest way of not loosing track of multiple dissolution operations:

Private Function fFlipPC(ByRef InPointColl As IPointCollection) As IPointCollection Dim pOutPC As IPointCollection Dim cnt As Long pOutPC = New Path '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 SecondPointColl.PointCount - 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) If Not (TypeOf pLayer Is IFeatureLayer) Then Exit Sub ' must be a feature layer Dim pFtLayer As IFeatureLayer = CType(pLayer, IFeatureLayer) ' step one: find the likely locations.. Dim pLikelyLocations As IMultipoint = New MultipointClass() Dim pLikelyPC As IPointCollection = CType(pLikelyLocations, IPointCollection) ' get a cursor on all your lines Dim pFtCur As IFeatureCursor = pFtLayer.Search(Nothing, True) Dim pFeat As IFeature = pFtCur.NextFeature() Dim pTopOp As ITopologicalOperator Dim pBoundary As IGeometry Dim pBoundaryPC As IPointCollection Dim pSpatFlt As ISpatialFilter = New SpatialFilterClass() pSpatFlt.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects Dim pSrchGeom As IGeometry Do Until pFeat Is Nothing pTopOp = pFeat.ShapeCopy pBoundary = pTopOp.Boundary ' both ends pBoundaryPC = CType(pBoundary, IPointCollection) For pPntCnt As Integer = 0 To pBoundaryPC.PointCount - 1 pTopOp = pBoundaryPC.Point(pPntCnt) pSpatFlt.Geometry = pTopOp.Buffer(0.01) ' use a suitable small number here If pFtLayer.FeatureClass.FeatureCount(pSpatFlt) = 2 Then pLikelyPC.AddPoint(pBoundaryPC.Point(pPntCnt)) ' store this point to go back later ' add some code here for checking attributes ' if that's important to your network 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() ' now go through the likely locations and dissolve For pLikelyCnt As Integer = 0 To pLikelyPC.PointCount - 1 pTopOp = pLikelyPC.Point(pLikelyCnt) pSpatFlt.Geometry = pTopOp.Buffer(0.01) ' use a suitable small number here Dim pUpCur As IFeatureCursor = pFtLayer.FeatureClass.Update(pSpatFlt, False) ' must be false here Dim pFtInto As IFeature = pUpCur.NextFeature() ' the one that will get the shape Dim pFtRem As IFeature = pUpCur.NextFeature() ' the one that will be removed Dim pIntoPC As IPointCollection = pFtInto.ShapeCopy Dim pRemPC As IPointCollection = pFtRem.ShapeCopy ' there are 4 possibilites for line orientation: Dim pProxOp As IProximityOperator = pIntoPC.Point(0) ' start point Dim pFromFromDist = pProxOp.ReturnDistance(pRemPC.Point(0)) 'distance 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 ' simplest case just extend pOutPath.AddPointCollection(fJoinPC(pIntoPC, pRemPC)) pHasUpdated = True ElseIf pFromFromDist < 0.01 Then ' flip first then join pOutPath.AddPointCollection(fJoinPC(fFlipPC(pRemPC), 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 pOutPath.AddPointCollection(fJoinPC(pIntoPC, fFlipPC(pRemPC))) pHasUpdated = True End If If pHasUpdated Then pOutPolyLine.AddGeometry(pOutPath) Dim pOutShape As IGeometry = pOutPolyLine pOutShape.SpatialReference = pFtInto.ShapeCopy.SpatialReference ' update one and remove the other pFtInto.Shape = pOutShape pUpCur.UpdateFeature(pFtInto) pFtRem.Delete() End If Next pEd.StopOperation("Unsplit") End Sub 

Disclaimer: this is very old code, I haven't written anything in VB.net for a few years now and may or may not be the current working version... I had to dredge this one up off a backup.

2
  • Thanks for digging this out for me. Upon reviewing the code, I believe this is a viable solution. Will update when I can get it to run. Commented Jul 28, 2015 at 16:47
  • After some testing regarding editing sessions, I managed to get the bulk of the code to run almost as is in an Add-In. Many thanks Michael! Commented Jul 28, 2015 at 22:59
1

This is my practice of removing 'parasite' nodes.

Original network with links direction shown. Links labelled by FID: enter image description here

Decide where the sink is going to be and flip relevant link if necessary. In this case I picked No 2.

enter image description here

Next step I call 'create network'. Script takes selected link, traces all upstream and flips them on the go if necessary. In case shown it flips only 1 link, that is No 5.

Assign node types based on combination of in/out links - another script. For simple no-diversions network "Source" node is the one where inCount=0 and outCount=1, redundant node (transition) has inCount=1 and outCount=1:

enter image description here

Trace all links downstream from Source (script). The list of FIDs in this case [3,0,5,1,4,2]. Build a single polyline by merging geometries in this order (script).

I don't think that scripting free approach will do here at all.

2
  • Thanks for the thorough answer, though if I'm reading this correctly, it still requires user intervention. Also, as mentioned my comment/response, the geometric network does not have sources or sinks. Commented Jul 23, 2015 at 22:21
  • Well, make them. My original network didn't have them either. Or to be more precise it had 2 sinks, 2 sources, 1 diversion and 2 transit nodes. Commented Jul 23, 2015 at 23:21

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.