diff --git a/EastCampusLiteV4.gml b/EastCampusLiteV4.gml
deleted file mode 100644
index 87be4bcd..00000000
--- a/EastCampusLiteV4.gml
+++ /dev/null
@@ -1,3200 +0,0 @@
-graph [
- directed 1
- node [
- id 0
- label "R_Node:172"
- active 0
- pos 36.85892184575399
- pos 17.077014287312828
- ]
- node [
- id 1
- label "R_Node:175"
- active 0
- pos 41.85546429951986
- pos 20.636311848958336
- ]
- node [
- id 2
- label "R_Node:129"
- active 0
- pos 212.161376953125
- pos 141.32177734375
- ]
- node [
- id 3
- label "R_Node:174"
- active 0
- pos 40.18995014826457
- pos 19.449879328409832
- ]
- node [
- id 4
- label "R_Node:258"
- active 0
- pos 27.437116622924805
- pos 13.336549758911133
- ]
- node [
- id 5
- label "R_Node:177"
- active 0
- pos 45.18649260203044
- pos 23.00917689005534
- ]
- node [
- id 6
- label "R_Node:246"
- active 0
- pos 46.160543714250835
- pos 31.095536913190568
- ]
- node [
- id 7
- label "R_Node:250"
- active 0
- pos 42.37858581542969
- pos 22.35539182027181
- ]
- node [
- id 8
- label "R_Node:251"
- active 0
- pos 40.4602165222168
- pos 20.564404169718426
- ]
- node [
- id 9
- label "R_Node:252"
- active 0
- pos 38.541847229003906
- pos 18.77341651916504
- ]
- node [
- id 10
- label "R_Node:176"
- active 0
- pos 43.52097845077515
- pos 21.822744369506836
- ]
- node [
- id 11
- label "R_Node:254"
- active 0
- pos 35.1614803314209
- pos 17.148366165161132
- ]
- node [
- id 12
- label "R_Node:255"
- active 0
- pos 33.23038940429687
- pos 16.19541206359863
- ]
- node [
- id 13
- label "R_Node:256"
- active 0
- pos 31.29929847717285
- pos 15.242457962036132
- ]
- node [
- id 14
- label "R_Node:257"
- active 0
- pos 29.36820755004883
- pos 14.289503860473634
- ]
- node [
- id 15
- label "R_Node:153"
- active 0
- pos 74.57064819335938
- pos 135.58511352539062
- ]
- node [
- id 16
- label "R_Node:152"
- active 0
- pos 87.55392456054688
- pos 131.78089904785156
- ]
- node [
- id 17
- label "R_Node:151"
- active 0
- pos 127.93462371826172
- pos 116.86445617675781
- ]
- node [
- id 18
- label "R_Node:150"
- active 0
- pos 127.51367950439453
- pos 127.16743469238281
- ]
- node [
- id 19
- label "R_Node:157"
- active 0
- pos 62.76912307739258
- pos 124.16730499267578
- ]
- node [
- id 20
- label "R_Node:156"
- active 0
- pos 62.997310638427734
- pos 130.343505859375
- ]
- node [
- id 21
- label "R_Node:155"
- active 0
- pos 62.744781494140625
- pos 136.39981079101562
- ]
- node [
- id 22
- label "R_Node:154"
- active 0
- pos 66.09662628173828
- pos 140.23387145996094
- ]
- node [
- id 23
- label "R_Node:159"
- active 0
- pos 62.36149597167969
- pos 112.84590148925781
- ]
- node [
- id 24
- label "R_Node:158"
- active 0
- pos 62.53026580810547
- pos 118.29088592529297
- ]
- node [
- id 25
- label "R_Node:242"
- active 0
- pos 46.904314858572825
- pos 39.40179170880999
- ]
- node [
- id 26
- label "R_Node:236"
- active 0
- pos 48.019971575055806
- pos 51.861173902239116
- ]
- node [
- id 27
- label "R_Node:240"
- active 0
- pos 47.276200430733816
- pos 43.5549191066197
- ]
- node [
- id 28
- label "R_Node:126"
- active 0
- pos 205.57742309570312
- pos 139.0648193359375
- ]
- node [
- id 29
- label "R_Node:127"
- active 0
- pos 207.92601013183594
- pos 139.86581420898438
- ]
- node [
- id 30
- label "R_Node:124"
- active 0
- pos 201.7657928466797
- pos 137.75791931152344
- ]
- node [
- id 31
- label "R_Node:237"
- active 0
- pos 47.83402878897531
- pos 49.78461020333426
- ]
- node [
- id 32
- label "R_Node:125"
- active 0
- pos 203.6590576171875
- pos 138.41526794433594
- ]
- node [
- id 33
- label "R_Node:249"
- active 0
- pos 44.29695510864258
- pos 24.146379470825195
- ]
- node [
- id 34
- label "R_Node:248"
- active 0
- pos 45.788658142089844
- pos 26.94240951538086
- ]
- node [
- id 35
- label "R_Node:247"
- active 0
- pos 45.97460092817034
- pos 29.01897321428571
- ]
- node [
- id 36
- label "R_Node:122"
- active 0
- pos 197.14239501953125
- pos 136.17918395996094
- ]
- node [
- id 37
- label "R_Node:245"
- active 0
- pos 46.34648650033133
- pos 33.17210061209542
- ]
- node [
- id 38
- label "R_Node:169"
- active 0
- pos 31.862379391988117
- pos 13.517716725667318
- ]
- node [
- id 39
- label "R_Node:243"
- active 0
- pos 46.71837207249233
- pos 37.32522800990513
- ]
- node [
- id 40
- label "R_Node:216"
- active 0
- pos 56.86594990321568
- pos 95.38580213274274
- ]
- node [
- id 41
- label "R_Node:241"
- active 0
- pos 47.09025764465332
- pos 41.478355407714844
- ]
- node [
- id 42
- label "R_Node:123"
- active 0
- pos 199.4720001220703
- pos 136.99835205078125
- ]
- node [
- id 43
- label "R_Node:97"
- active 0
- pos 144.37139892578125
- pos 117.93341064453125
- ]
- node [
- id 44
- label "R_Node:96"
- active 0
- pos 142.03541564941406
- pos 117.09336853027344
- ]
- node [
- id 45
- label "R_Node:95"
- active 0
- pos 139.6620330810547
- pos 116.3309326171875
- ]
- node [
- id 46
- label "R_Node:94"
- active 0
- pos 137.30259704589844
- pos 115.70829010009766
- ]
- node [
- id 47
- label "R_Node:93"
- active 0
- pos 134.86337280273438
- pos 115.23493957519531
- ]
- node [
- id 48
- label "R_Node:92"
- active 0
- pos 132.88206481933594
- pos 114.9500503540039
- ]
- node [
- id 49
- label "R_Node:91"
- active 0
- pos 130.88577270507812
- pos 114.79431915283203
- ]
- node [
- id 50
- label "R_Node:90"
- active 0
- pos 128.88699340820312
- pos 114.71823120117188
- ]
- node [
- id 51
- label "R_Node:121"
- active 0
- pos 195.22164916992188
- pos 135.53895568847656
- ]
- node [
- id 52
- label "R_Node:99"
- active 0
- pos 148.95623779296875
- pos 119.71843719482422
- ]
- node [
- id 53
- label "R_Node:98"
- active 0
- pos 146.67117309570312
- pos 118.83965301513672
- ]
- node [
- id 54
- label "R_Node:209"
- active 0
- pos 57.692172459193635
- pos 90.76302773611886
- ]
- node [
- id 55
- label "R_Node:11"
- active 0
- pos 24.81735610961914
- pos 10.96833324432373
- ]
- node [
- id 56
- label "R_Node:10"
- active 0
- pos 22.611421585083008
- pos 10.346707344055176
- ]
- node [
- id 57
- label "R_Node:208"
- active 0
- pos 56.97021320887974
- pos 88.80300685337612
- ]
- node [
- id 58
- label "R_Node:167"
- active 0
- pos 28.53135108947754
- pos 11.144851684570312
- ]
- node [
- id 59
- label "R_Node:88"
- active 0
- pos 124.84341430664062
- pos 114.89605712890625
- ]
- node [
- id 60
- label "R_Node:89"
- active 0
- pos 126.86002349853516
- pos 114.72852325439453
- ]
- node [
- id 61
- label "R_Node:244"
- active 0
- pos 46.53242928641183
- pos 35.248664311000276
- ]
- node [
- id 62
- label "R_Node:128"
- active 0
- pos 209.8089141845703
- pos 140.5406494140625
- ]
- node [
- id 63
- label "R_Node:80"
- active 0
- pos 107.35012817382812
- pos 118.9886703491211
- ]
- node [
- id 64
- label "R_Node:81"
- active 0
- pos 109.29534912109375
- pos 118.47537994384766
- ]
- node [
- id 65
- label "R_Node:82"
- active 0
- pos 111.63228607177734
- pos 117.79683685302734
- ]
- node [
- id 66
- label "R_Node:83"
- active 0
- pos 114.03765106201172
- pos 117.1289291381836
- ]
- node [
- id 67
- label "R_Node:84"
- active 0
- pos 116.42974090576172
- pos 116.4520034790039
- ]
- node [
- id 68
- label "R_Node:85"
- active 0
- pos 118.7590103149414
- pos 115.83805084228516
- ]
- node [
- id 69
- label "R_Node:86"
- active 0
- pos 120.77393341064453
- pos 115.4172134399414
- ]
- node [
- id 70
- label "R_Node:87"
- active 0
- pos 122.83879089355469
- pos 115.08295440673828
- ]
- node [
- id 71
- label "R_Node:135"
- active 0
- pos 225.37648010253906
- pos 145.98486328125
- ]
- node [
- id 72
- label "R_Node:134"
- active 0
- pos 223.47389221191406
- pos 145.31536865234375
- ]
- node [
- id 73
- label "R_Node:137"
- active 0
- pos 229.45050048828125
- pos 147.4447784423828
- ]
- node [
- id 74
- label "R_Node:136"
- active 0
- pos 227.44236755371094
- pos 146.7117919921875
- ]
- node [
- id 75
- label "R_Node:131"
- active 0
- pos 216.79237365722656
- pos 142.98812866210938
- ]
- node [
- id 76
- label "R_Node:130"
- active 0
- pos 214.5050811767578
- pos 142.1568603515625
- ]
- node [
- id 77
- label "R_Node:133"
- active 0
- pos 221.36578369140625
- pos 144.59803771972656
- ]
- node [
- id 78
- label "R_Node:132"
- active 0
- pos 219.1042022705078
- pos 143.80979919433594
- ]
- node [
- id 79
- label "R_Node:232"
- active 0
- pos 48.92604217529297
- pos 60.30195007324219
- ]
- node [
- id 80
- label "R_Node:233"
- active 0
- pos 48.668678283691406
- pos 58.30877685546875
- ]
- node [
- id 81
- label "R_Node:230"
- active 0
- pos 49.44076995849609
- pos 64.28829650878906
- ]
- node [
- id 82
- label "R_Node:231"
- active 0
- pos 49.183406066894534
- pos 62.29512329101563
- ]
- node [
- id 83
- label "R_Node:139"
- active 0
- pos 233.42654418945312
- pos 148.9989776611328
- ]
- node [
- id 84
- label "R_Node:138"
- active 0
- pos 231.49647521972656
- pos 148.26290893554688
- ]
- node [
- id 85
- label "R_Node:234"
- active 0
- pos 48.3918571472168
- pos 56.01430130004883
- ]
- node [
- id 86
- label "R_Node:235"
- active 0
- pos 48.2059143611363
- pos 53.93773760114397
- ]
- node [
- id 87
- label "R_Node:173"
- active 0
- pos 38.52443599700928
- pos 18.263446807861328
- ]
- node [
- id 88
- label "R_Node:180"
- active 0
- pos 48.754188537597656
- pos 28.451602935791016
- ]
- node [
- id 89
- label "R_Node:181"
- active 0
- pos 48.873538970947266
- pos 30.452623639787948
- ]
- node [
- id 90
- label "R_Node:182"
- active 0
- pos 48.992889404296875
- pos 32.45364434378488
- ]
- node [
- id 91
- label "R_Node:183"
- active 0
- pos 49.112239837646484
- pos 34.45466504778181
- ]
- node [
- id 92
- label "R_Node:184"
- active 0
- pos 49.231590270996094
- pos 36.45568575177874
- ]
- node [
- id 93
- label "R_Node:185"
- active 0
- pos 49.3509407043457
- pos 38.456706455775674
- ]
- node [
- id 94
- label "R_Node:186"
- active 0
- pos 49.47029113769531
- pos 40.4577271597726
- ]
- node [
- id 95
- label "R_Node:187"
- active 0
- pos 49.58964157104492
- pos 42.45874786376953
- ]
- node [
- id 96
- label "R_Node:188"
- active 0
- pos 49.70899200439453
- pos 44.45976856776646
- ]
- node [
- id 97
- label "R_Node:189"
- active 0
- pos 49.82834243774414
- pos 46.460789271763396
- ]
- node [
- id 98
- label "R_Node:108"
- active 0
- pos 167.94996643066406
- pos 126.34739685058594
- ]
- node [
- id 99
- label "R_Node:109"
- active 0
- pos 169.85992431640625
- pos 126.98471069335938
- ]
- node [
- id 100
- label "R_Node:100"
- active 0
- pos 150.85183715820312
- pos 120.40372467041016
- ]
- node [
- id 101
- label "R_Node:101"
- active 0
- pos 153.23667907714844
- pos 121.21746826171875
- ]
- node [
- id 102
- label "R_Node:102"
- active 0
- pos 155.14755249023438
- pos 121.89105224609375
- ]
- node [
- id 103
- label "R_Node:103"
- active 0
- pos 157.07484436035156
- pos 122.57482147216797
- ]
- node [
- id 104
- label "R_Node:104"
- active 0
- pos 158.97669982910156
- pos 123.2376937866211
- ]
- node [
- id 105
- label "R_Node:105"
- active 0
- pos 161.34388732910156
- pos 124.05858612060547
- ]
- node [
- id 106
- label "R_Node:106"
- active 0
- pos 163.71536254882812
- pos 124.89189147949219
- ]
- node [
- id 107
- label "R_Node:107"
- active 0
- pos 165.61778259277344
- pos 125.5633773803711
- ]
- node [
- id 108
- label "R_Node:229"
- active 0
- pos 49.698133850097655
- pos 66.2814697265625
- ]
- node [
- id 109
- label "R_Node:228"
- active 0
- pos 49.95549774169922
- pos 68.27464294433594
- ]
- node [
- id 110
- label "R_Node:221"
- active 0
- pos 53.337608337402344
- pos 85.12073516845703
- ]
- node [
- id 111
- label "R_Node:220"
- active 0
- pos 54.04327665056501
- pos 87.17374856131417
- ]
- node [
- id 112
- label "R_Node:223"
- active 0
- pos 52.32830581665039
- pos 80.42354125976563
- ]
- node [
- id 113
- label "R_Node:222"
- active 0
- pos 52.85615921020508
- pos 82.7434310913086
- ]
- node [
- id 114
- label "R_Node:225"
- active 0
- pos 51.27259902954101
- pos 75.78376159667968
- ]
- node [
- id 115
- label "R_Node:224"
- active 0
- pos 51.800452423095706
- pos 78.10365142822266
- ]
- node [
- id 116
- label "R_Node:227"
- active 0
- pos 50.21689224243164
- pos 71.14398193359375
- ]
- node [
- id 117
- label "R_Node:226"
- active 0
- pos 50.74474563598633
- pos 73.46387176513672
- ]
- node [
- id 118
- label "R_Node:75"
- active 0
- pos 95.37141418457031
- pos 120.68218994140625
- ]
- node [
- id 119
- label "R_Node:74"
- active 0
- pos 92.95496368408203
- pos 120.5523910522461
- ]
- node [
- id 120
- label "R_Node:77"
- active 0
- pos 100.25975799560547
- pos 120.49601745605469
- ]
- node [
- id 121
- label "R_Node:76"
- active 0
- pos 97.84554290771484
- pos 120.74671936035156
- ]
- node [
- id 122
- label "R_Node:71"
- active 0
- pos 86.01351928710938
- pos 119.37199401855469
- ]
- node [
- id 123
- label "R_Node:70"
- active 0
- pos 83.77678680419922
- pos 118.71979522705078
- ]
- node [
- id 124
- label "R_Node:73"
- active 0
- pos 90.56732177734375
- pos 120.32624053955078
- ]
- node [
- id 125
- label "R_Node:72"
- active 0
- pos 88.24047088623047
- pos 119.89970397949219
- ]
- node [
- id 126
- label "R_Node:79"
- active 0
- pos 105.03081512451172
- pos 119.5119857788086
- ]
- node [
- id 127
- label "R_Node:78"
- active 0
- pos 102.64038848876953
- pos 120.06380462646484
- ]
- node [
- id 128
- label "R_Node:197"
- active 0
- pos 51.500187683105466
- pos 64.12092590332031
- ]
- node [
- id 129
- label "R_Node:196"
- active 0
- pos 51.11942329406738
- pos 61.985361099243164
- ]
- node [
- id 130
- label "R_Node:195"
- active 0
- pos 50.7386589050293
- pos 59.849796295166016
- ]
- node [
- id 131
- label "R_Node:194"
- active 0
- pos 50.42509460449219
- pos 56.46589279174805
- ]
- node [
- id 132
- label "R_Node:193"
- active 0
- pos 50.30574417114258
- pos 54.46487208775112
- ]
- node [
- id 133
- label "R_Node:192"
- active 0
- pos 50.18639373779297
- pos 52.46385138375419
- ]
- node [
- id 134
- label "R_Node:191"
- active 0
- pos 50.06704330444336
- pos 50.46283067975726
- ]
- node [
- id 135
- label "R_Node:190"
- active 0
- pos 49.94769287109375
- pos 48.461809975760325
- ]
- node [
- id 136
- label "R_Node:199"
- active 0
- pos 52.26171646118164
- pos 68.39205551147461
- ]
- node [
- id 137
- label "R_Node:198"
- active 0
- pos 51.88095207214356
- pos 66.25649070739746
- ]
- node [
- id 138
- label "R_Node:119"
- active 0
- pos 190.9514923095703
- pos 134.0975799560547
- ]
- node [
- id 139
- label "R_Node:118"
- active 0
- pos 188.60523986816406
- pos 133.28880310058594
- ]
- node [
- id 140
- label "R_Node:117"
- active 0
- pos 186.25982666015625
- pos 132.5243682861328
- ]
- node [
- id 141
- label "R_Node:116"
- active 0
- pos 183.90382385253906
- pos 131.72488403320312
- ]
- node [
- id 142
- label "R_Node:115"
- active 0
- pos 181.5365447998047
- pos 130.93260192871094
- ]
- node [
- id 143
- label "R_Node:114"
- active 0
- pos 179.6199951171875
- pos 130.27706909179688
- ]
- node [
- id 144
- label "R_Node:113"
- active 0
- pos 177.69375610351562
- pos 129.64181518554688
- ]
- node [
- id 145
- label "R_Node:112"
- active 0
- pos 175.70069885253906
- pos 128.9686737060547
- ]
- node [
- id 146
- label "R_Node:111"
- active 0
- pos 173.7199249267578
- pos 128.29908752441406
- ]
- node [
- id 147
- label "R_Node:110"
- active 0
- pos 171.75375366210938
- pos 127.64253997802734
- ]
- node [
- id 148
- label "R_Node:218"
- active 0
- pos 55.45461327689035
- pos 91.27977534702846
- ]
- node [
- id 149
- label "R_Node:219"
- active 0
- pos 54.74894496372768
- pos 89.22676195417132
- ]
- node [
- id 150
- label "R_Node:214"
- active 0
- pos 58.277286529541016
- pos 99.49182891845703
- ]
- node [
- id 151
- label "R_Node:215"
- active 0
- pos 57.57161821637835
- pos 97.43881552559989
- ]
- node [
- id 152
- label "R_Node:120"
- active 0
- pos 192.8698272705078
- pos 134.75054931640625
- ]
- node [
- id 153
- label "R_Node:217"
- active 0
- pos 56.16028159005301
- pos 93.3327887398856
- ]
- node [
- id 154
- label "R_Node:210"
- active 0
- pos 58.41413170950754
- pos 92.72304861886161
- ]
- node [
- id 155
- label "R_Node:211"
- active 0
- pos 59.13609095982143
- pos 94.68306950160435
- ]
- node [
- id 156
- label "R_Node:212"
- active 0
- pos 59.858050210135325
- pos 96.64309038434709
- ]
- node [
- id 157
- label "R_Node:213"
- active 0
- pos 60.58000946044922
- pos 98.60311126708984
- ]
- node [
- id 158
- label "R_Node:66"
- active 0
- pos 75.40181732177734
- pos 114.78266906738281
- ]
- node [
- id 159
- label "R_Node:67"
- active 0
- pos 77.40827178955078
- pos 115.93681335449219
- ]
- node [
- id 160
- label "R_Node:64"
- active 0
- pos 71.57231140136719
- pos 112.16053771972656
- ]
- node [
- id 161
- label "R_Node:65"
- active 0
- pos 73.42894744873047
- pos 113.50651550292969
- ]
- node [
- id 162
- label "R_Node:62"
- active 0
- pos 67.9829330444336
- pos 109.18582153320312
- ]
- node [
- id 163
- label "R_Node:63"
- active 0
- pos 69.7397689819336
- pos 110.71794891357422
- ]
- node [
- id 164
- label "R_Node:60"
- active 0
- pos 64.87171936035156
- pos 105.78549194335938
- ]
- node [
- id 165
- label "R_Node:61"
- active 0
- pos 66.38858032226562
- pos 107.52010345458984
- ]
- node [
- id 166
- label "R_Node:68"
- active 0
- pos 79.46025848388672
- pos 116.9792709350586
- ]
- node [
- id 167
- label "R_Node:69"
- active 0
- pos 81.573974609375
- pos 117.91546630859375
- ]
- node [
- id 168
- label "R_Node:9"
- active 0
- pos 20.688304901123047
- pos 9.7810697555542
- ]
- node [
- id 169
- label "R_Node:8"
- active 0
- pos 18.5693359375
- pos 9.118142127990723
- ]
- node [
- id 170
- label "R_Node:253"
- active 0
- pos 37.09257125854492
- pos 18.101320266723633
- ]
- node [
- id 171
- label "R_Node:3"
- active 0
- pos 8.485836029052734
- pos 3.9599599838256836
- ]
- node [
- id 172
- label "R_Node:2"
- active 0
- pos 6.710972785949707
- pos 2.7150332927703857
- ]
- node [
- id 173
- label "R_Node:1"
- active 0
- pos 4.935946464538574
- pos 1.4794938564300537
- ]
- node [
- id 174
- label "R_Node:0"
- active 0
- pos 3.1503920555114746
- pos 0.5402687191963196
- ]
- node [
- id 175
- label "R_Node:7"
- active 0
- pos 16.40631866455078
- pos 8.319733619689941
- ]
- node [
- id 176
- label "R_Node:6"
- active 0
- pos 14.303437232971191
- pos 7.350276470184326
- ]
- node [
- id 177
- label "R_Node:5"
- active 0
- pos 12.293851852416992
- pos 6.330555438995361
- ]
- node [
- id 178
- label "R_Node:4"
- active 0
- pos 10.407621383666992
- pos 5.224569797515869
- ]
- node [
- id 179
- label "R_Node:171"
- active 0
- pos 35.193407694498696
- pos 15.890581766764324
- ]
- node [
- id 180
- label "R_Node:203"
- active 0
- pos 53.78477401733399
- pos 76.9343147277832
- ]
- node [
- id 181
- label "R_Node:202"
- active 0
- pos 53.404009628295896
- pos 74.79874992370605
- ]
- node [
- id 182
- label "R_Node:59"
- active 0
- pos 63.43403244018555
- pos 104.0111083984375
- ]
- node [
- id 183
- label "R_Node:58"
- active 0
- pos 62.10154724121094
- pos 102.12691497802734
- ]
- node [
- id 184
- label "R_Node:207"
- active 0
- pos 56.24825395856585
- pos 86.84298597063336
- ]
- node [
- id 185
- label "R_Node:206"
- active 0
- pos 55.52629470825195
- pos 84.88296508789062
- ]
- node [
- id 186
- label "R_Node:205"
- active 0
- pos 54.546302795410156
- pos 81.2054443359375
- ]
- node [
- id 187
- label "R_Node:204"
- active 0
- pos 54.16553840637207
- pos 79.06987953186035
- ]
- node [
- id 188
- label "R_Node:163"
- active 0
- pos 9.328222274780273
- pos 0.08156789094209671
- ]
- node [
- id 189
- label "R_Node:160"
- active 0
- pos 62.51338195800781
- pos 109.39071655273438
- ]
- node [
- id 190
- label "R_Node:161"
- active 0
- pos 22.66044044494629
- pos 4.209108829498291
- ]
- node [
- id 191
- label "R_Node:166"
- active 0
- pos 22.56236457824707
- pos 0.592990517616272
- ]
- node [
- id 192
- label "R_Node:164"
- active 0
- pos 13.247344970703125
- pos -3.6120378971099854
- ]
- node [
- id 193
- label "R_Node:168"
- active 0
- pos 30.19686524073283
- pos 12.331284205118815
- ]
- node [
- id 194
- label "R_Node:179"
- active 0
- pos 48.517520904541016
- pos 25.382041931152344
- ]
- node [
- id 195
- label "R_Node:178"
- active 0
- pos 46.85200675328573
- pos 24.195609410603844
- ]
- node [
- id 196
- label "R_Node:201"
- active 0
- pos 53.02324523925781
- pos 72.6631851196289
- ]
- node [
- id 197
- label "R_Node:165"
- active 0
- pos 19.836017608642578
- pos -2.8733162879943848
- ]
- node [
- id 198
- label "R_Node:238"
- active 0
- pos 47.64808600289481
- pos 47.708046504429404
- ]
- node [
- id 199
- label "R_Node:239"
- active 0
- pos 47.46214321681431
- pos 45.631482805524556
- ]
- node [
- id 200
- label "R_Node:200"
- active 0
- pos 52.64248085021973
- pos 70.52762031555176
- ]
- node [
- id 201
- label "R_Node:148"
- active 0
- pos 126.97246551513672
- pos 139.7107391357422
- ]
- node [
- id 202
- label "R_Node:149"
- active 0
- pos 127.31443786621094
- pos 133.76632690429688
- ]
- node [
- id 203
- label "R_Node:144"
- active 0
- pos 109.34207153320312
- pos 135.46420288085938
- ]
- node [
- id 204
- label "R_Node:145"
- active 0
- pos 115.02513122558594
- pos 138.55552673339844
- ]
- node [
- id 205
- label "R_Node:146"
- active 0
- pos 122.10986328125
- pos 143.45484924316406
- ]
- node [
- id 206
- label "R_Node:147"
- active 0
- pos 126.17327880859375
- pos 144.59207153320312
- ]
- node [
- id 207
- label "R_Node:141"
- active 0
- pos 94.5787353515625
- pos 125.63873291015625
- ]
- node [
- id 208
- label "R_Node:142"
- active 0
- pos 94.33634185791016
- pos 130.40090942382812
- ]
- node [
- id 209
- label "R_Node:143"
- active 0
- pos 102.3397216796875
- pos 132.2660369873047
- ]
- node [
- id 210
- label "R_Node:170"
- active 0
- pos 33.52789354324341
- pos 14.70414924621582
- ]
- edge [
- source 0
- target 87
- weight 2.0448861860374254
- ]
- edge [
- source 1
- target 10
- weight 2.0448861860374254
- ]
- edge [
- source 2
- target 76
- weight 2.4880339864663137
- ]
- edge [
- source 2
- target 62
- weight 2.4787581406772756
- ]
- edge [
- source 3
- target 1
- weight 2.0448861860374272
- ]
- edge [
- source 4
- target 55
- weight 3.531514491976503
- ]
- edge [
- source 5
- target 195
- weight 2.0448861860374272
- ]
- edge [
- source 6
- target 35
- weight 2.084872062095129
- ]
- edge [
- source 7
- target 8
- weight 2.624457564826845
- ]
- edge [
- source 8
- target 9
- weight 2.624457564826847
- ]
- edge [
- source 9
- target 170
- weight 1.597533790282889
- ]
- edge [
- source 10
- target 5
- weight 2.044886186037433
- ]
- edge [
- source 11
- target 12
- weight 2.153423713184546
- ]
- edge [
- source 12
- target 13
- weight 2.153423713184542
- ]
- edge [
- source 13
- target 14
- weight 2.153423713184542
- ]
- edge [
- source 14
- target 4
- weight 2.153423713184546
- ]
- edge [
- source 15
- target 16
- weight 13.529135708458513
- ]
- edge [
- source 15
- target 22
- weight 9.66540209680202
- ]
- edge [
- source 16
- target 15
- weight 13.529135708458513
- ]
- edge [
- source 16
- target 208
- weight 6.921383948169974
- ]
- edge [
- source 17
- target 60
- weight 2.391019673919837
- ]
- edge [
- source 17
- target 18
- weight 10.311574095385176
- ]
- edge [
- source 17
- target 49
- weight 3.604822830627851
- ]
- edge [
- source 18
- target 17
- weight 10.311574095385176
- ]
- edge [
- source 18
- target 202
- weight 6.6018993975102465
- ]
- edge [
- source 19
- target 24
- weight 5.881271448470269
- ]
- edge [
- source 19
- target 20
- weight 6.180414768349075
- ]
- edge [
- source 20
- target 19
- weight 6.180414768349075
- ]
- edge [
- source 20
- target 21
- weight 6.061567486527633
- ]
- edge [
- source 21
- target 20
- weight 6.061567486527633
- ]
- edge [
- source 21
- target 22
- weight 5.092630429679632
- ]
- edge [
- source 22
- target 15
- weight 9.66540209680202
- ]
- edge [
- source 22
- target 21
- weight 5.092630429679632
- ]
- edge [
- source 23
- target 189
- weight 3.458521692634201
- ]
- edge [
- source 23
- target 24
- weight 5.447599358098232
- ]
- edge [
- source 24
- target 23
- weight 5.447599358098232
- ]
- edge [
- source 24
- target 19
- weight 5.881271448470269
- ]
- edge [
- source 25
- target 39
- weight 2.084872062095129
- ]
- edge [
- source 26
- target 31
- weight 2.084872062095129
- ]
- edge [
- source 27
- target 41
- weight 2.084872062095129
- ]
- edge [
- source 28
- target 29
- weight 2.4814217402405596
- ]
- edge [
- source 28
- target 32
- weight 2.0253501226928665
- ]
- edge [
- source 29
- target 28
- weight 2.4814217402405596
- ]
- edge [
- source 29
- target 62
- weight 2.000182548123138
- ]
- edge [
- source 30
- target 32
- weight 2.0041354036857046
- ]
- edge [
- source 30
- target 42
- weight 2.416283817572408
- ]
- edge [
- source 31
- target 198
- weight 2.0848720620951293
- ]
- edge [
- source 32
- target 28
- weight 2.0253501226928665
- ]
- edge [
- source 32
- target 30
- weight 2.0041354036857046
- ]
- edge [
- source 33
- target 7
- weight 2.624457564826847
- ]
- edge [
- source 34
- target 33
- weight 3.169063260658222
- ]
- edge [
- source 35
- target 34
- weight 2.084872062095125
- ]
- edge [
- source 36
- target 42
- weight 2.4694323831184835
- ]
- edge [
- source 36
- target 51
- weight 2.0246374634485824
- ]
- edge [
- source 37
- target 6
- weight 2.084872062095125
- ]
- edge [
- source 38
- target 210
- weight 2.0448861860374294
- ]
- edge [
- source 39
- target 61
- weight 2.084872062095129
- ]
- edge [
- source 40
- target 153
- weight 2.170905746330924
- ]
- edge [
- source 41
- target 25
- weight 2.084872062095129
- ]
- edge [
- source 42
- target 30
- weight 2.416283817572408
- ]
- edge [
- source 42
- target 36
- weight 2.4694323831184835
- ]
- edge [
- source 43
- target 44
- weight 2.4824360255994344
- ]
- edge [
- source 43
- target 53
- weight 2.4718892505370196
- ]
- edge [
- source 44
- target 43
- weight 2.4824360255994344
- ]
- edge [
- source 44
- target 45
- weight 2.492840415541141
- ]
- edge [
- source 45
- target 44
- weight 2.492840415541141
- ]
- edge [
- source 45
- target 46
- weight 2.440209439388722
- ]
- edge [
- source 46
- target 45
- weight 2.440209439388722
- ]
- edge [
- source 46
- target 47
- weight 2.484728481718801
- ]
- edge [
- source 47
- target 46
- weight 2.484728481718801
- ]
- edge [
- source 47
- target 48
- weight 2.001685088476564
- ]
- edge [
- source 48
- target 47
- weight 2.001685088476564
- ]
- edge [
- source 48
- target 49
- weight 2.0023572140021275
- ]
- edge [
- source 49
- target 17
- weight 3.604822830627851
- ]
- edge [
- source 49
- target 48
- weight 2.0023572140021275
- ]
- edge [
- source 49
- target 50
- weight 2.0002270006186693
- ]
- edge [
- source 50
- target 60
- weight 2.026996038737844
- ]
- edge [
- source 50
- target 49
- weight 2.0002270006186693
- ]
- edge [
- source 51
- target 36
- weight 2.0246374634485824
- ]
- edge [
- source 51
- target 152
- weight 2.480453759715073
- ]
- edge [
- source 52
- target 100
- weight 2.0156676009878
- ]
- edge [
- source 52
- target 53
- weight 2.4482202321602267
- ]
- edge [
- source 53
- target 43
- weight 2.4718892505370196
- ]
- edge [
- source 53
- target 52
- weight 2.4482202321602267
- ]
- edge [
- source 54
- target 154
- weight 2.0887572908075014
- ]
- edge [
- source 55
- target 190
- weight 7.095026418166703
- ]
- edge [
- source 55
- target 58
- weight 3.7181873904041565
- ]
- edge [
- source 55
- target 56
- weight 2.2918477014027667
- ]
- edge [
- source 56
- target 168
- weight 2.004575681197983
- ]
- edge [
- source 56
- target 55
- weight 2.2918477014027667
- ]
- edge [
- source 57
- target 54
- weight 2.088757290807486
- ]
- edge [
- source 58
- target 193
- weight 2.0448861860374294
- ]
- edge [
- source 59
- target 60
- weight 2.023556332782071
- ]
- edge [
- source 59
- target 70
- weight 2.013317069105941
- ]
- edge [
- source 60
- target 59
- weight 2.023556332782071
- ]
- edge [
- source 60
- target 17
- weight 2.391019673919837
- ]
- edge [
- source 60
- target 50
- weight 2.026996038737844
- ]
- edge [
- source 61
- target 37
- weight 2.0848720620951293
- ]
- edge [
- source 62
- target 29
- weight 2.000182548123138
- ]
- edge [
- source 62
- target 2
- weight 2.4787581406772756
- ]
- edge [
- source 63
- target 64
- weight 2.011803065368662
- ]
- edge [
- source 63
- target 126
- weight 2.3776189895940814
- ]
- edge [
- source 64
- target 63
- weight 2.011803065368662
- ]
- edge [
- source 64
- target 65
- weight 2.433453315264198
- ]
- edge [
- source 65
- target 64
- weight 2.433453315264198
- ]
- edge [
- source 65
- target 66
- weight 2.4963736602906654
- ]
- edge [
- source 66
- target 65
- weight 2.4963736602906654
- ]
- edge [
- source 66
- target 67
- weight 2.4860253757006894
- ]
- edge [
- source 67
- target 66
- weight 2.4860253757006894
- ]
- edge [
- source 67
- target 68
- weight 2.408824157275536
- ]
- edge [
- source 68
- target 67
- weight 2.408824157275536
- ]
- edge [
- source 68
- target 69
- weight 2.058402098912965
- ]
- edge [
- source 69
- target 68
- weight 2.058402098912965
- ]
- edge [
- source 69
- target 70
- weight 2.0917374419386277
- ]
- edge [
- source 70
- target 59
- weight 2.013317069105941
- ]
- edge [
- source 70
- target 69
- weight 2.0917374419386277
- ]
- edge [
- source 71
- target 72
- weight 2.0169441587925045
- ]
- edge [
- source 71
- target 74
- weight 2.1900493856748255
- ]
- edge [
- source 72
- target 71
- weight 2.0169441587925045
- ]
- edge [
- source 72
- target 77
- weight 2.2268105445068924
- ]
- edge [
- source 73
- target 74
- weight 2.1377247294906563
- ]
- edge [
- source 73
- target 84
- weight 2.203485898651859
- ]
- edge [
- source 74
- target 71
- weight 2.1900493856748255
- ]
- edge [
- source 74
- target 73
- weight 2.1377247294906563
- ]
- edge [
- source 75
- target 76
- weight 2.4336626502718786
- ]
- edge [
- source 75
- target 78
- weight 2.453506470485739
- ]
- edge [
- source 76
- target 75
- weight 2.4336626502718786
- ]
- edge [
- source 76
- target 2
- weight 2.4880339864663137
- ]
- edge [
- source 77
- target 72
- weight 2.2268105445068924
- ]
- edge [
- source 77
- target 78
- weight 2.395009498157154
- ]
- edge [
- source 78
- target 75
- weight 2.453506470485739
- ]
- edge [
- source 78
- target 77
- weight 2.395009498157154
- ]
- edge [
- source 79
- target 80
- weight 2.0097202911722882
- ]
- edge [
- source 80
- target 85
- weight 2.31111402055776
- ]
- edge [
- source 81
- target 82
- weight 2.0097202911722802
- ]
- edge [
- source 82
- target 79
- weight 2.0097202911722882
- ]
- edge [
- source 83
- target 84
- weight 2.065662943630219
- ]
- edge [
- source 84
- target 73
- weight 2.203485898651859
- ]
- edge [
- source 84
- target 83
- weight 2.065662943630219
- ]
- edge [
- source 85
- target 86
- weight 2.084872062095129
- ]
- edge [
- source 86
- target 26
- weight 2.084872062095129
- ]
- edge [
- source 87
- target 3
- weight 2.044886186037433
- ]
- edge [
- source 88
- target 89
- weight 2.0045768590316304
- ]
- edge [
- source 89
- target 90
- weight 2.0045768590316304
- ]
- edge [
- source 90
- target 91
- weight 2.004576859031627
- ]
- edge [
- source 91
- target 92
- weight 2.004576859031627
- ]
- edge [
- source 92
- target 93
- weight 2.004576859031634
- ]
- edge [
- source 93
- target 94
- weight 2.004576859031627
- ]
- edge [
- source 94
- target 95
- weight 2.004576859031627
- ]
- edge [
- source 95
- target 96
- weight 2.004576859031627
- ]
- edge [
- source 96
- target 97
- weight 2.004576859031634
- ]
- edge [
- source 97
- target 135
- weight 2.004576859031627
- ]
- edge [
- source 98
- target 99
- weight 2.0134815766476266
- ]
- edge [
- source 98
- target 107
- weight 2.460440607573003
- ]
- edge [
- source 99
- target 98
- weight 2.0134815766476266
- ]
- edge [
- source 99
- target 147
- weight 2.00482641603035
- ]
- edge [
- source 100
- target 101
- weight 2.519851108846427
- ]
- edge [
- source 100
- target 52
- weight 2.0156676009878
- ]
- edge [
- source 101
- target 100
- weight 2.519851108846427
- ]
- edge [
- source 101
- target 102
- weight 2.0261176137739882
- ]
- edge [
- source 102
- target 101
- weight 2.0261176137739882
- ]
- edge [
- source 102
- target 103
- weight 2.0449924956209355
- ]
- edge [
- source 103
- target 102
- weight 2.0449924956209355
- ]
- edge [
- source 103
- target 104
- weight 2.0140640330641735
- ]
- edge [
- source 104
- target 103
- weight 2.0140640330641735
- ]
- edge [
- source 104
- target 105
- weight 2.5054821660012996
- ]
- edge [
- source 105
- target 104
- weight 2.5054821660012996
- ]
- edge [
- source 105
- target 106
- weight 2.5136213992816163
- ]
- edge [
- source 106
- target 105
- weight 2.5136213992816163
- ]
- edge [
- source 106
- target 107
- weight 2.0174477288604136
- ]
- edge [
- source 107
- target 98
- weight 2.460440607573003
- ]
- edge [
- source 107
- target 106
- weight 2.0174477288604136
- ]
- edge [
- source 108
- target 81
- weight 2.009720291172295
- ]
- edge [
- source 109
- target 108
- weight 2.009720291172281
- ]
- edge [
- source 110
- target 113
- weight 2.425565488150257
- ]
- edge [
- source 111
- target 110
- weight 2.170905746330924
- ]
- edge [
- source 112
- target 115
- weight 2.3791843214815556
- ]
- edge [
- source 113
- target 112
- weight 2.3791843214815556
- ]
- edge [
- source 114
- target 117
- weight 2.3791843214815556
- ]
- edge [
- source 115
- target 114
- weight 2.3791843214815707
- ]
- edge [
- source 116
- target 109
- weight 2.881220803806643
- ]
- edge [
- source 117
- target 116
- weight 2.3791843214815556
- ]
- edge [
- source 118
- target 119
- weight 2.4199340430964797
- ]
- edge [
- source 118
- target 121
- weight 2.4749700977179923
- ]
- edge [
- source 119
- target 118
- weight 2.4199340430964797
- ]
- edge [
- source 119
- target 124
- weight 2.3983281529442895
- ]
- edge [
- source 120
- target 121
- weight 2.427197135672506
- ]
- edge [
- source 120
- target 127
- weight 2.419547369869957
- ]
- edge [
- source 121
- target 118
- weight 2.4749700977179923
- ]
- edge [
- source 121
- target 120
- weight 2.427197135672506
- ]
- edge [
- source 122
- target 123
- weight 2.3298788517312627
- ]
- edge [
- source 122
- target 207
- weight 10.612961064956258
- ]
- edge [
- source 122
- target 125
- weight 2.2886221242705522
- ]
- edge [
- source 123
- target 122
- weight 2.3298788517312627
- ]
- edge [
- source 123
- target 167
- weight 2.345064300767156
- ]
- edge [
- source 124
- target 119
- weight 2.3983281529442895
- ]
- edge [
- source 124
- target 125
- weight 2.36562222397011
- ]
- edge [
- source 125
- target 122
- weight 2.2886221242705522
- ]
- edge [
- source 125
- target 124
- weight 2.36562222397011
- ]
- edge [
- source 126
- target 63
- weight 2.3776189895940814
- ]
- edge [
- source 126
- target 207
- weight 12.115403500980515
- ]
- edge [
- source 126
- target 127
- weight 2.4532923880969393
- ]
- edge [
- source 127
- target 120
- weight 2.419547369869957
- ]
- edge [
- source 127
- target 126
- weight 2.4532923880969393
- ]
- edge [
- source 128
- target 137
- weight 2.1692437743076782
- ]
- edge [
- source 129
- target 128
- weight 2.169243774307677
- ]
- edge [
- source 130
- target 129
- weight 2.169243774307677
- ]
- edge [
- source 131
- target 130
- weight 3.3984004312346316
- ]
- edge [
- source 132
- target 131
- weight 2.004576859031627
- ]
- edge [
- source 133
- target 132
- weight 2.004576859031627
- ]
- edge [
- source 134
- target 133
- weight 2.004576859031627
- ]
- edge [
- source 135
- target 134
- weight 2.004576859031634
- ]
- edge [
- source 136
- target 200
- weight 2.169243774307677
- ]
- edge [
- source 137
- target 136
- weight 2.169243774307677
- ]
- edge [
- source 138
- target 152
- weight 2.026419997905915
- ]
- edge [
- source 138
- target 139
- weight 2.481737399634923
- ]
- edge [
- source 139
- target 140
- weight 2.4668448880798084
- ]
- edge [
- source 139
- target 138
- weight 2.481737399634923
- ]
- edge [
- source 140
- target 141
- weight 2.4879558477156727
- ]
- edge [
- source 140
- target 139
- weight 2.4668448880798084
- ]
- edge [
- source 141
- target 140
- weight 2.4879558477156727
- ]
- edge [
- source 141
- target 142
- weight 2.4963415324457365
- ]
- edge [
- source 142
- target 141
- weight 2.4963415324457365
- ]
- edge [
- source 142
- target 143
- weight 2.025558191267938
- ]
- edge [
- source 143
- target 142
- weight 2.025558191267938
- ]
- edge [
- source 143
- target 144
- weight 2.0282860407737076
- ]
- edge [
- source 144
- target 143
- weight 2.0282860407737076
- ]
- edge [
- source 144
- target 145
- weight 2.103662676638815
- ]
- edge [
- source 145
- target 144
- weight 2.103662676638815
- ]
- edge [
- source 145
- target 146
- weight 2.090887610489607
- ]
- edge [
- source 146
- target 145
- weight 2.090887610489607
- ]
- edge [
- source 146
- target 147
- weight 2.072892694423823
- ]
- edge [
- source 147
- target 99
- weight 2.00482641603035
- ]
- edge [
- source 147
- target 146
- weight 2.072892694423823
- ]
- edge [
- source 148
- target 149
- weight 2.170905746330924
- ]
- edge [
- source 149
- target 111
- weight 2.170905746330938
- ]
- edge [
- source 150
- target 151
- weight 2.170905746330924
- ]
- edge [
- source 151
- target 40
- weight 2.170905746330938
- ]
- edge [
- source 152
- target 138
- weight 2.026419997905915
- ]
- edge [
- source 152
- target 51
- weight 2.480453759715073
- ]
- edge [
- source 153
- target 148
- weight 2.170905746330922
- ]
- edge [
- source 154
- target 155
- weight 2.088757290807486
- ]
- edge [
- source 155
- target 156
- weight 2.088757290807486
- ]
- edge [
- source 156
- target 157
- weight 2.088757290807499
- ]
- edge [
- source 157
- target 183
- weight 3.8382639059218158
- ]
- edge [
- source 158
- target 159
- weight 2.314715655694063
- ]
- edge [
- source 158
- target 161
- weight 2.3496347494966976
- ]
- edge [
- source 159
- target 158
- weight 2.314715655694063
- ]
- edge [
- source 159
- target 166
- weight 2.301601008214085
- ]
- edge [
- source 160
- target 161
- weight 2.293197245167791
- ]
- edge [
- source 160
- target 163
- weight 2.332225156939092
- ]
- edge [
- source 161
- target 158
- weight 2.3496347494966976
- ]
- edge [
- source 161
- target 160
- weight 2.293197245167791
- ]
- edge [
- source 162
- target 163
- weight 2.331069887621196
- ]
- edge [
- source 162
- target 165
- weight 2.3057704395935716
- ]
- edge [
- source 163
- target 189
- weight 7.347259023555887
- ]
- edge [
- source 163
- target 162
- weight 2.331069887621196
- ]
- edge [
- source 163
- target 160
- weight 2.332225156939092
- ]
- edge [
- source 164
- target 182
- weight 2.2837207896119796
- ]
- edge [
- source 164
- target 165
- weight 2.304288235588618
- ]
- edge [
- source 165
- target 162
- weight 2.3057704395935716
- ]
- edge [
- source 165
- target 164
- weight 2.304288235588618
- ]
- edge [
- source 166
- target 159
- weight 2.301601008214085
- ]
- edge [
- source 166
- target 167
- weight 2.311765047875286
- ]
- edge [
- source 167
- target 123
- weight 2.345064300767156
- ]
- edge [
- source 167
- target 166
- weight 2.311765047875286
- ]
- edge [
- source 168
- target 169
- weight 2.2202482987685563
- ]
- edge [
- source 168
- target 56
- weight 2.004575681197983
- ]
- edge [
- source 169
- target 168
- weight 2.2202482987685563
- ]
- edge [
- source 169
- target 175
- weight 2.305666903350038
- ]
- edge [
- source 170
- target 11
- weight 2.153423713184546
- ]
- edge [
- source 171
- target 172
- weight 2.167944186970709
- ]
- edge [
- source 171
- target 178
- weight 2.300542746851572
- ]
- edge [
- source 172
- target 171
- weight 2.167944186970709
- ]
- edge [
- source 172
- target 188
- weight 3.7128338111758374
- ]
- edge [
- source 172
- target 173
- weight 2.1627011213883724
- ]
- edge [
- source 173
- target 172
- weight 2.1627011213883724
- ]
- edge [
- source 173
- target 174
- weight 2.0175104475585353
- ]
- edge [
- source 174
- target 173
- weight 2.0175104475585353
- ]
- edge [
- source 175
- target 169
- weight 2.305666903350038
- ]
- edge [
- source 175
- target 190
- weight 7.484068105633168
- ]
- edge [
- source 175
- target 176
- weight 2.315590093261279
- ]
- edge [
- source 176
- target 175
- weight 2.315590093261279
- ]
- edge [
- source 176
- target 177
- weight 2.253500473305087
- ]
- edge [
- source 177
- target 176
- weight 2.253500473305087
- ]
- edge [
- source 177
- target 178
- weight 2.1865657137162944
- ]
- edge [
- source 178
- target 171
- weight 2.300542746851572
- ]
- edge [
- source 178
- target 188
- weight 5.255051954765709
- ]
- edge [
- source 178
- target 177
- weight 2.1865657137162944
- ]
- edge [
- source 179
- target 0
- weight 2.044886186037433
- ]
- edge [
- source 180
- target 187
- weight 2.169243774307677
- ]
- edge [
- source 181
- target 180
- weight 2.1692437743076782
- ]
- edge [
- source 182
- target 183
- weight 2.307748177553896
- ]
- edge [
- source 182
- target 164
- weight 2.2837207896119796
- ]
- edge [
- source 183
- target 150
- weight 4.644205909750766
- ]
- edge [
- source 183
- target 189
- weight 7.275467074399795
- ]
- edge [
- source 183
- target 182
- weight 2.307748177553896
- ]
- edge [
- source 184
- target 57
- weight 2.088757290807499
- ]
- edge [
- source 185
- target 184
- weight 2.088757290807486
- ]
- edge [
- source 186
- target 185
- weight 3.805856412199651
- ]
- edge [
- source 187
- target 186
- weight 2.169243774307677
- ]
- edge [
- source 188
- target 172
- weight 3.7128338111758374
- ]
- edge [
- source 188
- target 192
- weight 5.385373378256093
- ]
- edge [
- source 188
- target 178
- weight 5.255051954765709
- ]
- edge [
- source 189
- target 23
- weight 3.458521692634201
- ]
- edge [
- source 189
- target 183
- weight 7.275467074399795
- ]
- edge [
- source 189
- target 163
- weight 7.347259023555887
- ]
- edge [
- source 190
- target 191
- weight 3.617448067513515
- ]
- edge [
- source 190
- target 175
- weight 7.484068105633168
- ]
- edge [
- source 190
- target 55
- weight 7.095026418166703
- ]
- edge [
- source 191
- target 190
- weight 3.617448067513515
- ]
- edge [
- source 191
- target 197
- weight 4.410017082653349
- ]
- edge [
- source 192
- target 188
- weight 5.385373378256093
- ]
- edge [
- source 192
- target 197
- weight 6.629956013859094
- ]
- edge [
- source 193
- target 38
- weight 2.0448861860374272
- ]
- edge [
- source 194
- target 88
- weight 3.0786711954567356
- ]
- edge [
- source 195
- target 194
- weight 2.0448861860374254
- ]
- edge [
- source 196
- target 181
- weight 2.169243774307677
- ]
- edge [
- source 197
- target 191
- weight 4.410017082653349
- ]
- edge [
- source 197
- target 192
- weight 6.629956013859094
- ]
- edge [
- source 198
- target 199
- weight 2.0848720620951218
- ]
- edge [
- source 199
- target 27
- weight 2.084872062095129
- ]
- edge [
- source 200
- target 196
- weight 2.169243774307677
- ]
- edge [
- source 201
- target 206
- weight 4.946322408256132
- ]
- edge [
- source 201
- target 202
- weight 5.954240662440163
- ]
- edge [
- source 202
- target 18
- weight 6.6018993975102465
- ]
- edge [
- source 202
- target 201
- weight 5.954240662440163
- ]
- edge [
- source 203
- target 204
- weight 6.469424288795965
- ]
- edge [
- source 203
- target 209
- weight 7.6981276005095385
- ]
- edge [
- source 204
- target 203
- weight 6.469424288795965
- ]
- edge [
- source 204
- target 205
- weight 8.613755821663979
- ]
- edge [
- source 205
- target 204
- weight 8.613755821663979
- ]
- edge [
- source 205
- target 206
- weight 4.219552142682915
- ]
- edge [
- source 206
- target 205
- weight 4.219552142682915
- ]
- edge [
- source 206
- target 201
- weight 4.946322408256132
- ]
- edge [
- source 207
- target 122
- weight 10.612961064956258
- ]
- edge [
- source 207
- target 126
- weight 12.115403500980515
- ]
- edge [
- source 207
- target 208
- weight 4.768341404842254
- ]
- edge [
- source 208
- target 16
- weight 6.921383948169974
- ]
- edge [
- source 208
- target 207
- weight 4.768341404842254
- ]
- edge [
- source 208
- target 209
- weight 8.21783361961489
- ]
- edge [
- source 209
- target 203
- weight 7.6981276005095385
- ]
- edge [
- source 209
- target 208
- weight 8.21783361961489
- ]
- edge [
- source 210
- target 179
- weight 2.0448861860374272
- ]
-]
diff --git a/EastCampusLiteV5.gml b/EastCampusLiteV5.gml
new file mode 100644
index 00000000..f38d4386
--- /dev/null
+++ b/EastCampusLiteV5.gml
@@ -0,0 +1,4652 @@
+graph [
+ directed 1
+ node [
+ id 0
+ label "R_Node:405"
+ active 0
+ pos 126.32887129350142
+ pos 130.09720542214134
+ ]
+ node [
+ id 1
+ label "R_Node:404"
+ active 0
+ pos 126.16242564808239
+ pos 132.17148382013494
+ ]
+ node [
+ id 2
+ label "R_Node:407"
+ active 0
+ pos 126.66176258433948
+ pos 125.94864862615412
+ ]
+ node [
+ id 3
+ label "R_Node:406"
+ active 0
+ pos 126.49531693892045
+ pos 128.02292702414772
+ ]
+ node [
+ id 4
+ label "R_Node:401"
+ active 0
+ pos 125.66308871182528
+ pos 138.39431901411578
+ ]
+ node [
+ id 5
+ label "R_Node:400"
+ active 0
+ pos 125.49664306640625
+ pos 140.46859741210938
+ ]
+ node [
+ id 6
+ label "R_Node:403"
+ active 0
+ pos 125.99598000266336
+ pos 134.24576221812856
+ ]
+ node [
+ id 7
+ label "R_Node:402"
+ active 0
+ pos 125.82953435724431
+ pos 136.32004061612216
+ ]
+ node [
+ id 8
+ label "R_Node:409"
+ active 0
+ pos 126.99465387517756
+ pos 121.8000918301669
+ ]
+ node [
+ id 9
+ label "R_Node:408"
+ active 0
+ pos 126.82820822975852
+ pos 123.87437022816052
+ ]
+ node [
+ id 10
+ label "R_Node:470"
+ active 0
+ pos 70.37710507710774
+ pos 110.46276982625325
+ ]
+ node [
+ id 11
+ label "R_Node:471"
+ active 0
+ pos 71.95603942871094
+ pos 111.93141174316406
+ ]
+ node [
+ id 12
+ label "R_Node:499"
+ active 0
+ pos 108.2052230834961
+ pos 119.25115203857422
+ ]
+ node [
+ id 13
+ label "R_Node:496"
+ active 0
+ pos 103.8828353881836
+ pos 120.0474624633789
+ ]
+ node [
+ id 14
+ label "R_Node:497"
+ active 0
+ pos 106.19354629516602
+ pos 119.65007400512695
+ ]
+ node [
+ id 15
+ label "R_Node:494"
+ active 0
+ pos 99.26141357421875
+ pos 120.84223937988281
+ ]
+ node [
+ id 16
+ label "R_Node:495"
+ active 0
+ pos 101.57212448120117
+ pos 120.44485092163086
+ ]
+ node [
+ id 17
+ label "R_Node:539"
+ active 0
+ pos 86.37067413330078
+ pos 130.93798828125
+ ]
+ node [
+ id 18
+ label "R_Node:538"
+ active 0
+ pos 84.3013687133789
+ pos 131.54974060058595
+ ]
+ node [
+ id 19
+ label "R_Node:249"
+ active 0
+ pos 44.29695510864258
+ pos 24.146379470825195
+ ]
+ node [
+ id 20
+ label "R_Node:248"
+ active 0
+ pos 45.788658142089844
+ pos 26.94240951538086
+ ]
+ node [
+ id 21
+ label "R_Node:247"
+ active 0
+ pos 45.97460092817034
+ pos 29.01897321428571
+ ]
+ node [
+ id 22
+ label "R_Node:246"
+ active 0
+ pos 46.160543714250835
+ pos 31.095536913190568
+ ]
+ node [
+ id 23
+ label "R_Node:245"
+ active 0
+ pos 46.34648650033133
+ pos 33.17210061209542
+ ]
+ node [
+ id 24
+ label "R_Node:532"
+ active 0
+ pos 71.98013114929199
+ pos 135.6436424255371
+ ]
+ node [
+ id 25
+ label "R_Node:243"
+ active 0
+ pos 46.71837207249233
+ pos 37.32522800990513
+ ]
+ node [
+ id 26
+ label "R_Node:242"
+ active 0
+ pos 46.904314858572825
+ pos 39.40179170880999
+ ]
+ node [
+ id 27
+ label "R_Node:537"
+ active 0
+ pos 82.23206329345703
+ pos 132.16149291992187
+ ]
+ node [
+ id 28
+ label "R_Node:240"
+ active 0
+ pos 47.276200430733816
+ pos 43.5549191066197
+ ]
+ node [
+ id 29
+ label "R_Node:294"
+ active 0
+ pos 167.9210685567653
+ pos 124.57857529660488
+ ]
+ node [
+ id 30
+ label "R_Node:333"
+ active 0
+ pos 208.70319707342918
+ pos 142.62738718885058
+ ]
+ node [
+ id 31
+ label "R_Node:332"
+ active 0
+ pos 210.60300266996342
+ pos 143.33299661189952
+ ]
+ node [
+ id 32
+ label "R_Node:331"
+ active 0
+ pos 212.50280826649768
+ pos 144.03860603494846
+ ]
+ node [
+ id 33
+ label "R_Node:330"
+ active 0
+ pos 214.40261386303192
+ pos 144.74421545799743
+ ]
+ node [
+ id 34
+ label "R_Node:337"
+ active 0
+ pos 201.10397468729224
+ pos 139.80494949665476
+ ]
+ node [
+ id 35
+ label "R_Node:336"
+ active 0
+ pos 203.00378028382647
+ pos 140.5105589197037
+ ]
+ node [
+ id 36
+ label "R_Node:335"
+ active 0
+ pos 204.9035858803607
+ pos 141.21616834275267
+ ]
+ node [
+ id 37
+ label "R_Node:334"
+ active 0
+ pos 206.80339147689494
+ pos 141.9217777658016
+ ]
+ node [
+ id 38
+ label "R_Node:232"
+ active 0
+ pos 48.92604217529297
+ pos 60.30195007324219
+ ]
+ node [
+ id 39
+ label "R_Node:233"
+ active 0
+ pos 48.668678283691406
+ pos 58.30877685546875
+ ]
+ node [
+ id 40
+ label "R_Node:230"
+ active 0
+ pos 49.44076995849609
+ pos 64.28829650878906
+ ]
+ node [
+ id 41
+ label "R_Node:231"
+ active 0
+ pos 49.183406066894534
+ pos 62.29512329101563
+ ]
+ node [
+ id 42
+ label "R_Node:236"
+ active 0
+ pos 48.019971575055806
+ pos 51.861173902239116
+ ]
+ node [
+ id 43
+ label "R_Node:237"
+ active 0
+ pos 47.83402878897531
+ pos 49.78461020333426
+ ]
+ node [
+ id 44
+ label "R_Node:234"
+ active 0
+ pos 48.3918571472168
+ pos 56.01430130004883
+ ]
+ node [
+ id 45
+ label "R_Node:235"
+ active 0
+ pos 48.2059143611363
+ pos 53.93773760114397
+ ]
+ node [
+ id 46
+ label "R_Node:197"
+ active 0
+ pos 51.500187683105466
+ pos 64.12092590332031
+ ]
+ node [
+ id 47
+ label "R_Node:196"
+ active 0
+ pos 51.11942329406738
+ pos 61.985361099243164
+ ]
+ node [
+ id 48
+ label "R_Node:195"
+ active 0
+ pos 50.7386589050293
+ pos 59.849796295166016
+ ]
+ node [
+ id 49
+ label "R_Node:194"
+ active 0
+ pos 50.42509460449219
+ pos 56.46589279174805
+ ]
+ node [
+ id 50
+ label "R_Node:193"
+ active 0
+ pos 50.30574417114258
+ pos 54.46487208775112
+ ]
+ node [
+ id 51
+ label "R_Node:192"
+ active 0
+ pos 50.18639373779297
+ pos 52.46385138375419
+ ]
+ node [
+ id 52
+ label "R_Node:191"
+ active 0
+ pos 50.06704330444336
+ pos 50.46283067975726
+ ]
+ node [
+ id 53
+ label "R_Node:190"
+ active 0
+ pos 49.94769287109375
+ pos 48.461809975760325
+ ]
+ node [
+ id 54
+ label "R_Node:199"
+ active 0
+ pos 52.26171646118164
+ pos 68.39205551147461
+ ]
+ node [
+ id 55
+ label "R_Node:198"
+ active 0
+ pos 51.88095207214356
+ pos 66.25649070739746
+ ]
+ node [
+ id 56
+ label "R_Node:291"
+ active 0
+ pos 162.21566869857463
+ pos 122.53487185214428
+ ]
+ node [
+ id 57
+ label "R_Node:229"
+ active 0
+ pos 49.698133850097655
+ pos 66.2814697265625
+ ]
+ node [
+ id 58
+ label "R_Node:289"
+ active 0
+ pos 158.4120687931142
+ pos 121.17240288917054
+ ]
+ node [
+ id 59
+ label "R_Node:288"
+ active 0
+ pos 156.510268840384
+ pos 120.49116840768367
+ ]
+ node [
+ id 60
+ label "R_Node:228"
+ active 0
+ pos 49.95549774169922
+ pos 68.27464294433594
+ ]
+ node [
+ id 61
+ label "R_Node:283"
+ active 0
+ pos 147.00126907673288
+ pos 117.08499600024933
+ ]
+ node [
+ id 62
+ label "R_Node:282"
+ active 0
+ pos 145.09946912400267
+ pos 116.40376151876247
+ ]
+ node [
+ id 63
+ label "R_Node:281"
+ active 0
+ pos 143.19766917127245
+ pos 115.7225270372756
+ ]
+ node [
+ id 64
+ label "R_Node:280"
+ active 0
+ pos 141.2958692185422
+ pos 115.04129255578873
+ ]
+ node [
+ id 65
+ label "R_Node:287"
+ active 0
+ pos 154.60846888765377
+ pos 119.8099339261968
+ ]
+ node [
+ id 66
+ label "R_Node:286"
+ active 0
+ pos 152.70666893492353
+ pos 119.12869944470994
+ ]
+ node [
+ id 67
+ label "R_Node:285"
+ active 0
+ pos 150.8048689821933
+ pos 118.44746496322307
+ ]
+ node [
+ id 68
+ label "R_Node:284"
+ active 0
+ pos 148.9030690294631
+ pos 117.7662304817362
+ ]
+ node [
+ id 69
+ label "R_Node:575"
+ active 0
+ pos 84.9034194946289
+ pos 120.62381235758464
+ ]
+ node [
+ id 70
+ label "R_Node:574"
+ active 0
+ pos 86.80859375
+ pos 121.26056416829427
+ ]
+ node [
+ id 71
+ label "R_Node:577"
+ active 0
+ pos 81.45442199707031
+ pos 119.49200439453125
+ ]
+ node [
+ id 72
+ label "R_Node:576"
+ active 0
+ pos 82.99824523925781
+ pos 119.987060546875
+ ]
+ node [
+ id 73
+ label "R_Node:478"
+ active 0
+ pos 86.04608154296875
+ pos 119.16532135009766
+ ]
+ node [
+ id 74
+ label "R_Node:479"
+ active 0
+ pos 88.33107452392578
+ pos 119.53241577148438
+ ]
+ node [
+ id 75
+ label "R_Node:573"
+ active 0
+ pos 88.7137680053711
+ pos 121.8973159790039
+ ]
+ node [
+ id 76
+ label "R_Node:572"
+ active 0
+ pos 91.72807312011719
+ pos 121.99597930908203
+ ]
+ node [
+ id 77
+ label "R_Node:474"
+ active 0
+ pos 78.19667510986328
+ pos 115.64808349609375
+ ]
+ node [
+ id 78
+ label "R_Node:475"
+ active 0
+ pos 80.25677795410157
+ pos 116.68274993896485
+ ]
+ node [
+ id 79
+ label "R_Node:476"
+ active 0
+ pos 82.31688079833984
+ pos 117.71741638183593
+ ]
+ node [
+ id 80
+ label "R_Node:477"
+ active 0
+ pos 84.37698364257812
+ pos 118.75208282470703
+ ]
+ node [
+ id 81
+ label "R_Node:579"
+ active 0
+ pos 76.93404388427734
+ pos 117.4376449584961
+ ]
+ node [
+ id 82
+ label "R_Node:578"
+ active 0
+ pos 79.19423294067383
+ pos 118.46482467651367
+ ]
+ node [
+ id 83
+ label "R_Node:472"
+ active 0
+ pos 74.07646942138672
+ pos 113.57875061035156
+ ]
+ node [
+ id 84
+ label "R_Node:473"
+ active 0
+ pos 76.136572265625
+ pos 114.61341705322266
+ ]
+ node [
+ id 85
+ label "R_Node:227"
+ active 0
+ pos 50.21689224243164
+ pos 71.14398193359375
+ ]
+ node [
+ id 86
+ label "R_Node:226"
+ active 0
+ pos 50.74474563598633
+ pos 73.46387176513672
+ ]
+ node [
+ id 87
+ label "R_Node:372"
+ active 0
+ pos 134.61077880859375
+ pos 115.1086196899414
+ ]
+ node [
+ id 88
+ label "R_Node:371"
+ active 0
+ pos 136.510584405128
+ pos 115.81422911299036
+ ]
+ node [
+ id 89
+ label "R_Node:370"
+ active 0
+ pos 138.41039000166222
+ pos 116.51983853603932
+ ]
+ node [
+ id 90
+ label "R_Node:179"
+ active 0
+ pos 48.517520904541016
+ pos 25.382041931152344
+ ]
+ node [
+ id 91
+ label "R_Node:178"
+ active 0
+ pos 46.85200675328573
+ pos 24.195609410603844
+ ]
+ node [
+ id 92
+ label "R_Node:275"
+ active 0
+ pos 60.94453048706055
+ pos 106.27528381347656
+ ]
+ node [
+ id 93
+ label "R_Node:272"
+ active 0
+ pos 9.681283950805664
+ pos -0.7005032896995544
+ ]
+ node [
+ id 94
+ label "R_Node:273"
+ active 0
+ pos 5.183620452880859
+ pos 0.7034059762954712
+ ]
+ node [
+ id 95
+ label "R_Node:270"
+ active 0
+ pos 13.53003215789795
+ pos 5.624235153198242
+ ]
+ node [
+ id 96
+ label "R_Node:271"
+ active 0
+ pos 23.766420364379883
+ pos 9.130175590515137
+ ]
+ node [
+ id 97
+ label "R_Node:171"
+ active 0
+ pos 35.193407694498696
+ pos 15.890581766764324
+ ]
+ node [
+ id 98
+ label "R_Node:170"
+ active 0
+ pos 33.52789354324341
+ pos 14.70414924621582
+ ]
+ node [
+ id 99
+ label "R_Node:173"
+ active 0
+ pos 38.52443599700928
+ pos 18.263446807861328
+ ]
+ node [
+ id 100
+ label "R_Node:172"
+ active 0
+ pos 36.85892184575399
+ pos 17.077014287312828
+ ]
+ node [
+ id 101
+ label "R_Node:175"
+ active 0
+ pos 41.85546429951986
+ pos 20.636311848958336
+ ]
+ node [
+ id 102
+ label "R_Node:174"
+ active 0
+ pos 40.18995014826457
+ pos 19.449879328409832
+ ]
+ node [
+ id 103
+ label "R_Node:177"
+ active 0
+ pos 45.18649260203044
+ pos 23.00917689005534
+ ]
+ node [
+ id 104
+ label "R_Node:176"
+ active 0
+ pos 43.52097845077515
+ pos 21.822744369506836
+ ]
+ node [
+ id 105
+ label "R_Node:277"
+ active 0
+ pos 135.59046936035156
+ pos 112.99758911132812
+ ]
+ node [
+ id 106
+ label "R_Node:308"
+ active 0
+ pos 194.54626789498838
+ pos 134.11585803742105
+ ]
+ node [
+ id 107
+ label "R_Node:309"
+ active 0
+ pos 196.4480678477186
+ pos 134.7970925189079
+ ]
+ node [
+ id 108
+ label "R_Node:302"
+ active 0
+ pos 183.13546817860706
+ pos 130.02845114849984
+ ]
+ node [
+ id 109
+ label "R_Node:303"
+ active 0
+ pos 185.03726813133727
+ pos 130.7096856299867
+ ]
+ node [
+ id 110
+ label "R_Node:300"
+ active 0
+ pos 179.3318682731466
+ pos 128.6659821855261
+ ]
+ node [
+ id 111
+ label "R_Node:301"
+ active 0
+ pos 181.23366822587684
+ pos 129.34721666701296
+ ]
+ node [
+ id 112
+ label "R_Node:306"
+ active 0
+ pos 190.74266798952792
+ pos 132.7533890744473
+ ]
+ node [
+ id 113
+ label "R_Node:307"
+ active 0
+ pos 192.64446794225813
+ pos 133.43462355593417
+ ]
+ node [
+ id 114
+ label "R_Node:304"
+ active 0
+ pos 186.9390680840675
+ pos 131.39092011147358
+ ]
+ node [
+ id 115
+ label "R_Node:305"
+ active 0
+ pos 188.8408680367977
+ pos 132.07215459296043
+ ]
+ node [
+ id 116
+ label "R_Node:531"
+ active 0
+ pos 69.90438461303711
+ pos 136.51065826416016
+ ]
+ node [
+ id 117
+ label "R_Node:278"
+ active 0
+ pos 137.49226931308178
+ pos 113.678823592815
+ ]
+ node [
+ id 118
+ label "R_Node:530"
+ active 0
+ pos 67.82863807678223
+ pos 137.3776741027832
+ ]
+ node [
+ id 119
+ label "R_Node:279"
+ active 0
+ pos 139.394069265812
+ pos 114.36005807430186
+ ]
+ node [
+ id 120
+ label "R_Node:533"
+ active 0
+ pos 74.05587768554688
+ pos 134.77662658691406
+ ]
+ node [
+ id 121
+ label "R_Node:244"
+ active 0
+ pos 46.53242928641183
+ pos 35.248664311000276
+ ]
+ node [
+ id 122
+ label "R_Node:535"
+ active 0
+ pos 78.09345245361328
+ pos 133.38499755859374
+ ]
+ node [
+ id 123
+ label "R_Node:534"
+ active 0
+ pos 76.0241470336914
+ pos 133.9967498779297
+ ]
+ node [
+ id 124
+ label "R_Node:241"
+ active 0
+ pos 47.09025764465332
+ pos 41.478355407714844
+ ]
+ node [
+ id 125
+ label "R_Node:536"
+ active 0
+ pos 80.16275787353516
+ pos 132.77324523925782
+ ]
+ node [
+ id 126
+ label "R_Node:438"
+ active 0
+ pos 95.3791446685791
+ pos 132.47478485107422
+ ]
+ node [
+ id 127
+ label "R_Node:439"
+ active 0
+ pos 93.32544326782227
+ pos 132.47314453125
+ ]
+ node [
+ id 128
+ label "R_Node:437"
+ active 0
+ pos 97.43284606933594
+ pos 132.47642517089844
+ ]
+ node [
+ id 129
+ label "R_Node:566"
+ active 0
+ pos 108.26012929280598
+ pos 120.94359588623047
+ ]
+ node [
+ id 130
+ label "R_Node:295"
+ active 0
+ pos 169.82286850949552
+ pos 125.25980977809175
+ ]
+ node [
+ id 131
+ label "R_Node:564"
+ active 0
+ pos 113.3269271850586
+ pos 119.3891372680664
+ ]
+ node [
+ id 132
+ label "R_Node:565"
+ active 0
+ pos 110.52056121826172
+ pos 120.5362548828125
+ ]
+ node [
+ id 133
+ label "R_Node:290"
+ active 0
+ pos 160.31386874584442
+ pos 121.85363737065741
+ ]
+ node [
+ id 134
+ label "R_Node:481"
+ active 0
+ pos 92.90106048583985
+ pos 120.26660461425782
+ ]
+ node [
+ id 135
+ label "R_Node:480"
+ active 0
+ pos 90.6160675048828
+ pos 119.89951019287109
+ ]
+ node [
+ id 136
+ label "R_Node:482"
+ active 0
+ pos 95.18605346679688
+ pos 120.63369903564453
+ ]
+ node [
+ id 137
+ label "R_Node:292"
+ active 0
+ pos 164.11746865130485
+ pos 123.21610633363115
+ ]
+ node [
+ id 138
+ label "R_Node:293"
+ active 0
+ pos 166.01926860403506
+ pos 123.89734081511801
+ ]
+ node [
+ id 139
+ label "R_Node:508"
+ active 0
+ pos 126.55646006266277
+ pos 112.36990865071614
+ ]
+ node [
+ id 140
+ label "R_Node:509"
+ active 0
+ pos 128.9799041748047
+ pos 112.00094604492188
+ ]
+ node [
+ id 141
+ label "R_Node:504"
+ active 0
+ pos 117.57784525553386
+ pos 115.09004211425781
+ ]
+ node [
+ id 142
+ label "R_Node:505"
+ active 0
+ pos 119.4523696899414
+ pos 114.25782012939453
+ ]
+ node [
+ id 143
+ label "R_Node:506"
+ active 0
+ pos 121.7095718383789
+ pos 113.10783386230469
+ ]
+ node [
+ id 144
+ label "R_Node:507"
+ active 0
+ pos 124.13301595052083
+ pos 112.73887125651042
+ ]
+ node [
+ id 145
+ label "R_Node:500"
+ active 0
+ pos 110.07974751790364
+ pos 118.41893005371094
+ ]
+ node [
+ id 146
+ label "R_Node:501"
+ active 0
+ pos 111.9542719523112
+ pos 117.58670806884766
+ ]
+ node [
+ id 147
+ label "R_Node:502"
+ active 0
+ pos 113.82879638671875
+ pos 116.75448608398438
+ ]
+ node [
+ id 148
+ label "R_Node:503"
+ active 0
+ pos 115.7033208211263
+ pos 115.9222640991211
+ ]
+ node [
+ id 149
+ label "R_Node:445"
+ active 0
+ pos 78.92100715637207
+ pos 134.70959091186523
+ ]
+ node [
+ id 150
+ label "R_Node:444"
+ active 0
+ pos 81.2151985168457
+ pos 134.0921401977539
+ ]
+ node [
+ id 151
+ label "R_Node:447"
+ active 0
+ pos 73.31144714355469
+ pos 137.0347442626953
+ ]
+ node [
+ id 152
+ label "R_Node:446"
+ active 0
+ pos 76.62681579589844
+ pos 135.32704162597656
+ ]
+ node [
+ id 153
+ label "R_Node:346"
+ active 0
+ pos 184.00572431848406
+ pos 133.45446468921418
+ ]
+ node [
+ id 154
+ label "R_Node:347"
+ active 0
+ pos 182.1059187219498
+ pos 132.74885526616524
+ ]
+ node [
+ id 155
+ label "R_Node:344"
+ active 0
+ pos 187.80533551155253
+ pos 134.8656835353121
+ ]
+ node [
+ id 156
+ label "R_Node:345"
+ active 0
+ pos 185.9055299150183
+ pos 134.16007411226315
+ ]
+ node [
+ id 157
+ label "R_Node:342"
+ active 0
+ pos 191.604946704621
+ pos 136.27690238141
+ ]
+ node [
+ id 158
+ label "R_Node:343"
+ active 0
+ pos 189.70514110808676
+ pos 135.57129295836103
+ ]
+ node [
+ id 159
+ label "R_Node:340"
+ active 0
+ pos 195.4045578976895
+ pos 137.6881212275079
+ ]
+ node [
+ id 160
+ label "R_Node:341"
+ active 0
+ pos 193.50475230115526
+ pos 136.98251180445894
+ ]
+ node [
+ id 161
+ label "R_Node:221"
+ active 0
+ pos 53.337608337402344
+ pos 85.12073516845703
+ ]
+ node [
+ id 162
+ label "R_Node:220"
+ active 0
+ pos 54.04327665056501
+ pos 87.17374856131417
+ ]
+ node [
+ id 163
+ label "R_Node:223"
+ active 0
+ pos 52.32830581665039
+ pos 80.42354125976563
+ ]
+ node [
+ id 164
+ label "R_Node:222"
+ active 0
+ pos 52.85615921020508
+ pos 82.7434310913086
+ ]
+ node [
+ id 165
+ label "R_Node:225"
+ active 0
+ pos 51.27259902954101
+ pos 75.78376159667968
+ ]
+ node [
+ id 166
+ label "R_Node:224"
+ active 0
+ pos 51.800452423095706
+ pos 78.10365142822266
+ ]
+ node [
+ id 167
+ label "R_Node:348"
+ active 0
+ pos 180.20611312541556
+ pos 132.04324584311627
+ ]
+ node [
+ id 168
+ label "R_Node:349"
+ active 0
+ pos 178.30630752888132
+ pos 131.33763642006733
+ ]
+ node [
+ id 169
+ label "R_Node:589"
+ active 0
+ pos 229.1866912841797
+ pos 146.33322143554688
+ ]
+ node [
+ id 170
+ label "R_Node:251"
+ active 0
+ pos 40.4602165222168
+ pos 20.564404169718426
+ ]
+ node [
+ id 171
+ label "R_Node:548"
+ active 0
+ pos 109.86565399169922
+ pos 134.80704498291016
+ ]
+ node [
+ id 172
+ label "R_Node:549"
+ active 0
+ pos 111.69802284240723
+ pos 135.69972801208496
+ ]
+ node [
+ id 173
+ label "R_Node:540"
+ active 0
+ pos 90.82673645019531
+ pos 130.15594482421875
+ ]
+ node [
+ id 174
+ label "R_Node:541"
+ active 0
+ pos 93.16297912597656
+ pos 130.05372111002603
+ ]
+ node [
+ id 175
+ label "R_Node:542"
+ active 0
+ pos 95.49922180175781
+ pos 129.95149739583334
+ ]
+ node [
+ id 176
+ label "R_Node:543"
+ active 0
+ pos 97.83546447753906
+ pos 129.84927368164062
+ ]
+ node [
+ id 177
+ label "R_Node:544"
+ active 0
+ pos 102.53617858886719
+ pos 131.23631286621094
+ ]
+ node [
+ id 178
+ label "R_Node:545"
+ active 0
+ pos 104.3685474395752
+ pos 132.12899589538574
+ ]
+ node [
+ id 179
+ label "R_Node:546"
+ active 0
+ pos 106.2009162902832
+ pos 133.02167892456055
+ ]
+ node [
+ id 180
+ label "R_Node:547"
+ active 0
+ pos 108.03328514099121
+ pos 133.91436195373535
+ ]
+ node [
+ id 181
+ label "R_Node:463"
+ active 0
+ pos 61.36751492818197
+ pos 110.5137201944987
+ ]
+ node [
+ id 182
+ label "R_Node:462"
+ active 0
+ pos 61.439013163248696
+ pos 112.68739827473958
+ ]
+ node [
+ id 183
+ label "R_Node:461"
+ active 0
+ pos 61.51051139831543
+ pos 114.86107635498047
+ ]
+ node [
+ id 184
+ label "R_Node:460"
+ active 0
+ pos 61.582009633382164
+ pos 117.03475443522136
+ ]
+ node [
+ id 185
+ label "R_Node:467"
+ active 0
+ pos 65.64030202229817
+ pos 106.05684407552083
+ ]
+ node [
+ id 186
+ label "R_Node:466"
+ active 0
+ pos 64.06136767069499
+ pos 104.58820215861003
+ ]
+ node [
+ id 187
+ label "R_Node:465"
+ active 0
+ pos 62.4824333190918
+ pos 103.11956024169922
+ ]
+ node [
+ id 188
+ label "R_Node:464"
+ active 0
+ pos 61.296016693115234
+ pos 108.34004211425781
+ ]
+ node [
+ id 189
+ label "R_Node:469"
+ active 0
+ pos 68.79817072550456
+ pos 108.99412790934245
+ ]
+ node [
+ id 190
+ label "R_Node:468"
+ active 0
+ pos 67.21923637390137
+ pos 107.52548599243164
+ ]
+ node [
+ id 191
+ label "R_Node:238"
+ active 0
+ pos 47.64808600289481
+ pos 47.708046504429404
+ ]
+ node [
+ id 192
+ label "R_Node:239"
+ active 0
+ pos 47.46214321681431
+ pos 45.631482805524556
+ ]
+ node [
+ id 193
+ label "R_Node:388"
+ active 0
+ pos 129.69590759277344
+ pos 117.93450164794922
+ ]
+ node [
+ id 194
+ label "R_Node:389"
+ active 0
+ pos 129.51547171852806
+ pos 120.10107699307528
+ ]
+ node [
+ id 195
+ label "R_Node:265"
+ active 0
+ pos 13.253376007080078
+ pos -3.6941885948181152
+ ]
+ node [
+ id 196
+ label "R_Node:264"
+ active 0
+ pos 20.0776309967041
+ pos -3.232879638671875
+ ]
+ node [
+ id 197
+ label "R_Node:267"
+ active 0
+ pos 7.81241512298584
+ pos 3.8712637424468994
+ ]
+ node [
+ id 198
+ label "R_Node:261"
+ active 0
+ pos 19.063213348388672
+ pos 9.868268966674805
+ ]
+ node [
+ id 199
+ label "R_Node:263"
+ active 0
+ pos 22.475341796875
+ pos 0.4575856924057007
+ ]
+ node [
+ id 200
+ label "R_Node:262"
+ active 0
+ pos 22.106464385986328
+ pos 6.085541725158691
+ ]
+ node [
+ id 201
+ label "R_Node:269"
+ active 0
+ pos 8.457951545715332
+ pos 2.4873392581939697
+ ]
+ node [
+ id 202
+ label "R_Node:268"
+ active 0
+ pos 13.345596313476562
+ pos 6.823634624481201
+ ]
+ node [
+ id 203
+ label "R_Node:339"
+ active 0
+ pos 197.30436349422374
+ pos 138.39373065055685
+ ]
+ node [
+ id 204
+ label "R_Node:338"
+ active 0
+ pos 199.20416909075797
+ pos 139.0993400736058
+ ]
+ node [
+ id 205
+ label "R_Node:319"
+ active 0
+ pos 215.46606737502077
+ pos 141.6094373337766
+ ]
+ node [
+ id 206
+ label "R_Node:318"
+ active 0
+ pos 213.56426742229056
+ pos 140.92820285228973
+ ]
+ node [
+ id 207
+ label "R_Node:311"
+ active 0
+ pos 200.25166775317902
+ pos 136.15956148188164
+ ]
+ node [
+ id 208
+ label "R_Node:310"
+ active 0
+ pos 198.3498678004488
+ pos 135.47832700039478
+ ]
+ node [
+ id 209
+ label "R_Node:313"
+ active 0
+ pos 204.05526765863948
+ pos 137.52203044485537
+ ]
+ node [
+ id 210
+ label "R_Node:312"
+ active 0
+ pos 202.15346770590924
+ pos 136.84079596336852
+ ]
+ node [
+ id 211
+ label "R_Node:315"
+ active 0
+ pos 207.8588675640999
+ pos 138.88449940782914
+ ]
+ node [
+ id 212
+ label "R_Node:314"
+ active 0
+ pos 205.95706761136967
+ pos 138.20326492634226
+ ]
+ node [
+ id 213
+ label "R_Node:317"
+ active 0
+ pos 211.66246746956034
+ pos 140.24696837080285
+ ]
+ node [
+ id 214
+ label "R_Node:316"
+ active 0
+ pos 209.76066751683013
+ pos 139.565733889316
+ ]
+ node [
+ id 215
+ label "R_Node:168"
+ active 0
+ pos 30.19686524073283
+ pos 12.331284205118815
+ ]
+ node [
+ id 216
+ label "R_Node:169"
+ active 0
+ pos 31.862379391988117
+ pos 13.517716725667318
+ ]
+ node [
+ id 217
+ label "R_Node:258"
+ active 0
+ pos 27.437116622924805
+ pos 13.336549758911133
+ ]
+ node [
+ id 218
+ label "R_Node:393"
+ active 0
+ pos 128.79372822154653
+ pos 128.76737837357956
+ ]
+ node [
+ id 219
+ label "R_Node:529"
+ active 0
+ pos 65.75289154052734
+ pos 138.24468994140625
+ ]
+ node [
+ id 220
+ label "R_Node:584"
+ active 0
+ pos 67.94364356994629
+ pos 110.93163871765137
+ ]
+ node [
+ id 221
+ label "R_Node:585"
+ active 0
+ pos 66.33842849731445
+ pos 109.7099494934082
+ ]
+ node [
+ id 222
+ label "R_Node:586"
+ active 0
+ pos 64.73321342468262
+ pos 108.48826026916504
+ ]
+ node [
+ id 223
+ label "R_Node:587"
+ active 0
+ pos 63.12799835205078
+ pos 107.26657104492188
+ ]
+ node [
+ id 224
+ label "R_Node:580"
+ active 0
+ pos 75.33075714111328
+ pos 116.59120178222656
+ ]
+ node [
+ id 225
+ label "R_Node:581"
+ active 0
+ pos 73.09071350097656
+ pos 115.0128173828125
+ ]
+ node [
+ id 226
+ label "R_Node:582"
+ active 0
+ pos 70.85066986083984
+ pos 113.43443298339844
+ ]
+ node [
+ id 227
+ label "R_Node:583"
+ active 0
+ pos 69.54885864257812
+ pos 112.15332794189453
+ ]
+ node [
+ id 228
+ label "R_Node:422"
+ active 0
+ pos 101.05796813964844
+ pos 132.81764221191406
+ ]
+ node [
+ id 229
+ label "R_Node:421"
+ active 0
+ pos 102.96003646850586
+ pos 133.7566909790039
+ ]
+ node [
+ id 230
+ label "R_Node:420"
+ active 0
+ pos 104.86210479736329
+ pos 134.69573974609375
+ ]
+ node [
+ id 231
+ label "R_Node:250"
+ active 0
+ pos 42.37858581542969
+ pos 22.35539182027181
+ ]
+ node [
+ id 232
+ label "R_Node:398"
+ active 0
+ pos 127.89154885031961
+ pos 139.60025509920987
+ ]
+ node [
+ id 233
+ label "R_Node:252"
+ active 0
+ pos 38.541847229003906
+ pos 18.77341651916504
+ ]
+ node [
+ id 234
+ label "R_Node:253"
+ active 0
+ pos 37.09257125854492
+ pos 18.101320266723633
+ ]
+ node [
+ id 235
+ label "R_Node:526"
+ active 0
+ pos 63.510460662841794
+ pos 132.88221435546876
+ ]
+ node [
+ id 236
+ label "R_Node:527"
+ active 0
+ pos 63.285498046875
+ pos 135.09158172607422
+ ]
+ node [
+ id 237
+ label "R_Node:256"
+ active 0
+ pos 31.29929847717285
+ pos 15.242457962036132
+ ]
+ node [
+ id 238
+ label "R_Node:257"
+ active 0
+ pos 29.36820755004883
+ pos 14.289503860473634
+ ]
+ node [
+ id 239
+ label "R_Node:513"
+ active 0
+ pos 89.8988265991211
+ pos 128.95999145507812
+ ]
+ node [
+ id 240
+ label "R_Node:512"
+ active 0
+ pos 99.23931121826172
+ pos 128.9898681640625
+ ]
+ node [
+ id 241
+ label "R_Node:458"
+ active 0
+ pos 61.725006103515625
+ pos 121.38211059570312
+ ]
+ node [
+ id 242
+ label "R_Node:459"
+ active 0
+ pos 61.65350786844889
+ pos 119.20843251546223
+ ]
+ node [
+ id 243
+ label "R_Node:517"
+ active 0
+ pos 64.3510144551595
+ pos 111.53230158487956
+ ]
+ node [
+ id 244
+ label "R_Node:516"
+ active 0
+ pos 64.33849334716797
+ pos 109.28131103515625
+ ]
+ node [
+ id 245
+ label "R_Node:515"
+ active 0
+ pos 90.18960571289062
+ pos 123.43578338623047
+ ]
+ node [
+ id 246
+ label "R_Node:514"
+ active 0
+ pos 90.04421615600586
+ pos 126.1978874206543
+ ]
+ node [
+ id 247
+ label "R_Node:452"
+ active 0
+ pos 61.14606857299805
+ pos 135.52987670898438
+ ]
+ node [
+ id 248
+ label "R_Node:453"
+ active 0
+ pos 61.28652420043945
+ pos 133.4188674926758
+ ]
+ node [
+ id 249
+ label "R_Node:519"
+ active 0
+ pos 64.37605667114258
+ pos 116.03428268432617
+ ]
+ node [
+ id 250
+ label "R_Node:518"
+ active 0
+ pos 64.36353556315105
+ pos 113.78329213460286
+ ]
+ node [
+ id 251
+ label "R_Node:456"
+ active 0
+ pos 61.70789108276367
+ pos 127.08583984375
+ ]
+ node [
+ id 252
+ label "R_Node:457"
+ active 0
+ pos 61.84834671020508
+ pos 124.9748306274414
+ ]
+ node [
+ id 253
+ label "R_Node:454"
+ active 0
+ pos 61.42697982788086
+ pos 131.3078582763672
+ ]
+ node [
+ id 254
+ label "R_Node:455"
+ active 0
+ pos 61.56743545532227
+ pos 129.19684906005858
+ ]
+ node [
+ id 255
+ label "R_Node:511"
+ active 0
+ pos 99.34874725341797
+ pos 126.38595962524414
+ ]
+ node [
+ id 256
+ label "R_Node:510"
+ active 0
+ pos 99.45818328857422
+ pos 123.78205108642578
+ ]
+ node [
+ id 257
+ label "R_Node:450"
+ active 0
+ pos 67.5706672668457
+ pos 140.12034606933594
+ ]
+ node [
+ id 258
+ label "R_Node:355"
+ active 0
+ pos 166.90747394967588
+ pos 127.1039798817736
+ ]
+ node [
+ id 259
+ label "R_Node:354"
+ active 0
+ pos 168.8072795462101
+ pos 127.80958930482255
+ ]
+ node [
+ id 260
+ label "R_Node:357"
+ active 0
+ pos 163.10786275660737
+ pos 125.6927610356757
+ ]
+ node [
+ id 261
+ label "R_Node:451"
+ active 0
+ pos 65.65707397460938
+ pos 141.1488800048828
+ ]
+ node [
+ id 262
+ label "R_Node:351"
+ active 0
+ pos 174.50669633581282
+ pos 129.92641757396942
+ ]
+ node [
+ id 263
+ label "R_Node:350"
+ active 0
+ pos 176.40650193234708
+ pos 130.63202699701836
+ ]
+ node [
+ id 264
+ label "R_Node:353"
+ active 0
+ pos 170.70708514274435
+ pos 128.5151987278715
+ ]
+ node [
+ id 265
+ label "R_Node:352"
+ active 0
+ pos 172.60689073927858
+ pos 129.22080815092045
+ ]
+ node [
+ id 266
+ label "R_Node:214"
+ active 0
+ pos 58.277286529541016
+ pos 99.49182891845703
+ ]
+ node [
+ id 267
+ label "R_Node:215"
+ active 0
+ pos 57.57161821637835
+ pos 97.43881552559989
+ ]
+ node [
+ id 268
+ label "R_Node:216"
+ active 0
+ pos 56.86594990321568
+ pos 95.38580213274274
+ ]
+ node [
+ id 269
+ label "R_Node:217"
+ active 0
+ pos 56.16028159005301
+ pos 93.3327887398856
+ ]
+ node [
+ id 270
+ label "R_Node:210"
+ active 0
+ pos 58.41413170950754
+ pos 92.72304861886161
+ ]
+ node [
+ id 271
+ label "R_Node:358"
+ active 0
+ pos 161.20805716007314
+ pos 124.98715161262675
+ ]
+ node [
+ id 272
+ label "R_Node:448"
+ active 0
+ pos 71.39785385131836
+ pos 138.0632781982422
+ ]
+ node [
+ id 273
+ label "R_Node:559"
+ active 0
+ pos 124.39880752563477
+ pos 114.96366500854492
+ ]
+ node [
+ id 274
+ label "R_Node:558"
+ active 0
+ pos 126.9132080078125
+ pos 114.74713897705078
+ ]
+ node [
+ id 275
+ label "R_Node:557"
+ active 0
+ pos 122.32067108154297
+ pos 143.33338928222656
+ ]
+ node [
+ id 276
+ label "R_Node:556"
+ active 0
+ pos 124.96231079101562
+ pos 144.14073181152344
+ ]
+ node [
+ id 277
+ label "R_Node:555"
+ active 0
+ pos 123.02173614501953
+ pos 141.43768310546875
+ ]
+ node [
+ id 278
+ label "R_Node:554"
+ active 0
+ pos 120.79087829589844
+ pos 140.38500213623047
+ ]
+ node [
+ id 279
+ label "R_Node:553"
+ active 0
+ pos 118.56002044677734
+ pos 139.3323211669922
+ ]
+ node [
+ id 280
+ label "R_Node:552"
+ active 0
+ pos 117.19512939453125
+ pos 138.37777709960938
+ ]
+ node [
+ id 281
+ label "R_Node:551"
+ active 0
+ pos 115.36276054382324
+ pos 137.48509407043457
+ ]
+ node [
+ id 282
+ label "R_Node:550"
+ active 0
+ pos 113.53039169311523
+ pos 136.59241104125977
+ ]
+ node [
+ id 283
+ label "R_Node:416"
+ active 0
+ pos 112.47037811279297
+ pos 138.45193481445312
+ ]
+ node [
+ id 284
+ label "R_Node:417"
+ active 0
+ pos 110.56830978393555
+ pos 137.51288604736328
+ ]
+ node [
+ id 285
+ label "R_Node:414"
+ active 0
+ pos 116.2745147705078
+ pos 140.3300323486328
+ ]
+ node [
+ id 286
+ label "R_Node:415"
+ active 0
+ pos 114.3724464416504
+ pos 139.39098358154297
+ ]
+ node [
+ id 287
+ label "R_Node:412"
+ active 0
+ pos 120.07865142822266
+ pos 142.2081298828125
+ ]
+ node [
+ id 288
+ label "R_Node:413"
+ active 0
+ pos 118.17658309936523
+ pos 141.26908111572266
+ ]
+ node [
+ id 289
+ label "R_Node:410"
+ active 0
+ pos 127.1610995205966
+ pos 119.7258134321733
+ ]
+ node [
+ id 290
+ label "R_Node:411"
+ active 0
+ pos 127.32754516601562
+ pos 117.65153503417969
+ ]
+ node [
+ id 291
+ label "R_Node:418"
+ active 0
+ pos 108.66624145507812
+ pos 136.57383728027344
+ ]
+ node [
+ id 292
+ label "R_Node:419"
+ active 0
+ pos 106.7641731262207
+ pos 135.6347885131836
+ ]
+ node [
+ id 293
+ label "R_Node:391"
+ active 0
+ pos 129.15459997003728
+ pos 124.43422768332742
+ ]
+ node [
+ id 294
+ label "R_Node:390"
+ active 0
+ pos 129.33503584428266
+ pos 122.26765233820134
+ ]
+ node [
+ id 295
+ label "R_Node:528"
+ active 0
+ pos 63.0605354309082
+ pos 137.3009490966797
+ ]
+ node [
+ id 296
+ label "R_Node:392"
+ active 0
+ pos 128.9741640957919
+ pos 126.60080302845348
+ ]
+ node [
+ id 297
+ label "R_Node:395"
+ active 0
+ pos 128.43285647305575
+ pos 133.1005290638317
+ ]
+ node [
+ id 298
+ label "R_Node:394"
+ active 0
+ pos 128.61329234730113
+ pos 130.93395371870562
+ ]
+ node [
+ id 299
+ label "R_Node:397"
+ active 0
+ pos 128.071984724565
+ pos 137.4336797540838
+ ]
+ node [
+ id 300
+ label "R_Node:396"
+ active 0
+ pos 128.25242059881037
+ pos 135.26710440895775
+ ]
+ node [
+ id 301
+ label "R_Node:399"
+ active 0
+ pos 127.71111297607422
+ pos 141.76683044433594
+ ]
+ node [
+ id 302
+ label "R_Node:523"
+ active 0
+ pos 64.18534851074219
+ pos 126.25411224365234
+ ]
+ node [
+ id 303
+ label "R_Node:520"
+ active 0
+ pos 64.38857777913411
+ pos 118.28527323404948
+ ]
+ node [
+ id 304
+ label "R_Node:521"
+ active 0
+ pos 64.40109888712566
+ pos 120.53626378377278
+ ]
+ node [
+ id 305
+ label "R_Node:254"
+ active 0
+ pos 35.1614803314209
+ pos 17.148366165161132
+ ]
+ node [
+ id 306
+ label "R_Node:255"
+ active 0
+ pos 33.23038940429687
+ pos 16.19541206359863
+ ]
+ node [
+ id 307
+ label "R_Node:524"
+ active 0
+ pos 63.96038589477539
+ pos 128.4634796142578
+ ]
+ node [
+ id 308
+ label "R_Node:525"
+ active 0
+ pos 63.7354232788086
+ pos 130.67284698486327
+ ]
+ node [
+ id 309
+ label "R_Node:328"
+ active 0
+ pos 218.2022250561004
+ pos 146.15543430409534
+ ]
+ node [
+ id 310
+ label "R_Node:329"
+ active 0
+ pos 216.30241945956615
+ pos 145.44982488104637
+ ]
+ node [
+ id 311
+ label "R_Node:324"
+ active 0
+ pos 224.97506713867188
+ pos 145.01560974121094
+ ]
+ node [
+ id 312
+ label "R_Node:325"
+ active 0
+ pos 223.90164184570312
+ pos 148.2722625732422
+ ]
+ node [
+ id 313
+ label "R_Node:326"
+ active 0
+ pos 222.0018362491689
+ pos 147.56665315019325
+ ]
+ node [
+ id 314
+ label "R_Node:327"
+ active 0
+ pos 220.10203065263465
+ pos 146.86104372714428
+ ]
+ node [
+ id 315
+ label "R_Node:320"
+ active 0
+ pos 217.36786732775101
+ pos 142.29067181526347
+ ]
+ node [
+ id 316
+ label "R_Node:321"
+ active 0
+ pos 219.2696672804812
+ pos 142.97190629675032
+ ]
+ node [
+ id 317
+ label "R_Node:322"
+ active 0
+ pos 221.17146723321144
+ pos 143.6531407782372
+ ]
+ node [
+ id 318
+ label "R_Node:323"
+ active 0
+ pos 223.07326718594166
+ pos 144.33437525972408
+ ]
+ node [
+ id 319
+ label "R_Node:180"
+ active 0
+ pos 48.754188537597656
+ pos 28.451602935791016
+ ]
+ node [
+ id 320
+ label "R_Node:181"
+ active 0
+ pos 48.873538970947266
+ pos 30.452623639787948
+ ]
+ node [
+ id 321
+ label "R_Node:182"
+ active 0
+ pos 48.992889404296875
+ pos 32.45364434378488
+ ]
+ node [
+ id 322
+ label "R_Node:183"
+ active 0
+ pos 49.112239837646484
+ pos 34.45466504778181
+ ]
+ node [
+ id 323
+ label "R_Node:184"
+ active 0
+ pos 49.231590270996094
+ pos 36.45568575177874
+ ]
+ node [
+ id 324
+ label "R_Node:185"
+ active 0
+ pos 49.3509407043457
+ pos 38.456706455775674
+ ]
+ node [
+ id 325
+ label "R_Node:186"
+ active 0
+ pos 49.47029113769531
+ pos 40.4577271597726
+ ]
+ node [
+ id 326
+ label "R_Node:187"
+ active 0
+ pos 49.58964157104492
+ pos 42.45874786376953
+ ]
+ node [
+ id 327
+ label "R_Node:188"
+ active 0
+ pos 49.70899200439453
+ pos 44.45976856776646
+ ]
+ node [
+ id 328
+ label "R_Node:189"
+ active 0
+ pos 49.82834243774414
+ pos 46.460789271763396
+ ]
+ node [
+ id 329
+ label "R_Node:356"
+ active 0
+ pos 165.00766835314164
+ pos 126.39837045872466
+ ]
+ node [
+ id 330
+ label "R_Node:218"
+ active 0
+ pos 55.45461327689035
+ pos 91.27977534702846
+ ]
+ node [
+ id 331
+ label "R_Node:219"
+ active 0
+ pos 54.74894496372768
+ pos 89.22676195417132
+ ]
+ node [
+ id 332
+ label "R_Node:359"
+ active 0
+ pos 159.3082515635389
+ pos 124.28154218957779
+ ]
+ node [
+ id 333
+ label "R_Node:211"
+ active 0
+ pos 59.13609095982143
+ pos 94.68306950160435
+ ]
+ node [
+ id 334
+ label "R_Node:449"
+ active 0
+ pos 69.48426055908203
+ pos 139.09181213378906
+ ]
+ node [
+ id 335
+ label "R_Node:567"
+ active 0
+ pos 105.99969736735027
+ pos 121.35093688964844
+ ]
+ node [
+ id 336
+ label "R_Node:296"
+ active 0
+ pos 171.72466846222574
+ pos 125.94104425957863
+ ]
+ node [
+ id 337
+ label "R_Node:297"
+ active 0
+ pos 173.62646841495595
+ pos 126.62227874106549
+ ]
+ node [
+ id 338
+ label "R_Node:562"
+ active 0
+ pos 117.61172231038411
+ pos 117.25505828857422
+ ]
+ node [
+ id 339
+ label "R_Node:563"
+ active 0
+ pos 115.46932474772136
+ pos 118.32209777832031
+ ]
+ node [
+ id 340
+ label "R_Node:560"
+ active 0
+ pos 121.88440704345703
+ pos 115.18019104003906
+ ]
+ node [
+ id 341
+ label "R_Node:561"
+ active 0
+ pos 119.75411987304688
+ pos 116.18801879882812
+ ]
+ node [
+ id 342
+ label "R_Node:441"
+ active 0
+ pos 89.2180404663086
+ pos 132.46986389160156
+ ]
+ node [
+ id 343
+ label "R_Node:440"
+ active 0
+ pos 91.27174186706543
+ pos 132.47150421142578
+ ]
+ node [
+ id 344
+ label "R_Node:443"
+ active 0
+ pos 83.50938987731934
+ pos 133.47468948364258
+ ]
+ node [
+ id 345
+ label "R_Node:442"
+ active 0
+ pos 85.80358123779297
+ pos 132.85723876953125
+ ]
+ node [
+ id 346
+ label "R_Node:298"
+ active 0
+ pos 175.52826836768617
+ pos 127.30351322255237
+ ]
+ node [
+ id 347
+ label "R_Node:299"
+ active 0
+ pos 177.43006832041638
+ pos 127.98474770403922
+ ]
+ node [
+ id 348
+ label "R_Node:568"
+ active 0
+ pos 103.73926544189453
+ pos 121.7582778930664
+ ]
+ node [
+ id 349
+ label "R_Node:569"
+ active 0
+ pos 98.00495910644531
+ pos 122.3366470336914
+ ]
+ node [
+ id 350
+ label "R_Node:593"
+ active 0
+ pos 242.3580780029297
+ pos 145.98580932617188
+ ]
+ node [
+ id 351
+ label "R_Node:592"
+ active 0
+ pos 237.8785858154297
+ pos 144.04434204101562
+ ]
+ node [
+ id 352
+ label "R_Node:591"
+ active 0
+ pos 234.37088012695312
+ pos 144.2286834716797
+ ]
+ node [
+ id 353
+ label "R_Node:590"
+ active 0
+ pos 232.29957580566406
+ pos 146.43507385253906
+ ]
+ node [
+ id 354
+ label "R_Node:597"
+ active 0
+ pos 230.0952606201172
+ pos 149.51654052734375
+ ]
+ node [
+ id 355
+ label "R_Node:596"
+ active 0
+ pos 235.41139221191406
+ pos 150.87991333007812
+ ]
+ node [
+ id 356
+ label "R_Node:595"
+ active 0
+ pos 239.3179168701172
+ pos 150.83837890625
+ ]
+ node [
+ id 357
+ label "R_Node:594"
+ active 0
+ pos 242.24362182617188
+ pos 149.38795471191406
+ ]
+ node [
+ id 358
+ label "R_Node:522"
+ active 0
+ pos 64.41361999511719
+ pos 122.7872543334961
+ ]
+ node [
+ id 359
+ label "R_Node:368"
+ active 0
+ pos 142.21000119473072
+ pos 117.93105738213723
+ ]
+ node [
+ id 360
+ label "R_Node:369"
+ active 0
+ pos 140.31019559819646
+ pos 117.22544795908826
+ ]
+ node [
+ id 361
+ label "R_Node:360"
+ active 0
+ pos 157.40844596700464
+ pos 123.57593276652884
+ ]
+ node [
+ id 362
+ label "R_Node:361"
+ active 0
+ pos 155.5086403704704
+ pos 122.87032334347988
+ ]
+ node [
+ id 363
+ label "R_Node:362"
+ active 0
+ pos 153.60883477393617
+ pos 122.16471392043093
+ ]
+ node [
+ id 364
+ label "R_Node:363"
+ active 0
+ pos 151.70902917740193
+ pos 121.45910449738199
+ ]
+ node [
+ id 365
+ label "R_Node:364"
+ active 0
+ pos 149.8092235808677
+ pos 120.75349507433303
+ ]
+ node [
+ id 366
+ label "R_Node:365"
+ active 0
+ pos 147.90941798433346
+ pos 120.04788565128408
+ ]
+ node [
+ id 367
+ label "R_Node:366"
+ active 0
+ pos 146.00961238779922
+ pos 119.34227622823512
+ ]
+ node [
+ id 368
+ label "R_Node:367"
+ active 0
+ pos 144.10980679126496
+ pos 118.63666680518617
+ ]
+ node [
+ id 369
+ label "R_Node:203"
+ active 0
+ pos 53.78477401733399
+ pos 76.9343147277832
+ ]
+ node [
+ id 370
+ label "R_Node:202"
+ active 0
+ pos 53.404009628295896
+ pos 74.79874992370605
+ ]
+ node [
+ id 371
+ label "R_Node:201"
+ active 0
+ pos 53.02324523925781
+ pos 72.6631851196289
+ ]
+ node [
+ id 372
+ label "R_Node:200"
+ active 0
+ pos 52.64248085021973
+ pos 70.52762031555176
+ ]
+ node [
+ id 373
+ label "R_Node:207"
+ active 0
+ pos 56.24825395856585
+ pos 86.84298597063336
+ ]
+ node [
+ id 374
+ label "R_Node:206"
+ active 0
+ pos 55.52629470825195
+ pos 84.88296508789062
+ ]
+ node [
+ id 375
+ label "R_Node:205"
+ active 0
+ pos 54.546302795410156
+ pos 81.2054443359375
+ ]
+ node [
+ id 376
+ label "R_Node:204"
+ active 0
+ pos 54.16553840637207
+ pos 79.06987953186035
+ ]
+ node [
+ id 377
+ label "R_Node:209"
+ active 0
+ pos 57.692172459193635
+ pos 90.76302773611886
+ ]
+ node [
+ id 378
+ label "R_Node:208"
+ active 0
+ pos 56.97021320887974
+ pos 88.80300685337612
+ ]
+ node [
+ id 379
+ label "R_Node:167"
+ active 0
+ pos 28.53135108947754
+ pos 11.144851684570312
+ ]
+ node [
+ id 380
+ label "R_Node:571"
+ active 0
+ pos 93.82036844889323
+ pos 122.10953521728516
+ ]
+ node [
+ id 381
+ label "R_Node:570"
+ active 0
+ pos 95.91266377766927
+ pos 122.22309112548828
+ ]
+ edge [
+ source 0
+ target 3
+ weight 2.080945704544439
+ ]
+ edge [
+ source 1
+ target 0
+ weight 2.0809457045444106
+ ]
+ edge [
+ source 2
+ target 9
+ weight 2.080945704544425
+ ]
+ edge [
+ source 3
+ target 2
+ weight 2.0809457045444106
+ ]
+ edge [
+ source 4
+ target 7
+ weight 2.080945704544439
+ ]
+ edge [
+ source 5
+ target 4
+ weight 2.0809457045444106
+ ]
+ edge [
+ source 6
+ target 1
+ weight 2.080945704544439
+ ]
+ edge [
+ source 7
+ target 6
+ weight 2.0809457045444115
+ ]
+ edge [
+ source 8
+ target 289
+ weight 2.080945704544425
+ ]
+ edge [
+ source 9
+ target 8
+ weight 2.0809457045444257
+ ]
+ edge [
+ source 10
+ target 11
+ weight 2.1563725946088415
+ ]
+ edge [
+ source 11
+ target 83
+ weight 2.6851347633192657
+ ]
+ edge [
+ source 12
+ target 145
+ weight 2.050959601572082
+ ]
+ edge [
+ source 13
+ target 14
+ weight 2.344632696692467
+ ]
+ edge [
+ source 14
+ target 12
+ weight 2.0508491500118478
+ ]
+ edge [
+ source 15
+ target 16
+ weight 2.344632696692467
+ ]
+ edge [
+ source 16
+ target 13
+ weight 2.344632696692467
+ ]
+ edge [
+ source 17
+ target 173
+ weight 4.524166590736115
+ ]
+ edge [
+ source 17
+ target 239
+ weight 4.044790633199692
+ ]
+ edge [
+ source 18
+ target 17
+ weight 2.15783822867493
+ ]
+ edge [
+ source 19
+ target 231
+ weight 2.624457564826847
+ ]
+ edge [
+ source 20
+ target 19
+ weight 3.169063260658222
+ ]
+ edge [
+ source 21
+ target 20
+ weight 2.084872062095125
+ ]
+ edge [
+ source 22
+ target 21
+ weight 2.084872062095129
+ ]
+ edge [
+ source 23
+ target 22
+ weight 2.084872062095125
+ ]
+ edge [
+ source 24
+ target 120
+ weight 2.2495422083609298
+ ]
+ edge [
+ source 25
+ target 121
+ weight 2.084872062095129
+ ]
+ edge [
+ source 26
+ target 25
+ weight 2.084872062095129
+ ]
+ edge [
+ source 27
+ target 18
+ weight 2.157838228674922
+ ]
+ edge [
+ source 28
+ target 124
+ weight 2.084872062095129
+ ]
+ edge [
+ source 29
+ target 130
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 30
+ target 37
+ weight 2.0266094745950203
+ ]
+ edge [
+ source 31
+ target 30
+ weight 2.02660947459501
+ ]
+ edge [
+ source 32
+ target 31
+ weight 2.0266094745950367
+ ]
+ edge [
+ source 33
+ target 32
+ weight 2.0266094745950203
+ ]
+ edge [
+ source 34
+ target 204
+ weight 2.026609474595047
+ ]
+ edge [
+ source 35
+ target 34
+ weight 2.02660947459501
+ ]
+ edge [
+ source 36
+ target 35
+ weight 2.0266094745950203
+ ]
+ edge [
+ source 37
+ target 36
+ weight 2.02660947459501
+ ]
+ edge [
+ source 38
+ target 39
+ weight 2.0097202911722882
+ ]
+ edge [
+ source 39
+ target 44
+ weight 2.31111402055776
+ ]
+ edge [
+ source 40
+ target 41
+ weight 2.0097202911722802
+ ]
+ edge [
+ source 41
+ target 38
+ weight 2.0097202911722882
+ ]
+ edge [
+ source 42
+ target 43
+ weight 2.084872062095129
+ ]
+ edge [
+ source 43
+ target 191
+ weight 2.0848720620951293
+ ]
+ edge [
+ source 44
+ target 45
+ weight 2.084872062095129
+ ]
+ edge [
+ source 45
+ target 42
+ weight 2.084872062095129
+ ]
+ edge [
+ source 46
+ target 55
+ weight 2.1692437743076782
+ ]
+ edge [
+ source 47
+ target 46
+ weight 2.169243774307677
+ ]
+ edge [
+ source 48
+ target 47
+ weight 2.169243774307677
+ ]
+ edge [
+ source 49
+ target 48
+ weight 3.3984004312346316
+ ]
+ edge [
+ source 50
+ target 49
+ weight 2.004576859031627
+ ]
+ edge [
+ source 51
+ target 50
+ weight 2.004576859031627
+ ]
+ edge [
+ source 52
+ target 51
+ weight 2.004576859031627
+ ]
+ edge [
+ source 53
+ target 52
+ weight 2.004576859031634
+ ]
+ edge [
+ source 54
+ target 372
+ weight 2.169243774307677
+ ]
+ edge [
+ source 55
+ target 54
+ weight 2.169243774307677
+ ]
+ edge [
+ source 56
+ target 137
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 57
+ target 40
+ weight 2.009720291172295
+ ]
+ edge [
+ source 58
+ target 133
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 59
+ target 58
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 60
+ target 57
+ weight 2.009720291172281
+ ]
+ edge [
+ source 61
+ target 68
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 62
+ target 61
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 63
+ target 62
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 64
+ target 63
+ weight 2.0201295698473003
+ ]
+ edge [
+ source 65
+ target 59
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 66
+ target 65
+ weight 2.0201295698473003
+ ]
+ edge [
+ source 67
+ target 66
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 68
+ target 67
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 69
+ target 72
+ weight 2.008766241196523
+ ]
+ edge [
+ source 70
+ target 69
+ weight 2.0087662411965184
+ ]
+ edge [
+ source 71
+ target 82
+ weight 2.4826503466580028
+ ]
+ edge [
+ source 72
+ target 71
+ weight 1.6212559320143511
+ ]
+ edge [
+ source 73
+ target 74
+ weight 2.3142928157940905
+ ]
+ edge [
+ source 74
+ target 135
+ weight 2.3142928157940883
+ ]
+ edge [
+ source 75
+ target 70
+ weight 2.008766241196523
+ ]
+ edge [
+ source 76
+ target 75
+ weight 3.0159193917421874
+ ]
+ edge [
+ source 77
+ target 78
+ weight 2.305332595709828
+ ]
+ edge [
+ source 78
+ target 79
+ weight 2.305332595709809
+ ]
+ edge [
+ source 79
+ target 80
+ weight 2.305332595709828
+ ]
+ edge [
+ source 80
+ target 73
+ weight 1.719492332043214
+ ]
+ edge [
+ source 81
+ target 224
+ weight 1.8130070136264997
+ ]
+ edge [
+ source 82
+ target 81
+ weight 2.4826503466580028
+ ]
+ edge [
+ source 83
+ target 84
+ weight 2.305332595709828
+ ]
+ edge [
+ source 84
+ target 77
+ weight 2.305332595709809
+ ]
+ edge [
+ source 85
+ target 60
+ weight 2.881220803806643
+ ]
+ edge [
+ source 86
+ target 85
+ weight 2.3791843214815556
+ ]
+ edge [
+ source 87
+ target 193
+ weight 5.6693533942322825
+ ]
+ edge [
+ source 87
+ target 274
+ weight 7.706053759144949
+ ]
+ edge [
+ source 88
+ target 87
+ weight 2.0266094745950154
+ ]
+ edge [
+ source 89
+ target 88
+ weight 2.0266094745950154
+ ]
+ edge [
+ source 90
+ target 319
+ weight 3.0786711954567356
+ ]
+ edge [
+ source 91
+ target 90
+ weight 2.0448861860374254
+ ]
+ edge [
+ source 92
+ target 266
+ weight 7.288995173663438
+ ]
+ edge [
+ source 93
+ target 195
+ weight 4.660685932840957
+ ]
+ edge [
+ source 94
+ target 93
+ weight 4.711681034165182
+ ]
+ edge [
+ source 94
+ target 201
+ weight 3.7287614645841507
+ ]
+ edge [
+ source 95
+ target 96
+ weight 10.820132247981824
+ ]
+ edge [
+ source 96
+ target 379
+ weight 5.173343655600031
+ ]
+ edge [
+ source 97
+ target 100
+ weight 2.044886186037433
+ ]
+ edge [
+ source 98
+ target 97
+ weight 2.0448861860374272
+ ]
+ edge [
+ source 99
+ target 102
+ weight 2.044886186037433
+ ]
+ edge [
+ source 100
+ target 99
+ weight 2.0448861860374254
+ ]
+ edge [
+ source 101
+ target 104
+ weight 2.0448861860374254
+ ]
+ edge [
+ source 102
+ target 101
+ weight 2.0448861860374272
+ ]
+ edge [
+ source 103
+ target 91
+ weight 2.0448861860374272
+ ]
+ edge [
+ source 104
+ target 103
+ weight 2.044886186037433
+ ]
+ edge [
+ source 105
+ target 117
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 106
+ target 107
+ weight 2.0201295698472688
+ ]
+ edge [
+ source 107
+ target 208
+ weight 2.0201295698472785
+ ]
+ edge [
+ source 108
+ target 109
+ weight 2.0201295698472688
+ ]
+ edge [
+ source 109
+ target 114
+ weight 2.0201295698472785
+ ]
+ edge [
+ source 110
+ target 111
+ weight 2.0201295698472954
+ ]
+ edge [
+ source 111
+ target 108
+ weight 2.0201295698472785
+ ]
+ edge [
+ source 112
+ target 113
+ weight 2.0201295698472688
+ ]
+ edge [
+ source 113
+ target 106
+ weight 2.020129569847305
+ ]
+ edge [
+ source 114
+ target 115
+ weight 2.0201295698472688
+ ]
+ edge [
+ source 115
+ target 112
+ weight 2.0201295698472785
+ ]
+ edge [
+ source 116
+ target 24
+ weight 2.2495422083609298
+ ]
+ edge [
+ source 117
+ target 119
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 118
+ target 116
+ weight 2.2495422083609298
+ ]
+ edge [
+ source 119
+ target 64
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 120
+ target 123
+ weight 2.117142392013725
+ ]
+ edge [
+ source 121
+ target 23
+ weight 2.0848720620951293
+ ]
+ edge [
+ source 122
+ target 125
+ weight 2.157838228674922
+ ]
+ edge [
+ source 123
+ target 122
+ weight 2.15783822867493
+ ]
+ edge [
+ source 124
+ target 26
+ weight 2.084872062095129
+ ]
+ edge [
+ source 125
+ target 27
+ weight 2.15783822867493
+ ]
+ edge [
+ source 126
+ target 127
+ weight 2.053702055829841
+ ]
+ edge [
+ source 127
+ target 343
+ weight 2.053702055829841
+ ]
+ edge [
+ source 128
+ target 126
+ weight 2.053702055829841
+ ]
+ edge [
+ source 129
+ target 335
+ weight 2.2968411313551944
+ ]
+ edge [
+ source 130
+ target 336
+ weight 2.0201295698472785
+ ]
+ edge [
+ source 131
+ target 132
+ weight 3.0317600105642475
+ ]
+ edge [
+ source 132
+ target 129
+ weight 2.2968411313552086
+ ]
+ edge [
+ source 133
+ target 56
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 134
+ target 136
+ weight 2.3142928157940883
+ ]
+ edge [
+ source 135
+ target 134
+ weight 2.3142928157941047
+ ]
+ edge [
+ source 136
+ target 15
+ weight 4.0806922305340105
+ ]
+ edge [
+ source 136
+ target 256
+ weight 5.306902472231597
+ ]
+ edge [
+ source 137
+ target 138
+ weight 2.0201295698472737
+ ]
+ edge [
+ source 138
+ target 29
+ weight 2.0201295698473003
+ ]
+ edge [
+ source 139
+ target 193
+ weight 6.389117780975195
+ ]
+ edge [
+ source 139
+ target 140
+ weight 2.451369978022462
+ ]
+ edge [
+ source 140
+ target 105
+ weight 6.685272580394912
+ ]
+ edge [
+ source 141
+ target 142
+ weight 2.050959601572082
+ ]
+ edge [
+ source 142
+ target 143
+ weight 2.533264682856116
+ ]
+ edge [
+ source 143
+ target 144
+ weight 2.451369978022462
+ ]
+ edge [
+ source 144
+ target 139
+ weight 2.451369978022478
+ ]
+ edge [
+ source 145
+ target 146
+ weight 2.0509596015720954
+ ]
+ edge [
+ source 146
+ target 147
+ weight 2.050959601572082
+ ]
+ edge [
+ source 147
+ target 148
+ weight 2.050959601572082
+ ]
+ edge [
+ source 148
+ target 141
+ weight 2.0509596015720954
+ ]
+ edge [
+ source 149
+ target 152
+ weight 2.375828146737143
+ ]
+ edge [
+ source 150
+ target 149
+ weight 2.375828146737143
+ ]
+ edge [
+ source 151
+ target 272
+ weight 2.17249196653599
+ ]
+ edge [
+ source 152
+ target 151
+ weight 3.7293320576746427
+ ]
+ edge [
+ source 153
+ target 154
+ weight 2.0266094745950367
+ ]
+ edge [
+ source 154
+ target 167
+ weight 2.0266094745950203
+ ]
+ edge [
+ source 155
+ target 156
+ weight 2.02660947459501
+ ]
+ edge [
+ source 156
+ target 153
+ weight 2.0266094745950203
+ ]
+ edge [
+ source 157
+ target 158
+ weight 2.0266094745950203
+ ]
+ edge [
+ source 158
+ target 155
+ weight 2.02660947459501
+ ]
+ edge [
+ source 159
+ target 160
+ weight 2.0266094745950203
+ ]
+ edge [
+ source 160
+ target 157
+ weight 2.0266094745950367
+ ]
+ edge [
+ source 161
+ target 164
+ weight 2.425565488150257
+ ]
+ edge [
+ source 162
+ target 161
+ weight 2.170905746330924
+ ]
+ edge [
+ source 163
+ target 166
+ weight 2.3791843214815556
+ ]
+ edge [
+ source 164
+ target 163
+ weight 2.3791843214815556
+ ]
+ edge [
+ source 165
+ target 86
+ weight 2.3791843214815556
+ ]
+ edge [
+ source 166
+ target 165
+ weight 2.3791843214815707
+ ]
+ edge [
+ source 167
+ target 168
+ weight 2.02660947459501
+ ]
+ edge [
+ source 168
+ target 263
+ weight 2.0266094745950203
+ ]
+ edge [
+ source 169
+ target 353
+ weight 3.1145503622423827
+ ]
+ edge [
+ source 170
+ target 233
+ weight 2.624457564826847
+ ]
+ edge [
+ source 171
+ target 172
+ weight 2.0382489042365974
+ ]
+ edge [
+ source 172
+ target 282
+ weight 2.0382489042365974
+ ]
+ edge [
+ source 173
+ target 174
+ weight 2.3384780366479583
+ ]
+ edge [
+ source 174
+ target 175
+ weight 2.338478036647957
+ ]
+ edge [
+ source 175
+ target 176
+ weight 2.3384780366479583
+ ]
+ edge [
+ source 176
+ target 240
+ weight 1.6460144334365205
+ ]
+ edge [
+ source 176
+ target 177
+ weight 4.901080580440689
+ ]
+ edge [
+ source 177
+ target 178
+ weight 2.0382489042365974
+ ]
+ edge [
+ source 178
+ target 179
+ weight 2.0382489042365974
+ ]
+ edge [
+ source 179
+ target 180
+ weight 2.0382489042365974
+ ]
+ edge [
+ source 180
+ target 171
+ weight 2.0382489042365974
+ ]
+ edge [
+ source 181
+ target 188
+ weight 2.174853648900859
+ ]
+ edge [
+ source 182
+ target 181
+ weight 2.1748536489008443
+ ]
+ edge [
+ source 182
+ target 189
+ weight 8.23392045249578
+ ]
+ edge [
+ source 183
+ target 182
+ weight 2.174853648900859
+ ]
+ edge [
+ source 184
+ target 183
+ weight 2.174853648900859
+ ]
+ edge [
+ source 185
+ target 190
+ weight 2.1563725946088415
+ ]
+ edge [
+ source 186
+ target 185
+ weight 2.156372594608821
+ ]
+ edge [
+ source 186
+ target 244
+ weight 4.70128382122134
+ ]
+ edge [
+ source 187
+ target 186
+ weight 2.1563725946088415
+ ]
+ edge [
+ source 188
+ target 92
+ weight 2.094461599956369
+ ]
+ edge [
+ source 189
+ target 10
+ weight 2.156372594608821
+ ]
+ edge [
+ source 190
+ target 189
+ weight 2.1563725946088415
+ ]
+ edge [
+ source 191
+ target 192
+ weight 2.0848720620951218
+ ]
+ edge [
+ source 192
+ target 28
+ weight 2.084872062095129
+ ]
+ edge [
+ source 193
+ target 194
+ weight 2.174075856731501
+ ]
+ edge [
+ source 194
+ target 294
+ weight 2.1740758567315037
+ ]
+ edge [
+ source 195
+ target 196
+ weight 6.83982909994315
+ ]
+ edge [
+ source 196
+ target 199
+ weight 4.400971647391255
+ ]
+ edge [
+ source 197
+ target 93
+ weight 4.939000353494403
+ ]
+ edge [
+ source 198
+ target 202
+ weight 6.477726671879712
+ ]
+ edge [
+ source 199
+ target 200
+ weight 5.640031883851785
+ ]
+ edge [
+ source 200
+ target 96
+ weight 3.467744111707182
+ ]
+ edge [
+ source 201
+ target 95
+ weight 5.963733527964965
+ ]
+ edge [
+ source 202
+ target 197
+ weight 6.271569812406168
+ ]
+ edge [
+ source 203
+ target 159
+ weight 2.02660947459501
+ ]
+ edge [
+ source 204
+ target 203
+ weight 2.02660947459501
+ ]
+ edge [
+ source 205
+ target 315
+ weight 2.0201295698472954
+ ]
+ edge [
+ source 206
+ target 205
+ weight 2.0201295698472785
+ ]
+ edge [
+ source 207
+ target 210
+ weight 2.0201295698472785
+ ]
+ edge [
+ source 208
+ target 207
+ weight 2.0201295698472688
+ ]
+ edge [
+ source 209
+ target 212
+ weight 2.0201295698472514
+ ]
+ edge [
+ source 210
+ target 209
+ weight 2.0201295698472954
+ ]
+ edge [
+ source 211
+ target 214
+ weight 2.0201295698472688
+ ]
+ edge [
+ source 212
+ target 211
+ weight 2.020129569847305
+ ]
+ edge [
+ source 213
+ target 206
+ weight 2.0201295698472785
+ ]
+ edge [
+ source 214
+ target 213
+ weight 2.0201295698472688
+ ]
+ edge [
+ source 215
+ target 216
+ weight 2.0448861860374272
+ ]
+ edge [
+ source 216
+ target 98
+ weight 2.0448861860374294
+ ]
+ edge [
+ source 217
+ target 198
+ weight 9.063731444889704
+ ]
+ edge [
+ source 218
+ target 298
+ weight 2.1740758567315037
+ ]
+ edge [
+ source 219
+ target 118
+ weight 2.2495422083609298
+ ]
+ edge [
+ source 220
+ target 221
+ weight 2.017235729912668
+ ]
+ edge [
+ source 220
+ target 250
+ weight 4.577018740482775
+ ]
+ edge [
+ source 221
+ target 222
+ weight 2.017235729912668
+ ]
+ edge [
+ source 222
+ target 223
+ weight 2.017235729912668
+ ]
+ edge [
+ source 223
+ target 92
+ weight 2.397953772004691
+ ]
+ edge [
+ source 224
+ target 225
+ weight 2.7402723992389246
+ ]
+ edge [
+ source 225
+ target 226
+ weight 2.7402723992389246
+ ]
+ edge [
+ source 226
+ target 227
+ weight 1.8264562889263969
+ ]
+ edge [
+ source 227
+ target 220
+ weight 2.017235729912668
+ ]
+ edge [
+ source 228
+ target 128
+ weight 3.6411452997300513
+ ]
+ edge [
+ source 229
+ target 228
+ weight 2.1212440959529935
+ ]
+ edge [
+ source 230
+ target 229
+ weight 2.1212440959529935
+ ]
+ edge [
+ source 231
+ target 170
+ weight 2.624457564826845
+ ]
+ edge [
+ source 232
+ target 301
+ weight 2.1740758567315024
+ ]
+ edge [
+ source 233
+ target 234
+ weight 1.597533790282889
+ ]
+ edge [
+ source 234
+ target 305
+ weight 2.153423713184546
+ ]
+ edge [
+ source 235
+ target 236
+ weight 2.2207909304747084
+ ]
+ edge [
+ source 236
+ target 295
+ weight 2.2207909304747084
+ ]
+ edge [
+ source 237
+ target 238
+ weight 2.153423713184542
+ ]
+ edge [
+ source 238
+ target 217
+ weight 2.153423713184546
+ ]
+ edge [
+ source 239
+ target 246
+ weight 2.765927840749201
+ ]
+ edge [
+ source 240
+ target 177
+ weight 3.9894671648196076
+ ]
+ edge [
+ source 241
+ target 242
+ weight 2.174853648900859
+ ]
+ edge [
+ source 242
+ target 184
+ weight 2.1748536489008443
+ ]
+ edge [
+ source 243
+ target 250
+ weight 2.2510253737105965
+ ]
+ edge [
+ source 244
+ target 243
+ weight 2.2510253737106103
+ ]
+ edge [
+ source 245
+ target 134
+ weight 4.1708129992210425
+ ]
+ edge [
+ source 245
+ target 75
+ weight 2.131895612368234
+ ]
+ edge [
+ source 246
+ target 245
+ weight 2.765927840749201
+ ]
+ edge [
+ source 247
+ target 248
+ weight 2.115676651716835
+ ]
+ edge [
+ source 248
+ target 253
+ weight 2.115676651716835
+ ]
+ edge [
+ source 249
+ target 303
+ weight 2.2510253737106103
+ ]
+ edge [
+ source 250
+ target 249
+ weight 2.2510253737106103
+ ]
+ edge [
+ source 251
+ target 252
+ weight 2.115676651716835
+ ]
+ edge [
+ source 252
+ target 241
+ weight 3.5948365931864052
+ ]
+ edge [
+ source 253
+ target 254
+ weight 2.1156766517168637
+ ]
+ edge [
+ source 254
+ target 251
+ weight 2.115676651716835
+ ]
+ edge [
+ source 255
+ target 240
+ weight 2.6062071913648546
+ ]
+ edge [
+ source 256
+ target 255
+ weight 2.6062071913648546
+ ]
+ edge [
+ source 257
+ target 261
+ weight 2.17249196653599
+ ]
+ edge [
+ source 258
+ target 329
+ weight 2.02660947459501
+ ]
+ edge [
+ source 259
+ target 258
+ weight 2.0266094745950154
+ ]
+ edge [
+ source 260
+ target 271
+ weight 2.0266094745950154
+ ]
+ edge [
+ source 261
+ target 247
+ weight 7.205717713918863
+ ]
+ edge [
+ source 262
+ target 265
+ weight 2.0266094745950203
+ ]
+ edge [
+ source 263
+ target 262
+ weight 2.0266094745950367
+ ]
+ edge [
+ source 264
+ target 259
+ weight 2.0266094745950154
+ ]
+ edge [
+ source 265
+ target 264
+ weight 2.02660947459501
+ ]
+ edge [
+ source 266
+ target 267
+ weight 2.170905746330924
+ ]
+ edge [
+ source 267
+ target 268
+ weight 2.170905746330938
+ ]
+ edge [
+ source 268
+ target 269
+ weight 2.170905746330924
+ ]
+ edge [
+ source 269
+ target 330
+ weight 2.170905746330922
+ ]
+ edge [
+ source 270
+ target 333
+ weight 2.088757290807486
+ ]
+ edge [
+ source 271
+ target 332
+ weight 2.0266094745950154
+ ]
+ edge [
+ source 272
+ target 334
+ weight 2.17249196653599
+ ]
+ edge [
+ source 273
+ target 340
+ weight 2.5237062640272194
+ ]
+ edge [
+ source 274
+ target 273
+ weight 2.5237062640272194
+ ]
+ edge [
+ source 275
+ target 287
+ weight 2.508557522131839
+ ]
+ edge [
+ source 276
+ target 275
+ weight 2.7622567430045772
+ ]
+ edge [
+ source 277
+ target 5
+ weight 2.657873463993669
+ ]
+ edge [
+ source 278
+ target 277
+ weight 2.466751703350307
+ ]
+ edge [
+ source 279
+ target 278
+ weight 2.466751703350307
+ ]
+ edge [
+ source 280
+ target 279
+ weight 1.665557552616292
+ ]
+ edge [
+ source 281
+ target 280
+ weight 2.0382489042365974
+ ]
+ edge [
+ source 282
+ target 281
+ weight 2.0382489042365974
+ ]
+ edge [
+ source 283
+ target 284
+ weight 2.1212440959529935
+ ]
+ edge [
+ source 284
+ target 291
+ weight 2.1212440959529935
+ ]
+ edge [
+ source 285
+ target 286
+ weight 2.1212440959529806
+ ]
+ edge [
+ source 286
+ target 283
+ weight 2.1212440959529935
+ ]
+ edge [
+ source 287
+ target 288
+ weight 2.1212440959529935
+ ]
+ edge [
+ source 288
+ target 285
+ weight 2.1212440959529935
+ ]
+ edge [
+ source 289
+ target 290
+ weight 2.080945704544425
+ ]
+ edge [
+ source 290
+ target 140
+ weight 5.887227379628547
+ ]
+ edge [
+ source 290
+ target 273
+ weight 3.9751917489461412
+ ]
+ edge [
+ source 291
+ target 292
+ weight 2.1212440959529935
+ ]
+ edge [
+ source 292
+ target 230
+ weight 2.1212440959529806
+ ]
+ edge [
+ source 293
+ target 296
+ weight 2.174075856731501
+ ]
+ edge [
+ source 294
+ target 293
+ weight 2.1740758567315153
+ ]
+ edge [
+ source 295
+ target 219
+ weight 2.85296831440672
+ ]
+ edge [
+ source 296
+ target 218
+ weight 2.1740758567315153
+ ]
+ edge [
+ source 297
+ target 300
+ weight 2.174075856731501
+ ]
+ edge [
+ source 298
+ target 297
+ weight 2.174075856731501
+ ]
+ edge [
+ source 299
+ target 232
+ weight 2.1740758567315024
+ ]
+ edge [
+ source 300
+ target 299
+ weight 2.174075856731501
+ ]
+ edge [
+ source 301
+ target 276
+ weight 3.6319858416185467
+ ]
+ edge [
+ source 302
+ target 307
+ weight 2.2207909304747084
+ ]
+ edge [
+ source 303
+ target 304
+ weight 2.2510253737105965
+ ]
+ edge [
+ source 304
+ target 358
+ weight 2.2510253737106103
+ ]
+ edge [
+ source 305
+ target 306
+ weight 2.153423713184546
+ ]
+ edge [
+ source 306
+ target 237
+ weight 2.153423713184542
+ ]
+ edge [
+ source 307
+ target 308
+ weight 2.2207909304747084
+ ]
+ edge [
+ source 308
+ target 235
+ weight 2.2207909304747377
+ ]
+ edge [
+ source 309
+ target 310
+ weight 2.0266094745950203
+ ]
+ edge [
+ source 310
+ target 33
+ weight 2.02660947459501
+ ]
+ edge [
+ source 311
+ target 169
+ weight 4.412921766820168
+ ]
+ edge [
+ source 312
+ target 313
+ weight 2.02660947459501
+ ]
+ edge [
+ source 313
+ target 314
+ weight 2.0266094745950203
+ ]
+ edge [
+ source 314
+ target 309
+ weight 2.0266094745950367
+ ]
+ edge [
+ source 315
+ target 316
+ weight 2.020129569847242
+ ]
+ edge [
+ source 316
+ target 317
+ weight 2.020129569847305
+ ]
+ edge [
+ source 317
+ target 318
+ weight 2.0201295698472785
+ ]
+ edge [
+ source 318
+ target 311
+ weight 2.0201295698472688
+ ]
+ edge [
+ source 319
+ target 320
+ weight 2.0045768590316304
+ ]
+ edge [
+ source 320
+ target 321
+ weight 2.0045768590316304
+ ]
+ edge [
+ source 321
+ target 322
+ weight 2.004576859031627
+ ]
+ edge [
+ source 322
+ target 323
+ weight 2.004576859031627
+ ]
+ edge [
+ source 323
+ target 324
+ weight 2.004576859031634
+ ]
+ edge [
+ source 324
+ target 325
+ weight 2.004576859031627
+ ]
+ edge [
+ source 325
+ target 326
+ weight 2.004576859031627
+ ]
+ edge [
+ source 326
+ target 327
+ weight 2.004576859031627
+ ]
+ edge [
+ source 327
+ target 328
+ weight 2.004576859031634
+ ]
+ edge [
+ source 328
+ target 53
+ weight 2.004576859031627
+ ]
+ edge [
+ source 329
+ target 260
+ weight 2.0266094745950416
+ ]
+ edge [
+ source 330
+ target 331
+ weight 2.170905746330924
+ ]
+ edge [
+ source 331
+ target 162
+ weight 2.170905746330938
+ ]
+ edge [
+ source 332
+ target 361
+ weight 2.0266094745950416
+ ]
+ edge [
+ source 333
+ target 187
+ weight 9.07592326946155
+ ]
+ edge [
+ source 334
+ target 257
+ weight 2.17249196653599
+ ]
+ edge [
+ source 335
+ target 348
+ weight 2.2968411313552086
+ ]
+ edge [
+ source 336
+ target 337
+ weight 2.0201295698472688
+ ]
+ edge [
+ source 337
+ target 346
+ weight 2.0201295698472785
+ ]
+ edge [
+ source 338
+ target 339
+ weight 2.393416091944921
+ ]
+ edge [
+ source 339
+ target 131
+ weight 2.393416091944934
+ ]
+ edge [
+ source 340
+ target 341
+ weight 2.356658698199613
+ ]
+ edge [
+ source 341
+ target 338
+ weight 2.393416091944934
+ ]
+ edge [
+ source 342
+ target 345
+ weight 3.4363630656911903
+ ]
+ edge [
+ source 343
+ target 342
+ weight 2.053702055829841
+ ]
+ edge [
+ source 343
+ target 239
+ weight 3.770360482891123
+ ]
+ edge [
+ source 344
+ target 150
+ weight 2.375828146737143
+ ]
+ edge [
+ source 345
+ target 344
+ weight 2.375828146737143
+ ]
+ edge [
+ source 346
+ target 347
+ weight 2.0201295698472688
+ ]
+ edge [
+ source 347
+ target 110
+ weight 2.0201295698472785
+ ]
+ edge [
+ source 348
+ target 256
+ weight 4.735327057515424
+ ]
+ edge [
+ source 348
+ target 349
+ weight 5.763400039178293
+ ]
+ edge [
+ source 349
+ target 381
+ weight 2.095374593504918
+ ]
+ edge [
+ source 350
+ target 357
+ weight 3.404070128849415
+ ]
+ edge [
+ source 351
+ target 350
+ weight 4.88212509847971
+ ]
+ edge [
+ source 352
+ target 351
+ weight 3.5125462217642216
+ ]
+ edge [
+ source 353
+ target 352
+ weight 3.026294781434803
+ ]
+ edge [
+ source 354
+ target 312
+ weight 6.317368213887609
+ ]
+ edge [
+ source 355
+ target 354
+ weight 5.488172783407658
+ ]
+ edge [
+ source 356
+ target 355
+ weight 3.9067454503092183
+ ]
+ edge [
+ source 357
+ target 356
+ weight 3.2654984050521314
+ ]
+ edge [
+ source 358
+ target 302
+ weight 3.474364926111206
+ ]
+ edge [
+ source 359
+ target 360
+ weight 2.026609474595047
+ ]
+ edge [
+ source 360
+ target 89
+ weight 2.02660947459501
+ ]
+ edge [
+ source 361
+ target 362
+ weight 2.0266094745950154
+ ]
+ edge [
+ source 362
+ target 363
+ weight 2.0266094745950154
+ ]
+ edge [
+ source 363
+ target 364
+ weight 2.02660947459501
+ ]
+ edge [
+ source 364
+ target 365
+ weight 2.0266094745950154
+ ]
+ edge [
+ source 365
+ target 366
+ weight 2.0266094745950154
+ ]
+ edge [
+ source 366
+ target 367
+ weight 2.0266094745950154
+ ]
+ edge [
+ source 367
+ target 368
+ weight 2.0266094745950416
+ ]
+ edge [
+ source 368
+ target 359
+ weight 2.02660947459501
+ ]
+ edge [
+ source 369
+ target 376
+ weight 2.169243774307677
+ ]
+ edge [
+ source 370
+ target 369
+ weight 2.1692437743076782
+ ]
+ edge [
+ source 371
+ target 370
+ weight 2.169243774307677
+ ]
+ edge [
+ source 372
+ target 371
+ weight 2.169243774307677
+ ]
+ edge [
+ source 373
+ target 378
+ weight 2.088757290807499
+ ]
+ edge [
+ source 374
+ target 373
+ weight 2.088757290807486
+ ]
+ edge [
+ source 375
+ target 374
+ weight 3.805856412199651
+ ]
+ edge [
+ source 376
+ target 375
+ weight 2.169243774307677
+ ]
+ edge [
+ source 377
+ target 270
+ weight 2.0887572908075014
+ ]
+ edge [
+ source 378
+ target 377
+ weight 2.088757290807486
+ ]
+ edge [
+ source 379
+ target 215
+ weight 2.0448861860374294
+ ]
+ edge [
+ source 380
+ target 76
+ weight 2.095374593504918
+ ]
+ edge [
+ source 381
+ target 380
+ weight 2.095374593504904
+ ]
+]
diff --git a/cart_endpoints/launch/hardware_interface.launch b/cart_endpoints/launch/hardware_interface.launch
index 162b9ab6..543244c0 100644
--- a/cart_endpoints/launch/hardware_interface.launch
+++ b/cart_endpoints/launch/hardware_interface.launch
@@ -34,9 +34,9 @@
" />
-
-
+
diff --git a/cart_planning/launch/constants.launch b/cart_planning/launch/constants.launch
index 0672ca32..5a23be79 100755
--- a/cart_planning/launch/constants.launch
+++ b/cart_planning/launch/constants.launch
@@ -9,6 +9,6 @@
anchor_theta : 0
- graph_file : "/home/jeffercize/catkin_ws/src/ai-navigation/EastCampusLiteV4.gml"
+ graph_file : "/home/jeffercize/catkin_ws/src/ai-navigation/EastCampusLiteV5.gml"
diff --git a/cart_planning/scripts/affine.py b/cart_planning/scripts/affine.py
deleted file mode 100755
index 6e4aaac0..00000000
--- a/cart_planning/scripts/affine.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/env python
-
-import transformations
-import gps_util
-import numpy as np
-
-anchor_lat = 38.432147 # 38.431960
-anchor_long = -78.876115 # -78.875910
-anchor_elev = 396 #meters above sea level
-anchor_theta = 0 #angle pointing directly north, originally: 0
-
-
-#X
-v0 = [[35.9750671387,
-14.0169754028,
--3.60410761833,
-17.4223442078,
-30.7783546448,
-59.0794563293,
-47.9315681458],
-#Y
-[36.4229431152,
-1.30921435356,
-8.7294960022,
-46.9932327271,
-43.7685050964,
-72.0065460205,
-86.720085144]]
-
-
-
-
-
-#Latitude
-v1 = [[38.431686,
-38.432053,
-38.432108,
-38.431724,
-38.431672,
-38.431312,
-38.431282],
-#Longitude
-[-78.876137,
--78.876221,
--78.876016,
--78.875895,
--78.876047,
--78.876070,
--78.875866]]
-
-affine = transformations.affine_matrix_from_points(v0, v1)
-# print(affine)
-
-'''#!/usr/bin/env python
-
-import transformations
-
-#X
-v0 = [[36.4229431152,
-1.30921435356,
-8.7294960022,
-46.9932327271,
-43.7685050964,
-72.0065460205,
-86.720085144],
-#Y
-[35.9750671387,
-14.0169754028,
--3.60410761833,
-17.4223442078,
-30.7783546448,
-59.0794563293,
-47.9315681458]]
-
-
-
-#Latitude
-v1 = [[-78.876137,
--78.876221,
--78.876016,
--78.875895,
--78.876047,
--78.876070,
--78.875866],
-#Longitude
-[38.431686,
-38.432053,
-38.432108,
-38.431724,
-38.431672,
-38.431312,
-38.431282]]
-
-
-
-
-affine = transformations.affine_matrix_from_points(v0, v1)
-print(affine)
-'''
diff --git a/cart_planning/scripts/cubic_spline_planner.pyc b/cart_planning/scripts/cubic_spline_planner.pyc
index 95f96db1..10c0cff5 100644
Binary files a/cart_planning/scripts/cubic_spline_planner.pyc and b/cart_planning/scripts/cubic_spline_planner.pyc differ
diff --git a/cart_planning/scripts/global_planner.py b/cart_planning/scripts/global_planner.py
index 4af0650b..901dfd7b 100755
--- a/cart_planning/scripts/global_planner.py
+++ b/cart_planning/scripts/global_planner.py
@@ -37,6 +37,9 @@ def __init__(self):
#The points on the map
self.local_array = None
+ # Minimizng travel will have the cart stop when its closest to the passenger regardless of which side of the road the summon comes from
+ self.minimize_travel = True
+
# Temporary solution for destinations, TODO: Make destinations embedded in graph nodes
self.dest_dict = {"home":(22.9, 4.21), "cafeteria":(127, 140), "clinic":(63.3, 130), "reccenter":(73.7, 113), "office":(114, 117)}
@@ -100,6 +103,7 @@ def calc_nav(self, point):
# Get the node closest to where we want to go
destination_point = self.get_closest_node(point.x, point.y)
+ """
# Remove our previous node to prevent searching directly behind cart
name = None
@@ -132,7 +136,12 @@ def calc_nav(self, point):
rospy.loginfo("Out edge: u,v " + str(u) + "," + str(v))
self.global_graph.add_edge(name, v, weight=data['weight'])
-
+ """
+ if self.minimize_travel:
+ nodelist = self.calc_efficient_destination(destination_point)
+ else:
+ nodelist = nx.dijkstra_path(self.global_graph, self.current_cart_node, destination_point)
+
# Set all nodes back to a state of not being a part of the previous/current path
for node in self.global_graph:
self.global_graph.node[node]['active'] = False
@@ -149,6 +158,44 @@ def calc_nav(self, point):
self.logic_graph = copy.deepcopy(self.global_graph)
self.path_pub.publish(points_arr)
+ def calc_efficient_destination(self, destination):
+ # Find nodes within 3 meters of destination node
+ close_nodes = [destination]
+ local_logic_graph = copy.deepcopy(self.logic_graph)
+ dest_node_pos = local_logic_graph.node[destination]['pos']
+
+ for node in self.global_graph.nodes:
+ inefficient = True
+ node_pos = local_logic_graph.node[node]['pos']
+
+ # Is node close enough and also not incident to the destination
+ dist = self.dis(node_pos[0], node_pos[1], dest_node_pos[0], dest_node_pos[1])
+ if dist < 3 and node is not destination:
+ for u, v in local_logic_graph.out_edges(node):
+ if u is destination or v is destination:
+ inefficient = True
+ break
+ else:
+ inefficient = False
+
+ # if node is not an inefficient destination add it
+ if not inefficient:
+ close_nodes.append(node)
+
+ min_path = None
+ # Out of the most efficient paths, which one has the least driving distance
+ for node in close_nodes:
+ node_path = nx.dijkstra_path(local_logic_graph, self.current_cart_node, node)
+ if min_path is None:
+ min_path = node_path
+
+ # TODO replace with cost analysis
+ if len(node_path) < len(min_path):
+ min_path = node_path
+
+ return min_path
+
+
# Closest node to given point
def get_closest_node(self, x, y, cart_trans=False):
min_dist = 99999
diff --git a/cart_planning/scripts/gps_util.py b/cart_planning/scripts/gps_util.py
deleted file mode 100755
index 8679d282..00000000
--- a/cart_planning/scripts/gps_util.py
+++ /dev/null
@@ -1,259 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import tf
-import rospy
-import numpy as np
-import affine
-import math
-import transformations
-
-#This class still needs testing
-
-from geometry_msgs.msg import Pose, Point #point is able to be used for path planning in a 3d space
-from sensor_msgs.msg import NavSatFix #standard ros message for GPS data
-
-#current anchor is the center of the xlabs building, with direction pointing directly north
-anchor_lat = 38.432150 # 38.431691 # 38.432147 # 38.431960
-anchor_long = -78.876106 # -78.876036 #-78.876115 # -78.875910
-anchor_elev = 396 #meters above sea level
-anchor_theta = 40 #angle pointing directly north, originally: 0
-earth_radius = 6371000 #meters
-
-"""
-#This array is used to transform points from the frame based on this anchor point to the map frame used by sensors
-#This array was created using 7 points, their x,y positions in each frame, and their gps coordinates.
-#The affine matrices method from this code was used: https://www.lfd.uci.edu/~gohlke/code/transformations.py.html
-"""
-
-
-'''M = np.array([[-0.45644886, -0.77822273, -2.79976147],
- [ 0.84299717, -0.50090785, 41.31691467],
- [ 0.0, 0.0, 1.0]])'''
-
-
-v0 = None
-v1 = None
-M = None
-
-
-"""
-Always go from GPS to XYZ as soon as you can. Then never go back. Ever. Dont even think about it
-.
-If you get a batch of waypoints in lat/long, immediately convert all of them. Then do whatever other math you wanted to do.
-Through a combination of an anchor point, distance_between_points, and direction between points, we can convert any lat/long point to an xyz point in our coordinate frame
-
-TODO: move all the geometry methods to another utility file
-"""
-
-def get_point(current_gps):
- """
- Returns a Point() (xyz) of a lat/long relative to the set anchor point
-
- This relies on the xy_between_coordinates method
-
- Zack
- """
- relative_point = Point()
- current_lat = current_gps.latitude
- current_long = current_gps.longitude
-
- #The point is found in xyz in reference to the anchor being 0,0,0
- result = xy_between_coordinates(anchor_lat, anchor_long, anchor_theta, current_lat, current_long)
-
- planning_point = np.array([[result[0]], [result[1]], [1]]) #3rd value is to make point homogenous
- sensors_map_point = np.dot(M, planning_point) #dot product to get transformed point
- relative_point.x = sensors_map_point[0,0]
- relative_point.y = sensors_map_point[1,0]
- rospy.loginfo(relative_point)
- return relative_point
-
-def xy_between_coordinates(lat1, lng1, theta1, lat2, lng2):
- """
- Returns a tuple of x and y distances between two coordinates
-
- this relies on distance & direction between coordinates methods
-
- Zack
- """
- distance_flat = distance_between_coordinates(lat1,lng1,lat2,lng2)
- angle = math.radians( (theta1+direction_between_coordinates(lat1,lng1,lat2,lng2)) % 360 )
- x = math.sin(angle)*distance_flat
- y = math.cos(angle)*distance_flat
- return (x, y)
-
-def distance_between_coordinates(lat1, lng1, lat2, lng2):
- """
- :return: distance (meters) between two points. This is approximate as the math assumes the earth is a sphere
-
- https://www.movable-type.co.uk/scripts/latlong.html
- uses meters for earth radius
-
- Zack
- """
- global earth_radius
- lat1 = math.radians(lat1)
- lng1 = math.radians(lng1)
- lat2 = math.radians(lat2)
- lng2 = math.radians(lng2)
-
- a = math.sin((lat2-lat1)/2)*math.sin((lat2-lat1)/2) + math.cos(lat1) * math.cos(lat2) * math.sin((lng2-lng1)/2)*math.sin((lng2-lng1)/2)
- c = 2 * math.atan2(math.sqrt(a), math.sqrt((1-a)))
- distance = earth_radius * c
- return distance
-def direction_between_coordinates(lat1, lng1, lat2, lng2):
- """
- :return: bearing between two points (degrees)
- This calculates for the bearing between two points.
-
- Zack
- """
- lat1 = math.radians(lat1)
- lng1 = math.radians(lng1)
- lat2 = math.radians(lat2)
- lng2 = math.radians(lng2)
-
- bearing = math.atan2((math.sin(lng2-lng1)*math.cos(lat2)),(math.cos(lat1)*math.sin(lat2)-math.sin(lat1)*math.cos(lat2)*math.cos(lng2-lng1)))
- bearing = (math.degrees(bearing)+360)%360
- return bearing
-
-
-"""
-TODO
-Every method below here is a geometry util that should go in a separate file.
-These are used for Pure Pursuit"""
-
-def xy_angle_between_points(point1, point2):
- distx = point2.x - point1.x
- disty = point2.y - point1.y
- #y is forward while x is sideways
- return (math.atan2(distx, disty)*180/math.pi)%360
-
-def xyz_dist_between_points(point1, point2):
- """
- distance between two xyz points in a 3-dimensional coordinate plane
- """
- distx = point1.x - point2.x
- disty = point1.y - point2.y
- distz = point1.z - point2.z
- return math.sqrt(disty ** 2 + distx ** 2 + distz ** 2)
-
-def midpoint(p1, p2):
- """
- used to find a geometric midpoint in an x/y coordinate frame
- """
- x = (p1.x + p2.x) / 2.0
- y = (p1.y + p2.y) / 2.0
-
- return Point(x, y, 0)
-
-def add_intermediate_points(points, threshold):
- """
- Method for adding more points to a list of geometric points within a threshold.
- """
- #threshold = 5.0
-
- #keeps the final point to add at the end
- final = points[0]
-
- newPoints = []
- prev = points.pop()
-
- #loop until points is empty
- #we are using points as a stack here
- while points:
- #get the next point on the stack
- new = points.pop()
- dist = xyz_dist_between_points(prev, new)
-
- #if the distance is greater than the threshold
- if dist > threshold:
- #put the point on the stack
- points.append(new)
- mid = midpoint(new, prev)
- #add the midpoint to the stack
- points.append(mid)
- else:
- #add the start point to the newPoints and switch new point to the prev point
- newPoints.append(prev)
- prev = new
-
- #add the final point
- newPoints.append(final)
- newPoints.reverse()
- return newPoints
-
-#X
-v0 = [[35.9750671387,
-14.0169754028,
--3.60410761833,
-17.4223442078,
-30.7783546448,
-59.0794563293,
-47.9315681458],
-#Y
-[36.4229431152,
-1.30921435356,
-8.7294960022,
-46.9932327271,
-43.7685050964,
-72.0065460205,
-86.720085144]]
-
-
-
-
-
-#Latitude
-v1 = [[38.431686,
-38.432053,
-38.432108,
-38.431724,
-38.431672,
-38.431312,
-38.431282],
-#Longitude
-[-78.876137,
--78.876221,
--78.876016,
--78.875895,
--78.876047,
--78.876070,
--78.875866]]
-
-
-v1_np = np.array(v1)
-new_arr = [[],[]]
-'''
-# Setup for averaging
-anchor_lat = 0
-anchor_long = 0
-
-for i in range(v1_np.shape[1]):
-
- lat = v1_np[0][i]
- anchor_lat += lat
-
- lng = v1_np[1][i]
- anchor_long += lng
-
-# Average for anchor point
-anchor_lat = anchor_lat / 7
-anchor_long = anchor_long / 7'''
-
-# End averaging, begin converting
-
-for i in range(v1_np.shape[1]):
-
- lat = v1_np[0][i]
-
- lng = v1_np[1][i]
-
- elem = xy_between_coordinates(anchor_lat, anchor_long, anchor_theta, lat, lng)
- new_arr[0].append(elem[0])
- new_arr[1].append(elem[1])
-
-
-
-M = transformations.affine_matrix_from_points(v0, new_arr)
-#M = transformations.affine_matrix_from_points(v0, v1_np)
diff --git a/cart_planning/scripts/transformations.py b/cart_planning/scripts/transformations.py
deleted file mode 100755
index 7c0bcd79..00000000
--- a/cart_planning/scripts/transformations.py
+++ /dev/null
@@ -1,1954 +0,0 @@
-
-
-# -*- coding: utf-8 -*-
-# transformations.py
-
-# Copyright (c) 2006-2019, Christoph Gohlke
-# Copyright (c) 2006-2019, The Regents of the University of California
-# Produced at the Laboratory for Fluorescence Dynamics
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# * Neither the name of the copyright holder nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-"""Homogeneous Transformation Matrices and Quaternions.
-
-Transformations is a Python library for calculating 4x4 matrices for
-translating, rotating, reflecting, scaling, shearing, projecting,
-orthogonalizing, and superimposing arrays of 3D homogeneous coordinates
-as well as for converting between rotation matrices, Euler angles,
-and quaternions. Also includes an Arcball control object and
-functions to decompose transformation matrices.
-
-:Author:
- `Christoph Gohlke `_
-
-:Organization:
- Laboratory for Fluorescence Dynamics. University of California, Irvine
-
-:License: 3-clause BSD
-
-:Version: 2019.2.20
-
-Requirements
-------------
-* `CPython 2.7 or 3.5+ `_
-* `Numpy 1.14 `_
-* A Python distutils compatible C compiler (build)
-
-Revisions
----------
-2019.1.1
- Update copyright year.
-
-Notes
------
-Transformations.py is no longer actively developed and has a few known issues
-and numerical instabilities. The module is mostly superseded by other modules
-for 3D transformations and quaternions:
-
-* `Scipy.spatial.transform `_
-* `Transforms3d `_
- (includes most code of this module)
-* `Numpy-quaternion `_
-* `Blender.mathutils `_
-
-The API is not stable yet and is expected to change between revisions.
-
-Python 2.7 and 3.4 are deprecated.
-
-This Python code is not optimized for speed. Refer to the transformations.c
-module for a faster implementation of some functions.
-
-Documentation in HTML format can be generated with epydoc.
-
-Matrices (M) can be inverted using numpy.linalg.inv(M), be concatenated using
-numpy.dot(M0, M1), or transform homogeneous coordinate arrays (v) using
-numpy.dot(M, v) for shape (4, \*) column vectors, respectively
-numpy.dot(v, M.T) for shape (\*, 4) row vectors ("array of points").
-
-This module follows the "column vectors on the right" and "row major storage"
-(C contiguous) conventions. The translation components are in the right column
-of the transformation matrix, i.e. M[:3, 3].
-The transpose of the transformation matrices may have to be used to interface
-with other graphics systems, e.g. OpenGL's glMultMatrixd(). See also [16].
-
-Calculations are carried out with numpy.float64 precision.
-
-Vector, point, quaternion, and matrix function arguments are expected to be
-"array like", i.e. tuple, list, or numpy arrays.
-
-Return types are numpy arrays unless specified otherwise.
-
-Angles are in radians unless specified otherwise.
-
-Quaternions w+ix+jy+kz are represented as [w, x, y, z].
-
-A triple of Euler angles can be applied/interpreted in 24 ways, which can
-be specified using a 4 character string or encoded 4-tuple:
-
- *Axes 4-string*: e.g. 'sxyz' or 'ryxy'
-
- - first character : rotations are applied to 's'tatic or 'r'otating frame
- - remaining characters : successive rotation axis 'x', 'y', or 'z'
-
- *Axes 4-tuple*: e.g. (0, 0, 0, 0) or (1, 1, 1, 1)
-
- - inner axis: code of axis ('x':0, 'y':1, 'z':2) of rightmost matrix.
- - parity : even (0) if inner axis 'x' is followed by 'y', 'y' is followed
- by 'z', or 'z' is followed by 'x'. Otherwise odd (1).
- - repetition : first and last axis are same (1) or different (0).
- - frame : rotations are applied to static (0) or rotating (1) frame.
-
-References
-----------
-(1) Matrices and transformations. Ronald Goldman.
- In "Graphics Gems I", pp 472-475. Morgan Kaufmann, 1990.
-(2) More matrices and transformations: shear and pseudo-perspective.
- Ronald Goldman. In "Graphics Gems II", pp 320-323. Morgan Kaufmann, 1991.
-(3) Decomposing a matrix into simple transformations. Spencer Thomas.
- In "Graphics Gems II", pp 320-323. Morgan Kaufmann, 1991.
-(4) Recovering the data from the transformation matrix. Ronald Goldman.
- In "Graphics Gems II", pp 324-331. Morgan Kaufmann, 1991.
-(5) Euler angle conversion. Ken Shoemake.
- In "Graphics Gems IV", pp 222-229. Morgan Kaufmann, 1994.
-(6) Arcball rotation control. Ken Shoemake.
- In "Graphics Gems IV", pp 175-192. Morgan Kaufmann, 1994.
-(7) Representing attitude: Euler angles, unit quaternions, and rotation
- vectors. James Diebel. 2006.
-(8) A discussion of the solution for the best rotation to relate two sets
- of vectors. W Kabsch. Acta Cryst. 1978. A34, 827-828.
-(9) Closed-form solution of absolute orientation using unit quaternions.
- BKP Horn. J Opt Soc Am A. 1987. 4(4):629-642.
-(10) Quaternions. Ken Shoemake.
- http://www.sfu.ca/~jwa3/cmpt461/files/quatut.pdf
-(11) From quaternion to matrix and back. JMP van Waveren. 2005.
- http://www.intel.com/cd/ids/developer/asmo-na/eng/293748.htm
-(12) Uniform random rotations. Ken Shoemake.
- In "Graphics Gems III", pp 124-132. Morgan Kaufmann, 1992.
-(13) Quaternion in molecular modeling. CFF Karney.
- J Mol Graph Mod, 25(5):595-604
-(14) New method for extracting the quaternion from a rotation matrix.
- Itzhack Y Bar-Itzhack, J Guid Contr Dynam. 2000. 23(6): 1085-1087.
-(15) Multiple View Geometry in Computer Vision. Hartley and Zissermann.
- Cambridge University Press; 2nd Ed. 2004. Chapter 4, Algorithm 4.7, p 130.
-(16) Column Vectors vs. Row Vectors.
- http://steve.hollasch.net/cgindex/math/matrix/column-vec.html
-
-Examples
---------
->>> alpha, beta, gamma = 0.123, -1.234, 2.345
->>> origin, xaxis, yaxis, zaxis = [0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]
->>> I = identity_matrix()
->>> Rx = rotation_matrix(alpha, xaxis)
->>> Ry = rotation_matrix(beta, yaxis)
->>> Rz = rotation_matrix(gamma, zaxis)
->>> R = concatenate_matrices(Rx, Ry, Rz)
->>> euler = euler_from_matrix(R, 'rxyz')
->>> numpy.allclose([alpha, beta, gamma], euler)
-True
->>> Re = euler_matrix(alpha, beta, gamma, 'rxyz')
->>> is_same_transform(R, Re)
-True
->>> al, be, ga = euler_from_matrix(Re, 'rxyz')
->>> is_same_transform(Re, euler_matrix(al, be, ga, 'rxyz'))
-True
->>> qx = quaternion_about_axis(alpha, xaxis)
->>> qy = quaternion_about_axis(beta, yaxis)
->>> qz = quaternion_about_axis(gamma, zaxis)
->>> q = quaternion_multiply(qx, qy)
->>> q = quaternion_multiply(q, qz)
->>> Rq = quaternion_matrix(q)
->>> is_same_transform(R, Rq)
-True
->>> S = scale_matrix(1.23, origin)
->>> T = translation_matrix([1, 2, 3])
->>> Z = shear_matrix(beta, xaxis, origin, zaxis)
->>> R = random_rotation_matrix(numpy.random.rand(3))
->>> M = concatenate_matrices(T, R, Z, S)
->>> scale, shear, angles, trans, persp = decompose_matrix(M)
->>> numpy.allclose(scale, 1.23)
-True
->>> numpy.allclose(trans, [1, 2, 3])
-True
->>> numpy.allclose(shear, [0, math.tan(beta), 0])
-True
->>> is_same_transform(R, euler_matrix(axes='sxyz', *angles))
-True
->>> M1 = compose_matrix(scale, shear, angles, trans, persp)
->>> is_same_transform(M, M1)
-True
->>> v0, v1 = random_vector(3), random_vector(3)
->>> M = rotation_matrix(angle_between_vectors(v0, v1), vector_product(v0, v1))
->>> v2 = numpy.dot(v0, M[:3,:3].T)
->>> numpy.allclose(unit_vector(v1), unit_vector(v2))
-True
-
-"""
-
-from __future__ import division, print_function
-
-__version__ = '2019.2.20'
-__docformat__ = 'restructuredtext en'
-
-import math
-
-import numpy
-
-
-def identity_matrix():
- """Return 4x4 identity/unit matrix.
-
- >>> I = identity_matrix()
- >>> numpy.allclose(I, numpy.dot(I, I))
- True
- >>> numpy.sum(I), numpy.trace(I)
- (4.0, 4.0)
- >>> numpy.allclose(I, numpy.identity(4))
- True
-
- """
- return numpy.identity(4)
-
-
-def translation_matrix(direction):
- """Return matrix to translate by direction vector.
-
- >>> v = numpy.random.random(3) - 0.5
- >>> numpy.allclose(v, translation_matrix(v)[:3, 3])
- True
-
- """
- M = numpy.identity(4)
- M[:3, 3] = direction[:3]
- return M
-
-
-def translation_from_matrix(matrix):
- """Return translation vector from translation matrix.
-
- >>> v0 = numpy.random.random(3) - 0.5
- >>> v1 = translation_from_matrix(translation_matrix(v0))
- >>> numpy.allclose(v0, v1)
- True
-
- """
- return numpy.array(matrix, copy=False)[:3, 3].copy()
-
-
-def reflection_matrix(point, normal):
- """Return matrix to mirror at plane defined by point and normal vector.
-
- >>> v0 = numpy.random.random(4) - 0.5
- >>> v0[3] = 1.
- >>> v1 = numpy.random.random(3) - 0.5
- >>> R = reflection_matrix(v0, v1)
- >>> numpy.allclose(2, numpy.trace(R))
- True
- >>> numpy.allclose(v0, numpy.dot(R, v0))
- True
- >>> v2 = v0.copy()
- >>> v2[:3] += v1
- >>> v3 = v0.copy()
- >>> v2[:3] -= v1
- >>> numpy.allclose(v2, numpy.dot(R, v3))
- True
-
- """
- normal = unit_vector(normal[:3])
- M = numpy.identity(4)
- M[:3, :3] -= 2.0 * numpy.outer(normal, normal)
- M[:3, 3] = (2.0 * numpy.dot(point[:3], normal)) * normal
- return M
-
-
-def reflection_from_matrix(matrix):
- """Return mirror plane point and normal vector from reflection matrix.
-
- >>> v0 = numpy.random.random(3) - 0.5
- >>> v1 = numpy.random.random(3) - 0.5
- >>> M0 = reflection_matrix(v0, v1)
- >>> point, normal = reflection_from_matrix(M0)
- >>> M1 = reflection_matrix(point, normal)
- >>> is_same_transform(M0, M1)
- True
-
- """
- M = numpy.array(matrix, dtype=numpy.float64, copy=False)
- # normal: unit eigenvector corresponding to eigenvalue -1
- w, V = numpy.linalg.eig(M[:3, :3])
- i = numpy.where(abs(numpy.real(w) + 1.0) < 1e-8)[0]
- if not len(i):
- raise ValueError('no unit eigenvector corresponding to eigenvalue -1')
- normal = numpy.real(V[:, i[0]]).squeeze()
- # point: any unit eigenvector corresponding to eigenvalue 1
- w, V = numpy.linalg.eig(M)
- i = numpy.where(abs(numpy.real(w) - 1.0) < 1e-8)[0]
- if not len(i):
- raise ValueError('no unit eigenvector corresponding to eigenvalue 1')
- point = numpy.real(V[:, i[-1]]).squeeze()
- point /= point[3]
- return point, normal
-
-
-def rotation_matrix(angle, direction, point=None):
- """Return matrix to rotate about axis defined by point and direction.
-
- >>> R = rotation_matrix(math.pi/2, [0, 0, 1], [1, 0, 0])
- >>> numpy.allclose(numpy.dot(R, [0, 0, 0, 1]), [1, -1, 0, 1])
- True
- >>> angle = (random.random() - 0.5) * (2*math.pi)
- >>> direc = numpy.random.random(3) - 0.5
- >>> point = numpy.random.random(3) - 0.5
- >>> R0 = rotation_matrix(angle, direc, point)
- >>> R1 = rotation_matrix(angle-2*math.pi, direc, point)
- >>> is_same_transform(R0, R1)
- True
- >>> R0 = rotation_matrix(angle, direc, point)
- >>> R1 = rotation_matrix(-angle, -direc, point)
- >>> is_same_transform(R0, R1)
- True
- >>> I = numpy.identity(4, numpy.float64)
- >>> numpy.allclose(I, rotation_matrix(math.pi*2, direc))
- True
- >>> numpy.allclose(2, numpy.trace(rotation_matrix(math.pi/2,
- ... direc, point)))
- True
-
- """
- sina = math.sin(angle)
- cosa = math.cos(angle)
- direction = unit_vector(direction[:3])
- # rotation matrix around unit vector
- R = numpy.diag([cosa, cosa, cosa])
- R += numpy.outer(direction, direction) * (1.0 - cosa)
- direction *= sina
- R += numpy.array([[ 0.0, -direction[2], direction[1]],
- [ direction[2], 0.0, -direction[0]],
- [-direction[1], direction[0], 0.0]])
- M = numpy.identity(4)
- M[:3, :3] = R
- if point is not None:
- # rotation not around origin
- point = numpy.array(point[:3], dtype=numpy.float64, copy=False)
- M[:3, 3] = point - numpy.dot(R, point)
- return M
-
-
-def rotation_from_matrix(matrix):
- """Return rotation angle and axis from rotation matrix.
-
- >>> angle = (random.random() - 0.5) * (2*math.pi)
- >>> direc = numpy.random.random(3) - 0.5
- >>> point = numpy.random.random(3) - 0.5
- >>> R0 = rotation_matrix(angle, direc, point)
- >>> angle, direc, point = rotation_from_matrix(R0)
- >>> R1 = rotation_matrix(angle, direc, point)
- >>> is_same_transform(R0, R1)
- True
-
- """
- R = numpy.array(matrix, dtype=numpy.float64, copy=False)
- R33 = R[:3, :3]
- # direction: unit eigenvector of R33 corresponding to eigenvalue of 1
- w, W = numpy.linalg.eig(R33.T)
- i = numpy.where(abs(numpy.real(w) - 1.0) < 1e-8)[0]
- if not len(i):
- raise ValueError('no unit eigenvector corresponding to eigenvalue 1')
- direction = numpy.real(W[:, i[-1]]).squeeze()
- # point: unit eigenvector of R33 corresponding to eigenvalue of 1
- w, Q = numpy.linalg.eig(R)
- i = numpy.where(abs(numpy.real(w) - 1.0) < 1e-8)[0]
- if not len(i):
- raise ValueError('no unit eigenvector corresponding to eigenvalue 1')
- point = numpy.real(Q[:, i[-1]]).squeeze()
- point /= point[3]
- # rotation angle depending on direction
- cosa = (numpy.trace(R33) - 1.0) / 2.0
- if abs(direction[2]) > 1e-8:
- sina = (R[1, 0] + (cosa-1.0)*direction[0]*direction[1]) / direction[2]
- elif abs(direction[1]) > 1e-8:
- sina = (R[0, 2] + (cosa-1.0)*direction[0]*direction[2]) / direction[1]
- else:
- sina = (R[2, 1] + (cosa-1.0)*direction[1]*direction[2]) / direction[0]
- angle = math.atan2(sina, cosa)
- return angle, direction, point
-
-
-def scale_matrix(factor, origin=None, direction=None):
- """Return matrix to scale by factor around origin in direction.
-
- Use factor -1 for point symmetry.
-
- >>> v = (numpy.random.rand(4, 5) - 0.5) * 20
- >>> v[3] = 1
- >>> S = scale_matrix(-1.234)
- >>> numpy.allclose(numpy.dot(S, v)[:3], -1.234*v[:3])
- True
- >>> factor = random.random() * 10 - 5
- >>> origin = numpy.random.random(3) - 0.5
- >>> direct = numpy.random.random(3) - 0.5
- >>> S = scale_matrix(factor, origin)
- >>> S = scale_matrix(factor, origin, direct)
-
- """
- if direction is None:
- # uniform scaling
- M = numpy.diag([factor, factor, factor, 1.0])
- if origin is not None:
- M[:3, 3] = origin[:3]
- M[:3, 3] *= 1.0 - factor
- else:
- # nonuniform scaling
- direction = unit_vector(direction[:3])
- factor = 1.0 - factor
- M = numpy.identity(4)
- M[:3, :3] -= factor * numpy.outer(direction, direction)
- if origin is not None:
- M[:3, 3] = (factor * numpy.dot(origin[:3], direction)) * direction
- return M
-
-
-def scale_from_matrix(matrix):
- """Return scaling factor, origin and direction from scaling matrix.
-
- >>> factor = random.random() * 10 - 5
- >>> origin = numpy.random.random(3) - 0.5
- >>> direct = numpy.random.random(3) - 0.5
- >>> S0 = scale_matrix(factor, origin)
- >>> factor, origin, direction = scale_from_matrix(S0)
- >>> S1 = scale_matrix(factor, origin, direction)
- >>> is_same_transform(S0, S1)
- True
- >>> S0 = scale_matrix(factor, origin, direct)
- >>> factor, origin, direction = scale_from_matrix(S0)
- >>> S1 = scale_matrix(factor, origin, direction)
- >>> is_same_transform(S0, S1)
- True
-
- """
- M = numpy.array(matrix, dtype=numpy.float64, copy=False)
- M33 = M[:3, :3]
- factor = numpy.trace(M33) - 2.0
- try:
- # direction: unit eigenvector corresponding to eigenvalue factor
- w, V = numpy.linalg.eig(M33)
- i = numpy.where(abs(numpy.real(w) - factor) < 1e-8)[0][0]
- direction = numpy.real(V[:, i]).squeeze()
- direction /= vector_norm(direction)
- except IndexError:
- # uniform scaling
- factor = (factor + 2.0) / 3.0
- direction = None
- # origin: any eigenvector corresponding to eigenvalue 1
- w, V = numpy.linalg.eig(M)
- i = numpy.where(abs(numpy.real(w) - 1.0) < 1e-8)[0]
- if not len(i):
- raise ValueError('no eigenvector corresponding to eigenvalue 1')
- origin = numpy.real(V[:, i[-1]]).squeeze()
- origin /= origin[3]
- return factor, origin, direction
-
-
-def projection_matrix(point, normal, direction=None,
- perspective=None, pseudo=False):
- """Return matrix to project onto plane defined by point and normal.
-
- Using either perspective point, projection direction, or none of both.
-
- If pseudo is True, perspective projections will preserve relative depth
- such that Perspective = dot(Orthogonal, PseudoPerspective).
-
- >>> P = projection_matrix([0, 0, 0], [1, 0, 0])
- >>> numpy.allclose(P[1:, 1:], numpy.identity(4)[1:, 1:])
- True
- >>> point = numpy.random.random(3) - 0.5
- >>> normal = numpy.random.random(3) - 0.5
- >>> direct = numpy.random.random(3) - 0.5
- >>> persp = numpy.random.random(3) - 0.5
- >>> P0 = projection_matrix(point, normal)
- >>> P1 = projection_matrix(point, normal, direction=direct)
- >>> P2 = projection_matrix(point, normal, perspective=persp)
- >>> P3 = projection_matrix(point, normal, perspective=persp, pseudo=True)
- >>> is_same_transform(P2, numpy.dot(P0, P3))
- True
- >>> P = projection_matrix([3, 0, 0], [1, 1, 0], [1, 0, 0])
- >>> v0 = (numpy.random.rand(4, 5) - 0.5) * 20
- >>> v0[3] = 1
- >>> v1 = numpy.dot(P, v0)
- >>> numpy.allclose(v1[1], v0[1])
- True
- >>> numpy.allclose(v1[0], 3-v1[1])
- True
-
- """
- M = numpy.identity(4)
- point = numpy.array(point[:3], dtype=numpy.float64, copy=False)
- normal = unit_vector(normal[:3])
- if perspective is not None:
- # perspective projection
- perspective = numpy.array(perspective[:3], dtype=numpy.float64,
- copy=False)
- M[0, 0] = M[1, 1] = M[2, 2] = numpy.dot(perspective-point, normal)
- M[:3, :3] -= numpy.outer(perspective, normal)
- if pseudo:
- # preserve relative depth
- M[:3, :3] -= numpy.outer(normal, normal)
- M[:3, 3] = numpy.dot(point, normal) * (perspective+normal)
- else:
- M[:3, 3] = numpy.dot(point, normal) * perspective
- M[3, :3] = -normal
- M[3, 3] = numpy.dot(perspective, normal)
- elif direction is not None:
- # parallel projection
- direction = numpy.array(direction[:3], dtype=numpy.float64, copy=False)
- scale = numpy.dot(direction, normal)
- M[:3, :3] -= numpy.outer(direction, normal) / scale
- M[:3, 3] = direction * (numpy.dot(point, normal) / scale)
- else:
- # orthogonal projection
- M[:3, :3] -= numpy.outer(normal, normal)
- M[:3, 3] = numpy.dot(point, normal) * normal
- return M
-
-
-def projection_from_matrix(matrix, pseudo=False):
- """Return projection plane and perspective point from projection matrix.
-
- Return values are same as arguments for projection_matrix function:
- point, normal, direction, perspective, and pseudo.
-
- >>> point = numpy.random.random(3) - 0.5
- >>> normal = numpy.random.random(3) - 0.5
- >>> direct = numpy.random.random(3) - 0.5
- >>> persp = numpy.random.random(3) - 0.5
- >>> P0 = projection_matrix(point, normal)
- >>> result = projection_from_matrix(P0)
- >>> P1 = projection_matrix(*result)
- >>> is_same_transform(P0, P1)
- True
- >>> P0 = projection_matrix(point, normal, direct)
- >>> result = projection_from_matrix(P0)
- >>> P1 = projection_matrix(*result)
- >>> is_same_transform(P0, P1)
- True
- >>> P0 = projection_matrix(point, normal, perspective=persp, pseudo=False)
- >>> result = projection_from_matrix(P0, pseudo=False)
- >>> P1 = projection_matrix(*result)
- >>> is_same_transform(P0, P1)
- True
- >>> P0 = projection_matrix(point, normal, perspective=persp, pseudo=True)
- >>> result = projection_from_matrix(P0, pseudo=True)
- >>> P1 = projection_matrix(*result)
- >>> is_same_transform(P0, P1)
- True
-
- """
- M = numpy.array(matrix, dtype=numpy.float64, copy=False)
- M33 = M[:3, :3]
- w, V = numpy.linalg.eig(M)
- i = numpy.where(abs(numpy.real(w) - 1.0) < 1e-8)[0]
- if not pseudo and len(i):
- # point: any eigenvector corresponding to eigenvalue 1
- point = numpy.real(V[:, i[-1]]).squeeze()
- point /= point[3]
- # direction: unit eigenvector corresponding to eigenvalue 0
- w, V = numpy.linalg.eig(M33)
- i = numpy.where(abs(numpy.real(w)) < 1e-8)[0]
- if not len(i):
- raise ValueError('no eigenvector corresponding to eigenvalue 0')
- direction = numpy.real(V[:, i[0]]).squeeze()
- direction /= vector_norm(direction)
- # normal: unit eigenvector of M33.T corresponding to eigenvalue 0
- w, V = numpy.linalg.eig(M33.T)
- i = numpy.where(abs(numpy.real(w)) < 1e-8)[0]
- if len(i):
- # parallel projection
- normal = numpy.real(V[:, i[0]]).squeeze()
- normal /= vector_norm(normal)
- return point, normal, direction, None, False
- else:
- # orthogonal projection, where normal equals direction vector
- return point, direction, None, None, False
- else:
- # perspective projection
- i = numpy.where(abs(numpy.real(w)) > 1e-8)[0]
- if not len(i):
- raise ValueError(
- 'no eigenvector not corresponding to eigenvalue 0')
- point = numpy.real(V[:, i[-1]]).squeeze()
- point /= point[3]
- normal = - M[3, :3]
- perspective = M[:3, 3] / numpy.dot(point[:3], normal)
- if pseudo:
- perspective -= normal
- return point, normal, None, perspective, pseudo
-
-
-def clip_matrix(left, right, bottom, top, near, far, perspective=False):
- """Return matrix to obtain normalized device coordinates from frustum.
-
- The frustum bounds are axis-aligned along x (left, right),
- y (bottom, top) and z (near, far).
-
- Normalized device coordinates are in range [-1, 1] if coordinates are
- inside the frustum.
-
- If perspective is True the frustum is a truncated pyramid with the
- perspective point at origin and direction along z axis, otherwise an
- orthographic canonical view volume (a box).
-
- Homogeneous coordinates transformed by the perspective clip matrix
- need to be dehomogenized (divided by w coordinate).
-
- >>> frustum = numpy.random.rand(6)
- >>> frustum[1] += frustum[0]
- >>> frustum[3] += frustum[2]
- >>> frustum[5] += frustum[4]
- >>> M = clip_matrix(perspective=False, *frustum)
- >>> numpy.dot(M, [frustum[0], frustum[2], frustum[4], 1])
- array([-1., -1., -1., 1.])
- >>> numpy.dot(M, [frustum[1], frustum[3], frustum[5], 1])
- array([ 1., 1., 1., 1.])
- >>> M = clip_matrix(perspective=True, *frustum)
- >>> v = numpy.dot(M, [frustum[0], frustum[2], frustum[4], 1])
- >>> v / v[3]
- array([-1., -1., -1., 1.])
- >>> v = numpy.dot(M, [frustum[1], frustum[3], frustum[4], 1])
- >>> v / v[3]
- array([ 1., 1., -1., 1.])
-
- """
- if left >= right or bottom >= top or near >= far:
- raise ValueError('invalid frustum')
- if perspective:
- if near <= _EPS:
- raise ValueError('invalid frustum: near <= 0')
- t = 2.0 * near
- M = [[t/(left-right), 0.0, (right+left)/(right-left), 0.0],
- [0.0, t/(bottom-top), (top+bottom)/(top-bottom), 0.0],
- [0.0, 0.0, (far+near)/(near-far), t*far/(far-near)],
- [0.0, 0.0, -1.0, 0.0]]
- else:
- M = [[2.0/(right-left), 0.0, 0.0, (right+left)/(left-right)],
- [0.0, 2.0/(top-bottom), 0.0, (top+bottom)/(bottom-top)],
- [0.0, 0.0, 2.0/(far-near), (far+near)/(near-far)],
- [0.0, 0.0, 0.0, 1.0]]
- return numpy.array(M)
-
-
-def shear_matrix(angle, direction, point, normal):
- """Return matrix to shear by angle along direction vector on shear plane.
-
- The shear plane is defined by a point and normal vector. The direction
- vector must be orthogonal to the plane's normal vector.
-
- A point P is transformed by the shear matrix into P" such that
- the vector P-P" is parallel to the direction vector and its extent is
- given by the angle of P-P'-P", where P' is the orthogonal projection
- of P onto the shear plane.
-
- >>> angle = (random.random() - 0.5) * 4*math.pi
- >>> direct = numpy.random.random(3) - 0.5
- >>> point = numpy.random.random(3) - 0.5
- >>> normal = numpy.cross(direct, numpy.random.random(3))
- >>> S = shear_matrix(angle, direct, point, normal)
- >>> numpy.allclose(1, numpy.linalg.det(S))
- True
-
- """
- normal = unit_vector(normal[:3])
- direction = unit_vector(direction[:3])
- if abs(numpy.dot(normal, direction)) > 1e-6:
- raise ValueError('direction and normal vectors are not orthogonal')
- angle = math.tan(angle)
- M = numpy.identity(4)
- M[:3, :3] += angle * numpy.outer(direction, normal)
- M[:3, 3] = -angle * numpy.dot(point[:3], normal) * direction
- return M
-
-
-def shear_from_matrix(matrix):
- """Return shear angle, direction and plane from shear matrix.
-
- >>> angle = (random.random() - 0.5) * 4*math.pi
- >>> direct = numpy.random.random(3) - 0.5
- >>> point = numpy.random.random(3) - 0.5
- >>> normal = numpy.cross(direct, numpy.random.random(3))
- >>> S0 = shear_matrix(angle, direct, point, normal)
- >>> angle, direct, point, normal = shear_from_matrix(S0)
- >>> S1 = shear_matrix(angle, direct, point, normal)
- >>> is_same_transform(S0, S1)
- True
-
- """
- M = numpy.array(matrix, dtype=numpy.float64, copy=False)
- M33 = M[:3, :3]
- # normal: cross independent eigenvectors corresponding to the eigenvalue 1
- w, V = numpy.linalg.eig(M33)
- i = numpy.where(abs(numpy.real(w) - 1.0) < 1e-4)[0]
- if len(i) < 2:
- raise ValueError('no two linear independent eigenvectors found %s' % w)
- V = numpy.real(V[:, i]).squeeze().T
- lenorm = -1.0
- for i0, i1 in ((0, 1), (0, 2), (1, 2)):
- n = numpy.cross(V[i0], V[i1])
- w = vector_norm(n)
- if w > lenorm:
- lenorm = w
- normal = n
- normal /= lenorm
- # direction and angle
- direction = numpy.dot(M33 - numpy.identity(3), normal)
- angle = vector_norm(direction)
- direction /= angle
- angle = math.atan(angle)
- # point: eigenvector corresponding to eigenvalue 1
- w, V = numpy.linalg.eig(M)
- i = numpy.where(abs(numpy.real(w) - 1.0) < 1e-8)[0]
- if not len(i):
- raise ValueError('no eigenvector corresponding to eigenvalue 1')
- point = numpy.real(V[:, i[-1]]).squeeze()
- point /= point[3]
- return angle, direction, point, normal
-
-
-def decompose_matrix(matrix):
- """Return sequence of transformations from transformation matrix.
-
- matrix : array_like
- Non-degenerative homogeneous transformation matrix
-
- Return tuple of:
- scale : vector of 3 scaling factors
- shear : list of shear factors for x-y, x-z, y-z axes
- angles : list of Euler angles about static x, y, z axes
- translate : translation vector along x, y, z axes
- perspective : perspective partition of matrix
-
- Raise ValueError if matrix is of wrong type or degenerative.
-
- >>> T0 = translation_matrix([1, 2, 3])
- >>> scale, shear, angles, trans, persp = decompose_matrix(T0)
- >>> T1 = translation_matrix(trans)
- >>> numpy.allclose(T0, T1)
- True
- >>> S = scale_matrix(0.123)
- >>> scale, shear, angles, trans, persp = decompose_matrix(S)
- >>> scale[0]
- 0.123
- >>> R0 = euler_matrix(1, 2, 3)
- >>> scale, shear, angles, trans, persp = decompose_matrix(R0)
- >>> R1 = euler_matrix(*angles)
- >>> numpy.allclose(R0, R1)
- True
-
- """
- M = numpy.array(matrix, dtype=numpy.float64, copy=True).T
- if abs(M[3, 3]) < _EPS:
- raise ValueError('M[3, 3] is zero')
- M /= M[3, 3]
- P = M.copy()
- P[:, 3] = 0.0, 0.0, 0.0, 1.0
- if not numpy.linalg.det(P):
- raise ValueError('matrix is singular')
-
- scale = numpy.zeros((3, ))
- shear = [0.0, 0.0, 0.0]
- angles = [0.0, 0.0, 0.0]
-
- if any(abs(M[:3, 3]) > _EPS):
- perspective = numpy.dot(M[:, 3], numpy.linalg.inv(P.T))
- M[:, 3] = 0.0, 0.0, 0.0, 1.0
- else:
- perspective = numpy.array([0.0, 0.0, 0.0, 1.0])
-
- translate = M[3, :3].copy()
- M[3, :3] = 0.0
-
- row = M[:3, :3].copy()
- scale[0] = vector_norm(row[0])
- row[0] /= scale[0]
- shear[0] = numpy.dot(row[0], row[1])
- row[1] -= row[0] * shear[0]
- scale[1] = vector_norm(row[1])
- row[1] /= scale[1]
- shear[0] /= scale[1]
- shear[1] = numpy.dot(row[0], row[2])
- row[2] -= row[0] * shear[1]
- shear[2] = numpy.dot(row[1], row[2])
- row[2] -= row[1] * shear[2]
- scale[2] = vector_norm(row[2])
- row[2] /= scale[2]
- shear[1:] /= scale[2]
-
- if numpy.dot(row[0], numpy.cross(row[1], row[2])) < 0:
- numpy.negative(scale, scale)
- numpy.negative(row, row)
-
- angles[1] = math.asin(-row[0, 2])
- if math.cos(angles[1]):
- angles[0] = math.atan2(row[1, 2], row[2, 2])
- angles[2] = math.atan2(row[0, 1], row[0, 0])
- else:
- # angles[0] = math.atan2(row[1, 0], row[1, 1])
- angles[0] = math.atan2(-row[2, 1], row[1, 1])
- angles[2] = 0.0
-
- return scale, shear, angles, translate, perspective
-
-
-def compose_matrix(scale=None, shear=None, angles=None, translate=None,
- perspective=None):
- """Return transformation matrix from sequence of transformations.
-
- This is the inverse of the decompose_matrix function.
-
- Sequence of transformations:
- scale : vector of 3 scaling factors
- shear : list of shear factors for x-y, x-z, y-z axes
- angles : list of Euler angles about static x, y, z axes
- translate : translation vector along x, y, z axes
- perspective : perspective partition of matrix
-
- >>> scale = numpy.random.random(3) - 0.5
- >>> shear = numpy.random.random(3) - 0.5
- >>> angles = (numpy.random.random(3) - 0.5) * (2*math.pi)
- >>> trans = numpy.random.random(3) - 0.5
- >>> persp = numpy.random.random(4) - 0.5
- >>> M0 = compose_matrix(scale, shear, angles, trans, persp)
- >>> result = decompose_matrix(M0)
- >>> M1 = compose_matrix(*result)
- >>> is_same_transform(M0, M1)
- True
-
- """
- M = numpy.identity(4)
- if perspective is not None:
- P = numpy.identity(4)
- P[3, :] = perspective[:4]
- M = numpy.dot(M, P)
- if translate is not None:
- T = numpy.identity(4)
- T[:3, 3] = translate[:3]
- M = numpy.dot(M, T)
- if angles is not None:
- R = euler_matrix(angles[0], angles[1], angles[2], 'sxyz')
- M = numpy.dot(M, R)
- if shear is not None:
- Z = numpy.identity(4)
- Z[1, 2] = shear[2]
- Z[0, 2] = shear[1]
- Z[0, 1] = shear[0]
- M = numpy.dot(M, Z)
- if scale is not None:
- S = numpy.identity(4)
- S[0, 0] = scale[0]
- S[1, 1] = scale[1]
- S[2, 2] = scale[2]
- M = numpy.dot(M, S)
- M /= M[3, 3]
- return M
-
-
-def orthogonalization_matrix(lengths, angles):
- """Return orthogonalization matrix for crystallographic cell coordinates.
-
- Angles are expected in degrees.
-
- The de-orthogonalization matrix is the inverse.
-
- >>> O = orthogonalization_matrix([10, 10, 10], [90, 90, 90])
- >>> numpy.allclose(O[:3, :3], numpy.identity(3, float) * 10)
- True
- >>> O = orthogonalization_matrix([9.8, 12.0, 15.5], [87.2, 80.7, 69.7])
- >>> numpy.allclose(numpy.sum(O), 43.063229)
- True
-
- """
- a, b, c = lengths
- angles = numpy.radians(angles)
- sina, sinb, _ = numpy.sin(angles)
- cosa, cosb, cosg = numpy.cos(angles)
- co = (cosa * cosb - cosg) / (sina * sinb)
- return numpy.array([
- [ a*sinb*math.sqrt(1.0-co*co), 0.0, 0.0, 0.0],
- [-a*sinb*co, b*sina, 0.0, 0.0],
- [ a*cosb, b*cosa, c, 0.0],
- [ 0.0, 0.0, 0.0, 1.0]])
-
-
-def affine_matrix_from_points(v0, v1, shear=True, scale=True, usesvd=True):
- """Return affine transform matrix to register two point sets.
-
- v0 and v1 are shape (ndims, \*) arrays of at least ndims non-homogeneous
- coordinates, where ndims is the dimensionality of the coordinate space.
-
- If shear is False, a similarity transformation matrix is returned.
- If also scale is False, a rigid/Euclidean transformation matrix
- is returned.
-
- By default the algorithm by Hartley and Zissermann [15] is used.
- If usesvd is True, similarity and Euclidean transformation matrices
- are calculated by minimizing the weighted sum of squared deviations
- (RMSD) according to the algorithm by Kabsch [8].
- Otherwise, and if ndims is 3, the quaternion based algorithm by Horn [9]
- is used, which is slower when using this Python implementation.
-
- The returned matrix performs rotation, translation and uniform scaling
- (if specified).
-
- >>> v0 = [[0, 1031, 1031, 0], [0, 0, 1600, 1600]]
- >>> v1 = [[675, 826, 826, 677], [55, 52, 281, 277]]
- >>> affine_matrix_from_points(v0, v1)
- array([[ 0.14549, 0.00062, 675.50008],
- [ 0.00048, 0.14094, 53.24971],
- [ 0. , 0. , 1. ]])
- >>> T = translation_matrix(numpy.random.random(3)-0.5)
- >>> R = random_rotation_matrix(numpy.random.random(3))
- >>> S = scale_matrix(random.random())
- >>> M = concatenate_matrices(T, R, S)
- >>> v0 = (numpy.random.rand(4, 100) - 0.5) * 20
- >>> v0[3] = 1
- >>> v1 = numpy.dot(M, v0)
- >>> v0[:3] += numpy.random.normal(0, 1e-8, 300).reshape(3, -1)
- >>> M = affine_matrix_from_points(v0[:3], v1[:3])
- >>> numpy.allclose(v1, numpy.dot(M, v0))
- True
-
- More examples in superimposition_matrix()
-
- """
- v0 = numpy.array(v0, dtype=numpy.float64, copy=True)
- v1 = numpy.array(v1, dtype=numpy.float64, copy=True)
-
- ndims = v0.shape[0]
- if ndims < 2 or v0.shape[1] < ndims or v0.shape != v1.shape:
- raise ValueError('input arrays are of wrong shape or type')
-
- # move centroids to origin
- t0 = -numpy.mean(v0, axis=1)
- M0 = numpy.identity(ndims+1)
- M0[:ndims, ndims] = t0
- v0 += t0.reshape(ndims, 1)
- t1 = -numpy.mean(v1, axis=1)
- M1 = numpy.identity(ndims+1)
- M1[:ndims, ndims] = t1
- v1 += t1.reshape(ndims, 1)
-
- if shear:
- # Affine transformation
- A = numpy.concatenate((v0, v1), axis=0)
- u, s, vh = numpy.linalg.svd(A.T)
- vh = vh[:ndims].T
- B = vh[:ndims]
- C = vh[ndims:2*ndims]
- t = numpy.dot(C, numpy.linalg.pinv(B))
- t = numpy.concatenate((t, numpy.zeros((ndims, 1))), axis=1)
- M = numpy.vstack((t, ((0.0,)*ndims) + (1.0,)))
- elif usesvd or ndims != 3:
- # Rigid transformation via SVD of covariance matrix
- u, s, vh = numpy.linalg.svd(numpy.dot(v1, v0.T))
- # rotation matrix from SVD orthonormal bases
- R = numpy.dot(u, vh)
- if numpy.linalg.det(R) < 0.0:
- # R does not constitute right handed system
- R -= numpy.outer(u[:, ndims-1], vh[ndims-1, :]*2.0)
- s[-1] *= -1.0
- # homogeneous transformation matrix
- M = numpy.identity(ndims+1)
- M[:ndims, :ndims] = R
- else:
- # Rigid transformation matrix via quaternion
- # compute symmetric matrix N
- xx, yy, zz = numpy.sum(v0 * v1, axis=1)
- xy, yz, zx = numpy.sum(v0 * numpy.roll(v1, -1, axis=0), axis=1)
- xz, yx, zy = numpy.sum(v0 * numpy.roll(v1, -2, axis=0), axis=1)
- N = [[xx+yy+zz, 0.0, 0.0, 0.0],
- [yz-zy, xx-yy-zz, 0.0, 0.0],
- [zx-xz, xy+yx, yy-xx-zz, 0.0],
- [xy-yx, zx+xz, yz+zy, zz-xx-yy]]
- # quaternion: eigenvector corresponding to most positive eigenvalue
- w, V = numpy.linalg.eigh(N)
- q = V[:, numpy.argmax(w)]
- q /= vector_norm(q) # unit quaternion
- # homogeneous transformation matrix
- M = quaternion_matrix(q)
-
- if scale and not shear:
- # Affine transformation; scale is ratio of RMS deviations from centroid
- v0 *= v0
- v1 *= v1
- M[:ndims, :ndims] *= math.sqrt(numpy.sum(v1) / numpy.sum(v0))
-
- # move centroids back
- M = numpy.dot(numpy.linalg.inv(M1), numpy.dot(M, M0))
- M /= M[ndims, ndims]
- return M
-
-
-def superimposition_matrix(v0, v1, scale=False, usesvd=True):
- """Return matrix to transform given 3D point set into second point set.
-
- v0 and v1 are shape (3, \*) or (4, \*) arrays of at least 3 points.
-
- The parameters scale and usesvd are explained in the more general
- affine_matrix_from_points function.
-
- The returned matrix is a similarity or Euclidean transformation matrix.
- This function has a fast C implementation in transformations.c.
-
- >>> v0 = numpy.random.rand(3, 10)
- >>> M = superimposition_matrix(v0, v0)
- >>> numpy.allclose(M, numpy.identity(4))
- True
- >>> R = random_rotation_matrix(numpy.random.random(3))
- >>> v0 = [[1,0,0], [0,1,0], [0,0,1], [1,1,1]]
- >>> v1 = numpy.dot(R, v0)
- >>> M = superimposition_matrix(v0, v1)
- >>> numpy.allclose(v1, numpy.dot(M, v0))
- True
- >>> v0 = (numpy.random.rand(4, 100) - 0.5) * 20
- >>> v0[3] = 1
- >>> v1 = numpy.dot(R, v0)
- >>> M = superimposition_matrix(v0, v1)
- >>> numpy.allclose(v1, numpy.dot(M, v0))
- True
- >>> S = scale_matrix(random.random())
- >>> T = translation_matrix(numpy.random.random(3)-0.5)
- >>> M = concatenate_matrices(T, R, S)
- >>> v1 = numpy.dot(M, v0)
- >>> v0[:3] += numpy.random.normal(0, 1e-9, 300).reshape(3, -1)
- >>> M = superimposition_matrix(v0, v1, scale=True)
- >>> numpy.allclose(v1, numpy.dot(M, v0))
- True
- >>> M = superimposition_matrix(v0, v1, scale=True, usesvd=False)
- >>> numpy.allclose(v1, numpy.dot(M, v0))
- True
- >>> v = numpy.empty((4, 100, 3))
- >>> v[:, :, 0] = v0
- >>> M = superimposition_matrix(v0, v1, scale=True, usesvd=False)
- >>> numpy.allclose(v1, numpy.dot(M, v[:, :, 0]))
- True
-
- """
- v0 = numpy.array(v0, dtype=numpy.float64, copy=False)[:3]
- v1 = numpy.array(v1, dtype=numpy.float64, copy=False)[:3]
- return affine_matrix_from_points(v0, v1, shear=False,
- scale=scale, usesvd=usesvd)
-
-
-def euler_matrix(ai, aj, ak, axes='sxyz'):
- """Return homogeneous rotation matrix from Euler angles and axis sequence.
-
- ai, aj, ak : Euler's roll, pitch and yaw angles
- axes : One of 24 axis sequences as string or encoded tuple
-
- >>> R = euler_matrix(1, 2, 3, 'syxz')
- >>> numpy.allclose(numpy.sum(R[0]), -1.34786452)
- True
- >>> R = euler_matrix(1, 2, 3, (0, 1, 0, 1))
- >>> numpy.allclose(numpy.sum(R[0]), -0.383436184)
- True
- >>> ai, aj, ak = (4*math.pi) * (numpy.random.random(3) - 0.5)
- >>> for axes in _AXES2TUPLE.keys():
- ... R = euler_matrix(ai, aj, ak, axes)
- >>> for axes in _TUPLE2AXES.keys():
- ... R = euler_matrix(ai, aj, ak, axes)
-
- """
- try:
- firstaxis, parity, repetition, frame = _AXES2TUPLE[axes]
- except (AttributeError, KeyError):
- _TUPLE2AXES[axes] # noqa: validation
- firstaxis, parity, repetition, frame = axes
-
- i = firstaxis
- j = _NEXT_AXIS[i+parity]
- k = _NEXT_AXIS[i-parity+1]
-
- if frame:
- ai, ak = ak, ai
- if parity:
- ai, aj, ak = -ai, -aj, -ak
-
- si, sj, sk = math.sin(ai), math.sin(aj), math.sin(ak)
- ci, cj, ck = math.cos(ai), math.cos(aj), math.cos(ak)
- cc, cs = ci*ck, ci*sk
- sc, ss = si*ck, si*sk
-
- M = numpy.identity(4)
- if repetition:
- M[i, i] = cj
- M[i, j] = sj*si
- M[i, k] = sj*ci
- M[j, i] = sj*sk
- M[j, j] = -cj*ss+cc
- M[j, k] = -cj*cs-sc
- M[k, i] = -sj*ck
- M[k, j] = cj*sc+cs
- M[k, k] = cj*cc-ss
- else:
- M[i, i] = cj*ck
- M[i, j] = sj*sc-cs
- M[i, k] = sj*cc+ss
- M[j, i] = cj*sk
- M[j, j] = sj*ss+cc
- M[j, k] = sj*cs-sc
- M[k, i] = -sj
- M[k, j] = cj*si
- M[k, k] = cj*ci
- return M
-
-
-def euler_from_matrix(matrix, axes='sxyz'):
- """Return Euler angles from rotation matrix for specified axis sequence.
-
- axes : One of 24 axis sequences as string or encoded tuple
-
- Note that many Euler angle triplets can describe one matrix.
-
- >>> R0 = euler_matrix(1, 2, 3, 'syxz')
- >>> al, be, ga = euler_from_matrix(R0, 'syxz')
- >>> R1 = euler_matrix(al, be, ga, 'syxz')
- >>> numpy.allclose(R0, R1)
- True
- >>> angles = (4*math.pi) * (numpy.random.random(3) - 0.5)
- >>> for axes in _AXES2TUPLE.keys():
- ... R0 = euler_matrix(axes=axes, *angles)
- ... R1 = euler_matrix(axes=axes, *euler_from_matrix(R0, axes))
- ... if not numpy.allclose(R0, R1): print(axes, "failed")
-
- """
- try:
- firstaxis, parity, repetition, frame = _AXES2TUPLE[axes.lower()]
- except (AttributeError, KeyError):
- _TUPLE2AXES[axes] # noqa: validation
- firstaxis, parity, repetition, frame = axes
-
- i = firstaxis
- j = _NEXT_AXIS[i+parity]
- k = _NEXT_AXIS[i-parity+1]
-
- M = numpy.array(matrix, dtype=numpy.float64, copy=False)[:3, :3]
- if repetition:
- sy = math.sqrt(M[i, j]*M[i, j] + M[i, k]*M[i, k])
- if sy > _EPS:
- ax = math.atan2( M[i, j], M[i, k])
- ay = math.atan2( sy, M[i, i])
- az = math.atan2( M[j, i], -M[k, i])
- else:
- ax = math.atan2(-M[j, k], M[j, j])
- ay = math.atan2( sy, M[i, i])
- az = 0.0
- else:
- cy = math.sqrt(M[i, i]*M[i, i] + M[j, i]*M[j, i])
- if cy > _EPS:
- ax = math.atan2( M[k, j], M[k, k])
- ay = math.atan2(-M[k, i], cy)
- az = math.atan2( M[j, i], M[i, i])
- else:
- ax = math.atan2(-M[j, k], M[j, j])
- ay = math.atan2(-M[k, i], cy)
- az = 0.0
-
- if parity:
- ax, ay, az = -ax, -ay, -az
- if frame:
- ax, az = az, ax
- return ax, ay, az
-
-
-def euler_from_quaternion(quaternion, axes='sxyz'):
- """Return Euler angles from quaternion for specified axis sequence.
-
- >>> angles = euler_from_quaternion([0.99810947, 0.06146124, 0, 0])
- >>> numpy.allclose(angles, [0.123, 0, 0])
- True
-
- """
- return euler_from_matrix(quaternion_matrix(quaternion), axes)
-
-
-def quaternion_from_euler(ai, aj, ak, axes='sxyz'):
- """Return quaternion from Euler angles and axis sequence.
-
- ai, aj, ak : Euler's roll, pitch and yaw angles
- axes : One of 24 axis sequences as string or encoded tuple
-
- >>> q = quaternion_from_euler(1, 2, 3, 'ryxz')
- >>> numpy.allclose(q, [0.435953, 0.310622, -0.718287, 0.444435])
- True
-
- """
- try:
- firstaxis, parity, repetition, frame = _AXES2TUPLE[axes.lower()]
- except (AttributeError, KeyError):
- _TUPLE2AXES[axes] # noqa: validation
- firstaxis, parity, repetition, frame = axes
-
- i = firstaxis + 1
- j = _NEXT_AXIS[i+parity-1] + 1
- k = _NEXT_AXIS[i-parity] + 1
-
- if frame:
- ai, ak = ak, ai
- if parity:
- aj = -aj
-
- ai /= 2.0
- aj /= 2.0
- ak /= 2.0
- ci = math.cos(ai)
- si = math.sin(ai)
- cj = math.cos(aj)
- sj = math.sin(aj)
- ck = math.cos(ak)
- sk = math.sin(ak)
- cc = ci*ck
- cs = ci*sk
- sc = si*ck
- ss = si*sk
-
- q = numpy.empty((4, ))
- if repetition:
- q[0] = cj*(cc - ss)
- q[i] = cj*(cs + sc)
- q[j] = sj*(cc + ss)
- q[k] = sj*(cs - sc)
- else:
- q[0] = cj*cc + sj*ss
- q[i] = cj*sc - sj*cs
- q[j] = cj*ss + sj*cc
- q[k] = cj*cs - sj*sc
- if parity:
- q[j] *= -1.0
-
- return q
-
-
-def quaternion_about_axis(angle, axis):
- """Return quaternion for rotation about axis.
-
- >>> q = quaternion_about_axis(0.123, [1, 0, 0])
- >>> numpy.allclose(q, [0.99810947, 0.06146124, 0, 0])
- True
-
- """
- q = numpy.array([0.0, axis[0], axis[1], axis[2]])
- qlen = vector_norm(q)
- if qlen > _EPS:
- q *= math.sin(angle/2.0) / qlen
- q[0] = math.cos(angle/2.0)
- return q
-
-
-def quaternion_matrix(quaternion):
- """Return homogeneous rotation matrix from quaternion.
-
- >>> M = quaternion_matrix([0.99810947, 0.06146124, 0, 0])
- >>> numpy.allclose(M, rotation_matrix(0.123, [1, 0, 0]))
- True
- >>> M = quaternion_matrix([1, 0, 0, 0])
- >>> numpy.allclose(M, numpy.identity(4))
- True
- >>> M = quaternion_matrix([0, 1, 0, 0])
- >>> numpy.allclose(M, numpy.diag([1, -1, -1, 1]))
- True
-
- """
- q = numpy.array(quaternion, dtype=numpy.float64, copy=True)
- n = numpy.dot(q, q)
- if n < _EPS:
- return numpy.identity(4)
- q *= math.sqrt(2.0 / n)
- q = numpy.outer(q, q)
- return numpy.array([
- [1.0-q[2, 2]-q[3, 3], q[1, 2]-q[3, 0], q[1, 3]+q[2, 0], 0.0],
- [ q[1, 2]+q[3, 0], 1.0-q[1, 1]-q[3, 3], q[2, 3]-q[1, 0], 0.0],
- [ q[1, 3]-q[2, 0], q[2, 3]+q[1, 0], 1.0-q[1, 1]-q[2, 2], 0.0],
- [ 0.0, 0.0, 0.0, 1.0]])
-
-
-def quaternion_from_matrix(matrix, isprecise=False):
- """Return quaternion from rotation matrix.
-
- If isprecise is True, the input matrix is assumed to be a precise rotation
- matrix and a faster algorithm is used.
-
- >>> q = quaternion_from_matrix(numpy.identity(4), True)
- >>> numpy.allclose(q, [1, 0, 0, 0])
- True
- >>> q = quaternion_from_matrix(numpy.diag([1, -1, -1, 1]))
- >>> numpy.allclose(q, [0, 1, 0, 0]) or numpy.allclose(q, [0, -1, 0, 0])
- True
- >>> R = rotation_matrix(0.123, (1, 2, 3))
- >>> q = quaternion_from_matrix(R, True)
- >>> numpy.allclose(q, [0.9981095, 0.0164262, 0.0328524, 0.0492786])
- True
- >>> R = [[-0.545, 0.797, 0.260, 0], [0.733, 0.603, -0.313, 0],
- ... [-0.407, 0.021, -0.913, 0], [0, 0, 0, 1]]
- >>> q = quaternion_from_matrix(R)
- >>> numpy.allclose(q, [0.19069, 0.43736, 0.87485, -0.083611])
- True
- >>> R = [[0.395, 0.362, 0.843, 0], [-0.626, 0.796, -0.056, 0],
- ... [-0.677, -0.498, 0.529, 0], [0, 0, 0, 1]]
- >>> q = quaternion_from_matrix(R)
- >>> numpy.allclose(q, [0.82336615, -0.13610694, 0.46344705, -0.29792603])
- True
- >>> R = random_rotation_matrix()
- >>> q = quaternion_from_matrix(R)
- >>> is_same_transform(R, quaternion_matrix(q))
- True
- >>> is_same_quaternion(quaternion_from_matrix(R, isprecise=False),
- ... quaternion_from_matrix(R, isprecise=True))
- True
- >>> R = euler_matrix(0.0, 0.0, numpy.pi/2.0)
- >>> is_same_quaternion(quaternion_from_matrix(R, isprecise=False),
- ... quaternion_from_matrix(R, isprecise=True))
- True
-
- """
- M = numpy.array(matrix, dtype=numpy.float64, copy=False)[:4, :4]
- if isprecise:
- q = numpy.empty((4, ))
- t = numpy.trace(M)
- if t > M[3, 3]:
- q[0] = t
- q[3] = M[1, 0] - M[0, 1]
- q[2] = M[0, 2] - M[2, 0]
- q[1] = M[2, 1] - M[1, 2]
- else:
- i, j, k = 0, 1, 2
- if M[1, 1] > M[0, 0]:
- i, j, k = 1, 2, 0
- if M[2, 2] > M[i, i]:
- i, j, k = 2, 0, 1
- t = M[i, i] - (M[j, j] + M[k, k]) + M[3, 3]
- q[i] = t
- q[j] = M[i, j] + M[j, i]
- q[k] = M[k, i] + M[i, k]
- q[3] = M[k, j] - M[j, k]
- q = q[[3, 0, 1, 2]]
- q *= 0.5 / math.sqrt(t * M[3, 3])
- else:
- m00 = M[0, 0]
- m01 = M[0, 1]
- m02 = M[0, 2]
- m10 = M[1, 0]
- m11 = M[1, 1]
- m12 = M[1, 2]
- m20 = M[2, 0]
- m21 = M[2, 1]
- m22 = M[2, 2]
- # symmetric matrix K
- K = numpy.array([[m00-m11-m22, 0.0, 0.0, 0.0],
- [m01+m10, m11-m00-m22, 0.0, 0.0],
- [m02+m20, m12+m21, m22-m00-m11, 0.0],
- [m21-m12, m02-m20, m10-m01, m00+m11+m22]])
- K /= 3.0
- # quaternion is eigenvector of K that corresponds to largest eigenvalue
- w, V = numpy.linalg.eigh(K)
- q = V[[3, 0, 1, 2], numpy.argmax(w)]
- if q[0] < 0.0:
- numpy.negative(q, q)
- return q
-
-
-def quaternion_multiply(quaternion1, quaternion0):
- """Return multiplication of two quaternions.
-
- >>> q = quaternion_multiply([4, 1, -2, 3], [8, -5, 6, 7])
- >>> numpy.allclose(q, [28, -44, -14, 48])
- True
-
- """
- w0, x0, y0, z0 = quaternion0
- w1, x1, y1, z1 = quaternion1
- return numpy.array([
- -x1*x0 - y1*y0 - z1*z0 + w1*w0,
- x1*w0 + y1*z0 - z1*y0 + w1*x0,
- -x1*z0 + y1*w0 + z1*x0 + w1*y0,
- x1*y0 - y1*x0 + z1*w0 + w1*z0], dtype=numpy.float64)
-
-
-def quaternion_conjugate(quaternion):
- """Return conjugate of quaternion.
-
- >>> q0 = random_quaternion()
- >>> q1 = quaternion_conjugate(q0)
- >>> q1[0] == q0[0] and all(q1[1:] == -q0[1:])
- True
-
- """
- q = numpy.array(quaternion, dtype=numpy.float64, copy=True)
- numpy.negative(q[1:], q[1:])
- return q
-
-
-def quaternion_inverse(quaternion):
- """Return inverse of quaternion.
-
- >>> q0 = random_quaternion()
- >>> q1 = quaternion_inverse(q0)
- >>> numpy.allclose(quaternion_multiply(q0, q1), [1, 0, 0, 0])
- True
-
- """
- q = numpy.array(quaternion, dtype=numpy.float64, copy=True)
- numpy.negative(q[1:], q[1:])
- return q / numpy.dot(q, q)
-
-
-def quaternion_real(quaternion):
- """Return real part of quaternion.
-
- >>> quaternion_real([3, 0, 1, 2])
- 3.0
-
- """
- return float(quaternion[0])
-
-
-def quaternion_imag(quaternion):
- """Return imaginary part of quaternion.
-
- >>> quaternion_imag([3, 0, 1, 2])
- array([ 0., 1., 2.])
-
- """
- return numpy.array(quaternion[1:4], dtype=numpy.float64, copy=True)
-
-
-def quaternion_slerp(quat0, quat1, fraction, spin=0, shortestpath=True):
- """Return spherical linear interpolation between two quaternions.
-
- >>> q0 = random_quaternion()
- >>> q1 = random_quaternion()
- >>> q = quaternion_slerp(q0, q1, 0)
- >>> numpy.allclose(q, q0)
- True
- >>> q = quaternion_slerp(q0, q1, 1, 1)
- >>> numpy.allclose(q, q1)
- True
- >>> q = quaternion_slerp(q0, q1, 0.5)
- >>> angle = math.acos(numpy.dot(q0, q))
- >>> numpy.allclose(2, math.acos(numpy.dot(q0, q1)) / angle) or \
- numpy.allclose(2, math.acos(-numpy.dot(q0, q1)) / angle)
- True
-
- """
- q0 = unit_vector(quat0[:4])
- q1 = unit_vector(quat1[:4])
- if fraction == 0.0:
- return q0
- elif fraction == 1.0:
- return q1
- d = numpy.dot(q0, q1)
- if abs(abs(d) - 1.0) < _EPS:
- return q0
- if shortestpath and d < 0.0:
- # invert rotation
- d = -d
- numpy.negative(q1, q1)
- angle = math.acos(d) + spin * math.pi
- if abs(angle) < _EPS:
- return q0
- isin = 1.0 / math.sin(angle)
- q0 *= math.sin((1.0 - fraction) * angle) * isin
- q1 *= math.sin(fraction * angle) * isin
- q0 += q1
- return q0
-
-
-def random_quaternion(rand=None):
- """Return uniform random unit quaternion.
-
- rand: array like or None
- Three independent random variables that are uniformly distributed
- between 0 and 1.
-
- >>> q = random_quaternion()
- >>> numpy.allclose(1, vector_norm(q))
- True
- >>> q = random_quaternion(numpy.random.random(3))
- >>> len(q.shape), q.shape[0]==4
- (1, True)
-
- """
- if rand is None:
- rand = numpy.random.rand(3)
- else:
- assert len(rand) == 3
- r1 = numpy.sqrt(1.0 - rand[0])
- r2 = numpy.sqrt(rand[0])
- pi2 = math.pi * 2.0
- t1 = pi2 * rand[1]
- t2 = pi2 * rand[2]
- return numpy.array([numpy.cos(t2)*r2, numpy.sin(t1)*r1,
- numpy.cos(t1)*r1, numpy.sin(t2)*r2])
-
-
-def random_rotation_matrix(rand=None):
- """Return uniform random rotation matrix.
-
- rand: array like
- Three independent random variables that are uniformly distributed
- between 0 and 1 for each returned quaternion.
-
- >>> R = random_rotation_matrix()
- >>> numpy.allclose(numpy.dot(R.T, R), numpy.identity(4))
- True
-
- """
- return quaternion_matrix(random_quaternion(rand))
-
-
-class Arcball(object):
- """Virtual Trackball Control.
-
- >>> ball = Arcball()
- >>> ball = Arcball(initial=numpy.identity(4))
- >>> ball.place([320, 320], 320)
- >>> ball.down([500, 250])
- >>> ball.drag([475, 275])
- >>> R = ball.matrix()
- >>> numpy.allclose(numpy.sum(R), 3.90583455)
- True
- >>> ball = Arcball(initial=[1, 0, 0, 0])
- >>> ball.place([320, 320], 320)
- >>> ball.setaxes([1, 1, 0], [-1, 1, 0])
- >>> ball.constrain = True
- >>> ball.down([400, 200])
- >>> ball.drag([200, 400])
- >>> R = ball.matrix()
- >>> numpy.allclose(numpy.sum(R), 0.2055924)
- True
- >>> ball.next()
-
- """
- def __init__(self, initial=None):
- """Initialize virtual trackball control.
-
- initial : quaternion or rotation matrix
-
- """
- self._axis = None
- self._axes = None
- self._radius = 1.0
- self._center = [0.0, 0.0]
- self._vdown = numpy.array([0.0, 0.0, 1.0])
- self._constrain = False
- if initial is None:
- self._qdown = numpy.array([1.0, 0.0, 0.0, 0.0])
- else:
- initial = numpy.array(initial, dtype=numpy.float64)
- if initial.shape == (4, 4):
- self._qdown = quaternion_from_matrix(initial)
- elif initial.shape == (4, ):
- initial /= vector_norm(initial)
- self._qdown = initial
- else:
- raise ValueError("initial not a quaternion or matrix")
- self._qnow = self._qpre = self._qdown
-
- def place(self, center, radius):
- """Place Arcball, e.g. when window size changes.
-
- center : sequence[2]
- Window coordinates of trackball center.
- radius : float
- Radius of trackball in window coordinates.
-
- """
- self._radius = float(radius)
- self._center[0] = center[0]
- self._center[1] = center[1]
-
- def setaxes(self, *axes):
- """Set axes to constrain rotations."""
- if axes is None:
- self._axes = None
- else:
- self._axes = [unit_vector(axis) for axis in axes]
-
- @property
- def constrain(self):
- """Return state of constrain to axis mode."""
- return self._constrain
-
- @constrain.setter
- def constrain(self, value):
- """Set state of constrain to axis mode."""
- self._constrain = bool(value)
-
- def down(self, point):
- """Set initial cursor window coordinates and pick constrain-axis."""
- self._vdown = arcball_map_to_sphere(point, self._center, self._radius)
- self._qdown = self._qpre = self._qnow
- if self._constrain and self._axes is not None:
- self._axis = arcball_nearest_axis(self._vdown, self._axes)
- self._vdown = arcball_constrain_to_axis(self._vdown, self._axis)
- else:
- self._axis = None
-
- def drag(self, point):
- """Update current cursor window coordinates."""
- vnow = arcball_map_to_sphere(point, self._center, self._radius)
- if self._axis is not None:
- vnow = arcball_constrain_to_axis(vnow, self._axis)
- self._qpre = self._qnow
- t = numpy.cross(self._vdown, vnow)
- if numpy.dot(t, t) < _EPS:
- self._qnow = self._qdown
- else:
- q = [numpy.dot(self._vdown, vnow), t[0], t[1], t[2]]
- self._qnow = quaternion_multiply(q, self._qdown)
-
- def next(self, acceleration=0.0):
- """Continue rotation in direction of last drag."""
- q = quaternion_slerp(self._qpre, self._qnow, 2.0+acceleration, False)
- self._qpre, self._qnow = self._qnow, q
-
- def matrix(self):
- """Return homogeneous rotation matrix."""
- return quaternion_matrix(self._qnow)
-
-
-def arcball_map_to_sphere(point, center, radius):
- """Return unit sphere coordinates from window coordinates."""
- v0 = (point[0] - center[0]) / radius
- v1 = (center[1] - point[1]) / radius
- n = v0*v0 + v1*v1
- if n > 1.0:
- # position outside of sphere
- n = math.sqrt(n)
- return numpy.array([v0/n, v1/n, 0.0])
- else:
- return numpy.array([v0, v1, math.sqrt(1.0 - n)])
-
-
-def arcball_constrain_to_axis(point, axis):
- """Return sphere point perpendicular to axis."""
- v = numpy.array(point, dtype=numpy.float64, copy=True)
- a = numpy.array(axis, dtype=numpy.float64, copy=True)
- v -= a * numpy.dot(a, v) # on plane
- n = vector_norm(v)
- if n > _EPS:
- if v[2] < 0.0:
- numpy.negative(v, v)
- v /= n
- return v
- if a[2] == 1.0:
- return numpy.array([1.0, 0.0, 0.0])
- return unit_vector([-a[1], a[0], 0.0])
-
-
-def arcball_nearest_axis(point, axes):
- """Return axis, which arc is nearest to point."""
- point = numpy.array(point, dtype=numpy.float64, copy=False)
- nearest = None
- mx = -1.0
- for axis in axes:
- t = numpy.dot(arcball_constrain_to_axis(point, axis), point)
- if t > mx:
- nearest = axis
- mx = t
- return nearest
-
-
-# epsilon for testing whether a number is close to zero
-_EPS = numpy.finfo(float).eps * 4.0
-
-# axis sequences for Euler angles
-_NEXT_AXIS = [1, 2, 0, 1]
-
-# map axes strings to/from tuples of inner axis, parity, repetition, frame
-_AXES2TUPLE = {
- 'sxyz': (0, 0, 0, 0), 'sxyx': (0, 0, 1, 0), 'sxzy': (0, 1, 0, 0),
- 'sxzx': (0, 1, 1, 0), 'syzx': (1, 0, 0, 0), 'syzy': (1, 0, 1, 0),
- 'syxz': (1, 1, 0, 0), 'syxy': (1, 1, 1, 0), 'szxy': (2, 0, 0, 0),
- 'szxz': (2, 0, 1, 0), 'szyx': (2, 1, 0, 0), 'szyz': (2, 1, 1, 0),
- 'rzyx': (0, 0, 0, 1), 'rxyx': (0, 0, 1, 1), 'ryzx': (0, 1, 0, 1),
- 'rxzx': (0, 1, 1, 1), 'rxzy': (1, 0, 0, 1), 'ryzy': (1, 0, 1, 1),
- 'rzxy': (1, 1, 0, 1), 'ryxy': (1, 1, 1, 1), 'ryxz': (2, 0, 0, 1),
- 'rzxz': (2, 0, 1, 1), 'rxyz': (2, 1, 0, 1), 'rzyz': (2, 1, 1, 1)}
-
-_TUPLE2AXES = dict((v, k) for k, v in _AXES2TUPLE.items())
-
-
-def vector_norm(data, axis=None, out=None):
- """Return length, i.e. Euclidean norm, of ndarray along axis.
-
- >>> v = numpy.random.random(3)
- >>> n = vector_norm(v)
- >>> numpy.allclose(n, numpy.linalg.norm(v))
- True
- >>> v = numpy.random.rand(6, 5, 3)
- >>> n = vector_norm(v, axis=-1)
- >>> numpy.allclose(n, numpy.sqrt(numpy.sum(v*v, axis=2)))
- True
- >>> n = vector_norm(v, axis=1)
- >>> numpy.allclose(n, numpy.sqrt(numpy.sum(v*v, axis=1)))
- True
- >>> v = numpy.random.rand(5, 4, 3)
- >>> n = numpy.empty((5, 3))
- >>> vector_norm(v, axis=1, out=n)
- >>> numpy.allclose(n, numpy.sqrt(numpy.sum(v*v, axis=1)))
- True
- >>> vector_norm([])
- 0.0
- >>> vector_norm([1])
- 1.0
-
- """
- data = numpy.array(data, dtype=numpy.float64, copy=True)
- if out is None:
- if data.ndim == 1:
- return math.sqrt(numpy.dot(data, data))
- data *= data
- out = numpy.atleast_1d(numpy.sum(data, axis=axis))
- numpy.sqrt(out, out)
- return out
- else:
- data *= data
- numpy.sum(data, axis=axis, out=out)
- numpy.sqrt(out, out)
-
-
-def unit_vector(data, axis=None, out=None):
- """Return ndarray normalized by length, i.e. Euclidean norm, along axis.
-
- >>> v0 = numpy.random.random(3)
- >>> v1 = unit_vector(v0)
- >>> numpy.allclose(v1, v0 / numpy.linalg.norm(v0))
- True
- >>> v0 = numpy.random.rand(5, 4, 3)
- >>> v1 = unit_vector(v0, axis=-1)
- >>> v2 = v0 / numpy.expand_dims(numpy.sqrt(numpy.sum(v0*v0, axis=2)), 2)
- >>> numpy.allclose(v1, v2)
- True
- >>> v1 = unit_vector(v0, axis=1)
- >>> v2 = v0 / numpy.expand_dims(numpy.sqrt(numpy.sum(v0*v0, axis=1)), 1)
- >>> numpy.allclose(v1, v2)
- True
- >>> v1 = numpy.empty((5, 4, 3))
- >>> unit_vector(v0, axis=1, out=v1)
- >>> numpy.allclose(v1, v2)
- True
- >>> list(unit_vector([]))
- []
- >>> list(unit_vector([1]))
- [1.0]
-
- """
- if out is None:
- data = numpy.array(data, dtype=numpy.float64, copy=True)
- if data.ndim == 1:
- data /= math.sqrt(numpy.dot(data, data))
- return data
- else:
- if out is not data:
- out[:] = numpy.array(data, copy=False)
- data = out
- length = numpy.atleast_1d(numpy.sum(data*data, axis))
- numpy.sqrt(length, length)
- if axis is not None:
- length = numpy.expand_dims(length, axis)
- data /= length
- if out is None:
- return data
-
-
-def random_vector(size):
- """Return array of random doubles in the half-open interval [0.0, 1.0).
-
- >>> v = random_vector(10000)
- >>> numpy.all(v >= 0) and numpy.all(v < 1)
- True
- >>> v0 = random_vector(10)
- >>> v1 = random_vector(10)
- >>> numpy.any(v0 == v1)
- False
-
- """
- return numpy.random.random(size)
-
-
-def vector_product(v0, v1, axis=0):
- """Return vector perpendicular to vectors.
-
- >>> v = vector_product([2, 0, 0], [0, 3, 0])
- >>> numpy.allclose(v, [0, 0, 6])
- True
- >>> v0 = [[2, 0, 0, 2], [0, 2, 0, 2], [0, 0, 2, 2]]
- >>> v1 = [[3], [0], [0]]
- >>> v = vector_product(v0, v1)
- >>> numpy.allclose(v, [[0, 0, 0, 0], [0, 0, 6, 6], [0, -6, 0, -6]])
- True
- >>> v0 = [[2, 0, 0], [2, 0, 0], [0, 2, 0], [2, 0, 0]]
- >>> v1 = [[0, 3, 0], [0, 0, 3], [0, 0, 3], [3, 3, 3]]
- >>> v = vector_product(v0, v1, axis=1)
- >>> numpy.allclose(v, [[0, 0, 6], [0, -6, 0], [6, 0, 0], [0, -6, 6]])
- True
-
- """
- return numpy.cross(v0, v1, axis=axis)
-
-
-def angle_between_vectors(v0, v1, directed=True, axis=0):
- """Return angle between vectors.
-
- If directed is False, the input vectors are interpreted as undirected axes,
- i.e. the maximum angle is pi/2.
-
- >>> a = angle_between_vectors([1, -2, 3], [-1, 2, -3])
- >>> numpy.allclose(a, math.pi)
- True
- >>> a = angle_between_vectors([1, -2, 3], [-1, 2, -3], directed=False)
- >>> numpy.allclose(a, 0)
- True
- >>> v0 = [[2, 0, 0, 2], [0, 2, 0, 2], [0, 0, 2, 2]]
- >>> v1 = [[3], [0], [0]]
- >>> a = angle_between_vectors(v0, v1)
- >>> numpy.allclose(a, [0, 1.5708, 1.5708, 0.95532])
- True
- >>> v0 = [[2, 0, 0], [2, 0, 0], [0, 2, 0], [2, 0, 0]]
- >>> v1 = [[0, 3, 0], [0, 0, 3], [0, 0, 3], [3, 3, 3]]
- >>> a = angle_between_vectors(v0, v1, axis=1)
- >>> numpy.allclose(a, [1.5708, 1.5708, 1.5708, 0.95532])
- True
-
- """
- v0 = numpy.array(v0, dtype=numpy.float64, copy=False)
- v1 = numpy.array(v1, dtype=numpy.float64, copy=False)
- dot = numpy.sum(v0 * v1, axis=axis)
- dot /= vector_norm(v0, axis=axis) * vector_norm(v1, axis=axis)
- dot = numpy.clip(dot, -1.0, 1.0)
- return numpy.arccos(dot if directed else numpy.fabs(dot))
-
-
-def inverse_matrix(matrix):
- """Return inverse of square transformation matrix.
-
- >>> M0 = random_rotation_matrix()
- >>> M1 = inverse_matrix(M0.T)
- >>> numpy.allclose(M1, numpy.linalg.inv(M0.T))
- True
- >>> for size in range(1, 7):
- ... M0 = numpy.random.rand(size, size)
- ... M1 = inverse_matrix(M0)
- ... if not numpy.allclose(M1, numpy.linalg.inv(M0)): print(size)
-
- """
- return numpy.linalg.inv(matrix)
-
-
-def concatenate_matrices(*matrices):
- """Return concatenation of series of transformation matrices.
-
- >>> M = numpy.random.rand(16).reshape((4, 4)) - 0.5
- >>> numpy.allclose(M, concatenate_matrices(M))
- True
- >>> numpy.allclose(numpy.dot(M, M.T), concatenate_matrices(M, M.T))
- True
-
- """
- M = numpy.identity(4)
- for i in matrices:
- M = numpy.dot(M, i)
- return M
-
-
-def is_same_transform(matrix0, matrix1):
- """Return True if two matrices perform same transformation.
-
- >>> is_same_transform(numpy.identity(4), numpy.identity(4))
- True
- >>> is_same_transform(numpy.identity(4), random_rotation_matrix())
- False
-
- """
- matrix0 = numpy.array(matrix0, dtype=numpy.float64, copy=True)
- matrix0 /= matrix0[3, 3]
- matrix1 = numpy.array(matrix1, dtype=numpy.float64, copy=True)
- matrix1 /= matrix1[3, 3]
- return numpy.allclose(matrix0, matrix1)
-
-
-def is_same_quaternion(q0, q1):
- """Return True if two quaternions are equal."""
- q0 = numpy.array(q0)
- q1 = numpy.array(q1)
- return numpy.allclose(q0, q1) or numpy.allclose(q0, -q1)
-
-
-def _import_module(name, package=None, warn=True, postfix='_py', ignore='_'):
- """Try import all public attributes from module into global namespace.
-
- Existing attributes with name clashes are renamed with prefix.
- Attributes starting with underscore are ignored by default.
-
- Return True on successful import.
-
- """
- import warnings
- from importlib import import_module
- try:
- if not package:
- module = import_module(name)
- else:
- module = import_module('.' + name, package=package)
- except ImportError as err:
- if warn:
- warnings.warn(str(err))
- else:
- for attr in dir(module):
- if ignore and attr.startswith(ignore):
- continue
- if postfix:
- if attr in globals():
- globals()[attr + postfix] = globals()[attr]
- elif warn:
- warnings.warn('no Python implementation of ' + attr)
- globals()[attr] = getattr(module, attr)
- return True
-
-
-_import_module('_transformations', __package__)
-
-
-if __name__ == '__main__':
- import doctest
- import random # noqa: used in doctests
- try:
- numpy.set_printoptions(suppress=True, precision=5, legacy='1.13')
- except TypeError:
- numpy.set_printoptions(suppress=True, precision=5)
- doctest.testmod()
-
-