spyrrow 0.4.0__tar.gz → 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of spyrrow might be problematic. Click here for more details.
- {spyrrow-0.4.0 → spyrrow-0.6.0}/Cargo.lock +180 -11
- {spyrrow-0.4.0 → spyrrow-0.6.0}/Cargo.toml +3 -3
- {spyrrow-0.4.0 → spyrrow-0.6.0}/PKG-INFO +3 -3
- {spyrrow-0.4.0 → spyrrow-0.6.0}/README.md +2 -2
- {spyrrow-0.4.0 → spyrrow-0.6.0}/docs/conf.py +1 -1
- {spyrrow-0.4.0 → spyrrow-0.6.0}/docs/index.rst +16 -3
- {spyrrow-0.4.0 → spyrrow-0.6.0}/spyrrow.pyi +18 -22
- {spyrrow-0.4.0 → spyrrow-0.6.0}/src/lib.rs +49 -41
- {spyrrow-0.4.0 → spyrrow-0.6.0}/tests/test_basic.py +24 -8
- {spyrrow-0.4.0 → spyrrow-0.6.0}/.github/workflows/CI.yml +0 -0
- {spyrrow-0.4.0 → spyrrow-0.6.0}/.gitignore +0 -0
- {spyrrow-0.4.0 → spyrrow-0.6.0}/.readthedocs.yaml +0 -0
- {spyrrow-0.4.0 → spyrrow-0.6.0}/LICENSE.txt +0 -0
- {spyrrow-0.4.0 → spyrrow-0.6.0}/docs/Makefile +0 -0
- {spyrrow-0.4.0 → spyrrow-0.6.0}/docs/api.rst +0 -0
- {spyrrow-0.4.0 → spyrrow-0.6.0}/docs/make.bat +0 -0
- {spyrrow-0.4.0 → spyrrow-0.6.0}/pyproject.toml +0 -0
- {spyrrow-0.4.0 → spyrrow-0.6.0}/tests/utils.py +0 -0
- {spyrrow-0.4.0 → spyrrow-0.6.0}/uv.lock +0 -0
|
@@ -58,6 +58,24 @@ version = "1.0.98"
|
|
|
58
58
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
59
59
|
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
|
60
60
|
|
|
61
|
+
[[package]]
|
|
62
|
+
name = "approx"
|
|
63
|
+
version = "0.5.1"
|
|
64
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
65
|
+
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
|
66
|
+
dependencies = [
|
|
67
|
+
"num-traits",
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
[[package]]
|
|
71
|
+
name = "atomic-polyfill"
|
|
72
|
+
version = "1.0.3"
|
|
73
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
74
|
+
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
|
|
75
|
+
dependencies = [
|
|
76
|
+
"critical-section",
|
|
77
|
+
]
|
|
78
|
+
|
|
61
79
|
[[package]]
|
|
62
80
|
name = "autocfg"
|
|
63
81
|
version = "1.4.0"
|
|
@@ -70,6 +88,12 @@ version = "2.9.0"
|
|
|
70
88
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
71
89
|
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
|
72
90
|
|
|
91
|
+
[[package]]
|
|
92
|
+
name = "byteorder"
|
|
93
|
+
version = "1.5.0"
|
|
94
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
95
|
+
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|
96
|
+
|
|
73
97
|
[[package]]
|
|
74
98
|
name = "cfg-if"
|
|
75
99
|
version = "1.0.0"
|
|
@@ -128,6 +152,12 @@ version = "1.0.3"
|
|
|
128
152
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
129
153
|
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
|
130
154
|
|
|
155
|
+
[[package]]
|
|
156
|
+
name = "critical-section"
|
|
157
|
+
version = "1.2.0"
|
|
158
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
159
|
+
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
|
160
|
+
|
|
131
161
|
[[package]]
|
|
132
162
|
name = "crossbeam-deque"
|
|
133
163
|
version = "0.8.6"
|
|
@@ -202,6 +232,58 @@ dependencies = [
|
|
|
202
232
|
"num-traits",
|
|
203
233
|
]
|
|
204
234
|
|
|
235
|
+
[[package]]
|
|
236
|
+
name = "float_next_after"
|
|
237
|
+
version = "1.0.0"
|
|
238
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
239
|
+
checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8"
|
|
240
|
+
|
|
241
|
+
[[package]]
|
|
242
|
+
name = "geo"
|
|
243
|
+
version = "0.24.1"
|
|
244
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
245
|
+
checksum = "c7d640a4dd1d1c98b45f4653c841a8ec15f461a71b86bc30533ae64c6f20f268"
|
|
246
|
+
dependencies = [
|
|
247
|
+
"float_next_after",
|
|
248
|
+
"geo-types",
|
|
249
|
+
"geographiclib-rs",
|
|
250
|
+
"log",
|
|
251
|
+
"num-traits",
|
|
252
|
+
"robust",
|
|
253
|
+
"rstar",
|
|
254
|
+
]
|
|
255
|
+
|
|
256
|
+
[[package]]
|
|
257
|
+
name = "geo-buffer"
|
|
258
|
+
version = "0.2.0"
|
|
259
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
260
|
+
checksum = "267bf0373df2f0b0b05065ebc0c84b97ccd221e19e0cb9442bcffe8fce04c130"
|
|
261
|
+
dependencies = [
|
|
262
|
+
"geo",
|
|
263
|
+
"geo-types",
|
|
264
|
+
]
|
|
265
|
+
|
|
266
|
+
[[package]]
|
|
267
|
+
name = "geo-types"
|
|
268
|
+
version = "0.7.16"
|
|
269
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
270
|
+
checksum = "62ddb1950450d67efee2bbc5e429c68d052a822de3aad010d28b351fbb705224"
|
|
271
|
+
dependencies = [
|
|
272
|
+
"approx",
|
|
273
|
+
"num-traits",
|
|
274
|
+
"rstar",
|
|
275
|
+
"serde",
|
|
276
|
+
]
|
|
277
|
+
|
|
278
|
+
[[package]]
|
|
279
|
+
name = "geographiclib-rs"
|
|
280
|
+
version = "0.2.5"
|
|
281
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
282
|
+
checksum = "f611040a2bb37eaa29a78a128d1e92a378a03e0b6e66ae27398d42b1ba9a7841"
|
|
283
|
+
dependencies = [
|
|
284
|
+
"libm",
|
|
285
|
+
]
|
|
286
|
+
|
|
205
287
|
[[package]]
|
|
206
288
|
name = "getrandom"
|
|
207
289
|
version = "0.3.2"
|
|
@@ -214,6 +296,28 @@ dependencies = [
|
|
|
214
296
|
"wasi",
|
|
215
297
|
]
|
|
216
298
|
|
|
299
|
+
[[package]]
|
|
300
|
+
name = "hash32"
|
|
301
|
+
version = "0.2.1"
|
|
302
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
303
|
+
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
|
|
304
|
+
dependencies = [
|
|
305
|
+
"byteorder",
|
|
306
|
+
]
|
|
307
|
+
|
|
308
|
+
[[package]]
|
|
309
|
+
name = "heapless"
|
|
310
|
+
version = "0.7.17"
|
|
311
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
312
|
+
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
|
|
313
|
+
dependencies = [
|
|
314
|
+
"atomic-polyfill",
|
|
315
|
+
"hash32",
|
|
316
|
+
"rustc_version",
|
|
317
|
+
"spin",
|
|
318
|
+
"stable_deref_trait",
|
|
319
|
+
]
|
|
320
|
+
|
|
217
321
|
[[package]]
|
|
218
322
|
name = "heck"
|
|
219
323
|
version = "0.5.0"
|
|
@@ -255,12 +359,14 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
|
|
255
359
|
|
|
256
360
|
[[package]]
|
|
257
361
|
name = "jagua-rs"
|
|
258
|
-
version = "0.
|
|
259
|
-
source = "git+https://github.com/JeroenGar/jagua-rs.git?rev=
|
|
362
|
+
version = "0.6.2"
|
|
363
|
+
source = "git+https://github.com/JeroenGar/jagua-rs.git?rev=6e47329e4fd8dfe014428bd9045db132d26d35c9#6e47329e4fd8dfe014428bd9045db132d26d35c9"
|
|
260
364
|
dependencies = [
|
|
261
365
|
"anyhow",
|
|
262
366
|
"document-features",
|
|
263
367
|
"float-cmp",
|
|
368
|
+
"geo-buffer",
|
|
369
|
+
"geo-types",
|
|
264
370
|
"itertools",
|
|
265
371
|
"log",
|
|
266
372
|
"ndarray",
|
|
@@ -270,7 +376,6 @@ dependencies = [
|
|
|
270
376
|
"serde",
|
|
271
377
|
"slotmap",
|
|
272
378
|
"svg",
|
|
273
|
-
"tribool",
|
|
274
379
|
]
|
|
275
380
|
|
|
276
381
|
[[package]]
|
|
@@ -332,6 +437,16 @@ version = "0.4.1"
|
|
|
332
437
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
333
438
|
checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
|
|
334
439
|
|
|
440
|
+
[[package]]
|
|
441
|
+
name = "lock_api"
|
|
442
|
+
version = "0.4.13"
|
|
443
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
444
|
+
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
|
|
445
|
+
dependencies = [
|
|
446
|
+
"autocfg",
|
|
447
|
+
"scopeguard",
|
|
448
|
+
]
|
|
449
|
+
|
|
335
450
|
[[package]]
|
|
336
451
|
name = "log"
|
|
337
452
|
version = "0.4.27"
|
|
@@ -630,12 +745,50 @@ dependencies = [
|
|
|
630
745
|
"crossbeam-utils",
|
|
631
746
|
]
|
|
632
747
|
|
|
748
|
+
[[package]]
|
|
749
|
+
name = "robust"
|
|
750
|
+
version = "0.2.3"
|
|
751
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
752
|
+
checksum = "e5864e7ef1a6b7bcf1d6ca3f655e65e724ed3b52546a0d0a663c991522f552ea"
|
|
753
|
+
|
|
754
|
+
[[package]]
|
|
755
|
+
name = "rstar"
|
|
756
|
+
version = "0.10.0"
|
|
757
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
758
|
+
checksum = "1f39465655a1e3d8ae79c6d9e007f4953bfc5d55297602df9dc38f9ae9f1359a"
|
|
759
|
+
dependencies = [
|
|
760
|
+
"heapless",
|
|
761
|
+
"num-traits",
|
|
762
|
+
"smallvec",
|
|
763
|
+
]
|
|
764
|
+
|
|
765
|
+
[[package]]
|
|
766
|
+
name = "rustc_version"
|
|
767
|
+
version = "0.4.1"
|
|
768
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
769
|
+
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
|
770
|
+
dependencies = [
|
|
771
|
+
"semver",
|
|
772
|
+
]
|
|
773
|
+
|
|
633
774
|
[[package]]
|
|
634
775
|
name = "ryu"
|
|
635
776
|
version = "1.0.20"
|
|
636
777
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
637
778
|
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
|
638
779
|
|
|
780
|
+
[[package]]
|
|
781
|
+
name = "scopeguard"
|
|
782
|
+
version = "1.2.0"
|
|
783
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
784
|
+
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|
785
|
+
|
|
786
|
+
[[package]]
|
|
787
|
+
name = "semver"
|
|
788
|
+
version = "1.0.26"
|
|
789
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
790
|
+
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
|
|
791
|
+
|
|
639
792
|
[[package]]
|
|
640
793
|
name = "serde"
|
|
641
794
|
version = "1.0.219"
|
|
@@ -677,10 +830,16 @@ dependencies = [
|
|
|
677
830
|
"version_check",
|
|
678
831
|
]
|
|
679
832
|
|
|
833
|
+
[[package]]
|
|
834
|
+
name = "smallvec"
|
|
835
|
+
version = "1.15.1"
|
|
836
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
837
|
+
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
|
838
|
+
|
|
680
839
|
[[package]]
|
|
681
840
|
name = "sparrow"
|
|
682
841
|
version = "0.1.0"
|
|
683
|
-
source = "git+https://github.com/JeroenGar/sparrow.git?rev=
|
|
842
|
+
source = "git+https://github.com/JeroenGar/sparrow.git?rev=7f069e9d146f5599d7ba69a47ab4e8097c56e54f#7f069e9d146f5599d7ba69a47ab4e8097c56e54f"
|
|
684
843
|
dependencies = [
|
|
685
844
|
"anyhow",
|
|
686
845
|
"clap",
|
|
@@ -691,6 +850,7 @@ dependencies = [
|
|
|
691
850
|
"jagua-rs",
|
|
692
851
|
"jiff",
|
|
693
852
|
"log",
|
|
853
|
+
"ndarray",
|
|
694
854
|
"num_cpus",
|
|
695
855
|
"numfmt",
|
|
696
856
|
"ordered-float",
|
|
@@ -705,9 +865,18 @@ dependencies = [
|
|
|
705
865
|
"test-case",
|
|
706
866
|
]
|
|
707
867
|
|
|
868
|
+
[[package]]
|
|
869
|
+
name = "spin"
|
|
870
|
+
version = "0.9.8"
|
|
871
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
872
|
+
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
|
873
|
+
dependencies = [
|
|
874
|
+
"lock_api",
|
|
875
|
+
]
|
|
876
|
+
|
|
708
877
|
[[package]]
|
|
709
878
|
name = "spyrrow"
|
|
710
|
-
version = "0.
|
|
879
|
+
version = "0.6.0"
|
|
711
880
|
dependencies = [
|
|
712
881
|
"jagua-rs",
|
|
713
882
|
"pyo3",
|
|
@@ -717,6 +886,12 @@ dependencies = [
|
|
|
717
886
|
"sparrow",
|
|
718
887
|
]
|
|
719
888
|
|
|
889
|
+
[[package]]
|
|
890
|
+
name = "stable_deref_trait"
|
|
891
|
+
version = "1.2.0"
|
|
892
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
893
|
+
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
|
894
|
+
|
|
720
895
|
[[package]]
|
|
721
896
|
name = "strsim"
|
|
722
897
|
version = "0.11.1"
|
|
@@ -785,12 +960,6 @@ dependencies = [
|
|
|
785
960
|
"test-case-core",
|
|
786
961
|
]
|
|
787
962
|
|
|
788
|
-
[[package]]
|
|
789
|
-
name = "tribool"
|
|
790
|
-
version = "0.3.0"
|
|
791
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
792
|
-
checksum = "1e8660361502033a51e119386b47fbb811e5706722f2e91ccf867aa6b2b09f90"
|
|
793
|
-
|
|
794
963
|
[[package]]
|
|
795
964
|
name = "unicode-ident"
|
|
796
965
|
version = "1.0.18"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "spyrrow"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.6.0"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
license = "MIT"
|
|
6
6
|
|
|
@@ -10,9 +10,9 @@ name = "spyrrow"
|
|
|
10
10
|
crate-type = ["cdylib"]
|
|
11
11
|
|
|
12
12
|
[dependencies]
|
|
13
|
-
jagua-rs = { git = "https://github.com/JeroenGar/jagua-rs.git", rev="
|
|
13
|
+
jagua-rs = { git = "https://github.com/JeroenGar/jagua-rs.git", rev="6e47329e4fd8dfe014428bd9045db132d26d35c9", features = ["spp"], default-features = false}
|
|
14
14
|
pyo3 = "0.24.0"
|
|
15
15
|
rand = { version = "0.9.0", features = ["small_rng"] }
|
|
16
16
|
serde = {version = "1.0.219", features = ["derive"]}
|
|
17
17
|
serde_json = "1.0.140"
|
|
18
|
-
sparrow = { git = "https://github.com/JeroenGar/sparrow.git",rev="
|
|
18
|
+
sparrow = { git = "https://github.com/JeroenGar/sparrow.git",rev="7f069e9d146f5599d7ba69a47ab4e8097c56e54f",features = ["only_final_svg"], default-features = false}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spyrrow
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
@@ -35,10 +35,10 @@ pip install spyrrow
|
|
|
35
35
|
import spyrrow
|
|
36
36
|
|
|
37
37
|
rectangle1 = spyrrow.Item(
|
|
38
|
-
|
|
38
|
+
"rectangle", [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)], demand=4, allowed_orientations=[0]
|
|
39
39
|
)
|
|
40
40
|
triangle1 = spyrrow.Item(
|
|
41
|
-
|
|
41
|
+
"triangle",
|
|
42
42
|
[(0, 0), (1, 0), (1, 1), (0, 0)],
|
|
43
43
|
demand=6,
|
|
44
44
|
allowed_orientations=[0, 90, 180, -90],
|
|
@@ -21,10 +21,10 @@ pip install spyrrow
|
|
|
21
21
|
import spyrrow
|
|
22
22
|
|
|
23
23
|
rectangle1 = spyrrow.Item(
|
|
24
|
-
|
|
24
|
+
"rectangle", [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)], demand=4, allowed_orientations=[0]
|
|
25
25
|
)
|
|
26
26
|
triangle1 = spyrrow.Item(
|
|
27
|
-
|
|
27
|
+
"triangle",
|
|
28
28
|
[(0, 0), (1, 0), (1, 1), (0, 0)],
|
|
29
29
|
demand=6,
|
|
30
30
|
allowed_orientations=[0, 90, 180, -90],
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
project = 'spyrrow'
|
|
10
10
|
copyright = '2025, Paul Durand-Lupinski'
|
|
11
11
|
author = 'Paul Durand-Lupinski'
|
|
12
|
-
release = '0.
|
|
12
|
+
release = '0.5.0'
|
|
13
13
|
|
|
14
14
|
# -- General configuration ---------------------------------------------------
|
|
15
15
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
|
@@ -36,10 +36,10 @@ Examples
|
|
|
36
36
|
import spyrrow
|
|
37
37
|
|
|
38
38
|
rectangle1 = spyrrow.Item(
|
|
39
|
-
|
|
39
|
+
"rectangle", [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)], demand=4, allowed_orientations=[0]
|
|
40
40
|
)
|
|
41
41
|
triangle1 = spyrrow.Item(
|
|
42
|
-
|
|
42
|
+
"triangle",
|
|
43
43
|
[(0, 0), (1, 0), (1, 1), (0, 0)],
|
|
44
44
|
demand=6,
|
|
45
45
|
allowed_orientations=[0, 90, 180, -90],
|
|
@@ -54,4 +54,17 @@ Examples
|
|
|
54
54
|
print(pi.id)
|
|
55
55
|
print(pi.rotation)
|
|
56
56
|
print(pi.translation)
|
|
57
|
-
print("\n")
|
|
57
|
+
print("\n")
|
|
58
|
+
|
|
59
|
+
In order to express that an Item can rotate freely, its `allowed_orientations` attributes should be set to `None`.
|
|
60
|
+
|
|
61
|
+
.. code-block:: python
|
|
62
|
+
|
|
63
|
+
import spyrrow
|
|
64
|
+
|
|
65
|
+
triangle1 = spyrrow.Item(
|
|
66
|
+
"triangle",
|
|
67
|
+
[(0, 0), (1, 0), (1, 1), (0, 0)],
|
|
68
|
+
demand=6,
|
|
69
|
+
allowed_orientations=None,
|
|
70
|
+
)
|
|
@@ -3,52 +3,51 @@ from typing import TypeAlias
|
|
|
3
3
|
Point: TypeAlias = tuple[float, float]
|
|
4
4
|
|
|
5
5
|
class Item:
|
|
6
|
-
id:
|
|
6
|
+
id: str
|
|
7
7
|
demand: int
|
|
8
8
|
shape: list[Point]
|
|
9
9
|
allowed_orientations: list[float]
|
|
10
10
|
|
|
11
11
|
def __init__(
|
|
12
12
|
self,
|
|
13
|
-
id:
|
|
13
|
+
id: str,
|
|
14
14
|
shape: list[Point],
|
|
15
15
|
demand: int,
|
|
16
|
-
allowed_orientations: list[float],
|
|
16
|
+
allowed_orientations: list[float] | None,
|
|
17
17
|
):
|
|
18
18
|
"""
|
|
19
19
|
An Item represents any closed 2D shape by its outer boundary.
|
|
20
20
|
|
|
21
21
|
Spyrrow doesn't support hole(s) inside the shape as of yet. Therefore no Item can be nested inside another.
|
|
22
22
|
|
|
23
|
-
Continous rotation is not supported as of yet. A workaround is to specify any integer degrees between 0 and 360
|
|
24
|
-
to the allowed_orientations list.
|
|
25
|
-
|
|
26
23
|
Args:
|
|
27
|
-
id: The Item identifier
|
|
28
|
-
|
|
24
|
+
id (str): The Item identifier
|
|
25
|
+
Needs to be unique accross all Items of a StripPackingInstance
|
|
29
26
|
shape: An ordered list of (x,y) defining the shape boundary. The shape is represented as a polygon formed by this list of points.
|
|
30
27
|
The origin point can be included twice as the finishing point. If not, [last point, first point] is infered to be the last straight line of the shape.
|
|
31
28
|
demand: The quantity of identical Items to be placed inside the strip. Should be positive.
|
|
32
|
-
allowed_orientations: List of angles in degrees allowed.
|
|
29
|
+
allowed_orientations (list[float]|None): List of angles in degrees allowed.
|
|
30
|
+
An empty list is equivalent to [0.].
|
|
31
|
+
A None value means that the item is free to rotate
|
|
33
32
|
The algorithmn is only very weakly sensible to the length of the list given.
|
|
34
33
|
|
|
35
34
|
"""
|
|
36
|
-
|
|
37
|
-
def to_json_str(self)->str:
|
|
38
|
-
"""
|
|
35
|
+
|
|
36
|
+
def to_json_str(self) -> str:
|
|
37
|
+
"""Return a string of the JSON representation of the object"""
|
|
39
38
|
|
|
40
39
|
class PlacedItem:
|
|
41
40
|
"""
|
|
42
41
|
An object representing where a copy of an Item was placed inside the strip.
|
|
43
42
|
|
|
44
43
|
Attributes:
|
|
45
|
-
id (
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
id (str): The Item identifier referencing the items of the StripPackingInstance
|
|
45
|
+
rotation (float): The rotation angle in degrees, assuming that the original Item was defined with 0° as its rotation angle.
|
|
46
|
+
Use the origin (0.0,0.0) as the rotation point.
|
|
47
|
+
translation (tuple[float,float]): the translation vector in the X-Y axis. To apply after the rotation
|
|
48
48
|
"""
|
|
49
49
|
|
|
50
|
-
id:
|
|
51
|
-
shape: list[Point]
|
|
50
|
+
id: str
|
|
52
51
|
translation: Point
|
|
53
52
|
rotation: float
|
|
54
53
|
|
|
@@ -82,14 +81,11 @@ class StripPackingInstance:
|
|
|
82
81
|
An empty string '' can be used, if the user doesn't have a use for this name.
|
|
83
82
|
strip_height (float): the fixed height of the strip. The unit should be compatible with the Item
|
|
84
83
|
items (list[Item]): The Items which defines the instances. All Items should be defined with the same scale ( same length unit).
|
|
85
|
-
Items ids should be an increasing series starting at 0 until len(items)-1.
|
|
86
|
-
|
|
87
84
|
Raises:
|
|
88
85
|
ValueError
|
|
89
86
|
"""
|
|
90
|
-
def to_json_str(self)->str:
|
|
91
|
-
"""
|
|
92
|
-
|
|
87
|
+
def to_json_str(self) -> str:
|
|
88
|
+
"""Return a string of the JSON representation of the object"""
|
|
93
89
|
|
|
94
90
|
def solve(self, computation_time: int = 600) -> StripPackingSolution:
|
|
95
91
|
"""
|
|
@@ -11,6 +11,7 @@ use sparrow::config::{
|
|
|
11
11
|
CDE_CONFIG, COMPRESS_TIME_RATIO, EXPLORE_TIME_RATIO, MIN_ITEM_SEPARATION, SIMPL_TOLERANCE,
|
|
12
12
|
};
|
|
13
13
|
use sparrow::optimizer::{Terminator, optimize};
|
|
14
|
+
use std::collections::HashSet;
|
|
14
15
|
use std::fs;
|
|
15
16
|
use std::time::Duration;
|
|
16
17
|
|
|
@@ -20,20 +21,20 @@ use std::time::Duration;
|
|
|
20
21
|
///
|
|
21
22
|
/// Spyrrow doesn't support hole(s) inside the shape as of yet. Therefore no Item can be nested inside another.
|
|
22
23
|
///
|
|
23
|
-
/// Continous rotation is not supported as of yet. A workaround is to specify any integer degrees between 0 and 360
|
|
24
|
-
/// to the allowed_orientations list.
|
|
25
24
|
///
|
|
26
25
|
/// Args:
|
|
27
|
-
/// id (
|
|
28
|
-
///
|
|
26
|
+
/// id (str): The Item identifier
|
|
27
|
+
/// Needs to be unique accross all Items of a StripPackingInstance
|
|
29
28
|
/// shape (list[tuple[float,float]]): An ordered list of (x,y) defining the shape boundary. The shape is represented as a polygon formed by this list of points.
|
|
30
29
|
/// The origin point can be included twice as the finishing point. If not, [last point, first point] is infered to be the last straight line of the shape.
|
|
31
30
|
/// demand (int): The quantity of identical Items to be placed inside the strip. Should be positive.
|
|
32
|
-
/// allowed_orientations (list[float]): List of angles in degrees allowed.
|
|
31
|
+
/// allowed_orientations (list[float]|None): List of angles in degrees allowed.
|
|
32
|
+
/// An empty list is equivalent to [0.].
|
|
33
|
+
/// A None value means that the item is free to rotate
|
|
33
34
|
/// The algorithmn is only very weakly sensible to the length of the list given.
|
|
34
35
|
///
|
|
35
36
|
struct ItemPy {
|
|
36
|
-
id:
|
|
37
|
+
id: String,
|
|
37
38
|
demand: u64,
|
|
38
39
|
allowed_orientations: Option<Vec<f32>>,
|
|
39
40
|
shape: Vec<(f32, f32)>,
|
|
@@ -42,11 +43,16 @@ struct ItemPy {
|
|
|
42
43
|
#[pymethods]
|
|
43
44
|
impl ItemPy {
|
|
44
45
|
#[new]
|
|
45
|
-
fn new(
|
|
46
|
+
fn new(
|
|
47
|
+
id: String,
|
|
48
|
+
shape: Vec<(f32, f32)>,
|
|
49
|
+
demand: u64,
|
|
50
|
+
allowed_orientations: Option<Vec<f32>>,
|
|
51
|
+
) -> Self {
|
|
46
52
|
ItemPy {
|
|
47
53
|
id,
|
|
48
54
|
demand,
|
|
49
|
-
allowed_orientations
|
|
55
|
+
allowed_orientations,
|
|
50
56
|
shape,
|
|
51
57
|
}
|
|
52
58
|
}
|
|
@@ -78,34 +84,19 @@ impl ItemPy {
|
|
|
78
84
|
}
|
|
79
85
|
}
|
|
80
86
|
|
|
81
|
-
impl From<ItemPy> for ExtItem {
|
|
82
|
-
fn from(value: ItemPy) -> Self {
|
|
83
|
-
let polygon = ExtSPolygon(value.shape);
|
|
84
|
-
let shape = ExtShape::SimplePolygon(polygon);
|
|
85
|
-
let base = BaseItem {
|
|
86
|
-
id: value.id,
|
|
87
|
-
allowed_orientations: value.allowed_orientations,
|
|
88
|
-
shape,
|
|
89
|
-
min_quality: None,
|
|
90
|
-
};
|
|
91
|
-
ExtItem {
|
|
92
|
-
base,
|
|
93
|
-
demand: value.demand,
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
87
|
#[pyclass(name = "PlacedItem", get_all)]
|
|
99
88
|
#[derive(Clone, Debug)]
|
|
100
89
|
/// An object representing where a copy of an Item was placed inside the strip.
|
|
101
90
|
///
|
|
102
91
|
/// Attributes:
|
|
103
|
-
/// id (
|
|
104
|
-
///
|
|
105
|
-
///
|
|
92
|
+
/// id (str): The Item identifier referencing the items of the StripPackingInstance
|
|
93
|
+
/// rotation (float): The rotation angle in degrees, assuming that the original Item was defined with 0° as its rotation angle.
|
|
94
|
+
/// Use the origin (0.0,0.0) as the rotation point.
|
|
95
|
+
/// translation (tuple[float,float]): the translation vector in the X-Y axis. To apply after the rotation
|
|
96
|
+
///
|
|
106
97
|
///
|
|
107
98
|
struct PlacedItemPy {
|
|
108
|
-
pub id:
|
|
99
|
+
pub id: String,
|
|
109
100
|
pub translation: (f32, f32),
|
|
110
101
|
pub rotation: f32,
|
|
111
102
|
}
|
|
@@ -127,6 +118,11 @@ struct StripPackingSolutionPy {
|
|
|
127
118
|
pub density: f32,
|
|
128
119
|
}
|
|
129
120
|
|
|
121
|
+
fn all_unique(strings: &[&str]) -> bool {
|
|
122
|
+
let mut seen = HashSet::new();
|
|
123
|
+
strings.iter().all(|s| seen.insert(*s))
|
|
124
|
+
}
|
|
125
|
+
|
|
130
126
|
#[pyclass(name = "StripPackingInstance", get_all, set_all)]
|
|
131
127
|
#[derive(Clone, Serialize)]
|
|
132
128
|
/// An Instance of a Strip Packing Problem.
|
|
@@ -136,7 +132,6 @@ struct StripPackingSolutionPy {
|
|
|
136
132
|
/// An empty string '' can be used, if the user doesn't have a use for this name.
|
|
137
133
|
/// strip_height (float): the fixed height of the strip. The unit should be compatible with the Item
|
|
138
134
|
/// items (list[Item]): The Items which defines the instances. All Items should be defined with the same scale ( same length unit).
|
|
139
|
-
/// Items ids should be an increasing series starting at 0 until len(items)-1.
|
|
140
135
|
///
|
|
141
136
|
/// Raises:
|
|
142
137
|
/// ValueError
|
|
@@ -149,7 +144,25 @@ struct StripPackingInstancePy {
|
|
|
149
144
|
|
|
150
145
|
impl From<StripPackingInstancePy> for ExtSPInstance {
|
|
151
146
|
fn from(value: StripPackingInstancePy) -> Self {
|
|
152
|
-
let items = value
|
|
147
|
+
let items = value
|
|
148
|
+
.items
|
|
149
|
+
.into_iter()
|
|
150
|
+
.enumerate()
|
|
151
|
+
.map(|(idx, v)| {
|
|
152
|
+
let polygon = ExtSPolygon(v.shape);
|
|
153
|
+
let shape = ExtShape::SimplePolygon(polygon);
|
|
154
|
+
let base = BaseItem {
|
|
155
|
+
id: idx as u64,
|
|
156
|
+
allowed_orientations: v.allowed_orientations,
|
|
157
|
+
shape,
|
|
158
|
+
min_quality: None,
|
|
159
|
+
};
|
|
160
|
+
ExtItem {
|
|
161
|
+
base,
|
|
162
|
+
demand: v.demand,
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
.collect();
|
|
153
166
|
ExtSPInstance {
|
|
154
167
|
name: value.name,
|
|
155
168
|
strip_height: value.strip_height,
|
|
@@ -162,14 +175,9 @@ impl From<StripPackingInstancePy> for ExtSPInstance {
|
|
|
162
175
|
impl StripPackingInstancePy {
|
|
163
176
|
#[new]
|
|
164
177
|
fn new(name: String, strip_height: f32, items: Vec<ItemPy>) -> PyResult<Self> {
|
|
165
|
-
let
|
|
166
|
-
item_ids
|
|
167
|
-
|
|
168
|
-
if item_ids != expected_ids {
|
|
169
|
-
let error_string = format!(
|
|
170
|
-
"The item ids are not ordered from 0 to the Items length -1: {:#?}",
|
|
171
|
-
item_ids
|
|
172
|
-
);
|
|
178
|
+
let item_ids: Vec<&str> = items.iter().map(|i| i.id.as_str()).collect();
|
|
179
|
+
if !all_unique(&item_ids) {
|
|
180
|
+
let error_string = format!("The item ids are not uniques: {:#?}", item_ids);
|
|
173
181
|
return Err(PyValueError::new_err(error_string));
|
|
174
182
|
}
|
|
175
183
|
Ok(StripPackingInstancePy {
|
|
@@ -238,8 +246,8 @@ impl StripPackingInstancePy {
|
|
|
238
246
|
.placed_items
|
|
239
247
|
.into_iter()
|
|
240
248
|
.map(|jpi| PlacedItemPy {
|
|
241
|
-
id: jpi.item_id,
|
|
242
|
-
rotation: jpi.transformation.rotation,
|
|
249
|
+
id: self.items[jpi.item_id as usize].id.clone(),
|
|
250
|
+
rotation: jpi.transformation.rotation.to_degrees(), // Until sparrow exports to degrees instead of radians
|
|
243
251
|
translation: jpi.transformation.translation,
|
|
244
252
|
})
|
|
245
253
|
.collect();
|
|
@@ -2,12 +2,11 @@ import spyrrow
|
|
|
2
2
|
import pytest
|
|
3
3
|
|
|
4
4
|
def test_basic():
|
|
5
|
-
## Continuous rotation seems to not be implemented for strip packing
|
|
6
5
|
rectangle1 = spyrrow.Item(
|
|
7
|
-
|
|
6
|
+
"rectangle", [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)], demand=4, allowed_orientations=[0]
|
|
8
7
|
)
|
|
9
8
|
triangle1 = spyrrow.Item(
|
|
10
|
-
|
|
9
|
+
"triangle",
|
|
11
10
|
[(0, 0), (1, 0), (1, 1), (0, 0)],
|
|
12
11
|
demand=6,
|
|
13
12
|
allowed_orientations=[0, 90, 180, -90],
|
|
@@ -22,10 +21,10 @@ def test_basic():
|
|
|
22
21
|
def test_2_consecutive_calls():
|
|
23
22
|
# Test correpsonding to crash on the second consecutive call of solve method
|
|
24
23
|
rectangle1 = spyrrow.Item(
|
|
25
|
-
|
|
24
|
+
"rectangle", [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)], demand=4, allowed_orientations=[0]
|
|
26
25
|
)
|
|
27
26
|
triangle1 = spyrrow.Item(
|
|
28
|
-
|
|
27
|
+
"triangle",
|
|
29
28
|
[(0, 0), (1, 0), (1, 1), (0, 0)],
|
|
30
29
|
demand=6,
|
|
31
30
|
allowed_orientations=[0, 90, 180, -90],
|
|
@@ -39,9 +38,26 @@ def test_2_consecutive_calls():
|
|
|
39
38
|
assert sol.width == pytest.approx(4,rel=0.2)
|
|
40
39
|
|
|
41
40
|
def test_concave_polygons():
|
|
42
|
-
poly1 = spyrrow.Item(0,[(0, 0), (3, 0), (4, 1), (3, 2), (0, 2), (1, 1), (0, 0)],demand=2,allowed_orientations=[0,90,180,270])
|
|
43
|
-
poly2 = spyrrow.Item(1,[(0, 0), (1, 0), (1, 2), (3, 2), (3, 0), (4, 0), (4, 3), (0, 3), (0, 0)], demand=3, allowed_orientations=[0,90,180,270])
|
|
41
|
+
poly1 = spyrrow.Item("0",[(0, 0), (3, 0), (4, 1), (3, 2), (0, 2), (1, 1), (0, 0)],demand=2,allowed_orientations=[0,90,180,270])
|
|
42
|
+
poly2 = spyrrow.Item("1",[(0, 0), (1, 0), (1, 2), (3, 2), (3, 0), (4, 0), (4, 3), (0, 3), (0, 0)], demand=3, allowed_orientations=[0,90,180,270])
|
|
44
43
|
instance = spyrrow.StripPackingInstance(
|
|
45
44
|
"test", strip_height=4.001, items=[poly1, poly2]
|
|
46
45
|
)
|
|
47
|
-
sol = instance.solve(30)
|
|
46
|
+
sol = instance.solve(30)
|
|
47
|
+
|
|
48
|
+
def test_continuous_rotation():
|
|
49
|
+
rectangle1 = spyrrow.Item(
|
|
50
|
+
"rectangle", [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)], demand=4, allowed_orientations=None
|
|
51
|
+
)
|
|
52
|
+
triangle1 = spyrrow.Item(
|
|
53
|
+
"triangle",
|
|
54
|
+
[(0, 0), (1, 0), (1, 1), (0, 0)],
|
|
55
|
+
demand=6,
|
|
56
|
+
allowed_orientations=None,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
instance = spyrrow.StripPackingInstance(
|
|
60
|
+
"test", strip_height=2.001, items=[rectangle1, triangle1]
|
|
61
|
+
)
|
|
62
|
+
sol = instance.solve(30)
|
|
63
|
+
assert sol.width == pytest.approx(4,rel=0.2)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|