Ticket #18138: 18138.3.patch
| File 18138.3.patch, 32.3 KB (added by , 6 years ago) |
|---|
-
data/defaultpresets.xml
7580 7580 <role key="to" text="to way" requisite="required" count="1" type="way" /> 7581 7581 </roles> 7582 7582 </item> <!-- Turn Restriction --> 7583 <item name="Lane Connectivity" type="relation" preset_name_label="true" icon="presets/transport/way/relation_connectivity.svg"> 7584 <link wiki="Relation:connectivity" /> 7585 <space /> 7586 <key key="type" value="connectivity" /> 7587 <optional> 7588 <text key="connectivity" text="Lane Connectivity" /> 7589 </optional> 7590 <roles> 7591 <role key="from" text="from way" requisite="required" count="1" type="way" /> 7592 <role key="via" text="via node or ways" requisite="required" type="way,node" /> 7593 <role key="to" text="to way" requisite="required" count="1" type="way" /> 7594 </roles> 7595 </item> <!-- Lane Connectivity --> 7583 7596 <item name="Enforcement" icon="presets/vehicle/restriction/speed_camera.svg" type="relation" preset_name_label="true"> 7584 7597 <link wiki="Relation:enforcement" /> 7585 7598 <space /> -
images/presets/transport/way/relation_connectivity.svg
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 3 <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 640 640" width="640" height="640"><defs><path d="M0 46.49C0 46.49 0 46.49 0 46.49C0 20.82 20.82 0 46.49 0C59.5 0 124.53 0 241.58 0C241.58 0 241.58 0 241.58 0C253.92 0 265.74 4.9 274.46 13.62C283.18 22.34 288.08 34.16 288.08 46.49C288.08 65.09 288.08 213.86 288.08 232.46C288.08 258.14 267.26 278.95 241.58 278.95C222.08 278.95 66 278.95 46.49 278.95C20.82 278.95 0 258.14 0 232.46C0 207.66 0 145.67 0 46.49Z" id="a7taVMJVF2"></path><path d="M0 46.49C0 46.49 0 46.49 0 46.49C0 20.82 20.82 0 46.49 0C59.5 0 124.53 0 241.58 0C241.58 0 241.58 0 241.58 0C253.92 0 265.74 4.9 274.46 13.62C283.18 22.34 288.08 34.16 288.08 46.49C288.08 65.09 288.08 213.86 288.08 232.46C288.08 258.14 267.26 278.95 241.58 278.95C222.08 278.95 66 278.95 46.49 278.95C20.82 278.95 0 258.14 0 232.46C0 207.66 0 145.67 0 46.49Z" id="apgHjUq2Q"></path><path d="M351.92 46.49C351.92 46.49 351.92 46.49 351.92 46.49C351.92 20.82 372.74 0 398.42 0C411.42 0 476.45 0 593.51 0C593.51 0 593.51 0 593.51 0C605.84 0 617.66 4.9 626.38 13.62C635.1 22.34 640 34.16 640 46.49C640 65.09 640 213.86 640 232.46C640 258.14 619.18 278.95 593.51 278.95C574 278.95 417.92 278.95 398.42 278.95C372.74 278.95 351.92 258.14 351.92 232.46C351.92 207.66 351.92 145.67 351.92 46.49Z" id="c2kLrQggK"></path><path d="M351.92 46.49C351.92 46.49 351.92 46.49 351.92 46.49C351.92 20.82 372.74 0 398.42 0C411.42 0 476.45 0 593.51 0C593.51 0 593.51 0 593.51 0C605.84 0 617.66 4.9 626.38 13.62C635.1 22.34 640 34.16 640 46.49C640 65.09 640 213.86 640 232.46C640 258.14 619.18 278.95 593.51 278.95C574 278.95 417.92 278.95 398.42 278.95C372.74 278.95 351.92 258.14 351.92 232.46C351.92 207.66 351.92 145.67 351.92 46.49Z" id="bRf59UWe"></path><path d="M351.92 407.54C351.92 407.54 351.92 407.54 351.92 407.54C351.92 381.86 372.74 361.05 398.42 361.05C411.42 361.05 476.45 361.05 593.51 361.05C593.51 361.05 593.51 361.05 593.51 361.05C605.84 361.05 617.66 365.95 626.38 374.67C635.1 383.39 640 395.21 640 407.54C640 426.14 640 574.91 640 593.51C640 619.18 619.18 640 593.51 640C574 640 417.92 640 398.42 640C372.74 640 351.92 619.18 351.92 593.51C351.92 568.71 351.92 506.72 351.92 407.54Z" id="b3XpfhE8d"></path><path d="M351.92 407.54C351.92 407.54 351.92 407.54 351.92 407.54C351.92 381.86 372.74 361.05 398.42 361.05C411.42 361.05 476.45 361.05 593.51 361.05C593.51 361.05 593.51 361.05 593.51 361.05C605.84 361.05 617.66 365.95 626.38 374.67C635.1 383.39 640 395.21 640 407.54C640 426.14 640 574.91 640 593.51C640 619.18 619.18 640 593.51 640C574 640 417.92 640 398.42 640C372.74 640 351.92 619.18 351.92 593.51C351.92 568.71 351.92 506.72 351.92 407.54Z" id="g6peWbU7wg"></path><path d="M0 407.54C0 407.54 0 407.54 0 407.54C0 381.86 20.82 361.05 46.49 361.05C59.5 361.05 124.53 361.05 241.58 361.05C241.58 361.05 241.58 361.05 241.58 361.05C253.92 361.05 265.74 365.95 274.46 374.67C283.18 383.39 288.08 395.21 288.08 407.54C288.08 426.14 288.08 574.91 288.08 593.51C288.08 619.18 267.26 640 241.58 640C222.08 640 66 640 46.49 640C20.82 640 0 619.18 0 593.51C0 568.71 0 506.72 0 407.54Z" id="b3X9mZS0XS"></path><path d="M0 407.54C0 407.54 0 407.54 0 407.54C0 381.86 20.82 361.05 46.49 361.05C59.5 361.05 124.53 361.05 241.58 361.05C241.58 361.05 241.58 361.05 241.58 361.05C253.92 361.05 265.74 365.95 274.46 374.67C283.18 383.39 288.08 395.21 288.08 407.54C288.08 426.14 288.08 574.91 288.08 593.51C288.08 619.18 267.26 640 241.58 640C222.08 640 66 640 46.49 640C20.82 640 0 619.18 0 593.51C0 568.71 0 506.72 0 407.54Z" id="c2OicV7Ga1"></path><path d="M0 230.92C0 230.92 0 230.92 0 230.92C0 202.89 22.73 180.16 50.77 180.16C104.61 180.16 535.39 180.16 589.23 180.16C602.7 180.16 615.61 185.51 625.13 195.03C634.65 204.55 640 217.46 640 230.92C640 251.23 640 413.67 640 433.98C640 462.01 617.27 484.74 589.23 484.74C535.39 484.74 104.61 484.74 50.77 484.74C22.73 484.74 0 462.01 0 433.98C0 406.9 0 339.22 0 230.92Z" id="aaiiO6LMf9"></path><path d="M165.66 48.01C165.66 48.01 165.66 48.01 165.66 48.01C165.66 21.5 187.16 0 213.68 0C226.48 0 290.5 0 405.73 0C405.73 0 405.73 0 405.73 0C418.46 0 430.67 5.06 439.68 14.06C448.68 23.07 453.74 35.28 453.74 48.01C453.74 102.41 453.74 537.59 453.74 591.99C453.74 618.5 432.25 640 405.73 640C386.52 640 232.88 640 213.68 640C187.16 640 165.66 618.5 165.66 591.99C165.66 519.46 165.66 338.13 165.66 48.01Z" id="abbTqBwz"></path><path d="M202.77 0L428.27 0" id="h8eVNYgClu"></path><path d="M202.77 0L428.27 0" id="b3wCehSi4F"></path><path d="M196.95 640L422.45 640" id="a8ZF3dFoi"></path><path d="M196.95 640L422.45 640" id="g2XjesW754"></path><path d="M640 459.85L639.37 203.2" id="c1aq5Qb0th"></path><path d="M640 459.85L639.37 203.2" id="b5fB0Jggyg"></path><path d="M0.63 466.77L0 210.12" id="e1w7hZayOo"></path><path d="M0.63 466.77L0 210.12" id="dHcZYYnhO"></path><path d="M37.55 47.79C37.55 47.79 37.55 47.79 37.55 47.79C37.55 40.11 43.78 33.88 51.47 33.88C55.18 33.88 73.73 33.88 107.12 33.88C107.12 33.88 107.12 33.88 107.12 33.88C110.81 33.88 114.35 35.34 116.96 37.95C119.57 40.56 121.04 44.1 121.04 47.79C121.04 55.94 121.04 121.1 121.04 129.24C121.04 136.93 114.81 143.16 107.12 143.16C101.56 143.16 57.03 143.16 51.47 143.16C43.78 143.16 37.55 136.93 37.55 129.24C37.55 118.38 37.55 91.23 37.55 47.79Z" id="bGa13pfAK"></path><path d="M519.5 47.79C519.5 47.79 519.5 47.79 519.5 47.79C519.5 40.11 525.73 33.88 533.42 33.88C537.13 33.88 555.68 33.88 589.07 33.88C589.07 33.88 589.07 33.88 589.07 33.88C592.76 33.88 596.3 35.34 598.91 37.95C601.52 40.56 602.99 44.1 602.99 47.79C602.99 55.94 602.99 121.1 602.99 129.24C602.99 136.93 596.76 143.16 589.07 143.16C583.51 143.16 538.98 143.16 533.42 143.16C525.73 143.16 519.5 136.93 519.5 129.24C519.5 118.38 519.5 91.23 519.5 47.79Z" id="d2wCkNoM3P"></path><path d="M37.55 507.57C37.55 507.57 37.55 507.57 37.55 507.57C37.55 499.89 43.78 493.66 51.47 493.66C55.18 493.66 73.73 493.66 107.12 493.66C107.12 493.66 107.12 493.66 107.12 493.66C110.81 493.66 114.35 495.13 116.96 497.74C119.57 500.34 121.04 503.88 121.04 507.57C121.04 515.72 121.04 580.88 121.04 589.02C121.04 596.71 114.81 602.94 107.12 602.94C101.56 602.94 57.03 602.94 51.47 602.94C43.78 602.94 37.55 596.71 37.55 589.02C37.55 578.16 37.55 551.01 37.55 507.57Z" id="g1Te9z9uK"></path><path d="M519.5 507.57C519.5 507.57 519.5 507.57 519.5 507.57C519.5 499.89 525.73 493.66 533.42 493.66C537.13 493.66 555.68 493.66 589.07 493.66C589.07 493.66 589.07 493.66 589.07 493.66C592.76 493.66 596.3 495.13 598.91 497.74C601.52 500.34 602.99 503.88 602.99 507.57C602.99 515.72 602.99 580.88 602.99 589.02C602.99 596.71 596.76 602.94 589.07 602.94C583.51 602.94 538.98 602.94 533.42 602.94C525.73 602.94 519.5 596.71 519.5 589.02C519.5 578.16 519.5 551.01 519.5 507.57Z" id="a5xlHsGyW"></path><path d="M94.04 33.88L545.32 33.88L545.32 602.93L94.04 602.93L94.04 33.88Z" id="i5XppWnd6A"></path><path d="M37.55 98.96L602.99 98.96L602.99 537.35L37.55 537.35L37.55 98.96Z" id="a1npIiv3d"></path><path d="M428.27 157.29L478.88 65.19L529.49 157.29L428.27 157.29Z" id="aGrCMZldo"></path><path d="M264.9 157.29L315.52 65.19L366.13 157.29L264.9 157.29Z" id="a2vqq6wfRW"></path><path d="M309.92 151.76L309.48 563.17" id="a4mZiuAN4"></path><path d="M309.92 151.76L309.48 563.17" id="f2eR1MdjtU"></path><path d="M320.22 151.76L319.78 563.17" id="i1aw7I6IO"></path><path d="M320.22 151.76L319.78 563.17" id="aiXcaY4gb"></path><path d="M474.86 151.76L474.42 563.17" id="g5YujQDwx"></path><path d="M474.86 151.76L474.42 563.17" id="c4xBbdTiNV"></path><path d="M485.16 151.76L484.72 563.17" id="ciAys2Kx0"></path><path d="M485.16 151.76L484.72 563.17" id="b2UTI2pbY"></path><path d="M146.84 453.33C146.84 395.62 187.67 366.76 228.5 337.91C269.34 309.05 310.17 280.19 310.17 222.48" id="a17DFS0xbs"></path><path d="M146.84 453.33C146.84 395.62 187.67 366.76 228.5 337.91C269.34 309.05 310.17 280.19 310.17 222.48" id="asAo4qo53"></path><path d="M155.87 453.33C155.87 395.62 196.7 366.76 237.53 337.91C278.36 309.05 319.19 280.19 319.19 222.48" id="c353BxmIjg"></path><path d="M155.87 453.33C155.87 395.62 196.7 366.76 237.53 337.91C278.36 309.05 319.19 280.19 319.19 222.48" id="bNwkHbP5N"></path><path d="M146.84 450.88L144.54 563.13" id="aRkZLonUJ"></path><path d="M146.84 450.88L144.54 563.13" id="gCYFFvttG"></path><path d="M155.44 434.91L154.84 563.16" id="e4poeBsfvT"></path><path d="M155.44 434.91L154.84 563.16" id="aTTBmkyhq"></path></defs><g><g><g><use xlink:href="#a7taVMJVF2" opacity="1" fill="#ffffff" fill-opacity="1"></use><g><use xlink:href="#a7taVMJVF2" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#apgHjUq2Q" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#apgHjUq2Q" opacity="1" fill-opacity="0" stroke="#595959" stroke-width="1" stroke-opacity="1"></use></g></g><g><use xlink:href="#c2kLrQggK" opacity="1" fill="#ffffff" fill-opacity="1"></use><g><use xlink:href="#c2kLrQggK" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#bRf59UWe" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#bRf59UWe" opacity="1" fill-opacity="0" stroke="#595959" stroke-width="1" stroke-opacity="1"></use></g></g><g><use xlink:href="#b3XpfhE8d" opacity="1" fill="#ffffff" fill-opacity="1"></use><g><use xlink:href="#b3XpfhE8d" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#g6peWbU7wg" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#g6peWbU7wg" opacity="1" fill-opacity="0" stroke="#595959" stroke-width="1" stroke-opacity="1"></use></g></g><g><use xlink:href="#b3X9mZS0XS" opacity="1" fill="#ffffff" fill-opacity="1"></use><g><use xlink:href="#b3X9mZS0XS" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#c2OicV7Ga1" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#c2OicV7Ga1" opacity="1" fill-opacity="0" stroke="#595959" stroke-width="1" stroke-opacity="1"></use></g></g><g><use xlink:href="#aaiiO6LMf9" opacity="1" fill="#ffffff" fill-opacity="1"></use><g><use xlink:href="#aaiiO6LMf9" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#abbTqBwz" opacity="1" fill="#ffffff" fill-opacity="1"></use><g><use xlink:href="#abbTqBwz" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#h8eVNYgClu" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#h8eVNYgClu" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#b3wCehSi4F" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#b3wCehSi4F" opacity="1" fill-opacity="0" stroke="#595959" stroke-width="1" stroke-opacity="1"></use></g></g><g><use xlink:href="#a8ZF3dFoi" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#a8ZF3dFoi" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#g2XjesW754" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#g2XjesW754" opacity="1" fill-opacity="0" stroke="#595959" stroke-width="1" stroke-opacity="1"></use></g></g><g><use xlink:href="#c1aq5Qb0th" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#c1aq5Qb0th" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#b5fB0Jggyg" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#b5fB0Jggyg" opacity="1" fill-opacity="0" stroke="#595959" stroke-width="1" stroke-opacity="1"></use></g></g><g><use xlink:href="#e1w7hZayOo" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#e1w7hZayOo" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#dHcZYYnhO" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#dHcZYYnhO" opacity="1" fill-opacity="0" stroke="#595959" stroke-width="1" stroke-opacity="1"></use></g></g><g><use xlink:href="#bGa13pfAK" opacity="1" fill="#0000ff" fill-opacity="1"></use><g><use xlink:href="#bGa13pfAK" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#d2wCkNoM3P" opacity="1" fill="#0000ff" fill-opacity="1"></use><g><use xlink:href="#d2wCkNoM3P" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#g1Te9z9uK" opacity="1" fill="#0000ff" fill-opacity="1"></use><g><use xlink:href="#g1Te9z9uK" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#a5xlHsGyW" opacity="1" fill="#0000ff" fill-opacity="1"></use><g><use xlink:href="#a5xlHsGyW" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#i5XppWnd6A" opacity="1" fill="#0000ff" fill-opacity="1"></use><g><use xlink:href="#i5XppWnd6A" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#a1npIiv3d" opacity="1" fill="#0000ff" fill-opacity="1"></use><g><use xlink:href="#a1npIiv3d" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#aGrCMZldo" opacity="1" fill="#ffffff" fill-opacity="1"></use><g><use xlink:href="#aGrCMZldo" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#a2vqq6wfRW" opacity="1" fill="#ffffff" fill-opacity="1"></use><g><use xlink:href="#a2vqq6wfRW" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#a4mZiuAN4" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#a4mZiuAN4" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#f2eR1MdjtU" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#f2eR1MdjtU" opacity="1" fill-opacity="0" stroke="#ffffff" stroke-width="24" stroke-opacity="1"></use></g></g><g><use xlink:href="#i1aw7I6IO" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#i1aw7I6IO" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#aiXcaY4gb" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#aiXcaY4gb" opacity="1" fill-opacity="0" stroke="#ffffff" stroke-width="24" stroke-opacity="1"></use></g></g><g><use xlink:href="#g5YujQDwx" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#g5YujQDwx" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#c4xBbdTiNV" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#c4xBbdTiNV" opacity="1" fill-opacity="0" stroke="#ffffff" stroke-width="24" stroke-opacity="1"></use></g></g><g><use xlink:href="#ciAys2Kx0" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#ciAys2Kx0" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#b2UTI2pbY" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#b2UTI2pbY" opacity="1" fill-opacity="0" stroke="#ffffff" stroke-width="24" stroke-opacity="1"></use></g></g><g><use xlink:href="#a17DFS0xbs" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#a17DFS0xbs" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#asAo4qo53" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#asAo4qo53" opacity="1" fill-opacity="0" stroke="#ffffff" stroke-width="24" stroke-opacity="1"></use></g></g><g><use xlink:href="#c353BxmIjg" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#c353BxmIjg" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#bNwkHbP5N" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#bNwkHbP5N" opacity="1" fill-opacity="0" stroke="#ffffff" stroke-width="24" stroke-opacity="1"></use></g></g><g><use xlink:href="#aRkZLonUJ" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#aRkZLonUJ" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#gCYFFvttG" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#gCYFFvttG" opacity="1" fill-opacity="0" stroke="#ffffff" stroke-width="24" stroke-opacity="1"></use></g></g><g><use xlink:href="#e4poeBsfvT" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#e4poeBsfvT" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g><g><use xlink:href="#aTTBmkyhq" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#aTTBmkyhq" opacity="1" fill-opacity="0" stroke="#ffffff" stroke-width="24" stroke-opacity="1"></use></g></g></g></g></svg> 4 No newline at end of file -
src/org/openstreetmap/josm/data/validation/OsmValidator.java
42 42 import org.openstreetmap.josm.data.validation.tests.BarriersEntrances; 43 43 import org.openstreetmap.josm.data.validation.tests.Coastlines; 44 44 import org.openstreetmap.josm.data.validation.tests.ConditionalKeys; 45 import org.openstreetmap.josm.data.validation.tests.ConnectivityRelations; 45 46 import org.openstreetmap.josm.data.validation.tests.CrossingWays; 46 47 import org.openstreetmap.josm.data.validation.tests.DuplicateNode; 47 48 import org.openstreetmap.josm.data.validation.tests.DuplicateRelation; … … 150 151 PublicTransportRouteTest.class, // 3600 .. 3699 151 152 RightAngleBuildingTest.class, // 3700 .. 3799 152 153 SharpAngles.class, // 3800 .. 3899 154 ConnectivityRelations.class, // 3900 .. 3999 153 155 }; 154 156 155 157 /** -
src/org/openstreetmap/josm/data/validation/tests/ConnectivityRelations.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.data.validation.tests; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import java.util.Collections; 7 import java.util.Comparator; 8 import java.util.HashMap; 9 import java.util.Map; 10 import java.util.Map.Entry; 11 import java.util.regex.Pattern; 12 13 import org.openstreetmap.josm.data.osm.Node; 14 import org.openstreetmap.josm.data.osm.OsmPrimitive; 15 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 16 import org.openstreetmap.josm.data.osm.Relation; 17 import org.openstreetmap.josm.data.osm.RelationMember; 18 import org.openstreetmap.josm.data.osm.Way; 19 import org.openstreetmap.josm.data.validation.Severity; 20 import org.openstreetmap.josm.data.validation.Test; 21 import org.openstreetmap.josm.data.validation.TestError; 22 import org.openstreetmap.josm.tools.Logging; 23 24 /** 25 * Check for inconsistencies in lane information between relation and members. 26 */ 27 public class ConnectivityRelations extends Test { 28 29 protected static final int INCONSISTENT_LANE_COUNT = 3900; 30 31 protected static final int UNKNOWN_CONNECTIVITY_ROLE = INCONSISTENT_LANE_COUNT + 1; 32 33 protected static final int NO_CONNECTIVITY_TAG = INCONSISTENT_LANE_COUNT + 2; 34 35 protected static final int TOO_MANY_ROLES = INCONSISTENT_LANE_COUNT + 3; 36 37 private static final String CONNECTIVITY_TAG = "connectivity"; 38 private static final String VIA = "via"; 39 private static final String TO = "to"; 40 private static final String FROM = "from"; 41 private static final Pattern OPTIONAL_LANE_PATTERN = Pattern.compile("\\([0-9]+\\)"); 42 private static final Pattern TO_LANE_PATTERN = Pattern.compile("\\p{Zs}*[,:;]\\p{Zs}*"); 43 44 /** 45 * Constructor 46 */ 47 public ConnectivityRelations() { 48 super(tr("Connectivity Relation Check"), tr("Checks that lane count of relation matches with lanes of members")); 49 } 50 51 /** 52 * Convert the connectivity tag into a map of values 53 * 54 * @param relation A relation with a {@code connectivity} tag. 55 * @return A Map in the form of {@code Map<Lane From, Map<Lane To, Optional>>} May contain nulls when errors are encountered 56 * @since xxx 57 */ 58 public static Map<Integer, Map<Integer, Boolean>> parseConnectivityTag(Relation relation) { 59 final String joined = relation.get(CONNECTIVITY_TAG); 60 61 if (joined == null) { 62 return Collections.emptyMap(); 63 } 64 65 final Map<Integer, Map<Integer, Boolean>> result = new HashMap<>(); 66 String[] lanes = joined.split("\\|", -1); 67 for (int i = 0; i < lanes.length; i++) { 68 String[] lane = lanes[i].split(":", -1); 69 int laneNumber = Integer.parseInt(lane[0].trim()); 70 Map<Integer, Boolean> connections = new HashMap<>(); 71 String[] toLanes = TO_LANE_PATTERN.split(lane[1]); 72 for (int j = 0; j < toLanes.length; j++) { 73 String toLane = toLanes[j].trim(); 74 try { 75 if (OPTIONAL_LANE_PATTERN.matcher(toLane).matches()) { 76 toLane = toLane.replace("(", "").replace(")", "").trim(); 77 connections.put(Integer.parseInt(toLane), Boolean.TRUE); 78 } else { 79 connections.put(Integer.parseInt(toLane), Boolean.FALSE); 80 } 81 } catch (NumberFormatException e) { 82 Logging.debug(e); 83 connections.put(null, null); 84 } 85 86 } 87 result.put(laneNumber, connections); 88 } 89 return result; 90 } 91 92 @Override 93 public void visit(Relation r) { 94 if (r.hasTag("type", CONNECTIVITY_TAG)) { 95 if (!r.hasKey(CONNECTIVITY_TAG)) { 96 errors.add(TestError.builder(this, Severity.WARNING, NO_CONNECTIVITY_TAG) 97 .message(tr("No connectivity tag in connectivity relation")).primitives(r).build()); 98 } else if (!r.hasIncompleteMembers()) { 99 boolean badRole = checkForBadRole(r); 100 if (!badRole) 101 checkForInconsistentLanes(r); 102 } 103 } 104 } 105 106 private void checkForInconsistentLanes(Relation relation) { 107 // Lane count from connectivity tag 108 Map<Integer, Map<Integer, Boolean>> connTagLanes = parseConnectivityTag(relation); 109 // Lane count from member tags 110 Map<String, Integer> roleLanes = new HashMap<>(); 111 112 for (RelationMember rM : relation.getMembers()) { 113 // Check lanes 114 if (rM.getType() == OsmPrimitiveType.WAY) { 115 OsmPrimitive prim = rM.getMember(); 116 if (prim.hasKey("lanes") && !VIA.equals(rM.getRole())) { 117 roleLanes.put(rM.getRole(), Integer.parseInt(prim.get("lanes"))); 118 } 119 } 120 } 121 boolean fromCheck = roleLanes.get(FROM) < Collections 122 .max(connTagLanes.entrySet(), Comparator.comparingInt(Map.Entry::getKey)).getKey(); 123 boolean toCheck = false; 124 for (Entry<Integer, Map<Integer, Boolean>> to : connTagLanes.entrySet()) { 125 toCheck = roleLanes.get(TO) < Collections 126 .max(to.getValue().entrySet(), Comparator.comparingInt(Map.Entry::getKey)).getKey(); 127 } 128 if (fromCheck || toCheck) { 129 errors.add(TestError.builder(this, Severity.WARNING, INCONSISTENT_LANE_COUNT) 130 .message(tr("Inconsistent lane numbering between relation and members")).primitives(relation) 131 .build()); 132 } 133 } 134 135 private boolean checkForBadRole(Relation relation) { 136 // Check role names 137 int viaWays = 0; 138 int viaNodes = 0; 139 int toWays = 0; 140 int fromWays = 0; 141 for (RelationMember relationMember : relation.getMembers()) { 142 if (relationMember.getMember() instanceof Way) { 143 if (relationMember.hasRole(FROM)) 144 fromWays++; 145 else if (relationMember.hasRole(TO)) 146 toWays++; 147 else if (relationMember.hasRole(VIA)) 148 viaWays++; 149 else { 150 createUnknownRole(relation, relationMember.getMember()); 151 return true; 152 } 153 } else if (relationMember.getMember() instanceof Node) { 154 if (!relationMember.hasRole(VIA)) { 155 createUnknownRole(relation, relationMember.getMember()); 156 return true; 157 } 158 viaNodes++; 159 } 160 } 161 return mixedViaNodeAndWay(relation, viaWays, viaNodes, toWays, fromWays); 162 } 163 164 private boolean mixedViaNodeAndWay(Relation relation, int viaWays, int viaNodes, int toWays, int fromWays) { 165 String message = ""; 166 if ((viaWays != 0 && viaNodes != 0) || viaNodes > 1) { 167 message = tr("Relation contains {1} {0} roles.", VIA, viaWays + viaNodes); 168 } else if (toWays != 1) { 169 message = tr("Relation contains too many {0} roles", TO); 170 } else if (fromWays != 1) { 171 message = tr("Relation contains too many {0} roles", FROM); 172 } 173 if (message.isEmpty()) { 174 return false; 175 } else { 176 errors.add(TestError.builder(this, Severity.WARNING, TOO_MANY_ROLES) 177 .message(message).primitives(relation).build()); 178 return true; 179 } 180 } 181 182 private void createUnknownRole(Relation relation, OsmPrimitive primitive) { 183 errors.add(TestError.builder(this, Severity.WARNING, UNKNOWN_CONNECTIVITY_ROLE) 184 .message(tr("Unkown role in connectivity relation")).primitives(relation).highlight(primitive).build()); 185 } 186 } -
test/unit/org/openstreetmap/josm/data/validation/tests/ConnectivityRelationsTest.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.data.validation.tests; 3 4 import org.junit.Assert; 5 import org.junit.Before; 6 import org.junit.Test; 7 import org.openstreetmap.josm.JOSMFixture; 8 import org.openstreetmap.josm.TestUtils; 9 import org.openstreetmap.josm.data.coor.LatLon; 10 import org.openstreetmap.josm.data.osm.Node; 11 import org.openstreetmap.josm.data.osm.Relation; 12 import org.openstreetmap.josm.data.osm.RelationMember; 13 14 /** 15 * Test the ConnectivityRelations validation test 16 * 17 * @author Taylor Smock 18 */ 19 public class ConnectivityRelationsTest { 20 private ConnectivityRelations check; 21 private static final String CONNECTIVITY = "connectivity"; 22 /** 23 * Setup test. 24 * 25 * @throws Exception if an error occurs 26 */ 27 @Before 28 public void setUp() throws Exception { 29 JOSMFixture.createUnitTestFixture().init(); 30 check = new ConnectivityRelations(); 31 } 32 33 private Relation createDefaultTestRelation() { 34 Node connection = new Node(new LatLon(0, 0)); 35 return TestUtils.newRelation("type=connectivity connectivity=1:1", 36 new RelationMember("from", TestUtils.newWay("lanes=4", new Node(new LatLon(-0.1, -0.1)), connection)), 37 new RelationMember("via", connection), 38 new RelationMember("to", TestUtils.newWay("lanes=4", connection, new Node(new LatLon(0.1, 0.1))))); 39 } 40 41 /** 42 * Test for connectivity relations without a connectivity tag 43 */ 44 @Test 45 public void testNoConnectivityTag() { 46 Relation relation = createDefaultTestRelation(); 47 check.visit(relation); 48 49 Assert.assertEquals(0, check.getErrors().size()); 50 51 relation.remove(CONNECTIVITY); 52 check.visit(relation); 53 Assert.assertEquals(1, check.getErrors().size()); 54 } 55 56 /** 57 * Check for lanes that don't make sense 58 */ 59 @Test 60 public void testMisMatchedLanes() { 61 Relation relation = createDefaultTestRelation(); 62 check.visit(relation); 63 int expectedFailures = 0; 64 65 Assert.assertEquals(expectedFailures, check.getErrors().size()); 66 67 relation.put(CONNECTIVITY, "45000:1"); 68 check.visit(relation); 69 Assert.assertEquals(++expectedFailures, check.getErrors().size()); 70 71 relation.put(CONNECTIVITY, "1:45000"); 72 check.visit(relation); 73 Assert.assertEquals(++expectedFailures, check.getErrors().size()); 74 75 relation.put(CONNECTIVITY, "1:1,2"); 76 check.visit(relation); 77 Assert.assertEquals(expectedFailures, check.getErrors().size()); 78 79 relation.put(CONNECTIVITY, "1:1,(2)"); 80 check.visit(relation); 81 Assert.assertEquals(expectedFailures, check.getErrors().size()); 82 83 relation.put(CONNECTIVITY, "1:1,(20000)"); 84 check.visit(relation); 85 Assert.assertEquals(++expectedFailures, check.getErrors().size()); 86 } 87 88 /** 89 * Check for bad roles (not from/via/to) 90 */ 91 @Test 92 public void testForBadRole() { 93 Relation relation = createDefaultTestRelation(); 94 check.visit(relation); 95 int expectedFailures = 0; 96 97 Assert.assertEquals(expectedFailures, check.getErrors().size()); 98 99 for (int i = 0; i < relation.getMembers().size(); i++) { 100 String tRole = replaceMember(relation, i, "badRole"); 101 check.visit(relation); 102 Assert.assertEquals(++expectedFailures, check.getErrors().size()); 103 replaceMember(relation, i, tRole); 104 check.visit(relation); 105 Assert.assertEquals(expectedFailures, check.getErrors().size()); 106 } 107 } 108 109 private String replaceMember(Relation relation, int index, String replacementRole) { 110 RelationMember relationMember = relation.getMember(index); 111 String currentRole = relationMember.getRole(); 112 relation.removeMember(index); 113 relation.addMember(index, new RelationMember(replacementRole, relationMember.getMember())); 114 return currentRole; 115 } 116 }
