{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "60db6be101e99c83",
   "metadata": {},
   "source": [
    "<img src=\"https://raw.githubusercontent.com/UXARRAY/uxarray/main/docs/_static/images/logos/uxarray_logo_h_dark.svg\"\n",
    "     width=\"30%\"\n",
    "     alt=\"UXarray logo\"\n",
    "     align=\"right\"\n",
    "/>\n",
    "\n",
    "# Rendering Techniques\n",
    "\n",
    "### In this section, you'll learn:\n",
    "\n",
    "* Rendering methods that can be used for unstructured grids visualization. \n",
    "\n",
    "\n",
    "### Related Documentation\n",
    "\n",
    "* No UXarray documentation is referenced here since this section covers the content from a general point of view.\n",
    "\n",
    "\n",
    "### Prerequisites\n",
    "\n",
    "| Concepts | Importance | Notes |\n",
    "| --- | --- | --- |\n",
    "| Geometry | Necessary | |\n",
    "\n",
    "**Time to learn**: 10 minutes\n",
    "\n",
    "-----\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "40b652f0-4a70-4b08-a0db-702b4d5e1545",
   "metadata": {},
   "source": [
    "Since Unstructured Grids require significantly more overhead to represent compared to Structured grids, the choice of rendering technique plays an important role in obtaining high-resolution, accurate, and scalable visualizations. \n",
    "\n",
    "\n",
    "This notebook introduces relevant concepts and techniques that will be mentioned and used throughout this Cookbook."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95a35645-2c16-4506-8ae7-abf5e6f8c7e2",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "## Vector (Shape) Geometries\n",
    "\n",
    "The nodes (vertices), edges, and faces (cells) that make up an Unstructured Grid can each be converted into a geometric shape for visualization. These geometric shapes can often be referred to as vector graphics, since each geometry is mathematically represented when rendering.\n",
    "\n",
    "For example, in the \"Plotting with UXarray\" chapter, we will showcase how we can convert the faces in our Unstructured Grid into Polygons.\n",
    "\n",
    "When constructing unstructured grids visualization, we can render each face directly onto the screen. \n",
    "\n",
    "Rendering each face as a polygon will lead to visuals that look like this, which are high-quality since they represent the exact geometry of each face.\n",
    "\n",
    "&nbsp;\n",
    "\n",
    "<img src=\"../images/rendering/polygons.png\" alt=\"Continents\" width=\"400\"/>\n",
    "\n",
    "&nbsp;"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b862e8ae-58e6-47cb-849b-631878b0090f",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "Another example of Vector Geometries is encountered when adding features to a visualization, such as Contents or Borders. The geometries of these features are drawn onto our screen.\n",
    "\n",
    "&nbsp;\n",
    "\n",
    "<img src=\"../images/rendering/contients.jpg\" alt=\"Continents\" width=\"600\"/>\n",
    "\n",
    "&nbsp;"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6f2fde1d-82b8-47c9-9852-0d4e7d7618ee",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "### Shapely Example"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5807c07-d64b-4f75-969c-bd908d6c134d",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "One Python package which is used for representing and manipulating geometries is [Shapely](https://shapely.readthedocs.io/en/stable/manual.html).\n",
    "\n",
    "Shapely can be paired with SpatialPandas and other packages to represent unstructured grid elements (nodes, edges, faces) as geometries for visualization.\n",
    "\n",
    "The following code snippets are basic examples of how these elements can be represented as geometries.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "78cbec48-6730-4562-80a5-ffc20515d087",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "import shapely as sp"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "91edd03c-c30e-4635-b9dd-1be2a59fff7a",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "A node is represented as a pair of longitude and latitude coordinates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6a5942f1-9e27-470f-859d-9f9bcd458963",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"100.0\" height=\"100.0\" viewBox=\"-1.0 -1.0 2.0 2.0\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,0.0)\"><circle cx=\"0.0\" cy=\"0.0\" r=\"0.06\" stroke=\"#555555\" stroke-width=\"0.02\" fill=\"#66cc99\" opacity=\"0.6\" /></g></svg>"
      ],
      "text/plain": [
       "<POINT (0 0)>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sp.Point([0.0, 0.0])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a4783e9-eccd-450b-91c6-fe0bfda39123",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "An edge is represented as a pair of nodes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "e5ad35dd-1899-4495-ab94-11f75be3f1d6",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"194.39999999999998\" height=\"104.4\" viewBox=\"-7.2 -97.2 194.39999999999998 104.4\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,-90.0)\"><polyline fill=\"none\" stroke=\"#66cc99\" stroke-width=\"2.0\" points=\"0.0,0.0 180.0,-90.0\" opacity=\"0.8\" /></g></svg>"
      ],
      "text/plain": [
       "<LINESTRING (0 0, 180 -90)>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sp.LineString([[0.0, 0.0], [180, -90]])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ac6ee958-4b5e-4327-b466-f3c2dbdba2f4",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "A face is represented as a counter-clockwise set of nodes, with the first and final nodes in the set being equivalent (form a closed face)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "575edb2b-adf1-400c-ab8b-d6357b3aacb1",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"100.0\" height=\"100.0\" viewBox=\"89.6 39.6 10.800000000000011 10.799999999999997\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,90.0)\"><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"0.21600000000000022\" opacity=\"0.6\" d=\"M 100.0,40.0 L 100.0,50.0 L 90.0,50.0 L 90.0,40.0 L 100.0,40.0 z\" /></g></svg>"
      ],
      "text/plain": [
       "<POLYGON ((100 40, 100 50, 90 50, 90 40, 100 40))>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sp.Polygon([[100, 40], [100, 50], [90, 50], [90, 40], [100, 40]])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4bfdd46f-5810-43d6-b7d6-b277119d6dd4",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "## Rasterization\n",
    "\n",
    "While there is definitely merit in rendering each geometric shape directly, this operation is computationally expensive for large datasets.\n",
    "\n",
    "Rasterization is a technique in computer graphics that converts vector (a.k.a geometric shapes) graphics into a raster image, which can be thought of as a regularly-sampled array of pixel values used for rendering.\n",
    "\n",
    "The figure below shows a simplified example of how rasterization \"approximates\" the geometry of different elements.\n",
    "\n",
    "&nbsp;\n",
    "\n",
    "<img src=\"../images/rendering/raster_example.png\" alt=\"Rasterization Example\" width=\"1000\"/>\n",
    "\n",
    "&nbsp;"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c081ea7a-a033-46e9-baf5-d52b1be4a9db",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "For unstructured grids, rasterization looks something like the following.\n",
    "\n",
    "&nbsp;\n",
    "\n",
    "<img src=\"../images/rendering/raster-vs-vector.png\" alt=\"raster and vector\" width=\"400\"/>\n",
    "\n",
    "&nbsp;"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "709e29b3-da78-4a00-b595-864af151905e",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "The black edges outline the expected geometry of each face (a.k.a polygon).\n",
    "\n",
    "We can observe the jaggedness in the shading, which is the product of rasterization approximating each face."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "563f167c-9c2f-4ddc-a02f-8e40e5fba956",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "<div class=\"admonition alert alert-info\">\n",
    "    <p class=\"admonition-title\" style=\"font-weight:bold\">Note:</p>\n",
    "    The selection between vector graphics and rasterization needs to be made taking into account several factors such as how large is the dataset (i.e. how fine-resolution the data is), what data fidelity with the visualization is desired, what performance is expected, etc.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e486b87-54ad-476a-b724-398d989e8934",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "<div class=\"admonition alert alert-info\">\n",
    "    <p class=\"admonition-title\" style=\"font-weight:bold\">See also:</p>\n",
    "    A more comprehensive showcase of rasterization can be found <a href=\"https://learn.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-rasterizer-stage-rules\">here</a>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5d8786a7-8059-4fff-9af5-fba3b80ec8a3",
   "metadata": {
    "panel-layout": {
     "height": 84.3924,
     "visible": true,
     "width": 100
    }
   },
   "source": [
    "## What is next?\n",
    "Up next is the new chapter that will provide an Introduction to UXarray."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.12.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}