├── Cargo.toml ├── LICENSE ├── OPTO.md ├── README.md ├── benches ├── benchoutput │ └── empty_square.js └── speedtest.rs ├── examples └── main.rs ├── src ├── lib.rs └── node.rs ├── tests ├── fixtures │ ├── bad-diagonals.json │ ├── bad-hole.json │ ├── building.json │ ├── degenerate.json │ ├── dude.json │ ├── eberly-3.json │ ├── eberly-6.json │ ├── empty-square.json │ ├── hilbert.json │ ├── hole-touching-outer.json │ ├── issue16.json │ ├── issue17.json │ ├── issue29.json │ ├── issue34.json │ ├── issue35.json │ ├── issue45.json │ ├── issue52.json │ ├── issue83.json │ ├── outside-ring.json │ ├── self-touching.json │ ├── shared-points.json │ ├── simplified-us-border.json │ ├── steiner.json │ ├── touching-holes.json │ ├── water-huge.json │ ├── water-huge2.json │ ├── water.json │ ├── water2.json │ ├── water3.json │ ├── water3b.json │ └── water4.json └── integration_test.rs └── viz ├── circle.png ├── earcut.js ├── testoutput ├── bad_diagonals.js ├── bad_hole.js ├── building.js ├── degenerate.js ├── dude.js ├── eberly_3.js ├── eberly_6.js ├── empty_square.js ├── hilbert.js ├── hole_touching_outer.js ├── issue16.js ├── issue17.js ├── issue29.js ├── issue34.js ├── issue35.js ├── issue45.js ├── issue52.js ├── issue83.js ├── outside_ring.js ├── self_touching.js ├── shared_points.js ├── simplified_us_border.js ├── steiner.js ├── touching_holes.js ├── water.js ├── water2.js ├── water3.js ├── water3b.js ├── water4.js ├── water_huge.js └── water_huge2.js ├── viz.css ├── viz.html └── viz.js /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "earcutr" 3 | version = "0.1.0" 4 | authors = ["don bright "] 5 | 6 | [dev-dependencies] 7 | serde = "1.0.80" 8 | serde_derive = "1.0.80" 9 | serde_json = "1.0.33" 10 | bencher ="0.1.5" 11 | 12 | [[bench]] 13 | name = "speedtest" 14 | harness = false 15 | 16 | # for profiling with standard tools, like 17 | # Valgrind's Callgrind or Perf 18 | [profile.release] 19 | debug = true 20 | 21 | # for profiling with CpuProfiler 22 | #[dependencies] 23 | #cpuprofiler = "0.0.3" 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2016, Mapbox 4 | Copyright (c) 2018, Tree Cricket 5 | 6 | Permission to use, copy, modify, and/or distribute this software for any purpose 7 | with or without fee is hereby granted, provided that the above copyright notice 8 | and this permission notice appear in all copies. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 11 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 12 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 13 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 14 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 16 | THIS SOFTWARE. 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://stand-with-ukraine.pp.ua) 3 | 4 | # Earcutr 5 | 6 | This is a port of the MapBox company's Earcut computer code ( see 7 | https://github.com/mourner, Volodymyr Agafonkin) , which triangulates 8 | polygons. Please see https://github.com/mapbox/earcut for more 9 | information about the original javascript code. This port is to the 10 | Rust computer language, and is single-threaded. 11 | 12 | This port is not affiliated with MapBox in any way and no endorsement is 13 | implied. Also please note MapBox has their own Rust port of this code, 14 | no claim is made this is better than theirs. The goal is to have identical 15 | output to MapBox's Javascript code however several updates have been 16 | made to MapBox js and this Rust port is a few years behind. 17 | 18 | Please also note someone made this into a Crate (not me) for 19 | convenience, please check crates.io 20 | 21 | ![image showing an outline of a circle with a hole inside of it, with 22 | !triangles inside of it](viz/circle.png "circle, earcut") 23 | 24 | 25 | 26 | ## Usage 27 | 28 | ```rust 29 | extern crate earcutr; 30 | var triangles = earcutr::earcut(&vec![10,0, 0,50, 60,60, 70,10],&vec![],2); 31 | println!("{:?}",triangles); // [1, 0, 3, 3, 2, 1] 32 | ``` 33 | 34 | Signature: 35 | 36 | `earcut(vertices:&vec, hole_indices:&vec, dimensions:usize)`. 37 | 38 | * `vertices` is a flat array of vertex coordinates like `[x0,y0, x1,y1, x2,y2, ...]`. 39 | * `holes` is an array of hole _indices_ if any 40 | (e.g. `[5, 8]` for a 12-vertex input would mean one hole with vertices 5–7 and another with 8–11). 41 | * `dimensions` is the number of coordinates per vertex in the input array. Dimensions must be 2. 42 | 43 | Each group of three vertex indices in the resulting array forms a triangle. 44 | 45 | ```rust 46 | // triangulating a polygon with a hole 47 | earcutr::earcut( 48 | &vec![0.,0., 100.,0., 100.,100., 0.,100., 20.,20., 80.,20., 80.,80., 20.,80.], 49 | &vec![4] , 2 ); 50 | // result: [3,0,4, 5,4,0, 3,4,7, 5,0,1, 2,3,7, 6,5,1, 2,7,6, 6,1,2] 51 | ``` 52 | 53 | If you pass a single vertex as a hole, Earcut treats it as a Steiner point. 54 | See the 'steiner' test under ./tests/fixtures for an example input, 55 | and the test visualization under ./viz. 56 | 57 | After getting a triangulation, you can verify its correctness with 58 | `earcutr.deviation`: 59 | 60 | ```rust 61 | let deviation = earcutr.deviation(&data.vertices, &data.holes, data.dimensions, &triangles); 62 | ``` 63 | 64 | Deviation returns the relative difference between the total area of 65 | triangles and the area of the input polygon. `0` means the triangulation 66 | is fully correct. 67 | 68 | ## Flattened vs multi-dimensional data 69 | 70 | If your input is a multi-dimensional array you can convert it to the 71 | format expected by Earcut with `earcut.flatten`. For example: 72 | 73 | ```rust 74 | let v = vec![ 75 | vec![vec![0.,0.],vec![1.,0.],vec![1.,1.],vec![0.,1.]], // outer ring 76 | vec![vec![1.,1.],vec![3.,1.],vec![3.,3.]] // hole ring 77 | ]; 78 | let (vertices,holes,dimensions) = earcutr::flatten( &v ); 79 | let triangles = earcutr::earcut(&vertices, &holes, dimensions); 80 | ``` 81 | 82 | The [GeoJSON Polygon](http://geojson.org/geojson-spec.html#polygon) format uses 83 | multi-dimensional data in a text based JSON format. There is example code under 84 | tests/integration_test.rs on how to parse JSON data. The test/fixtures test 85 | files are all multi-dimensional .json files. 86 | 87 | ## How it works: The algorithm 88 | 89 | The library implements a modified ear slicing algorithm, 90 | optimized by [z-order curve](http://en.wikipedia.org/wiki/Z-order_curve) hashing 91 | and extended to handle holes, twisted polygons, degeneracies and self-intersections 92 | in a way that doesn't _guarantee_ correctness of triangulation, 93 | but attempts to always produce acceptable results for practical data. 94 | 95 | It's based on ideas from 96 | [FIST: Fast Industrial-Strength Triangulation of Polygons](http://www.cosy.sbg.ac.at/~held/projects/triang/triang.html) by Martin Held 97 | and [Triangulation by Ear Clipping](http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf) by David Eberly. 98 | 99 | ### Visual example 100 | 101 | For example a rectangle could be given in GeoJSON format like so: 102 | 103 | [ [ [0,0],[7,0],[7,4],[0,4] ] ] 104 | 105 | This has a single contour, or ring, with four points. The way 106 | the points are listed, it looks 'counter-clockwise' or 'anti-clockwise' 107 | on the page. This is the 'winding' and signifies that it is an 'outer' 108 | ring, or 'body' of the shape. 109 | 110 | _______ 111 | | | 112 | | | 113 | | | 114 | |_____| 115 | 116 | Now let's add a hole to the square.: 117 | 118 | [ 119 | [ [0,0],[7,0],[7,4],[0,4] ], 120 | [ [1,1],[3,1],[3,3] ] 121 | ] 122 | 123 | This has two contours (rings), the first with four points, the second 124 | with three points. The second has 'clockwise' winding, signifying it is 125 | a 'hole'. 126 | 127 | _______ 128 | | | 129 | | /| | 130 | | /_| | 131 | |_____| 132 | 133 | After 'flattening', we end up with a single array: 134 | 135 | data [ 0,0,7,0,7,4,0,4,1,1,3,1,3,3 ] 136 | holeindexes: [ 4 ] 137 | dimensions: 2 138 | 139 | The program will interpret this sequence of data into two separate "rings", 140 | the outside ring and the 'hole'. The rings are stored using a circular 141 | doubly-linked list. 142 | 143 | The program then "removes" the hole, by essentially adding a "cut" between 144 | the hole and the polygon, so that there is only a single "ring" cycle. 145 | 146 | _______ 147 | | | 148 | | /| | 149 | cut> |_/_| | 150 | |_____| 151 | 152 | The program also automatically 'corrects' the winding of the points 153 | during input so they are all counter-clockwise. 154 | 155 | Then, an "ear cutting" algorithm is applied. But not just any earcutting 156 | algorithm. 157 | 158 | Normally, an ear-cutter algorithm works by finding a potential ear, 159 | or a "candidate" ear, by looking at three consecutive points on the 160 | polygon. Then, it must make sure there are no other points "inside" 161 | the ear. 162 | 163 | In order to do this, it must iterate through every point in the polygon, 164 | so if your polygon has 15,000 points then it must go through all of them 165 | looking to see if each one is inside the potential ear. Each ear check 166 | takes a dozen or two calculations, typically using a test like the 167 | wedge product between each side of the ear, and the point to check - if 168 | the point is on the right-hand-side (Wedge is less than zero) of each 169 | side, it's inside the ear, and so the ear cannot be cut. The algorithm 170 | then moves on to the next potential ear. 171 | 172 | #### Z-order curve 173 | 174 | Z-order hashing allows the number of 'is in ear' checks to be drastically 175 | cut down. How? Instead of running the "is in ear" code on each other point 176 | in the polygon, it is able to only check points 'nearby' the ear. This is 177 | accomplished in the following manner: 178 | 179 | Step 1: before earcut, each point of the polygon is given a coordinate 180 | on the z-order (Morton) curve through the space of the bounding box 181 | of the polygon. This is a type of space-filling curve strategy that 182 | has been explored in many geometry algorithms. Pleas see 183 | https://en.wikipedia.org/wiki/Z-order_curve 184 | 185 | Step 2: The clever bit is that if you want to search within a limited 186 | rectangle inside the space filled by the Z-order curve, you can 187 | relatively easily figure out which points are inside that box by 188 | looking at their position on the z-order curve.. in other words 189 | their z index. The code stores the index as ".z" in each node of the 190 | linked list that represents a vertex of the polygon. 191 | 192 | To be more specific, Z-order curves have a special thing about them, 193 | when you pick a limited rectangle inside, you can iterate along the 194 | z-curve from the "lowest" corner to the "highest" corner and be 195 | guaranteed to hit every 2d point inside that rectangle. 196 | 197 | For example, in a 4x4 morton square, there are 16 Morton codes. 198 | 199 | x-----0--1--2--3--> 200 | y|0 0 1 4 5 201 | |1 2 3 6 7 202 | |2 8 9 12 13 203 | |3 10 11 14 15 204 | \|/ 205 | 206 | Going from z-code 0 to z-code 6, 0 1 2 3 4 5 6, takes us through 207 | every 2 dimensional point between 0,0, where 0 lives, and 2,1, 208 | where 6 lives. It also goes through 3,0 but nothing is perfect. 209 | 210 | Let's say you pick 2,2 and 3,3. The z code at the lowest point 211 | is 12, and the highest is 15. So your z-iteration would be 212 | 12, 13, 14, 15, which covers the rectangle from 2,2 to 3,3. 213 | 214 | So, that is how it gets away without checking every point in the polygon 215 | to see if they are inside the ear. It draws a rectangle around the ear, 216 | it finds the lowest and highest corner of that rectangle, and iterates 217 | through the z-curve to check every 2-d point that is 'near' the polygon 218 | ear. 219 | 220 | As you can imagine, if 14,000 of your points in your polygon are outside 221 | this box, and only 1000 are in the box, thats quite a bit less math 222 | and calculation to be done than if you had to iterate through 15,000 points. 223 | 224 | #### Additional massaging 225 | 226 | If the straightforward earcutting fails, it also does some simple fixes, 227 | 228 | - Filtering points - removing some collinear and equal points 229 | 230 | - Self intersections - removing points that only tie a tiny little knot 231 | in the polygon without contributing to its overall shape (and also 232 | make it not-simple) 233 | 234 | - Split bridge - actually split the polygon into two separate ones, 235 | and try to earcut each. 236 | 237 | Data examples are included under tests/fixtures in json files. 238 | Visualization of test results is generated under viz/testoutput and can 239 | be viewed in a web browser by opening viz/viz.html 240 | 241 | ### Coordinate number type 242 | 243 | The coordinate type in this code is 64-bit floating point. Note that 244 | 32-bit floating point will fail the tests because the test data files 245 | have numbers that cannot be held with full precision in 32 bits, like 246 | the base 10 number 537629.886026485, which gets rounded to 537629.875 247 | during conversion from base 10 to 32-bit base 2. 248 | 249 | 250 | ### Tradeoffs 251 | 252 | This triangulator is built primarily as an exercise in porting 253 | javascript to Rust. However some minor details of the implementation 254 | have been modified for speed optimization. The code is supposed to 255 | produce exacly the same output as the javascript version, by using the 256 | large amount of test data supplied with the original javascript code. 257 | The speed is comparable with Mapbox's C++ version of earcut, earcut.hpp, 258 | except for input of very small polygons where the speed is much slower. 259 | See the benchmarking section for more detail. 260 | 261 | If you want to get correct triangulation even on very bad data with lots 262 | of self-intersections and earcutr is not precise enough, take a look at 263 | [libtess.js](https://github.com/brendankenny/libtess.js). 264 | 265 | You may also want to consider pre-processing the polygon data with 266 | [Angus J's Clipper](http://angusj.com/delphi/clipper.php) which uses 267 | Vatti's Algorithm to clean up 'polygon soup' type of data. 268 | 269 | ### These algorithms are based on linked lists, is that difficult in Rust? 270 | 271 | Yes. [A. Beinges's "Too Many Lists"](https://cglab.ca/~abeinges/blah/too-many-lists/book/) 272 | shows how to do Linked Lists in Rust. Rust also has a 'linked list' type 273 | builtin, which could be made Circular in theory by calling iter().cycle(). 274 | 275 | However this code implements a Circular Doubly Linked List entirely on 276 | top of a Rust Vector, without any unsafe blocks. This does not use Rc, 277 | Box, Arc, etc. The pointers in normal Linked List Node code have been 278 | replaced by integers which index into a single Vector of Nodes stored in 279 | LinkedLists struct. It will still crash if you use an index out of bounds 280 | but the RUST_BACKTRACE=1 will tell you exactly where it happened. 281 | 282 | It also uses Extension Traits to basically extend the type usize itself, 283 | so you can have methods on indexes even though the indexes are just integers. 284 | For example: 285 | 286 | In C++ pointers imagine the following expression 287 | 288 | start.prev.next = i 289 | 290 | This takes the start node, finds the previous node, then sets the next 291 | node of the previous node to some other node. start, prev, next, 292 | and i are all pointers into memory, which if set incorrectly could lead to 293 | segmentation faults. 294 | 295 | In this Rust implementation with Extension Traits we express the same idea as 296 | follows. 297 | 298 | start.prev(fll).set_next(fll,i); 299 | 300 | In this version, we replaced pointers by integers (type usize) then 301 | use Trait Extensions on usize to allow functions to be called 'on' the 302 | integers. 303 | 304 | fll is a reference to a struct, which has a vector of nodes. (fake linked list) 305 | start is a usize, i is a usize, both indexes into fll's vector 306 | 307 | The trick here mentally is to separate the idea of a node from the idea 308 | of a pointer. So once we do that, we can comprehend that the 309 | idea of a Node is separate from the idea of it's index, which is 310 | basically it's pointer but the pointer is limited to be within the 311 | Vector inside of the 'fll' structure. So since a lot of linked list code 312 | is just shuffling pointers around, in this Rust version, the code is 313 | just shuffling indexes around. Since indexes are just integers, and we 314 | can do Trait Extensions of integers, this allows us to mimic the syntax 315 | of pointers a little bit. 316 | 317 | Now we can also do some silly tricks with Nodes themselves, implementing 318 | 'next' method for Node, that just calls the trait extension method 319 | on the nodes own index. Then if we need to get the next Node and we have 320 | a Node, we can just call next() on the node. 321 | 322 | fll: LinkedList 323 | a: Node = Node::new(blah blah blah); 324 | fll.add(&node); 325 | calculate_something(a,a.next(fll)); 326 | 327 | So basically we have two concepts of next() here. 328 | 329 | i: usize // i is an index into some linked list fll 330 | i.next(fll) // calling next() on an integer i which is an index into fll 331 | // this gives us the index of the next node in fll. 332 | 333 | n: Node // plain old struct Node 334 | n.next(fll) // calling next() on a Node which gives us the next Node 335 | 336 | One theoretical benefit of this setup is that if you want to transform 337 | every single point in your dataset, you can just iterate thru the vector 338 | of nodes, rather than iterating thru a linked list. In theory 339 | this could be faster than iterating through a linked list, since 340 | many pieces of the machine are designed to quickly process arrays. 341 | 342 | This might seem like a source of a slowdown - to bounds check every 343 | array access. However in practice the difference is barely measurable. 344 | In fact, the code is built so it is relatively easy to switch to 345 | "unchecked_get" to test vector access without bounds checking. 346 | 347 | ## Tests, Benchmarks 348 | 349 | To run tests: 350 | 351 | ```bash 352 | $ git clone github.com/donbright/earcutr 353 | $ cd earcutr 354 | $ cargo test # normal Rust tests. Also outputs visualization data 355 | $ cd viz # which is stored under viz/testoutput. you can 356 | $ firefox viz.html # view in your favorite web browser (circa 2018) 357 | ``` 358 | 359 | To run benchmarks: 360 | 361 | ```bash 362 | $ cargo bench 363 | ... 364 | test bench_water ... bench: 1,860,385 ns/iter (+/- 21,188) 365 | test bench_water2 ... bench: 1,477,185 ns/iter (+/- 10,294) 366 | test bench_water3 ... bench: 63,800 ns/iter (+/- 3,809) 367 | test bench_water3b ... bench: 5,751 ns/iter (+/- 18) 368 | test bench_water4 ... bench: 473,971 ns/iter (+/- 5,950) 369 | test bench_water_huge ... bench: 26,770,194 ns/iter (+/- 532,784) 370 | test bench_water_huge2 ... bench: 53,256,089 ns/iter (+/- 1,208,028) 371 | ``` 372 | 373 | Bench note: As of this writing, benchmarking is not in Stable Rust, so 374 | this project uses an alternative, https://docs.rs/bencher/0.1.5/bencher/ 375 | 376 | ### Speed of this Rust code vs earcut.hpp C++ code 377 | 378 | Following is a rough table based on testing of Earcut's C++ code, 379 | Earcut's C++ test of LibTess' C++ code, and finally this Rust port of Earcut. 380 | 381 | ``` 382 | ____polygon______earcut.hpp_-O2__libtessc++_-O2___Rust_earcutr_release 383 | | water | 1,831,501 ns/i | 9,615,384 ns/i | 1,860,385 ns/i | 384 | | water2 | 1,626,016 ns/i | 1,694,915 ns/i | 1,477,185 ns/i | 385 | | water3 | 53,140 ns/i | 153,869 ns/i | 63,800 ns/i | 386 | | water3b | 4,183 ns/i | 20,143 ns/i | 5,751 ns/i | 387 | | water4 | 475,511 ns/i | 871,839 ns/i | 473,971 ns/i | 388 | | water_huge | 26,315,789 ns/i | 26,315,789 ns/i | 26,770,194 ns/i | 389 | | water_huge2| 55,555,555 ns/i | 20,000,000 ns/i | 53,256,089 ns/i | 390 | ---------------------------------------------------------------------- 391 | ns/i = nanoseconds per iteration 392 | ``` 393 | 394 | This Rust code appears to be about 20-40% slower than the C++ version of 395 | Earcut for tiny shapes. However with bigger shapes, it is either within 396 | the error margin, or maybe a bit faster. 397 | 398 | #### Method for comparing Earcut C++ / Earcutr Rust 399 | 400 | Mapbox has a C++ port of earcut.hpp, with a built in benchmarker, 401 | measured in 'ops per second'. It also compares against a c++ version of 402 | libtess. However by default it builds without optimization, which 403 | hampers comparison. We can fix this. Editing the .hpp CMakeLists.txt 404 | file for the C compiler flags lets us turn on optimization, 405 | 406 | add_compile_options("-g" "-O2" .... 407 | 408 | Now, Rust bench measures in nanoseconds per iteration. 409 | C++ Earcut measures in iterations per second. To convert: 410 | 18 ops in 1 second, is 411 | 18 iterations in 1,000,000,000 nanoseconds. 412 | 1,000,000,000 / 18 -> 55,555,555 nanoseconds/iteration 413 | This way, a conversion can be done. 414 | 415 | #### Profiling 416 | 417 | - http://www.codeofview.com/fix-rs/2017/01/24/how-to-optimize-rust-programs-on-linux/ 418 | 419 | - Valgrind 's callgrind: (see Cargo.toml, set debug=yes) 420 | 421 | ```bash 422 | sudo apt install valgrind 423 | cargo bench water2 # find the binary name "Running: target/release/..." 424 | valgrind --tool=callgrind target/release/deps/speedtest-bc0e4fb32ac081fc water2 425 | callgrind_annotate callgrind.out.6771 426 | kcachegrind callgrind.out.6771 427 | ``` 428 | 429 | - CpuProfiler 430 | 431 | From AtheMathmo https://github.com/AtheMathmo/cpuprofiler 432 | 433 | - Perf 434 | 435 | https://perf.wiki.kernel.org/index.php/Tutorial 436 | 437 | ```bash 438 | cargo bench water2 # find the binary name "Running: target/release/..." 439 | sudo perf stat target/release/deps/speedtest-bc0e4fb32ac081fc water2 440 | sudo perf record target/release/deps/speedtest-bc0e4fb32ac081fc water2 441 | sudo perf report 442 | ``` 443 | 444 | #### Profiling results 445 | 446 | Please see [OPTO.md] if you wish a long description of the optimization 447 | process. Here are a few other highlights: 448 | 449 | * is_earcut_hashed() is hot 450 | 451 | Profilers reveal that on bigger shapes the vast majority of time is 452 | spent inside is_earcut_hashed(), which is determining whether an ear is 453 | "really an ear" so that it may be cut without damaging the polygon. 454 | 455 | * Zorder is also hot 456 | 457 | The second major speed boost comes from Callgrind/kcachegrind in 458 | particular revealed that the zorder() function was a source of some a 459 | lot of work by the CPU. In particular the conversion from floating point 460 | 64 bit numbers in the input arguments, to the 32 bit integer, can be 461 | important to improving speed. 462 | 463 | * inline by-hand is important 464 | 465 | Most of the time in C++ you can assume the compiler figures out 466 | inlining. In Rust, however, the point_in_triangle and area function 467 | inside ear_checker wont get inlined unless specifically indicated with 468 | the inline macro. 469 | 470 | * Vector [Indexing] and bounds checking in Rust doesn't hurt speed here 471 | 472 | As mentioned, this code is implemented as a double-linked list sitting on 473 | top of a vector, an the 'pointers' are actually indexes into the vector. 474 | There are several macros used that represent the normal linked list 475 | language, such as next!(index) prev!(index), which take index integers 476 | as input, and return a Node or Reference to Node. Each index uses Rust's 477 | built in vector indexing, which uses 'bounds checking' so it will panic 478 | immediately if memory outside the vector range is accessed on accident. 479 | The panic and backtrace will report exactly what line the access occured 480 | and the value of the index that was too large to use. 481 | 482 | Theoretically this slows down the program. In practice, it does not. 483 | This has been tested extensively because the macros like next!() and prev!() 484 | have been written in a way that it is extremely easy to switch back and 485 | forth between bounds-checked vector indexing, and unsafe vector indexing 486 | using get_unchecked(), and re-run 'cargo bench water' to compare them. 487 | 488 | The benchmark of water shapes shows the difference is within error, 489 | except for tiny shapes like water3b, where the benefit is so tiny 490 | as to not be worth it for most usage. 491 | 492 | * Iteration vs loops 493 | 494 | This code has converted several javascript for loops into Rust 495 | iteration. In theory this is slower. In practice, it is not, and in some 496 | cases it is actually faster, especially in find_hole_bridge. In theory 497 | iterators are easier to read and write, take up less code, and have less 498 | bugs. 499 | 500 | #### It could be faster 501 | 502 | The goal is to have identical output to MapBox's Javascript code. So if 503 | there are optimizations that break that compatability they will not be 504 | used. But there is of course always room for improvement. 505 | 506 | ## This triangulator in other languages 507 | 508 | - [mapbox/earcut](https://github.com/mapbox/earcut) MapBox Original javascript 509 | - [mapbox/earcut.hpp](https://github.com/mapbox/earcut.hpp) MapBox C++11 510 | 511 | 512 | Thanks 513 | -------------------------------------------------------------------------------- /benches/benchoutput/empty_square.js: -------------------------------------------------------------------------------- 1 | testOutput["empty_square"]["benchmark"]=[0,0,[]]; 2 | -------------------------------------------------------------------------------- /benches/speedtest.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Note: This module uses the 'unofficial' bench that works with Stable Rust as 3 | of 2018. This may conflict with "official" bench which is in "Nightly" Rust 4 | */ 5 | #[macro_use] 6 | extern crate bencher; 7 | extern crate earcutr; 8 | extern crate serde; 9 | extern crate serde_json; 10 | use bencher::Bencher; 11 | use std::fs::File; 12 | use std::fs::OpenOptions; 13 | use std::io::Read; 14 | use std::io::Write; 15 | 16 | //extern crate cpuprofiler; 17 | //use cpuprofiler::PROFILER; 18 | 19 | // this is to "force" optimized code to measure results, by outputting 20 | fn mkoutput(filename_w_dashes: &str, triangles: Vec) { 21 | let filename = str::replace(filename_w_dashes, "-", "_"); 22 | let outfile = &format!("benches/benchoutput/{}.js", filename); 23 | match OpenOptions::new() 24 | .write(true) 25 | .create(true) 26 | .truncate(true) 27 | .open(outfile) 28 | { 29 | Err(e) => println!("error writing {} {}", outfile, e), 30 | Ok(f) => writeln!( 31 | &f, 32 | r###"testOutput["{}"]["benchmark"]=[{:?},{:?},{:?}];"###, 33 | filename, 34 | 0, 35 | triangles.len(), 36 | triangles 37 | ) 38 | .unwrap(), 39 | }; 40 | } 41 | 42 | fn parse_json(rawdata: &str) -> Option>>> { 43 | let mut v: Vec>> = Vec::new(); 44 | match serde_json::from_str::(&rawdata) { 45 | Err(e) => println!("error deserializing, {}", e), 46 | Ok(jsondata) => { 47 | if jsondata.is_array() { 48 | let contours = jsondata.as_array().unwrap(); 49 | for i in 0..contours.len() { 50 | let contourval = &contours[i]; 51 | if contourval.is_array() { 52 | let contour = contourval.as_array().unwrap(); 53 | let mut vc: Vec> = Vec::new(); 54 | for j in 0..contour.len() { 55 | let points = contour[j].as_array().unwrap(); 56 | let mut vp: Vec = Vec::new(); 57 | for k in 0..points.len() { 58 | let val = points[k].to_string(); 59 | let pval = val.parse::().unwrap(); 60 | vp.push(pval); 61 | } 62 | vc.push(vp); 63 | } 64 | v.push(vc); 65 | } 66 | } 67 | } 68 | } 69 | }; 70 | return Some(v); 71 | } 72 | 73 | fn load_json(testname: &str) -> (Vec, Vec, usize) { 74 | let fullname = format!("./tests/fixtures/{}.json", testname); 75 | let mut xdata: Vec>> = Vec::new(); 76 | match File::open(&fullname) { 77 | Err(why) => println!("failed to open file '{}': {}", fullname, why), 78 | Ok(mut f) => { 79 | //println!("testing {},", fullname); 80 | let mut strdata = String::new(); 81 | match f.read_to_string(&mut strdata) { 82 | Err(why) => println!("failed to read {}, {}", fullname, why), 83 | Ok(_numb) => { 84 | //println!("read {} bytes", numb); 85 | let rawstring = strdata.trim(); 86 | match parse_json(rawstring) { 87 | None => println!("failed to parse {}", fullname), 88 | Some(parsed_data) => { 89 | xdata = parsed_data; 90 | } 91 | }; 92 | } 93 | }; 94 | } 95 | }; 96 | return earcutr::flatten(&xdata); 97 | } 98 | 99 | fn bench_quadrilateral(bench: &mut Bencher) { 100 | bench.iter(|| { 101 | earcutr::earcut(&vec![10., 0., 0., 50., 60., 60., 70., 10.], &vec![], 2); 102 | }); 103 | } 104 | 105 | fn bench_hole(bench: &mut Bencher) { 106 | let mut v = vec![0., 0., 50., 0., 50., 50., 0., 50.]; 107 | let h = vec![10., 10., 40., 10., 40., 40., 10., 40.]; 108 | v.extend(h); 109 | bench.iter(|| { 110 | earcutr::earcut(&v, &vec![4], 2); 111 | }) 112 | } 113 | 114 | fn bench_flatten(bench: &mut Bencher) { 115 | let v = vec![ 116 | vec![vec![0., 0.], vec![1., 0.], vec![1., 1.], vec![0., 1.]], // outer ring 117 | vec![vec![1., 1.], vec![3., 1.], vec![3., 3.]], // hole ring 118 | ]; 119 | bench.iter(|| { 120 | let (_vertices, _holes, _dimensions) = earcutr::flatten(&v); 121 | }) 122 | } 123 | 124 | fn bench_indices_2d(bench: &mut Bencher) { 125 | bench.iter(|| { 126 | let _indices = earcutr::earcut( 127 | &vec![10.0, 0.0, 0.0, 50.0, 60.0, 60.0, 70.0, 10.0], 128 | &vec![], 129 | 2, 130 | ); 131 | }) 132 | } 133 | 134 | fn bench_indices_3d(bench: &mut Bencher) { 135 | bench.iter(|| { 136 | let _indices = earcutr::earcut( 137 | &vec![ 138 | 10.0, 0.0, 0.0, 0.0, 50.0, 0.0, 60.0, 60.0, 0.0, 70.0, 10.0, 0.0, 139 | ], 140 | &vec![], 141 | 3, 142 | ); 143 | }) 144 | } 145 | 146 | fn bench_empty(bench: &mut Bencher) { 147 | bench.iter(|| { 148 | let _indices = earcutr::earcut(&vec![], &vec![], 2); 149 | }) 150 | } 151 | 152 | // file based tests 153 | 154 | fn bench_building(bench: &mut Bencher) { 155 | let nm = "building"; 156 | let (data, holeidxs, dimensions) = load_json(nm); 157 | let mut triangles = Vec::new(); 158 | bench.iter(|| { 159 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 160 | }); 161 | mkoutput(nm, triangles); 162 | } 163 | 164 | fn bench_dude(bench: &mut Bencher) { 165 | let nm = "dude"; 166 | let (data, holeidxs, dimensions) = load_json(nm); 167 | let mut triangles = Vec::new(); 168 | bench.iter(|| { 169 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 170 | }); 171 | mkoutput(nm, triangles); 172 | } 173 | 174 | fn bench_water(bench: &mut Bencher) { 175 | let nm = "water"; 176 | let (data, holeidxs, dimensions) = load_json(nm); 177 | let mut triangles = Vec::new(); 178 | bench.iter(|| { 179 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 180 | }); 181 | mkoutput(nm, triangles); 182 | } 183 | 184 | fn bench_water2(bench: &mut Bencher) { 185 | let nm = "water2"; 186 | let (data, holeidxs, dimensions) = load_json(nm); 187 | let mut triangles = Vec::new(); 188 | bench.iter(|| { 189 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 190 | }); 191 | mkoutput(nm, triangles); 192 | } 193 | 194 | fn bench_water3(bench: &mut Bencher) { 195 | let nm = "water3"; 196 | 197 | let (data, holeidxs, dimensions) = load_json(nm); 198 | let mut triangles = Vec::new(); 199 | bench.iter(|| { 200 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 201 | }); 202 | mkoutput(nm, triangles); 203 | } 204 | 205 | fn bench_water3b(bench: &mut Bencher) { 206 | let nm = "water3b"; 207 | 208 | let (data, holeidxs, dimensions) = load_json(nm); 209 | let mut triangles = Vec::new(); 210 | bench.iter(|| { 211 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 212 | }); 213 | mkoutput(nm, triangles); 214 | } 215 | 216 | fn bench_water4(bench: &mut Bencher) { 217 | let nm = "water4"; 218 | 219 | let (data, holeidxs, dimensions) = load_json(nm); 220 | let mut triangles = Vec::new(); 221 | bench.iter(|| { 222 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 223 | }); 224 | mkoutput(nm, triangles); 225 | } 226 | 227 | fn bench_water_huge(bench: &mut Bencher) { 228 | let nm = "water-huge"; 229 | 230 | let (data, holeidxs, dimensions) = load_json(nm); 231 | let mut triangles = Vec::new(); 232 | //PROFILER.lock().unwrap().start("./earcutr.profile").unwrap(); 233 | bench.iter(|| { 234 | // for i in 0..99 { 235 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 236 | // } 237 | }); 238 | //PROFILER.lock().unwrap().stop().unwrap(); 239 | 240 | mkoutput(nm, triangles); 241 | } 242 | 243 | fn bench_water_huge2(bench: &mut Bencher) { 244 | let nm = "water-huge2"; 245 | let (data, holeidxs, dimensions) = load_json(nm); 246 | let mut triangles = Vec::new(); 247 | bench.iter(|| { 248 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 249 | }); 250 | mkoutput(nm, triangles); 251 | } 252 | 253 | fn bench_degenerate(bench: &mut Bencher) { 254 | let nm = "degenerate"; 255 | let (data, holeidxs, dimensions) = load_json(nm); 256 | let mut triangles = Vec::new(); 257 | bench.iter(|| { 258 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 259 | }); 260 | mkoutput(nm, triangles); 261 | } 262 | 263 | fn bench_bad_hole(bench: &mut Bencher) { 264 | let nm = "bad-hole"; 265 | let (data, holeidxs, dimensions) = load_json(nm); 266 | let mut triangles = Vec::new(); 267 | bench.iter(|| { 268 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 269 | }); 270 | mkoutput(nm, triangles); 271 | } 272 | 273 | fn bench_empty_square(bench: &mut Bencher) { 274 | let nm = "empty-square"; 275 | let (data, holeidxs, dimensions) = load_json(nm); 276 | let mut triangles = Vec::new(); 277 | bench.iter(|| { 278 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 279 | }); 280 | mkoutput(nm, triangles); 281 | } 282 | 283 | fn bench_issue16(bench: &mut Bencher) { 284 | let nm = "issue16"; 285 | let (data, holeidxs, dimensions) = load_json(nm); 286 | let mut triangles = Vec::new(); 287 | bench.iter(|| { 288 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 289 | }); 290 | mkoutput(nm, triangles); 291 | } 292 | 293 | fn bench_issue17(bench: &mut Bencher) { 294 | let nm = "issue17"; 295 | let (data, holeidxs, dimensions) = load_json(nm); 296 | let mut triangles = Vec::new(); 297 | bench.iter(|| { 298 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 299 | }); 300 | mkoutput(nm, triangles); 301 | } 302 | 303 | fn bench_steiner(bench: &mut Bencher) { 304 | let nm = "steiner"; 305 | let (data, holeidxs, dimensions) = load_json(nm); 306 | let mut triangles = Vec::new(); 307 | bench.iter(|| { 308 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 309 | }); 310 | mkoutput(nm, triangles); 311 | } 312 | 313 | fn bench_issue29(bench: &mut Bencher) { 314 | let nm = "issue29"; 315 | let (data, holeidxs, dimensions) = load_json(nm); 316 | 317 | let mut triangles = Vec::new(); 318 | bench.iter(|| { 319 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 320 | }); 321 | mkoutput(nm, triangles); 322 | } 323 | 324 | fn bench_issue34(bench: &mut Bencher) { 325 | let nm = "issue34"; 326 | let (data, holeidxs, dimensions) = load_json(nm); 327 | let mut triangles = Vec::new(); 328 | bench.iter(|| { 329 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 330 | }); 331 | mkoutput(nm, triangles); 332 | } 333 | 334 | fn bench_issue35(bench: &mut Bencher) { 335 | let nm = "issue35"; 336 | let (data, holeidxs, dimensions) = load_json(nm); 337 | let mut triangles = Vec::new(); 338 | bench.iter(|| { 339 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 340 | }); 341 | mkoutput(nm, triangles); 342 | } 343 | 344 | fn bench_self_touching(bench: &mut Bencher) { 345 | let nm = "self-touching"; 346 | let (data, holeidxs, dimensions) = load_json(nm); 347 | let mut triangles = Vec::new(); 348 | bench.iter(|| { 349 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 350 | }); 351 | mkoutput(nm, triangles); 352 | } 353 | 354 | fn bench_outside_ring(bench: &mut Bencher) { 355 | let nm = "outside-ring"; 356 | let (data, holeidxs, dimensions) = load_json(nm); 357 | let mut triangles = Vec::new(); 358 | bench.iter(|| { 359 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 360 | }); 361 | mkoutput(nm, triangles); 362 | } 363 | 364 | fn bench_simplified_us_border(bench: &mut Bencher) { 365 | let nm = "simplified-us-border"; 366 | let (data, holeidxs, dimensions) = load_json(nm); 367 | let mut triangles = Vec::new(); 368 | bench.iter(|| { 369 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 370 | }); 371 | mkoutput(nm, triangles); 372 | } 373 | 374 | fn bench_touching_holes(bench: &mut Bencher) { 375 | let nm = "touching-holes"; 376 | let (data, holeidxs, dimensions) = load_json(nm); 377 | let mut triangles = Vec::new(); 378 | bench.iter(|| { 379 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 380 | }); 381 | mkoutput(nm, triangles); 382 | } 383 | 384 | fn bench_hole_touching_outer(bench: &mut Bencher) { 385 | let nm = "hole-touching-outer"; 386 | let (data, holeidxs, dimensions) = load_json(nm); 387 | let mut triangles = Vec::new(); 388 | bench.iter(|| { 389 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 390 | }); 391 | mkoutput(nm, triangles); 392 | } 393 | 394 | fn bench_hilbert(bench: &mut Bencher) { 395 | let nm = "hilbert"; 396 | let (data, holeidxs, dimensions) = load_json(nm); 397 | let mut triangles = Vec::new(); 398 | bench.iter(|| { 399 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 400 | }); 401 | mkoutput(nm, triangles); 402 | } 403 | 404 | fn bench_issue45(bench: &mut Bencher) { 405 | let nm = "issue45"; 406 | let (data, holeidxs, dimensions) = load_json(nm); 407 | let mut triangles = Vec::new(); 408 | bench.iter(|| { 409 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 410 | }); 411 | mkoutput(nm, triangles); 412 | } 413 | 414 | fn bench_eberly_3(bench: &mut Bencher) { 415 | let nm = "eberly-3"; 416 | let (data, holeidxs, dimensions) = load_json(nm); 417 | let mut triangles = Vec::new(); 418 | bench.iter(|| { 419 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 420 | }); 421 | mkoutput(nm, triangles); 422 | } 423 | 424 | fn bench_eberly_6(bench: &mut Bencher) { 425 | let nm = "eberly-6"; 426 | let (data, holeidxs, dimensions) = load_json(nm); 427 | let mut triangles = Vec::new(); 428 | bench.iter(|| { 429 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 430 | }); 431 | mkoutput(nm, triangles); 432 | } 433 | 434 | fn bench_issue52(bench: &mut Bencher) { 435 | let nm = "issue52"; 436 | let (data, holeidxs, dimensions) = load_json(nm); 437 | let mut triangles = Vec::new(); 438 | bench.iter(|| { 439 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 440 | }); 441 | mkoutput(nm, triangles); 442 | } 443 | 444 | fn bench_shared_points(bench: &mut Bencher) { 445 | let nm = "shared-points"; 446 | let (data, holeidxs, dimensions) = load_json(nm); 447 | let mut triangles = Vec::new(); 448 | bench.iter(|| { 449 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 450 | }); 451 | mkoutput(nm, triangles); 452 | } 453 | 454 | fn bench_bad_diagonals(bench: &mut Bencher) { 455 | let nm = "bad-diagonals"; 456 | let (data, holeidxs, dimensions) = load_json(nm); 457 | let mut triangles = Vec::new(); 458 | bench.iter(|| { 459 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 460 | }); 461 | mkoutput(nm, triangles); 462 | } 463 | 464 | fn bench_issue83(bench: &mut Bencher) { 465 | let nm = "issue83"; 466 | let (data, holeidxs, dimensions) = load_json(nm); 467 | let mut triangles = Vec::new(); 468 | bench.iter(|| { 469 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 470 | }); 471 | mkoutput(nm, triangles); 472 | } 473 | 474 | benchmark_group!( 475 | benches, 476 | bench_indices_3d, 477 | bench_indices_2d, 478 | bench_empty, 479 | bench_quadrilateral, 480 | bench_hole, 481 | bench_flatten, 482 | bench_bad_diagonals, 483 | bench_bad_hole, 484 | bench_building, 485 | bench_degenerate, 486 | bench_dude, 487 | bench_eberly_3, 488 | bench_eberly_6, 489 | bench_empty_square, 490 | bench_hilbert, 491 | bench_hole_touching_outer, 492 | bench_issue16, 493 | bench_issue17, 494 | bench_issue29, 495 | bench_issue34, 496 | bench_issue35, 497 | bench_issue45, 498 | bench_issue52, 499 | bench_issue83, 500 | bench_outside_ring, 501 | bench_self_touching, 502 | bench_shared_points, 503 | bench_simplified_us_border, 504 | bench_steiner, 505 | bench_touching_holes, 506 | bench_water_huge, 507 | bench_water_huge2, 508 | bench_water, 509 | bench_water2, 510 | bench_water3, 511 | bench_water3b, 512 | bench_water4, 513 | ); 514 | benchmark_main!(benches); 515 | -------------------------------------------------------------------------------- /examples/main.rs: -------------------------------------------------------------------------------- 1 | extern crate earcutr; 2 | extern crate serde; 3 | extern crate serde_json; 4 | use std::fs::File; 5 | use std::fs::OpenOptions; 6 | use std::io::Read; 7 | use std::io::Write; 8 | use std::time::Instant; 9 | 10 | fn mkoutput(filename_w_dashes: &str, triangles: Vec) { 11 | let filename = str::replace(filename_w_dashes, "-", "_"); 12 | let outfile = &format!("examples/output/{}.js", filename); 13 | match OpenOptions::new() 14 | .write(true) 15 | .create(true) 16 | .truncate(true) 17 | .open(outfile) 18 | { 19 | Err(e) => println!("error writing {} {}", outfile, e), 20 | Ok(f) => writeln!( 21 | &f, 22 | r###"testOutput["{}"]["benchmark"]=[{:?},{:?},{:?}];"###, 23 | filename, 24 | 0, 25 | triangles.len(), 26 | triangles 27 | ) 28 | .unwrap(), 29 | }; 30 | } 31 | 32 | fn parse_json(rawdata: &str) -> Option>>> { 33 | let mut v: Vec>> = Vec::new(); 34 | match serde_json::from_str::(&rawdata) { 35 | Err(e) => println!("error deserializing, {}", e), 36 | Ok(jsondata) => { 37 | if jsondata.is_array() { 38 | let contours = jsondata.as_array().unwrap(); 39 | for i in 0..contours.len() { 40 | let contourval = &contours[i]; 41 | if contourval.is_array() { 42 | let contour = contourval.as_array().unwrap(); 43 | let mut vc: Vec> = Vec::new(); 44 | for j in 0..contour.len() { 45 | let points = contour[j].as_array().unwrap(); 46 | let mut vp: Vec = Vec::new(); 47 | for k in 0..points.len() { 48 | let val = points[k].to_string(); 49 | let pval = val.parse::().unwrap(); 50 | vp.push(pval); 51 | } 52 | vc.push(vp); 53 | } 54 | v.push(vc); 55 | } 56 | } 57 | } 58 | } 59 | }; 60 | return Some(v); 61 | } 62 | 63 | fn load_json(testname: &str) -> (Vec, Vec, usize) { 64 | let fullname = format!("./tests/fixtures/{}.json", testname); 65 | let mut xdata: Vec>> = Vec::new(); 66 | match File::open(&fullname) { 67 | Err(why) => println!("failed to open file '{}': {}", fullname, why), 68 | Ok(mut f) => { 69 | //println!("testing {},", fullname); 70 | let mut strdata = String::new(); 71 | match f.read_to_string(&mut strdata) { 72 | Err(why) => println!("failed to read {}, {}", fullname, why), 73 | Ok(_numb) => { 74 | //println!("read {} bytes", numb); 75 | let rawstring = strdata.trim(); 76 | match parse_json(rawstring) { 77 | None => println!("failed to parse {}", fullname), 78 | Some(parsed_data) => { 79 | xdata = parsed_data; 80 | } 81 | }; 82 | } 83 | }; 84 | } 85 | }; 86 | return earcutr::flatten(&xdata); 87 | } 88 | 89 | fn benchy(nm: &str) { 90 | let (data, holeidxs, dimensions) = load_json(nm); 91 | let mut triangles = Vec::new(); 92 | let now = Instant::now(); 93 | let iters = 99u32; 94 | 95 | println!("report for {}", nm); 96 | for _ in 0..iters { 97 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 98 | } 99 | println!("{:?}", triangles); 100 | println!("num tris {}", triangles.len() / 3); 101 | println!( 102 | "Duration: {} seconds and {} nanoseconds", 103 | now.elapsed().as_secs(), 104 | now.elapsed().subsec_nanos() 105 | ); 106 | println!("ns/iter {}", now.elapsed().subsec_nanos() / (iters)); 107 | 108 | mkoutput(nm, triangles); 109 | } 110 | 111 | fn main() { 112 | benchy("water"); 113 | // benchy("water2"); 114 | } 115 | -------------------------------------------------------------------------------- /src/node.rs: -------------------------------------------------------------------------------- 1 | use crate::{NodeIdx, VertIdx, NULL}; 2 | use std::ops::Sub; 3 | 4 | #[derive(Clone, Debug)] 5 | pub struct Node { 6 | pub i: VertIdx, // vertex index in flat one-d array of 64bit float coords 7 | pub x: f64, // vertex x coordinate 8 | pub y: f64, // vertex y coordinate 9 | pub prev_idx: NodeIdx, // previous vertex node in a polygon ring 10 | pub next_idx: NodeIdx, // next vertex node in a polygon ring 11 | pub z: i32, // z-order curve value 12 | pub prevz_idx: NodeIdx, // previous node in z-order 13 | pub nextz_idx: NodeIdx, // next node in z-order 14 | pub steiner: bool, // indicates whether this is a steiner point 15 | pub idx: NodeIdx, // index within LinkedLists vector that holds all nodes 16 | } 17 | 18 | impl<'a> Sub for &'a Node { 19 | type Output = Node; 20 | 21 | fn sub(self, other: &'a Node) -> Node { 22 | Node::new(NULL, self.x - other.x, self.y - other.y, NULL) 23 | } 24 | } 25 | 26 | // check if two points are equal 27 | pub fn equal_coords(p1: &Node, p2: &Node) -> bool { 28 | p1.x == p2.x && p1.y == p2.y 29 | } 30 | 31 | impl Node { 32 | pub fn new(i: VertIdx, x: f64, y: f64, idx: NodeIdx) -> Node { 33 | Node { 34 | i: i, 35 | x: x, 36 | y: y, 37 | prev_idx: NULL, 38 | next_idx: NULL, 39 | z: 0, 40 | nextz_idx: NULL, 41 | prevz_idx: NULL, 42 | steiner: false, 43 | idx: idx, 44 | } 45 | } 46 | pub fn prev<'a>(&'a self, ll: &'a LinkedLists) -> &Node { 47 | &self.idx.prev(ll).node(ll) 48 | } 49 | pub fn next<'a>(&'a self, ll: &'a LinkedLists) -> &Node { 50 | &self.idx.next(ll).node(ll) 51 | } 52 | } 53 | 54 | // Extension Trait for NodeIdx 55 | // this allows us to do stuff like i.next(ll).next(ll) 56 | // which helps to write linked list code in a more concise, clear fashion 57 | pub trait NodeIndex { 58 | fn next(self, ll: &LinkedLists) -> NodeIdx; 59 | fn nextz(self, ll: &LinkedLists) -> NodeIdx; 60 | fn prevz(self, ll: &LinkedLists) -> NodeIdx; 61 | fn prev(self, ll: &LinkedLists) -> NodeIdx; 62 | fn set_next(self, ll: &mut LinkedLists, i: NodeIdx); 63 | fn set_nextz(self, ll: &mut LinkedLists, i: NodeIdx); 64 | fn node(self, ll: &LinkedLists) -> &Node; 65 | fn set_prev(self, ll: &mut LinkedLists, i: NodeIdx); 66 | fn set_prevz(self, ll: &mut LinkedLists, i: NodeIdx); 67 | fn set_z(self, ll: &mut LinkedLists, z: i32); 68 | fn set_steiner(self, ll: &mut LinkedLists, v: bool); 69 | } 70 | 71 | // Extension Trait implementation. NodeIdx is typically just usize 72 | // so basically we are extending the integers to allow looking up nodes in a linked list 73 | // by calling methods on integers. for example 74 | // 75 | // i is an NodeIdx ll is a LinkedLists 76 | // i.next(ll).next(ll) // this gets the index of the node after the node after i 77 | // 78 | impl NodeIndex for NodeIdx { 79 | fn next(self, ll: &LinkedLists) -> NodeIdx { 80 | ll.nodes[self].next_idx 81 | } 82 | fn nextz(self, ll: &LinkedLists) -> NodeIdx { 83 | ll.nodes[self].nextz_idx 84 | } 85 | fn prevz(self, ll: &LinkedLists) -> NodeIdx { 86 | ll.nodes[self].prevz_idx 87 | } 88 | fn prev(self, ll: &LinkedLists) -> NodeIdx { 89 | ll.nodes[self].prev_idx 90 | } 91 | fn set_next(self, ll: &mut LinkedLists, i: NodeIdx) { 92 | ll.nodes.get_mut(self).unwrap().next_idx = i; 93 | } 94 | fn set_nextz(self, ll: &mut LinkedLists, i: NodeIdx) { 95 | ll.nodes.get_mut(self).unwrap().nextz_idx = i; 96 | } 97 | fn set_prev(self, ll: &mut LinkedLists, i: NodeIdx) { 98 | ll.nodes.get_mut(self).unwrap().prev_idx = i; 99 | } 100 | fn set_prevz(self, ll: &mut LinkedLists, i: NodeIdx) { 101 | ll.nodes.get_mut(self).unwrap().prevz_idx = i; 102 | } 103 | fn set_z(self, ll: &mut LinkedLists, z: i32) { 104 | ll.nodes.get_mut(self).unwrap().z = z; 105 | } 106 | fn set_steiner(self, ll: &mut LinkedLists, v: bool) { 107 | ll.nodes.get_mut(self).unwrap().steiner = v; 108 | } 109 | fn node(self, ll: &LinkedLists) -> &Node { 110 | &ll.nodes[self] 111 | } 112 | } 113 | 114 | pub struct LinkedLists { 115 | pub nodes: Vec, 116 | pub invsize: f64, 117 | pub minx: f64, 118 | pub miny: f64, 119 | pub maxx: f64, 120 | pub maxy: f64, 121 | } 122 | 123 | #[macro_export] 124 | macro_rules! dlog { 125 | ($loglevel:expr, $($s:expr),*) => ( 126 | if DEBUG>=$loglevel { print!("{}:",$loglevel); println!($($s),+); } 127 | ) 128 | } 129 | 130 | impl LinkedLists { 131 | pub fn iter(&self, r: std::ops::Range) -> NodeIterator { 132 | return NodeIterator::new(self, r.start, r.end); 133 | } 134 | pub fn iter_pairs(&self, r: std::ops::Range) -> NodePairIterator { 135 | return NodePairIterator::new(self, r.start, r.end); 136 | } 137 | pub fn insert_node(&mut self, i: VertIdx, x: f64, y: f64, last: NodeIdx) -> NodeIdx { 138 | let mut p = Node::new(i, x, y, self.nodes.len()); 139 | if last == NULL { 140 | p.next_idx = p.idx; 141 | p.prev_idx = p.idx; 142 | } else { 143 | p.next_idx = last.next(self); 144 | p.prev_idx = last; 145 | let lastnextidx = last.next(self); 146 | lastnextidx.set_prev(self, p.idx); 147 | last.set_next(self, p.idx); 148 | }; 149 | let result = p.idx; 150 | self.nodes.push(p); 151 | return result; 152 | } 153 | pub fn remove_node(&mut self, p_idx: NodeIdx) { 154 | let pi = p_idx.prev(self); 155 | let ni = p_idx.next(self); 156 | let pz = p_idx.prevz(self); 157 | let nz = p_idx.nextz(self); 158 | pi.set_next(self, ni); 159 | ni.set_prev(self, pi); 160 | pz.set_nextz(self, nz); 161 | nz.set_prevz(self, pz); 162 | } 163 | pub fn new(size_hint: usize) -> LinkedLists { 164 | let mut ll = LinkedLists { 165 | nodes: Vec::with_capacity(size_hint), 166 | invsize: 0.0, 167 | minx: std::f64::MAX, 168 | miny: std::f64::MAX, 169 | maxx: std::f64::MIN, 170 | maxy: std::f64::MIN, 171 | }; 172 | // ll.nodes[0] is the NULL node. For example usage, see remove_node() 173 | ll.nodes.push(Node { 174 | i: 0, 175 | x: 0.0, 176 | y: 0.0, 177 | prev_idx: 0, 178 | next_idx: 0, 179 | z: 0, 180 | nextz_idx: 0, 181 | prevz_idx: 0, 182 | steiner: false, 183 | idx: 0, 184 | }); 185 | ll 186 | } 187 | pub fn node(&self, i: NodeIdx) -> &Node { 188 | &self.nodes[i] 189 | } 190 | } 191 | 192 | pub struct NodeIterator<'a> { 193 | cur: NodeIdx, 194 | end: NodeIdx, 195 | ll: &'a LinkedLists, 196 | pending_result: Option<&'a Node>, 197 | } 198 | 199 | impl<'a> NodeIterator<'a> { 200 | pub fn new(ll: &LinkedLists, start: NodeIdx, end: NodeIdx) -> NodeIterator { 201 | NodeIterator { 202 | pending_result: Some(ll.node(start)), 203 | cur: start, 204 | end: end, 205 | ll, 206 | } 207 | } 208 | } 209 | 210 | impl<'a> Iterator for NodeIterator<'a> { 211 | type Item = &'a Node; 212 | fn next(&mut self) -> Option { 213 | self.cur = self.cur.next(self.ll); 214 | let cur_result = self.pending_result; 215 | if self.cur == self.end { 216 | // only one branch, saves time 217 | self.pending_result = None; 218 | } else { 219 | self.pending_result = Some(self.ll.node(self.cur)); 220 | } 221 | cur_result 222 | } 223 | } 224 | 225 | pub struct NodePairIterator<'a> { 226 | cur: NodeIdx, 227 | end: NodeIdx, 228 | ll: &'a LinkedLists, 229 | pending_result: Option<(&'a Node, &'a Node)>, 230 | } 231 | 232 | impl<'a> NodePairIterator<'a> { 233 | pub fn new(ll: &LinkedLists, start: NodeIdx, end: NodeIdx) -> NodePairIterator { 234 | NodePairIterator { 235 | pending_result: Some((ll.node(start), start.next(ll).node(ll))), 236 | cur: start, 237 | end: end, 238 | ll, 239 | } 240 | } 241 | } 242 | 243 | impl<'a> Iterator for NodePairIterator<'a> { 244 | type Item = (&'a Node, &'a Node); 245 | fn next(&mut self) -> Option { 246 | self.cur = self.cur.next(self.ll); 247 | let cur_result = self.pending_result; 248 | if self.cur == self.end { 249 | // only one branch, saves time 250 | self.pending_result = None; 251 | } else { 252 | self.pending_result = 253 | Some((self.ll.node(self.cur), self.ll.node(self.cur).next(self.ll))) 254 | } 255 | cur_result 256 | } 257 | } 258 | 259 | pub fn pn(a: usize) -> String { 260 | match a { 261 | 0x777A91CC => String::from("NULL"), 262 | _ => a.to_string(), 263 | } 264 | } 265 | pub fn pb(a: bool) -> String { 266 | match a { 267 | true => String::from("x"), 268 | false => String::from(" "), 269 | } 270 | } 271 | pub fn dump(ll: &LinkedLists) -> String { 272 | let mut s = format!("LL, #nodes: {}", ll.nodes.len()); 273 | s.push_str(&format!( 274 | " #used: {}\n", 275 | // ll.nodes.len() as i64 - ll.freelist.len() as i64 276 | ll.nodes.len() as i64 277 | )); 278 | s.push_str(&format!( 279 | " {:>3} {:>3} {:>4} {:>4} {:>8.3} {:>8.3} {:>4} {:>4} {:>2} {:>2} {:>2} {:>4}\n", 280 | "vi", "i", "p", "n", "x", "y", "pz", "nz", "st", "fr", "cyl", "z" 281 | )); 282 | for n in &ll.nodes { 283 | s.push_str(&format!( 284 | " {:>3} {:>3} {:>4} {:>4} {:>8.3} {:>8.3} {:>4} {:>4} {:>2} {:>2} {:>2} {:>4}\n", 285 | n.idx, 286 | n.i, 287 | pn(n.prev_idx), 288 | pn(n.next_idx), 289 | n.x, 290 | n.y, 291 | pn(n.prevz_idx), 292 | pn(n.nextz_idx), 293 | pb(n.steiner), 294 | false, 295 | // pb(ll.freelist.contains(&n.idx)), 296 | 0, //,ll.iter(n.idx..n.idx).count(), 297 | n.z, 298 | )); 299 | } 300 | return s; 301 | } 302 | 303 | pub fn cycle_dump(ll: &LinkedLists, p: NodeIdx) -> String { 304 | let mut s = format!("cycle from {}, ", p); 305 | s.push_str(&format!(" len {}, idxs:", 0)); //cycle_len(&ll, p))); 306 | let mut i = p; 307 | let end = i; 308 | let mut count = 0; 309 | loop { 310 | count += 1; 311 | s.push_str(&format!("{} ", i.node(ll).idx)); 312 | s.push_str(&format!("(i:{}), ", i.node(ll).i)); 313 | i = i.next(ll); 314 | if i == end { 315 | break s; 316 | } 317 | if count > ll.nodes.len() { 318 | s.push_str(&format!(" infinite loop")); 319 | break s; 320 | } 321 | } 322 | } 323 | 324 | pub fn cycles_report(ll: &LinkedLists) -> String { 325 | if ll.nodes.len() == 1 { 326 | return format!("[]"); 327 | } 328 | let mut markv: Vec = Vec::new(); 329 | markv.resize(ll.nodes.len(), NULL); 330 | let mut cycler; 331 | for i in 0..markv.len() { 332 | // if ll.freelist.contains(&i) { 333 | if true { 334 | markv[i] = NULL; 335 | } else if markv[i] == NULL { 336 | cycler = i; 337 | let mut p = i; 338 | let end = p.prev(ll); 339 | markv[p] = cycler; 340 | let mut count = 0; 341 | loop { 342 | p = p.next(ll); 343 | markv[p] = cycler; 344 | count += 1; 345 | if p == end || count > ll.nodes.len() { 346 | break; 347 | } 348 | } // loop 349 | } // if markvi == 0 350 | } //for markv 351 | format!("cycles report:\n{:?}", markv) 352 | } 353 | 354 | pub fn dump_cycle(ll: &LinkedLists, start: usize) -> String { 355 | let mut s = format!("LL, #nodes: {}", ll.nodes.len()); 356 | // s.push_str(&format!(" #used: {}\n", ll.nodes.len() - ll.freelist.len())); 357 | s.push_str(&format!(" #used: {}\n", ll.nodes.len())); 358 | s.push_str(&format!( 359 | " {:>3} {:>3} {:>3} {:>4} {:>4} {:>8.3} {:>8.3} {:>4} {:>4} {:>2} {:>2} {:>2}\n", 360 | "#", "vi", "i", "p", "n", "x", "y", "pz", "nz", "st", "fr", "cyl" 361 | )); 362 | let mut startidx: usize = 0; 363 | for n in &ll.nodes { 364 | if n.i == start { 365 | startidx = n.idx; 366 | }; 367 | } 368 | let endidx = startidx; 369 | let mut idx = startidx; 370 | let mut count = 0; 371 | let mut state; // = 0i32; 372 | loop { 373 | let n = idx.node(ll); 374 | state = 0; //horsh( state, n.i as i32); 375 | s.push_str(&format!( 376 | " {:>3} {:>3} {:>3} {:>4} {:>4} {:>8.3} {:>8.3} {:>4} {:>4} {:>2} {:>2} {:>2}\n", 377 | count, 378 | n.idx, 379 | n.i, 380 | n.prev(ll).i, 381 | n.next(ll).i, 382 | n.x, 383 | n.y, 384 | pn(n.prevz_idx), 385 | pn(n.nextz_idx), 386 | pb(n.steiner), 387 | // pb(ll.freelist.contains(&n.idx)), 388 | false, 389 | cycle_len(&ll, n.idx), 390 | )); 391 | idx = idx.next(ll); 392 | count += 1; 393 | if idx == endidx || count > ll.nodes.len() { 394 | break; 395 | } 396 | } 397 | s.push_str(&format!("dump end, horshcount:{} horsh:{}", count, state)); 398 | return s; 399 | } 400 | 401 | pub fn cycle_len(ll: &LinkedLists, p: NodeIdx) -> usize { 402 | if p >= ll.nodes.len() { 403 | return 0; 404 | } 405 | let end = p.prev(ll); 406 | let mut i = p; 407 | let mut count = 1; 408 | loop { 409 | i = i.next(ll); 410 | count += 1; 411 | if i == end { 412 | break count; 413 | } 414 | if count > ll.nodes.len() { 415 | break count; 416 | } 417 | } 418 | } 419 | 420 | #[cfg(test)] 421 | mod tests { 422 | use super::*; 423 | 424 | // https://www.cs.hmc.edu/~geoff/classes/hmc.cs070.200101/homework10/hashfuncs.$ 425 | // https://stackoverflow.com/questions/1908492/unsigned-integer-in-javascript 426 | fn horsh(mut h: u32, n: u32) -> u32 { 427 | let highorder = h & 0xf8000000; // extract high-order 5 bits from h 428 | // 0xf8000000 is the hexadecimal representat$ 429 | // for the 32-bit number with the first fi$ 430 | // bits = 1 and the other bits = 0 431 | h = h << 5; // shift h left by 5 bits 432 | h = h ^ (highorder >> 27); // move the highorder 5 bits to the low-ord$ 433 | // end and XOR into h 434 | h = h ^ n; // XOR h and ki 435 | return h; 436 | } 437 | 438 | // find the node with 'i' of starti, horsh it 439 | fn horsh_ll(ll: &LinkedLists, starti: VertIdx) -> String { 440 | let mut s = format!("LL horsh: "); 441 | let mut startidx: usize = 0; 442 | for n in &ll.nodes { 443 | if n.i == starti { 444 | startidx = n.idx; 445 | }; 446 | } 447 | let endidx = startidx; 448 | let mut idx = startidx; 449 | let mut count = 0; 450 | let mut state = 0u32; 451 | loop { 452 | let n = idx.node(ll); 453 | state = horsh(state, n.i as u32); 454 | idx = idx.next(ll); 455 | count += 1; 456 | if idx == endidx || count > ll.nodes.len() { 457 | break; 458 | } 459 | } 460 | s.push_str(&format!(" count:{} horsh: {}", count, state)); 461 | return s; 462 | } 463 | } 464 | -------------------------------------------------------------------------------- /tests/fixtures/bad-diagonals.json: -------------------------------------------------------------------------------- 1 | [[[440,4152],[440,4208],[296,4192],[368,4192],[400,4200],[400,4176],[368,4192],[296,4192],[264,4200],[288,4160],[296,4192]]] 2 | -------------------------------------------------------------------------------- /tests/fixtures/bad-hole.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[810,2828],[818,2828],[832,2818],[844,2806],[855,2808],[866,2816],[867,2824],[876,2827],[883,2834],[875,2834],[867,2840],[878,2838],[889,2844],[880,2847],[870,2847],[860,2864],[852,2879],[847,2867],[810,2828],[810,2828]], 3 | [[818,2834],[823,2833],[831,2828],[839,2829],[839,2837],[851,2845],[847,2835],[846,2827],[847,2827],[837,2827],[840,2815],[835,2823],[818,2834],[818,2834]], 4 | [[857,2846],[864,2850],[866,2839],[857,2846],[857,2846]], 5 | [[848,2863],[848,2866],[854,2852],[846,2854],[847,2862],[838,2851],[838,2859],[848,2863],[848,2863]] 6 | ] 7 | -------------------------------------------------------------------------------- /tests/fixtures/building.json: -------------------------------------------------------------------------------- 1 | [[[661,112],[661,96],[666,96],[666,87],[743,87],[771,87],[771,114],[750,114],[750,113],[742,113],[742,106],[710,106],[710,113],[666,113],[666,112]]] 2 | -------------------------------------------------------------------------------- /tests/fixtures/degenerate.json: -------------------------------------------------------------------------------- 1 | [[[100,100],[100,100],[200,100],[200,200],[200,100],[0,100]]] 2 | -------------------------------------------------------------------------------- /tests/fixtures/dude.json: -------------------------------------------------------------------------------- 1 | [[[280.35714, 648.79075],[286.78571, 662.8979],[263.28607, 661.17871],[262.31092, 671.41548],[250.53571, 677.00504],[250.53571, 683.43361],[256.42857, 685.21933],[297.14286, 669.50504],[289.28571, 649.50504],[285, 631.6479],[285, 608.79075],[292.85714, 585.21932],[306.42857, 563.79075],[323.57143, 548.79075],[339.28571, 545.21932],[357.85714, 547.36218],[375, 550.21932],[391.42857, 568.07647],[404.28571, 588.79075],[413.57143, 612.36218],[417.14286, 628.07647],[438.57143, 619.1479],[438.03572, 618.96932],[437.5, 609.50504],[426.96429, 609.86218],[424.64286, 615.57647],[419.82143, 615.04075],[420.35714, 605.04075],[428.39286, 598.43361],[437.85714, 599.68361],[443.57143, 613.79075],[450.71429, 610.21933],[431.42857, 575.21932],[405.71429, 550.21932],[372.85714, 534.50504],[349.28571, 531.6479],[346.42857, 521.6479],[346.42857, 511.6479],[350.71429, 496.6479],[367.85714, 476.6479],[377.14286, 460.93361],[385.71429, 445.21932],[388.57143, 404.50504],[360, 352.36218],[337.14286, 325.93361],[330.71429, 334.50504],[347.14286, 354.50504],[337.85714, 370.21932],[333.57143, 359.50504],[319.28571, 353.07647],[312.85714, 366.6479],[350.71429, 387.36218],[368.57143, 408.07647],[375.71429, 431.6479],[372.14286, 454.50504],[366.42857, 462.36218],[352.85714, 462.36218],[336.42857, 456.6479],[332.85714, 438.79075],[338.57143, 423.79075],[338.57143, 411.6479],[327.85714, 405.93361],[320.71429, 407.36218],[315.71429, 423.07647],[314.28571, 440.21932],[325, 447.71932],[324.82143, 460.93361],[317.85714, 470.57647],[304.28571, 483.79075],[287.14286, 491.29075],[263.03571, 498.61218],[251.60714, 503.07647],[251.25, 533.61218],[260.71429, 533.61218],[272.85714, 528.43361],[286.07143, 518.61218],[297.32143, 508.25504],[297.85714, 507.36218],[298.39286, 506.46932],[307.14286, 496.6479],[312.67857, 491.6479],[317.32143, 503.07647],[322.5, 514.1479],[325.53571, 521.11218],[327.14286, 525.75504],[326.96429, 535.04075],[311.78571, 540.04075],[291.07143, 552.71932],[274.82143, 568.43361],[259.10714, 592.8979],[254.28571, 604.50504],[251.07143, 621.11218],[250.53571, 649.1479],[268.1955, 654.36208]],[[325, 437], [320, 423], [329, 413], [332, 423]],[[320.72342, 480], [338.90617, 465.96863], [347.99754, 480.61584], [329.8148, 510.41534], [339.91632, 480.11077], [334.86556, 478.09046]]] 2 | -------------------------------------------------------------------------------- /tests/fixtures/eberly-3.json: -------------------------------------------------------------------------------- 1 | [[[2328,2408],[2328,2472],[2344,2472],[2344,2432],[2384,2448],[2384,2536],[2408,2552],[2448,2544],[2456,2560],[2496,2544],[2480,2624],[2456,2664],[2424,2680],[2400,2768],[2376,2768],[2368,2704],[2336,2704],[2264,2784],[2216,2784],[2200,2760],[2168,2760],[2152,2744],[2128,2744],[2128,2784],[2072,2768],[2032,2720],[2000,2720],[2000,2688],[1936,2696],[1920,2736],[1888,2728],[1896,2696],[1928,2688],[1928,2664],[1896,2664],[1896,2640],[1912,2632],[1872,2608],[1888,2576],[2056,2576],[2088,2600],[2184,2608],[2216,2632],[2256,2624],[2248,2600],[2216,2592],[2192,2560],[2120,2576],[2072,2544],[2096,2544],[2080,2520],[2080,2488],[2096,2480],[2080,2448],[2096,2432],[2176,2496],[2200,2488],[2224,2528],[2248,2528],[2240,2488],[2256,2472],[2280,2480],[2264,2416],[2272,2392],[2328,2408]],[[2320,2608],[2304,2640],[2312,2664],[2360,2632],[2352,2608],[2320,2608]],[[1912,2632],[1936,2632],[1936,2616],[1912,2608],[1912,2632]]] 2 | -------------------------------------------------------------------------------- /tests/fixtures/empty-square.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[0,0],[4000,0],[4000,4000],[0,4000]], 3 | [[0,0],[4000,0],[4000,4000],[0,4000]] 4 | ] 5 | -------------------------------------------------------------------------------- /tests/fixtures/hilbert.json: -------------------------------------------------------------------------------- 1 | [[[0,0],[-1,0],[-1,-1],[0,-1],[0,-2],[0,-3],[-1,-3],[-1,-2],[-2,-2],[-2,-3],[-3,-3],[-3,-2],[-3,-1],[-2,-1],[-2,0],[-3,0],[-4,0],[-4,-1],[-5,-1],[-5,0],[-6,0],[-7,0],[-7,-1],[-6,-1],[-6,-2],[-7,-2],[-7,-3],[-6,-3],[-5,-3],[-5,-2],[-4,-2],[-4,-3],[-4,-4],[-4,-5],[-5,-5],[-5,-4],[-6,-4],[-7,-4],[-7,-5],[-6,-5],[-6,-6],[-7,-6],[-7,-7],[-6,-7],[-5,-7],[-5,-6],[-4,-6],[-4,-7],[-3,-7],[-2,-7],[-2,-6],[-3,-6],[-3,-5],[-3,-4],[-2,-4],[-2,-5],[-1,-5],[-1,-4],[0,-4],[0,-5],[0,-6],[-1,-6],[-1,-7],[0,-7],[0,-8],[0,-9],[-1,-9],[-1,-8],[-2,-8],[-3,-8],[-3,-9],[-2,-9],[-2,-10],[-3,-10],[-3,-11],[-2,-11],[-1,-11],[-1,-10],[0,-10],[0,-11],[0,-12],[-1,-12],[-1,-13],[0,-13],[0,-14],[0,-15],[-1,-15],[-1,-14],[-2,-14],[-2,-15],[-3,-15],[-3,-14],[-3,-13],[-2,-13],[-2,-12],[-3,-12],[-4,-12],[-5,-12],[-5,-13],[-4,-13],[-4,-14],[-4,-15],[-5,-15],[-5,-14],[-6,-14],[-6,-15],[-7,-15],[-7,-14],[-7,-13],[-6,-13],[-6,-12],[-7,-12],[-7,-11],[-7,-10],[-6,-10],[-6,-11],[-5,-11],[-4,-11],[-4,-10],[-5,-10],[-5,-9],[-4,-9],[-4,-8],[-5,-8],[-6,-8],[-6,-9],[-7,-9],[-7,-8],[-8,-8],[-8,-9],[-9,-9],[-9,-8],[-10,-8],[-11,-8],[-11,-9],[-10,-9],[-10,-10],[-11,-10],[-11,-11],[-10,-11],[-9,-11],[-9,-10],[-8,-10],[-8,-11],[-8,-12],[-9,-12],[-9,-13],[-8,-13],[-8,-14],[-8,-15],[-9,-15],[-9,-14],[-10,-14],[-10,-15],[-11,-15],[-11,-14],[-11,-13],[-10,-13],[-10,-12],[-11,-12],[-12,-12],[-13,-12],[-13,-13],[-12,-13],[-12,-14],[-12,-15],[-13,-15],[-13,-14],[-14,-14],[-14,-15],[-15,-15],[-15,-14],[-15,-13],[-14,-13],[-14,-12],[-15,-12],[-15,-11],[-15,-10],[-14,-10],[-14,-11],[-13,-11],[-12,-11],[-12,-10],[-13,-10],[-13,-9],[-12,-9],[-12,-8],[-13,-8],[-14,-8],[-14,-9],[-15,-9],[-15,-8],[-15,-7],[-14,-7],[-14,-6],[-15,-6],[-15,-5],[-15,-4],[-14,-4],[-14,-5],[-13,-5],[-13,-4],[-12,-4],[-12,-5],[-12,-6],[-13,-6],[-13,-7],[-12,-7],[-11,-7],[-11,-6],[-10,-6],[-10,-7],[-9,-7],[-8,-7],[-8,-6],[-9,-6],[-9,-5],[-8,-5],[-8,-4],[-9,-4],[-10,-4],[-10,-5],[-11,-5],[-11,-4],[-11,-3],[-11,-2],[-10,-2],[-10,-3],[-9,-3],[-8,-3],[-8,-2],[-9,-2],[-9,-1],[-8,-1],[-8,0],[-9,0],[-10,0],[-10,-1],[-11,-1],[-11,0],[-12,0],[-13,0],[-13,-1],[-12,-1],[-12,-2],[-12,-3],[-13,-3],[-13,-2],[-14,-2],[-14,-3],[-15,-3],[-15,-2],[-15,-1],[-14,-1],[-14,0],[-15,0],[-16,0],[-16,-1],[-17,-1],[-17,0],[-18,0],[-19,0],[-19,-1],[-18,-1],[-18,-2],[-19,-2],[-19,-3],[-18,-3],[-17,-3],[-17,-2],[-16,-2],[-16,-3],[-16,-4],[-17,-4],[-17,-5],[-16,-5],[-16,-6],[-16,-7],[-17,-7],[-17,-6],[-18,-6],[-18,-7],[-19,-7],[-19,-6],[-19,-5],[-18,-5],[-18,-4],[-19,-4],[-20,-4],[-21,-4],[-21,-5],[-20,-5],[-20,-6],[-20,-7],[-21,-7],[-21,-6],[-22,-6],[-22,-7],[-23,-7],[-23,-6],[-23,-5],[-22,-5],[-22,-4],[-23,-4],[-23,-3],[-23,-2],[-22,-2],[-22,-3],[-21,-3],[-20,-3],[-20,-2],[-21,-2],[-21,-1],[-20,-1],[-20,0],[-21,0],[-22,0],[-22,-1],[-23,-1],[-23,0],[-24,0],[-25,0],[-25,-1],[-24,-1],[-24,-2],[-24,-3],[-25,-3],[-25,-2],[-26,-2],[-26,-3],[-27,-3],[-27,-2],[-27,-1],[-26,-1],[-26,0],[-27,0],[-28,0],[-28,-1],[-29,-1],[-29,0],[-30,0],[-31,0],[-31,-1],[-30,-1],[-30,-2],[-31,-2],[-31,-3],[-30,-3],[-29,-3],[-29,-2],[-28,-2],[-28,-3],[-28,-4],[-28,-5],[-29,-5],[-29,-4],[-30,-4],[-31,-4],[-31,-5],[-30,-5],[-30,-6],[-31,-6],[-31,-7],[-30,-7],[-29,-7],[-29,-6],[-28,-6],[-28,-7],[-27,-7],[-26,-7],[-26,-6],[-27,-6],[-27,-5],[-27,-4],[-26,-4],[-26,-5],[-25,-5],[-25,-4],[-24,-4],[-24,-5],[-24,-6],[-25,-6],[-25,-7],[-24,-7],[-24,-8],[-25,-8],[-25,-9],[-24,-9],[-24,-10],[-24,-11],[-25,-11],[-25,-10],[-26,-10],[-26,-11],[-27,-11],[-27,-10],[-27,-9],[-26,-9],[-26,-8],[-27,-8],[-28,-8],[-28,-9],[-29,-9],[-29,-8],[-30,-8],[-31,-8],[-31,-9],[-30,-9],[-30,-10],[-31,-10],[-31,-11],[-30,-11],[-29,-11],[-29,-10],[-28,-10],[-28,-11],[-28,-12],[-28,-13],[-29,-13],[-29,-12],[-30,-12],[-31,-12],[-31,-13],[-30,-13],[-30,-14],[-31,-14],[-31,-15],[-30,-15],[-29,-15],[-29,-14],[-28,-14],[-28,-15],[-27,-15],[-26,-15],[-26,-14],[-27,-14],[-27,-13],[-27,-12],[-26,-12],[-26,-13],[-25,-13],[-25,-12],[-24,-12],[-24,-13],[-24,-14],[-25,-14],[-25,-15],[-24,-15],[-23,-15],[-23,-14],[-22,-14],[-22,-15],[-21,-15],[-20,-15],[-20,-14],[-21,-14],[-21,-13],[-20,-13],[-20,-12],[-21,-12],[-22,-12],[-22,-13],[-23,-13],[-23,-12],[-23,-11],[-22,-11],[-22,-10],[-23,-10],[-23,-9],[-23,-8],[-22,-8],[-22,-9],[-21,-9],[-21,-8],[-20,-8],[-20,-9],[-20,-10],[-21,-10],[-21,-11],[-20,-11],[-19,-11],[-18,-11],[-18,-10],[-19,-10],[-19,-9],[-19,-8],[-18,-8],[-18,-9],[-17,-9],[-17,-8],[-16,-8],[-16,-9],[-16,-10],[-17,-10],[-17,-11],[-16,-11],[-16,-12],[-16,-13],[-17,-13],[-17,-12],[-18,-12],[-19,-12],[-19,-13],[-18,-13],[-18,-14],[-19,-14],[-19,-15],[-18,-15],[-17,-15],[-17,-14],[-16,-14],[-16,-15],[-16,-16],[-16,-17],[-17,-17],[-17,-16],[-18,-16],[-19,-16],[-19,-17],[-18,-17],[-18,-18],[-19,-18],[-19,-19],[-18,-19],[-17,-19],[-17,-18],[-16,-18],[-16,-19],[-16,-20],[-17,-20],[-17,-21],[-16,-21],[-16,-22],[-16,-23],[-17,-23],[-17,-22],[-18,-22],[-18,-23],[-19,-23],[-19,-22],[-19,-21],[-18,-21],[-18,-20],[-19,-20],[-20,-20],[-21,-20],[-21,-21],[-20,-21],[-20,-22],[-20,-23],[-21,-23],[-21,-22],[-22,-22],[-22,-23],[-23,-23],[-23,-22],[-23,-21],[-22,-21],[-22,-20],[-23,-20],[-23,-19],[-23,-18],[-22,-18],[-22,-19],[-21,-19],[-20,-19],[-20,-18],[-21,-18],[-21,-17],[-20,-17],[-20,-16],[-21,-16],[-22,-16],[-22,-17],[-23,-17],[-23,-16],[-24,-16],[-25,-16],[-25,-17],[-24,-17],[-24,-18],[-24,-19],[-25,-19],[-25,-18],[-26,-18],[-26,-19],[-27,-19],[-27,-18],[-27,-17],[-26,-17],[-26,-16],[-27,-16],[-28,-16],[-28,-17],[-29,-17],[-29,-16],[-30,-16],[-31,-16],[-31,-17],[-30,-17],[-30,-18],[-31,-18],[-31,-19],[-30,-19],[-29,-19],[-29,-18],[-28,-18],[-28,-19],[-28,-20],[-28,-21],[-29,-21],[-29,-20],[-30,-20],[-31,-20],[-31,-21],[-30,-21],[-30,-22],[-31,-22],[-31,-23],[-30,-23],[-29,-23],[-29,-22],[-28,-22],[-28,-23],[-27,-23],[-26,-23],[-26,-22],[-27,-22],[-27,-21],[-27,-20],[-26,-20],[-26,-21],[-25,-21],[-25,-20],[-24,-20],[-24,-21],[-24,-22],[-25,-22],[-25,-23],[-24,-23],[-24,-24],[-25,-24],[-25,-25],[-24,-25],[-24,-26],[-24,-27],[-25,-27],[-25,-26],[-26,-26],[-26,-27],[-27,-27],[-27,-26],[-27,-25],[-26,-25],[-26,-24],[-27,-24],[-28,-24],[-28,-25],[-29,-25],[-29,-24],[-30,-24],[-31,-24],[-31,-25],[-30,-25],[-30,-26],[-31,-26],[-31,-27],[-30,-27],[-29,-27],[-29,-26],[-28,-26],[-28,-27],[-28,-28],[-28,-29],[-29,-29],[-29,-28],[-30,-28],[-31,-28],[-31,-29],[-30,-29],[-30,-30],[-31,-30],[-31,-31],[-30,-31],[-29,-31],[-29,-30],[-28,-30],[-28,-31],[-27,-31],[-26,-31],[-26,-30],[-27,-30],[-27,-29],[-27,-28],[-26,-28],[-26,-29],[-25,-29],[-25,-28],[-24,-28],[-24,-29],[-24,-30],[-25,-30],[-25,-31],[-24,-31],[-23,-31],[-23,-30],[-22,-30],[-22,-31],[-21,-31],[-20,-31],[-20,-30],[-21,-30],[-21,-29],[-20,-29],[-20,-28],[-21,-28],[-22,-28],[-22,-29],[-23,-29],[-23,-28],[-23,-27],[-22,-27],[-22,-26],[-23,-26],[-23,-25],[-23,-24],[-22,-24],[-22,-25],[-21,-25],[-21,-24],[-20,-24],[-20,-25],[-20,-26],[-21,-26],[-21,-27],[-20,-27],[-19,-27],[-18,-27],[-18,-26],[-19,-26],[-19,-25],[-19,-24],[-18,-24],[-18,-25],[-17,-25],[-17,-24],[-16,-24],[-16,-25],[-16,-26],[-17,-26],[-17,-27],[-16,-27],[-16,-28],[-16,-29],[-17,-29],[-17,-28],[-18,-28],[-19,-28],[-19,-29],[-18,-29],[-18,-30],[-19,-30],[-19,-31],[-18,-31],[-17,-31],[-17,-30],[-16,-30],[-16,-31],[-15,-31],[-14,-31],[-14,-30],[-15,-30],[-15,-29],[-15,-28],[-14,-28],[-14,-29],[-13,-29],[-13,-28],[-12,-28],[-12,-29],[-12,-30],[-13,-30],[-13,-31],[-12,-31],[-11,-31],[-11,-30],[-10,-30],[-10,-31],[-9,-31],[-8,-31],[-8,-30],[-9,-30],[-9,-29],[-8,-29],[-8,-28],[-9,-28],[-10,-28],[-10,-29],[-11,-29],[-11,-28],[-11,-27],[-11,-26],[-10,-26],[-10,-27],[-9,-27],[-8,-27],[-8,-26],[-9,-26],[-9,-25],[-8,-25],[-8,-24],[-9,-24],[-10,-24],[-10,-25],[-11,-25],[-11,-24],[-12,-24],[-13,-24],[-13,-25],[-12,-25],[-12,-26],[-12,-27],[-13,-27],[-13,-26],[-14,-26],[-14,-27],[-15,-27],[-15,-26],[-15,-25],[-14,-25],[-14,-24],[-15,-24],[-15,-23],[-15,-22],[-14,-22],[-14,-23],[-13,-23],[-12,-23],[-12,-22],[-13,-22],[-13,-21],[-12,-21],[-12,-20],[-13,-20],[-14,-20],[-14,-21],[-15,-21],[-15,-20],[-15,-19],[-14,-19],[-14,-18],[-15,-18],[-15,-17],[-15,-16],[-14,-16],[-14,-17],[-13,-17],[-13,-16],[-12,-16],[-12,-17],[-12,-18],[-13,-18],[-13,-19],[-12,-19],[-11,-19],[-10,-19],[-10,-18],[-11,-18],[-11,-17],[-11,-16],[-10,-16],[-10,-17],[-9,-17],[-9,-16],[-8,-16],[-8,-17],[-8,-18],[-9,-18],[-9,-19],[-8,-19],[-8,-20],[-8,-21],[-9,-21],[-9,-20],[-10,-20],[-11,-20],[-11,-21],[-10,-21],[-10,-22],[-11,-22],[-11,-23],[-10,-23],[-9,-23],[-9,-22],[-8,-22],[-8,-23],[-7,-23],[-7,-22],[-6,-22],[-6,-23],[-5,-23],[-4,-23],[-4,-22],[-5,-22],[-5,-21],[-4,-21],[-4,-20],[-5,-20],[-6,-20],[-6,-21],[-7,-21],[-7,-20],[-7,-19],[-6,-19],[-6,-18],[-7,-18],[-7,-17],[-7,-16],[-6,-16],[-6,-17],[-5,-17],[-5,-16],[-4,-16],[-4,-17],[-4,-18],[-5,-18],[-5,-19],[-4,-19],[-3,-19],[-2,-19],[-2,-18],[-3,-18],[-3,-17],[-3,-16],[-2,-16],[-2,-17],[-1,-17],[-1,-16],[0,-16],[0,-17],[0,-18],[-1,-18],[-1,-19],[0,-19],[0,-20],[0,-21],[-1,-21],[-1,-20],[-2,-20],[-3,-20],[-3,-21],[-2,-21],[-2,-22],[-3,-22],[-3,-23],[-2,-23],[-1,-23],[-1,-22],[0,-22],[0,-23],[0,-24],[-1,-24],[-1,-25],[0,-25],[0,-26],[0,-27],[-1,-27],[-1,-26],[-2,-26],[-2,-27],[-3,-27],[-3,-26],[-3,-25],[-2,-25],[-2,-24],[-3,-24],[-4,-24],[-4,-25],[-5,-25],[-5,-24],[-6,-24],[-7,-24],[-7,-25],[-6,-25],[-6,-26],[-7,-26],[-7,-27],[-6,-27],[-5,-27],[-5,-26],[-4,-26],[-4,-27],[-4,-28],[-4,-29],[-5,-29],[-5,-28],[-6,-28],[-7,-28],[-7,-29],[-6,-29],[-6,-30],[-7,-30],[-7,-31],[-6,-31],[-5,-31],[-5,-30],[-4,-30],[-4,-31],[-3,-31],[-2,-31],[-2,-30],[-3,-30],[-3,-29],[-3,-28],[-2,-28],[-2,-29],[-1,-29],[-1,-28],[0,-28],[0,-29],[0,-30],[-1,-30],[-1,-31],[0,-31],[1,-31],[1,0],[0,0]]] 2 | -------------------------------------------------------------------------------- /tests/fixtures/hole-touching-outer.json: -------------------------------------------------------------------------------- 1 | [[[-64,-64],[253,-64],[491,358],[697,298],[928,197],[929,505],[1346,507],[1347,303],[1771,306],[1770,512],[2191,509],[2198,933],[2621,932],[2623,1115],[2577,1120],[2494,1183],[2390,1329],[2326,1590],[2287,1678],[2286,1407],[2229,1407],[2182,1493],[2106,1494],[2068,1460],[2019,1460],[2016,1775],[1889,1923],[1953,1989],[2097,1866],[2198,1925],[2203,1973],[2311,1976],[2320,1831],[2352,1824],[2358,1797],[2378,1780],[3350,1782],[3307,2086],[3139,2088],[3143,2203],[3493,2205],[3543,2187],[3540,2260],[3661,2264],[3665,1906],[3630,1902],[3626,1784],[4160,1786],[4160,2631],[4076,2631],[4021,2683],[3930,2701],[3915,2693],[3898,2639],[2630,2630],[2635,3476],[2287,3478],[2118,3203],[2180,3145],[2327,3087],[2610,2643],[2613,2536],[2658,2495],[2650,2203],[1829,2189],[1732,2241],[1551,2245],[933,1183],[890,1152],[455,401],[398,412],[89,547],[-64,606],[-64,-64]],[[1762,928],[1770,512],[1343,513],[1345,715],[931,719],[932,930],[1762,928]]] 2 | -------------------------------------------------------------------------------- /tests/fixtures/issue16.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[143.129527283745121, 61.240160826593640], 3 | [147.399527283763751, 74.780160826630892], 4 | [154.049527283757931, 90.260160827077932], 5 | [174.429527283762581, 81.710160826332872], 6 | [168.03952728374861, 67.040160826407372], 7 | [159.099527283746281, 53.590160826221112]], 8 | [[156.85952728375561, 67.430160827003422], 9 | [157.489527283760251, 67.160160826519132], 10 | [159.969527283741631, 68.350160826928912], 11 | [161.339527283766071, 67.640160826966172], 12 | [159.649527283763751, 63.310160826891662], 13 | [155.759527283749781, 64.880160826258362]] 14 | ] 15 | -------------------------------------------------------------------------------- /tests/fixtures/issue17.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[-20037508.34,19971868.877628453], 3 | [-20037508.34,-19971868.877628453], 4 | [20037508.34,-19971868.877628453], 5 | [20037508.34,19971868.877628453]], 6 | [[537637.6007702783,5907542.234420554], 7 | [539500.1483225027,5905165.501947839], 8 | [538610.3146341922,5905217.430281373], 9 | [538040.6306361248,5906132.0755739985], 10 | [538068.958329954,5906571.138846622], 11 | [537711.0379352621,5906645.06648362], 12 | [537629.886026485,5907533.69114742]] 13 | ] 14 | -------------------------------------------------------------------------------- /tests/fixtures/issue29.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[200.95000055654114,69.90565782485673],[201.73186418809928,76.50881049432792],[204.05247248713854,82.73234962527638],[207.79442497901618,88.23839184455574],[212.7323883100471,92.70045673093409],[218.58296075442922,95.86217257360113],[225.00460918453172,97.53918036725955],[231.66534446463922,97.66082593216561],[238.15796607054654,96.21973398409901],[244.1176358256489,93.27806596420706],[249.2188404462824,88.99822680730722],[253.15628113771672,83.64108043884043],[255.70631344406866,77.51111824424007],[256.73126424155197,70.93641692795792],[256.19351709797047,64.30797780468129],[254.1057433114911,57.996416078653425],[250.56431880965246,52.346517799043795],[245.8112865351897,47.719993951247304],[240.07834375849924,44.33761266223155],[233.71343464441597,42.419284673407674],[227.06488359675492,42.055728640102465],[220.51757991796475,43.257153422775446],[214.45449861431845,45.97523169373744],[209.20995664413203,50.053084840223896],[205.06721924245355,55.271000209450726],[202.29122001552022,61.30178454495035],[201.02451470680535,67.8368895214051]], 3 | [[242.34999892718187,69.90549289577612],[240.7584948063828,76.30057721128688],[236.31611852571368,81.17358751371503],[230.07699953842675,83.34595728587593],[223.55761859836056,82.33733346881347],[218.2910646148026,78.34856240227819],[215.5668820463121,72.34290095195175],[215.9904494531453,65.75019118711353],[219.47497291108593,60.1536534355022],[225.2189893186092,56.88651757836341],[231.8100271829404,56.72041164720431],[237.70269737243652,59.67713584899902],[241.47838292121884,65.0856644153595]] 4 | ] 5 | -------------------------------------------------------------------------------- /tests/fixtures/issue34.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[1500,0],[0,0],[0,1000],[1500,1000],[1500,0]], 3 | [[804,642],[814,644],[818,676],[850,690],[838,728],[806,728],[772,752],[748,746],[764,724],[728,726],[710,708],[738,656],[764,668],[784,700],[806,702],[792,666],[804,642]], 4 | [[1176,214],[1254,216],[1292,242],[1324,242],[1332,268],[1352,278],[1352,298],[1290,348],[1290,358],[1312,350],[1314,362],[1266,416],[1240,474],[1182,500],[1200,510],[1200,520],[1186,520],[1200,544],[1186,580],[1160,584],[1162,606],[1146,620],[1162,650],[1136,672],[1124,658],[1076,668],[1022,658],[1036,698],[1066,706],[1118,688],[1144,708],[1132,746],[1064,748],[1004,740],[990,668],[966,670],[946,648],[948,632],[962,628],[992,650],[1016,648],[1054,622],[1044,592],[1054,584],[1078,606],[1076,576],[1052,570],[1056,540],[1038,568],[1004,570],[976,526],[996,502],[958,496],[948,454],[962,454],[952,436],[964,390],[986,382],[974,368],[1004,376],[1018,420],[1052,434],[1060,482],[1078,490],[1062,472],[1062,442],[1104,450],[1104,436],[1142,422],[1154,402],[1110,424],[1046,416],[1022,388],[1022,344],[1002,344],[1018,318],[1060,308],[1076,272],[1104,288],[1122,246],[1140,230],[1168,234],[1176,214]], 5 | [[974,698],[986,738],[964,740],[952,714],[974,698]], 6 | [[842,596],[860,626],[848,622],[842,596]], 7 | [[798,572],[792,606],[768,614],[740,580],[758,586],[798,572]], 8 | [[892,584],[894,594],[882,588],[892,584]], 9 | [[870,500],[912,538],[922,586],[908,590],[894,568],[864,564],[854,550],[868,538],[846,520],[854,500],[870,500]] 10 | ] 11 | -------------------------------------------------------------------------------- /tests/fixtures/issue35.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[216,-128],[218,-98],[232,-104],[238,-98],[234,-58],[242,-32],[232,-16],[254,-2],[256,20],[268,6],[274,6],[278,20],[284,16],[284,6],[266,-4],[276,-28],[262,-64],[296,-68],[312,-60],[308,-50],[322,-46],[338,-46],[344,-52],[378,-50],[396,-16],[434,22],[446,26],[452,38],[470,42],[466,58],[450,56],[436,68],[428,102],[406,96],[408,116],[370,114],[340,96],[356,124],[358,164],[352,174],[328,186],[326,208],[342,208],[346,232],[328,232],[318,248],[306,246],[302,236],[284,238],[240,190],[218,194],[194,176],[184,124],[142,102],[134,102],[118,118],[72,118],[70,90],[52,68],[68,42],[68,24],[54,40],[36,28],[30,46],[12,48],[14,82],[30,98],[18,150],[-8,170],[-22,190],[-40,194],[-50,204],[-70,208],[-112,198],[-116,212],[-114,230],[-96,250],[-72,244],[-58,276],[-50,332],[-24,364],[-30,384],[-20,390],[-16,410],[-26,426],[-36,428],[-38,444],[-92,422],[-128,422],[-128,4224],[4224,4224],[4224,3520],[4204,3506],[4204,3498],[4212,3498],[4210,3486],[4164,3492],[4132,3478],[4104,3474],[4074,3458],[4034,3456],[3992,3428],[3928,3362],[3880,3342],[3870,3342],[3850,3360],[3814,3374],[3790,3374],[3768,3362],[3742,3360],[3706,3344],[3698,3334],[3656,3326],[3640,3314],[3592,3298],[3554,3266],[3534,3266],[3488,3252],[3464,3224],[3416,3202],[3384,3154],[3386,3142],[3398,3140],[3392,3124],[3400,3116],[3402,3094],[3392,3088],[3388,3070],[3394,3062],[3382,3052],[3378,3038],[3346,3010],[3316,2966],[3278,2938],[3278,2926],[3264,2910],[3212,2880],[3212,2866],[3220,2858],[3218,2844],[3208,2834],[3198,2836],[3184,2814],[3162,2802],[3158,2776],[3130,2768],[3090,2720],[3080,2728],[3070,2724],[3080,2698],[3044,2628],[3044,2602],[3024,2596],[3010,2580],[2992,2584],[2980,2574],[2966,2580],[2966,2608],[2972,2614],[2980,2664],[3022,2700],[3026,2718],[3056,2746],[3062,2778],[3080,2792],[3098,2824],[3112,2832],[3122,2848],[3130,2884],[3156,2922],[3156,2954],[3162,2960],[3176,2954],[3186,2960],[3202,2988],[3212,2994],[3212,3010],[3186,3026],[3170,2992],[3112,2946],[3102,2944],[3086,2926],[3090,2882],[3078,2860],[3062,2854],[3040,2832],[3018,2832],[3012,2822],[2986,2812],[2958,2782],[2960,2776],[2994,2776],[3000,2742],[2958,2696],[2928,2680],[2920,2648],[2910,2638],[2910,2624],[2900,2616],[2896,2598],[2882,2582],[2882,2566],[2862,2538],[2852,2496],[2828,2472],[2804,2464],[2796,2448],[2772,2446],[2754,2428],[2708,2424],[2702,2418],[2700,2388],[2644,2322],[2642,2304],[2648,2292],[2624,2276],[2616,2234],[2598,2224],[2590,2202],[2564,2176],[2556,2120],[2530,2086],[2542,2054],[2544,2012],[2530,1976],[2524,1928],[2542,1870],[2554,1718],[2546,1710],[2546,1668],[2540,1664],[2528,1616],[2518,1606],[2516,1576],[2524,1574],[2552,1588],[2612,1594],[2614,1588],[2606,1580],[2616,1564],[2616,1552],[2600,1528],[2586,1528],[2580,1506],[2552,1498],[2542,1480],[2534,1480],[2534,1494],[2512,1456],[2498,1452],[2498,1470],[2524,1504],[2552,1514],[2560,1520],[2564,1536],[2578,1540],[2578,1572],[2556,1576],[2498,1550],[2498,1534],[2474,1532],[2460,1514],[2434,1502],[2430,1490],[2418,1486],[2414,1472],[2402,1468],[2400,1460],[2374,1452],[2368,1428],[2350,1414],[2352,1402],[2380,1396],[2396,1412],[2418,1420],[2426,1420],[2430,1410],[2394,1396],[2378,1380],[2380,1352],[2364,1356],[2360,1350],[2360,1340],[2370,1336],[2370,1328],[2358,1328],[2356,1312],[2348,1306],[2350,1290],[2344,1284],[2332,1288],[2330,1270],[2318,1278],[2308,1264],[2314,1246],[2294,1236],[2306,1220],[2288,1220],[2278,1228],[2252,1202],[2258,1180],[2246,1174],[2246,1164],[2264,1158],[2254,1140],[2258,1112],[2232,1102],[2230,1082],[2222,1070],[2216,1070],[2220,1096],[2208,1092],[2202,1072],[2190,1068],[2196,1032],[2188,1044],[2172,1048],[2186,1068],[2182,1110],[2170,1108],[2168,1096],[2154,1084],[2144,1090],[2154,1092],[2154,1106],[2144,1108],[2130,1086],[2130,1074],[2106,1048],[2108,1042],[2122,1040],[2110,1022],[2120,1022],[2122,1014],[2102,1012],[2112,996],[2110,980],[2136,980],[2140,966],[2110,970],[2102,964],[2096,992],[2082,992],[2080,976],[2088,966],[2076,950],[2076,934],[2090,930],[2100,938],[2094,916],[2134,922],[2114,906],[2120,892],[2108,872],[2112,858],[2100,842],[2094,840],[2098,896],[2090,898],[2074,920],[2066,920],[2068,880],[2060,868],[2050,814],[2038,820],[2028,808],[2002,802],[1996,812],[1970,818],[1960,806],[1948,804],[1918,776],[1900,748],[1832,708],[1840,692],[1836,674],[1810,690],[1792,690],[1762,678],[1758,662],[1738,666],[1690,654],[1638,662],[1630,652],[1602,640],[1596,624],[1578,632],[1548,616],[1538,630],[1520,638],[1516,622],[1546,612],[1548,604],[1534,596],[1520,598],[1514,570],[1492,580],[1476,574],[1472,582],[1452,590],[1454,570],[1448,570],[1440,592],[1450,594],[1450,608],[1458,614],[1456,632],[1448,642],[1460,654],[1460,664],[1440,658],[1432,668],[1392,664],[1354,706],[1340,710],[1334,722],[1286,738],[1276,730],[1276,720],[1310,696],[1310,690],[1288,694],[1280,686],[1286,660],[1298,646],[1306,622],[1302,596],[1340,568],[1350,568],[1358,578],[1376,572],[1364,548],[1332,546],[1312,566],[1296,570],[1286,580],[1286,594],[1272,602],[1262,614],[1258,634],[1244,644],[1248,660],[1238,674],[1228,676],[1228,688],[1222,694],[1206,694],[1196,712],[1180,722],[1176,744],[1212,754],[1212,774],[1182,798],[1172,828],[1140,838],[1124,860],[1112,862],[1104,876],[1076,892],[1076,912],[1068,924],[1056,926],[1040,940],[1028,940],[1022,956],[1006,956],[1006,966],[984,970],[982,978],[990,988],[980,1002],[940,1018],[930,1034],[918,1020],[890,1044],[868,1048],[856,1058],[842,1056],[846,1040],[838,1038],[820,1078],[806,1086],[792,1082],[788,1090],[776,1090],[768,1080],[772,1092],[762,1102],[766,1108],[752,1116],[720,1118],[704,1134],[688,1132],[686,1118],[706,1092],[718,1092],[734,1082],[758,1088],[762,1076],[794,1056],[806,1030],[836,1010],[864,1008],[870,1020],[888,1016],[886,1000],[900,974],[952,938],[970,936],[976,910],[998,894],[1004,882],[1016,878],[1022,800],[1044,774],[1044,766],[1036,766],[990,786],[976,762],[970,762],[964,776],[968,800],[956,804],[928,764],[912,770],[898,760],[896,750],[888,750],[842,786],[826,786],[830,744],[820,740],[818,730],[830,704],[802,646],[794,664],[766,678],[724,678],[718,660],[702,642],[680,630],[676,616],[666,614],[682,596],[684,580],[674,574],[680,564],[674,558],[658,562],[652,544],[640,534],[644,522],[630,518],[630,510],[638,506],[634,492],[650,488],[650,460],[674,424],[688,418],[690,382],[706,354],[732,350],[756,370],[768,370],[794,346],[806,322],[818,328],[848,328],[868,310],[874,286],[866,254],[844,230],[844,220],[866,216],[872,210],[872,194],[854,182],[846,194],[814,202],[794,220],[788,236],[782,236],[778,220],[768,210],[768,230],[750,216],[710,216],[676,228],[634,216],[616,204],[618,182],[600,160],[614,150],[620,136],[570,124],[542,104],[542,96],[566,86],[570,74],[588,72],[620,38],[652,44],[644,24],[652,16],[684,8],[696,-4],[716,-10],[740,-4],[732,34],[738,48],[828,54],[840,30],[860,32],[854,18],[824,16],[826,2],[846,4],[826,-20],[826,-36],[836,-54],[820,-60],[798,-52],[748,-66],[724,-128],[216,-128]], 3 | [[4124,4134],[4118,4136],[4120,4130],[4126,4130],[4124,4134]], 4 | [[4086,4128],[4074,4130],[4072,4122],[4086,4118],[4086,4128]], 5 | [[4068,4106],[4068,4112],[4060,4112],[4060,4104],[4068,4106]], 6 | [[1032,4014],[1026,4014],[1026,4008],[1032,4014]], 7 | [[1122,3162],[1144,3186],[1142,3198],[1124,3204],[1108,3218],[1096,3212],[1090,3176],[1098,3168],[1098,3156],[1122,3162]], 8 | [[1088,3124],[1092,3134],[1074,3138],[1062,3126],[1064,3118],[1088,3124]], 9 | [[1054,3114],[1038,3114],[1038,3108],[1050,3108],[1054,3114]], 10 | [[1014,3104],[994,3102],[994,3088],[1006,3086],[1014,3104]], 11 | [[940,3068],[934,3076],[926,3074],[922,3062],[940,3058],[940,3068]], 12 | [[3042,2702],[3042,2710],[3034,2710],[3022,2694],[3030,2690],[3042,2702]], 13 | [[2598,1566],[2590,1566],[2588,1558],[2594,1554],[2600,1554],[2598,1566]], 14 | [[158,1326],[170,1326],[168,1334],[142,1342],[140,1336],[150,1318],[158,1326]], 15 | [[100,1326],[98,1340],[90,1340],[84,1322],[100,1326]], 16 | [[130,1336],[120,1338],[128,1326],[130,1336]], 17 | [[-12,1318],[-14,1324],[-22,1324],[-18,1314],[-12,1318]], 18 | [[-112,1318],[-116,1320],[-110,1312],[-112,1318]], 19 | [[182,1314],[174,1316],[174,1310],[182,1314]], 20 | [[272,1288],[266,1308],[234,1312],[248,1304],[260,1286],[272,1288]], 21 | [[300,1312],[278,1308],[296,1306],[300,1312]], 22 | [[2172,1156],[2180,1162],[2200,1160],[2188,1196],[2188,1222],[2200,1232],[2198,1260],[2208,1264],[2206,1278],[2226,1294],[2228,1310],[2208,1298],[2202,1282],[2160,1236],[2156,1210],[2142,1202],[2132,1178],[2136,1152],[2172,1156]], 23 | [[348,1290],[346,1296],[338,1294],[342,1288],[348,1290]], 24 | [[428,1270],[420,1272],[420,1266],[428,1270]], 25 | [[610,1170],[626,1168],[626,1186],[616,1192],[604,1206],[588,1208],[568,1222],[552,1214],[536,1222],[518,1244],[506,1246],[512,1224],[526,1220],[532,1202],[546,1198],[554,1212],[580,1206],[590,1188],[586,1172],[596,1164],[608,1164],[610,1170]], 26 | [[648,1152],[642,1160],[632,1158],[636,1148],[648,1152]], 27 | [[2240,1118],[2238,1126],[2232,1124],[2234,1116],[2240,1118]], 28 | [[806,1096],[802,1090],[808,1090],[806,1096]], 29 | [[908,1080],[906,1076],[914,1072],[908,1080]], 30 | [[894,1060],[884,1072],[872,1070],[876,1054],[894,1060]], 31 | [[2024,826],[2052,836],[2048,856],[2056,876],[2054,904],[2066,948],[2062,986],[2052,980],[2044,954],[2030,938],[2028,912],[2020,922],[2010,922],[2012,894],[1976,846],[1976,834],[1988,820],[2016,816],[2024,826]] 32 | ] 33 | -------------------------------------------------------------------------------- /tests/fixtures/issue45.json: -------------------------------------------------------------------------------- 1 | [[[10,10], [25,10], [25,40], [10,40]], [[15,30], [20,35], [10,40]], [[15,15], [15,20], [20,15]]] 2 | -------------------------------------------------------------------------------- /tests/fixtures/issue52.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[1920,552],[1904,616],[1912,664],[1984,672],[2008,712],[1944,720],[1904,760],[1896,800],[1856,760],[1824,768],[1824,832],[1864,864],[1888,864],[1904,936],[1936,944],[1936,1064],[1936,1112],[1872,1136],[1856,1160],[1840,1144],[1792,1152],[1784,1112],[1752,1096],[1608,1096],[1600,1064],[1640,1040],[1664,992],[1640,968],[1568,1024],[1560,1056],[1480,1048],[1440,1072],[1440,1032],[1400,1032],[1400,1088],[1336,1136],[1320,1136],[1264,1072],[1232,1080],[1240,1104],[1200,1096],[1232,1048],[1272,1032],[1272,1000],[1232,1024],[1176,1024],[1176,1000],[1248,952],[1344,944],[1352,904],[1424,880],[1448,848],[1496,840],[1512,800],[1568,760],[1616,752],[1640,640],[1680,600],[1736,592],[1776,560],[1776,536],[1840,464],[1848,400],[1888,328],[1952,264],[2000,240],[2040,240],[2040,264],[1968,376],[1912,424],[1936,512],[1920,528],[1880,528],[1872,552],[1920,552]], 3 | [[1608,800],[1576,848],[1520,840],[1512,872],[1456,904],[1440,952],[1528,936],[1552,912],[1584,912],[1608,880],[1664,864],[1680,816],[1656,776],[1608,800]], 4 | [[1720,792],[1736,792],[1720,780],[1720,792]], 5 | [[1656,728],[1670,752],[1672,728],[1656,728]], 6 | [[1712,680],[1696,720],[1720,728],[1736,704],[1736,680],[1712,680]], 7 | [[1968,712],[2000,712],[1968,688],[1968,712]] 8 | ] 9 | -------------------------------------------------------------------------------- /tests/fixtures/issue83.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[0,0],[4000,0],[4000,4000],[0,4000]], 3 | [[0,0],[4000,0],[4000,4000],[0,4000]], 4 | [[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1]] 5 | ] 6 | -------------------------------------------------------------------------------- /tests/fixtures/outside-ring.json: -------------------------------------------------------------------------------- 1 | [[[2181,1228],[2182,1231],[2178,1231],[2180,1228],[2175,1225],[2174,1212],[2182,1210],[2182,1193],[2190,1187],[2187,1166],[2194,1158],[2186,1149],[2186,1103],[2195,1091],[2207,1092],[2209,1080],[2203,1077],[2213,1057],[2213,1035],[2224,1031],[2238,983],[2251,982],[2254,965],[2275,970],[2277,948],[2317,982],[2317,1030],[2323,1044],[2306,1041],[2303,1051],[2290,1057],[2294,1062],[2287,1071],[2294,1081],[2255,1123],[2249,1118],[2253,1128],[2245,1131],[2249,1137],[2243,1168],[2265,1195],[2253,1203],[2260,1204],[2252,1215],[2249,1208],[2245,1217],[2232,1220],[2241,1223],[2235,1223],[2238,1245],[2229,1274],[2215,1272],[2209,1288],[2196,1288],[2190,1269],[2194,1271],[2195,1262],[2181,1240],[2182,1233],[2183,1229],[2181,1228]],[[2181,1228],[2181,1227],[2180,1228],[2181,1228]],[[2246,1197],[2230,1201],[2251,1203],[2246,1197]]] 2 | -------------------------------------------------------------------------------- /tests/fixtures/self-touching.json: -------------------------------------------------------------------------------- 1 | [[[160.40671875,11.3976701817587],[160.396875,11.3935345987524],[160.39828125,11.4018057045896],[160.39265625,11.4004272036667],[160.38984375,11.3811274888866],[160.3940625,11.3838846711709],[160.3771875,11.3521754635814],[160.33921875,11.3590690696413],[160.35046875,11.3645838345287],[160.3575,11.3645838345287],[160.3575,11.3756130442004],[160.29421875,11.3507967223837],[160.2928125,11.3480392200086],[160.28859375,11.3480392200086],[160.295625,11.3287359579628],[160.26328125,11.3080524456288],[160.295625,11.1866791818427],[160.31671875,11.1811610026871],[160.318125,11.1770222993774],[160.31390625,11.1687447155658],[160.3125,11.1494294353899],[160.2703125,11.1107950268865],[160.2421875,11.1149346728405],[160.23796875,11.0997556838987],[160.25625,11.095615822671],[160.21828125,11.0735355725517],[160.21546875,11.0652550492086],[160.2084375,11.0762956949617],[160.20140625,11.0638749392263],[160.19015625,11.0528338254202],[160.18453125,11.0528338254202],[160.183125,11.0486933005675],[160.24640625,11.0583544343014],[160.26890625,11.0555941428523],[160.250625,11.0804358297701],[160.28015625,11.0942358558913],[160.295625,11.0845759059922],[160.2928125,11.0721555015877],[160.318125,11.0790557913426],[160.31953125,11.0942358558913],[160.33359375,11.1038954864431],[160.34484375,11.0900959164515],[160.35609375,11.1038954864431],[160.363125,11.0969957829326],[160.36453125,11.1052754075802],[160.36171875,11.1121749153987],[160.37578125,11.1149346728405],[160.39828125,11.1080352302834],[160.36734375,11.1756427184796],[160.48125,11.1852996469051],[160.48546875,11.1825405573266],[160.5121875,11.1852996469051],[160.5459375,11.1342522433585],[160.56421875,11.1301128717933],[160.55578125,11.1204541093718],[160.56140625,11.1135547973836],[160.588125,11.1314926688534],[160.62328125,11.1121749153987],[160.633125,11.1135547973836],[160.6471875,11.1025155587833],[160.64296875,11.1176944041669],[160.63734375,11.1190742600349],[160.62328125,11.1342522433585],[160.62046875,11.128733068196],[160.6078125,11.1480497233847],[160.61203125,11.1480497233847],[160.6134375,11.1563278971795],[160.5909375,11.1425308098987],[160.576875,11.1480497233847],[160.57125,11.1549482179223],[160.57125,11.1494294353899],[160.57828125,11.1452902797332],[160.57265625,11.1425308098987],[160.57125,11.1494294353899],[160.54875,11.1577075698847],[160.554375,11.179781441482],[160.54875,11.1770222993774],[160.5628125,11.2087508469621],[160.5234375,11.2059919808933],[160.52203125,11.2032330885061],[160.50515625,11.2184066708578],[160.49390625,11.2032330885061],[160.46296875,11.2046125379891],[160.46296875,11.201853632445],[160.4165625,11.2115096867066],[160.41796875,11.2211654184183],[160.39546875,11.2266828344767],[160.35609375,11.2225447823168],[160.35328125,11.2363380587922],[160.3659375,11.2473722050633],[160.351875,11.2915045605453],[160.32375,11.2721974885629],[160.32234375,11.2846093266964],[160.35328125,11.3080524456288],[160.351875,11.3149471157772],[160.3659375,11.3204627323768],[160.36171875,11.2997786224589],[160.3828125,11.3011576095711],[160.37859375,11.3080524456288],[160.38140625,11.3094313929343],[160.3828125,11.3011576095711],[160.408125,11.3039155638972],[160.408125,11.2997786224589],[160.425,11.3094313929343],[160.41234375,11.3411453475587],[160.3996875,11.3301148056307],[160.40953125,11.3700984927314],[160.39265625,11.3618264654176],[160.396875,11.3797488877286],[160.4053125,11.3893989555911],[160.40953125,11.3866418267411],[160.419375,11.4004272036667],[160.41515625,11.4059411672242],[160.419375,11.4114550237293],[160.425,11.412833471123],[160.42359375,11.422482415387],[160.40671875,11.3976701817587]],[[160.363125,11.1425308098987],[160.3603125,11.1383915560672],[160.3603125,11.1439105480884],[160.363125,11.1425308098987]],[[160.35046875,11.1397713138873],[160.34625,11.1383915560672],[160.34203125,11.1480497233847],[160.35046875,11.1397713138873]]] -------------------------------------------------------------------------------- /tests/fixtures/shared-points.json: -------------------------------------------------------------------------------- 1 | [[[4136,1016],[4112,1016],[4104,976],[4136,1016],[4144,984],[4104,976],[4144,968],[4144,984],[4168,992],[4152,1064]]] 2 | -------------------------------------------------------------------------------- /tests/fixtures/simplified-us-border.json: -------------------------------------------------------------------------------- 1 | [[[1130,1713],[1131,1710],[1137,1731],[1133,1752],[1125,1753],[1118,1742],[1110,1717],[1105,1718],[1108,1704],[1096,1691],[1077,1694],[1067,1683],[1019,1687],[1031,1689],[1031,1704],[1022,1696],[1022,1702],[1010,1700],[1003,1692],[998,1696],[980,1690],[970,1698],[966,1694],[966,1702],[938,1718],[943,1742],[920,1736],[916,1721],[894,1693],[884,1691],[872,1703],[837,1667],[785,1672],[743,1654],[715,1656],[699,1636],[676,1628],[654,1587],[656,1583],[660,1588],[657,1579],[649,1580],[633,1547],[637,1529],[631,1507],[638,1454],[647,1454],[637,1452],[639,1441],[635,1442],[629,1417],[651,1421],[647,1434],[655,1428],[650,1440],[656,1434],[654,1423],[651,1420],[653,1419],[651,1407],[965,1407],[966,1400],[972,1411],[1008,1423],[1043,1419],[1083,1442],[1086,1450],[1091,1448],[1109,1468],[1114,1496],[1102,1520],[1107,1525],[1149,1508],[1147,1498],[1152,1495],[1174,1495],[1195,1474],[1242,1470],[1260,1433],[1277,1440],[1277,1462],[1286,1476],[1274,1484],[1265,1480],[1243,1503],[1240,1516],[1252,1526],[1238,1529],[1236,1523],[1234,1530],[1218,1531],[1206,1540],[1205,1554],[1195,1567],[1188,1556],[1194,1574],[1185,1590],[1187,1581],[1179,1567],[1185,1557],[1176,1562],[1180,1579],[1179,1585],[1170,1577],[1180,1593],[1169,1590],[1183,1596],[1186,1607],[1175,1605],[1183,1613],[1182,1618],[1171,1615],[1179,1624],[1167,1626],[1145,1650],[1132,1659],[1128,1656],[1121,1675],[1131,1708],[1129,1710],[1130,1713]],[[654,1419],[653,1419],[654,1423],[656,1425],[654,1419]]] 2 | -------------------------------------------------------------------------------- /tests/fixtures/steiner.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[0,0],[100,0],[100,100],[0,100]], 3 | [[50,50]], 4 | [[30,40]], 5 | [[70,60]], 6 | [[20,70]] 7 | ] 8 | -------------------------------------------------------------------------------- /tests/fixtures/touching-holes.json: -------------------------------------------------------------------------------- 1 | [[[3694,2061],[3794,2035],[3812,2123],[3784,2123],[3708,2139],[3694,2061]],[[3752,2109],[3740,2102],[3712,2109],[3715,2125],[3723,2128],[3740,2124],[3742,2112],[3752,2109]],[[3797,2101],[3787,2096],[3780,2106],[3788,2114],[3797,2101]],[[3734,2099],[3732,2091],[3719,2094],[3721,2102],[3734,2099]],[[3777,2082],[3774,2071],[3772,2086],[3765,2091],[3748,2088],[3749,2062],[3738,2081],[3745,2095],[3761,2099],[3777,2082]],[[3719,2079],[3712,2079],[3706,2091],[3712,2097],[3721,2080],[3719,2079]],[[3773,2067],[3761,2053],[3753,2061],[3753,2071],[3756,2075],[3773,2067]],[[3708,2079],[3712,2079],[3714,2076],[3719,2079],[3722,2079],[3718,2088],[3723,2089],[3734,2075],[3730,2068],[3717,2065],[3708,2079]]] 2 | -------------------------------------------------------------------------------- /tests/fixtures/water2.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[-128,-128],[-128,-128],[-128,-128],[-128,1998],[-119,1978],[-127,2036],[-128,2037],[-128,2050],[-107,2044],[-77,2056],[-61,2076],[-57,2112],[-59,2198],[-49,2208],[-29,2196],[-21,2178],[33,2132],[23,2018],[69,1948],[75,1932],[65,1912],[13,1888],[-13,1862],[-29,1834],[-67,1832],[-107,1816],[-128,1817],[-128,962],[-128,962],[-128,1583],[-121,1578],[-93,1578],[-55,1586],[-23,1598],[37,1598],[169,1466],[45,1606],[65,1672],[91,1692],[83,1864],[101,1886],[139,1872],[175,1810],[177,1786],[185,1808],[163,1846],[153,1876],[185,1882],[219,1874],[269,1846],[293,1842],[317,1846],[329,1866],[361,1888],[395,1908],[415,1910],[431,1886],[441,1864],[465,1842],[491,1828],[519,1800],[537,1758],[547,1698],[549,1626],[579,1580],[595,1528],[593,1470],[585,1428],[555,1356],[509,1302],[481,1262],[441,1236],[419,1232],[393,1248],[375,1228],[397,1238],[417,1222],[441,1224],[491,1264],[501,1230],[501,1206],[511,1236],[497,1272],[531,1312],[571,1350],[583,1382],[603,1422],[651,1386],[661,1352],[655,1390],[633,1414],[607,1430],[615,1476],[615,1590],[657,1568],[703,1522],[667,1570],[637,1596],[667,1590],[693,1612],[663,1600],[641,1604],[621,1616],[607,1736],[629,1718],[653,1710],[671,1710],[703,1726],[737,1726],[699,1734],[677,1722],[657,1718],[637,1722],[619,1738],[603,1766],[585,1828],[571,1854],[555,1874],[513,1880],[483,1876],[465,1888],[443,1888],[433,1914],[431,1926],[437,1946],[461,1942],[483,1918],[481,1934],[459,1954],[485,1960],[509,1960],[539,1968],[569,1970],[597,1980],[617,1980],[643,1976],[667,1958],[719,1900],[699,1934],[671,1972],[743,1978],[765,1984],[735,1988],[697,1982],[661,1990],[645,1998],[665,2042],[695,2098],[705,2140],[719,2162],[757,2190],[853,2186],[865,2214],[881,2242],[915,2252],[925,2264],[925,2286],[917,2316],[907,2376],[941,2382],[903,2392],[895,2444],[883,2470],[877,2566],[871,2596],[947,2648],[1011,2686],[1017,2706],[1029,2708],[1041,2700],[1099,2724],[1167,2768],[1427,2832],[1447,2826],[1467,2810],[1481,2792],[1487,2766],[1489,2742],[1480,2705],[1466,2683],[1429,2654],[1270,2561],[1243,2565],[1260,2552],[1209,2524],[1190,2506],[1187,2482],[1195,2431],[1215,2397],[1222,2368],[1210,2357],[1174,2343],[1126,2305],[1114,2281],[1099,2136],[1135,2096],[1174,2060],[1179,2040],[1173,2020],[1175,2008],[1170,1976],[1136,1924],[1121,1897],[1129,1863],[1157,1815],[1175,1800],[1205,1791],[1227,1771],[1243,1737],[1236,1776],[1218,1800],[1198,1805],[1178,1818],[1160,1839],[1140,1887],[1147,1915],[1170,1942],[1191,1948],[1211,1962],[1259,1977],[1301,2020],[1369,2046],[1385,2048],[1379,2063],[1409,2125],[1425,2141],[1444,2188],[1459,2197],[1549,2188],[1579,2180],[1592,2165],[1601,2136],[1595,2110],[1579,2086],[1556,2073],[1529,2070],[1485,2071],[1444,2053],[1423,2036],[1453,2042],[1483,2056],[1511,2058],[1529,2055],[1560,2061],[1597,2085],[1636,2120],[1653,2115],[1681,2098],[1693,2072],[1696,2048],[1696,2016],[1713,2003],[1702,1986],[1705,1966],[1675,1931],[1659,1920],[1626,1915],[1571,1885],[1554,1857],[1573,1877],[1627,1907],[1665,1912],[1686,1925],[1711,1953],[1739,1963],[1731,1945],[1707,1909],[1661,1846],[1631,1839],[1575,1842],[1602,1839],[1618,1827],[1642,1824],[1671,1834],[1703,1862],[1755,1893],[1774,1896],[1798,1891],[1823,1878],[1843,1862],[1857,1814],[1835,1738],[1871,1804],[1890,1811],[1903,1824],[1911,1841],[1937,1864],[1974,1888],[2001,1894],[2026,1906],[2047,1921],[2062,1952],[2076,2007],[2092,1995],[2091,1910],[2081,1879],[2085,1853],[2127,1818],[2134,1801],[2127,1787],[2102,1764],[2099,1746],[2103,1728],[1649,1232],[1587,1151],[1616,1180],[1651,1226],[2110,1719],[2122,1720],[2153,1755],[2175,1772],[2202,1775],[2214,1750],[2218,1728],[2205,1715],[2186,1704],[2179,1689],[2186,1674],[2203,1672],[2236,1679],[2247,1666],[2251,1648],[2231,1615],[2226,1573],[2218,1565],[2200,1574],[2178,1572],[2166,1561],[2165,1549],[2179,1538],[2198,1513],[2192,1477],[2166,1483],[2141,1480],[2121,1442],[2116,1427],[2100,1420],[2077,1420],[2059,1409],[2061,1378],[2079,1319],[2095,1305],[2117,1303],[2135,1314],[2147,1330],[2171,1325],[2183,1312],[2183,1290],[2163,1260],[2143,1238],[2107,1221],[2101,1206],[2104,1191],[2122,1176],[2143,1160],[2151,1143],[2147,1126],[2135,1114],[2115,1111],[2095,1101],[2084,1086],[2087,1067],[2111,1023],[2109,1010],[2095,1002],[2081,984],[2081,962],[2095,945],[2115,937],[2137,939],[2157,929],[2161,889],[2153,869],[2127,869],[2101,859],[2091,829],[2093,801],[2121,783],[2151,783],[2167,799],[2189,791],[2197,771],[2191,741],[2199,729],[2231,713],[2237,699],[2209,681],[2191,659],[2189,635],[2207,591],[2233,553],[2231,519],[2239,495],[2255,483],[2271,443],[2299,437],[2341,439],[2371,421],[2419,399],[2443,397],[2457,405],[2483,393],[2515,371],[2545,361],[2597,359],[2631,321],[2665,317],[2705,319],[2679,327],[2678,327],[2645,327],[2636,332],[2615,361],[2591,371],[2541,373],[2507,389],[2469,415],[2453,415],[2429,405],[2401,415],[2363,445],[2337,457],[2303,453],[2283,457],[2271,477],[2247,507],[2239,531],[2245,555],[2213,605],[2201,641],[2201,655],[2247,687],[2257,707],[2217,733],[2203,747],[2209,775],[2197,801],[2171,811],[2153,805],[2141,797],[2117,801],[2103,819],[2107,839],[2129,851],[2165,857],[2177,873],[2175,897],[2167,923],[2153,949],[2107,957],[2095,969],[2097,985],[2121,1003],[2135,1021],[2127,1041],[2105,1065],[2107,1075],[2121,1089],[2145,1103],[2163,1125],[2167,1143],[2157,1163],[2125,1191],[2119,1203],[2135,1221],[2161,1233],[2199,1287],[2201,1299],[2195,1323],[2175,1339],[2147,1341],[2129,1337],[2125,1319],[2113,1317],[2095,1335],[2087,1353],[2077,1397],[2079,1411],[2117,1407],[2135,1415],[2149,1457],[2165,1467],[2415,1383],[2205,1467],[2213,1487],[2211,1523],[2201,1545],[2183,1557],[2223,1553],[2233,1563],[2243,1579],[2241,1597],[2255,1617],[2273,1625],[2477,1599],[2263,1639],[2261,1671],[2251,1687],[2237,1697],[2223,1701],[2199,1695],[2227,1713],[2237,1733],[2233,1761],[2219,1781],[2207,1791],[2225,1811],[2245,1827],[2281,1839],[2315,1839],[2377,1855],[2313,1849],[2277,1853],[2251,1843],[2223,1825],[2207,1807],[2193,1799],[2173,1797],[2159,1799],[2153,1821],[2141,1839],[2115,1853],[2105,1871],[2113,2025],[2117,2057],[2113,2077],[2101,2097],[2095,2119],[2101,2135],[2121,2151],[2133,2169],[2127,2193],[2129,2211],[2145,2221],[2167,2215],[2195,2199],[2219,2191],[2265,2189],[2293,2169],[2317,2143],[2355,2137],[2377,2141],[2427,1971],[2387,2147],[2401,2165],[2535,2167],[2405,2179],[2421,2205],[2441,2227],[2445,2255],[2427,2287],[2391,2325],[2365,2357],[2361,2381],[2349,2397],[2327,2419],[2291,2413],[2263,2453],[2229,2473],[2251,2491],[2265,2555],[2263,2583],[2253,2613],[2285,2623],[2331,2645],[2319,2617],[2319,2583],[2335,2565],[2359,2565],[2389,2603],[2401,2627],[2447,2639],[2475,2631],[2493,2619],[2515,2615],[2561,2633],[2603,2635],[2636,2627],[2661,2571],[2687,2569],[2678,2561],[2655,2537],[2636,2546],[2621,2553],[2581,2555],[2549,2539],[2523,2509],[2571,2537],[2611,2545],[2636,2533],[2653,2525],[2637,2503],[2701,2565],[2737,2561],[2679,2583],[2669,2599],[2667,2619],[2659,2637],[2673,2651],[2677,2679],[2665,2697],[2641,2719],[2609,2733],[2601,2759],[2599,2787],[2633,2785],[2671,2787],[2701,2725],[2725,2715],[2779,2717],[2725,2723],[2705,2739],[2689,2771],[2683,2791],[2693,2793],[2737,2831],[2687,2797],[2678,2795],[2667,2793],[2599,2797],[2589,2819],[2575,2839],[2581,2881],[2607,2901],[2611,2927],[2623,2951],[2636,2968],[2647,2997],[2649,3019],[2671,3031],[2687,3029],[2733,3053],[2747,3067],[2753,3089],[2741,3117],[2709,3139],[2757,3151],[2791,3129],[2837,3093],[2865,3063],[2877,3041],[2871,3019],[2823,2963],[2885,3017],[2909,2993],[2951,2975],[2909,3007],[2887,3027],[2885,3053],[2867,3081],[2833,3109],[2805,3139],[2817,3153],[2973,3125],[2983,3135],[2995,3157],[2971,3135],[2939,3135],[2809,3165],[2795,3177],[2801,3191],[2795,3207],[2783,3221],[2785,3239],[2801,3251],[2823,3253],[2847,3239],[2879,3245],[2901,3257],[2921,3273],[2931,3303],[2947,3277],[2967,3273],[3013,3297],[3027,3315],[3179,3419],[3227,3457],[3257,3455],[3275,3441],[3265,3417],[3283,3351],[3277,3327],[3293,3293],[3119,3119],[3297,3283],[3305,3303],[3295,3323],[3309,3333],[3327,3321],[3331,3293],[3383,3241],[3387,3211],[3351,3187],[3321,3153],[3289,3091],[3279,3051],[3263,3047],[3217,3077],[3179,3083],[3147,3067],[3199,3071],[3235,3055],[3261,3039],[3217,2997],[3115,2953],[3169,2955],[3219,2977],[3261,3019],[3289,3039],[3303,3081],[3313,3121],[3351,3171],[3395,3195],[3415,3153],[3433,3131],[3435,3055],[3403,3049],[3373,3033],[3303,2931],[3281,2915],[3213,2909],[3287,2907],[3311,2925],[3381,3027],[3417,3043],[3443,3045],[3449,3061],[3443,3123],[3475,3115],[3493,3091],[3485,3113],[3521,3107],[3545,3085],[3577,2981],[3567,2961],[3519,2943],[3515,2933],[3491,2937],[3447,2913],[3363,2899],[3449,2901],[3497,2923],[3527,2921],[3533,2895],[3557,2881],[3585,2875],[3635,2839],[3615,2817],[3589,2797],[3603,2777],[3609,2743],[3591,2723],[3587,2709],[3453,2701],[3435,2695],[3411,2719],[3179,2655],[3409,2707],[3439,2685],[3467,2691],[3585,2695],[3607,2639],[3597,2605],[3609,2567],[3601,2557],[3539,2551],[3531,2531],[3551,2515],[3593,2505],[3629,2463],[3617,2419],[3605,2389],[3583,2365],[3581,2341],[3553,2347],[3477,2343],[3465,2315],[3479,2289],[3473,2265],[3453,2283],[3431,2289],[3407,2285],[3381,2267],[3377,2245],[3405,2213],[3397,2195],[3361,2197],[3337,2209],[3313,2213],[3305,2235],[3319,2261],[3321,2287],[3305,2335],[3311,2287],[3305,2259],[3289,2235],[3301,2215],[3321,2199],[3347,2195],[3371,2181],[3395,2187],[3407,2139],[3391,2121],[3379,2083],[3375,2019],[3367,1959],[3373,1913],[3371,1893],[3313,1855],[3299,1829],[3305,1797],[3305,1781],[3289,1769],[3243,1759],[3209,1737],[3183,1699],[3155,1687],[3141,1673],[3151,1627],[3151,1603],[3189,1555],[3201,1533],[3181,1483],[3189,1465],[3225,1463],[3239,1441],[3269,1439],[3287,1421],[3307,1411],[3329,1417],[3349,1403],[3355,1373],[3385,1341],[3389,1313],[3377,1269],[3387,1253],[3399,1211],[3409,1197],[3403,1183],[3407,1169],[3439,1145],[3445,1101],[3439,1063],[3455,1047],[3459,1025],[3471,1007],[3483,981],[3505,961],[3569,935],[3639,895],[3569,945],[3509,971],[3489,985],[3479,1007],[3463,1031],[3465,1049],[3449,1065],[3453,1101],[3449,1143],[3431,1165],[3411,1179],[3423,1197],[3411,1211],[3389,1273],[3395,1317],[3393,1339],[3373,1371],[3363,1379],[3359,1405],[3337,1427],[3305,1425],[3277,1441],[3259,1459],[3243,1455],[3227,1475],[3197,1481],[3209,1511],[3213,1541],[3173,1595],[3161,1623],[3157,1657],[3165,1671],[3197,1689],[3221,1729],[3263,1751],[3291,1751],[3319,1767],[3325,1795],[3319,1817],[3331,1847],[3363,1865],[3383,1883],[3395,1909],[3387,1985],[3397,2027],[3399,2071],[3415,2097],[3423,2117],[3423,2141],[3415,2185],[3429,2211],[3473,2235],[3497,2257],[3501,2287],[3489,2309],[3495,2325],[3531,2331],[3565,2321],[3593,2327],[3605,2353],[3603,2367],[3631,2387],[3729,2143],[3771,2119],[3735,2149],[3635,2407],[3649,2459],[3737,2519],[3733,2477],[3747,2447],[3811,2361],[3749,2461],[3739,2487],[3745,2531],[3741,2557],[3729,2583],[3699,2625],[3695,2649],[3707,2671],[3753,2731],[3791,2773],[3805,2811],[3823,2847],[3855,2803],[3853,2771],[3837,2759],[3829,2737],[3797,2695],[3785,2689],[3801,2653],[3831,2651],[3835,2623],[3851,2621],[3857,2593],[3867,2569],[3865,2547],[3879,2529],[3873,2553],[3875,2577],[3861,2625],[3845,2633],[3841,2659],[3807,2661],[3799,2681],[3843,2737],[3847,2753],[3865,2765],[3865,2807],[3837,2847],[3845,2865],[3869,2899],[3889,2945],[3911,3021],[3951,3069],[3959,3097],[3955,3129],[3975,3143],[4017,3147],[4051,3169],[4075,3188],[4087,3197],[4117,3198],[4145,3199],[4177,3223],[4215,3245],[4213,3279],[4199,3331],[4224,3350],[4224,3661],[4117,3663],[4081,3664],[3963,3670],[3937,3690],[3941,3736],[3949,3798],[3965,3816],[3987,3852],[4045,3858],[4075,3832],[4089,3820],[4155,3788],[4215,3782],[4224,3785],[4224,4062],[4195,4066],[4179,4088],[4189,4112],[4224,4129],[4224,4145],[4177,4122],[4101,4200],[4082,4224],[4224,4224],[4224,4224],[-128,4224],[-128,-128]], 3 | [[4117,4162],[4161,4115],[4165,4091],[4177,4067],[4203,4053],[4224,4047],[4224,3801],[4181,3801],[4157,3801],[4127,3819],[4081,3857],[4041,3877],[3997,3875],[3969,3851],[3941,3831],[3933,3769],[3911,3717],[3925,3665],[3929,3639],[3879,3619],[3849,3581],[3823,3601],[3815,3629],[3829,3669],[3861,3699],[3883,3737],[3883,3775],[3881,3827],[3867,3869],[3839,3907],[3787,3959],[3783,3989],[3801,4005],[3797,4027],[3799,4061],[3813,4093],[3805,4141],[3795,4191],[3789,4221],[3801,4224],[3907,4224],[4033,4217],[4049,4224],[4059,4224],[4117,4162],[4117,4162]], 4 | [[3857,2915],[3833,2925],[3817,2921],[3807,2913],[3773,2913],[3761,2927],[3765,2957],[3757,2979],[3773,2991],[3791,2995],[3789,3013],[3817,3017],[3835,3027],[3839,3039],[3827,3047],[3817,3055],[3811,3077],[3789,3085],[3765,3079],[3739,3093],[3711,3107],[3705,3115],[3707,3135],[3689,3161],[3705,3167],[3695,3197],[3705,3205],[3723,3211],[3723,3231],[3751,3229],[3749,3217],[3767,3203],[3799,3167],[3793,3131],[3809,3117],[3869,3085],[3911,3057],[3891,3035],[3887,3001],[3871,2959],[3857,2915],[3857,2915]], 5 | [[3653,2641],[3665,2621],[3681,2615],[3693,2613],[3731,2567],[3737,2541],[3727,2521],[3649,2473],[3625,2503],[3599,2519],[3573,2525],[3555,2531],[3555,2543],[3603,2541],[3631,2553],[3625,2579],[3615,2607],[3625,2643],[3653,2641],[3653,2641]], 6 | [[3413,2227],[3395,2243],[3393,2261],[3413,2273],[3433,2277],[3473,2259],[3413,2227],[3413,2227]], 7 | [[1991,2570],[2223,2614],[2239,2600],[2247,2570],[2237,2542],[2235,2516],[2223,2504],[2207,2490],[2213,2464],[2225,2446],[2249,2440],[2255,2424],[2263,2406],[2283,2394],[2307,2388],[2333,2394],[2343,2386],[2343,2364],[2351,2340],[2373,2318],[2403,2298],[2417,2272],[2421,2256],[2411,2234],[2397,2200],[2379,2172],[2349,2158],[2333,2156],[2315,2166],[2303,2192],[2279,2208],[2241,2208],[2221,2212],[2197,2218],[2181,2228],[2159,2246],[2139,2256],[2127,2260],[2111,2266],[2127,2332],[2251,2288],[2121,2348],[2099,2358],[2081,2378],[2055,2388],[2015,2410],[1973,2430],[1951,2442],[1945,2456],[1947,2476],[1963,2484],[2095,2432],[1969,2494],[1965,2510],[1971,2524],[1983,2538],[1989,2552],[1991,2570],[1991,2570]], 8 | [[850,2552],[858,2452],[790,2436],[778,2380],[806,2416],[870,2428],[910,2276],[870,2256],[838,2204],[762,2212],[706,2164],[686,2128],[634,2016],[582,1996],[510,1976],[422,1964],[370,1928],[314,1884],[270,1884],[218,1908],[130,1924],[134,1988],[106,2028],[86,2064],[114,2108],[114,2152],[-22,2292],[-102,2272],[-128,2252],[-128,2319],[-106,2328],[-102,2364],[-10,2400],[98,2400],[234,2408],[338,2432],[450,2448],[606,2488],[734,2536],[850,2552],[850,2552]], 9 | [[-128,1781],[-118,1780],[-54,1808],[-2,1820],[30,1860],[58,1860],[74,1708],[46,1692],[18,1620],[-54,1608],[-114,1608],[-128,1615],[-128,1781]] 10 | ] 11 | -------------------------------------------------------------------------------- /tests/fixtures/water3.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[-128,4224],[-128,-128],[4224,-128],[4224,4224],[-128,4224]], 3 | [[3030,-21],[3019,7],[3025,21],[3045,65],[3054,114],[3041,189],[3000,219],[3017,257],[2966,338],[2938,340],[2934,541],[2973,618],[2979,752],[3026,803],[3052,938],[3083,1030],[3034,1175],[3041,1264],[3083,1311],[3088,1348],[3067,1399],[3139,1435],[3209,1412],[3220,1378],[3242,1316],[3276,1335],[3314,1367],[3369,1529],[3436,1563],[3464,1681],[3512,1732],[3521,1811],[3508,1883],[3591,1939],[3724,2088],[3828,2171],[3867,2238],[3905,2344],[3939,2443],[3892,2498],[3889,2521],[3884,2560],[3942,2624],[3986,2681],[3999,2831],[4089,3008],[4117,3130],[4104,3172],[4023,3205],[3969,3283],[3991,3347],[4091,3365],[4146,3411],[4136,3456],[4068,3467],[3999,3412],[3978,3373],[3935,3350],[3937,3401],[4001,3465],[4036,3503],[3941,3459],[3907,3533],[3939,3655],[3867,3574],[3867,3663],[3796,3614],[3773,3730],[3880,4118],[3854,4159],[3891,4224],[4084,4224],[4106,4103],[4213,4062],[4224,4060],[4224,2439],[4155,2244],[4020,2282],[3978,2233],[3976,2146],[3927,2103],[3937,2060],[3910,1930],[3933,1862],[3893,1781],[3850,1774],[3803,1712],[3824,1651],[3794,1572],[3820,1535],[3835,1493],[3920,1550],[3957,1520],[3948,1444],[3973,1459],[3982,1508],[4016,1520],[4012,1471],[4042,1426],[4068,1422],[4198,1390],[4224,1368],[4224,969],[4214,1019],[4177,1095],[4142,1070],[4176,978],[4202,843],[4213,653],[4181,656],[4181,804],[4155,796],[4138,673],[4114,600],[4050,622],[4050,573],[4100,551],[4050,379],[4015,274],[3986,208],[3972,175],[3965,158],[3953,131],[3921,99],[3885,60],[3853,29],[3807,-4],[3755,-27],[3692,-53],[3639,-58],[3595,-34],[3573,-11],[3519,-4],[3488,17],[3467,6],[3426,4],[3384,25],[3308,28],[3263,-93],[3126,-83],[3041,-46],[3030,-21],[3030,-21]], 4 | [[3832,-21],[3840,-17],[3877,21],[3895,39],[3961,-21],[3893,-98],[3855,-128],[3688,-128],[3742,-81],[3793,-41],[3832,-21],[3832,-21]], 5 | [[4205,596],[4224,572],[4224,248],[4166,163],[4119,50],[4020,36],[4004,21],[3969,21],[3936,62],[3982,117],[4088,293],[4152,419],[4185,544],[4205,596],[4205,596]], 6 | [[3228,2459],[3243,2459],[3248,2434],[3273,2429],[3218,2186],[3255,2102],[3285,2094],[3314,1972],[3198,1969],[3192,1943],[3223,1943],[3222,1913],[3177,1928],[3187,1979],[3180,2171],[3134,2187],[3212,2399],[3243,2398],[3228,2459],[3228,2459]], 7 | [[4224,1574],[4212,1572],[4175,1600],[4152,1647],[4131,1689],[4106,1736],[4101,1785],[4115,1851],[4149,1885],[4169,1920],[4204,1908],[4224,1875],[4214,1844],[4199,1798],[4215,1763],[4224,1767],[4224,1574]] 8 | ] 9 | -------------------------------------------------------------------------------- /tests/fixtures/water3b.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[-128,4224],[-128,-128],[4224,-128],[4224,4224],[-128,4224]], 3 | [[3832,-21],[3840,-17],[3877,21],[3895,39],[3961,-21],[3893,-98],[3855,-128],[3688,-128],[3742,-81],[3793,-41],[3832,-21],[3832,-21]], 4 | [[4205,596],[4224,572],[4224,248],[4166,163],[4119,50],[4020,36],[4004,21],[3969,21],[3936,62],[3982,117],[4088,293],[4152,419],[4185,544],[4205,596],[4205,596]] 5 | ] 6 | -------------------------------------------------------------------------------- /tests/fixtures/water4.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[3911,4075],[3910,4075],[3926,4114],[3950,4132],[3965,4126],[3978,4139],[3986,4131],[3979,4119],[3986,4084],[3991,4075],[4020,4020],[4027,4012],[4030,4022],[4047,4033],[4058,4030],[4067,4022],[4120,4003],[4118,3993],[4135,3995],[4130,4032],[4121,4038],[4118,4056],[4107,4050],[4095,4060],[4086,4062],[4070,4075],[4027,4111],[4042,4140],[4058,4139],[4067,4135],[4078,4138],[4067,4151],[4067,4166],[4077,4180],[4088,4191],[4047,4172],[4031,4161],[4020,4165],[4000,4147],[4013,4171],[4000,4224],[3836,4224],[3828,4224],[3071,4224],[3070,4212],[3158,4140],[3202,4158],[3171,4117],[3161,4104],[3136,4131],[3122,4117],[3105,4099],[3122,4075],[3136,4055],[3156,4075],[3178,4097],[3205,4082],[3176,4036],[3187,3979],[3105,3947],[3084,3920],[3036,3976],[2980,3982],[2993,4043],[2956,3964],[3020,3960],[3050,3921],[3032,3880],[3069,3902],[3093,3894],[3188,3961],[3236,3917],[3222,3893],[3191,3891],[3173,3863],[3187,3818],[3225,3775],[3292,3774],[3239,3798],[3197,3845],[3211,3873],[3249,3877],[3442,3801],[3567,3769],[3587,3798],[3632,3777],[3607,3820],[3644,3880],[3707,3851],[3726,3899],[3766,3951],[3770,3977],[3778,3985],[3772,4012],[3763,3998],[3745,3990],[3747,3977],[3738,3974],[3735,3985],[3725,3995],[3745,4010],[3758,4024],[3763,4048],[3772,4067],[3762,4074],[3754,4093],[3763,4094],[3779,4083],[3779,4074],[3784,4066],[3792,4060],[3794,4043],[3795,4029],[3798,4016],[3807,4006],[3799,3933],[3849,3871],[3838,3840],[3885,3818],[3913,3778],[3958,3687],[4056,3501],[4109,3301],[3956,3259],[3876,3277],[3775,3251],[3705,3225],[3659,3243],[3613,3232],[3614,3310],[3606,3266],[3552,3297],[3494,3235],[3440,3221],[3402,3190],[3344,3177],[3264,3142],[3279,3201],[3248,3256],[3229,3197],[3200,3194],[3191,3246],[3159,3244],[3125,3282],[3097,3296],[3068,3279],[3013,3393],[3002,3486],[2994,3383],[2917,3406],[2985,3359],[3073,3239],[3106,3270],[3139,3238],[3156,3166],[3156,3101],[3106,3069],[3095,3021],[3060,3025],[3100,2967],[3058,2920],[3115,2933],[3138,2891],[3168,2877],[3217,2892],[3207,2847],[3143,2821],[3192,2691],[3239,2686],[3176,2615],[3191,2615],[3191,2600],[3240,2590],[3189,2544],[3161,2570],[3112,2769],[3087,2798],[3045,2878],[3028,2890],[2992,3118],[2905,3266],[2880,3271],[2860,3342],[2820,3348],[2800,3419],[2775,3424],[2756,3495],[2731,3501],[2711,3572],[2686,3577],[2642,3729],[2612,3730],[2628,3805],[2628,3821],[2579,3968],[2554,3973],[2554,4004],[2524,4004],[2534,4029],[2479,4050],[2470,4075],[2457,4111],[2442,4117],[2419,4126],[2414,4197],[2390,4218],[2388,4224],[-128,4224],[-128,-128],[-128,-128],[4224,-128],[4224,-128],[4224,3063],[4156,3260],[4172,3284],[4147,3288],[4125,3375],[4092,3462],[4080,3524],[3983,3692],[3965,3786],[3984,3816],[3943,3891],[3973,3902],[3978,3917],[3976,3929],[3964,3953],[3957,3968],[3941,3983],[3925,4009],[3923,4024],[3924,4033],[3922,4046],[3920,4055],[3911,4075],[3911,4075]], 3 | [[3364,4097],[3383,4108],[3398,4124],[3406,4144],[3413,4155],[3426,4156],[3442,4162],[3446,4176],[3465,4185],[3488,4189],[3502,4192],[3517,4205],[3520,4224],[3549,4224],[3557,4208],[3540,4198],[3528,4191],[3523,4183],[3510,4184],[3498,4178],[3485,4184],[3479,4173],[3480,4136],[3489,4120],[3475,4116],[3460,4105],[3471,4103],[3469,4083],[3444,4074],[3444,4056],[3455,4070],[3470,4074],[3478,4083],[3488,4079],[3477,4089],[3483,4100],[3475,4107],[3483,4113],[3506,4102],[3502,4092],[3527,4107],[3513,4106],[3512,4117],[3504,4125],[3490,4136],[3487,4146],[3486,4172],[3501,4173],[3510,4178],[3523,4177],[3532,4185],[3568,4199],[3582,4198],[3600,4183],[3579,4144],[3580,4123],[3586,4114],[3586,4104],[3594,4099],[3573,4090],[3581,4103],[3578,4114],[3565,4110],[3565,4101],[3562,4092],[3542,4081],[3540,4067],[3553,4052],[3538,4041],[3529,4040],[3532,4027],[3538,4019],[3551,4018],[3565,4011],[3567,3999],[3576,3996],[3595,3992],[3588,3958],[3573,3922],[3578,3885],[3559,3878],[3553,3866],[3558,3790],[3529,3795],[3468,3809],[3395,3836],[3247,3891],[3246,3922],[3246,3948],[3274,3976],[3335,3983],[3387,3980],[3383,4036],[3387,4052],[3364,4097],[3364,4097]], 4 | [[2976,2176],[2953,2237],[2969,2285],[3011,2301],[3046,2297],[3091,2255],[3133,2276],[3155,2245],[3145,2194],[3171,2157],[3148,2085],[3109,2097],[3096,2079],[3073,2080],[3056,2136],[3008,2171],[3032,2134],[3042,2085],[3064,2068],[3067,2028],[3099,1984],[3126,1980],[3146,1951],[3158,1893],[3207,1857],[3240,1826],[3321,1842],[3238,1848],[3213,1885],[3177,1917],[3163,1968],[3138,2017],[3180,2004],[3206,1958],[3272,1951],[3346,1944],[3360,1988],[3402,2001],[3437,2053],[3460,2054],[3468,2089],[3455,2140],[3425,2187],[3486,2135],[3505,2080],[3506,2038],[3516,1985],[3559,1955],[3556,1887],[3548,1857],[3520,1881],[3482,1895],[3473,1860],[3448,1842],[3449,1791],[3480,1773],[3532,1750],[3510,1789],[3463,1808],[3475,1835],[3509,1874],[3542,1836],[3579,1847],[3579,1891],[3580,1936],[3601,1954],[3630,1924],[3699,1930],[3720,1966],[3708,1994],[3695,1943],[3629,1945],[3611,1975],[3581,1966],[3556,1993],[3548,2073],[3517,2148],[3475,2199],[3486,2254],[3456,2300],[3410,2293],[3384,2219],[3346,2189],[3270,2185],[3214,2148],[3183,2217],[3231,2271],[3301,2317],[3296,2369],[3282,2441],[3230,2488],[3242,2507],[3233,2539],[3275,2568],[3272,2646],[3301,2638],[3312,2583],[3359,2662],[3350,2602],[3374,2555],[3413,2549],[3444,2550],[3459,2526],[3481,2534],[3464,2556],[3506,2588],[3536,2535],[3555,2549],[3518,2625],[3491,2600],[3463,2623],[3451,2583],[3398,2637],[3437,2690],[3378,2678],[3354,2693],[3301,2701],[3301,2767],[3266,2712],[3235,2713],[3195,2731],[3203,2761],[3224,2792],[3291,2804],[3341,2802],[3357,2780],[3363,2753],[3388,2724],[3415,2726],[3445,2736],[3460,2779],[3516,2736],[3537,2741],[3579,2749],[3608,2715],[3645,2709],[3659,2727],[3691,2712],[3734,2691],[3745,2648],[3731,2635],[3687,2679],[3654,2685],[3633,2662],[3598,2658],[3584,2630],[3596,2597],[3594,2557],[3613,2518],[3640,2517],[3636,2486],[3658,2444],[3647,2409],[3686,2446],[3652,2488],[3651,2525],[3626,2560],[3655,2597],[3630,2629],[3667,2669],[3727,2616],[3758,2623],[3817,2628],[3823,2593],[3791,2551],[3753,2515],[3754,2484],[3775,2484],[3795,2454],[3831,2471],[3893,2485],[3927,2485],[3953,2458],[3998,2422],[4046,2383],[4022,2355],[4020,2296],[3946,2285],[3902,2357],[3920,2295],[3894,2249],[3839,2250],[3898,2235],[3927,2187],[3916,2149],[3887,2161],[3822,2135],[3883,2132],[3922,2040],[3909,2109],[3937,2104],[3949,2152],[3998,2135],[4080,2138],[4119,2083],[4101,2020],[4106,1978],[4164,1986],[4163,1952],[4203,1992],[4210,2013],[4200,2031],[4224,2021],[4224,1949],[4216,1915],[4199,1891],[4199,1876],[4183,1816],[4097,1796],[4059,1748],[4030,1713],[3989,1696],[3955,1681],[3926,1657],[3869,1646],[3824,1612],[3788,1591],[3561,1609],[3546,1624],[3515,1624],[3510,1649],[3350,1732],[3335,1732],[3274,1748],[3259,1763],[3108,1795],[3049,1887],[3015,2080],[2976,2176],[2976,2176]], 5 | [[3183,-128],[3192,-118],[3253,-36],[3313,26],[3357,31],[3406,103],[3514,134],[3541,271],[3547,344],[3664,311],[3669,216],[3565,168],[3662,150],[3655,88],[3528,39],[3581,26],[3608,-21],[3675,-87],[3637,-128],[3183,-128]], 6 | [[3205,-15],[3114,-30],[3065,-59],[3017,-29],[3047,7],[3013,118],[2971,183],[2978,281],[3026,305],[3081,298],[3107,369],[3157,360],[3191,397],[3312,393],[3350,371],[3363,294],[3419,236],[3334,298],[3306,338],[3305,290],[3261,235],[3253,140],[3254,86],[3335,51],[3273,34],[3227,26],[3199,49],[3232,96],[3223,166],[3224,247],[3242,268],[3224,281],[3202,244],[3173,266],[3187,328],[3158,328],[3136,258],[3184,231],[3177,169],[3149,144],[3133,188],[3078,155],[3058,183],[3102,221],[3074,236],[3048,198],[3011,180],[3043,144],[3111,74],[3120,37],[3098,19],[3100,-1],[3201,8],[3205,-15],[3205,-15]], 7 | [[4224,2296],[4180,2330],[4198,2362],[4203,2411],[4224,2415],[4224,2482],[4212,2474],[4198,2509],[4197,2541],[4177,2531],[4124,2533],[4101,2514],[4023,2555],[4029,2506],[4055,2468],[4029,2422],[3955,2489],[3928,2532],[3913,2515],[3857,2512],[3804,2481],[3789,2511],[3844,2590],[3830,2643],[3767,2641],[3761,2730],[3704,2728],[3675,2737],[3670,2764],[3651,2765],[3651,2741],[3626,2729],[3607,2761],[3552,2763],[3551,2781],[3513,2781],[3505,2817],[3477,2800],[3459,2831],[3422,2852],[3420,2901],[3399,2855],[3428,2807],[3428,2770],[3402,2751],[3378,2764],[3400,2817],[3363,2833],[3319,2849],[3299,2895],[3313,2925],[3283,2942],[3286,2853],[3237,2904],[3230,2941],[3254,2952],[3267,2985],[3302,3016],[3346,2995],[3379,3004],[3384,3070],[3416,3072],[3456,3069],[3459,3042],[3478,2986],[3481,3022],[3496,3023],[3512,3072],[3486,3080],[3488,3150],[3508,3174],[3535,3195],[3553,3174],[3571,3206],[3605,3179],[3639,3213],[3701,3204],[3881,3256],[3964,3239],[4113,3273],[4168,3133],[4224,2979],[4224,2296]] 8 | ] 9 | -------------------------------------------------------------------------------- /tests/integration_test.rs: -------------------------------------------------------------------------------- 1 | extern crate earcutr; 2 | 3 | extern crate serde; 4 | extern crate serde_json; 5 | 6 | use std::fs::File; 7 | use std::fs::OpenOptions; 8 | use std::io::Read; 9 | use std::io::Write; 10 | 11 | static DEBUG: usize = 1; 12 | macro_rules! dlog { 13 | ($loglevel:expr, $($s:expr),*) => ( 14 | if DEBUG>=$loglevel { print!("{}:",$loglevel); println!($($s),+); } 15 | ) 16 | } 17 | 18 | //fn format_percent(num: f64) -> String { 19 | // return num.to_string(); 20 | //String::from("1.234"); 21 | // return ((1e8 * num).round() / 1e6).to_string();// + "%"; 22 | //} 23 | 24 | fn parse_json(rawdata: &str) -> Option>>> { 25 | let mut v: Vec>> = Vec::new(); 26 | match serde_json::from_str::(&rawdata) { 27 | Err(e) => println!("error deserializing, {}", e), 28 | Ok(jsondata) => { 29 | if jsondata.is_array() { 30 | let contours = jsondata.as_array().unwrap(); 31 | dlog!(4, "deserialize ok, {} contours", contours.len()); 32 | for i in 0..contours.len() { 33 | let contourval = &contours[i]; 34 | if contourval.is_array() { 35 | let contour = contourval.as_array().unwrap(); 36 | dlog!(9, "countour {} numpoints {}", i, contour.len()); 37 | let mut vc: Vec> = Vec::new(); 38 | for j in 0..contour.len() { 39 | let points = contour[j].as_array().unwrap(); 40 | let mut vp: Vec = Vec::new(); 41 | for k in 0..points.len() { 42 | let val = points[k].to_string(); 43 | let pval = val.parse::().unwrap(); 44 | vp.push(pval); 45 | } 46 | vc.push(vp); 47 | } 48 | v.push(vc); 49 | } 50 | } 51 | } 52 | } 53 | }; 54 | return Some(v); 55 | } 56 | 57 | fn mkoutput( 58 | filename_w_dashes: &str, 59 | tris: Vec, 60 | data: &Vec>>, 61 | pass: bool, 62 | rpt: &str, 63 | ) -> Result<(), std::io::Error> { 64 | dlog!( 65 | 4, 66 | "save data + triangles: {}, num tri pts:{}, rpt: {},", 67 | &filename_w_dashes, 68 | tris.len(), 69 | rpt 70 | ); 71 | let filename = str::replace(filename_w_dashes, "-", "_"); 72 | let outfile = &format!("viz/testoutput/{}.js", filename); 73 | let f = OpenOptions::new() 74 | .write(true) 75 | .create(true) 76 | .truncate(true) 77 | .open(outfile) 78 | .unwrap(); 79 | try!(writeln!(&f, r###"testOutput["{}"]=[];"###, filename)); 80 | try!(writeln!( 81 | &f, 82 | r###"testOutput["{}"]["json"]={:?};"###, 83 | filename, data 84 | )); 85 | try!(writeln!( 86 | &f, 87 | r###"testOutput["{}"]["triangles"]={:?};"###, 88 | filename, tris 89 | )); 90 | try!(writeln!( 91 | &f, 92 | r###"testOutput["{}"]["pass"]={:?};"###, 93 | filename, pass 94 | )); 95 | try!(writeln!( 96 | &f, 97 | r###"testOutput["{}"]["report"]={:?};"###, 98 | filename, rpt 99 | )); 100 | dlog!(4, "wrote results to {}", outfile); 101 | Ok(()) 102 | } 103 | 104 | // verify if triangles cover the same area as the shape itself 105 | fn area_test(filename: &str, expected_num_tris: usize, expected_deviation: f64) -> bool { 106 | // let visualize = std::env::args().any(|x| x == "--test-threads=1"); 107 | let visualize = true; 108 | dlog!(4, "visualization: {}", visualize); 109 | let mut actual_num_tris = 0; 110 | let mut actual_deviation = 0.0; 111 | let mut edeviation = expected_deviation; 112 | let mut triangles: Vec = Vec::new(); 113 | let mut xdata: Vec>> = Vec::new(); 114 | if edeviation == 0.0 { 115 | edeviation = 1e-14; 116 | } 117 | let fullname = format!("tests/fixtures/{}.json", filename); 118 | match File::open(&fullname) { 119 | Err(why) => panic!("failed to open file '{}': {}", fullname, why), 120 | Ok(mut f) => { 121 | dlog!(4, "testing {},", fullname); 122 | let mut strdata = String::new(); 123 | match f.read_to_string(&mut strdata) { 124 | Err(why) => dlog!(4, "failed to read {}, {}", fullname, why), 125 | Ok(numb) => { 126 | dlog!(4, "read {} bytes", numb); 127 | let rawstring = strdata.trim(); 128 | match parse_json(rawstring) { 129 | None => dlog!(4, "failed to parse {}", fullname), 130 | Some(parsed_data) => { 131 | xdata = parsed_data; 132 | let (data, holeidxs, dimensions) = earcutr::flatten(&xdata); 133 | triangles = earcutr::earcut(&data, &holeidxs, dimensions); 134 | actual_num_tris = triangles.len() / 3; 135 | actual_deviation = 136 | earcutr::deviation(&data, &holeidxs, dimensions, &triangles); 137 | } 138 | }; 139 | } 140 | }; 141 | } 142 | }; 143 | let mut pass = true; 144 | if expected_num_tris > 0 && (expected_num_tris < actual_num_tris) { 145 | pass = false; 146 | }; 147 | if edeviation < actual_deviation { 148 | pass = false; 149 | }; 150 | let rpt = format!( 151 | "exp numtri:{}\nexp dev:{}\nact numtri:{}\nact dev:{}", 152 | expected_num_tris, edeviation, actual_num_tris, actual_deviation 153 | ); 154 | if visualize { 155 | match mkoutput(&filename, triangles, &xdata, pass, &rpt) { 156 | Err(e) => println!("error writing output {}", e), 157 | _ => {} 158 | } 159 | } 160 | pass 161 | } 162 | 163 | // inline data based tests 164 | 165 | #[test] 166 | fn test_indices_2d() { 167 | let indices = earcutr::earcut( 168 | &vec![10.0, 0.0, 0.0, 50.0, 60.0, 60.0, 70.0, 10.0], 169 | &vec![], 170 | 2, 171 | ); 172 | assert!(indices == vec![1, 0, 3, 3, 2, 1]); 173 | } 174 | 175 | /* 176 | #[test] 177 | fn test_indices_3d() { 178 | let indices = earcutr::earcut( 179 | &vec![ 180 | 10.0, 0.0, 0.0, 0.0, 50.0, 0.0, 60.0, 60.0, 0.0, 70.0, 10.0, 0.0, 181 | ], 182 | &vec![], 183 | 3, 184 | ); 185 | assert!(indices == vec![1, 0, 3, 3, 2, 1]); 186 | } 187 | */ 188 | 189 | #[test] 190 | fn test_empty() { 191 | let indices = earcutr::earcut(&vec![], &vec![], 2); 192 | println!("{:?}", indices); 193 | assert!(indices.len() == 0); 194 | } 195 | 196 | // file based tests 197 | 198 | #[test] 199 | fn test_building() { 200 | assert!(area_test("building", 13, 0e0)); 201 | } 202 | 203 | #[test] 204 | fn test_dude() { 205 | assert!(area_test("dude", 106, 0e0)); 206 | } 207 | 208 | #[test] 209 | fn test_water() { 210 | assert!(area_test("water", 2482, 8e-4)); 211 | } 212 | 213 | #[test] 214 | fn test_water2() { 215 | assert!(area_test("water2", 1212, 0e0)); 216 | } 217 | 218 | #[test] 219 | fn test_water3() { 220 | assert!(area_test("water3", 197, 0e0)); 221 | } 222 | 223 | #[test] 224 | fn test_water3b() { 225 | assert!(area_test("water3b", 25, 0e0)); 226 | } 227 | 228 | #[test] 229 | fn test_water4() { 230 | assert!(area_test("water4", 705, 0e0)); 231 | } 232 | 233 | #[test] 234 | fn test_water_huge() { 235 | assert!(area_test("water-huge", 5174, 1.1e-3)); 236 | } 237 | 238 | #[test] 239 | fn test_water_huge2() { 240 | assert!(area_test("water-huge2", 4461, 2.8e-3)); 241 | } 242 | 243 | #[test] 244 | fn test_degenerate() { 245 | assert!(area_test("degenerate", 0, 0e0)); 246 | } 247 | 248 | #[test] 249 | fn test_bad_hole() { 250 | assert!(area_test("bad-hole", 42, 1.9e-2)); 251 | } 252 | 253 | #[test] 254 | fn test_empty_square() { 255 | assert!(area_test("empty-square", 0, 0e0)); 256 | } 257 | 258 | #[test] 259 | fn test_issue16() { 260 | assert!(area_test("issue16", 12, 0e0)); 261 | } 262 | 263 | #[test] 264 | fn test_issue17() { 265 | assert!(area_test("issue17", 11, 0e0)); 266 | } 267 | 268 | #[test] 269 | fn test_steiner() { 270 | assert!(area_test("steiner", 9, 0e0)); 271 | } 272 | 273 | #[test] 274 | fn test_issue29() { 275 | assert!(area_test("issue29", 40, 0e0)); 276 | } 277 | 278 | #[test] 279 | fn test_issue34() { 280 | assert!(area_test("issue34", 139, 0e0)); 281 | } 282 | 283 | #[test] 284 | fn test_issue35() { 285 | assert!(area_test("issue35", 844, 0e0)); 286 | } 287 | 288 | #[test] 289 | fn test_self_touching() { 290 | assert!(area_test("self-touching", 124, 3.4e-14)); 291 | } 292 | 293 | #[test] 294 | fn test_outside_ring() { 295 | assert!(area_test("outside-ring", 64, 0e0)); 296 | } 297 | 298 | #[test] 299 | fn test_simplified_us_border() { 300 | assert!(area_test("simplified-us-border", 120, 0e0)); 301 | } 302 | 303 | #[test] 304 | fn test_touching_holes() { 305 | assert!(area_test("touching-holes", 57, 0e0)); 306 | } 307 | 308 | #[test] 309 | fn test_hole_touching_outer() { 310 | assert!(area_test("hole-touching-outer", 77, 0e0)); 311 | } 312 | 313 | #[test] 314 | fn test_hilbert() { 315 | assert!(area_test("hilbert", 1024, 0e0)); 316 | } 317 | 318 | #[test] 319 | fn test_issue45() { 320 | assert!(area_test("issue45", 10, 0e0)); 321 | } 322 | 323 | #[test] 324 | fn test_eberly_3() { 325 | assert!(area_test("eberly-3", 73, 0e0)); 326 | } 327 | 328 | #[test] 329 | fn test_eberly_6() { 330 | assert!(area_test("eberly-6", 1429, 0e0)); 331 | } 332 | 333 | #[test] 334 | fn test_issue52() { 335 | assert!(area_test("issue52", 109, 0e0)); 336 | } 337 | 338 | #[test] 339 | fn test_shared_points() { 340 | assert!(area_test("shared-points", 4, 0e0)); 341 | } 342 | 343 | #[test] 344 | fn test_bad_diagonals() { 345 | assert!(area_test("bad-diagonals", 7, 0e0)); 346 | } 347 | 348 | #[test] 349 | fn test_issue83() { 350 | assert!(area_test("issue83", 0, 1e-14)); 351 | } 352 | -------------------------------------------------------------------------------- /viz/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/donbright/earcutr/c720dab5d6ab8b5b9abbf2f4222df3b6f5857ff3/viz/circle.png -------------------------------------------------------------------------------- /viz/testoutput/bad_diagonals.js: -------------------------------------------------------------------------------- 1 | testOutput["bad_diagonals"]=[]; 2 | testOutput["bad_diagonals"]["json"]=[[[440.0, 4152.0], [440.0, 4208.0], [296.0, 4192.0], [368.0, 4192.0], [400.0, 4200.0], [400.0, 4176.0], [368.0, 4192.0], [296.0, 4192.0], [264.0, 4200.0], [288.0, 4160.0], [296.0, 4192.0]]]; 3 | testOutput["bad_diagonals"]["triangles"]=[8, 9, 7, 7, 5, 6, 5, 10, 0, 2, 3, 4, 4, 5, 0, 1, 2, 4, 4, 0, 1]; 4 | testOutput["bad_diagonals"]["pass"]=true; 5 | testOutput["bad_diagonals"]["report"]="exp numtri:7\nexp dev:0.00000000000001\nact numtri:7\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/bad_hole.js: -------------------------------------------------------------------------------- 1 | testOutput["bad_hole"]=[]; 2 | testOutput["bad_hole"]["json"]=[[[810.0, 2828.0], [818.0, 2828.0], [832.0, 2818.0], [844.0, 2806.0], [855.0, 2808.0], [866.0, 2816.0], [867.0, 2824.0], [876.0, 2827.0], [883.0, 2834.0], [875.0, 2834.0], [867.0, 2840.0], [878.0, 2838.0], [889.0, 2844.0], [880.0, 2847.0], [870.0, 2847.0], [860.0, 2864.0], [852.0, 2879.0], [847.0, 2867.0], [810.0, 2828.0], [810.0, 2828.0]], [[818.0, 2834.0], [823.0, 2833.0], [831.0, 2828.0], [839.0, 2829.0], [839.0, 2837.0], [851.0, 2845.0], [847.0, 2835.0], [846.0, 2827.0], [847.0, 2827.0], [837.0, 2827.0], [840.0, 2815.0], [835.0, 2823.0], [818.0, 2834.0], [818.0, 2834.0]], [[857.0, 2846.0], [864.0, 2850.0], [866.0, 2839.0], [857.0, 2846.0], [857.0, 2846.0]], [[848.0, 2863.0], [848.0, 2866.0], [854.0, 2852.0], [846.0, 2854.0], [847.0, 2862.0], [838.0, 2851.0], [838.0, 2859.0], [848.0, 2863.0], [848.0, 2863.0]]]; 3 | testOutput["bad_hole"]["triangles"]=[21, 22, 23, 25, 34, 35, 27, 29, 30, 2, 3, 4, 4, 5, 6, 6, 7, 8, 10, 11, 12, 12, 13, 14, 15, 16, 17, 45, 39, 40, 42, 43, 44, 44, 0, 20, 21, 23, 24, 30, 31, 32, 32, 0, 1, 6, 8, 9, 10, 12, 14, 14, 15, 17, 17, 0, 44, 20, 21, 24, 30, 32, 1, 6, 9, 10, 20, 24, 25, 36, 37, 25, 25, 26, 27, 30, 1, 2, 4, 6, 10, 20, 25, 35, 36, 25, 27, 30, 2, 4, 36, 27, 30, 36, 30, 4, 36, 4, 10, 35, 36, 10, 35, 10, 14, 17, 44, 40, 41, 42, 44, 44, 20, 35, 14, 17, 40, 41, 44, 35, 35, 14, 40, 40, 41, 35]; 4 | testOutput["bad_hole"]["pass"]=true; 5 | testOutput["bad_hole"]["report"]="exp numtri:42\nexp dev:0.019\nact numtri:42\nact dev:0.018674136321195144"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/building.js: -------------------------------------------------------------------------------- 1 | testOutput["building"]=[]; 2 | testOutput["building"]["json"]=[[[661.0, 112.0], [661.0, 96.0], [666.0, 96.0], [666.0, 87.0], [743.0, 87.0], [771.0, 87.0], [771.0, 114.0], [750.0, 114.0], [750.0, 113.0], [742.0, 113.0], [742.0, 106.0], [710.0, 106.0], [710.0, 113.0], [666.0, 113.0], [666.0, 112.0]]]; 3 | testOutput["building"]["triangles"]=[14, 0, 1, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 1, 2, 4, 6, 8, 11, 13, 14, 14, 2, 4, 4, 8, 10, 11, 14, 4, 4, 10, 11]; 4 | testOutput["building"]["pass"]=true; 5 | testOutput["building"]["report"]="exp numtri:13\nexp dev:0.00000000000001\nact numtri:13\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/degenerate.js: -------------------------------------------------------------------------------- 1 | testOutput["degenerate"]=[]; 2 | testOutput["degenerate"]["json"]=[[[100.0, 100.0], [100.0, 100.0], [200.0, 100.0], [200.0, 200.0], [200.0, 100.0], [0.0, 100.0]]]; 3 | testOutput["degenerate"]["triangles"]=[]; 4 | testOutput["degenerate"]["pass"]=true; 5 | testOutput["degenerate"]["report"]="exp numtri:0\nexp dev:0.00000000000001\nact numtri:0\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/dude.js: -------------------------------------------------------------------------------- 1 | testOutput["dude"]=[]; 2 | testOutput["dude"]["json"]=[[[280.35714, 648.79075], [286.78571, 662.8979], [263.28607, 661.17871], [262.31092, 671.41548], [250.53571, 677.00504], [250.53571, 683.43361], [256.42857, 685.21933], [297.14286, 669.50504], [289.28571, 649.50504], [285.0, 631.6479], [285.0, 608.79075], [292.85714, 585.21932], [306.42857, 563.79075], [323.57143, 548.79075], [339.28571, 545.21932], [357.85714, 547.36218], [375.0, 550.21932], [391.42857, 568.07647], [404.28571, 588.79075], [413.57143, 612.36218], [417.14286, 628.07647], [438.57143, 619.1479], [438.03572, 618.96932], [437.5, 609.50504], [426.96429, 609.86218], [424.64286, 615.57647], [419.82143, 615.04075], [420.35714, 605.04075], [428.39286, 598.43361], [437.85714, 599.68361], [443.57143, 613.79075], [450.71429, 610.21933], [431.42857, 575.21932], [405.71429, 550.21932], [372.85714, 534.50504], [349.28571, 531.6479], [346.42857, 521.6479], [346.42857, 511.6479], [350.71429, 496.6479], [367.85714, 476.6479], [377.14286, 460.93361], [385.71429, 445.21932], [388.57143, 404.50504], [360.0, 352.36218], [337.14286, 325.93361], [330.71429, 334.50504], [347.14286, 354.50504], [337.85714, 370.21932], [333.57143, 359.50504], [319.28571, 353.07647], [312.85714, 366.6479], [350.71429, 387.36218], [368.57143, 408.07647], [375.71429, 431.6479], [372.14286, 454.50504], [366.42857, 462.36218], [352.85714, 462.36218], [336.42857, 456.6479], [332.85714, 438.79075], [338.57143, 423.79075], [338.57143, 411.6479], [327.85714, 405.93361], [320.71429, 407.36218], [315.71429, 423.07647], [314.28571, 440.21932], [325.0, 447.71932], [324.82143, 460.93361], [317.85714, 470.57647], [304.28571, 483.79075], [287.14286, 491.29075], [263.03571, 498.61218], [251.60714, 503.07647], [251.25, 533.61218], [260.71429, 533.61218], [272.85714, 528.43361], [286.07143, 518.61218], [297.32143, 508.25504], [297.85714, 507.36218], [298.39286, 506.46932], [307.14286, 496.6479], [312.67857, 491.6479], [317.32143, 503.07647], [322.5, 514.1479], [325.53571, 521.11218], [327.14286, 525.75504], [326.96429, 535.04075], [311.78571, 540.04075], [291.07143, 552.71932], [274.82143, 568.43361], [259.10714, 592.8979], [254.28571, 604.50504], [251.07143, 621.11218], [250.53571, 649.1479], [268.1955, 654.36208]], [[325.0, 437.0], [320.0, 423.0], [329.0, 413.0], [332.0, 423.0]], [[320.72342, 480.0], [338.90617, 465.96863], [347.99754, 480.61584], [329.8148, 510.41534], [339.91632, 480.11077], [334.86556, 478.09046]]]; 3 | testOutput["dude"]["triangles"]=[93, 92, 91, 91, 90, 89, 89, 88, 87, 87, 86, 85, 82, 81, 80, 77, 76, 75, 75, 74, 73, 73, 72, 71, 71, 70, 69, 69, 68, 98, 98, 103, 102, 99, 98, 68, 65, 64, 63, 63, 95, 94, 96, 95, 63, 63, 62, 61, 61, 60, 59, 51, 50, 49, 49, 48, 47, 46, 45, 44, 44, 43, 42, 42, 41, 40, 40, 39, 38, 35, 34, 33, 33, 32, 31, 31, 30, 29, 25, 24, 23, 22, 21, 20, 7, 6, 5, 5, 4, 3, 3, 2, 1, 0, 93, 91, 91, 89, 87, 78, 77, 75, 75, 73, 71, 69, 98, 102, 99, 68, 67, 65, 63, 94, 96, 63, 61, 51, 49, 47, 46, 44, 42, 33, 31, 29, 25, 23, 22, 7, 5, 3, 0, 91, 87, 79, 78, 75, 75, 71, 69, 99, 67, 66, 65, 94, 97, 97, 96, 61, 52, 51, 47, 47, 46, 42, 33, 29, 28, 26, 25, 22, 7, 3, 1, 79, 75, 69, 99, 66, 65, 97, 61, 59, 52, 47, 42, 33, 28, 27, 26, 22, 20, 8, 7, 1, 80, 79, 69, 65, 97, 59, 53, 52, 42, 33, 27, 26, 26, 20, 19, 9, 8, 1, 80, 69, 102, 65, 59, 58, 54, 53, 42, 33, 26, 19, 9, 1, 0, 82, 80, 102, 65, 58, 57, 54, 42, 40, 33, 19, 18, 10, 9, 0, 83, 82, 102, 99, 65, 57, 55, 54, 40, 33, 18, 17, 10, 0, 87, 83, 102, 101, 100, 99, 57, 55, 40, 38, 33, 17, 16, 11, 10, 87, 84, 83, 101, 100, 57, 56, 56, 55, 38, 35, 33, 16, 12, 11, 87, 85, 84, 101, 100, 56, 38, 35, 16, 15, 13, 12, 87, 85, 101, 100, 100, 38, 37, 35, 15, 14, 14, 13, 87, 85, 100, 37, 36, 35, 14, 14, 87, 85, 85, 37, 36, 36, 14, 85]; 4 | testOutput["dude"]["pass"]=true; 5 | testOutput["dude"]["report"]="exp numtri:106\nexp dev:0.00000000000001\nact numtri:106\nact dev:0.0000000000000012205647034940505"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/eberly_3.js: -------------------------------------------------------------------------------- 1 | testOutput["eberly_3"]=[]; 2 | testOutput["eberly_3"]["json"]=[[[2328.0, 2408.0], [2328.0, 2472.0], [2344.0, 2472.0], [2344.0, 2432.0], [2384.0, 2448.0], [2384.0, 2536.0], [2408.0, 2552.0], [2448.0, 2544.0], [2456.0, 2560.0], [2496.0, 2544.0], [2480.0, 2624.0], [2456.0, 2664.0], [2424.0, 2680.0], [2400.0, 2768.0], [2376.0, 2768.0], [2368.0, 2704.0], [2336.0, 2704.0], [2264.0, 2784.0], [2216.0, 2784.0], [2200.0, 2760.0], [2168.0, 2760.0], [2152.0, 2744.0], [2128.0, 2744.0], [2128.0, 2784.0], [2072.0, 2768.0], [2032.0, 2720.0], [2000.0, 2720.0], [2000.0, 2688.0], [1936.0, 2696.0], [1920.0, 2736.0], [1888.0, 2728.0], [1896.0, 2696.0], [1928.0, 2688.0], [1928.0, 2664.0], [1896.0, 2664.0], [1896.0, 2640.0], [1912.0, 2632.0], [1872.0, 2608.0], [1888.0, 2576.0], [2056.0, 2576.0], [2088.0, 2600.0], [2184.0, 2608.0], [2216.0, 2632.0], [2256.0, 2624.0], [2248.0, 2600.0], [2216.0, 2592.0], [2192.0, 2560.0], [2120.0, 2576.0], [2072.0, 2544.0], [2096.0, 2544.0], [2080.0, 2520.0], [2080.0, 2488.0], [2096.0, 2480.0], [2080.0, 2448.0], [2096.0, 2432.0], [2176.0, 2496.0], [2200.0, 2488.0], [2224.0, 2528.0], [2248.0, 2528.0], [2240.0, 2488.0], [2256.0, 2472.0], [2280.0, 2480.0], [2264.0, 2416.0], [2272.0, 2392.0], [2328.0, 2408.0]], [[2320.0, 2608.0], [2304.0, 2640.0], [2312.0, 2664.0], [2360.0, 2632.0], [2352.0, 2608.0], [2320.0, 2608.0]], [[1912.0, 2632.0], [1936.0, 2632.0], [1936.0, 2616.0], [1912.0, 2608.0], [1912.0, 2632.0]]]; 3 | testOutput["eberly_3"]["triangles"]=[2, 3, 4, 6, 7, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 30, 31, 32, 33, 34, 35, 35, 66, 67, 66, 35, 71, 74, 36, 37, 37, 38, 39, 40, 41, 42, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 63, 0, 1, 2, 4, 5, 6, 8, 10, 12, 14, 15, 16, 18, 19, 22, 24, 25, 28, 30, 32, 33, 35, 67, 66, 71, 72, 74, 37, 39, 46, 48, 49, 49, 51, 52, 52, 54, 55, 58, 60, 61, 61, 63, 1, 1, 2, 5, 5, 6, 10, 10, 12, 15, 16, 19, 21, 21, 22, 25, 27, 28, 32, 32, 33, 67, 66, 72, 73, 73, 74, 39, 46, 49, 52, 52, 55, 57, 58, 61, 1, 5, 10, 15, 16, 21, 25, 27, 32, 67, 73, 39, 40, 44, 46, 52, 58, 1, 5, 16, 25, 27, 73, 40, 42, 44, 52, 57, 57, 58, 5, 15, 16, 27, 66, 73, 42, 44, 57, 5, 15, 27, 67, 66, 42, 43, 43, 44, 5, 15, 67, 68, 65, 66, 43, 5, 15, 68, 65, 43, 5, 5, 68, 69, 69, 65, 5]; 4 | testOutput["eberly_3"]["pass"]=true; 5 | testOutput["eberly_3"]["report"]="exp numtri:73\nexp dev:0.00000000000001\nact numtri:73\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/empty_square.js: -------------------------------------------------------------------------------- 1 | testOutput["empty_square"]=[]; 2 | testOutput["empty_square"]["json"]=[[[0.0, 0.0], [4000.0, 0.0], [4000.0, 4000.0], [0.0, 4000.0]], [[0.0, 0.0], [4000.0, 0.0], [4000.0, 4000.0], [0.0, 4000.0]]]; 3 | testOutput["empty_square"]["triangles"]=[]; 4 | testOutput["empty_square"]["pass"]=true; 5 | testOutput["empty_square"]["report"]="exp numtri:0\nexp dev:0.00000000000001\nact numtri:0\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/hole_touching_outer.js: -------------------------------------------------------------------------------- 1 | testOutput["hole_touching_outer"]=[]; 2 | testOutput["hole_touching_outer"]["json"]=[[[-64.0, -64.0], [253.0, -64.0], [491.0, 358.0], [697.0, 298.0], [928.0, 197.0], [929.0, 505.0], [1346.0, 507.0], [1347.0, 303.0], [1771.0, 306.0], [1770.0, 512.0], [2191.0, 509.0], [2198.0, 933.0], [2621.0, 932.0], [2623.0, 1115.0], [2577.0, 1120.0], [2494.0, 1183.0], [2390.0, 1329.0], [2326.0, 1590.0], [2287.0, 1678.0], [2286.0, 1407.0], [2229.0, 1407.0], [2182.0, 1493.0], [2106.0, 1494.0], [2068.0, 1460.0], [2019.0, 1460.0], [2016.0, 1775.0], [1889.0, 1923.0], [1953.0, 1989.0], [2097.0, 1866.0], [2198.0, 1925.0], [2203.0, 1973.0], [2311.0, 1976.0], [2320.0, 1831.0], [2352.0, 1824.0], [2358.0, 1797.0], [2378.0, 1780.0], [3350.0, 1782.0], [3307.0, 2086.0], [3139.0, 2088.0], [3143.0, 2203.0], [3493.0, 2205.0], [3543.0, 2187.0], [3540.0, 2260.0], [3661.0, 2264.0], [3665.0, 1906.0], [3630.0, 1902.0], [3626.0, 1784.0], [4160.0, 1786.0], [4160.0, 2631.0], [4076.0, 2631.0], [4021.0, 2683.0], [3930.0, 2701.0], [3915.0, 2693.0], [3898.0, 2639.0], [2630.0, 2630.0], [2635.0, 3476.0], [2287.0, 3478.0], [2118.0, 3203.0], [2180.0, 3145.0], [2327.0, 3087.0], [2610.0, 2643.0], [2613.0, 2536.0], [2658.0, 2495.0], [2650.0, 2203.0], [1829.0, 2189.0], [1732.0, 2241.0], [1551.0, 2245.0], [933.0, 1183.0], [890.0, 1152.0], [455.0, 401.0], [398.0, 412.0], [89.0, 547.0], [-64.0, 606.0], [-64.0, -64.0]], [[1762.0, 928.0], [1770.0, 512.0], [1343.0, 513.0], [1345.0, 715.0], [931.0, 719.0], [932.0, 930.0], [1762.0, 928.0]]]; 3 | testOutput["hole_touching_outer"]["triangles"]=[0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 16, 17, 18, 20, 21, 22, 24, 25, 26, 27, 28, 29, 31, 32, 33, 33, 34, 35, 35, 36, 37, 40, 41, 42, 44, 45, 46, 46, 47, 48, 49, 50, 51, 51, 52, 53, 54, 55, 56, 56, 57, 58, 60, 61, 62, 64, 65, 66, 76, 77, 78, 70, 71, 72, 72, 0, 2, 2, 3, 5, 11, 13, 14, 16, 18, 19, 20, 22, 23, 27, 29, 30, 31, 33, 35, 35, 37, 38, 39, 40, 42, 44, 46, 48, 49, 51, 53, 56, 58, 59, 64, 66, 67, 70, 72, 2, 11, 14, 15, 15, 16, 19, 20, 23, 24, 27, 30, 31, 31, 35, 38, 43, 44, 48, 49, 53, 54, 54, 56, 59, 69, 70, 2, 11, 15, 19, 27, 31, 38, 42, 43, 48, 48, 49, 54, 54, 59, 60, 67, 68, 69, 69, 78, 79, 78, 69, 2, 11, 19, 20, 27, 38, 39, 39, 42, 48, 54, 60, 62, 64, 67, 69, 78, 2, 5, 11, 20, 24, 27, 39, 48, 48, 54, 62, 64, 69, 79, 76, 78, 5, 10, 11, 24, 48, 62, 63, 64, 79, 74, 76, 5, 6, 10, 24, 26, 27, 48, 63, 76, 6, 8, 27, 63, 64, 26, 27, 64, 10, 26, 64, 10, 64, 74, 75, 76, 8, 74, 9, 10]; 4 | testOutput["hole_touching_outer"]["pass"]=true; 5 | testOutput["hole_touching_outer"]["report"]="exp numtri:77\nexp dev:0.00000000000001\nact numtri:77\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/issue16.js: -------------------------------------------------------------------------------- 1 | testOutput["issue16"]=[]; 2 | testOutput["issue16"]["json"]=[[[143.12952728374512, 61.24016082659364], [147.39952728376375, 74.78016082663089], [154.04952728375793, 90.26016082707794], [174.42952728376258, 81.71016082633287], [168.0395272837486, 67.04016082640737], [159.09952728374628, 53.590160826221116]], [[156.8595272837556, 67.43016082700342], [157.48952728376025, 67.16016082651913], [159.96952728374163, 68.35016082692891], [161.33952728376607, 67.64016082696618], [159.64952728376375, 63.31016082689166], [155.7595272837498, 64.88016082625836]]]; 3 | testOutput["issue16"]["triangles"]=[0, 11, 6, 6, 7, 8, 10, 11, 0, 5, 4, 3, 3, 2, 1, 1, 0, 6, 10, 0, 5, 3, 1, 6, 9, 10, 5, 3, 6, 8, 9, 5, 3, 3, 8, 9]; 4 | testOutput["issue16"]["pass"]=true; 5 | testOutput["issue16"]["report"]="exp numtri:12\nexp dev:0.00000000000001\nact numtri:12\nact dev:0.00000000000000035318783557241835"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/issue17.js: -------------------------------------------------------------------------------- 1 | testOutput["issue17"]=[]; 2 | testOutput["issue17"]["json"]=[[[-20037508.34, 19971868.877628453], [-20037508.34, -19971868.877628453], [20037508.34, -19971868.877628453], [20037508.34, 19971868.877628453]], [[537637.6007702783, 5907542.234420554], [539500.1483225027, 5905165.501947839], [538610.3146341922, 5905217.430281373], [538040.6306361248, 5906132.0755739985], [538068.958329954, 5906571.138846622], [537711.0379352621, 5906645.06648362], [537629.886026485, 5907533.69114742]]]; 3 | testOutput["issue17"]["triangles"]=[0, 1, 10, 7, 8, 9, 9, 10, 1, 1, 2, 3, 0, 10, 4, 6, 7, 9, 3, 0, 4, 6, 9, 1, 3, 4, 5, 5, 6, 1, 1, 3, 5]; 4 | testOutput["issue17"]["pass"]=true; 5 | testOutput["issue17"]["report"]="exp numtri:11\nexp dev:0.00000000000001\nact numtri:11\nact dev:0.0000000000000001561771867280377"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/issue29.js: -------------------------------------------------------------------------------- 1 | testOutput["issue29"]=[]; 2 | testOutput["issue29"]["json"]=[[[200.9500005565411, 69.90565782485673], [201.73186418809928, 76.50881049432792], [204.05247248713857, 82.73234962527638], [207.79442497901616, 88.23839184455574], [212.7323883100471, 92.70045673093408], [218.5829607544292, 95.86217257360111], [225.00460918453172, 97.53918036725956], [231.6653444646392, 97.6608259321656], [238.15796607054656, 96.219733984099], [244.1176358256489, 93.27806596420706], [249.2188404462824, 88.99822680730722], [253.15628113771672, 83.64108043884043], [255.70631344406863, 77.51111824424007], [256.73126424155197, 70.93641692795792], [256.19351709797047, 64.30797780468129], [254.1057433114911, 57.996416078653425], [250.5643188096525, 52.346517799043795], [245.8112865351897, 47.719993951247304], [240.07834375849924, 44.33761266223155], [233.71343464441597, 42.419284673407674], [227.06488359675492, 42.055728640102465], [220.51757991796475, 43.257153422775446], [214.45449861431845, 45.97523169373744], [209.20995664413203, 50.053084840223896], [205.06721924245355, 55.271000209450726], [202.29122001552025, 61.30178454495035], [201.02451470680535, 67.8368895214051]], [[242.34999892718187, 69.90549289577612], [240.7584948063828, 76.30057721128688], [236.31611852571368, 81.17358751371503], [230.07699953842675, 83.34595728587593], [223.55761859836056, 82.33733346881347], [218.2910646148026, 78.34856240227819], [215.5668820463121, 72.34290095195175], [215.9904494531453, 65.75019118711353], [219.47497291108593, 60.1536534355022], [225.2189893186092, 56.88651757836341], [231.8100271829404, 56.72041164720431], [237.70269737243652, 59.67713584899902], [241.47838292121884, 65.0856644153595]]]; 3 | testOutput["issue29"]["triangles"]=[0, 33, 32, 34, 33, 0, 0, 26, 25, 25, 24, 23, 23, 22, 21, 21, 20, 19, 19, 18, 17, 17, 16, 15, 15, 14, 13, 13, 12, 11, 11, 10, 9, 9, 8, 7, 7, 6, 5, 5, 4, 3, 3, 2, 1, 1, 0, 32, 35, 34, 0, 0, 25, 23, 23, 21, 19, 19, 17, 15, 15, 13, 11, 11, 9, 7, 7, 5, 3, 3, 1, 32, 36, 35, 0, 0, 23, 19, 19, 15, 11, 11, 7, 3, 3, 32, 31, 36, 0, 19, 3, 31, 30, 37, 36, 19, 11, 3, 30, 38, 37, 19, 11, 30, 29, 39, 38, 19, 11, 29, 28, 39, 19, 11, 11, 28, 27, 27, 39, 11]; 4 | testOutput["issue29"]["pass"]=true; 5 | testOutput["issue29"]["report"]="exp numtri:40\nexp dev:0.00000000000001\nact numtri:40\nact dev:0.0000000000000003640306326849255"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/issue34.js: -------------------------------------------------------------------------------- 1 | testOutput["issue34"]=[]; 2 | testOutput["issue34"]["json"]=[[[1500.0, 0.0], [0.0, 0.0], [0.0, 1000.0], [1500.0, 1000.0], [1500.0, 0.0]], [[804.0, 642.0], [814.0, 644.0], [818.0, 676.0], [850.0, 690.0], [838.0, 728.0], [806.0, 728.0], [772.0, 752.0], [748.0, 746.0], [764.0, 724.0], [728.0, 726.0], [710.0, 708.0], [738.0, 656.0], [764.0, 668.0], [784.0, 700.0], [806.0, 702.0], [792.0, 666.0], [804.0, 642.0]], [[1176.0, 214.0], [1254.0, 216.0], [1292.0, 242.0], [1324.0, 242.0], [1332.0, 268.0], [1352.0, 278.0], [1352.0, 298.0], [1290.0, 348.0], [1290.0, 358.0], [1312.0, 350.0], [1314.0, 362.0], [1266.0, 416.0], [1240.0, 474.0], [1182.0, 500.0], [1200.0, 510.0], [1200.0, 520.0], [1186.0, 520.0], [1200.0, 544.0], [1186.0, 580.0], [1160.0, 584.0], [1162.0, 606.0], [1146.0, 620.0], [1162.0, 650.0], [1136.0, 672.0], [1124.0, 658.0], [1076.0, 668.0], [1022.0, 658.0], [1036.0, 698.0], [1066.0, 706.0], [1118.0, 688.0], [1144.0, 708.0], [1132.0, 746.0], [1064.0, 748.0], [1004.0, 740.0], [990.0, 668.0], [966.0, 670.0], [946.0, 648.0], [948.0, 632.0], [962.0, 628.0], [992.0, 650.0], [1016.0, 648.0], [1054.0, 622.0], [1044.0, 592.0], [1054.0, 584.0], [1078.0, 606.0], [1076.0, 576.0], [1052.0, 570.0], [1056.0, 540.0], [1038.0, 568.0], [1004.0, 570.0], [976.0, 526.0], [996.0, 502.0], [958.0, 496.0], [948.0, 454.0], [962.0, 454.0], [952.0, 436.0], [964.0, 390.0], [986.0, 382.0], [974.0, 368.0], [1004.0, 376.0], [1018.0, 420.0], [1052.0, 434.0], [1060.0, 482.0], [1078.0, 490.0], [1062.0, 472.0], [1062.0, 442.0], [1104.0, 450.0], [1104.0, 436.0], [1142.0, 422.0], [1154.0, 402.0], [1110.0, 424.0], [1046.0, 416.0], [1022.0, 388.0], [1022.0, 344.0], [1002.0, 344.0], [1018.0, 318.0], [1060.0, 308.0], [1076.0, 272.0], [1104.0, 288.0], [1122.0, 246.0], [1140.0, 230.0], [1168.0, 234.0], [1176.0, 214.0]], [[974.0, 698.0], [986.0, 738.0], [964.0, 740.0], [952.0, 714.0], [974.0, 698.0]], [[842.0, 596.0], [860.0, 626.0], [848.0, 622.0], [842.0, 596.0]], [[798.0, 572.0], [792.0, 606.0], [768.0, 614.0], [740.0, 580.0], [758.0, 586.0], [798.0, 572.0]], [[892.0, 584.0], [894.0, 594.0], [882.0, 588.0], [892.0, 584.0]], [[870.0, 500.0], [912.0, 538.0], [922.0, 586.0], [908.0, 590.0], [894.0, 568.0], [864.0, 564.0], [854.0, 550.0], [868.0, 538.0], [846.0, 520.0], [854.0, 500.0], [870.0, 500.0]]]; 3 | testOutput["issue34"]["triangles"]=[11, 10, 9, 9, 108, 107, 109, 108, 9, 8, 7, 6, 6, 58, 57, 57, 56, 55, 51, 50, 49, 49, 48, 47, 47, 46, 45, 44, 43, 42, 42, 41, 40, 39, 38, 37, 36, 35, 34, 34, 33, 32, 31, 30, 29, 27, 26, 25, 25, 24, 23, 104, 103, 102, 101, 100, 99, 99, 98, 97, 96, 95, 94, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 70, 69, 68, 68, 67, 66, 64, 63, 62, 62, 61, 60, 59, 58, 6, 20, 19, 18, 16, 15, 1, 1, 117, 116, 123, 122, 113, 113, 115, 119, 119, 118, 117, 117, 1, 132, 132, 131, 130, 129, 128, 127, 133, 132, 1, 2, 1, 15, 14, 13, 12, 11, 9, 107, 109, 9, 8, 8, 6, 57, 51, 49, 47, 44, 42, 40, 37, 36, 34, 31, 29, 28, 102, 101, 99, 92, 90, 89, 87, 86, 84, 71, 70, 68, 68, 66, 65, 64, 62, 60, 60, 59, 6, 20, 18, 17, 17, 16, 1, 116, 115, 113, 111, 113, 122, 123, 113, 119, 119, 117, 132, 134, 133, 1, 2, 15, 14, 109, 8, 57, 51, 47, 45, 44, 40, 39, 39, 37, 34, 32, 31, 28, 93, 92, 89, 87, 84, 83, 71, 68, 65, 65, 64, 60, 60, 6, 21, 21, 20, 17, 17, 1, 116, 116, 113, 112, 111, 122, 121, 119, 132, 130, 2, 14, 12, 106, 109, 57, 52, 51, 45, 44, 39, 34, 93, 89, 87, 87, 83, 81, 71, 65, 60, 21, 17, 116, 116, 112, 111, 119, 130, 129, 3, 2, 12, 106, 57, 55, 52, 45, 44, 44, 34, 32, 94, 93, 87, 72, 71, 60, 21, 116, 111, 123, 119, 129, 3, 12, 11, 107, 106, 55, 52, 44, 32, 94, 87, 81, 74, 72, 60, 60, 21, 111, 123, 129, 127, 3, 11, 107, 107, 55, 54, 53, 52, 32, 96, 94, 81, 75, 74, 60, 60, 111, 121, 121, 123, 127, 3, 107, 54, 53, 32, 28, 96, 81, 80, 60, 121, 127, 3, 54, 53, 97, 96, 80, 60, 127, 126, 4, 3, 53, 75, 60, 126, 4, 53, 28, 75, 126, 125, 4, 28, 27, 77, 75, 125, 4, 27, 25, 78, 77, 125, 4, 25, 23, 78, 125, 134, 1, 4, 23, 80, 78, 134, 1, 23, 104, 80, 134, 1, 1, 104, 102, 97, 80, 1, 1, 102, 99, 99, 97, 1]; 4 | testOutput["issue34"]["pass"]=true; 5 | testOutput["issue34"]["report"]="exp numtri:139\nexp dev:0.00000000000001\nact numtri:139\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/issue45.js: -------------------------------------------------------------------------------- 1 | testOutput["issue45"]=[]; 2 | testOutput["issue45"]["json"]=[[[10.0, 10.0], [25.0, 10.0], [25.0, 40.0], [10.0, 40.0]], [[15.0, 30.0], [20.0, 35.0], [10.0, 40.0]], [[15.0, 15.0], [15.0, 20.0], [20.0, 15.0]]]; 3 | testOutput["issue45"]["triangles"]=[2, 6, 5, 4, 3, 0, 0, 7, 8, 9, 7, 0, 1, 2, 5, 5, 4, 0, 9, 0, 1, 5, 0, 8, 9, 1, 5, 5, 8, 9]; 4 | testOutput["issue45"]["pass"]=true; 5 | testOutput["issue45"]["report"]="exp numtri:10\nexp dev:0.00000000000001\nact numtri:10\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/issue52.js: -------------------------------------------------------------------------------- 1 | testOutput["issue52"]=[]; 2 | testOutput["issue52"]["json"]=[[[1920.0, 552.0], [1904.0, 616.0], [1912.0, 664.0], [1984.0, 672.0], [2008.0, 712.0], [1944.0, 720.0], [1904.0, 760.0], [1896.0, 800.0], [1856.0, 760.0], [1824.0, 768.0], [1824.0, 832.0], [1864.0, 864.0], [1888.0, 864.0], [1904.0, 936.0], [1936.0, 944.0], [1936.0, 1064.0], [1936.0, 1112.0], [1872.0, 1136.0], [1856.0, 1160.0], [1840.0, 1144.0], [1792.0, 1152.0], [1784.0, 1112.0], [1752.0, 1096.0], [1608.0, 1096.0], [1600.0, 1064.0], [1640.0, 1040.0], [1664.0, 992.0], [1640.0, 968.0], [1568.0, 1024.0], [1560.0, 1056.0], [1480.0, 1048.0], [1440.0, 1072.0], [1440.0, 1032.0], [1400.0, 1032.0], [1400.0, 1088.0], [1336.0, 1136.0], [1320.0, 1136.0], [1264.0, 1072.0], [1232.0, 1080.0], [1240.0, 1104.0], [1200.0, 1096.0], [1232.0, 1048.0], [1272.0, 1032.0], [1272.0, 1000.0], [1232.0, 1024.0], [1176.0, 1024.0], [1176.0, 1000.0], [1248.0, 952.0], [1344.0, 944.0], [1352.0, 904.0], [1424.0, 880.0], [1448.0, 848.0], [1496.0, 840.0], [1512.0, 800.0], [1568.0, 760.0], [1616.0, 752.0], [1640.0, 640.0], [1680.0, 600.0], [1736.0, 592.0], [1776.0, 560.0], [1776.0, 536.0], [1840.0, 464.0], [1848.0, 400.0], [1888.0, 328.0], [1952.0, 264.0], [2000.0, 240.0], [2040.0, 240.0], [2040.0, 264.0], [1968.0, 376.0], [1912.0, 424.0], [1936.0, 512.0], [1920.0, 528.0], [1880.0, 528.0], [1872.0, 552.0], [1920.0, 552.0]], [[1608.0, 800.0], [1576.0, 848.0], [1520.0, 840.0], [1512.0, 872.0], [1456.0, 904.0], [1440.0, 952.0], [1528.0, 936.0], [1552.0, 912.0], [1584.0, 912.0], [1608.0, 880.0], [1664.0, 864.0], [1680.0, 816.0], [1656.0, 776.0], [1608.0, 800.0]], [[1720.0, 792.0], [1736.0, 792.0], [1720.0, 780.0], [1720.0, 792.0]], [[1656.0, 728.0], [1670.0, 752.0], [1672.0, 728.0], [1656.0, 728.0]], [[1712.0, 680.0], [1696.0, 720.0], [1720.0, 728.0], [1736.0, 704.0], [1736.0, 680.0], [1712.0, 680.0]], [[1968.0, 712.0], [2000.0, 712.0], [1968.0, 688.0], [1968.0, 712.0]]]; 3 | testOutput["issue52"]["triangles"]=[6, 7, 8, 11, 12, 13, 13, 14, 15, 15, 16, 17, 17, 18, 19, 19, 20, 21, 22, 23, 24, 28, 29, 30, 30, 31, 32, 33, 34, 35, 35, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 81, 82, 83, 83, 84, 85, 75, 76, 77, 77, 78, 79, 48, 49, 50, 50, 51, 52, 52, 53, 54, 99, 103, 104, 97, 98, 93, 56, 57, 58, 59, 60, 61, 61, 62, 63, 63, 64, 65, 65, 66, 67, 67, 68, 69, 69, 70, 71, 73, 0, 1, 5, 6, 8, 10, 11, 13, 13, 15, 17, 17, 19, 21, 22, 24, 25, 27, 28, 30, 33, 35, 37, 38, 40, 42, 43, 45, 47, 87, 75, 77, 48, 50, 52, 52, 54, 55, 55, 93, 94, 95, 93, 98, 97, 93, 55, 55, 56, 58, 61, 63, 65, 65, 67, 69, 69, 71, 72, 73, 1, 2, 5, 8, 9, 10, 13, 17, 17, 21, 22, 22, 25, 26, 27, 30, 32, 33, 37, 38, 43, 47, 80, 80, 47, 48, 52, 55, 94, 94, 95, 98, 97, 55, 58, 59, 61, 65, 69, 72, 73, 10, 17, 22, 27, 32, 33, 33, 38, 42, 42, 43, 80, 79, 80, 48, 94, 98, 99, 105, 103, 99, 101, 97, 58, 59, 65, 69, 9, 10, 22, 27, 33, 42, 42, 80, 81, 77, 79, 48, 52, 94, 99, 105, 99, 100, 101, 58, 59, 59, 69, 73, 9, 22, 26, 27, 42, 81, 77, 48, 52, 105, 100, 101, 101, 59, 73, 9, 26, 27, 27, 81, 83, 87, 77, 52, 101, 73, 2, 27, 83, 85, 87, 52, 99, 105, 101, 2, 9, 27, 85, 86, 87, 89, 91, 89, 87, 105, 2, 3, 9, 85, 86, 86, 89, 90, 91, 87, 99, 104, 105, 3, 5, 9, 86, 90, 91, 99, 104, 3, 4, 5, 86, 90, 99, 104, 4, 5, 90, 99, 99, 4, 5]; 4 | testOutput["issue52"]["pass"]=true; 5 | testOutput["issue52"]["report"]="exp numtri:109\nexp dev:0.00000000000001\nact numtri:109\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/issue83.js: -------------------------------------------------------------------------------- 1 | testOutput["issue83"]=[]; 2 | testOutput["issue83"]["json"]=[[[0.0, 0.0], [4000.0, 0.0], [4000.0, 4000.0], [0.0, 4000.0]], [[0.0, 0.0], [4000.0, 0.0], [4000.0, 4000.0], [0.0, 4000.0]], [[-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0], [-1.0, -1.0]]]; 3 | testOutput["issue83"]["triangles"]=[]; 4 | testOutput["issue83"]["pass"]=true; 5 | testOutput["issue83"]["report"]="exp numtri:0\nexp dev:0.00000000000001\nact numtri:0\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/outside_ring.js: -------------------------------------------------------------------------------- 1 | testOutput["outside_ring"]=[]; 2 | testOutput["outside_ring"]["json"]=[[[2181.0, 1228.0], [2182.0, 1231.0], [2178.0, 1231.0], [2180.0, 1228.0], [2175.0, 1225.0], [2174.0, 1212.0], [2182.0, 1210.0], [2182.0, 1193.0], [2190.0, 1187.0], [2187.0, 1166.0], [2194.0, 1158.0], [2186.0, 1149.0], [2186.0, 1103.0], [2195.0, 1091.0], [2207.0, 1092.0], [2209.0, 1080.0], [2203.0, 1077.0], [2213.0, 1057.0], [2213.0, 1035.0], [2224.0, 1031.0], [2238.0, 983.0], [2251.0, 982.0], [2254.0, 965.0], [2275.0, 970.0], [2277.0, 948.0], [2317.0, 982.0], [2317.0, 1030.0], [2323.0, 1044.0], [2306.0, 1041.0], [2303.0, 1051.0], [2290.0, 1057.0], [2294.0, 1062.0], [2287.0, 1071.0], [2294.0, 1081.0], [2255.0, 1123.0], [2249.0, 1118.0], [2253.0, 1128.0], [2245.0, 1131.0], [2249.0, 1137.0], [2243.0, 1168.0], [2265.0, 1195.0], [2253.0, 1203.0], [2260.0, 1204.0], [2252.0, 1215.0], [2249.0, 1208.0], [2245.0, 1217.0], [2232.0, 1220.0], [2241.0, 1223.0], [2235.0, 1223.0], [2238.0, 1245.0], [2229.0, 1274.0], [2215.0, 1272.0], [2209.0, 1288.0], [2196.0, 1288.0], [2190.0, 1269.0], [2194.0, 1271.0], [2195.0, 1262.0], [2181.0, 1240.0], [2182.0, 1233.0], [2183.0, 1229.0], [2181.0, 1228.0]], [[2181.0, 1228.0], [2181.0, 1227.0], [2180.0, 1228.0], [2181.0, 1228.0]], [[2246.0, 1197.0], [2230.0, 1201.0], [2251.0, 1203.0], [2246.0, 1197.0]]]; 3 | testOutput["outside_ring"]["triangles"]=[1, 2, 63, 62, 3, 4, 4, 5, 6, 6, 7, 66, 65, 66, 7, 8, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 17, 18, 19, 19, 20, 21, 21, 22, 23, 23, 24, 25, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34, 35, 36, 37, 37, 38, 39, 39, 40, 41, 41, 42, 43, 44, 45, 46, 46, 47, 48, 48, 49, 50, 51, 52, 53, 53, 54, 55, 56, 57, 58, 62, 4, 6, 6, 66, 67, 65, 7, 8, 10, 12, 14, 14, 15, 17, 17, 19, 21, 21, 23, 25, 25, 26, 28, 30, 32, 34, 41, 43, 44, 46, 48, 50, 51, 53, 55, 56, 58, 59, 62, 6, 67, 65, 8, 10, 14, 17, 21, 21, 25, 28, 30, 34, 35, 41, 44, 46, 46, 50, 51, 51, 55, 56, 65, 10, 14, 14, 21, 28, 46, 51, 56, 67, 65, 14, 14, 28, 30, 46, 56, 59, 14, 30, 35, 41, 46, 59, 14, 35, 37, 14, 37, 39, 67, 14, 39, 67, 39, 41, 62, 67, 41, 62, 41, 59, 62, 59, 61, 63, 0, 1]; 4 | testOutput["outside_ring"]["pass"]=true; 5 | testOutput["outside_ring"]["report"]="exp numtri:64\nexp dev:0.00000000000001\nact numtri:64\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/self_touching.js: -------------------------------------------------------------------------------- 1 | testOutput["self_touching"]=[]; 2 | testOutput["self_touching"]["json"]=[[[160.40671875, 11.3976701817587], [160.396875, 11.3935345987524], [160.39828125, 11.4018057045896], [160.39265625, 11.4004272036667], [160.38984375, 11.3811274888866], [160.3940625, 11.3838846711709], [160.3771875, 11.3521754635814], [160.33921875, 11.3590690696413], [160.35046875, 11.3645838345287], [160.3575, 11.3645838345287], [160.3575, 11.3756130442004], [160.29421875, 11.3507967223837], [160.2928125, 11.3480392200086], [160.28859375, 11.3480392200086], [160.295625, 11.3287359579628], [160.26328125, 11.3080524456288], [160.295625, 11.1866791818427], [160.31671875, 11.1811610026871], [160.318125, 11.1770222993774], [160.31390625, 11.1687447155658], [160.3125, 11.1494294353899], [160.2703125, 11.1107950268865], [160.2421875, 11.1149346728405], [160.23796875, 11.0997556838987], [160.25625, 11.095615822671], [160.21828125, 11.0735355725517], [160.21546875, 11.0652550492086], [160.2084375, 11.0762956949617], [160.20140625, 11.0638749392263], [160.19015625, 11.0528338254202], [160.18453125, 11.0528338254202], [160.183125, 11.0486933005675], [160.24640625, 11.0583544343014], [160.26890625, 11.0555941428523], [160.250625, 11.0804358297701], [160.28015625, 11.0942358558913], [160.295625, 11.0845759059922], [160.2928125, 11.0721555015877], [160.318125, 11.0790557913426], [160.31953125, 11.0942358558913], [160.33359375, 11.1038954864431], [160.34484375, 11.0900959164515], [160.35609375, 11.1038954864431], [160.363125, 11.0969957829326], [160.36453125, 11.1052754075802], [160.36171875, 11.1121749153987], [160.37578125, 11.1149346728405], [160.39828125, 11.1080352302834], [160.36734375, 11.1756427184796], [160.48125, 11.1852996469051], [160.48546875, 11.1825405573266], [160.5121875, 11.1852996469051], [160.5459375, 11.1342522433585], [160.56421875, 11.1301128717933], [160.55578125, 11.1204541093718], [160.56140625, 11.1135547973836], [160.588125, 11.1314926688534], [160.62328125, 11.1121749153987], [160.633125, 11.1135547973836], [160.6471875, 11.1025155587833], [160.64296875, 11.1176944041669], [160.63734375, 11.1190742600349], [160.62328125, 11.1342522433585], [160.62046875, 11.128733068196], [160.6078125, 11.1480497233847], [160.61203125, 11.1480497233847], [160.6134375, 11.1563278971795], [160.5909375, 11.1425308098987], [160.576875, 11.1480497233847], [160.57125, 11.1549482179223], [160.57125, 11.1494294353899], [160.57828125, 11.1452902797332], [160.57265625, 11.1425308098987], [160.57125, 11.1494294353899], [160.54875, 11.1577075698847], [160.554375, 11.179781441482], [160.54875, 11.1770222993774], [160.5628125, 11.2087508469621], [160.5234375, 11.2059919808933], [160.52203125, 11.2032330885061], [160.50515625, 11.2184066708578], [160.49390625, 11.2032330885061], [160.46296875, 11.2046125379891], [160.46296875, 11.201853632445], [160.4165625, 11.2115096867066], [160.41796875, 11.2211654184183], [160.39546875, 11.2266828344767], [160.35609375, 11.2225447823168], [160.35328125, 11.2363380587922], [160.3659375, 11.2473722050633], [160.351875, 11.2915045605453], [160.32375, 11.2721974885629], [160.32234375, 11.2846093266964], [160.35328125, 11.3080524456288], [160.351875, 11.3149471157772], [160.3659375, 11.3204627323768], [160.36171875, 11.2997786224589], [160.3828125, 11.3011576095711], [160.37859375, 11.3080524456288], [160.38140625, 11.3094313929343], [160.3828125, 11.3011576095711], [160.408125, 11.3039155638972], [160.408125, 11.2997786224589], [160.425, 11.3094313929343], [160.41234375, 11.3411453475587], [160.3996875, 11.3301148056307], [160.40953125, 11.3700984927314], [160.39265625, 11.3618264654176], [160.396875, 11.3797488877286], [160.4053125, 11.3893989555911], [160.40953125, 11.3866418267411], [160.419375, 11.4004272036667], [160.41515625, 11.4059411672242], [160.419375, 11.4114550237293], [160.425, 11.412833471123], [160.42359375, 11.422482415387], [160.40671875, 11.3976701817587]], [[160.363125, 11.1425308098987], [160.3603125, 11.1383915560672], [160.3603125, 11.1439105480884], [160.363125, 11.1425308098987]], [[160.35046875, 11.1397713138873], [160.34625, 11.1383915560672], [160.34203125, 11.1480497233847], [160.35046875, 11.1397713138873]]]; 3 | testOutput["self_touching"]["triangles"]=[1, 2, 3, 3, 4, 5, 8, 9, 10, 10, 11, 12, 12, 13, 14, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 40, 41, 42, 42, 43, 44, 46, 47, 48, 49, 50, 51, 51, 52, 53, 53, 54, 55, 56, 57, 58, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 72, 73, 74, 74, 75, 76, 76, 77, 78, 79, 80, 81, 81, 82, 83, 84, 85, 86, 88, 89, 90, 92, 93, 94, 95, 96, 97, 99, 100, 101, 101, 102, 103, 103, 104, 105, 105, 106, 107, 109, 110, 111, 113, 114, 115, 1, 3, 5, 7, 8, 10, 10, 12, 14, 14, 16, 17, 21, 23, 24, 26, 28, 29, 29, 31, 32, 35, 36, 38, 40, 42, 44, 45, 46, 48, 53, 55, 56, 58, 60, 61, 64, 66, 67, 67, 68, 70, 74, 76, 78, 79, 81, 83, 84, 86, 87, 88, 90, 91, 95, 97, 98, 99, 101, 103, 109, 111, 112, 112, 113, 115, 0, 1, 5, 7, 10, 14, 14, 17, 18, 20, 21, 123, 26, 29, 32, 35, 38, 39, 40, 44, 45, 56, 58, 61, 63, 64, 67, 67, 70, 71, 74, 78, 79, 83, 84, 87, 87, 88, 91, 95, 98, 99, 99, 103, 105, 108, 109, 112, 112, 115, 0, 0, 5, 6, 6, 7, 14, 18, 20, 123, 122, 123, 21, 26, 32, 34, 35, 39, 40, 56, 61, 63, 63, 67, 71, 95, 99, 105, 108, 112, 0, 14, 18, 123, 118, 122, 21, 24, 26, 34, 35, 40, 45, 56, 63, 71, 95, 105, 107, 108, 0, 6, 14, 123, 121, 118, 21, 24, 24, 34, 35, 53, 56, 71, 94, 95, 107, 107, 108, 6, 118, 24, 35, 53, 71, 72, 92, 94, 107, 118, 35, 45, 53, 72, 74, 92, 107, 6, 121, 122, 118, 117, 118, 45, 51, 53, 74, 92, 6, 14, 14, 121, 118, 117, 45, 48, 51, 74, 79, 91, 92, 14, 14, 118, 119, 119, 117, 48, 49, 51, 79, 91, 14, 119, 48, 49, 79, 87, 91, 119, 48, 79, 83, 87, 119, 48, 48, 83, 87]; 4 | testOutput["self_touching"]["pass"]=true; 5 | testOutput["self_touching"]["report"]="exp numtri:124\nexp dev:0.000000000000034\nact numtri:124\nact dev:0.00000000000003355590533513436"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/shared_points.js: -------------------------------------------------------------------------------- 1 | testOutput["shared_points"]=[]; 2 | testOutput["shared_points"]["json"]=[[[4136.0, 1016.0], [4112.0, 1016.0], [4104.0, 976.0], [4136.0, 1016.0], [4144.0, 984.0], [4104.0, 976.0], [4144.0, 968.0], [4144.0, 984.0], [4168.0, 992.0], [4152.0, 1064.0]]]; 3 | testOutput["shared_points"]["triangles"]=[8, 9, 7, 7, 5, 6, 0, 1, 2, 9, 3, 4]; 4 | testOutput["shared_points"]["pass"]=true; 5 | testOutput["shared_points"]["report"]="exp numtri:4\nexp dev:0.00000000000001\nact numtri:4\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/simplified_us_border.js: -------------------------------------------------------------------------------- 1 | testOutput["simplified_us_border"]=[]; 2 | testOutput["simplified_us_border"]["json"]=[[[1130.0, 1713.0], [1131.0, 1710.0], [1137.0, 1731.0], [1133.0, 1752.0], [1125.0, 1753.0], [1118.0, 1742.0], [1110.0, 1717.0], [1105.0, 1718.0], [1108.0, 1704.0], [1096.0, 1691.0], [1077.0, 1694.0], [1067.0, 1683.0], [1019.0, 1687.0], [1031.0, 1689.0], [1031.0, 1704.0], [1022.0, 1696.0], [1022.0, 1702.0], [1010.0, 1700.0], [1003.0, 1692.0], [998.0, 1696.0], [980.0, 1690.0], [970.0, 1698.0], [966.0, 1694.0], [966.0, 1702.0], [938.0, 1718.0], [943.0, 1742.0], [920.0, 1736.0], [916.0, 1721.0], [894.0, 1693.0], [884.0, 1691.0], [872.0, 1703.0], [837.0, 1667.0], [785.0, 1672.0], [743.0, 1654.0], [715.0, 1656.0], [699.0, 1636.0], [676.0, 1628.0], [654.0, 1587.0], [656.0, 1583.0], [660.0, 1588.0], [657.0, 1579.0], [649.0, 1580.0], [633.0, 1547.0], [637.0, 1529.0], [631.0, 1507.0], [638.0, 1454.0], [647.0, 1454.0], [637.0, 1452.0], [639.0, 1441.0], [635.0, 1442.0], [629.0, 1417.0], [651.0, 1421.0], [647.0, 1434.0], [655.0, 1428.0], [650.0, 1440.0], [656.0, 1434.0], [654.0, 1423.0], [651.0, 1420.0], [653.0, 1419.0], [651.0, 1407.0], [965.0, 1407.0], [966.0, 1400.0], [972.0, 1411.0], [1008.0, 1423.0], [1043.0, 1419.0], [1083.0, 1442.0], [1086.0, 1450.0], [1091.0, 1448.0], [1109.0, 1468.0], [1114.0, 1496.0], [1102.0, 1520.0], [1107.0, 1525.0], [1149.0, 1508.0], [1147.0, 1498.0], [1152.0, 1495.0], [1174.0, 1495.0], [1195.0, 1474.0], [1242.0, 1470.0], [1260.0, 1433.0], [1277.0, 1440.0], [1277.0, 1462.0], [1286.0, 1476.0], [1274.0, 1484.0], [1265.0, 1480.0], [1243.0, 1503.0], [1240.0, 1516.0], [1252.0, 1526.0], [1238.0, 1529.0], [1236.0, 1523.0], [1234.0, 1530.0], [1218.0, 1531.0], [1206.0, 1540.0], [1205.0, 1554.0], [1195.0, 1567.0], [1188.0, 1556.0], [1194.0, 1574.0], [1185.0, 1590.0], [1187.0, 1581.0], [1179.0, 1567.0], [1185.0, 1557.0], [1176.0, 1562.0], [1180.0, 1579.0], [1179.0, 1585.0], [1170.0, 1577.0], [1180.0, 1593.0], [1169.0, 1590.0], [1183.0, 1596.0], [1186.0, 1607.0], [1175.0, 1605.0], [1183.0, 1613.0], [1182.0, 1618.0], [1171.0, 1615.0], [1179.0, 1624.0], [1167.0, 1626.0], [1145.0, 1650.0], [1132.0, 1659.0], [1128.0, 1656.0], [1121.0, 1675.0], [1131.0, 1708.0], [1129.0, 1710.0], [1130.0, 1713.0]], [[654.0, 1419.0], [653.0, 1419.0], [654.0, 1423.0], [656.0, 1425.0], [654.0, 1419.0]]]; 3 | testOutput["simplified_us_border"]["triangles"]=[0, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 20, 21, 22, 22, 23, 24, 24, 25, 26, 29, 30, 31, 31, 32, 33, 33, 34, 35, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 49, 50, 50, 51, 52, 52, 53, 54, 121, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 68, 69, 70, 72, 73, 74, 75, 76, 77, 77, 78, 79, 80, 81, 82, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 96, 97, 97, 98, 99, 100, 101, 102, 103, 104, 105, 105, 106, 107, 108, 109, 110, 111, 112, 113, 113, 114, 115, 117, 118, 119, 0, 2, 4, 4, 6, 8, 12, 14, 15, 15, 17, 18, 24, 26, 27, 28, 29, 31, 31, 33, 35, 35, 37, 39, 40, 42, 43, 43, 45, 46, 46, 48, 50, 50, 52, 54, 124, 121, 59, 59, 60, 62, 63, 65, 66, 66, 68, 70, 72, 74, 75, 77, 79, 80, 80, 82, 83, 85, 87, 88, 91, 93, 94, 94, 95, 97, 100, 102, 103, 105, 107, 108, 108, 110, 111, 111, 113, 115, 119, 0, 4, 12, 15, 18, 22, 24, 27, 31, 35, 39, 40, 43, 46, 46, 50, 54, 124, 59, 62, 62, 63, 66, 72, 75, 77, 77, 80, 83, 84, 85, 88, 94, 97, 99, 105, 108, 111, 111, 115, 116, 117, 119, 4, 12, 18, 20, 22, 27, 28, 31, 39, 40, 40, 46, 54, 124, 62, 66, 72, 77, 83, 84, 88, 90, 91, 94, 99, 105, 111, 116, 117, 4, 8, 11, 12, 20, 20, 22, 28, 28, 31, 40, 40, 54, 55, 124, 66, 70, 71, 72, 83, 84, 90, 91, 91, 99, 100, 103, 105, 116, 116, 117, 8, 11, 20, 28, 28, 40, 55, 124, 70, 71, 71, 83, 84, 84, 91, 100, 100, 103, 116, 116, 8, 9, 11, 28, 55, 71, 84, 100, 100, 116, 9, 9, 11, 55, 124, 71, 100, 100, 9, 55, 124, 100, 55, 124, 55, 123, 123, 57, 122]; 4 | testOutput["simplified_us_border"]["pass"]=true; 5 | testOutput["simplified_us_border"]["report"]="exp numtri:120\nexp dev:0.00000000000001\nact numtri:120\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/steiner.js: -------------------------------------------------------------------------------- 1 | testOutput["steiner"]=[]; 2 | testOutput["steiner"]["json"]=[[[0.0, 0.0], [100.0, 0.0], [100.0, 100.0], [0.0, 100.0]], [[50.0, 50.0]], [[30.0, 40.0]], [[70.0, 60.0]], [[20.0, 70.0]]]; 3 | testOutput["steiner"]["triangles"]=[3, 0, 7, 7, 0, 5, 5, 0, 1, 2, 3, 7, 7, 5, 4, 6, 5, 1, 2, 7, 4, 6, 1, 2, 2, 4, 6]; 4 | testOutput["steiner"]["pass"]=true; 5 | testOutput["steiner"]["report"]="exp numtri:9\nexp dev:0.00000000000001\nact numtri:9\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/touching_holes.js: -------------------------------------------------------------------------------- 1 | testOutput["touching_holes"]=[]; 2 | testOutput["touching_holes"]["json"]=[[[3694.0, 2061.0], [3794.0, 2035.0], [3812.0, 2123.0], [3784.0, 2123.0], [3708.0, 2139.0], [3694.0, 2061.0]], [[3752.0, 2109.0], [3740.0, 2102.0], [3712.0, 2109.0], [3715.0, 2125.0], [3723.0, 2128.0], [3740.0, 2124.0], [3742.0, 2112.0], [3752.0, 2109.0]], [[3797.0, 2101.0], [3787.0, 2096.0], [3780.0, 2106.0], [3788.0, 2114.0], [3797.0, 2101.0]], [[3734.0, 2099.0], [3732.0, 2091.0], [3719.0, 2094.0], [3721.0, 2102.0], [3734.0, 2099.0]], [[3777.0, 2082.0], [3774.0, 2071.0], [3772.0, 2086.0], [3765.0, 2091.0], [3748.0, 2088.0], [3749.0, 2062.0], [3738.0, 2081.0], [3745.0, 2095.0], [3761.0, 2099.0], [3777.0, 2082.0]], [[3719.0, 2079.0], [3712.0, 2079.0], [3706.0, 2091.0], [3712.0, 2097.0], [3721.0, 2080.0], [3719.0, 2079.0]], [[3773.0, 2067.0], [3761.0, 2053.0], [3753.0, 2061.0], [3753.0, 2071.0], [3756.0, 2075.0], [3773.0, 2067.0]], [[3708.0, 2079.0], [3712.0, 2079.0], [3714.0, 2076.0], [3719.0, 2079.0], [3722.0, 2079.0], [3718.0, 2088.0], [3723.0, 2089.0], [3734.0, 2075.0], [3730.0, 2068.0], [3717.0, 2065.0], [3708.0, 2079.0]]]; 3 | testOutput["touching_holes"]["triangles"]=[25, 26, 27, 41, 42, 0, 4, 0, 8, 11, 12, 6, 15, 16, 7, 8, 0, 36, 36, 0, 46, 25, 27, 28, 55, 46, 0, 41, 0, 1, 4, 8, 9, 8, 36, 37, 55, 0, 42, 40, 41, 1, 4, 9, 10, 3, 4, 10, 3, 10, 11, 3, 11, 6, 2, 3, 6, 17, 2, 6, 6, 7, 17, 2, 17, 14, 1, 2, 14, 40, 1, 14, 40, 14, 15, 7, 22, 19, 7, 19, 20, 21, 51, 52, 29, 30, 52, 20, 21, 52, 29, 52, 53, 20, 52, 30, 29, 53, 54, 7, 20, 30, 29, 54, 55, 7, 30, 31, 29, 55, 42, 7, 31, 32, 28, 29, 42, 15, 7, 32, 28, 42, 43, 15, 32, 24, 28, 43, 44, 40, 15, 24, 25, 28, 44, 40, 24, 25, 25, 44, 40, 51, 21, 37, 50, 51, 37, 50, 37, 38, 47, 48, 34, 38, 49, 50, 46, 35, 36, 22, 7, 8, 8, 37, 21, 21, 22, 8, 17, 7, 16]; 4 | testOutput["touching_holes"]["pass"]=true; 5 | testOutput["touching_holes"]["report"]="exp numtri:57\nexp dev:0.00000000000001\nact numtri:57\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/water3.js: -------------------------------------------------------------------------------- 1 | testOutput["water3"]=[]; 2 | testOutput["water3"]["json"]=[[[-128.0, 4224.0], [-128.0, -128.0], [4224.0, -128.0], [4224.0, 4224.0], [-128.0, 4224.0]], [[3030.0, -21.0], [3019.0, 7.0], [3025.0, 21.0], [3045.0, 65.0], [3054.0, 114.0], [3041.0, 189.0], [3000.0, 219.0], [3017.0, 257.0], [2966.0, 338.0], [2938.0, 340.0], [2934.0, 541.0], [2973.0, 618.0], [2979.0, 752.0], [3026.0, 803.0], [3052.0, 938.0], [3083.0, 1030.0], [3034.0, 1175.0], [3041.0, 1264.0], [3083.0, 1311.0], [3088.0, 1348.0], [3067.0, 1399.0], [3139.0, 1435.0], [3209.0, 1412.0], [3220.0, 1378.0], [3242.0, 1316.0], [3276.0, 1335.0], [3314.0, 1367.0], [3369.0, 1529.0], [3436.0, 1563.0], [3464.0, 1681.0], [3512.0, 1732.0], [3521.0, 1811.0], [3508.0, 1883.0], [3591.0, 1939.0], [3724.0, 2088.0], [3828.0, 2171.0], [3867.0, 2238.0], [3905.0, 2344.0], [3939.0, 2443.0], [3892.0, 2498.0], [3889.0, 2521.0], [3884.0, 2560.0], [3942.0, 2624.0], [3986.0, 2681.0], [3999.0, 2831.0], [4089.0, 3008.0], [4117.0, 3130.0], [4104.0, 3172.0], [4023.0, 3205.0], [3969.0, 3283.0], [3991.0, 3347.0], [4091.0, 3365.0], [4146.0, 3411.0], [4136.0, 3456.0], [4068.0, 3467.0], [3999.0, 3412.0], [3978.0, 3373.0], [3935.0, 3350.0], [3937.0, 3401.0], [4001.0, 3465.0], [4036.0, 3503.0], [3941.0, 3459.0], [3907.0, 3533.0], [3939.0, 3655.0], [3867.0, 3574.0], [3867.0, 3663.0], [3796.0, 3614.0], [3773.0, 3730.0], [3880.0, 4118.0], [3854.0, 4159.0], [3891.0, 4224.0], [4084.0, 4224.0], [4106.0, 4103.0], [4213.0, 4062.0], [4224.0, 4060.0], [4224.0, 2439.0], [4155.0, 2244.0], [4020.0, 2282.0], [3978.0, 2233.0], [3976.0, 2146.0], [3927.0, 2103.0], [3937.0, 2060.0], [3910.0, 1930.0], [3933.0, 1862.0], [3893.0, 1781.0], [3850.0, 1774.0], [3803.0, 1712.0], [3824.0, 1651.0], [3794.0, 1572.0], [3820.0, 1535.0], [3835.0, 1493.0], [3920.0, 1550.0], [3957.0, 1520.0], [3948.0, 1444.0], [3973.0, 1459.0], [3982.0, 1508.0], [4016.0, 1520.0], [4012.0, 1471.0], [4042.0, 1426.0], [4068.0, 1422.0], [4198.0, 1390.0], [4224.0, 1368.0], [4224.0, 969.0], [4214.0, 1019.0], [4177.0, 1095.0], [4142.0, 1070.0], [4176.0, 978.0], [4202.0, 843.0], [4213.0, 653.0], [4181.0, 656.0], [4181.0, 804.0], [4155.0, 796.0], [4138.0, 673.0], [4114.0, 600.0], [4050.0, 622.0], [4050.0, 573.0], [4100.0, 551.0], [4050.0, 379.0], [4015.0, 274.0], [3986.0, 208.0], [3972.0, 175.0], [3965.0, 158.0], [3953.0, 131.0], [3921.0, 99.0], [3885.0, 60.0], [3853.0, 29.0], [3807.0, -4.0], [3755.0, -27.0], [3692.0, -53.0], [3639.0, -58.0], [3595.0, -34.0], [3573.0, -11.0], [3519.0, -4.0], [3488.0, 17.0], [3467.0, 6.0], [3426.0, 4.0], [3384.0, 25.0], [3308.0, 28.0], [3263.0, -93.0], [3126.0, -83.0], [3041.0, -46.0], [3030.0, -21.0], [3030.0, -21.0]], [[3832.0, -21.0], [3840.0, -17.0], [3877.0, 21.0], [3895.0, 39.0], [3961.0, -21.0], [3893.0, -98.0], [3855.0, -128.0], [3688.0, -128.0], [3742.0, -81.0], [3793.0, -41.0], [3832.0, -21.0], [3832.0, -21.0]], [[4205.0, 596.0], [4224.0, 572.0], [4224.0, 248.0], [4166.0, 163.0], [4119.0, 50.0], [4020.0, 36.0], [4004.0, 21.0], [3969.0, 21.0], [3936.0, 62.0], [3982.0, 117.0], [4088.0, 293.0], [4152.0, 419.0], [4185.0, 544.0], [4205.0, 596.0], [4205.0, 596.0]], [[3228.0, 2459.0], [3243.0, 2459.0], [3248.0, 2434.0], [3273.0, 2429.0], [3218.0, 2186.0], [3255.0, 2102.0], [3285.0, 2094.0], [3314.0, 1972.0], [3198.0, 1969.0], [3192.0, 1943.0], [3223.0, 1943.0], [3222.0, 1913.0], [3177.0, 1928.0], [3187.0, 1979.0], [3180.0, 2171.0], [3134.0, 2187.0], [3212.0, 2399.0], [3243.0, 2398.0], [3228.0, 2459.0], [3228.0, 2459.0]], [[4224.0, 1574.0], [4212.0, 1572.0], [4175.0, 1600.0], [4152.0, 1647.0], [4131.0, 1689.0], [4106.0, 1736.0], [4101.0, 1785.0], [4115.0, 1851.0], [4149.0, 1885.0], [4169.0, 1920.0], [4204.0, 1908.0], [4224.0, 1875.0], [4214.0, 1844.0], [4199.0, 1798.0], [4215.0, 1763.0], [4224.0, 1767.0], [4224.0, 1574.0]]]; 3 | testOutput["water3"]["triangles"]=[176, 177, 178, 178, 179, 180, 182, 183, 184, 187, 188, 189, 189, 190, 1, 1, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 27, 28, 29, 29, 30, 31, 32, 33, 34, 34, 35, 36, 37, 38, 39, 39, 40, 41, 41, 42, 43, 46, 47, 48, 49, 50, 51, 51, 52, 53, 55, 56, 57, 57, 58, 59, 59, 60, 61, 63, 64, 65, 67, 68, 69, 69, 70, 71, 72, 73, 74, 76, 77, 78, 81, 82, 83, 84, 85, 86, 86, 87, 88, 88, 89, 201, 202, 203, 204, 207, 208, 209, 197, 198, 199, 200, 201, 89, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 101, 102, 103, 107, 108, 109, 109, 110, 111, 114, 115, 116, 118, 119, 120, 123, 124, 125, 127, 128, 129, 129, 168, 169, 169, 170, 171, 162, 163, 164, 164, 165, 166, 167, 168, 129, 135, 136, 137, 137, 138, 139, 140, 141, 142, 7, 8, 9, 9, 10, 11, 11, 12, 13, 14, 15, 1, 148, 149, 150, 153, 154, 2, 0, 1, 190, 191, 192, 175, 178, 180, 181, 182, 184, 185, 187, 189, 1, 1, 16, 17, 17, 19, 21, 22, 24, 25, 27, 29, 31, 32, 34, 36, 37, 39, 41, 41, 43, 44, 46, 48, 49, 49, 51, 53, 55, 57, 59, 63, 65, 66, 66, 67, 69, 76, 78, 79, 81, 83, 84, 84, 86, 88, 88, 201, 202, 206, 207, 209, 197, 199, 200, 200, 89, 91, 92, 94, 96, 97, 99, 100, 101, 103, 104, 107, 109, 111, 114, 116, 117, 118, 120, 121, 123, 125, 126, 127, 129, 169, 169, 171, 172, 134, 135, 137, 137, 139, 140, 140, 142, 143, 6, 7, 9, 11, 13, 14, 157, 148, 150, 152, 153, 2, 0, 190, 191, 178, 181, 182, 182, 185, 186, 186, 187, 1, 1, 17, 21, 27, 31, 32, 32, 36, 37, 37, 41, 44, 46, 49, 53, 55, 59, 61, 63, 66, 69, 81, 84, 88, 88, 202, 204, 206, 209, 210, 197, 200, 91, 91, 92, 96, 96, 97, 100, 101, 104, 105, 107, 111, 112, 114, 117, 118, 126, 127, 169, 134, 137, 140, 6, 9, 11, 11, 14, 1, 157, 150, 151, 151, 152, 2, 0, 191, 175, 1, 21, 22, 26, 27, 32, 37, 44, 45, 46, 53, 54, 54, 55, 61, 62, 63, 69, 81, 88, 204, 196, 197, 91, 91, 96, 100, 107, 112, 113, 113, 114, 118, 123, 126, 169, 134, 140, 143, 6, 11, 1, 0, 175, 176, 1, 22, 25, 26, 32, 37, 37, 45, 46, 46, 54, 61, 62, 69, 71, 80, 81, 204, 91, 100, 101, 113, 118, 121, 122, 123, 169, 5, 6, 1, 186, 1, 25, 25, 26, 37, 37, 46, 61, 80, 204, 205, 196, 91, 101, 113, 121, 122, 122, 169, 172, 145, 5, 1, 182, 186, 25, 25, 37, 61, 80, 205, 206, 195, 196, 101, 113, 122, 172, 144, 145, 1, 182, 25, 61, 195, 101, 105, 143, 144, 1, 178, 182, 61, 195, 105, 106, 143, 1, 155, 176, 178, 61, 134, 143, 155, 176, 61, 62, 133, 134, 155, 0, 176, 62, 132, 133, 155, 0, 62, 71, 131, 132, 155, 0, 71, 72, 130, 131, 155, 0, 72, 74, 130, 155, 156, 0, 74, 75, 129, 130, 156, 129, 156, 157, 129, 157, 151, 167, 129, 151, 167, 151, 2, 166, 167, 2, 164, 166, 2, 162, 164, 2, 3, 76, 79, 113, 172, 160, 113, 160, 161, 107, 113, 161]; 4 | testOutput["water3"]["pass"]=true; 5 | testOutput["water3"]["report"]="exp numtri:197\nexp dev:0.00000000000001\nact numtri:197\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/water3b.js: -------------------------------------------------------------------------------- 1 | testOutput["water3b"]=[]; 2 | testOutput["water3b"]["json"]=[[[-128.0, 4224.0], [-128.0, -128.0], [4224.0, -128.0], [4224.0, 4224.0], [-128.0, 4224.0]], [[3832.0, -21.0], [3840.0, -17.0], [3877.0, 21.0], [3895.0, 39.0], [3961.0, -21.0], [3893.0, -98.0], [3855.0, -128.0], [3688.0, -128.0], [3742.0, -81.0], [3793.0, -41.0], [3832.0, -21.0], [3832.0, -21.0]], [[4205.0, 596.0], [4224.0, 572.0], [4224.0, 248.0], [4166.0, 163.0], [4119.0, 50.0], [4020.0, 36.0], [4004.0, 21.0], [3969.0, 21.0], [3936.0, 62.0], [3982.0, 117.0], [4088.0, 293.0], [4152.0, 419.0], [4185.0, 544.0], [4205.0, 596.0], [4205.0, 596.0]]]; 3 | testOutput["water3b"]["triangles"]=[1, 25, 26, 26, 27, 28, 19, 20, 21, 21, 22, 23, 1, 12, 13, 5, 6, 7, 10, 11, 2, 3, 0, 1, 1, 26, 28, 1, 13, 14, 14, 5, 7, 9, 10, 2, 3, 1, 28, 1, 14, 7, 8, 9, 2, 3, 28, 29, 1, 7, 8, 25, 1, 8, 24, 25, 8, 24, 8, 2, 23, 24, 2, 21, 23, 2, 19, 21, 2, 17, 18, 3, 3, 29, 17]; 4 | testOutput["water3b"]["pass"]=true; 5 | testOutput["water3b"]["report"]="exp numtri:25\nexp dev:0.00000000000001\nact numtri:25\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/testoutput/water4.js: -------------------------------------------------------------------------------- 1 | testOutput["water4"]=[]; 2 | testOutput["water4"]["json"]=[[[3911.0, 4075.0], [3910.0, 4075.0], [3926.0, 4114.0], [3950.0, 4132.0], [3965.0, 4126.0], [3978.0, 4139.0], [3986.0, 4131.0], [3979.0, 4119.0], [3986.0, 4084.0], [3991.0, 4075.0], [4020.0, 4020.0], [4027.0, 4012.0], [4030.0, 4022.0], [4047.0, 4033.0], [4058.0, 4030.0], [4067.0, 4022.0], [4120.0, 4003.0], [4118.0, 3993.0], [4135.0, 3995.0], [4130.0, 4032.0], [4121.0, 4038.0], [4118.0, 4056.0], [4107.0, 4050.0], [4095.0, 4060.0], [4086.0, 4062.0], [4070.0, 4075.0], [4027.0, 4111.0], [4042.0, 4140.0], [4058.0, 4139.0], [4067.0, 4135.0], [4078.0, 4138.0], [4067.0, 4151.0], [4067.0, 4166.0], [4077.0, 4180.0], [4088.0, 4191.0], [4047.0, 4172.0], [4031.0, 4161.0], [4020.0, 4165.0], [4000.0, 4147.0], [4013.0, 4171.0], [4000.0, 4224.0], [3836.0, 4224.0], [3828.0, 4224.0], [3071.0, 4224.0], [3070.0, 4212.0], [3158.0, 4140.0], [3202.0, 4158.0], [3171.0, 4117.0], [3161.0, 4104.0], [3136.0, 4131.0], [3122.0, 4117.0], [3105.0, 4099.0], [3122.0, 4075.0], [3136.0, 4055.0], [3156.0, 4075.0], [3178.0, 4097.0], [3205.0, 4082.0], [3176.0, 4036.0], [3187.0, 3979.0], [3105.0, 3947.0], [3084.0, 3920.0], [3036.0, 3976.0], [2980.0, 3982.0], [2993.0, 4043.0], [2956.0, 3964.0], [3020.0, 3960.0], [3050.0, 3921.0], [3032.0, 3880.0], [3069.0, 3902.0], [3093.0, 3894.0], [3188.0, 3961.0], [3236.0, 3917.0], [3222.0, 3893.0], [3191.0, 3891.0], [3173.0, 3863.0], [3187.0, 3818.0], [3225.0, 3775.0], [3292.0, 3774.0], [3239.0, 3798.0], [3197.0, 3845.0], [3211.0, 3873.0], [3249.0, 3877.0], [3442.0, 3801.0], [3567.0, 3769.0], [3587.0, 3798.0], [3632.0, 3777.0], [3607.0, 3820.0], [3644.0, 3880.0], [3707.0, 3851.0], [3726.0, 3899.0], [3766.0, 3951.0], [3770.0, 3977.0], [3778.0, 3985.0], [3772.0, 4012.0], [3763.0, 3998.0], [3745.0, 3990.0], [3747.0, 3977.0], [3738.0, 3974.0], [3735.0, 3985.0], [3725.0, 3995.0], [3745.0, 4010.0], [3758.0, 4024.0], [3763.0, 4048.0], [3772.0, 4067.0], [3762.0, 4074.0], [3754.0, 4093.0], [3763.0, 4094.0], [3779.0, 4083.0], [3779.0, 4074.0], [3784.0, 4066.0], [3792.0, 4060.0], [3794.0, 4043.0], [3795.0, 4029.0], [3798.0, 4016.0], [3807.0, 4006.0], [3799.0, 3933.0], [3849.0, 3871.0], [3838.0, 3840.0], [3885.0, 3818.0], [3913.0, 3778.0], [3958.0, 3687.0], [4056.0, 3501.0], [4109.0, 3301.0], [3956.0, 3259.0], [3876.0, 3277.0], [3775.0, 3251.0], [3705.0, 3225.0], [3659.0, 3243.0], [3613.0, 3232.0], [3614.0, 3310.0], [3606.0, 3266.0], [3552.0, 3297.0], [3494.0, 3235.0], [3440.0, 3221.0], [3402.0, 3190.0], [3344.0, 3177.0], [3264.0, 3142.0], [3279.0, 3201.0], [3248.0, 3256.0], [3229.0, 3197.0], [3200.0, 3194.0], [3191.0, 3246.0], [3159.0, 3244.0], [3125.0, 3282.0], [3097.0, 3296.0], [3068.0, 3279.0], [3013.0, 3393.0], [3002.0, 3486.0], [2994.0, 3383.0], [2917.0, 3406.0], [2985.0, 3359.0], [3073.0, 3239.0], [3106.0, 3270.0], [3139.0, 3238.0], [3156.0, 3166.0], [3156.0, 3101.0], [3106.0, 3069.0], [3095.0, 3021.0], [3060.0, 3025.0], [3100.0, 2967.0], [3058.0, 2920.0], [3115.0, 2933.0], [3138.0, 2891.0], [3168.0, 2877.0], [3217.0, 2892.0], [3207.0, 2847.0], [3143.0, 2821.0], [3192.0, 2691.0], [3239.0, 2686.0], [3176.0, 2615.0], [3191.0, 2615.0], [3191.0, 2600.0], [3240.0, 2590.0], [3189.0, 2544.0], [3161.0, 2570.0], [3112.0, 2769.0], [3087.0, 2798.0], [3045.0, 2878.0], [3028.0, 2890.0], [2992.0, 3118.0], [2905.0, 3266.0], [2880.0, 3271.0], [2860.0, 3342.0], [2820.0, 3348.0], [2800.0, 3419.0], [2775.0, 3424.0], [2756.0, 3495.0], [2731.0, 3501.0], [2711.0, 3572.0], [2686.0, 3577.0], [2642.0, 3729.0], [2612.0, 3730.0], [2628.0, 3805.0], [2628.0, 3821.0], [2579.0, 3968.0], [2554.0, 3973.0], [2554.0, 4004.0], [2524.0, 4004.0], [2534.0, 4029.0], [2479.0, 4050.0], [2470.0, 4075.0], [2457.0, 4111.0], [2442.0, 4117.0], [2419.0, 4126.0], [2414.0, 4197.0], [2390.0, 4218.0], [2388.0, 4224.0], [-128.0, 4224.0], [-128.0, -128.0], [-128.0, -128.0], [4224.0, -128.0], [4224.0, -128.0], [4224.0, 3063.0], [4156.0, 3260.0], [4172.0, 3284.0], [4147.0, 3288.0], [4125.0, 3375.0], [4092.0, 3462.0], [4080.0, 3524.0], [3983.0, 3692.0], [3965.0, 3786.0], [3984.0, 3816.0], [3943.0, 3891.0], [3973.0, 3902.0], [3978.0, 3917.0], [3976.0, 3929.0], [3964.0, 3953.0], [3957.0, 3968.0], [3941.0, 3983.0], [3925.0, 4009.0], [3923.0, 4024.0], [3924.0, 4033.0], [3922.0, 4046.0], [3920.0, 4055.0], [3911.0, 4075.0], [3911.0, 4075.0]], [[3364.0, 4097.0], [3383.0, 4108.0], [3398.0, 4124.0], [3406.0, 4144.0], [3413.0, 4155.0], [3426.0, 4156.0], [3442.0, 4162.0], [3446.0, 4176.0], [3465.0, 4185.0], [3488.0, 4189.0], [3502.0, 4192.0], [3517.0, 4205.0], [3520.0, 4224.0], [3549.0, 4224.0], [3557.0, 4208.0], [3540.0, 4198.0], [3528.0, 4191.0], [3523.0, 4183.0], [3510.0, 4184.0], [3498.0, 4178.0], [3485.0, 4184.0], [3479.0, 4173.0], [3480.0, 4136.0], [3489.0, 4120.0], [3475.0, 4116.0], [3460.0, 4105.0], [3471.0, 4103.0], [3469.0, 4083.0], [3444.0, 4074.0], [3444.0, 4056.0], [3455.0, 4070.0], [3470.0, 4074.0], [3478.0, 4083.0], [3488.0, 4079.0], [3477.0, 4089.0], [3483.0, 4100.0], [3475.0, 4107.0], [3483.0, 4113.0], [3506.0, 4102.0], [3502.0, 4092.0], [3527.0, 4107.0], [3513.0, 4106.0], [3512.0, 4117.0], [3504.0, 4125.0], [3490.0, 4136.0], [3487.0, 4146.0], [3486.0, 4172.0], [3501.0, 4173.0], [3510.0, 4178.0], [3523.0, 4177.0], [3532.0, 4185.0], [3568.0, 4199.0], [3582.0, 4198.0], [3600.0, 4183.0], [3579.0, 4144.0], [3580.0, 4123.0], [3586.0, 4114.0], [3586.0, 4104.0], [3594.0, 4099.0], [3573.0, 4090.0], [3581.0, 4103.0], [3578.0, 4114.0], [3565.0, 4110.0], [3565.0, 4101.0], [3562.0, 4092.0], [3542.0, 4081.0], [3540.0, 4067.0], [3553.0, 4052.0], [3538.0, 4041.0], [3529.0, 4040.0], [3532.0, 4027.0], [3538.0, 4019.0], [3551.0, 4018.0], [3565.0, 4011.0], [3567.0, 3999.0], [3576.0, 3996.0], [3595.0, 3992.0], [3588.0, 3958.0], [3573.0, 3922.0], [3578.0, 3885.0], [3559.0, 3878.0], [3553.0, 3866.0], [3558.0, 3790.0], [3529.0, 3795.0], [3468.0, 3809.0], [3395.0, 3836.0], [3247.0, 3891.0], [3246.0, 3922.0], [3246.0, 3948.0], [3274.0, 3976.0], [3335.0, 3983.0], [3387.0, 3980.0], [3383.0, 4036.0], [3387.0, 4052.0], [3364.0, 4097.0], [3364.0, 4097.0]], [[2976.0, 2176.0], [2953.0, 2237.0], [2969.0, 2285.0], [3011.0, 2301.0], [3046.0, 2297.0], [3091.0, 2255.0], [3133.0, 2276.0], [3155.0, 2245.0], [3145.0, 2194.0], [3171.0, 2157.0], [3148.0, 2085.0], [3109.0, 2097.0], [3096.0, 2079.0], [3073.0, 2080.0], [3056.0, 2136.0], [3008.0, 2171.0], [3032.0, 2134.0], [3042.0, 2085.0], [3064.0, 2068.0], [3067.0, 2028.0], [3099.0, 1984.0], [3126.0, 1980.0], [3146.0, 1951.0], [3158.0, 1893.0], [3207.0, 1857.0], [3240.0, 1826.0], [3321.0, 1842.0], [3238.0, 1848.0], [3213.0, 1885.0], [3177.0, 1917.0], [3163.0, 1968.0], [3138.0, 2017.0], [3180.0, 2004.0], [3206.0, 1958.0], [3272.0, 1951.0], [3346.0, 1944.0], [3360.0, 1988.0], [3402.0, 2001.0], [3437.0, 2053.0], [3460.0, 2054.0], [3468.0, 2089.0], [3455.0, 2140.0], [3425.0, 2187.0], [3486.0, 2135.0], [3505.0, 2080.0], [3506.0, 2038.0], [3516.0, 1985.0], [3559.0, 1955.0], [3556.0, 1887.0], [3548.0, 1857.0], [3520.0, 1881.0], [3482.0, 1895.0], [3473.0, 1860.0], [3448.0, 1842.0], [3449.0, 1791.0], [3480.0, 1773.0], [3532.0, 1750.0], [3510.0, 1789.0], [3463.0, 1808.0], [3475.0, 1835.0], [3509.0, 1874.0], [3542.0, 1836.0], [3579.0, 1847.0], [3579.0, 1891.0], [3580.0, 1936.0], [3601.0, 1954.0], [3630.0, 1924.0], [3699.0, 1930.0], [3720.0, 1966.0], [3708.0, 1994.0], [3695.0, 1943.0], [3629.0, 1945.0], [3611.0, 1975.0], [3581.0, 1966.0], [3556.0, 1993.0], [3548.0, 2073.0], [3517.0, 2148.0], [3475.0, 2199.0], [3486.0, 2254.0], [3456.0, 2300.0], [3410.0, 2293.0], [3384.0, 2219.0], [3346.0, 2189.0], [3270.0, 2185.0], [3214.0, 2148.0], [3183.0, 2217.0], [3231.0, 2271.0], [3301.0, 2317.0], [3296.0, 2369.0], [3282.0, 2441.0], [3230.0, 2488.0], [3242.0, 2507.0], [3233.0, 2539.0], [3275.0, 2568.0], [3272.0, 2646.0], [3301.0, 2638.0], [3312.0, 2583.0], [3359.0, 2662.0], [3350.0, 2602.0], [3374.0, 2555.0], [3413.0, 2549.0], [3444.0, 2550.0], [3459.0, 2526.0], [3481.0, 2534.0], [3464.0, 2556.0], [3506.0, 2588.0], [3536.0, 2535.0], [3555.0, 2549.0], [3518.0, 2625.0], [3491.0, 2600.0], [3463.0, 2623.0], [3451.0, 2583.0], [3398.0, 2637.0], [3437.0, 2690.0], [3378.0, 2678.0], [3354.0, 2693.0], [3301.0, 2701.0], [3301.0, 2767.0], [3266.0, 2712.0], [3235.0, 2713.0], [3195.0, 2731.0], [3203.0, 2761.0], [3224.0, 2792.0], [3291.0, 2804.0], [3341.0, 2802.0], [3357.0, 2780.0], [3363.0, 2753.0], [3388.0, 2724.0], [3415.0, 2726.0], [3445.0, 2736.0], [3460.0, 2779.0], [3516.0, 2736.0], [3537.0, 2741.0], [3579.0, 2749.0], [3608.0, 2715.0], [3645.0, 2709.0], [3659.0, 2727.0], [3691.0, 2712.0], [3734.0, 2691.0], [3745.0, 2648.0], [3731.0, 2635.0], [3687.0, 2679.0], [3654.0, 2685.0], [3633.0, 2662.0], [3598.0, 2658.0], [3584.0, 2630.0], [3596.0, 2597.0], [3594.0, 2557.0], [3613.0, 2518.0], [3640.0, 2517.0], [3636.0, 2486.0], [3658.0, 2444.0], [3647.0, 2409.0], [3686.0, 2446.0], [3652.0, 2488.0], [3651.0, 2525.0], [3626.0, 2560.0], [3655.0, 2597.0], [3630.0, 2629.0], [3667.0, 2669.0], [3727.0, 2616.0], [3758.0, 2623.0], [3817.0, 2628.0], [3823.0, 2593.0], [3791.0, 2551.0], [3753.0, 2515.0], [3754.0, 2484.0], [3775.0, 2484.0], [3795.0, 2454.0], [3831.0, 2471.0], [3893.0, 2485.0], [3927.0, 2485.0], [3953.0, 2458.0], [3998.0, 2422.0], [4046.0, 2383.0], [4022.0, 2355.0], [4020.0, 2296.0], [3946.0, 2285.0], [3902.0, 2357.0], [3920.0, 2295.0], [3894.0, 2249.0], [3839.0, 2250.0], [3898.0, 2235.0], [3927.0, 2187.0], [3916.0, 2149.0], [3887.0, 2161.0], [3822.0, 2135.0], [3883.0, 2132.0], [3922.0, 2040.0], [3909.0, 2109.0], [3937.0, 2104.0], [3949.0, 2152.0], [3998.0, 2135.0], [4080.0, 2138.0], [4119.0, 2083.0], [4101.0, 2020.0], [4106.0, 1978.0], [4164.0, 1986.0], [4163.0, 1952.0], [4203.0, 1992.0], [4210.0, 2013.0], [4200.0, 2031.0], [4224.0, 2021.0], [4224.0, 1949.0], [4216.0, 1915.0], [4199.0, 1891.0], [4199.0, 1876.0], [4183.0, 1816.0], [4097.0, 1796.0], [4059.0, 1748.0], [4030.0, 1713.0], [3989.0, 1696.0], [3955.0, 1681.0], [3926.0, 1657.0], [3869.0, 1646.0], [3824.0, 1612.0], [3788.0, 1591.0], [3561.0, 1609.0], [3546.0, 1624.0], [3515.0, 1624.0], [3510.0, 1649.0], [3350.0, 1732.0], [3335.0, 1732.0], [3274.0, 1748.0], [3259.0, 1763.0], [3108.0, 1795.0], [3049.0, 1887.0], [3015.0, 2080.0], [2976.0, 2176.0], [2976.0, 2176.0]], [[3183.0, -128.0], [3192.0, -118.0], [3253.0, -36.0], [3313.0, 26.0], [3357.0, 31.0], [3406.0, 103.0], [3514.0, 134.0], [3541.0, 271.0], [3547.0, 344.0], [3664.0, 311.0], [3669.0, 216.0], [3565.0, 168.0], [3662.0, 150.0], [3655.0, 88.0], [3528.0, 39.0], [3581.0, 26.0], [3608.0, -21.0], [3675.0, -87.0], [3637.0, -128.0], [3183.0, -128.0]], [[3205.0, -15.0], [3114.0, -30.0], [3065.0, -59.0], [3017.0, -29.0], [3047.0, 7.0], [3013.0, 118.0], [2971.0, 183.0], [2978.0, 281.0], [3026.0, 305.0], [3081.0, 298.0], [3107.0, 369.0], [3157.0, 360.0], [3191.0, 397.0], [3312.0, 393.0], [3350.0, 371.0], [3363.0, 294.0], [3419.0, 236.0], [3334.0, 298.0], [3306.0, 338.0], [3305.0, 290.0], [3261.0, 235.0], [3253.0, 140.0], [3254.0, 86.0], [3335.0, 51.0], [3273.0, 34.0], [3227.0, 26.0], [3199.0, 49.0], [3232.0, 96.0], [3223.0, 166.0], [3224.0, 247.0], [3242.0, 268.0], [3224.0, 281.0], [3202.0, 244.0], [3173.0, 266.0], [3187.0, 328.0], [3158.0, 328.0], [3136.0, 258.0], [3184.0, 231.0], [3177.0, 169.0], [3149.0, 144.0], [3133.0, 188.0], [3078.0, 155.0], [3058.0, 183.0], [3102.0, 221.0], [3074.0, 236.0], [3048.0, 198.0], [3011.0, 180.0], [3043.0, 144.0], [3111.0, 74.0], [3120.0, 37.0], [3098.0, 19.0], [3100.0, -1.0], [3201.0, 8.0], [3205.0, -15.0], [3205.0, -15.0]], [[4224.0, 2296.0], [4180.0, 2330.0], [4198.0, 2362.0], [4203.0, 2411.0], [4224.0, 2415.0], [4224.0, 2482.0], [4212.0, 2474.0], [4198.0, 2509.0], [4197.0, 2541.0], [4177.0, 2531.0], [4124.0, 2533.0], [4101.0, 2514.0], [4023.0, 2555.0], [4029.0, 2506.0], [4055.0, 2468.0], [4029.0, 2422.0], [3955.0, 2489.0], [3928.0, 2532.0], [3913.0, 2515.0], [3857.0, 2512.0], [3804.0, 2481.0], [3789.0, 2511.0], [3844.0, 2590.0], [3830.0, 2643.0], [3767.0, 2641.0], [3761.0, 2730.0], [3704.0, 2728.0], [3675.0, 2737.0], [3670.0, 2764.0], [3651.0, 2765.0], [3651.0, 2741.0], [3626.0, 2729.0], [3607.0, 2761.0], [3552.0, 2763.0], [3551.0, 2781.0], [3513.0, 2781.0], [3505.0, 2817.0], [3477.0, 2800.0], [3459.0, 2831.0], [3422.0, 2852.0], [3420.0, 2901.0], [3399.0, 2855.0], [3428.0, 2807.0], [3428.0, 2770.0], [3402.0, 2751.0], [3378.0, 2764.0], [3400.0, 2817.0], [3363.0, 2833.0], [3319.0, 2849.0], [3299.0, 2895.0], [3313.0, 2925.0], [3283.0, 2942.0], [3286.0, 2853.0], [3237.0, 2904.0], [3230.0, 2941.0], [3254.0, 2952.0], [3267.0, 2985.0], [3302.0, 3016.0], [3346.0, 2995.0], [3379.0, 3004.0], [3384.0, 3070.0], [3416.0, 3072.0], [3456.0, 3069.0], [3459.0, 3042.0], [3478.0, 2986.0], [3481.0, 3022.0], [3496.0, 3023.0], [3512.0, 3072.0], [3486.0, 3080.0], [3488.0, 3150.0], [3508.0, 3174.0], [3535.0, 3195.0], [3553.0, 3174.0], [3571.0, 3206.0], [3605.0, 3179.0], [3639.0, 3213.0], [3701.0, 3204.0], [3881.0, 3256.0], [3964.0, 3239.0], [4113.0, 3273.0], [4168.0, 3133.0], [4224.0, 2979.0], [4224.0, 2296.0]]]; 3 | testOutput["water4"]["triangles"]=[590, 591, 592, 592, 593, 594, 596, 597, 598, 599, 600, 601, 601, 602, 603, 603, 604, 605, 608, 609, 610, 611, 612, 613, 615, 616, 617, 621, 622, 623, 624, 625, 626, 627, 628, 629, 631, 632, 633, 582, 583, 584, 585, 586, 587, 587, 588, 209, 209, 562, 563, 565, 566, 567, 567, 568, 569, 572, 573, 574, 575, 576, 577, 577, 578, 579, 579, 580, 211, 213, 214, 215, 215, 216, 217, 217, 218, 219, 220, 221, 222, 222, 223, 224, 224, 225, 226, 226, 227, 228, 230, 231, 232, 232, 233, 234, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 22, 23, 24, 28, 29, 30, 33, 34, 35, 36, 37, 38, 38, 39, 40, 43, 44, 45, 48, 49, 50, 50, 51, 52, 52, 53, 55, 56, 57, 58, 58, 59, 60, 62, 63, 64, 66, 67, 68, 68, 69, 70, 70, 323, 324, 326, 327, 328, 237, 238, 239, 240, 241, 242, 244, 245, 246, 246, 247, 248, 251, 252, 253, 253, 254, 255, 255, 256, 257, 257, 258, 259, 259, 260, 261, 264, 265, 266, 266, 267, 268, 268, 269, 270, 270, 271, 272, 274, 275, 276, 277, 278, 279, 282, 283, 284, 284, 285, 286, 289, 290, 291, 292, 293, 294, 295, 296, 297, 297, 298, 299, 300, 301, 302, 304, 305, 306, 306, 307, 308, 309, 310, 311, 313, 314, 315, 315, 316, 317, 72, 73, 74, 74, 75, 76, 76, 77, 78, 81, 82, 83, 84, 85, 86, 87, 88, 89, 89, 90, 91, 91, 92, 93, 94, 95, 96, 97, 98, 99, 99, 100, 101, 102, 103, 104, 107, 108, 109, 111, 112, 113, 114, 115, 116, 116, 117, 118, 119, 120, 121, 124, 125, 126, 126, 127, 128, 128, 129, 130, 130, 131, 132, 132, 133, 134, 134, 135, 136, 136, 137, 138, 140, 141, 142, 142, 143, 144, 146, 147, 148, 148, 149, 150, 155, 156, 157, 157, 158, 159, 159, 160, 161, 161, 691, 692, 694, 695, 696, 699, 700, 701, 702, 703, 704, 708, 709, 710, 710, 711, 712, 712, 713, 714, 638, 639, 640, 640, 641, 642, 644, 645, 646, 646, 647, 648, 648, 649, 650, 653, 654, 655, 655, 656, 657, 664, 665, 666, 668, 669, 670, 670, 671, 672, 672, 673, 674, 674, 675, 676, 676, 677, 678, 682, 683, 684, 686, 687, 688, 690, 691, 161, 161, 162, 163, 168, 169, 170, 170, 171, 172, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 203, 203, 204, 205, 205, 206, 207, 207, 209, 333, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 350, 351, 352, 354, 355, 356, 357, 358, 359, 359, 360, 361, 361, 362, 363, 364, 365, 366, 366, 367, 368, 368, 369, 370, 370, 371, 372, 372, 373, 374, 376, 377, 378, 381, 382, 383, 384, 385, 386, 386, 387, 388, 388, 389, 390, 393, 394, 395, 399, 400, 401, 403, 404, 405, 406, 407, 408, 409, 410, 411, 411, 412, 413, 414, 415, 416, 418, 419, 420, 420, 421, 422, 422, 423, 424, 424, 425, 426, 427, 428, 429, 429, 430, 431, 431, 432, 433, 433, 434, 435, 437, 438, 439, 439, 440, 441, 441, 442, 443, 444, 445, 446, 446, 447, 448, 448, 449, 450, 457, 458, 459, 459, 460, 461, 462, 463, 464, 465, 466, 467, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 483, 484, 485, 486, 487, 488, 488, 489, 490, 496, 497, 498, 499, 500, 501, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 516, 517, 518, 519, 520, 521, 521, 522, 523, 523, 524, 525, 526, 527, 528, 529, 530, 531, 531, 532, 533, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 549, 550, 551, 551, 552, 553, 555, 556, 557, 558, 559, 332, 332, 333, 209, 209, 588, 589, 589, 590, 592, 598, 599, 601, 601, 603, 605, 608, 610, 611, 611, 613, 614, 615, 617, 618, 624, 626, 627, 627, 629, 630, 631, 633, 634, 585, 587, 209, 565, 567, 569, 575, 577, 579, 215, 217, 219, 219, 220, 222, 222, 224, 226, 230, 232, 234, 6, 8, 9, 9, 11, 12, 16, 18, 20, 20, 22, 24, 27, 28, 30, 32, 33, 35, 43, 45, 46, 48, 50, 52, 61, 62, 64, 65, 66, 68, 70, 324, 325, 325, 326, 328, 237, 239, 240, 240, 242, 243, 244, 246, 248, 250, 251, 253, 253, 255, 257, 263, 264, 266, 266, 268, 270, 274, 276, 277, 277, 279, 280, 282, 284, 286, 289, 291, 292, 295, 297, 299, 300, 302, 303, 303, 304, 306, 309, 311, 312, 312, 313, 315, 315, 317, 318, 74, 76, 78, 84, 86, 87, 87, 89, 91, 91, 93, 94, 99, 101, 102, 102, 104, 105, 107, 109, 110, 110, 111, 113, 114, 116, 118, 128, 130, 132, 136, 138, 139, 140, 142, 144, 145, 146, 148, 148, 150, 151, 155, 157, 159, 159, 161, 692, 694, 696, 697, 699, 701, 702, 702, 704, 705, 640, 642, 643, 643, 644, 646, 648, 650, 651, 652, 653, 655, 664, 666, 667, 674, 676, 678, 682, 684, 685, 686, 688, 689, 690, 161, 163, 168, 170, 172, 174, 176, 178, 178, 180, 181, 185, 187, 189, 191, 193, 195, 195, 197, 199, 199, 201, 203, 203, 205, 207, 207, 333, 334, 345, 347, 348, 350, 352, 353, 354, 356, 357, 357, 359, 361, 364, 366, 368, 368, 370, 372, 376, 378, 379, 386, 388, 390, 393, 395, 396, 399, 401, 402, 406, 408, 409, 409, 411, 413, 417, 418, 420, 426, 427, 429, 429, 431, 433, 433, 435, 436, 437, 439, 441, 444, 446, 448, 448, 450, 451, 459, 461, 462, 462, 464, 465, 475, 477, 478, 478, 480, 481, 483, 485, 486, 495, 496, 498, 503, 505, 506, 509, 511, 512, 512, 514, 515, 516, 518, 519, 519, 521, 523, 526, 528, 529, 529, 531, 533, 536, 538, 539, 539, 541, 542, 542, 544, 545, 545, 547, 548, 551, 553, 554, 558, 332, 209, 209, 589, 592, 598, 601, 605, 608, 611, 614, 614, 615, 618, 624, 627, 630, 630, 631, 634, 584, 585, 209, 574, 575, 579, 213, 215, 219, 222, 226, 228, 229, 230, 234, 6, 9, 12, 14, 16, 20, 27, 30, 31, 31, 32, 35, 48, 52, 55, 61, 64, 65, 70, 325, 328, 243, 244, 248, 263, 266, 270, 273, 274, 277, 289, 292, 294, 295, 299, 300, 303, 306, 308, 74, 78, 79, 91, 94, 96, 99, 102, 105, 110, 113, 114, 114, 118, 119, 126, 128, 132, 136, 139, 140, 145, 148, 151, 155, 159, 692, 699, 702, 705, 638, 640, 643, 643, 646, 648, 648, 651, 652, 663, 664, 667, 674, 678, 679, 685, 686, 689, 690, 163, 164, 178, 181, 183, 191, 195, 199, 199, 203, 207, 207, 334, 335, 345, 348, 350, 353, 354, 357, 363, 364, 368, 368, 372, 374, 375, 376, 379, 384, 386, 390, 398, 399, 402, 409, 413, 414, 417, 420, 422, 429, 433, 436, 436, 437, 441, 474, 475, 478, 481, 483, 486, 495, 498, 499, 508, 509, 512, 516, 519, 523, 526, 529, 533, 551, 554, 555, 557, 558, 209, 209, 592, 594, 614, 618, 619, 623, 624, 630, 584, 209, 563, 572, 574, 579, 212, 213, 219, 222, 228, 229, 229, 234, 1, 6, 12, 13, 13, 14, 20, 27, 31, 35, 47, 48, 55, 60, 61, 65, 70, 328, 329, 240, 243, 248, 262, 263, 270, 295, 300, 303, 303, 308, 309, 74, 79, 80, 87, 91, 96, 110, 114, 119, 126, 132, 134, 144, 145, 151, 154, 155, 692, 698, 699, 705, 638, 643, 648, 663, 667, 668, 672, 674, 679, 689, 690, 164, 174, 178, 183, 191, 199, 207, 207, 335, 336, 344, 345, 350, 350, 353, 357, 363, 368, 374, 383, 384, 390, 398, 402, 403, 409, 414, 416, 417, 422, 424, 436, 441, 443, 481, 486, 488, 508, 512, 515, 515, 516, 523, 525, 526, 533, 551, 555, 557, 557, 209, 594, 608, 614, 619, 621, 623, 630, 582, 584, 563, 572, 579, 211, 222, 229, 1, 13, 20, 24, 26, 27, 35, 46, 47, 55, 60, 65, 68, 262, 270, 272, 294, 295, 303, 303, 309, 312, 72, 74, 80, 87, 96, 97, 110, 119, 121, 144, 151, 152, 153, 154, 692, 697, 698, 705, 638, 648, 652, 670, 672, 679, 689, 164, 165, 174, 183, 185, 189, 191, 207, 207, 336, 338, 342, 344, 350, 350, 357, 361, 383, 390, 391, 397, 398, 403, 429, 436, 443, 478, 481, 488, 508, 515, 523, 525, 533, 534, 551, 557, 594, 608, 619, 620, 620, 621, 630, 582, 563, 564, 571, 572, 211, 6, 13, 24, 26, 35, 36, 46, 55, 56, 58, 60, 68, 261, 262, 272, 294, 303, 312, 71, 72, 80, 87, 97, 99, 140, 144, 152, 153, 692, 693, 697, 705, 706, 637, 638, 652, 685, 689, 165, 174, 185, 189, 189, 207, 338, 350, 361, 363, 383, 391, 392, 397, 403, 405, 429, 443, 444, 478, 488, 490, 508, 523, 525, 549, 551, 594, 608, 620, 630, 634, 582, 564, 5, 6, 24, 26, 36, 38, 58, 68, 70, 259, 261, 272, 289, 294, 312, 323, 70, 71, 71, 80, 81, 87, 99, 105, 136, 140, 152, 153, 693, 694, 694, 697, 706, 685, 165, 166, 174, 189, 338, 342, 350, 363, 381, 383, 392, 396, 397, 405, 429, 444, 448, 474, 478, 490, 506, 508, 525, 548, 549, 594, 607, 608, 630, 634, 564, 565, 5, 24, 25, 56, 58, 70, 259, 272, 273, 322, 323, 71, 84, 87, 105, 136, 152, 153, 694, 706, 707, 173, 174, 338, 341, 342, 363, 381, 392, 393, 393, 396, 405, 426, 429, 448, 474, 490, 491, 506, 525, 534, 545, 548, 594, 607, 630, 634, 5, 25, 26, 56, 70, 329, 259, 273, 277, 322, 71, 81, 83, 84, 105, 136, 153, 694, 694, 707, 708, 172, 173, 338, 381, 393, 405, 426, 448, 451, 472, 474, 491, 542, 545, 594, 606, 607, 634, 5, 26, 38, 46, 56, 329, 259, 277, 280, 321, 322, 81, 134, 136, 694, 172, 338, 339, 380, 381, 405, 472, 491, 492, 539, 542, 594, 605, 606, 634, 3, 5, 38, 259, 280, 281, 320, 321, 81, 134, 694, 708, 172, 339, 341, 379, 380, 405, 471, 472, 492, 539, 594, 595, 605, 634, 565, 3, 38, 40, 257, 259, 281, 320, 81, 83, 134, 708, 710, 379, 405, 406, 471, 492, 493, 539, 595, 596, 605, 565, 569, 2, 3, 40, 257, 281, 282, 319, 320, 83, 126, 134, 710, 375, 379, 406, 470, 471, 493, 539, 596, 598, 598, 605, 569, 253, 257, 282, 318, 319, 83, 126, 710, 712, 375, 406, 409, 598, 569, 570, 253, 282, 286, 315, 318, 83, 126, 712, 714, 374, 375, 409, 539, 598, 570, 250, 253, 286, 312, 315, 83, 124, 126, 714, 374, 409, 416, 539, 570, 571, 250, 286, 287, 312, 83, 105, 123, 124, 714, 363, 374, 416, 539, 571, 211, 249, 250, 287, 289, 312, 105, 123, 714, 715, 341, 363, 416, 536, 539, 211, 249, 287, 288, 288, 289, 105, 122, 123, 715, 341, 416, 417, 535, 536, 211, 249, 288, 105, 122, 715, 716, 172, 341, 417, 249, 105, 106, 122, 716, 717, 172, 417, 424, 121, 122, 717, 172, 424, 426, 121, 717, 718, 168, 172, 426, 168, 426, 451, 167, 168, 451, 167, 451, 452, 166, 167, 452, 166, 452, 453, 166, 453, 454, 685, 166, 454, 685, 454, 455, 685, 455, 456, 682, 685, 456, 682, 456, 457, 682, 457, 459, 681, 682, 459, 680, 681, 459, 680, 459, 462, 679, 680, 462, 670, 679, 462, 670, 462, 465, 668, 670, 465, 668, 465, 467, 668, 467, 468, 663, 668, 468, 663, 468, 469, 662, 663, 469, 662, 469, 470, 661, 662, 470, 661, 470, 493, 660, 661, 493, 660, 493, 494, 659, 660, 494, 659, 494, 495, 658, 659, 495, 658, 495, 499, 657, 658, 499, 657, 499, 501, 655, 657, 501, 655, 501, 502, 655, 502, 503, 652, 655, 503, 637, 652, 503, 637, 503, 506, 637, 506, 534, 46, 329, 236, 236, 237, 240, 121, 718, 212, 43, 46, 236, 121, 212, 219, 43, 236, 240, 110, 121, 219, 43, 240, 248, 110, 219, 222, 107, 110, 222, 107, 222, 1, 106, 107, 1, 249, 106, 1, 249, 1, 2, 249, 2, 40]; 4 | testOutput["water4"]["pass"]=true; 5 | testOutput["water4"]["report"]="exp numtri:705\nexp dev:0.00000000000001\nact numtri:705\nact dev:0"; 6 | -------------------------------------------------------------------------------- /viz/viz.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 100%; 3 | } 4 | div.main { 5 | position:fixed; 6 | top:0px; 7 | bottom:0px; 8 | left:0px; 9 | right:0px; 10 | } 11 | 12 | div.leftpanel { 13 | float: left; 14 | position: fixed; 15 | width: 20%; 16 | height: 100%; 17 | background-color: slategray; 18 | } 19 | 20 | div.flist { 21 | float: left; 22 | position: relative; 23 | width: 100%; 24 | height: 75%; 25 | background-color: slategray; 26 | overflow: scroll; 27 | } 28 | 29 | .file, .file_fail { 30 | position: relative; 31 | color: white; 32 | font-family: Helvetica, Arial, sans-serif; 33 | font-size: 1em; 34 | height: 5%; 35 | text-align: left; 36 | margin: 3%; 37 | margin-right: 4%; 38 | box-shadow: 5px 10px 18px #000000; 39 | z-index: 1; 40 | display:flex; 41 | align-items: center; 42 | justify-content: left; 43 | padding-left: 5%; 44 | overflow: visible; 45 | cursor: default; 46 | 47 | -webkit-user-select: none; 48 | -khtml-user-select: none; 49 | -moz-user-select: none; 50 | -o-user-select: none; 51 | user-select: none; 52 | } 53 | 54 | .file { 55 | background-color: gray; 56 | } 57 | 58 | .file_fail { 59 | background-color: red; 60 | } 61 | 62 | .file:hover,.file_fail:hover { 63 | color: white; 64 | box-shadow: 7px 14px 26px #000000; 65 | overflow: visible; 66 | } 67 | .file:hover { 68 | background-color: lightgray; 69 | } 70 | .file_fail:hover { 71 | background-color: pink; 72 | } 73 | .file:active,.file_fail:active { 74 | margin-right: 3%; 75 | margin-left: 4%; 76 | margin-top: 4%; 77 | margin-bottom: -1%; 78 | } 79 | 80 | div.controlpanel { 81 | float: left; 82 | position: relative; 83 | width: 100%; 84 | height: 10%; 85 | background-color: slategray; 86 | font-family: Helvetica, Arial, sans-serif; 87 | font-size: 1em; 88 | // padding: 5%; 89 | // border: 1px solid black; 90 | } 91 | 92 | div.controlpanel { 93 | // float: right; 94 | position: relative; 95 | width: 100%; 96 | height: 5%; 97 | background-color: slategray; 98 | font-family: Helvetica, Arial, sans-serif; 99 | font-size: 1em; 100 | display: flex; 101 | // padding: 5%; 102 | // border: 1px solid black; 103 | } 104 | 105 | div.controlbutton { 106 | // position: relative; 107 | background-color: gray; 108 | color: white; 109 | font-family: Helvetica, Arial, sans-serif; 110 | font-size: 1em; 111 | // width: 20%; 112 | height: 75%; 113 | text-align: center; 114 | margin-left: 3%; 115 | margin-top: 2%; 116 | margin-down: 2%; 117 | margin-right: 0%; 118 | box-shadow: 5px 10px 18px #000000; 119 | z-index: 1; 120 | // display:flex; 121 | display: inline-block; 122 | // align-items: center; 123 | // justify-content: left; 124 | padding-left: 2%; 125 | padding-right: 2%; 126 | padding: 1%em; 127 | overflow: visible; 128 | cursor: default; 129 | 130 | -webkit-user-select: none; 131 | -khtml-user-select: none; 132 | -moz-user-select: none; 133 | -o-user-select: none; 134 | user-select: none; 135 | } 136 | div.controlbutton:hover { 137 | background-color: lightgray; 138 | color: white; 139 | box-shadow: 7px 14px 26px #000000; 140 | overflow: visible; 141 | } 142 | div.controlbutton:active { 143 | margin-right: -2%; 144 | margin-left: 5%; 145 | margin-top: 4%; 146 | margin-bottom: -1%; 147 | } 148 | 149 | div.reportpanel { 150 | float: left; 151 | position: relative; 152 | width: 100%; 153 | height: 20%; 154 | background-color: slategray; 155 | font-family: Helvetica, Arial, sans-serif; 156 | font-size: 1em; 157 | // padding: 5%; 158 | // border: 1px solid black; 159 | } 160 | 161 | div.report { 162 | background-color: white; 163 | position: relative; 164 | box-shadow: 5px 10px 18px #000000; 165 | z-index: 1; 166 | margin: 3%; 167 | margin-right: 4%; 168 | height: 82.4%; 169 | overflow: scroll; 170 | // border: 1px solid red; 171 | padding: 2%; 172 | white-space: pre-wrap; 173 | } 174 | 175 | 176 | 177 | div.viewpanel { 178 | position: relative; 179 | float: right; 180 | width: 80%; 181 | height: 100%; 182 | background-color: slategray; 183 | z-index: 0; 184 | overflow: visible; 185 | } 186 | div.viewholder { 187 | // border: 5px solid red; 188 | background-color: white; 189 | position: relative; 190 | width: 98%; 191 | height: 98%; 192 | top: 50%; 193 | left: 50%; 194 | transform: translate(-50%, -50%); 195 | box-shadow: 5px 10px 18px #000000; 196 | z-index: 1; 197 | } 198 | div.viewer { 199 | // border: 5px solid green; 200 | overflow: visible; 201 | display: block; 202 | background-color: white; 203 | position: relative; 204 | width: 98.2%; 205 | height: 97%; 206 | top: 50%; 207 | left: 50%; 208 | transform: translate(-50%, -50%); 209 | } 210 | 211 | .can { 212 | margin: 0 auto; 213 | position: relative; 214 | } 215 | 216 | -------------------------------------------------------------------------------- /viz/viz.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 | 13 |
14 |
labels
15 |
triangles
16 |
earcut.js
17 |
18 |
19 |
20 | 21 |
22 |
23 |
24 |
25 |
26 |
27 | 28 |
29 |
30 |
31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /viz/viz.js: -------------------------------------------------------------------------------- 1 | var currentTestName = ""; 2 | var labelsToggle = 0; 3 | var fillToggle = 1; 4 | var labelmap = []; 5 | 6 | function setupCanvas(viewerid,canvasid) { 7 | // size must be reset because CSS sizing doesn't work on canvases. 8 | canvas = document.getElementById(canvasid); 9 | par = document.getElementById(viewerid); 10 | wextra = 0; 11 | hextra = 0; 12 | var wdt = par.clientWidth - wextra; 13 | var ht = par.clientHeight - hextra; 14 | canvas.setAttribute('height',ht+"px"); 15 | canvas.setAttribute('width',wdt+"px"); 16 | 17 | canvas.addEventListener("wheel", function (ev) { 18 | console.log("wheel"); 19 | console.log(ev.deltaX); 20 | console.log(ev.deltaY); 21 | console.log(ev.offsetX); 22 | console.log(ev.offsetY); 23 | redraw( canvas.id ); 24 | } ); 25 | 26 | return canvas; 27 | } 28 | 29 | /* Map from pset coordinates to canvas coordinates 30 | Example: pset has x-coordinates from -50 to 100, 31 | canvas x coordinates go from 0 to 600. 32 | consider a single point, and its x coordinate. 33 | first lets translate x so it goes from 0 to 150. psetx=(inputx-minx). 34 | now psetx / pset width is proportional to canvas x / canvas width 35 | ox/ow = cx/cw, therefore cx = (ox/ow)*cw 36 | (100-(-50))/150 * 600 => 600 37 | (-50-(-50))/150 * 600 => 0 38 | ( 0-(-50))/150 * 600 => 200 39 | now, also cx = ox * ( cw/ow ), cw/ow can be the 'xratio', and we have 40 | different ratio y direction, y ratio. in order to keep the pset's 41 | original aspect ratio, only multiply by the lowest of these two ratios. 42 | */ 43 | class PointMapper { 44 | constructor( pset, canvas ) { 45 | this.canvas = canvas; 46 | this.bbox = findBoundingBox( pset ); 47 | //console.log("mapper bbox",this.bbox,pset); 48 | this.psetw = this.bbox.maxx-this.bbox.minx; 49 | this.pseth = this.bbox.maxy-this.bbox.miny; 50 | var wratio = (this.canvas.width-1) / this.psetw; 51 | var hratio = (this.canvas.height-1) / this.pseth; 52 | this.ratio = Math.min(wratio,hratio); 53 | } 54 | x( psetx ) { 55 | return (psetx-this.bbox.minx)*this.ratio; 56 | } 57 | y( psety ) { 58 | return (psety-this.bbox.miny)*this.ratio; 59 | } 60 | } 61 | 62 | function labelmapr( mapr, x, y, offset,labeltxt ) { 63 | mx = mapr.x(x); 64 | my = mapr.y(y); 65 | if (!labelmap[x]) { 66 | labelmap[x]=[]; 67 | labelmap[x][y] = 1; 68 | } else if (!labelmap[x][y]) { 69 | labelmap[x][y] = 1; 70 | } else { 71 | times_used = labelmap[x][y]; 72 | my += offset * times_used; 73 | labelmap[x][y] += 1; 74 | } 75 | if (mx>(mapr.canvas.width-30)) { mx -= 40; } 76 | if (my>(mapr.canvas.height-10)) { my -= 10; } 77 | if (mx<(0+10)) { mx += 10; } 78 | if (my<(0+offset)) { my += 22; } 79 | return [mx,my]; 80 | } 81 | 82 | function findBoundingBox( Pset ) { 83 | var minx = Pset[0][0][0], miny = Pset[0][0][1]; 84 | var maxx = minx, maxy = miny; 85 | for ( var i=0; i0 ) { 142 | ctx.font="1.5em Verdana"; 143 | ctx.fillStyle = "black"; 144 | labeltxt = i+':'+j; 145 | if (labels==2) labeltxt = pointindex; 146 | labelpoint = labelmapr(mapr,point[0],point[1],40,labeltxt); 147 | ctx.fillText( labeltxt, labelpoint[0], labelpoint[1] ); 148 | ctx.fillStyle = fs; 149 | //console.log(i+','+j, mapr.x(point[0]), mapr.y(point[1])); 150 | } 151 | } 152 | ctx.closePath(); 153 | if (fillLevel==1) { 154 | //var fs = 'hsla('+360*(i*3)/(pset.length*3-1)+',100%,50%,0.05)'; 155 | //console.log('fs',i*3,pset.length*3-1,fs ); 156 | hue = 360*(i*3)/(pset.length*3-1) 157 | if (special=="earcut") { hue = (hue + 180) % 360; }; 158 | var fs = 'hsla('+hue+',100%,50%,0.32)'; 159 | ctx.fillStyle = fs; 160 | ctx.strokeStyle = "black"; 161 | ctx.fill(); 162 | } else if (fillLevel==2) { 163 | ctx.fillStyle = "gray"; 164 | ctx.strokeStyle = ctx.fillStyle; 165 | ctx.fill(); 166 | } else { 167 | ctx.strokeStyle = "black"; 168 | } 169 | ctx.stroke(); 170 | } 171 | 172 | } 173 | 174 | // create a function to respond to filename clicks, used by build_testmenu 175 | function mkfunc( testname, canvasid ) { 176 | return function() { 177 | currentTestName = testname; 178 | redraw( canvasid ); 179 | } 180 | }; 181 | 182 | function build_testmenu( canvasid ) { 183 | /* this data comes from the files under viz/testoutput/*.js 184 | and testOutput=[] defined inside viz.html*/ 185 | 186 | names = Object.keys(testOutput); 187 | names.sort(); 188 | 189 | // fill up the 'file' menu on the left hand side of the screen 190 | for (var i in names) { 191 | testname = names[i]; 192 | var menu = document.getElementById("menu"); 193 | var filenode = document.createElement("div"); 194 | filenode.setAttribute( "class", "file" ); 195 | if (testOutput[testname]["pass"]=="0") { 196 | filenode.setAttribute( "class", "file_fail" ); } 197 | filenode.innerHTML = testname; 198 | filenode.addEventListener('click', mkfunc(testname,canvasid) ); 199 | menu.appendChild(filenode); 200 | } 201 | } 202 | 203 | function drawTest( pset, tris, report, canvas, showlabels, fillLevel, special ) 204 | { 205 | ctx = canvas.getContext('2d').clearRect(0,0,canvas.width,canvas.height); 206 | mapr = new PointMapper( pset, canvas ); 207 | triPset = makeTriPset( pset, tris, mapr ); 208 | drawPset( pset, canvas, mapr, showlabels, pset.length, 0 ); 209 | if ( fillLevel == 1 ) { 210 | todraw = triPset.length; 211 | drawPset( triPset, canvas, mapr, false, todraw, fillLevel, special ); 212 | } else if ( fillLevel == 2 ) { 213 | todraw = triPset.length; 214 | drawPset( triPset, canvas, mapr, false, todraw, fillLevel, special ); 215 | } 216 | // for ( var i = 0; i < 6; i ++ ) { 217 | // } 218 | var reportbox = document.getElementById("report"); 219 | reportbox.innerHTML = report + '
' + tris; 220 | } 221 | 222 | function redraw( canvasid ) { 223 | canvas = document.getElementById( "mycan" ); 224 | rpttxt = currentTestName + '\n'+ testOutput[currentTestName]["report"]; 225 | drawTest( testOutput[currentTestName]["json"], 226 | testOutput[currentTestName]["triangles"], 227 | rpttxt, 228 | canvas, 229 | labelsToggle, 230 | fillToggle ); 231 | } 232 | function redrawEarcutVersion ( canvasid ) { 233 | // this section creates earcut.js versions of each test from testOutput 234 | var canvas = document.getElementById( "mycan" ); 235 | var testname = currentTestName; 236 | var jsondata = testOutput[testname]["json"]; 237 | var data = earcut.flatten( jsondata ); 238 | console.log("-------earcut start" ); 239 | var result = earcut(data.vertices, data.holes, data.dimensions); 240 | console.log("-------earcut end"); 241 | var rpttxt = "filename:" + testname + ".json\n num tris" + result.length/3; 242 | 243 | drawTest( jsondata, 244 | result, 245 | rpttxt, 246 | canvas, 247 | labelsToggle, 248 | fillToggle, 249 | "earcut" ); 250 | } 251 | 252 | 253 | function labelsfunc( canvasid ) { labelsToggle = (labelsToggle+1)%3;redraw(canvasid);}; 254 | function trisfunc( canvasid ) { fillToggle = (fillToggle+1)%3; redraw(canvasid); }; 255 | function earcutfunc( canvasid ) { redrawEarcutVersion( canvasid ); } 256 | 257 | function setupControls( canvasid ) { 258 | document.getElementById("labelsbutton").addEventListener('click', 259 | labelsfunc, canvasid ); 260 | document.getElementById("trisbutton").addEventListener('click', 261 | trisfunc, canvasid ); 262 | document.getElementById("earcutbutton").addEventListener('click', 263 | earcutfunc, canvasid ); 264 | } 265 | 266 | function main() { 267 | canvas = setupCanvas("viewer","mycan"); 268 | setupControls( "mycan" ); 269 | 270 | /* 271 | var testPset = [[[661,112],[661,96],[666,96],[666,87],[743,87],[771,87],[771,114],[750,114],[750,113],[742,113],[742,106],[710,106],[710,113],[666,113],[666,112]]]; 272 | var testTris = [14, 0, 1, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 273 | 12, 13, 14, 1, 2, 4, 6, 8, 11, 13, 14, 14, 2, 4, 4, 8, 10, 11, 14, 274 | 4, 4, 10, 11]; 275 | var testReport = "default shape, " + testTris.length + " triangles"; 276 | drawTest( testPset, testTris, testReport, canvas ); 277 | */ 278 | 279 | build_testmenu( canvas ); 280 | 281 | currentTestName = Object.keys(testOutput)[0]; 282 | console.log(currentTestName); 283 | redraw( canvas.id ); 284 | } 285 | 286 | main(); 287 | --------------------------------------------------------------------------------