19 using System.Collections.Generic;
20 using System.Diagnostics;
22 using Spatial4n.Core.Context;
23 using Spatial4n.Core.Shapes;
25 namespace Lucene.Net.Spatial.Prefix.Tree
38 protected override int GetLevelForDistance(
double degrees)
41 return grid.GetLevelForDistance(degrees);
46 return new QuadPrefixTree(ctx, maxLevels != null ? maxLevels.Value : MAX_LEVELS_POSSIBLE);
50 public static readonly
int MAX_LEVELS_POSSIBLE = 50;
52 public static readonly
int DEFAULT_MAX_LEVELS = 12;
69 : base(ctx, maxLevels)
71 Init(ctx, bounds, maxLevels);
75 : base(ctx, DEFAULT_MAX_LEVELS)
77 Init(ctx, ctx.GetWorldBounds(), DEFAULT_MAX_LEVELS);
81 : base(ctx, maxLevels)
83 Init(ctx, ctx.GetWorldBounds(), maxLevels);
86 protected void Init(SpatialContext ctx, Rectangle bounds,
int maxLevels)
88 this.xmin = bounds.GetMinX();
89 this.xmax = bounds.GetMaxX();
90 this.ymin = bounds.GetMinY();
91 this.ymax = bounds.GetMaxY();
93 levelW =
new double[maxLevels];
94 levelH =
new double[maxLevels];
95 levelS =
new int[maxLevels];
96 levelN =
new int[maxLevels];
100 xmid = xmin + gridW / 2.0;
101 ymid = ymin + gridH / 2.0;
102 levelW[0] = gridW / 2.0;
103 levelH[0] = gridH / 2.0;
107 for (
int i = 1; i < levelW.Length; i++)
109 levelW[i] = levelW[i - 1] / 2.0;
110 levelH[i] = levelH[i - 1] / 2.0;
111 levelS[i] = levelS[i - 1] * 2;
112 levelN[i] = levelN[i - 1] * 4;
117 public override int GetLevelForDistance(
double dist)
121 for (
int i = 0; i < maxLevels - 1; i++)
124 if (dist > levelW[i] && dist > levelH[i])
132 protected override Node GetNode(Point p,
int level)
134 var cells =
new List<Node>(1);
135 Build(xmid, ymid, 0, cells,
new StringBuilder(), ctx.MakePoint(p.GetX(), p.GetY()), level);
139 public override Node GetNode(
string token)
144 public override Node GetNode(byte[] bytes,
int offset,
int len)
146 throw new System.NotImplementedException();
149 public override IList<Node> GetNodes(Shape shape,
int detailLevel,
bool inclParents)
151 var point = shape as Point;
153 return base.GetNodesAltPoint(point, detailLevel, inclParents);
155 return base.GetNodes(shape, detailLevel, inclParents);
158 private void Build(
double x,
double y,
int level, List<Node> matches, StringBuilder str, Shape shape,
int maxLevel)
160 Debug.Assert(str.Length == level);
161 double w = levelW[level] / 2;
162 double h = levelH[level] / 2;
166 CheckBattenberg(
'A', x - w, y + h, level, matches, str, shape, maxLevel);
167 CheckBattenberg(
'B', x + w, y + h, level, matches, str, shape, maxLevel);
168 CheckBattenberg(
'C', x - w, y - h, level, matches, str, shape, maxLevel);
169 CheckBattenberg(
'D', x + w, y - h, level, matches, str, shape, maxLevel);
177 private void CheckBattenberg(
187 Debug.Assert(str.Length == level);
188 double w = levelW[level] / 2;
189 double h = levelH[level] / 2;
191 int strlen = str.Length;
192 Rectangle rectangle = ctx.MakeRectangle(cx - w, cx + w, cy - h, cy + h);
193 SpatialRelation v = shape.Relate(rectangle);
194 if (SpatialRelation.CONTAINS == v)
198 matches.Add(
new QuadCell(str.ToString(), v.Transpose(),
this));
200 else if (SpatialRelation.DISJOINT == v)
208 int nextLevel = level + 1;
209 if (nextLevel >= maxLevel)
212 matches.Add(
new QuadCell(str.ToString(), v.Transpose(),
this));
216 Build(cx, cy, nextLevel, matches, str, shape, maxLevel);
226 : base(enclosingInstance, token)
231 : base(enclosingInstance, token)
233 this.shapeRel = shapeRel;
236 public override void Reset(
string newToken)
238 base.Reset(newToken);
242 public override IList<Node> GetSubCells()
245 var cells =
new List<Node>(4)
247 new QuadCell(GetTokenString() +
"A", tree),
248 new QuadCell(GetTokenString() +
"B", tree),
249 new QuadCell(GetTokenString() +
"C", tree),
250 new QuadCell(GetTokenString() +
"D", tree)
255 public override int GetSubCellsSize()
260 public override Node GetSubCell(Point p)
262 return ((
QuadPrefixTree)spatialPrefixTree).GetNode(p, GetLevel() + 1);
267 public override Shape GetShape()
274 private Rectangle MakeShape()
276 String token = GetTokenString();
278 double xmin = tree.xmin;
279 double ymin = tree.ymin;
281 for (
int i = 0; i < token.Length; i++)
284 if (
'A' == c ||
'a' == c)
286 ymin += tree.levelH[i];
288 else if (
'B' == c ||
'b' == c)
290 xmin += tree.levelW[i];
291 ymin += tree.levelH[i];
293 else if (
'C' == c ||
'c' == c)
297 else if (
'D' == c ||
'd' == c)
299 xmin += tree.levelW[i];
303 throw new Exception(
"unexpected char: " + c);
306 int len = token.Length;
307 double width, height;
310 width = tree.levelW[len - 1];
311 height = tree.levelH[len - 1];
318 return spatialPrefixTree.ctx.MakeRectangle(xmin, xmin + width, ymin, ymin + height);