public void WalkPois(Vec3d centerPos, float radius, PoiMatcher callback = null) { int mincx = (int)(centerPos.X - radius) / chunksize; int mincz = (int)(centerPos.Z - radius) / chunksize; int maxcx = (int)(centerPos.X + radius) / chunksize; int maxcz = (int)(centerPos.Z + radius) / chunksize; float radiusSq = radius * radius; for (int cx = mincx; cx < maxcx; cx++) { for (int cz = mincz; cz < maxcz; cz++) { List <IPointOfInterest> pois = null; tmp.Set(cx, cz); PoisByChunkColumn.TryGetValue(tmp, out pois); if (pois == null) { continue; } for (int i = 0; i < pois.Count; i++) { Vec3d poipos = pois[i].Position; if (poipos.SquareDistanceTo(centerPos) > radiusSq) { continue; } callback(pois[i]); } } } }
public IPointOfInterest GetNearestPoi(Vec3d centerPos, float radius, PoiMatcher matcher = null) { int mincx = (int)(centerPos.X - radius) / chunksize; int mincz = (int)(centerPos.Z - radius) / chunksize; int maxcx = (int)(centerPos.X + radius) / chunksize; int maxcz = (int)(centerPos.Z + radius) / chunksize; float radiusSq = radius * radius; float nearestDistSq = 9999999; IPointOfInterest nearestPoi = null; for (int cx = mincx; cx <= maxcx; cx++) { for (int cz = mincz; cz <= maxcz; cz++) { List <IPointOfInterest> pois = null; tmp.Set(cx, cz); PoisByChunkColumn.TryGetValue(tmp, out pois); if (pois == null) { continue; } for (int i = 0; i < pois.Count; i++) { Vec3d poipos = pois[i].Position; float distSq = poipos.SquareDistanceTo(centerPos); if (distSq > radiusSq) { continue; } if (distSq < nearestDistSq && matcher(pois[i])) { nearestPoi = pois[i]; nearestDistSq = distSq; } } } } return(nearestPoi); }
public IPointOfInterest GetWeightedNearestPoi(Vec3d centerPos, float radius, PoiMatcher matcher = null) { int mincx = (int)(centerPos.X - radius) / chunksize; int mincz = (int)(centerPos.Z - radius) / chunksize; int maxcx = (int)(centerPos.X + radius) / chunksize; int maxcz = (int)(centerPos.Z + radius) / chunksize; float radiusSq = radius * radius; float nearestDistSq = 9999999; IPointOfInterest nearestPoi = null; for (int cx = mincx; cx <= maxcx; cx++) { double chunkDistX = 0; // x-distance from centerPos to nearest position in this chunk if (cx * chunksize > centerPos.X) { chunkDistX = cx * chunksize - centerPos.X; } else if ((cx + 1) * chunksize < centerPos.X) { chunkDistX = centerPos.X - (cx + 1) * chunksize; } for (int cz = mincz; cz <= maxcz; cz++) { double cdistZ = 0; // z-distance from centerPos to nearest position in this chunk if (cz * chunksize > centerPos.Z) { cdistZ = cz * chunksize - centerPos.Z; } else if ((cz + 1) * chunksize < centerPos.Z) { cdistZ = centerPos.Z - (cz + 1) * chunksize; } if (chunkDistX * chunkDistX + cdistZ * cdistZ > nearestDistSq) { continue; // skip the search if this whole chunk is further than the nearest found so far } List <IPointOfInterest> pois = null; tmp.Set(cx, cz); PoisByChunkColumn.TryGetValue(tmp, out pois); if (pois == null) { continue; } for (int i = 0; i < pois.Count; i++) { Vec3d poipos = pois[i].Position; float weight = pois[i] is IAnimalNest nest ? nest.DistanceWeighting : 1f; float distSq = poipos.SquareDistanceTo(centerPos) * weight; if (distSq > radiusSq) { continue; } if (distSq < nearestDistSq && matcher(pois[i])) { nearestPoi = pois[i]; nearestDistSq = distSq; } } } } return(nearestPoi); }