//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(); }
public void testMultiShape(SpatialContext ctx) { this.ctx = ctx; if(ctx.IsGeo()) return;//TODO not yet supported! //come up with some random shapes int NUM_SHAPES = random.Next(1, 5); var shapes = new List<Rectangle>(NUM_SHAPES); while (shapes.Count < NUM_SHAPES) { shapes.Add(RandomRectangle(20)); } var multiShape = new MultiShape(shapes.Cast<Shape>(), ctx); //test multiShape.getBoundingBox(); Rectangle msBbox = multiShape.GetBoundingBox(); if (shapes.Count == 1) { Assert.Equal(shapes[0], msBbox.GetBoundingBox()); } else { foreach (Rectangle shape in shapes) { AssertRelation("bbox contains shape", SpatialRelation.CONTAINS, msBbox, shape); } } //TODO test multiShape.relate() }
private readonly GeoCircle inverseCircle; //when distance reaches > 1/2 way around the world, cache the inverse. #endregion Fields #region Constructors public GeoCircle(Point p, double dist, SpatialContext ctx) : base(p, dist, ctx) { Debug.Assert(ctx.IsGeo()); //In the direction of latitude (N,S), distance is the same number of degrees. distDEG = ctx.GetDistCalc().DistanceToDegrees(distRadius); if (distDEG > 90) { //--spans more than half the globe Debug.Assert(enclosingBox.GetWidth() == 360); double backDistDEG = 180 - distDEG; if (backDistDEG > 0) { double backDistance = ctx.GetDistCalc().DegreesToDistance(backDistDEG); //shrink inverseCircle as small as possible to avoid accidental overlap backDistance -= Ulp(backDistance); Point backPoint = ctx.MakePoint(GetCenter().GetX() + 180, GetCenter().GetY() + 180); inverseCircle = new GeoCircle(backPoint, backDistance, ctx); } else inverseCircle = null;//whole globe horizAxisY = GetCenter().GetY();//although probably not used } else { inverseCircle = null; double _horizAxisY = ctx.GetDistCalc().CalcBoxByDistFromPt_yHorizAxisDEG(GetCenter(), dist, ctx); //some rare numeric conditioning cases can cause this to be barely beyond the box if (_horizAxisY > enclosingBox.GetMaxY()) { horizAxisY = enclosingBox.GetMaxY(); } else if (_horizAxisY < enclosingBox.GetMinY()) { horizAxisY = enclosingBox.GetMinY(); } else { horizAxisY = _horizAxisY; } //Debug.Assert(enclosingBox.Relate_yRange(horizAxis, horizAxis, ctx).Intersects()); } }
/// <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.InvariantCultureIgnoreCase)) instance = new GeohashPrefixTree.Factory(); else if ("quad".Equals(cname, StringComparison.InvariantCultureIgnoreCase)) instance = new QuadPrefixTree.Factory(); else { Type t = Type.GetType(cname); instance = (SpatialPrefixTreeFactory)Activator.CreateInstance(t); } instance.Init(args, ctx); return instance.NewSPT(); }
public SpatialRelation RelateXRange(double ext_minX, double ext_maxX, SpatialContext ctx) { //For ext & this we have local minX and maxX variable pairs. We rotate them so that minX <= maxX double minX = this.minX; double maxX = this.maxX; if (ctx.IsGeo()) { //unwrap dateline, plus do world-wrap short circuit double rawWidth = maxX - minX; if (rawWidth == 360) return SpatialRelation.CONTAINS; if (rawWidth < 0) { maxX = minX + (rawWidth + 360); } double ext_rawWidth = ext_maxX - ext_minX; if (ext_rawWidth == 360) return SpatialRelation.WITHIN; if (ext_rawWidth < 0) { ext_maxX = ext_minX + (ext_rawWidth + 360); } //shift to potentially overlap if (maxX < ext_minX) { minX += 360; maxX += 360; } else if (ext_maxX < minX) { ext_minX += 360; ext_maxX += 360; } } return Relate_Range(minX, maxX, ext_minX, ext_maxX); }
public SpatialRelation Relate(Point point, SpatialContext ctx) { if (point.GetY() > GetMaxY() || point.GetY() < GetMinY()) return SpatialRelation.DISJOINT; // all the below logic is rather unfortunate but some dateline cases demand it double minX = this.minX; double maxX = this.maxX; double pX = point.GetX(); if (ctx.IsGeo()) { //unwrap dateline and normalize +180 to become -180 double rawWidth = maxX - minX; if (rawWidth < 0) { maxX = minX + (rawWidth + 360); } //shift to potentially overlap if (pX < minX) { pX += 360; } else if (pX > maxX) { pX -= 360; } else { return SpatialRelation.CONTAINS; //short-circuit } } if (pX < minX || pX > maxX) return SpatialRelation.DISJOINT; return SpatialRelation.CONTAINS; }
public DistanceSimilarity(SpatialContext ctx, Point queryPoint) { this.queryPoint = queryPoint; this.distCalc = ctx.GetDistCalc(); this.nullValue = (ctx.IsGeo() ? 180 : double.MaxValue); }
private GeoCircle inverseCircle; //when distance reaches > 1/2 way around the world, cache the inverse. #endregion Fields #region Constructors public GeoCircle(Point p, double radiusDEG, SpatialContext ctx) : base(p, radiusDEG, ctx) { Debug.Assert(ctx.IsGeo()); Init(); }