{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Examples\n",
    "\n",
    "Here's some examples of using the **antimeridian** package on some artificial and real-world data.\n",
    "\n",
    "## Test cases\n",
    "\n",
    "Our test suite exercises the antimeridian algorithm in a variety of ways.\n",
    "Here, we visualize some our test cases in two projections."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 201660 characters]",
      "text/plain": [
       "<Figure size 640x480 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 205248 characters]",
      "text/plain": [
       "<Figure size 640x480 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 217032 characters]",
      "text/plain": [
       "<Figure size 640x480 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 206268 characters]",
      "text/plain": [
       "<Figure size 640x480 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 228192 characters]",
      "text/plain": [
       "<Figure size 640x480 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import json\n",
    "import warnings\n",
    "from pathlib import Path\n",
    "from typing import Any\n",
    "\n",
    "import shapely.geometry\n",
    "from cartopy.crs import Mollweide, PlateCarree\n",
    "from cartopy.io import DownloadWarning\n",
    "from matplotlib import pyplot\n",
    "\n",
    "import antimeridian\n",
    "\n",
    "warnings.filterwarnings(\"ignore\", category=DownloadWarning)\n",
    "\n",
    "\n",
    "def read_json(path: Path) -> dict[str, Any]:\n",
    "    with open(path) as f:\n",
    "        return json.load(f)\n",
    "\n",
    "\n",
    "def plot(name: str, fix_winding: bool = True, suptitle: str | None = None) -> None:\n",
    "    data = read_json(f\"../tests/data/input/{name}.json\")\n",
    "    input = shapely.geometry.shape(data)\n",
    "    output = shapely.geometry.shape(\n",
    "        antimeridian.fix_geojson(data, fix_winding=fix_winding)\n",
    "    )\n",
    "\n",
    "    if suptitle is None:\n",
    "        suptitle = name\n",
    "\n",
    "    figure = pyplot.figure()\n",
    "    figure.suptitle(suptitle)\n",
    "\n",
    "    axes = figure.add_subplot(2, 2, 1, projection=PlateCarree())\n",
    "    axes.set_title(\"Original in PlateCarree\")\n",
    "    axes.stock_img()\n",
    "    axes.coastlines()\n",
    "    axes.add_geometries(input, crs=PlateCarree(), color=\"coral\", alpha=0.7)\n",
    "\n",
    "    axes = figure.add_subplot(2, 2, 2, projection=PlateCarree())\n",
    "    axes.set_title(\"Fixed in PlateCarree\")\n",
    "    axes.stock_img()\n",
    "    axes.coastlines()\n",
    "    axes.add_geometries(output, crs=PlateCarree(), color=\"coral\", alpha=0.7)\n",
    "\n",
    "    axes = figure.add_subplot(2, 2, 3, projection=Mollweide(central_longitude=180))\n",
    "    axes.set_title(\"Original in Mollweide\")\n",
    "    axes.stock_img()\n",
    "    axes.coastlines()\n",
    "    axes.add_geometries(input, crs=PlateCarree(), color=\"coral\", alpha=0.7)\n",
    "\n",
    "    axes = figure.add_subplot(2, 2, 4, projection=Mollweide(central_longitude=180))\n",
    "    axes.set_title(\"Fixed in Mollweide\")\n",
    "    axes.stock_img()\n",
    "    axes.coastlines()\n",
    "    axes.add_geometries(output, crs=PlateCarree(), color=\"coral\", alpha=0.7)\n",
    "\n",
    "    pyplot.show()\n",
    "\n",
    "\n",
    "for name in [\n",
    "    \"split\",\n",
    "    \"north-pole\",\n",
    "    \"complex-split\",\n",
    "    \"multi-split\",\n",
    "    \"overlap\",\n",
    "]:\n",
    "    plot(name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Winding order\n",
    "\n",
    "The exterior ring of a GeoJSON Polygon _should_ be wound counter-clockwise.\n",
    "Taken literally, this means that a clockwise-wound polygon would be a hole in a large polygon that encloses both poles.\n",
    "However, in practice, it is common for polygons to be wound incorrectly (e.g. [#29](https://github.com/gadomski/antimeridian/issues/29) and [#32](https://github.com/gadomski/antimeridian/issues/32)).\n",
    "Our package therefore defaults to correcting the winding order to be counter-clockwise, and only creates these pole-encompassing polygons if explicitly asked.\n",
    "\n",
    "Most GIS software will automatically fix clockwise exterior polygons, and so it can be hard to know if your Polygon is wound correctly without inspecting the points themselves."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/gadomski/Code/gadomski/antimeridian/src/antimeridian/_implementation.py:594: FixWindingWarning: The exterior ring of this shape is wound clockwise. Since this is a common error in real-world geometries, this package is reversing the exterior coordinates of the input shape before running its algorithm. If you know that your input shape is correct (i.e. if your data encompasses both poles), pass `fix_winding=False`.\n",
      "  FixWindingWarning.warn()\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 202832 characters]",
      "text/plain": [
       "<Figure size 640x480 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 226172 characters]",
      "text/plain": [
       "<Figure size 640x480 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot(\"cw-split\", fix_winding=True, suptitle=\"Fix winding\")\n",
    "plot(\"cw-split\", fix_winding=False, suptitle=\"No fix winding\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "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": 2
}
