I've been working on a model using Mesa and mesa-geo and I think I found an off-by-one error in create_rtree. Fix is included in the following example, but I can also send you a pull request if you like.
from mesa_geo import GeoSpace, GeoAgent
from rtree import index
import numpy as np
### A point and an area on the map (taken randomly from an area I was working on).
geojson = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "Place 1"
},
"geometry": {
"type": "Point",
"coordinates": (77.51153557398285, 12.99263321577877)
}
},
{
"type": "Feature",
"properties": {
"name": "Polygon 1"
},
"geometry": {
"type": "Polygon",
"coordinates": (
((77.51123346718991, 12.992670785882310, 0.0),
(77.51152849328670, 12.992644874747185, 0.0),
(77.51163657102643, 12.992596162126380, 0.0),
(77.51141598069705, 12.992492901787061, 0.0),
(77.51107841065166, 12.992325112397564, 0.0),
(77.51093841043954, 12.992298472878362, 0.0),
(77.51100798363507, 12.992609158241951, 0.0),
(77.51115273788980, 12.992670631920141, 0.0),
(77.51111122952850, 12.992710069434820, 0.0),
(77.51101370887120, 12.992953447818099, 0.0),
(77.51130135960666, 12.993078282112991, 0.0),
(77.51138271453809, 12.993073876211817, 0.0),
(77.51127776250400, 12.992831987550323, 0.0),
(77.51136227169478, 12.992745508748830, 0.0),
(77.51123346718991, 12.992670785882310, 0.0)),
)
}
}
]
}
# Create a geospace and load the agents
grid = GeoSpace(crs='epsg:4326')
grid.create_agents_from_GeoJSON(geojson, agent=GeoAgent, model=None, unique_id="name")
# They're loaded successfully
print("Grid size: ", len(grid.agents))
print(grid.agents[0].unique_id, "Shape: ", grid.agents[0].shape)
print(grid.agents[1].unique_id, "Shape:", grid.agents[1].shape)
# Shapely shows the point is indeed in the area
print("\nShapely within/contains:")
print("Point within area:", grid.agents[0].shape.within(grid.agents[1].shape))
print("Area contains point:", grid.agents[1].shape.contains(grid.agents[0].shape))
# The area has intersections with the point, but the point does not with the area, strange
point_intersections = grid.get_rtree_intersections(grid.agents[0])
area_intersections = grid.get_rtree_intersections(grid.agents[1])
print("\nDefault rtree")
print("Point intersections", [a.unique_id for a in point_intersections])
print("Area intersections", [a.unique_id for a in area_intersections])
##### Fix is here
def create_rtree_fixed(self):
"""Create a new rtree index from agents shapes."""
shapes = []
i = 0
for i, agent in enumerate(self.agents):
agent.idx_id = i
shapes.append(agent.shape)
index_ids = range(i+1) # Off by one error
# Bulk load the shapes
def data_gen():
for index_id, shape in zip(index_ids, shapes):
yield (index_id, shape.bounds, shape)
self.idx = index.Index(data_gen())
self.idx.maxid = i
# Apply the new rtree
create_rtree_fixed(grid)
point_intersections = [a.unique_id for a in grid.get_rtree_intersections(grid.agents[0])]
area_intersections = [a.unique_id for a in grid.get_rtree_intersections(grid.agents[1])]
# Indeed the fix works
print("\nFixed rtree")
print("Point intersections", point_intersections)
print("Area intersections", area_intersections)
Grid size: 2
Place 1 Shape: POINT (77.51153557398285 12.99263321577877)
Polygon 1 Shape: POLYGON Z ((77.51123346718991 12.99267078588231 0, 77.5115284932867 12.99264487474719 0, 77.51163657102643 12.99259616212638 0, 77.51141598069705 12.99249290178706 0, 77.51107841065166 12.99232511239756 0, 77.51093841043954 12.99229847287836 0, 77.51100798363507 12.99260915824195 0, 77.5111527378898 12.99267063192014 0, 77.5111112295285 12.99271006943482 0, 77.5110137088712 12.9929534478181 0, 77.51130135960666 12.99307828211299 0, 77.51138271453809 12.99307387621182 0, 77.51127776250399 12.99283198755032 0, 77.51136227169478 12.99274550874883 0, 77.51123346718991 12.99267078588231 0))
Shapely within/contains:
Point within area: True
Area contains point: True
Default rtree
Point intersections []
Area intersections ['Place 1']
Fixed rtree
Point intersections ['Polygon 1']
Area intersections ['Place 1']