[GRASS-user] Criteria for v.clean tool=rmdangle

The rmdangle tool in v.clean usually behaves exactly the way I would expect it to, but occasionally it does not.

I have a vector generated from a raster using r.thin and r.to.vect that has numerous dangles. In the attached screenshot there are what appear to be two dangles with lengths of ~2 and ~5 ft. The two terminal polylines of what appears to be the core vector are 16 ft and 11 ft (27 ft combined). The pre-clean vector is gray, the cleaned vector is red, vertices are displayed as points derived using v.to.points.

After running v.clean tool=rmdangle thresh=30 the resulting vector (in red) removes one of the dangles plus what appears to be the two terminal polylines of the core vector, while leaving the smaller dangle attached. I tried running v.edit tool=merge or v.build.polylines before cleaning, but got the same results.

How does v.clean decide which line segment to remove as a dangle? Is there a way to force it to remove the line segment that leaves the longest possible remaining vector?

My workaround has been to run v.clean repeatedly with increasing thresholds, which I think removes the shortest line segment on each pass.

Thanks, -Dwight

(attachments)

v.clean_rmdangle.png

Dwight Needels wrote:

The rmdangle tool in v.clean usually behaves exactly the way I would
expect it to, but occasionally it does not.

I have a vector generated from a raster using r.thin and r.to.vect
that has numerous dangles. In the attached screenshot there are what
appear to be two dangles with lengths of ~2 and ~5 ft. The two
terminal polylines of what appears to be the core vector are 16 ft and
11 ft (27 ft combined). The pre-clean vector is gray, the cleaned
vector is red, vertices are displayed as points derived using
v.to.points.

After running v.clean tool=rmdangle thresh=30 the resulting vector (in
red) removes one of the dangles plus what appears to be the two
terminal polylines of the core vector, while leaving the smaller
dangle attached. I tried running v.edit tool=merge or
v.build.polylines before cleaning, but got the same results.

How does v.clean decide which line segment to remove as a dangle? Is
there a way to force it to remove the line segment that leaves the
longest possible remaining vector?

AFAIU, tool=rmdangle does not remove line segments, it only removes
whole lines. In GRASS terminology, a line has two end nodes, any number
of vertices and (n vertices - 1) segments. In your case, it may be
necessary to snap lines first, then break lines at intersections, then
remove dangles. Something like v.clean tool=snap,break,rmdangle
thresh=X,0,X.

v.build.polylines would rather prevent tool=rmdangle to find anything to
remove.

My workaround has been to run v.clean repeatedly with increasing
thresholds, which I think removes the shortest line segment on each pass.

As above, tool=rmdangle shouldn't remove line segments, only complete lines.

BTW, have you tried r.to.vect on the original GPS tracks, then
v.generalize, instead of r.buffer/r.grow/r.thin?

Markus M

On Jun 14, 2009, at 3:00 AM, Markus GRASS wrote:

Dwight Needels wrote:

The rmdangle tool in v.clean usually behaves exactly the way I would
expect it to, but occasionally it does not.

I have a vector generated from a raster using r.thin and r.to.vect
that has numerous dangles. In the attached screenshot there are what
appear to be two dangles with lengths of ~2 and ~5 ft. The two
terminal polylines of what appears to be the core vector are 16 ft and
11 ft (27 ft combined). The pre-clean vector is gray, the cleaned
vector is red, vertices are displayed as points derived using
v.to.points.

After running v.clean tool=rmdangle thresh=30 the resulting vector (in
red) removes one of the dangles plus what appears to be the two
terminal polylines of the core vector, while leaving the smaller
dangle attached. I tried running v.edit tool=merge or
v.build.polylines before cleaning, but got the same results.

How does v.clean decide which line segment to remove as a dangle? Is
there a way to force it to remove the line segment that leaves the
longest possible remaining vector?

AFAIU, tool=rmdangle does not remove line segments, it only removes
whole lines. In GRASS terminology, a line has two end nodes, any number
of vertices and (n vertices - 1) segments. In your case, it may be
necessary to snap lines first, then break lines at intersections, then
remove dangles. Something like v.clean tool=snap,break,rmdangle
thresh=X,0,X.

I see what you mean... it does remove entire lines. The way these vectors are generated (from r.thin/r.to.vect) seems to create vectors that don't need snapping or breaking, and the vectors look correct in v.digit (green nodes at intersections, red nodes at terminii). I tried your suggestion just in case with a 1 ft snap threshold followed by break and rmdangle, and got the same result.

v.build.polylines would rather prevent tool=rmdangle to find anything to
remove.

As far as I can tell, v.build.polylines leaves existing nodes at line intersections. At any rate, I get the same result whether or not I run this command first.

BTW, have you tried r.to.vect on the original GPS tracks, then
v.generalize, instead of r.buffer/r.grow/r.thin?

I'm not sure that I follow what your are suggesting. I left out the fact that the reason for going through r.buffer/r.thin is to average multiple GPS tracks, so r.to.vect insists on running r.thin first. If you are suggesting something else that I am missing, I would appreciate a clarification.

I am still confused about how v.clean chooses which line to remove as a dangle when there is a choice.

Thanks, -Dwight

Dwight Needels wrote:

Markus:

AFAIU, tool=rmdangle does not remove line segments, it only removes
whole lines. In GRASS terminology, a line has two end nodes, any number
of vertices and (n vertices - 1) segments. In your case, it may be
necessary to snap lines first, then break lines at intersections, then
remove dangles. Something like v.clean tool=snap,break,rmdangle
thresh=X,0,X.

I see what you mean... it does remove entire lines. The way these
vectors are generated (from r.thin/r.to.vect) seems to create vectors
that don't need snapping or breaking, and the vectors look correct in
v.digit (green nodes at intersections, red nodes at terminii). I tried
your suggestion just in case with a 1 ft snap threshold followed by
break and rmdangle, and got the same result.

Then there was nothing snapped? You can see what happened with v.clean
--verbose. Just to make sure I understand you correctly, have a look at
the attached image. I guess you want to remove the line segments
indicated by the arrows? Then the two lines need to be broken where the
red crosses are, and in order to break there with tool=break, snapping
may be needed first, at least for the left cross.

v.build.polylines would rather prevent tool=rmdangle to find anything to
remove.

As far as I can tell, v.build.polylines leaves existing nodes at line
intersections.

The lines connecting to these nodes were not merged, otherwise the node
should have disappeared and only a vertex should be in its place.

At any rate, I get the same result whether or not I run this command
first.

BTW, have you tried r.to.vect on the original GPS tracks, then
v.generalize, instead of r.buffer/r.grow/r.thin?

I'm not sure that I follow what your are suggesting.

Error in my suggestion, sorry! No r.to.vect needed, I thought about the
vector you got from v.in.ogr, using that directly as input for
v.generalize. Unless you have multiple GPS tracks for the same
track/hiking route, then v.to.rast->r.buffer->r.thin->r.to.vect seems fine.

I left out the fact that the reason for going through r.buffer/r.thin
is to average multiple GPS tracks, so r.to.vect insists on running
r.thin first. If you are suggesting something else that I am missing,
I would appreciate a clarification.

I am still confused about how v.clean chooses which line to remove as
a dangle when there is a choice.

A line is a dangle if at least one of its two nodes is not connected to
another line (dead end). A dangle is removed if it is smaller than
threshold, if threshold is < 0, all dangles are removed. I want to
update the v.clean manual when I get the time...

Markus M

(attachments)

v.clean_snap_break.png

On Jun 15, 2009, at 2:25 AM, Markus GRASS wrote:

Then there was nothing snapped? You can see what happened with v.clean
--verbose. Just to make sure I understand you correctly, have a look at
the attached image. I guess you want to remove the line segments
indicated by the arrows? Then the two lines need to be broken where the
red crosses are, and in order to break there with tool=break, snapping
may be needed first, at least for the left cross.

Correct; nothing was snapped or broken with v.clean tool=snap,break, and the error map was empty. Also correct that I expected (and wanted) the segments indicated by the arrows in your screenshot to be removed (D & E in my new screenshot).

My previous screenshots showed a tiny piece of a vector that I had processed to remove the jaggies before running v.clean. I repeated everything with a smaller portion of the vector for simplicity, and without the processing step to make sure it wasn't causing the problem (it wasn't). The first attached screenshot (v.clean_quirk) shows the overall issue. The green and yellow line is the raster generated by r.thin (res = 1 ft), the gray line is the vector created by r.to.vect, and the red line is the vector after cleaning with v.clean tool=snap,break,rmdangle threshold=0.9,0,30.

The original vector has 6 nodes, 73 vertices, and 5 lines, with lengths as shown in the screenshot (most of line C is beyond the right edge of the screenshot). These counts do not change after cleaning with snap, break or after running v.build.polylines.

The second screenshot (v.clean_v.digit) shows the original vector (before v.clean) in v.digit, which is also identical to the way it looks after v.clean tool=snap, break as well as after v.build.polylines.

A line is a dangle if at least one of its two nodes is not connected to
another line (dead end). A dangle is removed if it is smaller than
threshold, if threshold is < 0, all dangles are removed. I want to
update the v.clean manual when I get the time...

When the rmdangle tool runs into a pair of dangles at the end of a line where each is shorter than threshold (a "Y"), it removes one but leaves the other. This makes sense, because after the first one is removed the second one is no longer a dangle (it is now the terminal line segment).

The question is, how does it decide which one to remove ? I expected rmdangle to remove the shorter of the two choices in each instance. In my example, lines A, B, D & E are all shorter than the 30 ft threshold, and A, D & E are dangles. Removing the shorter dangle at each decision point would leave the longest below-threshold segments (A & B) while removing the two shorter ones (D & E). Instead, rmdangle leaves only the shortest segment (E) while removing the three longest ones (A, B & D), including one that isn't a dangle in the original vector.

How does v.clean tool=rmdangle decide which dangle to remove when there is a choice between two dangles shorter than the threshold?

Thanks, -Dwight

(attachments)

v.clean_quirk.png
v.clean_v.digit.png

Dwight Needels wrote:

When the rmdangle tool runs into a pair of dangles at the end of a
line where each is shorter than threshold (a "Y"), it removes one but
leaves the other. This makes sense, because after the first one is
removed the second one is no longer a dangle (it is now the terminal
line segment).

"Line segment" is confusing because it refers to a part of a line, e.g.
a part of line C or A. Line E may have only one segment, line C is
composed of several segments.

The question is, how does it decide which one to remove ?

First come fist serve. The rmdangle tool doesn't really decide, it goes
through all lines and if a line is a dangle and shorter than threshold,
it gets removed. The tool does not look at a pair of dangles at once as
far as I can tell.

I expected rmdangle to remove the shorter of the two choices in each
instance. In my example, lines A, B, D & E are all shorter than the 30
ft threshold, and A, D & E are dangles. Removing the shorter dangle at
each decision point would leave the longest below-threshold segments
(A & B) while removing the two shorter ones (D & E). Instead, rmdangle
leaves only the shortest segment (E) while removing the three longest
ones (A, B & D), including one that isn't a dangle in the original
vector.

Looks like A and D were removed first, then B qualified as a dangle and
was also removed, but why line E stayed in place is strange, it should
also be removed with that threshold.

How does v.clean tool=rmdangle decide which dangle to remove when
there is a choice between two dangles shorter than the threshold?

I think first come first serve, no decision or comparison between two
dangles happens. I may have to go to the source code again to make sure...

Markus M

On Jun 16, 2009, at 3:41 AM, Markus GRASS wrote:

Dwight Needels wrote:

When the rmdangle tool runs into a pair of dangles at the end of a
line where each is shorter than threshold (a "Y"), it removes one but
leaves the other. This makes sense, because after the first one is
removed the second one is no longer a dangle (it is now the terminal
line segment).

"Line segment" is confusing because it refers to a part of a line, e.g.
a part of line C or A. Line E may have only one segment, line C is
composed of several segments.

Agreed; but I keep using the term unconsciously to distinguish that portion of a line that falls between a pair of nodes. The term "line" is ambiguous because it is also used to refer to an entire polyline. For example,the Vector Introduction says "Note that all lines and boundaries can be polylines (with nodes in between)" rather than something like:

"line: a directed sequence of connected vertices with exactly two endpoints called nodes", and
"polyline: a non-branching series of connected lines or boundaries with a shared node at each connection"

For this discussion I will try to restrict myself to the above definitions, so that the term "line" will never refer to a polyline. This seems to be consistent with your usage. Would it be useful to make this distinction explicit on the Vector Introduction page?

The question is, how does it decide which one to remove ?

First come fist serve. The rmdangle tool doesn't really decide, it goes
through all lines and if a line is a dangle and shorter than threshold,
it gets removed. The tool does not look at a pair of dangles at once as
far as I can tell.

Looks like A and D were removed first, then B qualified as a dangle and
was also removed, but why line E stayed in place is strange, it should
also be removed with that threshold.

Ah... this is becoming clearer. Since rmdangle only deals with one line at a time, it never knows that there is a choice.

I think I may have finally figured out how a dangle is defined by v.clean tool=rmdangle, working backwards from the behavior. As you suggested, lines are processed in some order, probably by internal Id. The lines A - E in my previous example have Id and cat values of 1 - 5, respectively. I deleted line A and replaced it with a similar length line that now has the highest Id (6) instead of the lowest. Removing dangles left the replacement line A in place while deleting the shorter dangles (consistent with either an Id or a cat processing order).

As far as I can tell, a dangle must have at least one free (unshared) node, so that this tool will never delete a line in the middle of a polyline. The rmdangle tool marches through the Id values until it finds a line with a free node (a terminal line). Starting at the terminus, it adds up all line lengths until it comes to either the other terminus or a branch point. If the total length is less than the threshold, the set of lines is a dangle and the entire polyline up to the branch point is removed. Processing continues through all Id values.

In my test case:
Line A was removed first because the sum of the (1) line length from terminus to branch point ABD is less than threshold.
Line B was not removed because it does not have a free node (despite having a length below the threshold).
Line C was not removed because it is longer than the threshold (despite having a free node).
Lines D and B are removed together, because the sum of the line lengths from terminus to branch point BCE is less than threshold.
Line E is not removed, because the sum of the line lengths from terminus to the closest branch point/terminus is greater than the threshold (despite the length of Line E being below the threshold).

This also explains why v.clean tool=rmdangle threshold=-1 removes most, if not all, non-closed lines.

The current definition on the v.clean manual page is...

"rmdangle: removes dangles, threshold ignored if <0", without defining what a dangle is.

I propose that this be changed to something like...

"rmdangle: removes terminal lines or polylines with a length (to the nearest branch point/terminus) less than threshold, threshold ignored if <0"

It may be worth having a note called "What is a dangle?", but regardless it would be good to have a statement that says something like...

"The rmdangle tool processes dangles sequentially by internal Id, which may result in short lines with high Id values remaining after lines with lower Id values have been deleted from the nearest branch point."

Does any of this look incorrect? Can the processing by internal Id be confirmed?

Markus, thanks for all of your help on this. -Dwight

Dwight Needels wrote:

On Jun 16, 2009, at 3:41 AM, Markus GRASS wrote:

Dwight Needels wrote:

When the rmdangle tool runs into a pair of dangles at the end of a
line where each is shorter than threshold (a "Y"), it removes one but
leaves the other. This makes sense, because after the first one is
removed the second one is no longer a dangle (it is now the terminal
line segment).

"Line segment" is confusing because it refers to a part of a line, e.g.
a part of line C or A. Line E may have only one segment, line C is
composed of several segments.

Agreed; but I keep using the term unconsciously to distinguish that
portion of a line that falls between a pair of nodes. The term "line"
is ambiguous because it is also used to refer to an entire polyline.
For example,the Vector Introduction says "Note that all lines and
boundaries can be polylines (with nodes in between)"

Which is confusing, and I guess comes from some previous GRASS version.
Maybe what is rather meant is that all lines and boundaries can consist
of multiple segments and any number of vertices. The shapefile-like
polyline is not as such supported in GRASS vectors, with the exception
of boundaries that make up an area, but these "polylines" are stored
internally in topology for each area.

rather than something like:

"line: a directed sequence of connected vertices with exactly two
endpoints called nodes", and
"polyline: a non-branching series of connected lines or boundaries
with a shared node at each connection"

Polyline is not a GRASS vector object available to users, these are only
point,line,boundary,centroid,area,kernel,face.

For this discussion I will try to restrict myself to the above
definitions, so that the term "line" will never refer to a polyline.
This seems to be consistent with your usage. Would it be useful to
make this distinction explicit on the Vector Introduction page?

Definitively!

Line E is not removed, because the sum of the line lengths from
terminus to the closest branch point/terminus is greater than the
threshold (despite the length of Line E being below the threshold).

Maybe start with a lower threshold first, e.g. 5 ft to remove D and E
first, then increase the threshold for any other, longer dangles you
would like to remove

It may be worth having a note called "What is a dangle?", but
regardless it would be good to have a statement that says something
like...

"The rmdangle tool processes dangles sequentially by internal Id,
which may result in short lines with high Id values remaining after
lines with lower Id values have been deleted from the nearest branch
point."

Does any of this look incorrect? Can the processing by internal Id be
confirmed?

According to the source code, the rmdangle tool processes nodes by
internal id, not lines. As soon as it finds a node with only one line
connected, it looks at the length and the other end node. If only one
other line is connected at that other end node, the length of that one
is added. That continues until a node is found with more than two lines
of the desired type connecting to it. If the accumulated length is
smaller than threshold or threshold is < 0, all lines from the start
node up to that node are removed.

I have updated the manual in grass-6.4.svn, please have a look at it [1]
and give feedback if it is now better explained what the different tools
do. You can safe a local copy of the html file for nicer display. I did
not modify the tooltip description in the GUI, that's long enough already.

[1]
https://trac.osgeo.org/grass/browser/grass/branches/releasebranch_6_4/vector/v.clean/description.html

Markus M

On Jun 17, 2009, at 11:13 AM, Markus GRASS wrote:

Maybe start with a lower threshold first, e.g. 5 ft to remove D and E
first, then increase the threshold for any other, longer dangles you
would like to remove

This is exactly what I ended up doing, and it works great. The only question is how fine a distinction I want to make (do I really care if it removes a 25 ft dangle while leaving a 30 ft dangle or removes a 5 ft while leaving a 10 ft?). For my GPS tracks I ended up running v.clean tool=rmdangle three times with threshold of 10, 20 and 30 ft.

It may be worth having a note called "What is a dangle?", but
regardless it would be good to have a statement that says something
like...

"The rmdangle tool processes dangles sequentially by internal Id,
which may result in short lines with high Id values remaining after
lines with lower Id values have been deleted from the nearest branch
point."

Does any of this look incorrect? Can the processing by internal Id be
confirmed?

According to the source code, the rmdangle tool processes nodes by
internal id, not lines. As soon as it finds a node with only one line
connected, it looks at the length and the other end node. If only one
other line is connected at that other end node, the length of that one
is added. That continues until a node is found with more than two lines
of the desired type connecting to it. If the accumulated length is
smaller than threshold or threshold is < 0, all lines from the start
node up to that node are removed.

I have updated the manual in grass-6.4.svn, please have a look at it [1]
and give feedback if it is now better explained what the different tools
do. You can safe a local copy of the html file for nicer display. I did
not modify the tooltip description in the GUI, that's long enough already.

[1]
https://trac.osgeo.org/grass/browser/grass/branches/releasebranch_6_4/vector/v.clean/description.html

Markus M

I looked at the updated manual, and I like the description for the rmdangle tool (big improvement). There are several somewhat surprising (but predictable) behaviors that it might be useful to point out.

A) It sometimes removes lines that are not part of a dangle in the original vector (line B in my test case). Specifically, if two branch points are connected by a short line, this connecting line may end up deleted as part of a newly created dangle. This probably won't happen very often without a very large or negative thresh, because it requires a single node with 3 short lines attached.

B) It sometimes doesn't remove lines that are part of a dangle in the original vector (line E in my test case). Specifically, if the original vector has a node with two dangles shorter than threshold, one of them (the one with the larger internal Id) will not be deleted. This will only happen where there is a single node with 2 short lines attached (e.g. near a terminus).

C) It sometimes ends up with a vector that still has dangles, which require a second pass (and, conceivably even a third pass).

D) Use of a negative threshold removes a somewhat surprising number of lines, but in a useful way (leaving loops and lines connecting loops). I have attached two screenshots showing this with my averaged GPS trail data (gray is original vector, red is vector after v.clean tool-rmdangle thresh=-1).

All of these quirks have the same underlying cause... the rmdangle tool does not remove all dangles in the original vector, it sequentially removes dangles one at a time and doesn't go back to lines it has already processed. If run repeatedly, the final vector will have no dangles shorter than threshold, but this is different than removing all of the dangles in the original. Perhaps this underlying behavior can be communicated with something like the text below.

Existing text...
"Threshold gives maximum line/boundary length in map units, degrees for latlon. Dangles shorter than thresh will be removed. All dangles will be removed if thresh < 0."

Suggested text...
"Threshold gives maximum line/boundary length in map units, degrees for latlon. Dangles shorter than thresh are removed sequentially. Lines that are not either part of a loop or connecting two loops will be removed if thresh < 0."

And perhaps under Notes, something like...

"The lines removed by the rmdangle tool will sometimes not be the same as the dangles in the original vector. For example, if the original vector has a node with two dangles shorter than threshold, one of them (the one with the larger internal Id) will not be deleted, because it is no longer part of a dangle. If the tool is run repeatedly, the final vector will have no dangles shorter than thresh. To preferentially remove the shortest dangles, use a small thresh value in the first pass, and a larger value in the second pass."

Thanks, -Dwight

(attachments)

rmdangles_all_blue_blazed.png
rmdangles_all_unblazed.png

Dwight Needels wrote:

A) It sometimes removes lines that are not part of a dangle in the
original vector (line B in my test case). Specifically, if two branch
points are connected by a short line, this connecting line may end up
deleted as part of a newly created dangle. This probably won't happen
very often without a very large or negative thresh, because it
requires a single node with 3 short lines attached.

[...]

D) Use of a negative threshold removes a somewhat surprising number of
lines, but in a useful way (leaving loops and lines connecting loops).
I have attached two screenshots showing this with my averaged GPS
trail data (gray is original vector, red is vector after v.clean
tool-rmdangle thresh=-1).

Useful to remove incorrect boundaries, e.g. in v.in.ogr.

All of these quirks have the same underlying cause... the rmdangle
tool does not remove all dangles in the original vector, it
sequentially removes dangles one at a time and doesn't go back to
lines it has already processed. If run repeatedly, the final vector
will have no dangles shorter than threshold, but this is different
than removing all of the dangles in the original. Perhaps this
underlying behavior can be communicated with something like the text
below.

Existing text...
"Threshold gives maximum line/boundary length in map units, degrees
for latlon. Dangles shorter than thresh will be removed. All dangles
will be removed if thresh < 0."

Suggested text...
"Threshold gives maximum line/boundary length in map units, degrees
for latlon. Dangles shorter than thresh are removed sequentially.
Lines that are not either part of a loop or connecting two loops will
be removed if thresh < 0."

And perhaps under Notes, something like...

"The lines removed by the rmdangle tool will sometimes not be the same
as the dangles in the original vector. For example, if the original
vector has a node with two dangles shorter than threshold, one of them
(the one with the larger internal Id) will not be deleted, because it
is no longer part of a dangle.

but only if the remaining dangle and the next line(s, depending if the
other end node has only one more line connecting to it) are together
longer than thresh.

Just to illustrate that it can become a bit much to explain every
conceivable situation and quirk A) would then need to be included too.

If the tool is run repeatedly, the final vector will have no dangles
shorter than thresh.

Not so sure if repeated runs are necessary. One run should be enough to
have no dangles shorter than thresh in the output vector.

To preferentially remove the shortest dangles, use a small thresh
value in the first pass, and a larger value in the second pass."

Included in the manual with an example.

I have included some but not all of your suggestions because e.g. this
internal id thing is IMHO a bit too technical and not needed for running
the tool. Mentioning internal ids would suggest that they can be used by
the user which is the case for very few modules but not v.clean. The
internal id is nothing fixed, neither for lines nor for nodes, in
particular when using several cleaning tools in one go, internal ids are
constantly changed. Even nodes are a bit technical because they are no
regular vector object like point,line,boundary,centroid,area,face,kernel
but can be easily edited with the wxdigitizer or v.digit, so it would
hopefully be not too confusing to mention nodes.

Markus M

PS: I hope you have now the world's cleanest hiking trails:-)

On Jun 18, 2009, at 3:15 PM, Markus GRASS wrote:

If the tool is run repeatedly, the final vector will have no dangles
shorter than thresh.

Not so sure if repeated runs are necessary. One run should be enough to
have no dangles shorter than thresh in the output vector.

My mistake. I had what I thought was an example with a dangle remaining after v.clean tool=rmdangle thresh=-1, but I apparently never confirmed that it was removed by a second pass. It turned out to be an ultra-thin loop created when two pairs of lines were overlaid exactly on top of each other. I tried unsuccessfully to concoct a scenario that would expose a previously-processed line as a dangle, and agree that one run should be enough (thank goodness).

I have included some but not all of your suggestions because e.g. this
internal id thing is IMHO a bit too technical and not needed for running
the tool. Mentioning internal ids would suggest that they can be used by
the user which is the case for very few modules but not v.clean. The
internal id is nothing fixed, neither for lines nor for nodes, in
particular when using several cleaning tools in one go, internal ids are
constantly changed. Even nodes are a bit technical because they are no
regular vector object like point,line,boundary,centroid,area,face,kernel
but can be easily edited with the wxdigitizer or v.digit, so it would
hopefully be not too confusing to mention nodes.

Understood (and thanks!).

I think most of my personal confusion was centered around thinking that the tool removes the dangles found in the original vector, when in fact it just keeps going until no dangles are left. For example, my original prediction was that tool=rmdangle thresh=-1 would have pruned one layer of dangles from the outer tip of each branch (the original dangles), while leaving most of the core structure intact. In reality, it removes much more than the original dangles.

Below wording I started to suggest last time, but modified when I got concerned about multiple passes being required. Although I might not have understood the implications upon first reading, if I read it after running into the issues I did I think (hope?) this would have helped me figure it out much more quickly.

Suggested wording:
"Dangles shorter than thresh are removed sequentially until no dangles remain. No dangles will remain if thresh < 0."

PS: I hope you have now the world's cleanest hiking trails:-)

Thanks; I think I could have swept them clean with a broom in the time I have spent analyzing v.clean! However, this has been a very educational experience for me, and I appreciate all of your help.

Dwight Needels wrote:

On Jun 18, 2009, at 3:15 PM, Markus GRASS wrote:

"Dangles shorter than thresh are removed sequentially until no dangles remain. No dangles will remain if thresh < 0."

PS: I hope you have now the world's cleanest hiking trails:-)

Thanks; I think I could have swept them clean with a broom in the time I have spent analyzing v.clean! However, this has been a very educational experience for me, and I appreciate all of your help.
_______________________________________________

Would you care to summarize on this on the wiki?
Thanks,
Micha

Micha Silver wrote:

Dwight Needels wrote:

On Jun 18, 2009, at 3:15 PM, Markus GRASS wrote:

"Dangles shorter than thresh are removed sequentially until no
dangles remain. No dangles will remain if thresh < 0."

PS: I hope you have now the world's cleanest hiking trails:-)

Thanks; I think I could have swept them clean with a broom in the
time I have spent analyzing v.clean! However, this has been a very
educational experience for me, and I appreciate all of your help.
_______________________________________________

Would you care to summarize on this on the wiki?

The manual for v.clean has been updated in 6.4svn, 6.5, and 7, please
have a look.

Markus M