Я потратил некоторое время на просмотр исходного кода и думаю, что понимаю, что происходит не так.Во-первых, я сделал неверное предположение, что расстояния, вычисленные с помощью geocoder.us, будут такими же, как и то, что lucene внутренне рассчитывает как расстояния между точками.Значения близки, но не точны.Поэтому я переключился на вычисление расстояний между парами широта / долгота, вызвав команду lucene
double distance = DistanceUtils.getInstance().getDistanceMi(lat1,lon1,lat2,lon2);
Затем я копался в классе DistanceQueryBuilder http://grepcode.com/file/repo1.maven.org/maven2/org.apache.lucene/lucene-spatial/2.9.4/org/apache/lucene/spatial/tier/DistanceQueryBuilder.java?av=f,, в котором, как мне кажется, есть ошибка.
Он рассчитывает ограничивающий прямоугольник для извлечения декартовых ярусов следующим образом:
CartesianPolyFilterBuilder cpf = new CartesianPolyFilterBuilder(tierFieldPrefix);
Filter cartesianFilter = cpf.getBoundingArea(lat, lng, miles);
И, посмотрев в LLRect.createBox http://grepcode.com/file/repo1.maven.org/maven2/org.apache.lucene/lucene-spatial/2.9.4/org/apache/lucene/spatial/geometry/shape/LLRect.java#LLRect.createBox%28org.apache.lucene.spatial.geometry.LatLng%2Cdouble%2Cdouble%29, становится совершенно ясно, что третий параметрgetBoudningArea будет обрабатываться как полная ширина / высота ограничительной рамки.Таким образом, передача значения радиуса приводит к слишком маленькому ограничивающему прямоугольнику.
Исправление состояло в том, чтобы предоставить альтернативную версию DistanceQueryBuilder, которая делает это:
Filter cartesianFilter = cpf.getBoundingArea(lat,lng,miles*2);
, которая, кажется, работает.Я все еще убежден, что DistanceApproximation http://grepcode.com/file/repo1.maven.org/maven2/org.apache.lucene/lucene-spatial/2.9.4/org/apache/lucene/spatial/geometry/shape/DistanceApproximation.java#DistanceApproximation.getMilesPerLngDeg%28double%29 нарушен, потому что кажется, что следующие операции должны быть обратимыми, а они нет:
// similar to implementation of DistanceUtils.getBoundary():
double milesPerLng = DistanceApproximation.getMilesPerLngDeg(lat);
double milesPerLat = DistanceApproximation.getMilesperLatDeg();
double lngDelta = radius / milesPerLng;
double latDelta = radius / milesPerLat;
// Now it seems like this should be roughly true:
assertEquals(radius, DistanceUtils.getInstance().getDistanceMi(lat,lng,lat,lng+lngDelta));
assertEquals(radius, DistanceUtils.getInstance().getDistanceMi(lat,lng,lat+latDelta,lng));
Но это не так.Например, когда приведенный выше код задан как lat = 34, lng = -118 и radius = 25 (и вместо утверждения я просто печатаю результаты), я получаю:
Lng delta: 0.36142327178505024, dist: 20.725929003138496
Lat delta: 0.4359569489852007, dist: 30.155567734407825
Я предполагаючто код работает только потому, что декартовы ярусы, выбранные после выбора ограничивающего прямоугольника, приведут к области, несколько большей, чем ограничивающий прямоугольник.Но я не думаю, что это будет гарантировано.
Я надеюсь, что кто-то, кто больше знает об этом, может прокомментировать, потому что это всего лишь наблюдения после того, как копаться в коде во второй половине дня.Я заметил, что то, что выглядит как самый последний код для lucene пространственный, находится на googlecode по адресу: http://code.google.com/p/spatial-search-lucene/,, и кажется, что реализация значительно изменилась, но я не слишком углублялся в детали.