Home | History | Annotate | Download | only in tests
      1 # Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """This module contains unit tests for geometry module."""
      6 
      7 
      8 import random
      9 import unittest
     10 
     11 import common_unittest_utils
     12 
     13 from math import sqrt
     14 from sets import Set
     15 
     16 from geometry.elements import Circle, Point
     17 from geometry.minicircle import minicircle
     18 from geometry.two_farthest_clusters import get_two_farthest_clusters
     19 
     20 
     21 class MinicircleTest(unittest.TestCase):
     22     """A class for FirwareSummary unit tests."""
     23 
     24     def test_minicircle(self):
     25         # a list of points: [center, radius]
     26         tests = [
     27             # a right triagnle
     28             ([(0, 0), (3, 0), (0, 4)], [(1.5, 2), 2.5]),
     29 
     30             # an obtuse triagnle
     31             ([(1, 1), (3, 0), (0, 4)], [(1.5, 2), 2.5]),
     32 
     33             # a right triagnle with one point inside
     34             ([(0, 0), (1, 1), (3, 0), (0, 4)], [(1.5, 2), 2.5]),
     35 
     36             # three points at the same coordinates
     37             ([(5, 3), (5, 3), (5, 3)], [(5, 3), 0]),
     38 
     39             # two points at the same coordinates, a diagonal line
     40             ([(0, 0), (0, 0), (4, 4)], [(2, 2), 2 * sqrt(2)]),
     41 
     42             # two points at the same coordinates, a vertical line
     43             ([(0, 2), (0, 2), (0, 12)], [(0, 7), 5]),
     44 
     45             # two points at the same coordinates, a vertical line, one outlier
     46             ([(0, 2), (0, 2), (1, 5), (0, 12)], [(0, 7), 5]),
     47 
     48             # an equilateral triangle
     49             ([(0, 0), (10, 0), (5, 5 * sqrt(3))],
     50                     [(5, 5 * sqrt(3) / 3), 5 * sqrt(3) * 2 / 3]),
     51 
     52             # an equilateral triangle with a few points inside
     53             ([(0, 0), (10, 0), (5, 5 * sqrt(3)), (4, 1), (6, 2), (4.5, 3),
     54               (5.2, 2.99), (4.33, 1.78), (5.65, 3.1)],
     55                     [(5, 5 * sqrt(3) / 3), 5 * sqrt(3) * 2 / 3]),
     56 
     57             # a list of random points:
     58             #   Verify with octave geometry package:
     59             #   > points = [1,1; 1,0; 2,1; 2,2;  12,22; 11,21; 30,30; 31,30;
     60             #               30,31; 31,31; 5,35]
     61             #   > enclosingCircle(points)
     62             ([(1, 1), (1, 0), (2, 1), (2, 2), (12, 22), (11, 21), (30, 30),
     63               (31, 30), (30, 31), (31, 31), (5, 35)],
     64                     [(15.39740821, 16.08315335), 21.58594878]),
     65 
     66             # another list of random points:
     67             #   Verify with octave geometry package:
     68             #   > points = [11,11; 11,15; 12,11; 12.5,21.25; 12.77,22.84; 11,21;
     69             #               13.3,31; 13.7,33; 14.9,29; 15,10.9; 12.5,13.55]
     70             #   > enclosingCircle(points)
     71             ([(11, 11), (11, 15), (12, 11), (12.5, 21.25), (12.77, 22.84),
     72               (11, 21), (13.3, 31), (13.7, 33), (14.9, 29), (15, 10.9),
     73               (12.5, 13.55)],
     74                     [(13.27341679, 21.88667158), 11.12151257]),
     75         ]
     76         for points, circle_values in tests:
     77             center_values, radius = circle_values
     78             expected_circle = Circle(Point(*center_values), radius)
     79             actual_circle = minicircle(points)
     80             self.assertTrue(actual_circle == expected_circle)
     81 
     82     def test_get_two_farthest_clusters(self):
     83         tests = [
     84             # Each row is a tuple of two separated clusters.
     85             # two empty lists
     86             ([], []),
     87 
     88             # one point only
     89             ([(3.5, 7.886612)], []),
     90 
     91             # two points only
     92             ([(3.5, 7.886612)], [(3.4, 7.02)]),
     93 
     94             ([(1.2, 0), (2.3, 0), (0, 2.2)],
     95              [(10, 5), (11.87, 3.45), (10.55, 7.6)]),
     96 
     97             ([(100, 3.1), (101.1, 2.9), (99.8, 4.2)],
     98              [(1.1, 55.3), (11.87, 73.45), (3.58, 67.7)]),
     99 
    100             ([(101, 5.5), (102.1, 2.9), (89.8, 4.2), (65.2, 3.3)],
    101              [(1.5, 5.3), (1.87, 3.5), (23.8, 14.9), (3.8, 2.7)]),
    102         ]
    103 
    104         # Shuffle the two clusters, and then test the get_two_farthest_clusters
    105         # function. It should return cluster1 and cluster2.
    106         # Since every point is unique in the tests, we could simply use Set
    107         # to compare the clusters.
    108         for expected_cluster1, expected_cluster2 in tests:
    109             points = [Point(*p) for p in expected_cluster1 + expected_cluster2]
    110             # A fixed seed is used so that it gets the same shuffles every time.
    111             random.shuffle(points, lambda: 0.1234)
    112             actual_cluster1, actual_cluster2 = get_two_farthest_clusters(points)
    113 
    114             # The set of the expected sets should be equal to the set of
    115             # the actual sets.
    116             expected_set1 = Set([Point(*p) for p in expected_cluster1])
    117             expected_set2 = Set([Point(*p) for p in expected_cluster2])
    118             actual_set1 = Set(actual_cluster1)
    119             actual_set2 = Set(actual_cluster2)
    120             self.assertTrue(Set([expected_set1, expected_set2]) ==
    121                             Set([actual_set1, actual_set2]))
    122 
    123 
    124 if __name__ == '__main__':
    125   unittest.main()
    126