Project

General

Profile

root / branches / compiler / cSharp / ooasCompiler / src / libs / c5 / UserGuideExamples / PointLocation.cs @ 3

1
/*
2
 Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
3
 Permission is hereby granted, free of charge, to any person obtaining a copy
4
 of this software and associated documentation files (the "Software"), to deal
5
 in the Software without restriction, including without limitation the rights
6
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
 copies of the Software, and to permit persons to whom the Software is
8
 furnished to do so, subject to the following conditions:
9
 
10
 The above copyright notice and this permission notice shall be included in
11
 all copies or substantial portions of the Software.
12
 
13
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
 SOFTWARE.
20
*/
21

    
22
using System;
23
using System.Diagnostics;
24
using C5;
25
using SCG = System.Collections.Generic;
26

    
27
namespace PointLocation
28
{
29
  //public enum Site { Cell,Edge,Outside}
30
  /// <summary>
31
  /// A line segment with associated data of type T for the cell 
32
  /// to its right respectively left.
33
  /// </summary>
34
  public struct Edge<T>
35
    {
36
      public double xs, ys, xe, ye;
37
      
38
      public T right, left;
39
      
40
      public Edge(double xs, double ys, double xe, double ye, T right, T left)
41
	{
42
	  this.xs = xs;
43
	  this.ys = ys;
44
	  this.xe = xe;
45
	  this.ye = ye;
46
	  this.right = right;
47
	  this.left = left;
48
	}
49
      
50
      
51
      public T Cell(bool upper)
52
	{
53
	  return (DoubleComparer.StaticCompare(xs, xe) < 0) == upper ? left : right;
54
	}
55
      
56
      
57
      public override string ToString()
58
	{
59
	  return String.Format("[({0:G5};{1:G5})->({2:G5};{3:G5})/R:{4} L:{5}]", xs, ys, xe, ye, right, left);
60
	}
61
    }
62
  
63
  
64
  
65
  /// <summary>
66
  /// A data structure for point location in a plane divided into
67
  /// cells by edges. This is the classical use of persistent trees
68
  /// by Sarnak and Tarjan [?]. See de Berg et al for alternatives.
69
  /// 
70
  /// The internal data is an outer sorted dictionary that maps each
71
  /// x coordinate of an endpoint of some edge to an inner sorted set
72
  /// of the edges crossing or touching the vertical line at that x
73
  /// coordinate, the edges being ordered by their y coordinates
74
  /// to the immediate right of x. Lookup of a point (x,y) is done by
75
  /// finding the predecessor of x cell the outer dictionary and then locating
76
  /// the edges above and below (x,y) by searching in the inner sorted set.
77
  /// 
78
  /// The creation of the inner sorted sets is done by maintaining a
79
  /// (persistent) tree of edges, inserting and deleting edges according
80
  /// to a horzontal sweep of the edges while saving a snapshot of the
81
  /// inner tree in the outer dictionary at each new x coordinate.
82
  ///
83
  /// If there are n edges, there will be 2n updates to the inner tree,
84
  /// and in the worst case, the inner tree will have size Omega(n) for
85
  /// Omega(n) snapshots. We will use O(n*logn) time and O(n) space for
86
  /// sorting the endpoints. If we use a nodecopying persistent inner tree,
87
  /// we will use O(n) space and time for building the data structure proper.
88
  /// If we use a pathcopy persistent tree, we will use O(n*logn) time and
89
  /// space for the data struicture. Finally, if we use a non-persistent
90
  /// tree with a full copy for snapshot, we may use up to O(n^2) space and
91
  /// time for building the datastructure.
92
  ///
93
  /// Lookup will take O(logn) time in any case, but taking the memory
94
  /// hierarchy into consideration, a low space use is very beneficial
95
  /// for large problems.
96
  ///
97
  /// The code assumes that the given set of edges is correct, in particular
98
  /// that they do not touch at interior points (e.g. cross or coincide). 
99
  /// </summary>
100
	
101
  public class PointLocator<T>
102
  {
103
    private TreeDictionary<double,ISorted<Edge<T>>> htree;
104
    
105
    private EdgeComparer<T> lc = new EdgeComparer<T>();
106
    
107
    private SCG.IComparer<EndPoint> epc = new EndPoint(0, 0, true, 0);
108
    
109
    private DoubleComparer dc = new DoubleComparer();
110
    
111
    private TreeDictionary<EndPoint,Edge<T>> endpoints;
112
    
113
    private int count;
114
    
115
    private bool built = false;
116
    
117
    public PointLocator()
118
    {
119
      //htree = new TreeDictionary<double,TreeSet<Edge<T>>>(dc);
120
      endpoints = new TreeDictionary<EndPoint,Edge<T>>(epc);
121
    }
122
    
123
    public PointLocator(SCG.IEnumerable<Edge<T>> edges)
124
    {
125
      //htree = new TreeDictionary<double,TreeSet<Edge<T>>>(dc);
126
      endpoints = new TreeDictionary<EndPoint,Edge<T>>(epc);
127
      foreach (Edge<T> edge in edges)
128
	add(edge);
129
    }
130
    
131
    private void add(Edge<T> edge)
132
    {
133
      int c = DoubleComparer.StaticCompare(edge.xs, edge.xe);
134
      
135
      if (c == 0)
136
	return;
137
      
138
      endpoints.Add(new EndPoint(edge.xs, edge.ys, c < 0, count), edge);
139
      endpoints.Add(new EndPoint(edge.xe, edge.ye, c > 0, count++), edge);
140
    }
141

    
142
    public void Add(Edge<T> edge)
143
    {
144
      if (built)
145
	throw new InvalidOperationException("PointLocator static when built");
146
      add(edge);
147
    }
148
    
149
    public void AddAll(SCG.IEnumerable<Edge<T>> edges)
150
    {
151
      if (built)
152
	throw new InvalidOperationException("PointLocator static when built");
153
      
154
      foreach (Edge<T> edge in edges)
155
	add(edge);
156
    }
157
    
158
    public void Build()
159
    {
160
      //htree.Clear();
161
      htree = new TreeDictionary<double,ISorted<Edge<T>>>(dc);
162
      
163
      TreeSet<Edge<T>> vtree = new TreeSet<Edge<T>>(lc);
164
      double lastx = Double.NegativeInfinity;
165
      
166
      foreach (KeyValuePair<EndPoint,Edge<T>> p in endpoints)
167
	{
168
	  if (dc.Compare(p.Key.x,lastx)>0)
169
	    {
170
	      //Put an empty snapshot at -infinity!
171
	      htree[lastx] = (ISorted<Edge<T>>)(vtree.Snapshot());
172
	      lc.X = lastx = p.Key.x;
173
	      lc.compareToRight = false;
174
	    }
175
	  
176
	  if (p.Key.start)
177
	    {
178
	      if (!lc.compareToRight)
179
		lc.compareToRight = true;
180
	      Debug.Assert(vtree.Check());
181
	      bool chk = vtree.Add(p.Value);
182
	      Debug.Assert(vtree.Check());
183
	      
184
	      Debug.Assert(chk,"edge was not added!",""+p.Value);
185
	    }
186
	  else
187
	    {
188
	      Debug.Assert(!lc.compareToRight);
189
	      
190
	      Debug.Assert(vtree.Check("C"));
191
	      
192
	      bool chk = vtree.Remove(p.Value);
193
	      Debug.Assert(vtree.Check("D"));
194
	      
195
	      Debug.Assert(chk,"edge was not removed!",""+p.Value);
196
	    }
197
	}
198
      lc.compareToRight = true;
199
      
200
      htree[lastx] = (TreeSet<Edge<T>>)(vtree.Snapshot());
201
      built = true;
202
    }
203
    
204
    
205
    /*public void Clear()
206
      {
207
      endpoints.Clear();
208
      htree.Clear();
209
      }*/
210
    /// <summary>
211
    /// Find the cell, if any, containing (x,y).
212
    /// </summary>
213
    /// <param name="x">x coordinate of point</param>
214
    /// <param name="y">y coordinate of point</param>
215
    /// <param name="below">Associate data of cell according to edge below</param>
216
    /// <param name="above">Associate data of cell according to edge above</param>
217
    /// <returns>True if point is inside some cell</returns>
218
    public bool Place(double x, double y, out T cell)
219
    {
220
      if (!built)
221
	throw new InvalidOperationException("PointLocator must be built first");
222
      
223
      KeyValuePair<double,ISorted<Edge<T>>> p = htree.WeakPredecessor(x);
224
      
225
      //if (DoubleComparer.StaticCompare(cell.key,x)==0)
226
      //Just note it, we have thrown away the vertical edges!
227
      Edge<T> low, high;
228
      bool lval, hval;
229
      PointComparer<T> c = new PointComparer<T>(x, y);
230
      
231
      //Return value true here means we are at an edge.
232
      //But note that if x is in htree.Keys, we may be at a
233
      //vertical edge even if the return value is false here.
234
      //Therefore we do not attempt to sort out completely the case
235
      //where (x,y) is on an edge or even on several edges,
236
      //and just deliver some cell it is in.
237
      p.Value.Cut(c, out low, out lval, out high, out hval);
238
      if (!lval || !hval)
239
	{
240
	  cell = default(T);
241
	  return false;
242
	}
243
      else
244
	{
245
	  cell = low.Cell(true);//high.Cell(false);
246
	  return true;
247
	}
248
    }
249
    
250
    public void Place(double x, double y, out T upper, out bool hval, out T lower, out bool lval)
251
    {
252
      if (!built)
253
	throw new InvalidOperationException("PointLocator must be built first");
254
      
255
      KeyValuePair<double,ISorted<Edge<T>>> p = htree.WeakPredecessor(x);
256
      
257
      //if (DoubleComparer.StaticCompare(cell.key,x)==0)
258
      //Just note it, we have thrown away the vertical edges!
259
      Edge<T> low, high;
260
      PointComparer<T> c = new PointComparer<T>(x, y);
261
      
262
      //Return value true here means we are at an edge.
263
      //But note that if x is in htree.Keys, we may be at a
264
      //vertical edge even if the return value is false here.
265
      //Therefore we do not attempt to sort out completely the case
266
      //where (x,y) is on an edge or even on several edges,
267
      //and just deliver some cell it is in.
268
      p.Value.Cut(c, out low, out lval, out high, out hval);
269
      upper = hval ? high.Cell(false) : default(T);
270
      lower = lval ? low.Cell(true) : default(T);
271
      return; 
272
    }
273
    
274
    public void Test(double x, double y)
275
    {
276
      T cell;
277
      
278
      if (Place(x, y, out cell))
279
	Console.WriteLine("({0}; {1}): <- {2} ", x, y, cell);
280
      else
281
	Console.WriteLine("({0}; {1}): -", x, y);
282
    }
283
    
284
    /// <summary>
285
    /// Endpoint of an edge with ordering/comparison according to x
286
    /// coordinates with arbitration by the id field. 
287
    /// The client is assumed to keep the ids unique.
288
    /// </summary>
289
    public /*private*/ struct EndPoint: SCG.IComparer<EndPoint>
290
    {
291
      public double x, y;
292
      
293
      public bool start;
294
      
295
      private int id;
296
      
297
      
298
      public EndPoint(double x, double y, bool left, int id)
299
	{
300
	  this.x = x;this.y = y;this.start = left;this.id = id;
301
	}
302
      
303
      
304
      public int Compare(EndPoint a, EndPoint b)
305
	{
306
	  int c = DoubleComparer.StaticCompare(a.x, b.x);
307
	  
308
	  return c != 0 ? c : (a.start && !b.start) ? 1 : (!a.start && b.start) ? -1 : a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
309
	}
310
    }
311
  }
312

    
313
  /// <summary>
314
  /// Compare two doubles with tolerance. 
315
  /// </summary>
316
  class DoubleComparer: SCG.IComparer<double>
317
  {
318
    private const double eps = 1E-10;
319
    
320
    public int Compare(double a, double b)
321
    {
322
      return a > b + eps ? 1 : a < b - eps ? -1 : 0;
323
    }
324

    
325
    public static int StaticCompare(double a, double b)
326
    {
327
      return a > b + eps ? 1 : a < b - eps ? -1 : 0;
328
    }
329
  }
330

    
331
  /// <summary>
332
  /// Compare a given point (x,y) to edges: is the point above, at or below
333
  /// the edge. Assumes edges not vertical. 
334
  /// </summary>
335
  class PointComparer<T>: IComparable<Edge<T>>
336
  {
337
    private double x, y;
338
    
339
    public PointComparer(double x, double y)
340
    {
341
      this.x = x; this.y = y;
342
    }
343
    
344
    public int CompareTo(Edge<T> a)
345
    {
346
      double ya = (a.ye - a.ys) / (a.xe - a.xs) * (x - a.xs) + a.ys;
347
      
348
      return DoubleComparer.StaticCompare(y, ya);
349
    }
350
    
351
    public bool Equals(Edge<T> a) { return CompareTo(a) == 0; }
352
  }
353

    
354
  /// <summary>
355
  /// Compare two edges at a given x coordinate:
356
  /// Compares the y-coordinate  to the immediate right of x of the two edges.
357
  /// Assumes edges to be compared are not vertical.
358
  /// </summary>
359
  class EdgeComparer<T>: SCG.IComparer<Edge<T>>
360
  {
361
    private double x;
362
    
363
    public bool compareToRight = true;
364
    
365
    public double X { get { return x; } set { x = value; } }
366
    
367
    public int Compare(Edge<T> line1, Edge<T> line2)
368
    {
369
      double a1 = (line1.ye - line1.ys) / (line1.xe - line1.xs);
370
      double a2 = (line2.ye - line2.ys) / (line2.xe - line2.xs);
371
      double ya = a1 * (x - line1.xs) + line1.ys;
372
      double yb = a2 * (x - line2.xs) + line2.ys;
373
      int c = DoubleComparer.StaticCompare(ya, yb);
374
      
375
      return c != 0 ? c : (compareToRight ? 1 : -1) * DoubleComparer.StaticCompare(a1, a2);
376
    }
377
  }
378

    
379
  namespace Test
380
    {
381
      public class Ugly : EnumerableBase<Edge<int>>, SCG.IEnumerable<Edge<int>>, SCG.IEnumerator<Edge<int>>
382
      {
383
	private int level = -1, maxlevel;
384
	
385
	private bool leftend = false;
386
	
387
	public Ugly(int maxlevel)
388
	{
389
	  this.maxlevel = maxlevel;
390
	}
391
	
392
	public override SCG.IEnumerator<Edge<int>> GetEnumerator()
393
	{
394
	  return (SCG.IEnumerator<Edge<int>>)MemberwiseClone();
395
	}
396
	
397
	public void Reset()
398
	{
399
	  level = -1;
400
	  leftend = false;
401
	}
402
	
403
	public bool MoveNext()
404
	{
405
	  if (level > maxlevel)
406
	    throw new InvalidOperationException();
407
	  
408
	  if (leftend)
409
	    {
410
	      leftend = false;
411
	      return true;
412
	    }
413
	  else
414
	    {
415
	      leftend = true;
416
	      return ++level <= maxlevel;
417
	    }
418
	}
419
	
420
	public Edge<int> Current
421
	{
422
	  get
423
	    {
424
	      if (level < 0 || level > maxlevel)
425
		throw new InvalidOperationException();
426
	      
427
	      double y = (level * 37) % maxlevel;
428
	      double deltax = leftend ? 1 : maxlevel;
429
	      
430
	      if (leftend)
431
		return new Edge<int>(0, y, level, y - 0.5, 0, 0);
432
	      else
433
		return new Edge<int>(level, y - 0.5, level, y, 0, 0);
434
	    }
435
	}
436
	
437
	
438
	public void Dispose() { }
439
	
440
#region IEnumerable Members
441

    
442
	System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
443
	{
444
	  throw new Exception("The method or operation is not implemented.");
445
	}
446

    
447
#endregion
448
	
449
#region IEnumerator Members
450
	
451
	object System.Collections.IEnumerator.Current
452
	{
453
	  get { throw new Exception("The method or operation is not implemented."); }
454
	}
455
	
456
	void System.Collections.IEnumerator.Reset()
457
	{
458
	  throw new Exception("The method or operation is not implemented.");
459
	}
460
	
461
#endregion
462
      }
463

    
464
      public class TestUgly
465
      {
466
	private Ugly ugly;
467
	
468
	private int d;
469
	
470
	private PointLocator<int> pointlocator;
471
	
472
	
473
	public TestUgly(int d)
474
	{
475
	  this.d = d;
476
	  ugly = new Ugly(d);
477
	}
478
	
479
	
480
	public double Traverse()
481
	{
482
	  double xsum = 0;
483
	  
484
	  foreach (Edge<int> e in ugly)	xsum += e.xe;
485
	  
486
	  return xsum;
487
	}
488
	
489
	public bool LookUp(int count, int seed)
490
	{
491
	  Random random = new Random(seed);
492
	  bool res = false;
493
	  
494
	  for (int i = 0; i < count; i++)
495
	    {
496
	      int cell;
497
	      
498
	      res ^= pointlocator.Place(random.NextDouble() * d, random.NextDouble() * d, out cell);
499
	    }
500
	  
501
	  return res;
502
	}
503

    
504
	public static void Run(string[] args)
505
	{
506
	  int d = args.Length >= 2 ? int.Parse(args[1]) : 400;//00;
507
	  int repeats = args.Length >= 3 ? int.Parse(args[2]) : 10;
508
	  int lookups = args.Length >= 4 ? int.Parse(args[3]) : 500;//00;
509
	  
510
	  new TestUgly(d).run(lookups);
511
	}
512
	
513
	
514
	public void run(int lookups)
515
	{
516
	  double s = 0;
517
	  
518
	  s += Traverse();
519
	  
520
	  pointlocator = new PointLocator<int>(ugly);
521
	  pointlocator.Build();
522
	  
523
	  LookUp(lookups, 567);
524
	}
525
      }
526
      
527
      public class Lattice : EnumerableBase<Edge<string>>, SCG.IEnumerable<Edge<string>>, SCG.IEnumerator<Edge<string>>, System.Collections.IEnumerator
528
      {
529
	private int currenti = -1, currentj = 0, currentid = 0;
530
	
531
	private bool currenthoriz = true;
532
	
533
	private int maxi, maxj;
534
	
535
	private double a11 = 1, a21 = -1, a12 = 1, a22 = 1;
536
	
537
	public Lattice(int maxi, int maxj, double a11, double a21, double a12, double a22)
538
	{
539
	  this.maxi = maxi;
540
	  this.maxj = maxj;
541
	  this.a11 = a11;
542
	  this.a12 = a12;
543
	  this.a21 = a21;
544
	  this.a22 = a22;
545
	}
546

    
547
	public Lattice(int maxi, int maxj)
548
	{
549
	  this.maxi = maxi;
550
	  this.maxj = maxj;
551
	}
552
	
553
	public override SCG.IEnumerator<Edge<string>> GetEnumerator()
554
	{
555
	  return (SCG.IEnumerator<Edge<string>>)MemberwiseClone();
556
	}
557
	
558
	public void Reset()
559
	{
560
	  currenti = -1;
561
	  currentj = 0;
562
	  currentid = -1;
563
	  currenthoriz = true;
564
	}
565
	
566
	public bool MoveNext()
567
	{
568
	  currentid++;
569
	  if (currenthoriz)
570
	    {
571
	      if (++currenti >= maxi)
572
		{
573
		  if (currentj >= maxj)
574
		    return false;
575
		  
576
		  currenti = 0;
577
		  currenthoriz = false;
578
		}
579
	      
580
	      return true;
581
	    }
582
	  else
583
	    {
584
	      if (++currenti > maxi)
585
		{
586
		  currenti = 0;
587
		  currenthoriz = true;
588
		  if (++currentj > maxj)
589
		    return false;
590
		}
591
	      
592
	      return true;
593
	    }
594
	}
595
	
596
	
597
	private string i2l(int i)
598
	{
599
	  int ls = 0, j = i;
600
	  
601
	  do { ls++; j = j / 26 - 1; } while (j >= 0);
602
	  
603
	  char[] res = new char[ls];
604
	  
605
	  while (ls > 0) { res[--ls] = (char)(65 + i % 26); i = i / 26 - 1; }
606
	  
607
	  //res[0]--;
608
	  return new String(res);
609
	}
610
	
611
	
612
	private string fmtid(int i, int j)
613
	{
614
	  return "";//cell + ";" + cell;
615
	  /*if (cell < 0 || cell < 0 || cell >= maxi || cell >= maxj)
616
	    return "Outside";
617
	    
618
	    return String.Format("{0}{1}", i2l(cell), cell);*/
619
	}
620
	
621
	
622
	public Edge<string> Current
623
	{
624
	  get
625
	    {
626
	      if (currenti >= maxi && currentj >= maxj)
627
		throw new InvalidOperationException();
628
	      
629
	      double xs = currenti * a11 + currentj * a12;
630
	      double ys = currenti * a21 + currentj * a22;
631
	      double deltax = currenthoriz ? a11 : a12;
632
	      double deltay = currenthoriz ? a21 : a22;
633
	      string r = fmtid(currenti, currenthoriz ? currentj - 1 : currentj);
634
	      string l = fmtid(currenthoriz ? currenti : currenti - 1, currentj);
635
	      
636
	      return new Edge<string>(xs, ys, xs + deltax, ys + deltay, r, l);
637
	    }
638
	}
639
	
640
	
641
	public void Dispose() { }
642
	
643
#region IEnumerable Members
644
	
645
	System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
646
	{
647
	  throw new Exception("The method or operation is not implemented.");
648
	}
649
	
650
#endregion
651
	
652
#region IEnumerator Members
653
	
654
	object System.Collections.IEnumerator.Current
655
	{
656
	  get { throw new Exception("The method or operation is not implemented."); }
657
	}
658
	
659
	bool System.Collections.IEnumerator.MoveNext()
660
	{
661
	  throw new Exception("The method or operation is not implemented.");
662
	}
663
	
664
	void System.Collections.IEnumerator.Reset()
665
	{
666
	  throw new Exception("The method or operation is not implemented.");
667
	}
668
	
669
#endregion
670
      }
671
      
672
      public class TestLattice
673
      {
674
	private Lattice lattice;
675
	
676
	private int d;
677
	
678
	private PointLocator<string> pointlocator;
679
	
680
	
681
	public TestLattice(int d)
682
	{
683
	  this.d = d;
684
	  lattice = new Lattice(d, d, 1, 0, 0, 1);
685
	}
686

    
687
	public TestLattice(int d, double shear)
688
	{
689
	  this.d = d;
690
	  lattice = new Lattice(d, d, 1, 0, shear, 1);
691
	}
692

    
693
	public double Traverse()
694
	{
695
	  double xsum = 0;
696
	  
697
	  foreach (Edge<string> e in lattice)	xsum += e.xe;
698
	  
699
	  return xsum;
700
	}
701
	
702
	
703
	public bool LookUp(int count, int seed)
704
	{
705
	  Random random = new Random(seed);
706
	  bool res = false;
707
	  
708
	  for (int i = 0; i < count; i++)
709
	    {
710
	      string cell;
711
	      
712
	      res ^= pointlocator.Place(random.NextDouble() * d, random.NextDouble() * d, out cell);
713
	    }
714
	  
715
	  return res;
716
	}
717
	
718
	
719
	public static void Run()
720
	{
721
 	  int d = 200;
722
 	  int repeats = 2;
723
 	  int lookups = 50000;
724
 	  TestLattice tl = null;
725
	  
726
 	  Console.WriteLine("TestLattice Run({0}), means over {1} repeats:", d, repeats);
727
 	  tl = new TestLattice(d, 0.000001);
728

    
729
 	  tl.Traverse();
730
	  
731
 	  tl.pointlocator = new PointLocator<string>();
732
	  
733
 	  tl.pointlocator.AddAll(tl.lattice);
734
	  
735
 	  tl.pointlocator.Build();
736
	  
737
 	  tl.LookUp(lookups, 567);
738
	}
739
	
740
	
741
	public void BasicRun()
742
	{
743
	  pointlocator.Test(-0.5, -0.5);
744
	  pointlocator.Test(-0.5, 0.5);
745
	  pointlocator.Test(-0.5, 1.5);
746
	  pointlocator.Test(0.5, -0.5);
747
	  pointlocator.Test(0.5, 0.5);
748
	  pointlocator.Test(0.5, 1.5);
749
	  pointlocator.Test(1.5, -0.5);
750
	  pointlocator.Test(1.5, 0.5);
751
	  pointlocator.Test(1.5, 1.5);
752
	  pointlocator.Test(1.5, 4.99);
753
	  pointlocator.Test(1.5, 5);
754
	  pointlocator.Test(1.5, 5.01);
755
	  pointlocator.Test(1.99, 4.99);
756
	  pointlocator.Test(1.99, 5);
757
	  pointlocator.Test(1.99, 5.01);
758
	  pointlocator.Test(2, 4.99);
759
	  pointlocator.Test(2, 5);
760
	  pointlocator.Test(2, 5.01);
761
	  pointlocator.Test(2.01, 4.99);
762
	  pointlocator.Test(2.01, 5);
763
	  pointlocator.Test(2.01, 5.01);
764
	}
765
      }
766
    }
767

    
768
  public class TestPointLocation {
769
    public static void Main(String[] args) {
770
      Test.TestUgly.Run(new String[0]);
771
    }
772
  }
773
}
774