1#!/pxrpythonsubst 2# 3# Copyright 2016 Pixar 4# 5# Licensed under the Apache License, Version 2.0 (the "Apache License") 6# with the following modification; you may not use this file except in 7# compliance with the Apache License and the following modification to it: 8# Section 6. Trademarks. is deleted and replaced with: 9# 10# 6. Trademarks. This License does not grant permission to use the trade 11# names, trademarks, service marks, or product names of the Licensor 12# and its affiliates, except as required to comply with Section 4(c) of 13# the License and to reproduce the content of the NOTICE file. 14# 15# You may obtain a copy of the Apache License at 16# 17# http://www.apache.org/licenses/LICENSE-2.0 18# 19# Unless required by applicable law or agreed to in writing, software 20# distributed under the Apache License with the above modification is 21# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 22# KIND, either express or implied. See the Apache License for the specific 23# language governing permissions and limitations under the Apache License. 24# 25from __future__ import division 26 27import sys 28import unittest 29import math 30from pxr import Gf, Tf 31 32def err( msg ): 33 return "ERROR: " + msg + " failed" 34 35class TestGfPlane(unittest.TestCase): 36 37 def test_Constructors(self): 38 self.assertIsInstance(Gf.Plane(), Gf.Plane, err( "constructor" )) 39 self.assertIsInstance(Gf.Plane(Gf.Vec3d(1,1,1), 1), Gf.Plane, err( "constructor" )) 40 self.assertIsInstance(Gf.Plane(Gf.Vec3d(1,1,1), Gf.Vec3d(1,1,1)), Gf.Plane, err( "constructor" )) 41 self.assertIsInstance(Gf.Plane(Gf.Vec3d(0,0,1), Gf.Vec3d(0,1,0), Gf.Vec3d(1,0,0)), Gf.Plane, 42 err( "constructor" )) 43 self.assertIsInstance(Gf.Plane(Gf.Vec4d(3,4,0,5)), Gf.Plane, err("constructor" )) 44 45 def test_Properties(self): 46 p = Gf.Plane() 47 self.assertEqual(p.Set(Gf.Vec3d(1,1,1), 1), Gf.Plane(Gf.Vec3d(1,1,1), 1), err("Set")) 48 self.assertEqual(p.Set(Gf.Vec3d(1,1,1), Gf.Vec3d(1,1,1)), Gf.Plane(Gf.Vec3d(1,1,1), Gf.Vec3d(1,1,1)), 49 err("Set")) 50 self.assertEqual(p.Set(Gf.Vec3d(0,0,1), Gf.Vec3d(0,1,0), Gf.Vec3d(1,0,0)), 51 Gf.Plane(Gf.Vec3d(0,0,1), Gf.Vec3d(0,1,0), Gf.Vec3d(1,0,0)), err("Set")) 52 53 p = Gf.Plane(Gf.Vec3d(1,1,1), 1) 54 self.assertEqual(p.normal, Gf.Vec3d(1,1,1).GetNormalized(), err("normal")) 55 56 p = Gf.Plane(Gf.Vec3d(1,1,1), 10) 57 self.assertEqual(p.distanceFromOrigin, 10, err("distanceFromOrigin")) 58 59 def test_vec4d(self): 60 p = Gf.Plane(Gf.Vec4d(3,4,0,5)) 61 self.assertEqual(p.normal, Gf.Vec3d(3, 4, 0) / 5, err("normal")) 62 self.assertEqual(p.distanceFromOrigin, -1, err("distanceFromOrigin")) 63 64 pt0 = Gf.Vec3d(2,3,1) 65 pt1 = Gf.Vec3d(5,1,2) 66 pt2 = Gf.Vec3d(6,0,7) 67 68 p = Gf.Plane(pt0, pt1, pt2) 69 eqn = p.GetEquation() 70 71 for pt in [pt0, pt1, pt2]: 72 v = eqn[0] * pt[0] + eqn[1] * pt[1] + eqn[2] * pt[2] + eqn[3] 73 self.assertTrue(Gf.IsClose(v, 0, 1e-12)) 74 75 def test_Operators(self): 76 p1 = Gf.Plane(Gf.Vec3d(1,1,1), 10) 77 p2 = Gf.Plane(Gf.Vec3d(1,1,1), 20) 78 self.assertEqual(p1, Gf.Plane(Gf.Vec3d(1,1,1), 10), err("equality")) 79 self.assertTrue(not p1 == p2, err("equality")) 80 self.assertTrue(not p1 != Gf.Plane(Gf.Vec3d(1,1,1), 10), err("inequality")) 81 self.assertTrue(p1 != p2, err("inequality")) 82 83 def test_Methods(self): 84 p = Gf.Plane(Gf.Vec3d(1,1,1), 1) 85 self.assertTrue(Gf.IsClose(p.GetDistance(Gf.Vec3d(2,2,2)), 2.4641016151377553, 0.00001), 86 err("GetDistance")) 87 88 p = Gf.Plane(Gf.Vec3d(1,1,1), 0) 89 self.assertTrue(Gf.IsClose(p.GetDistance(Gf.Vec3d(0,0,0)), 0, 0.00001), \ 90 err("GetDistance")) 91 92 93 p = Gf.Plane(Gf.Vec3d(0,1,0), 0) 94 self.assertEqual(p.Project(Gf.Vec3d(3, 3, 3)), Gf.Vec3d(3, 0, 3), err("Project")) 95 96 p = Gf.Plane(Gf.Vec3d(1,1,1), 0) 97 p.Transform(Gf.Matrix4d().SetRotate(Gf.Rotation(Gf.Vec3d(1,0,0), 30))) 98 self.assertTrue(Gf.IsClose(p.normal, Gf.Vec3d(0.57735, 0.211325, 0.788675), 0.0001)) 99 100 p = Gf.Plane(Gf.Vec3d(1,1,1), 1) 101 self.assertEqual(p.normal * -1, p.Reorient(Gf.Vec3d()).normal, err("Reorient")) 102 103 b = Gf.Range3d() 104 self.assertFalse(Gf.Plane(Gf.Vec3d(1,1,1), 1).IntersectsPositiveHalfSpace(b), 105 err("IntersectsPositiveHalfSpace")) 106 107 b = Gf.Range3d(Gf.Vec3d(-1,-1,-1), Gf.Vec3d(1,1,1)) 108 self.assertTrue(Gf.Plane(Gf.Vec3d(1,1,1), 1).IntersectsPositiveHalfSpace(b), 109 err("IntersectsPositiveHalfSpace")) 110 self.assertTrue(Gf.Plane(Gf.Vec3d(1,1,-1), 1).IntersectsPositiveHalfSpace(b), 111 err("IntersectsPositiveHalfSpace")) 112 self.assertTrue(Gf.Plane(Gf.Vec3d(1,-1,1), 1).IntersectsPositiveHalfSpace(b), 113 err("IntersectsPositiveHalfSpace")) 114 self.assertTrue(Gf.Plane(Gf.Vec3d(1,-1,-1), 1).IntersectsPositiveHalfSpace(b), 115 err("IntersectsPositiveHalfSpace")) 116 self.assertTrue(Gf.Plane(Gf.Vec3d(-1,1,1), 1).IntersectsPositiveHalfSpace(b), 117 err("IntersectsPositiveHalfSpace")) 118 self.assertTrue(Gf.Plane(Gf.Vec3d(-1,1,-1), 1).IntersectsPositiveHalfSpace(b), 119 err("IntersectsPositiveHalfSpace")) 120 self.assertTrue(Gf.Plane(Gf.Vec3d(-1,-1,1), 1).IntersectsPositiveHalfSpace(b), 121 err("IntersectsPositiveHalfSpace")) 122 self.assertTrue(Gf.Plane(Gf.Vec3d(-1,-1,-1), 1).IntersectsPositiveHalfSpace(b), 123 err("IntersectsPositiveHalfSpace")) 124 125 p = Gf.Plane(Gf.Vec3d(1,1,1), 10) 126 self.assertFalse(p.IntersectsPositiveHalfSpace(Gf.Range3d(Gf.Vec3d(), Gf.Vec3d(1,1,1))), 127 err("IntersectsPositiveHalfSpace")) 128 129 p = Gf.Plane(Gf.Vec3d(1,1,1), 1) 130 self.assertTrue(p.IntersectsPositiveHalfSpace(Gf.Vec3d(1,1,1)), 131 err("IntersectsPositiveHalfSpace")) 132 133 p = Gf.Plane(Gf.Vec3d(1,1,1), 10) 134 self.assertFalse(p.IntersectsPositiveHalfSpace(Gf.Vec3d()), 135 err("IntersectsPositiveHalfSpace")) 136 137 self.assertEqual(p, eval(repr(p)), err("repr")) 138 139 self.assertTrue(len(str(Gf.Plane())), err("str")) 140 141 def test_Fitting(self): 142 # Collinear points should not define a plane. 143 a = Gf.Vec3d(0, 0, 0) 144 b = Gf.Vec3d(1, 0, 0) 145 c = Gf.Vec3d(2, 0, 0) 146 self.assertIsNone(Gf.FitPlaneToPoints([a, b, c]), err("collinear")) 147 148 # Cannot fit plane to 2 or fewer points. 149 with self.assertRaises(Tf.ErrorException): 150 Gf.FitPlaneToPoints([a, b]) 151 152 # Perfect fit (normal should be parallel to Z-axis, but OK if opposite 153 # direction). 154 c = Gf.Vec3d(0, 1, 0) 155 p = Gf.FitPlaneToPoints([a, b, c]) 156 self.assertAlmostEqual(Gf.Dot(p.GetNormal(), Gf.Vec3d.ZAxis()), 1.0, 157 msg=err("normal1")) 158 self.assertAlmostEqual(p.GetDistanceFromOrigin(), 0.0, 159 msg=err("distance1")) 160 161 # Try the same plane but with non-unit vectors. 162 b = Gf.Vec3d(1.5, 0, 0) 163 c = Gf.Vec3d(0, 3.2, 0) 164 p = Gf.FitPlaneToPoints([a, b, c]) 165 self.assertAlmostEqual(Gf.Dot(p.GetNormal(), Gf.Vec3d.ZAxis()), 1.0, 166 msg=err("normal2")) 167 self.assertAlmostEqual(p.GetDistanceFromOrigin(), 0.0, 168 msg=err("distance2")) 169 170 # Try a more complicated plane. 171 p1 = Gf.Plane(Gf.Vec4d(3, 4, 0, 5)) # equation constructor 172 a = p1.Project(Gf.Vec3d(2, 3, 6)) 173 b = p1.Project(Gf.Vec3d(34, -2, 2)) 174 c = p1.Project(Gf.Vec3d(-3, 7, -8)) 175 d = p1.Project(Gf.Vec3d(4, 1, 1)) 176 e = p1.Project(Gf.Vec3d(87, 67, 92)) 177 p2 = Gf.FitPlaneToPoints([a, b, c]) 178 self.assertAlmostEqual( 179 Gf.Dot(p1.GetNormal(), p2.GetNormal()), 1.0, 180 msg=err("p2 normal parallel to p1")) 181 self.assertAlmostEqual( 182 p1.GetDistanceFromOrigin(), 183 p2.GetDistanceFromOrigin(), 184 msg=err("p2 distance equals p1")) 185 p3 = Gf.FitPlaneToPoints([a, b, c, d, e]) 186 self.assertAlmostEqual( 187 Gf.Dot(p1.GetNormal(), p3.GetNormal()), 1.0, 188 msg=err("p3 normal parallel to p1")) 189 self.assertAlmostEqual( 190 p1.GetDistanceFromOrigin(), 191 p3.GetDistanceFromOrigin(), 192 msg=err("p3 distance equals p1")) 193 194 # Try fitting points that don't form a perfect plane. 195 # This roughly forms the plane with normal (1, -1, 0) passing through 196 # the origin. 197 # Decrease the number of places of accuracy since these points are 198 # fudged and don't form an exact plane. 199 a = Gf.Vec3d(1.1, 1, 5) 200 b = Gf.Vec3d(1, 1.1, 2) 201 c = Gf.Vec3d(2, 2.1, -4) 202 d = Gf.Vec3d(2.1, 2, 1) 203 e = Gf.Vec3d(25.3, 25.2, 3) 204 f = Gf.Vec3d(25.1, 25.4, 6) 205 p = Gf.FitPlaneToPoints([a, b, c, d, e, f]) 206 expectedNormal = Gf.Vec3d(1, -1, 0).GetNormalized() 207 self.assertAlmostEqual( 208 Gf.Dot(p.GetNormal(), expectedNormal), 1.0, 209 places=2, 210 msg=err("normal3")) 211 self.assertAlmostEqual( 212 p.GetDistanceFromOrigin(), 0.0, 213 places=2, 214 msg=err("distance3")) 215 216if __name__ == '__main__': 217 unittest.main() 218