A Spatial Prefix Tree, or Trie, which decomposes shapes into prefixed strings at variable lengths corresponding to variable precision. Each string corresponds to a spatial region. Implementations of this class should be thread-safe and immutable once initialized.
示例#1
0
        public virtual void TestBadPrefixTreePrune()
        {

            trie = new QuadPrefixTree(ctx, 12);
            TermQueryPrefixTreeStrategy strategy = new TermQueryPrefixTreeStrategy(trie, "geo");
            Document doc = new Document();
            doc.Add(new TextField("id", "1", Field.Store.YES));

            IShape area = ctx.MakeRectangle(-122.82, -122.78, 48.54, 48.56);

            Field[] fields = strategy.CreateIndexableFields(area, 0.025);
            foreach (Field field in fields)
            {
                doc.Add(field);
            }
            AddDocument(doc);

            IPoint upperleft = ctx.MakePoint(-122.88, 48.54);
            IPoint lowerright = ctx.MakePoint(-122.82, 48.62);

            Query query = strategy.MakeQuery(new SpatialArgs(SpatialOperation.Intersects, ctx.MakeRectangle(upperleft, lowerright)));

            Commit();

            TopDocs search = indexSearcher.Search(query, 10);
            ScoreDoc[] scoreDocs = search.ScoreDocs;
            foreach (ScoreDoc scoreDoc in scoreDocs)
            {
                Console.WriteLine(indexSearcher.Doc(scoreDoc.Doc));
            }

            assertEquals(1, search.TotalHits);
        }
示例#2
0
        public virtual void TestCellTraverse()
        {
            trie = new GeohashPrefixTree(ctx, 4);

            Cell prevC = null;
            Cell c     = trie.WorldCell;

            assertEquals(0, c.Level);
            assertEquals(ctx.WorldBounds, c.Shape);
            while (c.Level < trie.MaxLevels)
            {
                prevC = c;

                var iter = c.GetSubCells().GetEnumerator();
                iter.MoveNext();
                c = iter.Current;
                //c = c.GetSubCells().GetEnumerator().next();//TODO random which one?

                assertEquals(prevC.Level + 1, c.Level);
                IRectangle prevNShape = (IRectangle)prevC.Shape;
                IShape     s          = c.Shape;
                IRectangle sbox       = s.BoundingBox;
                assertTrue(prevNShape.Width > sbox.Width);
                assertTrue(prevNShape.Height > sbox.Height);
            }
        }
示例#3
0
        public virtual void TestBadPrefixTreePrune()
        {
            trie = new QuadPrefixTree(ctx, 12);
            TermQueryPrefixTreeStrategy strategy = new TermQueryPrefixTreeStrategy(trie, "geo");
            Document doc = new Document();

            doc.Add(new TextField("id", "1", Field.Store.YES));

            IShape area = ctx.MakeRectangle(-122.82, -122.78, 48.54, 48.56);

            Field[] fields = strategy.CreateIndexableFields(area, 0.025);
            foreach (Field field in fields)
            {
                doc.Add(field);
            }
            AddDocument(doc);

            IPoint upperleft  = ctx.MakePoint(-122.88, 48.54);
            IPoint lowerright = ctx.MakePoint(-122.82, 48.62);

            Query query = strategy.MakeQuery(new SpatialArgs(SpatialOperation.Intersects, ctx.MakeRectangle(upperleft, lowerright)));

            Commit();

            TopDocs search = indexSearcher.Search(query, 10);

            ScoreDoc[] scoreDocs = search.ScoreDocs;
            foreach (ScoreDoc scoreDoc in scoreDocs)
            {
                Console.WriteLine(indexSearcher.Doc(scoreDoc.Doc));
            }

            assertEquals(1, search.TotalHits);
        }
示例#4
0
        public virtual void TestCellTraverse()
        {
            trie = new GeohashPrefixTree(ctx, 4);

            Cell prevC = null;
            Cell c = trie.WorldCell;
            assertEquals(0, c.Level);
            assertEquals(ctx.WorldBounds, c.Shape);
            while (c.Level < trie.MaxLevels)
            {
                prevC = c;

                var iter = c.GetSubCells().GetEnumerator();
                iter.MoveNext();
                c = iter.Current;
                //c = c.GetSubCells().GetEnumerator().next();//TODO random which one?

                assertEquals(prevC.Level + 1, c.Level);
                IRectangle prevNShape = (IRectangle)prevC.Shape;
                IShape s = c.Shape;
                IRectangle sbox = s.BoundingBox;
                assertTrue(prevNShape.Width > sbox.Width);
                assertTrue(prevNShape.Height > sbox.Height);
            }
        }
 public AbstractPrefixTreeFilter(IShape queryShape, string fieldName, SpatialPrefixTree grid, int detailLevel)
 {
     this.queryShape = queryShape;
     this.fieldName = fieldName;
     this.grid = grid;
     this.detailLevel = detailLevel;
 }
示例#6
0
        /// <summary>
        /// Initializes a new instance of <see cref="Cell"/> for the
        /// <paramref name="spatialPrefixTree"/> with the specified <paramref name="bytes"/>, <paramref name="offset"/> and <paramref name="length"/>.
        /// </summary>
        /// <param name="spatialPrefixTree">The <see cref="SpatialPrefixTree"/> this instance belongs to.</param>
        /// <param name="bytes">The representation of this <see cref="Cell"/>.</param>
        /// <param name="offset">The offset into <paramref name="bytes"/> to use.</param>
        /// <param name="length">The count of <paramref name="bytes"/> to use.</param>
        /// <exception cref="ArgumentNullException"><paramref name="spatialPrefixTree"/> or <paramref name="bytes"/> is <c>null</c>.</exception>
        protected Cell(SpatialPrefixTree spatialPrefixTree, byte[] bytes, int offset, int length)
        {
            // LUCENENET specific - set the outer instance here
            // because overrides of Shape may require it
            this.m_spatialPrefixTree = spatialPrefixTree ?? throw new ArgumentNullException(nameof(spatialPrefixTree));

            //ensure any lazy instantiation completes to make this threadsafe
            this.bytes = bytes ?? throw new ArgumentNullException(nameof(bytes));

            // LUCENENET specific - check that the offset and length are in bounds
            int len = bytes.Length;

            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }
            if (offset + length > len)
            {
                throw new ArgumentException($"{nameof(offset)} and {nameof(length)} must refer to a location within the array.");
            }

            b_off = offset;
            b_len = length;
            B_fixLeaf();
        }
 public IntersectsPrefixTreeFilter(IShape queryShape, string fieldName, 
                                   SpatialPrefixTree grid, int detailLevel,
                                   int prefixGridScanLevel, bool hasIndexedLeaves)
     : base(queryShape, fieldName, grid, detailLevel, prefixGridScanLevel)
 {
     this.hasIndexedLeaves = hasIndexedLeaves;
 }
 public AbstractPrefixTreeFilter(Shape queryShape, string
     fieldName, SpatialPrefixTree grid, int detailLevel)
 {
     //not in equals/hashCode since it's implied for a specific field
     this.queryShape = queryShape;
     this.fieldName = fieldName;
     this.grid = grid;
     this.detailLevel = detailLevel;
 }
		public RecursivePrefixTreeFilter(String fieldName, SpatialPrefixTree grid, Shape queryShape, int prefixGridScanLevel,
							 int detailLevel)
		{
			this.fieldName = fieldName;
			this.grid = grid;
			this.queryShape = queryShape;
			this.prefixGridScanLevel = Math.Max(1, Math.Min(prefixGridScanLevel, grid.GetMaxLevels() - 1));
			this.detailLevel = detailLevel;
			Debug.Assert(detailLevel <= grid.GetMaxLevels());
		}
示例#10
0
        protected Node(SpatialPrefixTree spatialPrefixTree, String token)
        {
            this.spatialPrefixTree = spatialPrefixTree;
            SetToken(token);

            if (GetLevel() == 0)
            {
                GetShape();                //ensure any lazy instantiation completes to make this threadsafe
            }
        }
示例#11
0
        protected internal Cell(SpatialPrefixTree outerInstance, byte[] bytes, int off, int len)
        {
            // LUCENENET specific - set the outer instance here
            // because overrides of Shape may require it
            this.m_outerInstance = outerInstance;

            //ensure any lazy instantiation completes to make this threadsafe
            this.bytes = bytes;
            b_off      = off;
            b_len      = len;
            B_fixLeaf();
        }
示例#12
0
        private readonly IShape bufferedQueryShape;//if null then the whole world

        /// <summary>
        /// See <see cref="AbstractVisitingPrefixTreeFilter.AbstractVisitingPrefixTreeFilter(IShape, string, SpatialPrefixTree, int, int)"/>.
        /// <c>queryBuffer</c> is the (minimum) distance beyond the query shape edge
        /// where non-matching documents are looked for so they can be excluded. If
        /// -1 is used then the whole world is examined (a good default for correctness).
        /// </summary>
        public WithinPrefixTreeFilter(IShape queryShape, string fieldName, SpatialPrefixTree grid, 
                                      int detailLevel, int prefixGridScanLevel, double queryBuffer)
            : base(queryShape, fieldName, grid, detailLevel, prefixGridScanLevel)
        {
            if (queryBuffer == -1)
            {
                bufferedQueryShape = null;
            }
            else
            {
                bufferedQueryShape = BufferShape(queryShape, queryBuffer);
            }
        }
 private void SetupQuadGrid(int maxLevels)
 {
     //non-geospatial makes this test a little easier (in gridSnap), and using boundary values 2^X raises
     // the prospect of edge conditions we want to test, plus makes for simpler numbers (no decimals).
     FakeSpatialContextFactory factory = new FakeSpatialContextFactory();
     factory.geo = false;
     factory.worldBounds = new Rectangle(0, 256, -128, 128, null);
     this.ctx = factory.NewSpatialContext();
     //A fairly shallow grid, and default 2.5% distErrPct
     if (maxLevels == -1)
         maxLevels = randomIntBetween(1, 8);//max 64k cells (4^8), also 256*256
     this.grid = new QuadPrefixTree(ctx, maxLevels);
     this.strategy = new RecursivePrefixTreeStrategy(grid, GetType().Name);
 }
        protected Node(SpatialPrefixTree spatialPrefixTree, String token)
        {
            this.spatialPrefixTree = spatialPrefixTree;
            this.token             = token;
            if (token.Length > 0 && token[token.Length - 1] == (char)LEAF_BYTE)
            {
                this.token = token.Substring(0, token.Length - 1);
                SetLeaf();
            }

            if (GetLevel() == 0)
            {
                GetShape();                //ensure any lazy instantiation completes to make this threadsafe
            }
        }
示例#15
0
        protected Cell(SpatialPrefixTree outerInstance, string token)
        {
            // LUCENENET specific - set the outer instance here
            // because overrides of Shape may require it
            this.m_outerInstance = outerInstance;

            //NOTE: must sort before letters & numbers
            //this is the only part of equality
            this.token = token;
            if (token.Length > 0 && token[token.Length - 1] == (char)LEAF_BYTE)
            {
                this.token = token.Substring(0, (token.Length - 1) - 0);
                SetLeaf();
            }
            if (Level == 0)
            {
                var _ = Shape;//ensure any lazy instantiation completes to make this threadsafe
            }
        }
 /// <summary>
 /// See
 /// <see cref="AbstractVisitingPrefixTreeFilter">AbstractVisitingPrefixTreeFilter.AbstractVisitingPrefixTreeFilter(Shape, string, Lucene.Net.Spatial.Prefix.Tree.SpatialPrefixTree, int, int)
 /// 	</see>
 /// .
 /// <code>queryBuffer</code>
 /// is the (minimum) distance beyond the query shape edge
 /// where non-matching documents are looked for so they can be excluded. If
 /// -1 is used then the whole world is examined (a good default for correctness).
 /// </summary>
 public WithinPrefixTreeFilter(Shape queryShape, string fieldName
     , SpatialPrefixTree grid, int detailLevel, int prefixGridScanLevel,
     double queryBuffer
     )
     : base(queryShape, fieldName, grid, detailLevel, prefixGridScanLevel)
 {
     //TODO LUCENE-4869: implement faster algorithm based on filtering out false-positives of a
     //  minimal query buffer by looking in a DocValues cache holding a representative
     //  point of each disjoint component of a document's shape(s).
     //if null then the whole world
     if (queryBuffer == -1)
     {
         bufferedQueryShape = null;
     }
     else
     {
         bufferedQueryShape = BufferShape(queryShape, queryBuffer);
     }
 }
示例#17
0
        /// <summary>
        /// Initializes a new instance of <see cref="Cell"/> for the
        /// <paramref name="spatialPrefixTree"/> with the specified <paramref name="token"/>.
        /// </summary>
        /// <param name="spatialPrefixTree">The <see cref="SpatialPrefixTree"/> this instance belongs to.</param>
        /// <param name="token">The string representation of this <see cref="Cell"/>.</param>
        /// <exception cref="ArgumentNullException"><paramref name="spatialPrefixTree"/> or <paramref name="token"/> is <c>null</c>.</exception>
        protected Cell(SpatialPrefixTree spatialPrefixTree, string token)
        {
            // LUCENENET specific - set the outer instance here
            // because overrides of Shape may require it
            // LUCENENET specific - added guard clauses
            this.m_spatialPrefixTree = spatialPrefixTree ?? throw new ArgumentNullException(nameof(spatialPrefixTree));

            //NOTE: must sort before letters & numbers
            //this is the only part of equality
            this.token = token ?? throw new ArgumentNullException(nameof(token));
            if (token.Length > 0 && token[token.Length - 1] == (char)LEAF_BYTE)
            {
                this.token = token.Substring(0, (token.Length - 1) - 0);
                SetLeaf();
            }
            if (Level == 0)
            {
                var _ = Shape;//ensure any lazy instantiation completes to make this threadsafe
            }
        }
 public RecursivePrefixTreeStrategy(SpatialPrefixTree grid, string fieldName)
     : base(grid, fieldName, true)
 {
     //simplify indexed cells
     prefixGridScanLevel = grid.MaxLevels - 4;
 }
示例#19
0
		  public override void SetUp()
		{
			base.SetUp();
			ctx = SpatialContext.GEO;
			trie = new GeohashPrefixTree(ctx, 4);
		}
		public RecursivePrefixTreeStrategyThatSupportsWithin(SpatialPrefixTree grid, string fieldName)
			: base(grid, fieldName)
		{
			prefixGridScanLevel = grid.GetMaxLevels() - 4;//TODO this default constant is dependent on the prefix grid size
		}
 public ContainsPrefixTreeFilter(Shape queryShape, string
     fieldName, SpatialPrefixTree grid, int detailLevel)
     : base(queryShape, fieldName, grid, detailLevel)
 {
 }
示例#22
0
        protected double distErrPct = SpatialArgs.DEFAULT_DISTERRPCT; // [ 0 TO 0.5 ]

        protected PrefixTreeStrategy(SpatialPrefixTree grid, String fieldName)
            : base(grid.GetSpatialContext(), fieldName)
        {
            this.grid = grid;
        }
 public TermQueryPrefixTreeStrategy(SpatialPrefixTree grid, string fieldName)
     : base(grid, fieldName, false)
 {
 }
示例#24
0
        protected internal double distErrPct = SpatialArgs.DEFAULT_DISTERRPCT;// [ 0 TO 0.5 ]

        public PrefixTreeStrategy(SpatialPrefixTree grid, string fieldName, bool simplifyIndexedCells)
            : base(grid.SpatialContext, fieldName)
        {
            this.grid = grid;
            this.simplifyIndexedCells = simplifyIndexedCells;
        }
 public virtual void SetupGeohashGrid(int maxLevels)
 {
     this.ctx = SpatialContext.GEO;
     //A fairly shallow grid, and default 2.5% distErrPct
     if (maxLevels == -1)
         maxLevels = randomIntBetween(1, 3);//max 16k cells (32^3)
     this.grid = new GeohashPrefixTree(ctx, maxLevels);
     this.strategy = new RecursivePrefixTreeStrategy(grid, GetType().Name);
 }
 public RecursivePrefixTreeStrategy(SpatialPrefixTree grid, string fieldName)
     : base(grid, fieldName, true) //simplify indexed cells
 {
     prefixGridScanLevel = grid.MaxLevels - 4;//TODO this default constant is dependent on the prefix grid size
 }