LinExpr() accepts rational numbers
[linpy.git] / linpy / tests / test_geometry.py
1 # Copyright 2014 MINES ParisTech
2 #
3 # This file is part of LinPy.
4 #
5 # LinPy is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # LinPy is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with LinPy. If not, see <http://www.gnu.org/licenses/>.
17
18 import math
19 import unittest
20
21 from ..geometry import *
22 from ..linexprs import Symbol
23 from ..polyhedra import Eq
24
25
26 class TestPoint(unittest.TestCase):
27
28 def setUp(self):
29 self.x = Symbol('x')
30 self.y = Symbol('y')
31 self.z = Symbol('z')
32 self.t = Symbol('t')
33 self.pt1 = Point({self.x: 10, self.y: 5, self.z: 1})
34 self.pt2 = Point({self.x: 15, self.y: 40, self.z: 60})
35 self.vec1 = Vector({self.x: 20, self.y: 30, self.z: 40})
36
37 def test_new(self):
38 self.assertEqual(Point({self.x: 10, self.y: 5, self.z: 1}), self.pt1)
39 self.assertEqual(Point([(self.x, 10), (self.y, 5), (self.z, 1)]),
40 self.pt1)
41
42 def test_symbols(self):
43 self.assertTupleEqual(self.pt1.symbols, (self.x, self.y, self.z))
44
45 def test_dimension(self):
46 self.assertEqual(self.pt1.dimension, 3)
47
48 def test_coordinate(self):
49 self.assertEqual(self.pt1.coordinate(self.x), 10)
50 with self.assertRaises(KeyError):
51 self.pt1.coordinate(self.t)
52
53 def test_getitem(self):
54 self.assertEqual(self.pt1[self.x], 10)
55 with self.assertRaises(KeyError):
56 self.pt1[self.t]
57
58 def test_coordinates(self):
59 self.assertListEqual(list(self.pt1.coordinates()),
60 [(self.x, 10), (self.y, 5), (self.z, 1)])
61
62 def test_values(self):
63 self.assertListEqual(list(self.pt1.values()),
64 [10, 5, 1])
65
66 def test_isorigin(self):
67 self.assertFalse(self.pt1.isorigin())
68 self.assertTrue(Point({}).isorigin())
69
70 def test_bool(self):
71 self.assertTrue(self.pt1)
72 self.assertFalse(Point({}))
73
74 def test_add(self):
75 self.assertEqual(self.pt1 + self.vec1,
76 Point({self.x: 30, self.y: 35, self.z: 41}))
77 with self.assertRaises(TypeError):
78 self.pt1 + self.pt2
79
80 def test_sub(self):
81 self.assertEqual(self.pt1 - self.pt2,
82 Vector({self.x: -5, self.y: -35, self.z: -59}))
83 self.assertEqual(self.pt1 - self.vec1,
84 Point({self.x: -10, self.y: -25, self.z: -39}))
85
86 def test_eq(self):
87 self.assertEqual(self.pt1, self.pt1)
88 self.assertNotEqual(self.pt1, self.pt2)
89 self.assertNotEqual(self.pt1, self.vec1)
90
91 def test_aspolyhedron(self):
92 self.assertEqual(self.pt1.aspolyhedron(),
93 Eq(self.x, 10) & Eq(self.y, 5) & Eq(self.z, 1))
94
95 def test_repr(self):
96 self.assertEqual(repr(self.pt1), 'Point({x: 10, y: 5, z: 1})')
97
98
99 class TestVector(unittest.TestCase):
100
101 def setUp(self):
102 self.x = Symbol('x')
103 self.y = Symbol('y')
104 self.z = Symbol('z')
105 self.pt1 = Point({self.x: 10, self.y: 5, self.z: 1})
106 self.pt2 = Point({self.x: 15, self.y: 40, self.z: 60})
107 self.vec1 = Vector({self.x: 20, self.y: 30, self.z: 40})
108 self.vec2 = Vector({self.x: 45, self.y: 70, self.z: 80})
109
110 def test_add(self):
111 self.assertEqual(self.vec1 + self.pt1, Point({self.x: 30, self.y: 35, self.z: 41}))
112 self.assertEqual(self.vec1 + self.vec2, Vector({self.x: 65, self.y: 100, self.z: 120}))
113
114 def test_angle(self):
115 self.assertEqual(math.degrees(self.vec1.angle(self.vec1)), 0)
116 self.assertAlmostEqual(math.degrees(self.vec1.angle(self.vec2)), 4.15129, places=5)
117 self.assertAlmostEqual(math.degrees(self.vec2.angle(self.vec1)), 4.15129, places=5)
118
119 def test_cross(self):
120 self.assertEqual(self.vec1.cross(self.vec2), Vector({self.x: -400, self.y: 200, self.z: 50}))
121
122 def test_div(self):
123 self.assertEqual(self.vec1 / 10, Vector({self.x: 2, self.y: 3, self.z: 4}))
124
125 def test_dot(self):
126 self.assertEqual(self.vec1.dot(self.vec2), 6200)
127
128 def test_eq(self):
129 self.assertEqual(self.vec1, self.vec1)
130 self.assertNotEqual(self.vec1, self.vec2)
131
132 def test_mul(self):
133 self.assertEqual(75 * self.vec1, Vector({self.x: 1500, self.y: 2250, self.z: 3000}))
134 self.assertEqual(self.vec1 * 75, Vector({self.x: 1500, self.y: 2250, self.z: 3000}))
135
136 def test_neg(self):
137 self.assertEqual(-self.vec1, Vector({self.x: -20, self.y: -30, self.z: -40}))
138
139 def test_norm(self):
140 self.assertAlmostEqual(self.vec1.norm(), 53.85165, places=5)
141
142 def test_norm2(self):
143 self.assertEqual(self.vec1.norm2(), 2900)
144
145 def test_asunit(self):
146 unit = self.vec1.asunit()
147 self.assertAlmostEqual(unit[self.x], 0.37139, 5)
148 self.assertAlmostEqual(unit[self.y], 0.55709, 5)
149 self.assertAlmostEqual(unit[self.z], 0.74278, 5)
150
151 def test_sub(self):
152 self.assertEqual(self.vec1 - self.pt1, Point({self.x: 10, self.y: 25, self.z: 39}))
153 self.assertEqual(self.vec1 - self.vec2, Vector({self.x: -25, self.y: -40, self.z: -40}))