Пример #1
0
        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));
        }
Пример #2
0
        protected void TestCircle(double x, double y, double dist)
        {
            Circle c   = ctx.MakeCircle(x, y, dist);
            String msg = c.ToString();
            Circle c2  = ctx.MakeCircle(ctx.MakePoint(x, y), dist);

            Assert.Equal(c, c2);
            Assert.Equal(c.GetHashCode(), c2.GetHashCode());

            Assert.Equal(/*msg,*/ dist > 0, c.HasArea());
            double area = c.GetArea(ctx);

            Assert.True(/*msg,*/ c.HasArea() == (area > 0.0));
            Rectangle bbox = c.GetBoundingBox();

            Assert.Equal(/*msg,*/ dist > 0, bbox.GetArea(ctx) > 0);
            Assert.True(area <= bbox.GetArea(ctx));
            if (!ctx.IsGeo())
            {
                //if not geo then units of dist == units of x,y
                AssertEqualsRatio(msg, bbox.GetHeight(), dist * 2);
                AssertEqualsRatio(msg, bbox.GetWidth(), dist * 2);
            }
            assertRelation(msg, SpatialRelation.CONTAINS, c, c.GetCenter());
            assertRelation(msg, SpatialRelation.CONTAINS, bbox, c);
        }
Пример #3
0
        public static void testCircleReset(SpatialContext ctx)
        {
            Circle c  = ctx.MakeCircle(3, 4, 5);
            Circle c2 = ctx.MakeCircle(5, 6, 7);

            c2.Reset(3, 4, 5); // to c1
            Assert.Equal(c, c2);
            Assert.Equal(c.GetBoundingBox(), c2.GetBoundingBox());
        }
Пример #4
0
        public static void TestCircleReset(SpatialContext ctx)
        {
            ICircle c  = ctx.MakeCircle(3, 4, 5);
            ICircle c2 = ctx.MakeCircle(5, 6, 7);

            c2.Reset(3, 4, 5); // to c1
            Assert.Equal(c, c2);
            Assert.Equal(c.BoundingBox, c2.BoundingBox);
        }
Пример #5
0
        private void Search()
        {
            IndexReader   indexReader   = DirectoryReader.Open(directory);
            IndexSearcher indexSearcher = new IndexSearcher(indexReader);
            Sort          idSort        = new Sort(new SortField("id", SortFieldType.INT32));

            //--Filter by circle (<= distance from a point)
            {
                //Search with circle
                //note: SpatialArgs can be parsed from a string
                SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects,
                                                   ctx.MakeCircle(-80.0, 33.0, DistanceUtils.Dist2Degrees(200, DistanceUtils.EARTH_MEAN_RADIUS_KM)));
                Filter  filter = strategy.MakeFilter(args);
                TopDocs docs   = indexSearcher.Search(new MatchAllDocsQuery(), filter, 10, idSort);
                AssertDocMatchedIds(indexSearcher, docs, 2);
                //Now, lets get the distance for the 1st doc via computing from stored point value:
                // (this computation is usually not redundant)
                Document doc1    = indexSearcher.Doc(docs.ScoreDocs[0].Doc);
                String   doc1Str = doc1.GetField(strategy.FieldName).GetStringValue();
                //assume doc1Str is "x y" as written in newSampleDocument()
                int    spaceIdx    = doc1Str.IndexOf(' ');
                double x           = double.Parse(doc1Str.Substring(0, spaceIdx - 0), CultureInfo.InvariantCulture);
                double y           = double.Parse(doc1Str.Substring(spaceIdx + 1), CultureInfo.InvariantCulture);
                double doc1DistDEG = ctx.CalcDistance(args.Shape.Center, x, y);
                assertEquals(121.6d, DistanceUtils.Degrees2Dist(doc1DistDEG, DistanceUtils.EARTH_MEAN_RADIUS_KM), 0.1);
                //or more simply:
                assertEquals(121.6d, doc1DistDEG * DistanceUtils.DEG_TO_KM, 0.1);
            }
            //--Match all, order by distance ascending
            {
                IPoint      pt          = ctx.MakePoint(60, -50);
                ValueSource valueSource = strategy.MakeDistanceValueSource(pt, DistanceUtils.DEG_TO_KM);    //the distance (in km)
                Sort        distSort    = new Sort(valueSource.GetSortField(false)).Rewrite(indexSearcher); //false=asc dist
                TopDocs     docs        = indexSearcher.Search(new MatchAllDocsQuery(), 10, distSort);
                AssertDocMatchedIds(indexSearcher, docs, 4, 20, 2);
                //To get the distance, we could compute from stored values like earlier.
                // However in this example we sorted on it, and the distance will get
                // computed redundantly.  If the distance is only needed for the top-X
                // search results then that's not a big deal. Alternatively, try wrapping
                // the ValueSource with CachingDoubleValueSource then retrieve the value
                // from the ValueSource now. See LUCENE-4541 for an example.
            }
            //demo arg parsing
            {
                SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects,
                                                   ctx.MakeCircle(-80.0, 33.0, 1));
                SpatialArgs args2 = new SpatialArgsParser().Parse("Intersects(BUFFER(POINT(-80 33),1))", ctx);
                assertEquals(args.toString(), args2.toString());
            }

            indexReader.Dispose();
        }
Пример #6
0
        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);
        }
Пример #7
0
        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 IList <SearchItem> SearchByLocation(string queryString, double longitude, double latitude, double searchRadiusKm, int maxHits = 10)
        {
            IList <SearchItem> results;

            using (var searcher = new IndexSearcher(Directory, true))
                using (var analyser = new StandardAnalyzer(LuceneVersion))
                {
                    var distance   = DistanceUtils.Dist2Degrees(searchRadiusKm, DistanceUtils.EARTH_MEAN_RADIUS_KM);
                    var searchArea = _spatialContext.MakeCircle(longitude, latitude, distance);

                    var fields = new[] { Name };
                    var parser = new MultiFieldQueryParser(LuceneVersion, fields, analyser);
                    parser.DefaultOperator = QueryParser.Operator.OR; // Allow multiple terms.
                    var query = ParseQuery(queryString, parser);

                    var spatialArgs       = new SpatialArgs(SpatialOperation.Intersects, searchArea);
                    var spatialQuery      = _strategy.MakeQuery(spatialArgs);
                    var valueSource       = _strategy.MakeRecipDistanceValueSource(searchArea);
                    var valueSourceFilter = new ValueSourceFilter(new QueryWrapperFilter(spatialQuery), valueSource, 0, 1);

                    var filteredSpatial     = new FilteredQuery(query, valueSourceFilter);
                    var spatialRankingQuery = new FunctionQuery(valueSource);

                    BooleanQuery bq = new BooleanQuery();
                    bq.Add(filteredSpatial, Occur.MUST);
                    bq.Add(spatialRankingQuery, Occur.MUST);

                    var hits = searcher.Search(bq, maxHits).ScoreDocs;

                    results = MapResultsToSearchItems(hits, searcher);
                }

            return(results);
        }
Пример #9
0
        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);
        }
Пример #10
0
        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);
        }
Пример #11
0
        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();
        }
Пример #12
0
        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");
        }
        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");
        }
Пример #14
0
        public void testCircle(SpatialContext ctx)
        {
            Shape s = ctx.ReadShape("Circle(1.23 4.56 distance=7.89)");

            Assert.Equal(ctx.MakeCircle(1.23, 4.56, 7.89), s);
            Assert.Equal(s, WriteThenRead(s, ctx));
            Assert.Equal(s, ctx.ReadShape("CIRCLE( 4.56,1.23 d=7.89 )"));             // use lat,lon and use 'd' abbreviation
            Assert.True(s.HasArea());
        }
Пример #15
0
        public Filter ToFilter(SpatialContext spatialContext, SpatialPrefixTree tree)
        {
            var strategy = new RecursivePrefixTreeStrategy(tree, GeoFieldName);

            var spatialArgs = new SpatialArgs(SpatialOperation.Intersects,
                                              spatialContext.MakeCircle(X, Y, DistanceUtils.Dist2Degrees(this.Distance, DistanceUtils.EARTH_MEAN_RADIUS_KM)));

            return(strategy.MakeFilter(spatialArgs));
        }
Пример #16
0
 public void testCircleWithCriticalCulture(SpatialContext ctx)
 {
     using (new TemporaryCulture(new CultureInfo("de-DE")))
     {
         Shape s = ctx.ReadShape("Circle(1.23 4.56 distance=7.89)");
         Assert.Equal(ctx.MakeCircle(1.23, 4.56, 7.89), s);
         Assert.Equal(s, WriteThenRead(s, ctx));
         Assert.Equal(s, ctx.ReadShape("CIRCLE( 4.56,1.23 d=7.89 )")); // use lat,lon and use 'd' abbreviation
         Assert.True(s.HasArea());
     }
 }
Пример #17
0
        private QueryHelper <TModel> GeoFilter(Expression <Func <TModel, object> > exp, double longitude, double latitude, double distDEG)
        {
            string name = getName(exp.Body.ToString());
            //name = name.IndexOf('.') > -1 ? name.Substring(0, name.LastIndexOf('.')) : name;
            SpatialOperation op = SpatialOperation.Intersects;
            //SpatialStrategy strat = new PointVectorStrategy(ctx, name);
            int maxLevels          = 11;
            SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels);
            var strat = new RecursivePrefixTreeStrategy(grid, name);

            var point = ctx.MakePoint(longitude, latitude);
            var shape = ctx.MakeCircle(point, distDEG);
            var args  = new SpatialArgs(op, shape);

            filter = strat.MakeFilter(args);
            return(this);
        }
Пример #18
0
        private SpatialArgs GetArgs(int docId, int distanceInKms)
        {
            Document doc = base.indexSearcher.IndexReader.Document(docId, 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);
        }
Пример #19
0
        public void testArea()
        {
            double radius = DistanceUtils.EARTH_MEAN_RADIUS_KM * DistanceUtils.KM_TO_DEG;
            //surface of a sphere is 4 * pi * r^2
            double earthArea = 4 * Math.PI * radius * radius;

            Circle c = ctx.MakeCircle(random.Next(-180, 180), random.Next(-90, 90),
                                      180); //180 means whole earth

            CustomAssert.EqualWithDelta(earthArea, c.GetArea(ctx), 1.0);

            CustomAssert.EqualWithDelta(earthArea, ctx.GetWorldBounds().GetArea(ctx), 1.0);

            //now check half earth
            Circle cHalf = ctx.MakeCircle(c.GetCenter(), 90);

            CustomAssert.EqualWithDelta(earthArea / 2, cHalf.GetArea(ctx), 1.0);

            //circle with same radius at +20 lat with one at -20 lat should have same area as well as bbox with same area
            Circle c2 = ctx.MakeCircle(c.GetCenter(), 30);
            Circle c3 = ctx.MakeCircle(c.GetCenter().GetX(), 20, 30);

            CustomAssert.EqualWithDelta(c2.GetArea(ctx), c3.GetArea(ctx), 0.01);
            Circle c3Opposite = ctx.MakeCircle(c.GetCenter().GetX(), -20, 30);

            CustomAssert.EqualWithDelta(c3.GetArea(ctx), c3Opposite.GetArea(ctx), 0.01);
            CustomAssert.EqualWithDelta(c3.GetBoundingBox().GetArea(ctx), c3Opposite.GetBoundingBox().GetArea(ctx), 0.01);

            //small shapes near the equator should have similar areas to euclidean rectangle
            Rectangle smallRect = ctx.MakeRectangle(0, 1, 0, 1);

            CustomAssert.EqualWithDelta(1.0, smallRect.GetArea(null), 0.0);
            double smallDelta = smallRect.GetArea(null) - smallRect.GetArea(ctx);

            Assert.True(smallDelta > 0 && smallDelta < 0.0001);

            Circle smallCircle = ctx.MakeCircle(0, 0, 1);

            smallDelta = smallCircle.GetArea(null) - smallCircle.GetArea(ctx);
            Assert.True(smallDelta > 0 && smallDelta < 0.0001);

            //bigger, but still fairly similar
            //c2 = ctx.makeCircle(c.getCenter(), 30);
            double areaRatio = c2.GetArea(null) / c2.GetArea(ctx);

            Assert.True(areaRatio > 1 && areaRatio < 1.1);
        }
Пример #20
0
        static void Main(string[] args)
        {
            int maxLength = GeohashPrefixTree.GetMaxLevelsPossible();

            strategy = new RecursivePrefixTreeStrategy(
                new GeohashPrefixTree(context, maxLength));

            var dir    = new RAMDirectory();
            var writer = new IndexWriter(dir, new SimpleAnalyzer(), true,
                                         IndexWriter.MaxFieldLength.UNLIMITED);

            AddPoint(writer, "London", -81.233040, 42.983390);
            AddPoint(writer, "East New York", -73.882360, 40.666770);
            AddPoint(writer, "Manhattan", -73.966250, 40.783430);
            AddPoint(writer, "New York City", -74.005970, 40.714270);
            AddPoint(writer, "Oslo", 10.746090, 59.912730);
            AddPoint(writer, "Bergen", 5.324150, 60.392990);
            AddPoint(writer, "Washington, D. C.", -77.036370, 38.895110);

            writer.Close();

            // Origin point - Oslo Spektrum
            const double lat    = 59.9138688;
            const double lng    = 10.752245399999993;
            const double radius = 600;
            var          query  = strategy.MakeQuery(new SpatialArgs(SpatialOperation.IsWithin,
                                                                     context.MakeCircle(lng, lat, radius)), fieldInfo);

            var searcher = new IndexSearcher(dir);
            var results  = searcher.Search(query, null, 100);

            foreach (var topDoc in results.ScoreDocs)
            {
                var name = searcher.Doc(topDoc.doc).Get("Name");
                Console.WriteLine(name);
            }
            searcher.Close();
            dir.Close();
        }
Пример #21
0
        public virtual void TestSimplePoint(SpatialContext ctx)
        {
            base.ctx = ctx;

            Assert.Throws <InvalidShapeException>(() => ctx.MakePoint(2001, 0));
            Assert.Throws <InvalidShapeException>(() => ctx.MakePoint(0, -301));

            IPoint pt  = ctx.MakePoint(0, 0);
            string msg = pt.ToString();

            //test equals & hashcode
            IPoint 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.Center, pt);
            IRectangle bbox = pt.BoundingBox;

            Assert.False(bbox.HasArea, msg);

            var center = bbox.Center;

            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);

            Assert.Equal(ctx.MakeCircle(pt, 3), pt.GetBuffered(3, ctx));

            TestEmptiness(ctx.MakePoint(double.NaN, double.NaN));
        }
Пример #22
0
 public virtual ICircle ReadCircle(BinaryReader dataInput)
 {
     return(ctx.MakeCircle(ReadPoint(dataInput), ReadDim(dataInput)));
 }
Пример #23
0
        /// <summary>
        /// Reads the shape specification as defined in the class javadocs. If the first character is
        /// a letter but it doesn't complete out "Circle" or "CIRCLE" then this method returns null,
        /// offering the caller the opportunity to potentially try additional parsing.
        /// If the first character is not a letter then it's assumed to be a point or rectangle. If that
        /// doesn't work out then an <see cref="InvalidShapeException"/> is thrown.
        /// </summary>
        /// <param name="str"></param>
        /// <param name="ctx"></param>
        /// <returns></returns>
        public static IShape ReadShapeOrNull(string str, SpatialContext ctx)
        {
            if (str == null || str.Length == 0)
            {
                throw new InvalidShapeException(str);
            }

            string[] tokens;
            int      nextToken = 0;

            if (char.IsLetter(str[0]))
            {
                if (str.StartsWith("Circle(", StringComparison.Ordinal) || str.StartsWith("CIRCLE(", StringComparison.Ordinal))
                {
                    int idx = str.LastIndexOf(')');
                    if (idx > 0)
                    {
                        int    circleLength = "Circle(".Length;
                        string body         = str.Substring(circleLength, idx - circleLength);
                        tokens    = body.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        nextToken = 0;
                        string token = tokens[nextToken];
                        IPoint pt;
                        if (token.IndexOf(',') != -1)
                        {
                            pt = ReadLatCommaLonPoint(token, ctx);
                        }
                        else
                        {
                            double x = double.Parse(token, CultureInfo.InvariantCulture);
                            double y = double.Parse(token = tokens[++nextToken], CultureInfo.InvariantCulture);
                            pt = ctx.MakePoint(x, y);
                        }
                        double?d = null;

                        string arg = tokens[++nextToken];
                        idx = arg.IndexOf('=');
                        if (idx > 0)
                        {
                            string k = arg.Substring(0, idx - 0);
                            if (k.Equals("d", StringComparison.Ordinal) || k.Equals("distance", StringComparison.Ordinal))
                            {
                                d = double.Parse(arg.Substring(idx + 1), CultureInfo.InvariantCulture);
                            }
                            else
                            {
                                throw new InvalidShapeException("unknown arg: " + k + " :: " + str);
                            }
                        }
                        else
                        {
                            d = double.Parse(arg, CultureInfo.InvariantCulture);
                        }
                        // if we have additional tokens...
                        if (nextToken < tokens.Length - 1)
                        {
                            throw new InvalidShapeException("Extra arguments: " + tokens[++nextToken] /*st.nextToken()*/ + " :: " + str);
                        }
                        if (d == null)
                        {
                            throw new InvalidShapeException("Missing Distance: " + str);
                        }
                        //NOTE: we are assuming the units of 'd' is the same as that of the spatial context.
                        return(ctx.MakeCircle(pt, d.Value));
                    }
                }
                return(null);//caller has opportunity to try other parsing
            }

            if (str.IndexOf(',') != -1)
            {
                return(ReadLatCommaLonPoint(str, ctx));
            }
            tokens    = str.Split(' ');
            nextToken = 0;
            double p0 = double.Parse(tokens[nextToken], CultureInfo.InvariantCulture);
            double p1 = double.Parse(tokens[++nextToken], CultureInfo.InvariantCulture);

            // if we have additional tokens...
            if (nextToken < tokens.Length - 1)
            {
                double p2 = double.Parse(tokens[++nextToken], CultureInfo.InvariantCulture);
                double p3 = double.Parse(tokens[++nextToken], CultureInfo.InvariantCulture);
                // if we have additional tokens...
                if (nextToken < tokens.Length - 1)
                {
                    throw new InvalidShapeException("Only 4 numbers supported (rect) but found more: " + str);
                }
                return(ctx.MakeRectangle(p0, p2, p1, p3));
            }
            return(ctx.MakePoint(p0, p1));
        }
Пример #24
0
        /// <summary>
        /// Returns a new shape that is larger than shape by at distErr.
        /// </summary>
        protected virtual IShape BufferShape(IShape shape, double distErr)
        {
            //TODO move this generic code elsewhere?  Spatial4j?
            if (distErr <= 0)
            {
                throw new ArgumentException("distErr must be > 0");
            }
            SpatialContext ctx = m_grid.SpatialContext;

            if (shape is IPoint)
            {
                return(ctx.MakeCircle((IPoint)shape, distErr));
            }
            else if (shape is ICircle)
            {
                var    circle  = (ICircle)shape;
                double newDist = circle.Radius + distErr;
                if (ctx.IsGeo && newDist > 180)
                {
                    newDist = 180;
                }
                return(ctx.MakeCircle(circle.Center, newDist));
            }
            else
            {
                IRectangle bbox    = shape.BoundingBox;
                double     newMinX = bbox.MinX - distErr;
                double     newMaxX = bbox.MaxX + distErr;
                double     newMinY = bbox.MinY - distErr;
                double     newMaxY = bbox.MaxY + distErr;
                if (ctx.IsGeo)
                {
                    if (newMinY < -90)
                    {
                        newMinY = -90;
                    }
                    if (newMaxY > 90)
                    {
                        newMaxY = 90;
                    }
                    if (newMinY == -90 || newMaxY == 90 || bbox.Width + 2 * distErr > 360)
                    {
                        newMinX = -180;
                        newMaxX = 180;
                    }
                    else
                    {
                        newMinX = DistanceUtils.NormLonDEG(newMinX);
                        newMaxX = DistanceUtils.NormLonDEG(newMaxX);
                    }
                }
                else
                {
                    //restrict to world bounds
                    newMinX = Math.Max(newMinX, ctx.WorldBounds.MinX);
                    newMaxX = Math.Min(newMaxX, ctx.WorldBounds.MaxX);
                    newMinY = Math.Max(newMinY, ctx.WorldBounds.MinY);
                    newMaxY = Math.Min(newMaxY, ctx.WorldBounds.MaxY);
                }
                return(ctx.MakeRectangle(newMinX, newMaxX, newMinY, newMaxY));
            }
        }
Пример #25
0
 public virtual IShape GetBuffered(double distance, SpatialContext ctx)
 {
     return(ctx.MakeCircle(this, distance));
 }
Пример #26
0
 /// <summary>
 /// Make a spatial query
 /// </summary>
 /// <param name="lat"></param>
 /// <param name="lng"></param>
 /// <param name="radius">Radius, in miles</param>
 /// <returns></returns>
 public static Query MakeQuery(double lat, double lng, double radius)
 {
     return(strategy.MakeQuery(new SpatialArgs(SpatialOperation.IsWithin, RavenSpatialContext.MakeCircle(lng, lat, radius)), fieldInfo));
 }
Пример #27
0
        public virtual void TestGeoCircle(SpatialContext ctx)
        {
            base.ctx = ctx;

            Assert.Equal(string.Format("Circle(Pt(x={0:0.0},y={1:0.0}), d={2:0.0}° {3:0.00}km)", 10, 20, 30, 3335.85), ctx.MakeCircle(10, 20, 30).ToString());

            double v = 200 * (random.NextDouble() > 0.5 ? -1 : 1);

            Assert.Throws <InvalidShapeException>(() => ctx.MakeCircle(v, 0, 5));
            Assert.Throws <InvalidShapeException>(() => ctx.MakeCircle(0, v, 5));
            //Assert.Throws<InvalidShapeException>(() => ctx.MakeCircle(random.Next(-180, 180), random.Next(-90, 90), v));

            //--Start with some static tests that once failed:

            //Bug: numeric edge at pole, fails to init
            ctx.MakeCircle(110, -12, 90 + 12);

            //Bug: horizXAxis not in enclosing rectangle, assertion
            ctx.MakeCircle(-44, 16, 106);
            ctx.MakeCircle(-36, -76, 14);
            ctx.MakeCircle(107, 82, 172);

            // TODO need to update this test to be valid
            //{
            //    //Bug in which distance was being confused as being in the same coordinate system as x,y.
            //    double distDeltaToPole = 0.001;//1m
            //    double distDeltaToPoleDEG = ctx.getDistCalc().distanceToDegrees(distDeltaToPole);
            //    double dist = 1;//1km
            //    double distDEG = ctx.getDistCalc().distanceToDegrees(dist);
            //    Circle c = ctx.makeCircle(0, 90 - distDeltaToPoleDEG - distDEG, dist);
            //    Rectangle cBBox = c.getBoundingBox();
            //    Rectangle r = ctx.makeRect(cBBox.getMaxX() * 0.99, cBBox.getMaxX() + 1, c.getCenter().getY(), c.getCenter().getY());
            //    assertEquals(INTERSECTS, c.getBoundingBox().relate(r, ctx));
            //    assertEquals("dist != xy space", INTERSECTS, c.relate(r, ctx));//once failed here
            //}

            AssertEquals("bad proportion logic", SpatialRelation.INTERSECTS, ctx.MakeCircle(64, -70, 18).Relate(ctx.MakeRectangle(46, 116, -86, -62)));

            AssertEquals("Both touch pole", SpatialRelation.INTERSECTS, ctx.MakeCircle(-90, 30, 60).Relate(ctx.MakeRectangle(-24, -16, 14, 90)));

            AssertEquals("Spherical cap should contain enclosed band", SpatialRelation.CONTAINS,
                         ctx.MakeCircle(0, -90, 30).Relate(ctx.MakeRectangle(-180, 180, -90, -80)));

            AssertEquals("touches pole", SpatialRelation.INTERSECTS, ctx.MakeCircle(0, -88, 2).Relate(ctx.MakeRectangle(40, 60, -90, -86)));

            AssertEquals("wrong farthest opp corner", SpatialRelation.INTERSECTS, ctx.MakeCircle(92, 36, 46).Relate(ctx.MakeRectangle(134, 136, 32, 80)));

            AssertEquals("edge rounding issue 2", SpatialRelation.INTERSECTS, ctx.MakeCircle(84, -40, 136).Relate(ctx.MakeRectangle(-150, -80, 34, 84)));

            AssertEquals("edge rounding issue", SpatialRelation.CONTAINS, ctx.MakeCircle(0, 66, 156).Relate(ctx.MakePoint(0, -90)));

            AssertEquals("nudge back circle", SpatialRelation.CONTAINS, ctx.MakeCircle(-150, -90, 122).Relate(ctx.MakeRectangle(0, -132, 32, 32)));

            AssertEquals("wrong estimate", SpatialRelation.DISJOINT, ctx.MakeCircle(-166, 59, KmToDeg(5226.2)).Relate(ctx.MakeRectangle(36, 66, 23, 23)));

            AssertEquals("bad CONTAINS (dateline)", SpatialRelation.INTERSECTS, ctx.MakeCircle(56, -50, KmToDeg(12231.5)).Relate(ctx.MakeRectangle(108, 26, 39, 48)));

            AssertEquals("bad CONTAINS (backwrap2)", SpatialRelation.INTERSECTS,
                         ctx.MakeCircle(112, -3, 91).Relate(ctx.MakeRectangle(-163, 29, -38, 10)));

            AssertEquals("bad CONTAINS (r x-wrap)", SpatialRelation.INTERSECTS,
                         ctx.MakeCircle(-139, 47, 80).Relate(ctx.MakeRectangle(-180, 180, -3, 12)));

            AssertEquals("bad CONTAINS (pwrap)", SpatialRelation.INTERSECTS,
                         ctx.MakeCircle(-139, 47, 80).Relate(ctx.MakeRectangle(-180, 179, -3, 12)));

            AssertEquals("no-dist 1", SpatialRelation.WITHIN,
                         ctx.MakeCircle(135, 21, 0).Relate(ctx.MakeRectangle(-103, -154, -47, 52)));

            AssertEquals("bbox <= >= -90 bug", SpatialRelation.CONTAINS,
                         ctx.MakeCircle(-64, -84, 124).Relate(ctx.MakeRectangle(-96, 96, -10, -10)));

            //The horizontal axis line of a geo circle doesn't necessarily pass through c's ctr.
            AssertEquals("c's horiz axis doesn't pass through ctr", SpatialRelation.INTERSECTS,
                         ctx.MakeCircle(71, -44, 40).Relate(ctx.MakeRectangle(15, 27, -62, -34)));

            AssertEquals("pole boundary", SpatialRelation.INTERSECTS,
                         ctx.MakeCircle(-100, -12, 102).Relate(ctx.MakeRectangle(143, 175, 4, 32)));

            AssertEquals("full circle assert", SpatialRelation.CONTAINS,
                         ctx.MakeCircle(-64, 32, 180).Relate(ctx.MakeRectangle(47, 47, -14, 90)));

            //--Now proceed with systematic testing:
            AssertEquals(ctx.WorldBounds, ctx.MakeCircle(0, 0, 180).BoundingBox);
            //assertEquals(ctx.makeCircle(0,0,distToOpposeSide/2 - 500).getBoundingBox());

            double[] theXs = new double[] { -180, -45, 90 };
            foreach (double x in theXs)
            {
                double[] theYs = new double[] { -90, -45, 0, 45, 90 };
                foreach (double y in theYs)
                {
                    TestCircle(x, y, 0);
                    TestCircle(x, y, KmToDeg(500));
                    TestCircle(x, y, 90);
                    TestCircle(x, y, 180);
                }
            }

            TestCircleIntersect();
        }
Пример #28
0
 public virtual IShape GetBuffered(double distance, SpatialContext ctx)
 {
     return(ctx.MakeCircle(point, distance + radiusDEG));
 }
Пример #29
0
        /// <summary>Returns a new shape that is larger than shape by at distErr.</summary>
        /// <remarks>Returns a new shape that is larger than shape by at distErr.</remarks>
        protected internal virtual Shape BufferShape(Shape
                                                     shape, double distErr)
        {
            //TODO move this generic code elsewhere?  Spatial4j?
            if (distErr <= 0)
            {
                throw new ArgumentException("distErr must be > 0");
            }
            SpatialContext ctx = grid.SpatialContext;

            if (shape is Point)
            {
                return(ctx.MakeCircle((Point)shape, distErr));
            }
            else
            {
                if (shape is Circle)
                {
                    var    circle  = (Circle)shape;
                    double newDist = circle.GetRadius() + distErr;
                    if (ctx.IsGeo() && newDist > 180)
                    {
                        newDist = 180;
                    }
                    return(ctx.MakeCircle(circle.GetCenter(), newDist));
                }
                else
                {
                    Rectangle bbox    = shape.GetBoundingBox();
                    double    newMinX = bbox.GetMinX() - distErr;
                    double    newMaxX = bbox.GetMaxX() + distErr;
                    double    newMinY = bbox.GetMinY() - distErr;
                    double    newMaxY = bbox.GetMaxY() + distErr;
                    if (ctx.IsGeo())
                    {
                        if (newMinY < -90)
                        {
                            newMinY = -90;
                        }
                        if (newMaxY > 90)
                        {
                            newMaxY = 90;
                        }
                        if (newMinY == -90 || newMaxY == 90 || bbox.GetWidth() + 2 * distErr > 360)
                        {
                            newMinX = -180;
                            newMaxX = 180;
                        }
                        else
                        {
                            newMinX = DistanceUtils.NormLonDEG(newMinX);
                            newMaxX = DistanceUtils.NormLonDEG(newMaxX);
                        }
                    }
                    else
                    {
                        //restrict to world bounds
                        newMinX = Math.Max(newMinX, ctx.GetWorldBounds().GetMinX());
                        newMaxX = Math.Min(newMaxX, ctx.GetWorldBounds().GetMaxX());
                        newMinY = Math.Max(newMinY, ctx.GetWorldBounds().GetMinY());
                        newMaxY = Math.Min(newMaxY, ctx.GetWorldBounds().GetMaxY());
                    }
                    return(ctx.MakeRectangle(newMinX, newMaxX, newMinY, newMaxY));
                }
            }
        }
Пример #30
0
        public static void SearchSample()
        {
            Directory dir = new RAMDirectory();

            Analyzer analyzer = new StandardAnalyzer(Version);

            var indexWriter = new IndexWriter(dir, analyzer, IndexWriter.MaxFieldLength.UNLIMITED);

            SpatialContext ctx      = SpatialContext.GEO;
            var            strategy = new PointVectorStrategy(ctx, SpartialFieldName);
            //var precision = 8; // Precision 8 means down to 19 meter - higher precision consumes more memory
            //SpatialPrefixTree grid = new GeohashPrefixTree(ctx, precision);
            //var strategy = new RecursivePrefixTreeStrategy(grid, spartialFieldName);

            var docs = CreateSearchDocuments(GetDeals(), strategy);

            foreach (var doc in docs)
            {
                indexWriter.AddDocument(doc);
            }

            indexWriter.Commit();
            indexWriter.Dispose();

            // "Current" position
            Point littleMermaid = ctx.MakePoint(12.599239, 55.692848);

            //var parser = new QueryParser(Version, "title", analyzer);
            //Query q = parser.Parse("deal");
            Query q = new MatchAllDocsQuery(); // NOTE: MatchAllDocsQuery always returns score as 1.0

            // Add distance from current point to the scoring
            q = new DistanceCustomScoreQuery(q, strategy, littleMermaid);
            //q = new RecursivePrefixTreeStrategyDistanceCustomScoreQuery(q, strategy, littleMermaid, spartialFieldName);

            // Remove everything more than 2000 km away
            var filter = strategy.MakeFilter(new SpatialArgs(SpatialOperation.Intersects,
                                                             ctx.MakeCircle(littleMermaid, DistanceUtils.Dist2Degrees(2000, DistanceUtils.EARTH_MEAN_RADIUS_KM))));

            // Ensures the most recent searcher is used without destroying the Lucene IndexReader cache (via NRT)
            var searcherManager = new SearcherManager(dir);

            var collector = new GroupTopDocsCollector(5, SupplierFieldName);

            var searcher = searcherManager.GetSearcher();

            try
            {
                searcher.Search(q, filter, collector);
            }
            finally
            {
                searcherManager.ReleaseSearcher(searcher);
            }

            var hits = collector.GroupTopDocs();

            Console.WriteLine("Found {0} document(s) that matched query '{1}':", hits.TotalHits, q);
            foreach (var match in hits.GroupScoreDocs)
            {
                Document doc = searcher.Doc(match.Doc);
                Console.WriteLine("Best match '{0}' in group '{1}' with count {2} (MaxDoc: Score {3} Location '{4}')",
                                  doc.Get(TitleFieldName), match.GroupFieldValue, match.GroupCount, match.Score, doc.Get(LocationNameFieldName));
            }
        }