commit 8b5aa1913e54f548064851b676883c72c5a81acd
parent 75dfd3d8928ea08df5f0cc5a2a614f68ac457917
Author: Yuval Langer <yuvallangerontheroad@gmail.com>
Date: Fri, 5 Jun 2020 19:52:12 +0300
Add Hilbert curve curve.
Diffstat:
5 files changed, 121 insertions(+), 30 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,2 +1,4 @@
dabbling.egg-info
dabbling/__pycache__
+*.png
+*.svg
diff --git a/dabbling/console.py b/dabbling/console.py
@@ -2,6 +2,7 @@ import click
from . import __version__
from .dragon_curve import dragon_curve, path_to_curvy_svg_no_clue, path_to_svg_file_content, write_matplotlib_png
+from .hilbert_curve import hilbert_curve, make_svg_content
@click.command()
@@ -14,7 +15,7 @@ from .dragon_curve import dragon_curve, path_to_curvy_svg_no_clue, path_to_svg_f
show_default=True,
)
@click.version_option(version=__version__)
-def main(iterations: str):
+def main_dragon(iterations: str):
l = dragon_curve(int(iterations))
svg_content = path_to_svg_file_content(l)
@@ -28,3 +29,21 @@ def main(iterations: str):
write_matplotlib_png(l)
click.echo(l)
+
+
+@click.command()
+@click.option(
+ '--iterations',
+ '-n',
+ default='5',
+ help='Number of iterations',
+ metavar='ITERS',
+ show_default=True,
+)
+@click.version_option(version=__version__)
+def main_hilbert(iterations: str):
+ l = hilbert_curve(int(iterations))
+
+ svg_content = make_svg_content(l)
+ with open('hilbert-curve.svg', 'w') as f:
+ f.write(svg_content)
diff --git a/dabbling/hilbert_curve.py b/dabbling/hilbert_curve.py
@@ -0,0 +1,69 @@
+def mirror_on_y(path):
+ max_x = max(p[0] for p in path)
+ return [(abs(p[0] - max_x), p[1]) for p in path]
+
+
+def mirror_on_x(path):
+ max_y = max(p[1] for p in path)
+ return [(p[0], abs(p[1] - max_y)) for p in path]
+
+
+def mirror_on_xy(path):
+ return [(p[1], p[0]) for p in path]
+
+
+def right_flip(path):
+ path = mirror_on_y(path)
+ path = [(p[1], p[0]) for p in path]
+ path = mirror_on_y(path)
+
+ return path
+
+
+def left_flip(path):
+ return [(p[1], p[0]) for p in path]
+
+
+def hilbert_curve(iterations=3):
+ curve_coordinates = [
+ (0, 0),
+ (0, 1),
+ (1, 1),
+ (1, 0),
+ ]
+
+ for i in range(iterations):
+ curve_coordinates = (
+ left_flip(curve_coordinates) +
+ [(p[0], p[1] + 2 ** (i + 1)) for p in curve_coordinates] +
+ [(p[0] + 2 ** (i + 1), p[1] + 2 ** (i + 1)) for p in curve_coordinates] +
+ [(p[0] + 2 ** (i + 1), p[1]) for p in right_flip(curve_coordinates)]
+ )
+
+ return curve_coordinates
+
+
+def make_svg_content(
+ path,
+ image_width = 500,
+ image_height = 500,
+ ):
+ min_x = min(p[0] for p in path)
+ min_y = min(p[1] for p in path)
+ max_x = max(p[0] for p in path)
+ max_y = max(p[1] for p in path)
+ path = mirror_on_x(path)
+ stroke_width = min(0.1 * max_x, 0.1)
+ svg_path = f'M{path[0][0]} {path[0][1]}' + ''.join(f'L{p[0]} {p[1]}' for p in path)
+ return f'''
+<svg width="{image_width}" height="{image_height}" viewBox="0 0 {max_x} {max_y}" fill="white" xmlns="http://www.w3.org/2000/svg">
+ <path stroke="black" stroke-width="{stroke_width}" d="{svg_path}"/>
+</svg>'''
+
+
+if __name__ == '__main__':
+ import sys
+ path = hilbert_curve(int(sys.argv[1]))
+ svg_content = make_svg_content(path)
+ with open('hilbert-curve.svg', 'w') as f:
+ f.write(svg_content)
diff --git a/poetry.lock b/poetry.lock
@@ -478,7 +478,7 @@ description = "NumPy is the fundamental package for array computing with Python.
name = "numpy"
optional = false
python-versions = ">=3.5"
-version = "1.18.4"
+version = "1.18.5"
[[package]]
category = "main"
@@ -637,7 +637,7 @@ description = "pytest: simple powerful testing with Python"
name = "pytest"
optional = false
python-versions = ">=3.5"
-version = "5.4.2"
+version = "5.4.3"
[package.dependencies]
atomicwrites = ">=1.0"
@@ -841,7 +841,7 @@ description = "Measures the displayed width of unicode strings in a terminal"
name = "wcwidth"
optional = false
python-versions = "*"
-version = "0.2.2"
+version = "0.2.3"
[[package]]
category = "main"
@@ -1080,27 +1080,27 @@ notebook = [
{file = "notebook-6.0.3.tar.gz", hash = "sha256:47a9092975c9e7965ada00b9a20f0cf637d001db60d241d479f53c0be117ad48"},
]
numpy = [
- {file = "numpy-1.18.4-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:efdba339fffb0e80fcc19524e4fdbda2e2b5772ea46720c44eaac28096d60720"},
- {file = "numpy-1.18.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2b573fcf6f9863ce746e4ad00ac18a948978bb3781cffa4305134d31801f3e26"},
- {file = "numpy-1.18.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:3f0dae97e1126f529ebb66f3c63514a0f72a177b90d56e4bce8a0b5def34627a"},
- {file = "numpy-1.18.4-cp35-cp35m-win32.whl", hash = "sha256:dccd380d8e025c867ddcb2f84b439722cf1f23f3a319381eac45fd077dee7170"},
- {file = "numpy-1.18.4-cp35-cp35m-win_amd64.whl", hash = "sha256:02ec9582808c4e48be4e93cd629c855e644882faf704bc2bd6bbf58c08a2a897"},
- {file = "numpy-1.18.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:904b513ab8fbcbdb062bed1ce2f794ab20208a1b01ce9bd90776c6c7e7257032"},
- {file = "numpy-1.18.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:e22cd0f72fc931d6abc69dc7764484ee20c6a60b0d0fee9ce0426029b1c1bdae"},
- {file = "numpy-1.18.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2466fbcf23711ebc5daa61d28ced319a6159b260a18839993d871096d66b93f7"},
- {file = "numpy-1.18.4-cp36-cp36m-win32.whl", hash = "sha256:00d7b54c025601e28f468953d065b9b121ddca7fff30bed7be082d3656dd798d"},
- {file = "numpy-1.18.4-cp36-cp36m-win_amd64.whl", hash = "sha256:7d59f21e43bbfd9a10953a7e26b35b6849d888fc5a331fa84a2d9c37bd9fe2a2"},
- {file = "numpy-1.18.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:efb7ac5572c9a57159cf92c508aad9f856f1cb8e8302d7fdb99061dbe52d712c"},
- {file = "numpy-1.18.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0e6f72f7bb08f2f350ed4408bb7acdc0daba637e73bce9f5ea2b207039f3af88"},
- {file = "numpy-1.18.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:9933b81fecbe935e6a7dc89cbd2b99fea1bf362f2790daf9422a7bb1dc3c3085"},
- {file = "numpy-1.18.4-cp37-cp37m-win32.whl", hash = "sha256:96dd36f5cdde152fd6977d1bbc0f0561bccffecfde63cd397c8e6033eb66baba"},
- {file = "numpy-1.18.4-cp37-cp37m-win_amd64.whl", hash = "sha256:57aea170fb23b1fd54fa537359d90d383d9bf5937ee54ae8045a723caa5e0961"},
- {file = "numpy-1.18.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ed722aefb0ebffd10b32e67f48e8ac4c5c4cf5d3a785024fdf0e9eb17529cd9d"},
- {file = "numpy-1.18.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:50fb72bcbc2cf11e066579cb53c4ca8ac0227abb512b6cbc1faa02d1595a2a5d"},
- {file = "numpy-1.18.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:709c2999b6bd36cdaf85cf888d8512da7433529f14a3689d6e37ab5242e7add5"},
- {file = "numpy-1.18.4-cp38-cp38-win32.whl", hash = "sha256:f22273dd6a403ed870207b853a856ff6327d5cbce7a835dfa0645b3fc00273ec"},
- {file = "numpy-1.18.4-cp38-cp38-win_amd64.whl", hash = "sha256:1be2e96314a66f5f1ce7764274327fd4fb9da58584eaff00b5a5221edefee7d6"},
- {file = "numpy-1.18.4.zip", hash = "sha256:bbcc85aaf4cd84ba057decaead058f43191cc0e30d6bc5d44fe336dc3d3f4509"},
+ {file = "numpy-1.18.5-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:e91d31b34fc7c2c8f756b4e902f901f856ae53a93399368d9a0dc7be17ed2ca0"},
+ {file = "numpy-1.18.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:7d42ab8cedd175b5ebcb39b5208b25ba104842489ed59fbb29356f671ac93583"},
+ {file = "numpy-1.18.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a78e438db8ec26d5d9d0e584b27ef25c7afa5a182d1bf4d05e313d2d6d515271"},
+ {file = "numpy-1.18.5-cp35-cp35m-win32.whl", hash = "sha256:a87f59508c2b7ceb8631c20630118cc546f1f815e034193dc72390db038a5cb3"},
+ {file = "numpy-1.18.5-cp35-cp35m-win_amd64.whl", hash = "sha256:965df25449305092b23d5145b9bdaeb0149b6e41a77a7d728b1644b3c99277c1"},
+ {file = "numpy-1.18.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ac792b385d81151bae2a5a8adb2b88261ceb4976dbfaaad9ce3a200e036753dc"},
+ {file = "numpy-1.18.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:ef627986941b5edd1ed74ba89ca43196ed197f1a206a3f18cc9faf2fb84fd675"},
+ {file = "numpy-1.18.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f718a7949d1c4f622ff548c572e0c03440b49b9531ff00e4ed5738b459f011e8"},
+ {file = "numpy-1.18.5-cp36-cp36m-win32.whl", hash = "sha256:4064f53d4cce69e9ac613256dc2162e56f20a4e2d2086b1956dd2fcf77b7fac5"},
+ {file = "numpy-1.18.5-cp36-cp36m-win_amd64.whl", hash = "sha256:b03b2c0badeb606d1232e5f78852c102c0a7989d3a534b3129e7856a52f3d161"},
+ {file = "numpy-1.18.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a7acefddf994af1aeba05bbbafe4ba983a187079f125146dc5859e6d817df824"},
+ {file = "numpy-1.18.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cd49930af1d1e49a812d987c2620ee63965b619257bd76eaaa95870ca08837cf"},
+ {file = "numpy-1.18.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:b39321f1a74d1f9183bf1638a745b4fd6fe80efbb1f6b32b932a588b4bc7695f"},
+ {file = "numpy-1.18.5-cp37-cp37m-win32.whl", hash = "sha256:cae14a01a159b1ed91a324722d746523ec757357260c6804d11d6147a9e53e3f"},
+ {file = "numpy-1.18.5-cp37-cp37m-win_amd64.whl", hash = "sha256:0172304e7d8d40e9e49553901903dc5f5a49a703363ed756796f5808a06fc233"},
+ {file = "numpy-1.18.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e15b382603c58f24265c9c931c9a45eebf44fe2e6b4eaedbb0d025ab3255228b"},
+ {file = "numpy-1.18.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3676abe3d621fc467c4c1469ee11e395c82b2d6b5463a9454e37fe9da07cd0d7"},
+ {file = "numpy-1.18.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4674f7d27a6c1c52a4d1aa5f0881f1eff840d2206989bae6acb1c7668c02ebfb"},
+ {file = "numpy-1.18.5-cp38-cp38-win32.whl", hash = "sha256:9c9d6531bc1886454f44aa8f809268bc481295cf9740827254f53c30104f074a"},
+ {file = "numpy-1.18.5-cp38-cp38-win_amd64.whl", hash = "sha256:3dd6823d3e04b5f223e3e265b4a1eae15f104f4366edd409e5a5e413a98f911f"},
+ {file = "numpy-1.18.5.zip", hash = "sha256:34e96e9dae65c4839bd80012023aadd6ee2ccb73ce7fdf3074c62f301e63120b"},
]
packaging = [
{file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"},
@@ -1171,8 +1171,8 @@ pyrsistent = [
{file = "pyrsistent-0.16.0.tar.gz", hash = "sha256:28669905fe725965daa16184933676547c5bb40a5153055a8dee2a4bd7933ad3"},
]
pytest = [
- {file = "pytest-5.4.2-py3-none-any.whl", hash = "sha256:95c710d0a72d91c13fae35dce195633c929c3792f54125919847fdcdf7caa0d3"},
- {file = "pytest-5.4.2.tar.gz", hash = "sha256:eb2b5e935f6a019317e455b6da83dd8650ac9ffd2ee73a7b657a30873d67a698"},
+ {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"},
+ {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"},
]
python-dateutil = [
{file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"},
@@ -1290,8 +1290,8 @@ urllib3 = [
{file = "urllib3-1.25.9.tar.gz", hash = "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527"},
]
wcwidth = [
- {file = "wcwidth-0.2.2-py2.py3-none-any.whl", hash = "sha256:b651b6b081476420e4e9ae61239ac4c1b49d0c5ace42b2e81dc2ff49ed50c566"},
- {file = "wcwidth-0.2.2.tar.gz", hash = "sha256:3de2e41158cb650b91f9654cbf9a3e053cee0719c9df4ddc11e4b568669e9829"},
+ {file = "wcwidth-0.2.3-py2.py3-none-any.whl", hash = "sha256:980fbf4f3c196c0f329cdcd1e84c554d6a211f18e252e525a0cf4223154a41d6"},
+ {file = "wcwidth-0.2.3.tar.gz", hash = "sha256:edbc2b718b4db6cdf393eefe3a420183947d6aa312505ce6754516f458ff8830"},
]
webencodings = [
{file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"},
diff --git a/pyproject.toml b/pyproject.toml
@@ -23,4 +23,5 @@ requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
[tool.poetry.scripts]
-dragon-curve = "dabbling.console:main"
+dragon-curve = "dabbling.console:main_dragon"
+hilbert-curve = "dabbling.console:main_hilbert"