{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "nbsphinx": "hidden" }, "outputs": [], "source": [ "import open3d as o3d\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import copy\n", "import os\n", "import sys\n", "\n", "# only needed for tutorial, monkey patches visualization\n", "sys.path.append('..')\n", "import open3d_tutorial as o3dtut\n", "# change to True if you want to interact with the visualization windows\n", "o3dtut.interactive = not \"CI\" in os.environ" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Transformation\n", "The geometry types of Open3D have a number of transformation methods. In this tutorial we show how to use `translate`, `rotate`, `scale`, and `transform`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Translate\n", "The first transformation method we want to look at is `translate`. The translate method takes a single 3D vector $t$ as input and translates all points/vertices of the geometry by this vector, $v_t = v + t$. The code below shows how the mesh is once translated in the x- and once in the y-direction." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()\n", "mesh_tx = copy.deepcopy(mesh).translate((1.3,0,0))\n", "mesh_ty = copy.deepcopy(mesh).translate((0,1.3,0))\n", "print(f'Center of mesh: {mesh.get_center()}')\n", "print(f'Center of mesh tx: {mesh_tx.get_center()}')\n", "print(f'Center of mesh ty: {mesh_ty.get_center()}')\n", "o3d.visualization.draw_geometries([mesh, mesh_tx, mesh_ty])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " \n", "**Note:** \n", "\n", "The method `get_center` returns the mean of the `TriangleMesh` vertices. That means that for a coordinate frame created at the origin `[0,0,0]`, `get_center` will return `[0.05167549 0.05167549 0.05167549]`.\n", "\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The method takes a second argument `relative` that is default set to `true`. If we change it to `False` than the center of the geometry is translated directly to the position specified in the first argument." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()\n", "mesh_mv = copy.deepcopy(mesh).translate((2,2,2), relative=False)\n", "print(f'Center of mesh: {mesh.get_center()}')\n", "print(f'Center of translated mesh: {mesh_mv.get_center()}')\n", "o3d.visualization.draw_geometries([mesh, mesh_mv])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Rotation\n", "The geometry types of Open3D can also be rotated with the method `rotate`. It takes as first argument a rotation matrix `R`. As rotations in 3D can be parametrized in a number of ways, Open3D provides convenience functions to convert from different parametrizations to rotation matrices:\n", "\n", "- Convert from [Euler angles](https://en.wikipedia.org/wiki/Euler_angles) with `get_rotation_matrix_from_xyz` (where `xyz` can also be of the form `yzx` `zxy`, `xzy`, `zyx`, and `yxz`)\n", "- Convert from [Axis-angle representation](https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation) with `get_rotation_matrix_from_axis_angle`\n", "- Convert from [Quaternions](https://en.wikipedia.org/wiki/Quaternion) with `get_rotation_matrix_from_quaternion`\n", "\n", "In the code below we rotate the mesh using Euler angles ." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()\n", "mesh_r = copy.deepcopy(mesh)\n", "R = mesh.get_rotation_matrix_from_xyz((np.pi/2,0,np.pi/4))\n", "mesh_r.rotate(R, center=(0,0,0))\n", "o3d.visualization.draw_geometries([mesh, mesh_r])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The function `rotate` has a second argument `center` that is default set to `True`. This indicates that the object is first centered prior to applying the rotation and the moved back to its previous center. If this argument is set to `False`, then the rotation will be applied directly, which rotates the whole geometry around the coordinate center. This implies that the mesh center can be changed after the rotation." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()\n", "mesh_r = copy.deepcopy(mesh).translate((2,0,0))\n", "mesh_r.rotate(mesh.get_rotation_matrix_from_xyz((np.pi/2,0,np.pi/4)), center=(0,0,0))\n", "o3d.visualization.draw_geometries([mesh, mesh_r])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Scale\n", "Vertices and points of Open3D geometry types can also be scaled using `scale`, $v_s = s \\cdot v$. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()\n", "mesh_s = copy.deepcopy(mesh).translate((2,0,0))\n", "mesh_s.scale(0.5, center=mesh_s.get_center())\n", "o3d.visualization.draw_geometries([mesh, mesh_s])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `scale` method also has a second argument `center` that is set to `True` by default. If it is set to `False`, then the object is not centered prior to scaling and this can then move the center of the object." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()\n", "mesh_s = copy.deepcopy(mesh).translate((2,1,0))\n", "mesh_s.scale(0.5, center=(0,0,0))\n", "o3d.visualization.draw_geometries([mesh, mesh_s])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## General transformation\n", "Open3D also supports a general transformation by a general $4x4$ matrix using the method `transform`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()\n", "T = np.eye(4)\n", "T[:3,:3] = mesh.get_rotation_matrix_from_xyz((0,np.pi/3, np.pi/2))\n", "T[0,3] = 1\n", "T[1,3] = 1.3\n", "print(T)\n", "mesh_t = copy.deepcopy(mesh).transform(T)\n", "o3d.visualization.draw_geometries([mesh, mesh_t])" ] } ], "metadata": { "celltoolbar": "Edit Metadata", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.7" } }, "nbformat": 4, "nbformat_minor": 4 }