1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
//! Generate hatching and dotted patterns in a path.
//!
//! <svg viewBox="0 0 426.95679 426.52454" height="426.52454" width="426.95679">
//! <path style="fill:none;stroke:#4400aaff;stroke-linecap:round;stroke-opacity:1" d="m 16.917871,135.64793 4.76841,-7.42638 m 15.72455,-24.48953 7.19236,-11.20143 m 17.03683,-26.53329 2.03357,-3.16709 m -43.99289,77.76893 8.64512,-13.46397 m 11.54821,-17.98526 10.54139,-16.41727 m 12.25127,-19.08019 7.6854,-11.96933 m -65.1770704,110.76136 3.09963,-4.8274 m 14.5495904,-22.65963 12.13142,-18.89358 m 7.38155,-11.49608 13.89046,-21.63311 m 8.03079,-12.50722 11.25737,-17.53231 M 7.4520506,178.15229 16.233711,164.47567 m 9.73405,-15.15991 15.61774,-24.32318 m 3.21489,-5.00689 17.23952,-26.84896 m 3.81033,-5.93424 14.82933,-23.0953 m 12.08295,-18.81808 6.19302,-9.64507 m -87.78445,145.97029 12.86975,-20.04347 m 5.07048,-7.89678 56.732,-88.35488 M 93.067691,54.06792 103.88779,37.21663 M 14.890111,185.07637 108.48646,39.30868 m -106.9825894,175.8696 6.1426,-9.56656 M 18.609141,188.53841 113.08513,41.40074 M 4.8823606,219.17067 17.503941,199.51369 m 4.53224,-7.05853 95.647629,-148.96235 m 9.54351,-14.86313 7.69031,-11.97696 M 9.1329106,221.80491 124.10857,42.74089 m 1.10584,-1.72223 14.34702,-22.34415 M 13.383461,224.43915 49.891941,167.58057 M 59.162251,153.14292 143.62441,21.60089 M 17.634011,227.07339 52.435581,172.87314 M 65.108631,153.13604 147.68737,24.52727 M 5.4365906,255.32381 13.562901,242.66784 m 8.07471,-12.57562 34.65211,-53.96748 m 13.40238,-20.87295 8.31907,-12.95619 M 97.266581,112.30708 151.75033,27.45366 M 8.8376206,259.2811 61.260551,177.63723 m 11.90917,-18.54743 7.56957,-11.78894 M 113.60671,96.1129 156.45597,29.37913 m 7.69973,-11.9916 7.9425,-12.3697198 M 13.629031,261.07299 l 54.43399,-84.7759 m 6.63851,-10.33888 8.7659,-13.65207 M 125.66903,86.58105 177.17848,6.3598202 M 18.420461,262.86487 58.610571,200.27248 m 4.44395,-6.92105 23.14103,-36.04003 M 136.10735,79.57838 180.77656,10.01022 M 23.211891,264.65676 58.097511,210.32561 m 13.26663,-20.66157 17.55955,-27.34736 M 145.72273,73.85741 184.29598,13.78314 M 28.003291,266.44865 58.350681,219.18539 m 21.32309,-33.20874 11.97804,-18.65471 m 62.669079,-97.60129 33.4945,-52.1646 M 16.948341,292.91978 58.873831,227.6247 m 29.62346,-46.13579 3.92546,-6.11354 M 162.58722,66.10066 191.33481,21.32896 m -171.353389,276.12116 39.88577,-62.1184 m 50.933989,-79.32498 0.21438,-0.33389 M 170.32891,63.2978 209.29553,2.6108702 M 25.045171,298.81787 61.144811,242.59601 m 47.736709,-74.3455 3.02247,-4.70723 m 17.24689,-26.86043 3.24556,-5.05466 M 177.78227,60.94394 215.94693,1.5060002 M 30.425081,299.69324 62.757681,249.3382 m 28.96487,-45.1101 58.780339,-91.54495 M 184.78195,59.29668 219.61175,5.0524702 M 35.804981,300.56863 64.670691,255.61295 m 24.49552,-38.14951 51.312939,-79.91517 m 4.43283,-6.90372 14.95169,-23.28589 m 28.469,-44.33783 34.19392,-53.2538598 M 41.184881,301.44401 66.834971,261.49634 m 21.61322,-33.66056 41.973929,-65.37054 m 9.16543,-14.27431 5.67737,-8.84199 m 13.67266,-21.2939 10.28687,-16.02086 m 10.81567,-16.84441 0.21148,-0.32935 m 11.63179,-18.11544 8.60293,-13.39827 m 9.33176,-14.53336 15.62335,-24.33192 M 44.495111,305.54271 69.021671,267.34484 m 18.83868,-29.33949 31.051989,-48.36062 m 9.83742,-15.32086 8.32416,-12.96411 m 4.54095,-7.07212 8.43584,-13.13804 m 17.37519,-27.06025 11.15935,-17.37966 m 5.46833,-8.51642 0.95594,-1.48879 m 10.4246,-16.23535 7.61545,-11.86035 M 215.71354,38.8858 228.35627,19.19592 M 35.810801,328.3218 71.498781,272.74106 m 19.43484,-30.26797 18.545179,-28.88242 m 4.36969,-6.80537 9.34892,-14.56009 m 21.56425,-33.58433 11.89295,-18.52217 m 19.2596,-29.99505 13.55212,-21.10618 m 9.51851,-14.8242 7.93137,-12.35238 M 220.29754,41.00072 232.65892,21.74901 M 38.763911,332.9767 73.975901,278.13728 m 15.58755,-24.27619 19.548979,-30.44573 m 8.7471,-13.62281 7.77877,-12.11472 m 58.25286,-90.72345 9.43078,-14.68757 m 9.21363,-14.34938 9.36275,-14.58162 M 223.77927,44.83234 246.19634,9.9198102 M 44.088901,333.93757 76.489421,283.47678 m 11.70385,-18.22769 23.218229,-36.16026 m 9.78596,-15.24072 14.38341,-22.40083 m 52.63269,-81.97057 8.02567,-12.49923 M 206.37052,81.19893 218.72321,61.96074 M 225.24363,51.8058 255.23865,5.0913202 M 50.166661,333.7261 l 29.1109,-45.33754 m 7.8478,-12.22221 29.216639,-45.50222 m 7.51955,-11.711 18.81689,-29.30559 m 34.38877,-53.55733 20.50304,-31.9316 M 211.16916,82.97957 259.18233,8.2034702 M 56.244421,333.51462 l 25.8213,-40.21428 m 5.91775,-9.21634 18.638969,-29.02848 m 11.33638,-17.65537 14.58842,-22.72011 m 5.0953,-7.93547 9.34598,-14.55548 m 46.35021,-72.1862 2.33258,-3.63277 m 22.48888,-35.02436 43.31105,-67.45295 m -199.149059,319.41035 22.5919,-35.1848 m 6.02779,-9.38771 17.543699,-27.32271 m 18.17597,-28.30738 5.69322,-8.86667 m 12.68129,-19.74994 6.15477,-9.58548 M 232.46766,68.31727 263.65778,19.74155 M 65.946681,336.91243 88.007371,302.55492 m 5.89287,-9.17761 16.435209,-25.59631 m 21.91956,-34.13768 2.40453,-3.74485 M 244.02783,59.56746 265.84432,25.59027 M 63.181741,350.47264 91.100661,306.9915 m 5.8981,-9.18576 17.055329,-26.56209 m 22.20917,-34.58874 2.60102,-4.05085 M 249.17631,60.80325 269.54787,29.07641 M 62.078481,361.44493 94.318721,311.23375 m 5.949239,-9.26541 18.31023,-28.5165 m 21.69332,-33.78533 2.89003,-4.50095 M 254.32479,62.03905 277.74639,25.56209 M 65.783721,364.92844 97.722371,315.18695 m 5.814789,-9.056 19.56515,-30.47091 m 0.60177,-0.93721 4.03273,-6.2806 m 16.54296,-25.76413 3.22669,-5.02527 M 259.35075,63.46565 288.78948,17.61755 M 72.087211,364.36542 101.12603,319.14013 m 5.81347,-9.05394 26.01671,-40.51862 m 15.66833,-24.40198 3.59853,-5.60438 m 42.09482,-65.55879 16.14551,-25.14514 M 264.20251,65.16356 295.00926,17.18489 M 79.089411,362.71422 107.23187,318.88493 m 6.66792,-10.38466 24.34458,-37.91444 m 14.88199,-23.17733 4.05268,-6.31166 m 44.62071,-69.49265 4.09624,-6.37952 m 4.2394,-6.60247 6.55205,-10.20422 M 269.05426,66.86149 298.37928,21.19047 M 86.091621,361.063 114.12325,317.40632 m 6.73682,-10.49197 22.81133,-35.52655 m 14.32574,-22.31102 4.52698,-7.05035 m 45.67307,-71.13159 2.27191,-3.5383 m 1.09414,-1.70401 10.58327,-16.48248 M 273.80468,68.71724 299.66331,28.44479 M 91.406731,362.03931 121.01462,315.92772 m 6.69359,-10.42463 21.87593,-34.06974 m 13.36364,-20.81265 4.92143,-7.66467 m 46.36923,-72.2158 11.73478,-18.27584 M 278.3734,70.85594 300.8637,35.82938 M 93.138621,368.5961 107.29716,346.54549 m 10.22876,-15.93035 10.38009,-16.16604 m 5.89013,-9.17333 22.33654,-34.7871 m 11.93778,-18.59199 5.14384,-8.01106 m 46.43428,-72.3171 9.38564,-14.61727 m 53.90792,-83.95662 19.55403,-30.4536 M 92.798531,378.37984 110.07167,351.47851 m 13.01617,-20.27146 10.58512,-16.48536 m 5.23447,-8.1522 24.35014,-37.92309 m 9.403,-14.64431 7.18176,-11.18494 m 43.17229,-67.23686 0.93037,-1.44895 m 6.00743,-9.35603 2.14279,-3.3372 M 287.44428,75.23703 307.24821,44.39424 M 93.152171,387.08317 114.10248,354.455 m 13.38651,-20.84826 10.50517,-16.36084 m 5.19549,-8.0915 26.15125,-40.72817 m 7.99974,-12.45883 9.5233,-14.83168 M 291.73728,77.80517 315.65006,40.56323 M 97.011861,390.32612 119.25926,355.67785 m 11.37353,-17.71322 10.40149,-16.19936 m 5.51866,-8.59479 24.37416,-37.96052 M 296.03029,80.37327 324.05191,36.73219 m -220.45589,352.5938 23.58158,-36.72612 m 4.11996,-6.41648 11.44786,-17.82897 m 6.21521,-9.67963 24.77182,-38.57983 M 300.29741,82.98172 330.29742,36.25946 m -218.29773,349.23267 32.22576,-50.18864 m 6.51485,-10.14629 27.31203,-42.53597 M 304.31608,85.97709 333.86894,39.95123 M 120.36976,381.7106 145.70547,342.25256 m 6.58476,-10.25516 28.57321,-44.50013 m 92.30511,-143.75671 13.53183,-21.07458 M 308.33477,88.97242 334.04904,48.92483 M 124.782,384.093 147.18549,349.20165 m 6.65466,-10.36403 35.73428,-55.65284 m 46.36882,-72.21516 1.93514,-3.01381 m 37.18208,-57.90765 13.25393,-20.64177 m 15.36368,-23.9275 1.06312,-1.65573 m 7.61225,-11.85537 21.3604,-33.26686 M 126.11389,391.2728 150.16858,353.80983 m 5.60544,-8.72997 38.89353,-60.57306 m 36.57074,-56.95556 7.29288,-11.35799 m 38.09409,-59.32803 7.69672,-11.98693 m 24.45201,-38.08176 2.09358,-3.26054 m 5.23982,-8.16055 19.71658,-30.70676 m -208.50969,333.9887 27.49927,-42.82758 m 5.6849,-8.85371 52.15477,-81.22625 m 18.1742,-28.30463 8.35653,-13.01452 m 44.01287,-68.546 1.86799,-2.90922 m 27.97491,-43.56833 2.93522,-4.57134 m 3.87237,-6.03085 21.56255,-33.5817 m -212.69336,340.5044 30.94744,-48.1978 m 5.55894,-8.65755 57.21349,-89.10472 m 8.60265,-13.39784 5.56629,-8.66899 m 79.54238,-123.87993 3.93135,-6.12269 m 3.50818,-5.46367 24.82088,-38.65623 m -216.07779,345.7753 32.1906,-50.1339 m 5.67861,-8.8439 54.14482,-84.32556 m 92.62127,-144.2491 6.02091,-9.37698 m 4.09718,-6.381 28.32265,-44.10991 M 139.07782,408.099 169.37789,360.90941 m 5.87659,-9.15226 49.94232,-77.78053 m 71.70382,-111.67209 27.4233,-42.70925 m 6.21029,-9.67196 30.92904,-48.16912 m -211.31211,338.35319 24.35064,-37.92387 m 5.85877,-9.1245 47.33492,-73.71979 M 299.6699,167.2457 323.23044,130.55235 m 10.75428,-16.74881 31.06161,-48.37559 m -207.25591,332.03602 21.86761,-34.05676 m 6.0729,-9.45798 45.82252,-71.36435 m 71.67605,-111.62884 3.51227,-5.47005 m 30.44726,-47.4188 26.19055,-40.78937 M 161.24184,401.3428 184.81428,364.6309 m 6.28703,-9.79147 35.83827,-55.8148 m 80.31088,-125.0768 1.02014,-1.58876 m 32.0619,-49.93346 20.88416,-32.52516 m -197.78591,317.2874 26.832,-41.78836 m 6.32652,-9.85297 25.73644,-40.08214 M 343.47599,126.78401 365.10492,93.09892 m -199.48526,319.93399 30.12047,-46.90985 m 6.53635,-10.17976 30.87191,-48.08016 M 346.39856,131.48643 371.18085,92.89032 M 167.99084,418.59407 201.2362,366.8175 m 6.72748,-10.47743 23.17367,-36.09084 M 344.64054,143.47849 377.25676,92.68171 M 172.1411,421.38452 207.06653,366.99139 m 6.75556,-10.52116 23.81435,-37.08866 M 333.00361,170.856 383.33271,92.47308 M 182.37479,414.70056 212.89683,367.1653 m 6.95451,-10.831 18.3638,-28.59992 m 95.8752,-149.31679 54.3538,-84.65102 m -193.7208,310.95634 24.14333,-37.60099 m 7.01392,-10.92354 12.91325,-20.11121 m 98.70421,-153.7227 53.5309,-83.36945 M 198.79978,407.62831 225.09536,366.6754 m 7.11168,-11.07581 8.85179,-13.78584 m 100.83693,-157.04422 9.6456,-15.02212 m 10.55584,-16.43975 20.50876,-31.9405 m -180.88781,290.97016 29.60588,-46.10845 m 7.32108,-11.40191 9.93724,-15.47633 m 97.93635,-152.52682 7.90492,-12.3112 m 13.16554,-20.5041 18.56539,-28.91388 M 204.6365,417.04632 237.93722,365.18353 m 7.29823,-11.36632 6.34851,-9.88722 m 99.55768,-155.0519 7.39441,-11.51609 m 13.34463,-20.78305 19.65602,-30.61244 m -183.98183,295.7888 37.07456,-57.74022 m 7.59527,-11.82892 2.36085,-3.67682 m 101.17903,-157.57698 8.07631,-12.57813 m 11.05392,-17.21544 22.02405,-34.30044 M 211.40154,425.01854 251.60996,362.39766 M 360.3875,192.98665 372.22752,174.54694 m 3.02383,-4.70935 27.04965,-42.12735 M 230.25377,404.91202 258.86082,360.35919 M 365.01044,195.04094 407.29252,129.19052 M 235.83891,405.46775 266.415,357.84833 m 15.33285,-23.87951 12.22403,-19.0378 m 74.26166,-115.65568 41.76097,-65.03884 m -170.63804,275.00707 35.01145,-54.52709 m 4.41371,-6.87397 20.78689,-32.37365 m 69.08786,-107.59797 30.629,-47.70184 m -156.41139,252.85037 61.91687,-96.42981 m 63.87725,-99.48292 35.40996,-55.14773 m -157.68652,254.83628 47.343,-73.73236 m 6.72963,-10.48077 9.54903,-14.87174 m 57.89731,-90.1697 40.96021,-63.79177 m -158.8121,256.58928 45.22961,-70.44096 m 11.9926,-18.67736 7.95472,-12.38875 m 50.92941,-79.31784 47.49845,-73.97447 m -158.1344,255.53382 6.34924,-9.88836 m 9.22449,-14.36628 27.68934,-43.1236 m 13.42834,-20.91339 8.23748,-12.82912 m 41.75033,-65.02229 56.18032,-87.49567 m -142.90385,231.81363 27.91611,-43.47677 m 12.64869,-19.69916 13.491,-21.01099 m 23.11816,-36.0044 52.68547,-82.05275 m 9.31483,-14.507 6.95838,-10.83704 m -142.07071,230.51615 29.8416,-46.47554 m 9.16309,-14.27067 91.04352,-141.7919 M 283.60855,405.10359 413.84556,202.27148 m -126.17511,205.76015 13.74482,-21.40628 m 2.18013,-3.39537 114.50084,-178.3245 m -125.54604,204.78047 6.84019,-10.65298 m 10.21186,-15.90402 95.23334,-148.31715 m 5.47649,-8.52911 12.03486,-18.74322 m -108.15005,177.68781 94.35577,-146.9504 m 11.60598,-18.07524 5.29428,-8.24535 m -106.66137,175.36935 14.69993,-22.89379 m 1.17445,-1.8291 77.60382,-120.8608 m -88.88356,147.68201 10.40649,-16.20712 m 7.69533,-11.98479 56.51966,-88.02413 m 5.54183,-8.63091 12.43732,-19.36999 m -87.53496,145.58172 5.64202,-8.78693 m 12.55688,-19.55618 14.45803,-22.51704 m 4.25849,-6.63222 16.87144,-26.27569 m 3.65263,-5.68865 15.25238,-23.75418 m 10.22549,-15.92526 8.33469,-12.9805 m -67.8904,114.98712 10.8902,-16.96048 m 8.47408,-13.1976 13.52984,-21.0715 m 7.81816,-12.17605 11.754,-18.30579 m 15.40495,-23.99178 1.54604,-2.40782 m -64.25453,109.3246 7.32237,-11.40394 m 12.68967,-19.76297 10.18827,-15.8673 m 11.98366,-18.66346 8.25565,-12.8574 m -24.61707,47.59291 6.8467,-10.6631 m 16.34302,-25.45274 4.05302,-6.3122"/>
//! </svg>
//!
//! # Example
//!
//! ```ignore
//! // Generate a path representing a hatching of the original path.
//! let mut hatches = Path::builder();
//! let mut hatcher = Hatcher::new();
//! hatcher.hatch_path(
//! original_path.iter(),
//! &HatchingOptions::DEFAULT,
//! &mut RegularHatchingPattern {
//! interval: 1.0,
//! callback: &mut|segment: &HatchSegment| {
//! hatches.add_line_segment(&LineSegment {
//! from: segment.a.position,
//! to: segment.b.position,
//! });
//! },
//! },
//! );
//! let hatched_path = hatches.build();
//! ```
use crate::geom::LineSegment;
use crate::math::{point, vector, Angle, Point, Rotation, Vector};
use crate::path::builder::{Build, PathBuilder};
use crate::path::private::DebugValidator;
use crate::path::{self, EndpointId, PathEvent};
use std::marker::PhantomData;
use std::cmp::Ordering;
use std::f32;
use std::mem;
/// Parameters for the hatcher.
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(
feature = "serialization",
derive(serde::Serialize, serde::Deserialize)
)]
#[non_exhaustive]
pub struct HatchingOptions {
/// Maximum allowed distance to the path when building an approximation.
///
/// See [Flattening and tolerance](index.html#flattening-and-tolerance).
///
/// Default value: `HatchingOptions::DEFAULT_TOLERANCE`.
pub tolerance: f32,
/// Angle between the hatching pattern and the x axis.
///
/// Default value: `HatchingOptions::ANGLE`.
pub angle: Angle,
/// Whether to compute the tangent of the outline where it meets the hatching pattern.
///
/// Default value: `true, .
pub compute_tangents: bool,
/// The origin of the rotated uv coordinates.
pub uv_origin: Point,
}
impl Default for HatchingOptions {
fn default() -> Self {
Self::DEFAULT
}
}
impl HatchingOptions {
/// Default flattening tolerance.
pub const DEFAULT_TOLERANCE: f32 = 0.1;
/// Default hatching angle.
pub const DEFAULT_ANGLE: Angle = Angle { radians: 0.0 };
pub const DEFAULT_UV_ORIGIN: Point = Point {
x: 0.0,
y: 0.0,
_unit: PhantomData,
};
pub const DEFAULT: Self = HatchingOptions {
tolerance: Self::DEFAULT_TOLERANCE,
angle: Self::DEFAULT_ANGLE,
compute_tangents: true,
uv_origin: Self::DEFAULT_UV_ORIGIN,
};
#[inline]
pub fn tolerance(tolerance: f32) -> Self {
Self::DEFAULT.with_tolerance(tolerance)
}
#[inline]
pub fn angle(angle: Angle) -> Self {
Self::DEFAULT.with_angle(angle)
}
#[inline]
pub fn with_tolerance(mut self, tolerance: f32) -> Self {
self.tolerance = tolerance;
self
}
#[inline]
pub fn with_angle(mut self, angle: Angle) -> Self {
self.angle = angle;
self
}
#[inline]
pub fn with_tangents(mut self, compute_tangents: bool) -> Self {
self.compute_tangents = compute_tangents;
self
}
}
/// Parameters for generating dot patterns.
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(
feature = "serialization",
derive(serde::Serialize, serde::Deserialize)
)]
#[non_exhaustive]
pub struct DotOptions {
/// Maximum allowed distance to the path when building an approximation.
///
/// See [Flattening and tolerance](index.html#flattening-and-tolerance).
///
/// Default value: `HatchingOptions::DEFAULT_TOLERANCE`.
pub tolerance: f32,
/// Angle between the hatching pattern and the x axis.
///
/// Default value: `HatchingOptions::ANGLE`.
pub angle: Angle,
/// The origin of the rotated uv coordinates.
pub uv_origin: Point,
}
impl Default for DotOptions {
fn default() -> Self {
Self::DEFAULT
}
}
impl DotOptions {
/// Default flattening tolerance.
pub const DEFAULT_TOLERANCE: f32 = 0.1;
/// Default inclination of the dot pattern.
pub const DEFAULT_ANGLE: Angle = Angle { radians: 0.0 };
pub const DEFAULT_UV_ORIGIN: Point = Point {
x: 0.0,
y: 0.0,
_unit: PhantomData,
};
pub const DEFAULT: Self = DotOptions {
tolerance: Self::DEFAULT_TOLERANCE,
angle: Self::DEFAULT_ANGLE,
uv_origin: Self::DEFAULT_UV_ORIGIN,
};
#[inline]
pub fn tolerance(tolerance: f32) -> Self {
Self::DEFAULT.with_tolerance(tolerance)
}
#[inline]
pub fn angle(angle: Angle) -> Self {
Self::DEFAULT.with_angle(angle)
}
#[inline]
pub fn with_tolerance(mut self, tolerance: f32) -> Self {
self.tolerance = tolerance;
self
}
#[inline]
pub fn with_angle(mut self, angle: Angle) -> Self {
self.angle = angle;
self
}
}
type Edge = LineSegment<f32>;
pub struct HatchSegment {
/// Left endpoint.
pub a: HatchEndpoint,
/// Right endpoint.
pub b: HatchEndpoint,
/// Index of the current row.
pub row: u32,
/// Rotated position along a direction perpendicular to the hatching pattern.
///
/// This position is relative to `uv_origin` specified in the `HatchingOptions`.
pub v: f32,
}
pub struct HatchEndpoint {
/// Position in world space of the point.
pub position: Point,
/// Tangent of the path edge at this point (pointing downward).
pub tangent: Vector,
/// Rotated position along the direction of the hatching pattern.
///
/// This position is relative to `uv_origin` specified in the `HatchingOptions`.
pub u: f32,
}
/// The output of `Hatcher::hatch_path`.
///
/// Implement this trait to create custom hatching patterns.
pub trait HatchBuilder {
/// Called for each hatch segment.
fn add_segment(&mut self, segment: &HatchSegment);
/// Specifies the distance between each row of the pattern.
fn next_offset(&mut self, row_idx: u32) -> f32;
}
pub struct Dot {
/// World-space position of the dot.
pub position: Point,
/// Rotated position along an axis parallel to the rows of the pattern.
pub u: f32,
/// Rotated position along an axis parallel to the columns of the pattern.
pub v: f32,
/// Index of the current column.
pub column: u32,
/// Index of the current row.
pub row: u32,
}
/// The output of `Hatcher::dot_path`.
///
/// Implement this trait to create custom dot patterns.
pub trait DotBuilder {
/// Offset of the first dot after a left edge.
fn first_column_offset(&mut self, _row: u32) -> f32 {
0.0
}
/// Whether and how much to align the dots for a given row.
fn alignment(&mut self, _row: u32) -> Option<f32> {
None
}
/// Called for each row of dots.
fn next_row_offset(&mut self, column: u32, row: u32) -> f32;
/// Distance between each dot in a given row.
fn next_column_offset(&mut self, column: u32, row: u32) -> f32;
/// Called for each dot.
fn add_dot(&mut self, dot: &Dot);
}
/// A `DotBuilder` implementation for dot patterns with constant intervals.
pub struct RegularDotPattern<Cb: FnMut(&Dot)> {
/// Minimum distance between dots in a given column.
pub column_interval: f32,
/// Minimum distance between dots in a given row.
pub row_interval: f32,
/// A callback invoked for each dot.
pub callback: Cb,
}
/// A context object that can fill a path with a hatching or dot pattern.
pub struct Hatcher {
events: HatchingEvents,
active_edges: Vec<Edge>,
transform: Rotation,
compute_tangents: bool,
segment: HatchSegment,
uv_origin: Point,
}
impl Default for Hatcher {
fn default() -> Self {
Self::new()
}
}
impl Hatcher {
/// Constructor.
pub fn new() -> Self {
Hatcher {
events: HatchingEvents::new(),
active_edges: Vec::new(),
transform: Rotation::identity(),
compute_tangents: true,
segment: HatchSegment {
a: HatchEndpoint {
position: point(0.0, 0.0),
tangent: vector(f32::NAN, f32::NAN),
u: 0.0,
},
b: HatchEndpoint {
position: point(0.0, 0.0),
tangent: vector(f32::NAN, f32::NAN),
u: 0.0,
},
row: 0,
v: 0.0,
},
uv_origin: point(0.0, 0.0),
}
}
/// Generate hatches for a path.
pub fn hatch_path<Iter>(
&mut self,
it: Iter,
options: &HatchingOptions,
output: &mut dyn HatchBuilder,
) where
Iter: Iterator<Item = PathEvent>,
{
let mut events = mem::replace(&mut self.events, HatchingEvents::new());
events.set_path(options.tolerance, options.angle, it);
self.hatch(&events, options, output);
self.events = events;
}
/// Generate dots for a path.
pub fn dot_path<Iter>(&mut self, it: Iter, options: &DotOptions, output: &mut dyn DotBuilder)
where
Iter: Iterator<Item = PathEvent>,
{
let mut events = mem::replace(&mut self.events, HatchingEvents::new());
events.set_path(options.tolerance, options.angle, it);
self.dot(&events, options, output);
self.events = events;
}
fn hatch(
&mut self,
events: &HatchingEvents,
options: &HatchingOptions,
output: &mut dyn HatchBuilder,
) {
self.transform = Rotation::new(-options.angle);
self.uv_origin = Rotation::new(options.angle).transform_point(options.uv_origin);
self.active_edges.clear();
self.segment.row = 0;
self.segment.a.tangent = vector(f32::NAN, f32::NAN);
self.segment.b.tangent = vector(f32::NAN, f32::NAN);
self.compute_tangents = options.compute_tangents;
let mut y = events.edges.first().unwrap().from.y + output.next_offset(0);
let mut y_max = y;
for edge in &events.edges {
let y2 = edge.from.y;
while y < y2 {
self.hatch_line(y, output);
let offset = output.next_offset(self.segment.row);
y += offset;
if offset <= 0.0 {
return;
}
}
y_max = f32::max(y_max, edge.to.y);
self.update_sweep_line(edge);
}
while y < y_max {
self.hatch_line(y, output);
let offset = output.next_offset(self.segment.row);
y += offset;
if offset <= 0.0 {
return;
}
}
}
fn dot(&mut self, events: &HatchingEvents, options: &DotOptions, output: &mut dyn DotBuilder) {
let mut dotted = HatchesToDots {
builder: output,
column: 0,
};
let options = HatchingOptions {
tolerance: options.tolerance,
angle: options.angle,
uv_origin: options.uv_origin,
compute_tangents: false,
};
self.hatch(events, &options, &mut dotted);
}
fn update_sweep_line(&mut self, edge: &Edge) {
self.active_edges
.retain(|e| compare_positions(e.to, edge.from) != Ordering::Less);
self.active_edges.push(*edge);
}
fn hatch_line(&mut self, y: f32, output: &mut dyn HatchBuilder) {
self.active_edges
.sort_by_key(|e| Ordered(e.solve_x_for_y(y)));
let mut inside = false;
let mut prev_x = f32::NAN;
let mut prev_tangent = vector(f32::NAN, f32::NAN);
let mut tangent = vector(f32::NAN, f32::NAN);
self.segment.v = y - self.uv_origin.y;
for active_edge in &self.active_edges {
if active_edge.to.y <= y {
// TODO: we don't remove the edges during merge events so we can
// end up with extra edges that end above the sweep line and have
// to skip them. It would be better to properly manage the sweep
// line instead!
continue;
}
let x = active_edge.solve_x_for_y(y);
if self.compute_tangents {
tangent = self
.transform
.transform_vector(active_edge.to_vector())
.normalize();
}
if inside {
self.segment.a.position = self.transform.transform_point(point(prev_x, y));
self.segment.b.position = self.transform.transform_point(point(x, y));
self.segment.a.u = prev_x - self.uv_origin.x;
self.segment.b.u = x - self.uv_origin.x;
if self.compute_tangents {
self.segment.a.tangent = prev_tangent;
self.segment.b.tangent = tangent;
}
output.add_segment(&self.segment);
}
inside = !inside;
prev_x = x;
prev_tangent = tangent;
}
self.segment.row += 1;
}
}
struct HatchingEvents {
edges: Vec<Edge>,
}
impl HatchingEvents {
fn new() -> Self {
HatchingEvents { edges: Vec::new() }
}
}
struct EventsBuilder {
edges: Vec<Edge>,
angle: Angle,
first: Point,
current: Point,
tolerance: f32,
validator: DebugValidator,
}
impl EventsBuilder {
fn new(angle: Angle, tolerance: f32) -> Self {
EventsBuilder {
edges: Vec::new(),
angle,
first: point(0.0, 0.0),
current: point(0.0, 0.0),
tolerance,
validator: DebugValidator::new(),
}
}
fn add_edge(&mut self, from: Point, to: Point) {
if from == to {
return;
}
let rotation = Rotation::new(self.angle);
let mut from = rotation.transform_point(from);
let mut to = rotation.transform_point(to);
if compare_positions(from, to) == Ordering::Greater {
mem::swap(&mut from, &mut to);
}
self.edges.push(Edge { from, to });
}
}
impl Build for EventsBuilder {
type PathType = HatchingEvents;
fn build(mut self) -> HatchingEvents {
self.validator.build();
self.first = point(0.0, 0.0);
self.current = point(0.0, 0.0);
self.edges.sort_by(|a, b| compare_positions(a.from, b.from));
HatchingEvents {
edges: mem::take(&mut self.edges),
}
}
}
impl PathBuilder for EventsBuilder {
fn begin(&mut self, to: Point) -> EndpointId {
self.validator.begin();
self.first = to;
self.current = to;
EndpointId::INVALID
}
fn end(&mut self, _close: bool) {
self.validator.end();
self.add_edge(self.current, self.first);
}
fn line_to(&mut self, to: Point) -> EndpointId {
self.validator.edge();
self.add_edge(self.current, to);
self.current = to;
EndpointId::INVALID
}
fn quadratic_bezier_to(&mut self, ctrl: Point, to: Point) -> EndpointId {
path::private::flatten_quadratic_bezier(self.tolerance, self.current, ctrl, to, self)
}
fn cubic_bezier_to(&mut self, ctrl1: Point, ctrl2: Point, to: Point) -> EndpointId {
path::private::flatten_cubic_bezier(self.tolerance, self.current, ctrl1, ctrl2, to, self)
}
}
impl HatchingEvents {
pub fn set_path<Iter>(&mut self, tolerance: f32, angle: Angle, it: Iter)
where
Iter: Iterator<Item = PathEvent>,
{
self.edges.clear();
let mut builder = EventsBuilder::new(angle, tolerance);
builder.edges = mem::take(&mut self.edges);
for evt in it {
builder.path_event(evt);
}
mem::swap(self, &mut builder.build());
}
}
#[derive(PartialEq)]
struct Ordered(f32);
impl Eq for Ordered {}
impl PartialOrd for Ordered {
fn partial_cmp(&self, other: &Ordered) -> Option<Ordering> {
if self.0 > other.0 {
return Some(Ordering::Greater);
}
if self.0 < other.0 {
return Some(Ordering::Less);
}
Some(Ordering::Equal)
}
}
impl Ord for Ordered {
fn cmp(&self, other: &Ordered) -> Ordering {
self.partial_cmp(other).unwrap()
}
}
fn compare_positions(a: Point, b: Point) -> Ordering {
if a.y > b.y {
return Ordering::Greater;
}
if a.y < b.y {
return Ordering::Less;
}
if a.x > b.x {
return Ordering::Greater;
}
if a.x < b.x {
return Ordering::Less;
}
Ordering::Equal
}
impl<Cb: FnMut(&Dot)> DotBuilder for RegularDotPattern<Cb> {
fn alignment(&mut self, _row: u32) -> Option<f32> {
Some(self.column_interval)
}
fn next_row_offset(&mut self, _column: u32, _row: u32) -> f32 {
self.row_interval
}
fn next_column_offset(&mut self, _column: u32, _row: u32) -> f32 {
self.column_interval
}
fn add_dot(&mut self, dot: &Dot) {
(self.callback)(dot)
}
}
/// A `HatchBuilder` implementation for hatching patterns with constant intervals.
pub struct RegularHatchingPattern<Cb: FnMut(&HatchSegment)> {
/// The distance between each row of hatches.
pub interval: f32,
/// A callback invoked for each segment.
pub callback: Cb,
}
impl<Cb: FnMut(&HatchSegment)> HatchBuilder for RegularHatchingPattern<Cb> {
fn next_offset(&mut self, _row: u32) -> f32 {
self.interval
}
fn add_segment(&mut self, segment: &HatchSegment) {
(self.callback)(segment)
}
}
// Converts a hatching pattern into a dotted pattern.
struct HatchesToDots<'l> {
builder: &'l mut dyn DotBuilder,
column: u32,
}
impl<'l> HatchBuilder for HatchesToDots<'l> {
fn next_offset(&mut self, row: u32) -> f32 {
let val = self.builder.next_row_offset(self.column, row);
self.column = 0;
val
}
fn add_segment(&mut self, segment: &HatchSegment) {
let row = segment.row;
let mut u = self.builder.first_column_offset(row);
let u_start = segment.a.u;
if let Some(d) = self.builder.alignment(row) {
let m = modulo(u_start, d);
if m != 0.0 {
u += d - m;
}
}
let a = segment.a.position;
let ab = (segment.b.position - a).normalize();
while u_start + u < segment.b.u {
self.builder.add_dot(&Dot {
position: a + ab * u,
u: segment.a.u + u,
v: segment.v,
column: self.column,
row,
});
self.column += 1;
let du = self.builder.next_column_offset(self.column, row);
if du <= 0.0 {
return;
}
u += du;
}
}
}
fn modulo(a: f32, m: f32) -> f32 {
if a >= 0.0 {
a % m
} else {
m + (a % m)
}
}
#[test]
fn simple_hatching() {
use lyon_path::Path;
let mut original_path = Path::builder();
original_path.begin(point(0.0, 0.0));
original_path.line_to(point(10.0, 0.0));
original_path.line_to(point(10.0, 10.0));
original_path.line_to(point(0.0, 10.0));
original_path.end(true);
let original_path = original_path.build();
let mut hatches = Path::builder();
let mut hatcher = Hatcher::new();
hatcher.hatch_path(
original_path.iter(),
&HatchingOptions::DEFAULT,
&mut RegularHatchingPattern {
interval: 1.0,
callback: &mut |segment: &HatchSegment| {
hatches.add_line_segment(&LineSegment {
from: segment.a.position,
to: segment.b.position,
});
},
},
);
let _ = hatches.build();
}