{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Polygon Simplification" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Basic simplification:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import skgeom as sg\n", "poly = sg.random_polygon(30, seed=3)\n", "poly" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`simplify` tries to remove a given portion of the vertices without changing the topology:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sg.draw.draw(poly, facecolor=\"white\", alpha=0.4)\n", "res = sg.simplify(poly, 0.5) # try to remove 50% of the vertices\n", "sg.draw.draw(res, alpha=0.85)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sg.draw.draw(poly, facecolor=\"red\")\n", "sg.simplify(poly, 0.2) # try to remove 80% of the vertices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`simplify` works on `Polygon`, `PolygonWithHoles` and `PolygonSet`. You can also apply `simplify` on lists of polygons." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "poly_set = sg.PolygonSet([sg.random_polygon(10, seed=4), sg.random_polygon(40, seed=3)])\n", "sg.draw.draw(poly_set, facecolor=\"red\")\n", "sg.simplify(poly_set, 0.5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Simplification Modes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`simplify` currently supports three modes:\n", "* \"ratio\": try to reduce number of vertices to a given ratio of the original count\n", "* \"count\": try to reduce number of vertices to an absolute number\n", "* \"sqeuclidean\": try to reduce number of vertices until the error (squared euclidean distance) becomes too big" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sg.draw.draw(poly, facecolor=\"red\")\n", "sg.simplify(poly, 0.5, \"ratio\") # try to remove 50% of vertices" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sg.draw.draw(poly, facecolor=\"red\")\n", "sg.simplify(poly, 0.2, \"sqeuclidean\") # try to remove while err (sq. distance) < 0.2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In general, all modes are targets that might not be met:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "len(poly.coords)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "len(sg.simplify(poly, 0.5, \"ratio\").coords)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "len(sg.simplify(poly, 0.25, \"ratio\").coords)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "len(sg.simplify(poly, 5, \"count\").coords)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Simplification and Topology" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By default, `simplify` tries to preserve topology." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from skgeom import boolean_set\n", "poly = boolean_set.difference(\n", " sg.random_polygon(20, size=4, seed=4234),\n", " sg.random_polygon(20, size=1, seed=8421))[0]\n", "poly" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By preserving topology, features like holes will not get lost:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "poly2 = sg. simplify(poly, 0.2, \"ratio\") # try to remove 50% of vertices\n", "poly2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Turning off `preserve_topology` is much faster, but might destroy structural features:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "poly2 = sg. simplify(poly, 0.2, \"ratio\", preserve_topology=False)\n", "poly2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`preserve_topology` implies limits to how much simplifcation can happen:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "poly2 = sg. simplify(poly, 1, \"count\")\n", "poly2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "poly2 = sg.simplify(poly, 1, \"count\", preserve_topology=False)\n", "poly2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### More Topology Examples" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nested = [sg.random_polygon(15, shape=\"circle\", size=r ** 3, seed=r * 5) for r in range(3, 10)]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def draw_nested(nested):\n", " for p in reversed(nested):\n", " sg.draw.draw(p)\n", " \n", "draw_nested(nested)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "draw_nested(sg.simplify(nested, 0.3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "with defaults, forms have been simplified while preserving topology:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def n_vertices(nested):\n", " return sum(len(p) for p in nested)\n", "\n", "(n_vertices(nested), n_vertices([p.outer_boundary() for p in sg.simplify(nested, 0.3)]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "same call without preserving topology:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "draw_nested(sg.simplify(nested, 0.3, preserve_topology=False))" ] } ], "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.3" } }, "nbformat": 4, "nbformat_minor": 4 }