def test_replace_geometry(self): """Test for replacing mesh geometry.""" mesh = Box3d([0, 0, 0], [1, 1, 1]).to_mesh() mesh2 = Box3d([0, 0, 0], [1, 1, 1]).to_mesh() mesh2.merge(mesh) mesh.replace_geometry(mesh2) self.assertEqual(mesh.num_vertices(), mesh2.num_vertices()) self.assertEqual(mesh.num_indices(), mesh2.num_indices()) self.assertEqual(mesh.normals().shape, mesh2.vertices().shape)
def test_equal(self): """ Test == operator. """ box1 = Box3d(Vector3(1, 2, 3), Vector3(0, 4, 2)) box2 = Box3d(Vector3(1, 2, 3), Vector3(0, 4, 2)) box3 = Box3d(Vector3(1, 2.1, 3), Vector3(0, 4, 2)) assert (box1 == box2) assert (box2 != box3)
def test_xml(self): """ Test conversion to and from xml. This is just a basic functionality test of a round trip from Box3d to xml and back. """ box = Box3d(corner1=Vector3(1.5, 2.6, 3.7), corner2=Vector3(5.1, 6.2, 7.9)) box_xml = box.to_xml() assert (box_xml.tag == 'box3d') box_rt = Box3d.from_xml(box_xml) assert (box.almost_equal(box_rt))
def test_almost_equal(self): """ Test almost_equal function. """ box1 = Box3d(Vector3(1.000000001, 2.000000001, 3.000001), Vector3(-0.00000001, 3.99999999, 2.000001)) box2 = Box3d(Vector3(1.0, 2, 3), Vector3(0, 4, 2)) box3 = Box3d(Vector3(-1, -1, -1), Vector3(1, 1, 1)) self.assertTrue(box1.almost_equal(box2, atol=0.01)) self.assertFalse(box1.almost_equal(box2, atol=0.000000000001)) self.assertFalse(box1.almost_equal(box3))
def test_bounding_box_io(self): """ Save and load a bounding_box project. Also try overwriting the project (should fail). """ project_scene = ProjectScene(project_type="bounding_box") bounds = Box3d([-0.5, -0.5, -0.5], [0.5, 0.5, 0.5]) po = ProjectObject(id="1", bounds=bounds, category="chair") project_scene.elements["1"] = po # test saving project_scene.save(path=self.temp_directory, project_name="test") xml_path = os.path.join(self.temp_directory, "test", "test.xml") self.assertTrue(os.path.isfile(xml_path)) # test overwriting self.assertRaises(OSError, project_scene.save, path=self.temp_directory, project_name="test") # test loading project_scene = ProjectScene.load(path=self.temp_directory, project_name="test") self.assertIsInstance(project_scene, ProjectScene) self.assertIsInstance(project_scene.elements, ProjectObjectDict) # ::: TODO: improve check with equality test on project_scene # Check bounding box for the first ProjectObject po = project_scene.elements["1"] self.assertTrue(po.bounds.almost_equal(bounds, atol=0.01)) self.assertEqual(po.category, "chair")
def test_center(self): """ Test center function """ box = Box3d(corner1=Vector3f(2, 4, 6), corner2=Vector3f(0, 2, 3)) expected_center = Vector3f(1, 3, 4.5) np.testing.assert_array_almost_equal(box.center(), expected_center)
def test_bounds(self): points = np.array([[0.6, 0.1, -0.1], [1.1, 2.1, 3.1], [1.3, 2.2, 3.4]]) min_corner = Vector3f(-1, -2, -3) vg = VoxelGrid(0.5, min_corner=min_corner, points=points) bounds = vg.bounds() expected_bounds = Box3d(Vector3f(0.5, 0, -0.5), Vector3f(1.5, 2.5, 3.5)) self.assertAlmostEquals(bounds, expected_bounds)
def test_mesh(self): box = Box3d(corner1=Vector3(0, 0, 0), corner2=Vector3(1, 1, 1)) mesh = box.to_mesh() self.assertIsInstance(mesh, Mesh) self._check_mesh_helper(mesh) tex_mesh = box.to_textured_mesh(color=np.array([71, 57, 8], dtype=np.uint8)) self.assertIsInstance(tex_mesh, TexturedMesh) self._check_mesh_helper(tex_mesh)
def bounds(self): """ Compute bounding box of occupied voxels. Return: Box3d - the bounding box """ centers = self.voxel_centers() min_corner = np.amin(centers, 0) - 0.5 * self.voxel_size max_corner = np.amax(centers, 0) + 0.5 * self.voxel_size return Box3d(corner1=min_corner, corner2=max_corner)
def test_from_mesh(self): """Test converting mesh to textured mesh.""" mesh = Box3d([0, 0, 0], [1, 1, 1]).to_mesh() color = np.array([255, 0, 0], dtype=np.uint8) # red textured_mesh = TexturedMesh.from_mesh(mesh, color) self.assertIsInstance(textured_mesh, TexturedMesh) self.assertEqual(textured_mesh.num_vertices(), mesh.num_vertices()) self.assertEqual(textured_mesh.num_indices(), mesh.num_indices()) self.assertEqual(textured_mesh.normals().shape, mesh.vertices().shape) self.assertEqual(textured_mesh.uv_coords().shape[1], mesh.num_vertices())
def test_random_points(self): """ Make two random points and verify the bounding box's corners are correct """ corner1 = Vector3(-1, -2, -3) corner2 = Vector3(1, 2, 3) box = Box3d(corner1, corner2) corners = box.corners() corners_target = np.column_stack([[-1.0, -2.0, 3.0], [1.0, -2.0, 3.0], [1.0, 2.0, 3.0], [-1.0, 2.0, 3.0], [-1.0, -2.0, -3.0], [1.0, -2.0, -3.0], [1.0, 2.0, -3.0], [-1.0, 2.0, -3.0]]) np.testing.assert_array_equal(corners, corners_target)
def _parse_xml(base_elem): """ Parse the xml of an <element> tag, extracting the ProjectObject attributes. Inputs: base_elem (ET.Element) - An Element with tag "element" and appropriate sub-elements. Return: tuple (id, pose, category, bounds, symmetry, score, evaluated) ProjectObject attributes (see constructor for details). Exceptions: ValueError - If base_elem is not <element> or if none of its children is <id>. """ # verify base_elem tag is 'element' if base_elem.tag != "element": raise ValueError('Expected tag to be "element"') # defaults proxy = ProjectObject(1) category = proxy.category pose = proxy.pose symmetry = proxy.symmetry score = proxy.score evaluated = proxy.evaluated for elem in base_elem: if elem.tag == "id": id = elem.text elif elem.tag == "pose": pose = Pose3.from_xml(elem) elif elem.tag == "category": category = elem.text elif (elem.tag == "bounds"): # Note: Boxe3d.from_xml expects tag to be 'box3d' elem_temp = deepcopy(elem) elem_temp.tag = "box3d" bounds = Box3d.from_xml(elem_temp) elif elem.tag == "symmetry": symmetry = ObjectSymmetry.from_xml(elem) elif elem.tag == "detectionScore": score = float(elem.text) elif elem.tag == "evaluated": evaluated = bool(elem.text) if id is None: raise ValueError("XML is missing required <id> tag.") return (id, pose, category, bounds, symmetry, score, evaluated)
def test_unit_cube(self): """ Make two points inside a unit cube and verify the bounding box's corners are correct """ corner1 = Vector3(0, 0, 0) corner2 = Vector3(1, 1, 1) box = Box3d(corner1, corner2) corners = box.corners() corners_target = np.column_stack([[0.0, 0.0, 1.0], [1.0, 0.0, 1.0], [1.0, 1.0, 1.0], [0.0, 1.0, 1.0], [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [0.0, 1.0, 0.0]]) np.testing.assert_array_almost_equal(corners, corners_target) np.testing.assert_array_almost_equal(box.min_corner, corner1) np.testing.assert_array_almost_equal(box.max_corner, corner2)
def setUp(self): # create sample bounding box, meshes, and voxel grid objects self.bounds = Box3d([-1.5, -2.2, 3], [4, 4.1, 6.5]) textured_mesh = self.bounds.to_textured_mesh() self.meshes = GltfModel.from_textured_mesh(textured_mesh) points = np.array([[0.1, 0.1, 0.1], [1.1, 1.1, 1.1], [1.3, 1.2, 1.4]]) self.voxels = VoxelGrid(0.5, min_corner=Vector3f(0, 0, 0), points=points) # and pose rot = np.array([[1, 0, 0], [0, 0, -1], [0, 1, 0]], dtype=float) trans = Vector3f(1, 1, 1) self.pose = Pose3(rot, trans) # Create temporary outout directory. self.temp_directory = tempfile.mkdtemp()
def test_merge(self): box1 = Box3d(corner1=Vector3f(0, 1, 0), corner2=Vector3f(1, 2, 1)) box2 = Box3d(corner1=Vector3f(1, 0, 0), corner2=Vector3f(2, 1, 2)) merged = Box3d.merge([box1, box2]) np.testing.assert_array_equal(merged.min_corner, Vector3(0, 0, 0)) np.testing.assert_array_equal(merged.max_corner, Vector3(2, 2, 2))
def test_volume(self): """Test computation of box volume""" box = Box3d(corner1=Vector3f(2, 4, 6), corner2=Vector3f(0, 2, 3)) self.assertEqual(box.volume(), 12)