points-index.go
func (points *PointsIndex) KNearest(point Point, k int, maxDistance Meters, accept func(p Point) bool) []Point {
	nearbyPoints := make([]Point, 0)
	pointEntry := points.index.GetEntryAt(point).(set)
	nearbyPoints = append(nearbyPoints, getPoints([]interface{}{pointEntry}, accept)...)

	totalCount := 0
	idx := cellOf(point, points.index.resolution)
	// Explicitely assign a greater max distance so that we definitely return enough points
	// and make sure it searches at least one square away.
	coarseMaxDistance := math.Max(float64(maxDistance)*2.0, float64(points.index.resolution)*2.0+0.01)

	for d := 1; float64(d)*float64(points.index.resolution) <= coarseMaxDistance; d++ {
		oldCount := len(nearbyPoints)

		nearbyPoints = getPointsAppend(nearbyPoints, points.index.get(idx.x-d, idx.x+d, idx.y+d, idx.y+d), accept)
		nearbyPoints = getPointsAppend(nearbyPoints, points.index.get(idx.x-d, idx.x+d, idx.y-d, idx.y-d), accept)
		nearbyPoints = getPointsAppend(nearbyPoints, points.index.get(idx.x-d, idx.x-d, idx.y-d+1, idx.y+d-1), accept)
		nearbyPoints = getPointsAppend(nearbyPoints, points.index.get(idx.x+d, idx.x+d, idx.y-d+1, idx.y+d-1), accept)

		totalCount += len(nearbyPoints) - oldCount

		if totalCount > k {
			break
		}
	}

	sortedPoints := &sortedPoints{nearbyPoints, point}
	sort.Sort(sortedPoints)

	k = min(k, len(sortedPoints.points))

	// filter points which longer than maxDistance away from point.
	for i, nearbyPoint := range sortedPoints.points {
		if Distance(point, nearbyPoint) > maxDistance || i == k {
			k = i
			break
		}
	}

	return sortedPoints.points[0:k]
}
func (points *PointsIndex) KNearest(point Point, k int, maxDistance Meters, accept func(p Point) bool) []Point {
	nearbyPoints := make([]Point, 0)
	pointEntry := points.index.GetEntryAt(point).(set)
	nearbyPoints = append(nearbyPoints, getPoints([]interface{}{pointEntry}, accept)...)

	totalCount := 0
	idx := cellOf(point, points.index.resolution)
	// Explicitely assign a greater max distance so that we definitely return enough points
	// and make sure it searches at least one square away.
	coarseMaxDistance := math.Max(float64(maxDistance)*2.0, float64(points.index.resolution)*2.0+0.01)

	for d := 1; float64(d)*float64(points.index.resolution) <= coarseMaxDistance; d++ {
		oldCount := len(nearbyPoints)

		nearbyPoints = getPointsAppend(nearbyPoints, points.index.get(idx.x-d, idx.x+d, idx.y+d, idx.y+d), accept)
		nearbyPoints = getPointsAppend(nearbyPoints, points.index.get(idx.x-d, idx.x+d, idx.y-d, idx.y-d), accept)
		nearbyPoints = getPointsAppend(nearbyPoints, points.index.get(idx.x-d, idx.x-d, idx.y-d+1, idx.y+d-1), accept)
		nearbyPoints = getPointsAppend(nearbyPoints, points.index.get(idx.x+d, idx.x+d, idx.y-d+1, idx.y+d-1), accept)

		totalCount += len(nearbyPoints) - oldCount

		if totalCount > k {
			break
		}
	}

	sortedPoints := &sortedPoints{nearbyPoints, point}
	sort.Sort(sortedPoints)

	k = min(k, len(sortedPoints.points))

	// filter points which longer than maxDistance away from point.
	for i, nearbyPoint := range sortedPoints.points {
		if Distance(point, nearbyPoint) > maxDistance || i == k {
			k = i
			break
		}
	}

	return sortedPoints.points[0:k]
}
// KNearest returns the k nearest points near point within maxDistance that match the accept criteria.