// reference: http://en.wikipedia.org/wiki/Hilbert_curve //convert (x,y) to d public static long XYtoD(long n, LongPoint point) { long rx, ry, s, d = 0; for (s = n / 2; s > 0; s /= 2) { rx = (point.x & s) > 0 ? 1 : 0; ry = (point.y & s) > 0 ? 1 : 0; d += s * s * ((3 * rx) ^ ry); Rot(s, point, rx, ry); } return(d); }
public void LongPointTest() { var analyzer = new WhitespaceAnalyzer(); var iwc = new IndexWriterConfig(analyzer); iwc.SetOpenMode(IndexWriterConfigOpenMode.CREATE); //インデックス作成--------------------------------------------- DateTime baseDate = DateTime.Parse("2020/07/16 08:00:00"); var ram = new RAMDirectory(); var writer = new IndexWriter(ram, iwc); try { for (int i = 0; i < 10; i++) { var doc = new Document(); doc.Add(new TextField("text", "hoge foo", FieldStore.YES)); DateTime tmp = baseDate.AddDays(i); long l = long.Parse(tmp.ToString("yyyyMMddHHmmss")); doc.Add(new LongPoint("date", l)); doc.Add(new StoredField("date", l)); writer.AddDocument(doc); } } finally { writer.Close(); } //検索------------------------------------------------------------ TermQuery tq = new TermQuery(new Term("text", "foo")); Query rq = LongPoint.NewRangeQuery("date", 20200717000000, 20200719000000); BooleanQueryBuilder b = new BooleanQueryBuilder(); b.Add(tq, BooleanClauseOccur.MUST); //AND条件 b.Add(rq, BooleanClauseOccur.FILTER); //AND条件(スコアリングに関与しない) Query q = b.Build(); DirectoryReader dr = DirectoryReader.Open(ram); IndexSearcher searcher = new IndexSearcher(dr); ScoreDoc[] hits = searcher.Search(q, 100).ScoreDocs; for (int i = 0; i < hits.Length; i++) { var doc = searcher.Doc(hits[i].Doc); Debug.WriteLine(DateTime.ParseExact(doc.Get("date"), "yyyyMMddHHmmss", null)); } Assert.AreEqual(hits.Length, 2); }
//rotate/flip a quadrant appropriately private static void Rot(long n, LongPoint point, long rx, long ry) { if (ry == 0) { if (rx == 1) { point.x = n - 1 - point.x; point.y = n - 1 - point.y; } //Swap x and y long t = point.x; point.x = point.y; point.y = t; } }
//convert d to (x,y) public static LongPoint DtoXY(long n, long d) { long rx, ry, s, t = d; var point = new LongPoint(0, 0); for (s = 1; s <= n; s *= 2) { rx = 1 & (t / 2); ry = 1 & (t ^ rx); Rot(s, point, rx, ry); point.x += s * rx; point.y += s * ry; t /= 4; } return(point); }