Open Viech opened 3 years ago
The following works fine (compare with original script):
print("\nLoading node and point coordinates...")
point_coords = []
with VectorTopo("TEST_WITH_POINTS", mode="r") as features:
node_coords = tuple(node.coords() for node in features.viter("nodes"))
for f in features:
if isinstance(f, Point):
point_coords.append(f.coords())
So the culprit appears to be VectorTopo.viter
.
I've worked around the issue as explained above but I'd like to share my suspicion that viter
should maybe respect an ID offset as currently ids
are defined within viter
starting at 1
unconditionally (source):
ids = (indx for indx in range(1, self.number_of(vtype) + 1))
I believe IDs are assigned per feature and not per feature type? This could mean that incorrect IDs are assigned here and some lookups would then access the data of lines instead of points. Since points are placed at line nodes and multiple lines can share a node, this could explain the duplicates.
I can take a look at this, could you please provide a vector map or perhaps steps to produce a vector map? I believe the ID is meant to start on 1, namely we will have [Point(1..200) and Node(1..200)], the offsets (at least from what I observe for the case of Node
) is handled at lower levels during instantiation. However, on the first glance, this is not the case for Point
, where we read from the entire map_info
, instead of just the features belonging to Point
, using c_read_line
. I suspect (like you have mentioned), the viter
for Node
is accurate but the viter
for Point
has interleaving Nodes
in between.
Under class Point
,
def __init__(self, x=0, y=0, z=None, **kargs):
super(Point, self).__init__(**kargs)
if self.id and self.c_mapinfo:
self.read() # Here, we do a read that uses c_read_line that reads from all lines instead of just Point
I think this can be reproduced with pretty much any line network that points are added to using v.net operation=nodes
.
For instance, you can copy the roads
map in the spearfish location to TEST
(run v.db.reconnect.all
to make it use sqlite) and then run the script in my opening post. You will see only a few node/point pairs with matching coordinates.
Describe the bug I am using
v.net
to generate points for a network so that I can assign attributes to them. When I load these points withVectorTopo
in PyGRASS (usingVectorTopo.viter("points")
), I find that some of their coordinates are wrong. More precisely, when I draw the points (using Python tools unrelated to GRASS), it appears that some points are missing while others are drawn multiple times in the same location. When I load the network's nodes instead of the points (usingVectorTopo.viter("nodes")
), the network is drawn just fine and all nodes are where I expect them.To Reproduce I made a Python script to reproduce the problem. I did not yet learn how to export the
TEST
vector map for you to reproduce locally, however the error should become apparent from the output of the script:This outputs the following (some lines cut):
Expected behavior In the above output, all comparison lines should read
==
and none should read!=
. All questions should be answered withTrue
.Note in particular that the script sorts the coordinates, so the problem is not that the points and nodes would be retrieved in different orders. Instead the returned sets of coordinates are not equal. It can be seen from the answers to the three questions above that some nodes have multiple points placed in their location while some nodes have no points placed in their location.
Screenshots I can add images of the drawings, if it helps.
System description
Linux 5.11.16-arch1-1
7.8.5-1
Additional context The
TEST
network was generated by me usingv.clean tool=break,rmdup
on a number of least cost paths (r.cost
andr.path
) patched together withv.patch
.