private void GenerateRandomDocs(Random rng, int numDocs) { SpatialContext ctx = _spatialStrategy.GetSpatialContext(); base.addDocumentsAndCommit(Enumerable.Range(1, numDocs) .Select(a => CreateRandomDoc(a, rng, ctx)).ToList()); }
private void RunTest(SpatialContext ctx, SpatialStrategy strategy, Func <SpatialArgs, Query> createQuery) { var analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30); using (var luceneDir = new RandomIdRAMDirectory()) { string id1 = 1.ToString(); string id2 = 2.ToString(); string id3 = 3.ToString(); string id4 = 4.ToString(); using (var indexer = new TestIndex(luceneDir, analyzer)) { indexer.DocumentWriting += (sender, args) => Indexer_DocumentWriting(args, ctx, strategy); indexer.IndexItems(new[] { ValueSet.FromObject(id1, "content", new { nodeName = "location 1", bodyText = "Zanzibar is in Africa", lat = -6.1357, lng = 39.3621 }), ValueSet.FromObject(id2, "content", new { nodeName = "location 2", bodyText = "In Canada there is a town called Sydney in Nova Scotia", lat = 46.1368, lng = -60.1942 }), ValueSet.FromObject(id3, "content", new { nodeName = "location 3", bodyText = "Sydney is the capital of NSW in Australia", lat = -33.8688, lng = 151.2093 }), ValueSet.FromObject(id4, "content", new { nodeName = "location 4", bodyText = "Somewhere unknown", lat = 50, lng = 50 }) }); DoSpatialSearch(ctx, strategy, indexer, SearchRadius, id3, createQuery, lat: -33, lng: 151); DoSpatialSearch(ctx, strategy, indexer, SearchRadius, id2, createQuery, lat: 46, lng: -60); DoSpatialSearch(ctx, strategy, indexer, SearchRadius, id1, createQuery, lat: -6, lng: 39); DoSpatialSearch(ctx, strategy, indexer, SearchRadius, id4, createQuery, lat: 50, lng: 50); } } }
/// <summary> /// Computes the distance given a shape and the <paramref name="distErrPct"/>. The /// algorithm is the fraction of the distance from the center of the query /// shape to its furthest bounding box corner. /// </summary> /// <param name="shape">Mandatory.</param> /// <param name="distErrPct">0 to 0.5</param> /// <param name="ctx">Mandatory</param> /// <returns>A distance (in degrees).</returns> public static double CalcDistanceFromErrPct(IShape shape, double distErrPct, SpatialContext ctx) { // LUCENENET: Added null guard clauses if (shape is null) { throw new ArgumentNullException(nameof(shape)); } if (ctx is null) { throw new ArgumentNullException(nameof(ctx)); } if (distErrPct < 0 || distErrPct > 0.5) { throw new ArgumentOutOfRangeException(nameof(distErrPct), $"distErrPct {distErrPct} must be between [0 to 0.5]", nameof(distErrPct));// LUCENENET specific - changed from IllegalArgumentException to ArgumentOutOfRangeException (.NET convention) } if (distErrPct == 0 || shape is IPoint) { return(0); } IRectangle bbox = shape.BoundingBox; //Compute the distance from the center to a corner. Because the distance // to a bottom corner vs a top corner can vary in a geospatial scenario, // take the closest one (greater precision). IPoint ctr = bbox.Center; double y = (ctr.Y >= 0 ? bbox.MaxY : bbox.MinY); double diagonalDist = ctx.DistanceCalculator.Distance(ctr, bbox.MaxX, y); return(diagonalDist * distErrPct); }
public void testNGramPrefixGridLosAngeles() { SpatialContext ctx = SpatialContext.GEO; TermQueryPrefixTreeStrategy prefixGridStrategy = new TermQueryPrefixTreeStrategy(new QuadPrefixTree(ctx), "geo"); Shape point = ctx.MakePoint(-118.243680, 34.052230); Document losAngeles = new Document(); losAngeles.Add(new Field("name", "Los Angeles", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS)); foreach (var indexableField in prefixGridStrategy.CreateIndexableFields(point)) { losAngeles.Add(indexableField); } losAngeles.Add(new Field(prefixGridStrategy.GetFieldName(), ctx.ToString(point), Field.Store.YES, Field.Index.NO)); addDocumentsAndCommit(new List <Document> { losAngeles }); // This won't work with simple spatial context... SpatialArgsParser spatialArgsParser = new SpatialArgsParser(); // TODO... use a non polygon query // SpatialArgs spatialArgs = spatialArgsParser.parse( // "Intersects(POLYGON((-127.00390625 39.8125,-112.765625 39.98828125,-111.53515625 31.375,-125.94921875 30.14453125,-127.00390625 39.8125)))", // new SimpleSpatialContext()); // Query query = prefixGridStrategy.makeQuery(spatialArgs, fieldInfo); // SearchResults searchResults = executeQuery(query, 1); // assertEquals(1, searchResults.numFound); }
/// <summary> /// WARNING: geoms is copied by reference. /// </summary> /// <param name="geoms"></param> /// <param name="ctx"></param> public MultiShape(IEnumerable <Shape> geoms, SpatialContext ctx) { if (!geoms.Any()) { throw new ArgumentException("must be given at least 1 shape", "geoms"); } this.geoms = geoms; //compute and cache bbox double minX = Double.PositiveInfinity; double minY = Double.PositiveInfinity; double maxX = Double.NegativeInfinity; double maxY = Double.NegativeInfinity; foreach (var geom in geoms) { Rectangle r = geom.GetBoundingBox(); minX = Math.Min(minX, r.GetMinX()); minY = Math.Min(minY, r.GetMinY()); maxX = Math.Max(maxX, r.GetMaxX()); maxY = Math.Max(maxY, r.GetMaxY()); } this.bbox = ctx.MakeRectangle(minX, maxX, minY, maxY); }
/// <summary> /// /// </summary> /// <param name="points">ordered control points. If empty then this shape is empty.</param> /// <param name="buf">Buffer >= 0</param> /// <param name="expandBufForLongitudeSkew"> /// See <see cref="BufferedLine.ExpandBufForLongitudeSkew(IPoint, IPoint, double)"/> /// If true then the buffer for each segment is computed. /// </param> /// <param name="ctx"></param> public BufferedLineString(IList <IPoint> points, double buf, bool expandBufForLongitudeSkew, SpatialContext ctx) { this.buf = buf; if (!points.Any()) { this.segments = ctx.MakeCollection(new List <IShape>()); } else { List <IShape> segments = new List <IShape>(points.Count - 1); IPoint prevPoint = null; foreach (IPoint point in points) { if (prevPoint != null) { double segBuf = buf; if (expandBufForLongitudeSkew) { //TODO this is faulty in that it over-buffers. See Issue#60. segBuf = BufferedLine.ExpandBufForLongitudeSkew(prevPoint, point, buf); } segments.Add(new BufferedLine(prevPoint, point, segBuf, ctx)); } prevPoint = point; } if (!segments.Any()) {//TODO throw exception instead? segments.Add(new BufferedLine(prevPoint, prevPoint, buf, ctx)); } this.segments = ctx.MakeCollection(segments); } }
/// <summary> /// /// </summary> /// <param name="docId"></param> /// <param name="rng"></param> /// <param name="ctx"></param> /// <param name="percentageWithSpatialFields">ensures that some documents are missing spatial fields. This forces the cache to use FixedBitSet rather than MatchAllBits or MatchNoBits</param> /// <returns></returns> private Document CreateRandomDoc(int docId, Random rng, SpatialContext ctx, double percentageWithSpatialFields) { var doc = new Document(); var idField = new NumericField("locationId", Field.Store.YES, true); idField.SetIntValue(docId); doc.Add(idField); if (rng.NextDouble() > percentageWithSpatialFields) { return(doc); } Point shape = ctx.MakePoint(DistanceUtils.NormLonDEG(rng.NextDouble() * 360.0), DistanceUtils.NormLatDEG(rng.NextDouble() * 180.0)); foreach (AbstractField field in _spatialStrategy.CreateIndexableFields(shape)) { doc.Add(field); } doc.Add(_spatialStrategy.CreateStoredField(shape)); return(doc); }
public QuadPrefixTree(SpatialContext ctx, Rectangle bounds, int maxLevels) : base(ctx, maxLevels) { //not really sure how big this should be // side // number xmin = bounds.GetMinX(); xmax = bounds.GetMaxX(); ymin = bounds.GetMinY(); ymax = bounds.GetMaxY(); levelW = new double[maxLevels]; levelH = new double[maxLevels]; levelS = new int[maxLevels]; levelN = new int[maxLevels]; gridW = xmax - xmin; gridH = ymax - ymin; xmid = xmin + gridW / 2.0; ymid = ymin + gridH / 2.0; levelW[0] = gridW / 2.0; levelH[0] = gridH / 2.0; levelS[0] = 2; levelN[0] = 4; for (int i = 1; i < levelW.Length; i++) { levelW[i] = levelW[i - 1] / 2.0; levelH[i] = levelH[i - 1] / 2.0; levelS[i] = levelS[i - 1] * 2; levelN[i] = levelN[i - 1] * 4; } }
public void TestSimpleRectangle(SpatialContext ctx) { base.ctx = ctx; double v = 2001 * (random.NextDouble() > 0.5 ? -1 : 1); Assert.Throws <InvalidShapeException>(() => ctx.MakeRectangle(v, 0, 0, 0)); Assert.Throws <InvalidShapeException>(() => ctx.MakeRectangle(0, v, 0, 0)); Assert.Throws <InvalidShapeException>(() => ctx.MakeRectangle(0, 0, v, 0)); Assert.Throws <InvalidShapeException>(() => ctx.MakeRectangle(0, 0, 0, v)); Assert.Throws <InvalidShapeException>(() => ctx.MakeRectangle(0, 0, 10, -10)); Assert.Throws <InvalidShapeException>(() => ctx.MakeRectangle(10, -10, 0, 0)); double[] minXs = new double[] { -1000, -360, -180, -20, 0, 20, 180, 1000 }; foreach (double minX in minXs) { double[] widths = new double[] { 0, 10, 180, 360, 400 }; foreach (double width in widths) { TestRectangle(minX, width, 0, 0); TestRectangle(minX, width, -10, 10); TestRectangle(minX, width, 5, 10); } } Rectangle r = ctx.MakeRectangle(0, 0, 0, 0); r.Reset(1, 2, 3, 4); Assert.Equal(ctx.MakeRectangle(1, 2, 3, 4), r); testRectIntersect(); }
private SpatialArgs GetArgs(int docId, int distanceInKms) { Document doc; int index = docId; //we may land at a document that has no spatial field. In which case we keep increasing the index until we find one that does have a spatial field. do { doc = base.indexSearcher.IndexReader.Document(index % indexSearcher.MaxDoc, null); index++; } while (doc.GetField(StrategyPrefix) == null); SpatialContext ctx = _spatialStrategy.GetSpatialContext(); string[] parts = doc.Get(StrategyPrefix, null) .Split(' '); Point pt = ctx.MakePoint(double.Parse(parts[0]), double.Parse(parts[1])); Circle circle = ctx.MakeCircle(pt, DistanceUtils.Dist2Degrees(distanceInKms, DistanceUtils.EARTH_MEAN_RADIUS_KM)); var args = new SpatialArgs(SpatialOperation.Intersects, circle); return(args); }
public void TestSimplePoint(SpatialContext ctx) { base.ctx = ctx; Assert.Throws <InvalidShapeException>(() => ctx.MakePoint(2001, 0)); Assert.Throws <InvalidShapeException>(() => ctx.MakePoint(0, -301)); Point pt = ctx.MakePoint(0, 0); String msg = pt.ToString(); //test equals & hashcode Point pt2 = ctx.MakePoint(0, 0); Assert.Equal(/*msg,*/ pt, pt2); Assert.Equal(/*msg,*/ pt.GetHashCode(), pt2.GetHashCode()); Assert.False(pt.HasArea(), msg); Assert.Equal(/*msg,*/ pt.GetCenter(), pt); Rectangle bbox = pt.GetBoundingBox(); Assert.False(bbox.HasArea(), msg); var center = bbox.GetCenter(); Assert.True(pt.Equals(center)); //Assert.Equal(/*msg,*/ pt, center); assertRelation(msg, SpatialRelation.CONTAINS, pt, pt2); assertRelation(msg, SpatialRelation.DISJOINT, pt, ctx.MakePoint(0, 1)); assertRelation(msg, SpatialRelation.DISJOINT, pt, ctx.MakePoint(1, 0)); assertRelation(msg, SpatialRelation.DISJOINT, pt, ctx.MakePoint(1, 1)); pt.Reset(1, 2); Assert.Equal(ctx.MakePoint(1, 2), pt); }
public void TestSimpleCircle(SpatialContext ctx) { base.ctx = ctx; double[] theXs = new double[] { -10, 0, 10 }; foreach (double x in theXs) { double[] theYs = new double[] { -20, 0, 20 }; foreach (double y in theYs) { TestCircle(x, y, 0); TestCircle(x, y, 5); } } testCircleReset(ctx); //INTERSECTION: //Start with some static tests that have shown to cause failures at some point: Assert.Equal( /*"getX not getY",*/ SpatialRelation.INTERSECTS, ctx.MakeCircle(107, -81, 147).Relate(ctx.MakeRectangle(92, 121, -89, 74))); TestCircleIntersect(); }
public void CalcDistanceFromErrPct() { SpatialContext ctx = SpatialContext.GEO; double DEP = 0.5;//distErrPct //the result is the diagonal distance from the center to the closest corner, // times distErrPct IShape superwide = ctx.MakeRectangle(-180, 180, 0, 0); //0 distErrPct means 0 distance always assertEquals(0, SpatialArgs.CalcDistanceFromErrPct(superwide, 0, ctx), 0); assertEquals(180 * DEP, SpatialArgs.CalcDistanceFromErrPct(superwide, DEP, ctx), 0); IShape supertall = ctx.MakeRectangle(0, 0, -90, 90); assertEquals(90 * DEP, SpatialArgs.CalcDistanceFromErrPct(supertall, DEP, ctx), 0); IShape upperhalf = ctx.MakeRectangle(-180, 180, 0, 90); assertEquals(45 * DEP, SpatialArgs.CalcDistanceFromErrPct(upperhalf, DEP, ctx), 0.0001); IShape midCircle = ctx.MakeCircle(0, 0, 45); assertEquals(60 * DEP, SpatialArgs.CalcDistanceFromErrPct(midCircle, DEP, ctx), 0.0001); }
private void DoSpatialSearch( SpatialContext ctx, SpatialStrategy strategy, TestIndex indexer, double searchRadius, string idToMatch, Func <SpatialArgs, Query> createQuery, int lat, int lng) { var searcher = (LuceneSearcher)indexer.GetSearcher(); var luceneSearcher = searcher.GetLuceneSearcher(); GetXYFromCoords(lat, lng, out var x, out var y); // Make a circle around the search point var args = new SpatialArgs( SpatialOperation.Intersects, ctx.MakeCircle(x, y, DistanceUtils.Dist2Degrees(searchRadius, DistanceUtils.EARTH_MEAN_RADIUS_KM))); var filter = strategy.MakeFilter(args); var query = createQuery(args); // TODO: It doesn't make a whole lot of sense to sort by score when searching on only geo-coords, // typically you would sort by closest distance // Which can be done, see https://github.com/apache/lucene-solr/blob/branch_4x/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialExample.java#L169 TopDocs docs = luceneSearcher.Search(query, filter, MaxResultDocs, new Sort(new SortField(null, SortField.SCORE))); AssertDocMatchedIds(luceneSearcher, docs, idToMatch); // TODO: We should make this possible and allow passing in a Lucene Filter // to the LuceneSearchQuery along with the Lucene Query, then we // don't need to manually perform the Lucene Search //var criteria = (LuceneSearchQuery)searcher.CreateQuery(); //criteria.LuceneQuery(q); //var results = criteria.Execute(); }
protected internal virtual void Init(IDictionary <string, string> args, SpatialContext ctx) { // LUCENENET specific - added guard clauses this.m_args = args ?? throw new ArgumentNullException(nameof(args)); this.m_ctx = ctx ?? throw new ArgumentNullException(nameof(ctx)); InitMaxLevels(); }
protected internal virtual void Init(IDictionary <string, string> args, SpatialContext ctx) { this.args = args; this.ctx = ctx; InitMaxLevels(); }
static void Main(string[] args) { const Version version = Lucene.Net.Util.Version.LUCENE_30; Directory dir = new RAMDirectory(); Analyzer analyzer = new StandardAnalyzer(version); var indexWriter = new IndexWriter(dir, analyzer, IndexWriter.MaxFieldLength.UNLIMITED); SpatialContext ctx = SpatialContext.GEO; // BBoxStrategy //var strategy = new BBoxStrategy(ctx, "spartial"); // Can only index and search by retangle // TermQueryPrefixTreeStrategy //SpatialPrefixTree grid = new GeohashPrefixTree(ctx, 8); //var strategy = new TermQueryPrefixTreeStrategy(grid, "spartial"); // Only supports SpatialOperation.Intersects // RecursivePrefixTreeStrategy SpatialPrefixTree grid = new GeohashPrefixTree(ctx, 8); var strategy = new RecursivePrefixTreeStrategy(grid, "spartial"); // PointVectorStrategy //var strategy = new PointVectorStrategy(ctx, "pointvector"); foreach (var doc in CreateDocuments(strategy)) { indexWriter.AddDocument(doc); } indexWriter.Commit(); indexWriter.Dispose(); var searcher = new IndexSearcher(dir, true); Point littleMermaid = ctx.MakePoint(12.599239, 55.692848); // PointVectorStrategy //TopDocs hits = DistanceQueryAndSort_PointVectorStrategy(searcher, strategy, littleMermaid); //TopDocs hits = DistanceFilter_PointVectorStrategy(searcher, strategy, littleMermaid); //TopDocs hits = DistranceScore_PointVectorStrategy(searcher, strategy, littleMermaid); // TermQueryPrefixTreeStrategy //TopDocs hits = DistanceFilter_TermQueryPrefixTreeStrategy(searcher, strategy, littleMermaid); // RecursivePrefixTreeStrategy TopDocs hits = DistanceFilter_RecursivePrefixTreeStrategy(searcher, strategy, littleMermaid); Console.WriteLine("Found {0} document(s) that matched query:", hits.TotalHits); foreach (ScoreDoc match in hits.ScoreDocs) { Document doc = searcher.Doc(match.Doc); Console.WriteLine("Matched {0} (score: {1})", doc.Get("id"), match.Score); } searcher.Dispose(); }
/// <summary> /// The factory is looked up via "prefixTree" in args, expecting "geohash" or "quad". /// If its neither of these, then "geohash" is chosen for a geo context, otherwise "quad" is chosen. /// </summary> /// <param name="args"></param> /// <param name="ctx"></param> /// <returns></returns> public static SpatialPrefixTree MakeSPT(Dictionary <String, String> args, SpatialContext ctx) { SpatialPrefixTreeFactory instance; String cname; if (!args.TryGetValue(PREFIX_TREE, out cname) || cname == null) { cname = ctx.IsGeo() ? "geohash" : "quad"; } if ("geohash".Equals(cname, StringComparison.OrdinalIgnoreCase)) { instance = new GeohashPrefixTree.Factory(); } else if ("quad".Equals(cname, StringComparison.OrdinalIgnoreCase)) { instance = new QuadPrefixTree.Factory(); } else { Type t = Type.GetType(cname); instance = (SpatialPrefixTreeFactory)Activator.CreateInstance(t); } instance.Init(args, ctx); return(instance.NewSPT()); }
//1m /// <summary>The factory is looked up via "prefixTree" in args, expecting "geohash" or "quad". /// </summary> /// <remarks> /// The factory is looked up via "prefixTree" in args, expecting "geohash" or "quad". /// If its neither of these, then "geohash" is chosen for a geo context, otherwise "quad" is chosen. /// </remarks> public static SpatialPrefixTree MakeSPT(IDictionary <string, string> args, SpatialContext ctx) { SpatialPrefixTreeFactory instance; string cname = args[PrefixTree]; if (cname == null) { cname = ctx.IsGeo() ? "geohash" : "quad"; } if ("geohash".Equals(cname, StringComparison.OrdinalIgnoreCase)) { instance = new GeohashPrefixTree.Factory(); } else { if ("quad".Equals(cname, StringComparison.OrdinalIgnoreCase)) { instance = new QuadPrefixTree.Factory(); } else { try { Type c = Type.GetType(cname); instance = (SpatialPrefixTreeFactory)System.Activator.CreateInstance(c); } catch (Exception e) { throw new Exception(string.Empty, e); } } } instance.Init(args, ctx); return(instance.NewSPT()); }
protected virtual Lucene.Net.Search.Query VisitWithinRadius(WithinRadiusNode node, LuceneQueryMapperState mappingState) { SpatialContext ctx = SpatialContext.GEO; var strategy = new PointVectorStrategy(ctx, Sitecore.ContentSearch.Spatial.Common.Constants.LocationFieldName); if (node.Latitude is double && node.Longitude is double && node.Radius is double) { var distance = DistanceUtils.Dist2Degrees((double)node.Radius, DistanceUtils.EARTH_MEAN_RADIUS_MI); Circle circle = ctx.MakeCircle((double)node.Longitude, (double)node.Latitude, distance); var spatialArgs = new SpatialArgs(SpatialOperation.Intersects, circle); var dq = strategy.MakeQuery(spatialArgs); DistanceReverseValueSource valueSource = new DistanceReverseValueSource(strategy, circle.GetCenter(), distance); ValueSourceFilter vsf = new ValueSourceFilter(new QueryWrapperFilter(dq), valueSource, 0, distance); var filteredSpatial = new FilteredQuery(new MatchAllDocsQuery(), vsf); Lucene.Net.Search.Query spatialRankingQuery = new FunctionQuery(valueSource); BooleanQuery bq = new BooleanQuery(); bq.Add(filteredSpatial, Occur.MUST); bq.Add(spatialRankingQuery, Occur.MUST); return(bq); } throw new NotSupportedException("Wrong parameters type, Radius, latitude and longitude must be of type double"); }
internal readonly int[] levelN; // number public QuadPrefixTree(SpatialContext ctx, IRectangle bounds, int maxLevels) : base(ctx, maxLevels) { xmin = bounds.MinX; xmax = bounds.MaxX; ymin = bounds.MinY; ymax = bounds.MaxY; levelW = new double[maxLevels]; levelH = new double[maxLevels]; levelS = new int[maxLevels]; levelN = new int[maxLevels]; gridW = xmax - xmin; gridH = ymax - ymin; this.xmid = xmin + gridW / 2.0; this.ymid = ymin + gridH / 2.0; levelW[0] = gridW / 2.0; levelH[0] = gridH / 2.0; levelS[0] = 2; levelN[0] = 4; for (int i = 1; i < levelW.Length; i++) { levelW[i] = levelW[i - 1] / 2.0; levelH[i] = levelH[i - 1] / 2.0; levelS[i] = levelS[i - 1] * 2; levelN[i] = levelN[i - 1] * 4; } }
//@ParametersFactory public static IList <Object[]> Parameters() { List <Object[]> ctorArgs = new List <object[]>(); SpatialContext ctx = SpatialContext.GEO; SpatialPrefixTree grid; SpatialStrategy strategy; grid = new GeohashPrefixTree(ctx, 12); strategy = new RecursivePrefixTreeStrategy(grid, "recursive_geohash"); ctorArgs.Add(new Object[] { new Param(strategy) }); grid = new QuadPrefixTree(ctx, 25); strategy = new RecursivePrefixTreeStrategy(grid, "recursive_quad"); ctorArgs.Add(new Object[] { new Param(strategy) }); grid = new GeohashPrefixTree(ctx, 12); strategy = new TermQueryPrefixTreeStrategy(grid, "termquery_geohash"); ctorArgs.Add(new Object[] { new Param(strategy) }); strategy = new PointVectorStrategy(ctx, "pointvector"); ctorArgs.Add(new Object[] { new Param(strategy) }); return(ctorArgs); }
public void CalcDistanceFromErrPct() { SpatialContext ctx = SpatialContext.Geo; double DEP = 0.5;//distErrPct //the result is the diagonal distance from the center to the closest corner, // times distErrPct IShape superwide = ctx.MakeRectangle(-180, 180, 0, 0); // LUCENENET specific: Added delta to the first 3 asserts because it is not a // valid expectation that they are exactly on the nose when dealing with floating point // types. And in .NET Core 2.0, the implementation has changed which now makes this test // fail without delta. //0 distErrPct means 0 distance always assertEquals(0, SpatialArgs.CalcDistanceFromErrPct(superwide, 0, ctx), 0.0001); assertEquals(180 * DEP, SpatialArgs.CalcDistanceFromErrPct(superwide, DEP, ctx), 0.0001); IShape supertall = ctx.MakeRectangle(0, 0, -90, 90); assertEquals(90 * DEP, SpatialArgs.CalcDistanceFromErrPct(supertall, DEP, ctx), 0.0001); IShape upperhalf = ctx.MakeRectangle(-180, 180, 0, 90); assertEquals(45 * DEP, SpatialArgs.CalcDistanceFromErrPct(upperhalf, DEP, ctx), 0.0001); IShape midCircle = ctx.MakeCircle(0, 0, 45); assertEquals(60 * DEP, SpatialArgs.CalcDistanceFromErrPct(midCircle, DEP, ctx), 0.0001); }
public virtual void TestNGramPrefixGridLosAngeles() { SpatialContext ctx = SpatialContext.GEO; TermQueryPrefixTreeStrategy prefixGridStrategy = new TermQueryPrefixTreeStrategy(new QuadPrefixTree(ctx), "geo"); Spatial4n.Core.Shapes.IShape point = ctx.MakePoint(-118.243680, 34.052230); Document losAngeles = new Document(); losAngeles.Add(new StringField("name", "Los Angeles", Field.Store.YES)); foreach (IndexableField field in prefixGridStrategy.CreateIndexableFields(point)) { losAngeles.Add(field); } losAngeles.Add(new StoredField(prefixGridStrategy.FieldName, point.toString()));//just for diagnostics addDocumentsAndCommit(Arrays.AsList(losAngeles)); // This won't work with simple spatial context... SpatialArgsParser spatialArgsParser = new SpatialArgsParser(); // TODO... use a non polygon query // SpatialArgs spatialArgs = spatialArgsParser.parse( // "Intersects(POLYGON((-127.00390625 39.8125,-112.765625 39.98828125,-111.53515625 31.375,-125.94921875 30.14453125,-127.00390625 39.8125)))", // new SimpleSpatialContext()); // Query query = prefixGridStrategy.makeQuery(spatialArgs, fieldInfo); // SearchResults searchResults = executeQuery(query, 1); // assertEquals(1, searchResults.numFound); }
public LuceneIndexManager( IClock clock, IOptions <ShellOptions> shellOptions, ShellSettings shellSettings, ILogger <LuceneIndexManager> logger, LuceneAnalyzerManager luceneAnalyzerManager, LuceneIndexSettingsService luceneIndexSettingsService ) { _clock = clock; _logger = logger; _rootPath = PathExtensions.Combine( shellOptions.Value.ShellsApplicationDataPath, shellOptions.Value.ShellsContainerName, shellSettings.Name, "Lucene"); Directory.CreateDirectory(_rootPath); _luceneAnalyzerManager = luceneAnalyzerManager; _luceneIndexSettingsService = luceneIndexSettingsService; // Typical geospatial context // These can also be constructed from SpatialContextFactory _ctx = SpatialContext.Geo; var maxLevels = 11; // Results in sub-meter precision for geohash // TODO demo lookup by detail distance // This can also be constructed from SpatialPrefixTreeFactory _grid = new GeohashPrefixTree(_ctx, maxLevels); }
public override void TearDown() { base.TearDown(); ctx = null; strategy = null; storeShape = true; }
protected void Init(SpatialContext ctx, Rectangle bounds, int maxLevels) { this.xmin = bounds.GetMinX(); this.xmax = bounds.GetMaxX(); this.ymin = bounds.GetMinY(); this.ymax = bounds.GetMaxY(); levelW = new double[maxLevels]; levelH = new double[maxLevels]; levelS = new int[maxLevels]; levelN = new int[maxLevels]; gridW = xmax - xmin; gridH = ymax - ymin; xmid = xmin + gridW / 2.0; ymid = ymin + gridH / 2.0; levelW[0] = gridW / 2.0; levelH[0] = gridH / 2.0; levelS[0] = 2; levelN[0] = 4; for (int i = 1; i < levelW.Length; i++) { levelW[i] = levelW[i - 1] / 2.0; levelH[i] = levelH[i - 1] / 2.0; levelS[i] = levelS[i - 1] * 2; levelN[i] = levelN[i - 1] * 4; } }
protected virtual Lucene.Net.Search.Query VisitWithinRadius(WithinRadiusNode node, LuceneQueryMapperState mappingState) { SpatialContext ctx = SpatialContext.GEO; var strategy = new PointVectorStrategy(ctx, Sitecore.ContentSearch.Spatial.Common.Constants.LocationFieldName); if (node.Latitude is double && node.Longitude is double && node.Radius is double) { var distance = DistanceUtils.Dist2Degrees((double)node.Radius, DistanceUtils.EARTH_MEAN_RADIUS_MI); Circle circle = ctx.MakeCircle((double)node.Longitude, (double)node.Latitude, distance); var spatialArgs = new SpatialArgs(SpatialOperation.IsWithin, circle); var dq = strategy.MakeQuery(spatialArgs); DistanceReverseValueSource valueSource = new DistanceReverseValueSource(strategy, circle.GetCenter(), distance); ValueSourceFilter vsf = new ValueSourceFilter(new QueryWrapperFilter(dq), valueSource, 0, distance); var filteredSpatial = new FilteredQuery(new MatchAllDocsQuery(), vsf); mappingState.FilterQuery = filteredSpatial; Lucene.Net.Search.Query spatialRankingQuery = new FunctionQuery(valueSource); Random r = new Random(DateTime.Now.Millisecond); var randomNumber = r.Next(10000101, 11000101); Lucene.Net.Search.Query dummyQuery = Lucene.Net.Search.NumericRangeQuery.NewIntRange("__smallcreateddate", randomNumber, Int32.Parse(DateTime.Now.ToString("yyyyMMdd")), true, true); BooleanQuery bq = new BooleanQuery(); bq.Add(filteredSpatial, Occur.MUST); bq.Add(spatialRankingQuery, Occur.MUST); bq.Add(dummyQuery, Occur.SHOULD); return(bq); } throw new NotSupportedException("Wrong parameters type, Radius, latitude and longitude must be of type double"); }
/// <summary>The factory is looked up via "prefixTree" in args, expecting "geohash" or "quad".</summary> /// <remarks> /// The factory is looked up via "prefixTree" in args, expecting "geohash" or "quad". /// If its neither of these, then "geohash" is chosen for a geo context, otherwise "quad" is chosen. /// </remarks> public static SpatialPrefixTree MakeSPT(IDictionary <string, string> args, SpatialContext ctx) { SpatialPrefixTreeFactory instance; string cname; if (!args.TryGetValue(PREFIX_TREE, out cname)) { cname = ctx.IsGeo ? "geohash" : "quad"; } if ("geohash".Equals(cname, StringComparison.OrdinalIgnoreCase)) { instance = new GeohashPrefixTree.Factory(); } else if ("quad".Equals(cname, StringComparison.OrdinalIgnoreCase)) { instance = new QuadPrefixTree.Factory(); } else { try { Type c = Type.GetType(cname); instance = (SpatialPrefixTreeFactory)Activator.CreateInstance(c); } catch (Exception e) { throw new ApplicationException(string.Empty, e); } } instance.Init(args, ctx); return(instance.NewSPT()); }
public virtual void TestSimpleCircle(SpatialContext ctx) { base.ctx = ctx; double[] theXs = new double[] { -10, 0, 10 }; foreach (double x in theXs) { double[] theYs = new double[] { -20, 0, 20 }; foreach (double y in theYs) { TestCircle(x, y, 0); TestCircle(x, y, 5); } } TestCircleReset(ctx); //INTERSECTION: //Start with some static tests that have shown to cause failures at some point: Assert.Equal( /*"getX not getY",*/ SpatialRelation.INTERSECTS, ctx.MakeCircle(107, -81, 147).Relate(ctx.MakeRectangle(92, 121, -89, 74))); TestCircleIntersect(); Assert.Equal(ctx.MakeCircle(1, 2, 10), ctx.MakeCircle(1, 2, 6).GetBuffered(4, ctx)); TestEmptiness(ctx.MakeCircle(double.NaN, double.NaN, random.nextBoolean() ? 0 : double.NaN)); }
/// <summary> /// Gets the error distance that specifies how precise the query shape is. This /// looks at {@link #getDistErr()}, {@link #getDistErrPct()}, and {@code /// defaultDistErrPct}. /// </summary> /// <param name="ctx"></param> /// <param name="defaultDistErrPct">0 to 0.5</param> /// <returns>>= 0</returns> public double ResolveDistErr(SpatialContext ctx, double defaultDistErrPct) { if (DistErr != null) return DistErr.Value; double? distErrPct = (this.distErrPct ?? defaultDistErrPct); return CalcDistanceFromErrPct(Shape, distErrPct.Value, ctx); }
/// <summary> /// Computes the distance given a shape and the {@code distErrPct}. The /// algorithm is the fraction of the distance from the center of the query /// shape to its furthest bounding box corner. /// </summary> /// <param name="shape">Mandatory.</param> /// <param name="distErrPct">0 to 0.5</param> /// <param name="ctx">Mandatory</param> /// <returns>A distance (in degrees).</returns> public static double CalcDistanceFromErrPct(Shape shape, double distErrPct, SpatialContext ctx) { if (distErrPct < 0 || distErrPct > 0.5) { throw new ArgumentException("distErrPct " + distErrPct + " must be between [0 to 0.5]", "distErrPct"); } if (distErrPct == 0 || shape is Point) { return 0; } Rectangle bbox = shape.GetBoundingBox(); //The diagonal distance should be the same computed from any opposite corner, // and this is the longest distance that might be occurring within the shape. double diagonalDist = ctx.GetDistCalc().Distance( ctx.MakePoint(bbox.GetMinX(), bbox.GetMinY()), bbox.GetMaxX(), bbox.GetMaxY()); return diagonalDist * 0.5 * distErrPct; }