An extended version of https://bl.ocks.org/vkuchinov/a8248a3487da0d7c7f6e002845d00038
This version is based on OrbitControls.js.
Possibly should deligate some processes to worker.js or GLSL. Using BufferGeometry istead of Geometry is another option.
An extended version of https://bl.ocks.org/vkuchinov/a8248a3487da0d7c7f6e002845d00038
This version is based on OrbitControls.js.
Possibly should deligate some processes to worker.js or GLSL. Using BufferGeometry istead of Geometry is another option.
| id | x | y | z | colorid | radius | |
|---|---|---|---|---|---|---|
| 1 | 4.482339877 | -3.858535069 | -4.466362452 | 9 | 190 | |
| 2 | 6.06070237 | -2.416998983 | -1.556150519 | 2 | 472 | |
| 3 | 5.72501809 | -1.785750425 | 6.442992045 | 5 | 69 | |
| 4 | 0.8025236617 | -3.445751373 | 0.748589644 | 8 | 104 | |
| 5 | -2.040992897 | 0.2825309251 | -0.0666878286 | 6 | 500 | |
| 6 | 3.429120936 | -1.507411016 | -1.601075745 | 3 | 37 | |
| 7 | -1.58038841 | 0.6887202924 | 2.340087009 | 10 | 366 | |
| 8 | 2.613144321 | -0.7398779626 | 2.534196837 | 7 | 96 | |
| 9 | 0.3859048242 | 1.705626991 | 10.68581231 | 4 | 323 | |
| 10 | 2.060262558 | -0.090579813 | 0.598218811 | 7 | 453 | |
| 11 | -1.573490398 | -2.740830799 | 3.559481967 | 3 | 33 | |
| 12 | 0.259324269 | -0.8356099489 | -0.4705839817 | 5 | 308 | |
| 13 | 4.474273791 | 0.6449189057 | 0.3318801124 | 5 | 371 | |
| 14 | 0.503862094 | -1.029535782 | -3.063317745 | 1 | 47 | |
| 15 | 2.800118232 | -0.3262068538 | 6.772912345 | 4 | 243 | |
| 16 | 2.821844367 | -2.911453444 | -0.7522593594 | 3 | 467 | |
| 17 | -0.7483699574 | -1.637750921 | 4.006477576 | 5 | 52 | |
| 18 | 3.919926063 | 1.101892412 | -7.021235655 | 6 | 85 | |
| 19 | 0.5472089118 | -0.6489655001 | -3.112843659 | 1 | 365 | |
| 20 | 1.017649108 | 0.467474673 | -5.529214543 | 7 | 436 | |
| 21 | 4.362372266 | -0.3901083595 | -0.2553296577 | 1 | 271 | |
| 22 | 8.3701943 | -3.170232403 | 6.507204661 | 6 | 360 | |
| 23 | -0.6345359492 | -2.985823588 | -5.158898941 | 4 | 190 | |
| 24 | 2.285618547 | 0.2956785124 | -5.440463871 | 4 | 136 | |
| 25 | -1.829370757 | -2.741227013 | -1.523032522 | 7 | 159 | |
| 26 | 1.192071577 | -0.4039159227 | 0.5176009868 | 7 | 114 | |
| 27 | 2.825941013 | -0.7137279042 | 1.988156281 | 7 | 335 | |
| 28 | 0.8476052049 | -4.614315735 | -5.605282215 | 3 | 373 | |
| 29 | -3.761166959 | 1.868274892 | 6.860755689 | 7 | 43 | |
| 30 | 2.228408793 | -1.361769692 | 0.5100737156 | 9 | 48 | |
| 31 | 0.1893628307 | -1.337407098 | 8.399195582 | 7 | 166 | |
| 32 | 2.606413774 | 0.3329580751 | -2.082302643 | 1 | 15 | |
| 33 | 4.679760062 | 0.8929715919 | 1.874565239 | 5 | 38 | |
| 34 | -0.70099157 | -0.1385377189 | -0.4194491651 | 7 | 369 | |
| 35 | -3.46580238 | 0.1695962566 | -0.7606974248 | 1 | 216 | |
| 36 | -0.9028887483 | -2.031838516 | 7.036592817 | 4 | 249 | |
| 37 | 3.348113204 | 0.2999559961 | 6.199595348 | 9 | 70 | |
| 38 | 5.24339694 | 0.07376166821 | -2.581581077 | 4 | 102 | |
| 39 | -1.224334931 | -1.223643593 | 2.047072981 | 4 | 330 | |
| 40 | -0.9378161219 | -2.227102466 | -3.403787699 | 2 | 434 | |
| 41 | -3.1001964 | 0.01266793467 | -4.360014953 | 6 | 218 | |
| 42 | -1.416428618 | -0.7445283946 | -2.224576509 | 7 | 65 | |
| 43 | 2.379371171 | -2.036039495 | 6.390134334 | 2 | 355 | |
| 44 | -0.4261813065 | -3.289516939 | 6.217816651 | 5 | 14 | |
| 45 | 0.6397218519 | -2.535916581 | -12.35643942 | 1 | 193 | |
| 46 | 4.497297556 | -1.690192646 | -0.4552707233 | 7 | 479 | |
| 47 | 5.765875403 | -1.247495734 | -0.3353507473 | 7 | 246 | |
| 48 | -2.207118909 | -2.227118948 | -6.041511561 | 4 | 114 | |
| 49 | -2.072302039 | 2.916027463 | 1.492594418 | 4 | 36 | |
| 50 | -4.315692427 | -2.391108164 | 3.09182016 | 9 | 223 | |
| 51 | -2.886370694 | -1.504870818 | 5.027405626 | 9 | 406 | |
| 52 | 3.994847976 | 1.803160507 | 2.876087373 | 6 | 468 | |
| 53 | 2.416688432 | -1.212287413 | 8.485022323 | 8 | 74 | |
| 54 | 2.269403497 | 0.8228506059 | 1.98328284 | 7 | 166 | |
| 55 | 1.180251238 | -0.2444284997 | -1.554412824 | 9 | 230 | |
| 56 | -2.859874042 | -1.23514539 | 3.863829935 | 6 | 23 | |
| 57 | -1.385575037 | -2.155677967 | 3.191314364 | 7 | 155 | |
| 58 | 0.2717919017 | 2.89524005 | -1.919524703 | 8 | 110 | |
| 59 | -0.8929032543 | 1.141162062 | -1.849140817 | 9 | 315 | |
| 60 | 2.538018428 | 0.9864380563 | 2.455553923 | 6 | 403 | |
| 61 | 1.268958359 | 2.171760346 | -0.3483309099 | 5 | 330 | |
| 62 | 4.563875657 | 0.5951910361 | -3.407356824 | 1 | 411 | |
| 63 | 1.554130376 | 0.2387495851 | -3.520653265 | 3 | 370 | |
| 64 | -1.217342608 | -5.087350013 | 0.4459298342 | 7 | 269 | |
| 65 | -3.084204817 | -2.646182125 | 3.21598289 | 6 | 155 | |
| 66 | -0.2966085985 | 0.5262995789 | -1.87751911 | 6 | 485 | |
| 67 | 4.197791039 | 1.618979226 | 2.201506115 | 4 | 359 | |
| 68 | -1.029914674 | -2.885648568 | -3.035082384 | 6 | 137 | |
| 69 | -2.482393241 | -6.993660174 | -4.874650816 | 2 | 370 | |
| 70 | -0.6066044553 | -6.908968042 | 2.492838862 | 4 | 196 | |
| 71 | -0.1422670849 | -2.372655161 | 8.394659964 | 8 | 151 | |
| 72 | 1.988227349 | -4.895044871 | -1.904022719 | 1 | 21 | |
| 73 | 4.000090801 | -0.8684559946 | -4.295235973 | 6 | 212 | |
| 74 | -1.249810939 | -0.1964712067 | -0.455365154 | 7 | 102 | |
| 75 | 1.510891505 | -2.791589729 | 0.6658998548 | 1 | 141 | |
| 76 | 0.259759314 | 0.02643963578 | -2.204858223 | 1 | 24 | |
| 77 | 1.791441333 | -7.090766909 | 0.9637145503 | 3 | 170 | |
| 78 | -2.640177003 | -0.1335109077 | 4.048550909 | 2 | 300 | |
| 79 | 3.204001931 | -3.865529917 | -12.62370265 | 9 | 199 | |
| 80 | -2.080061565 | -1.00360148 | -5.9071611 | 9 | 291 | |
| 81 | -1.454456246 | -4.56220579 | 3.852605418 | 2 | 250 | |
| 82 | -3.451573906 | -4.638741026 | 6.392428552 | 5 | 56 | |
| 83 | -0.9164897038 | 0.8347000778 | -3.77010017 | 5 | 322 | |
| 84 | -0.9898018772 | -3.955191441 | 9.033400771 | 1 | 405 | |
| 85 | -3.215943133 | 0.6396778863 | -8.088847059 | 9 | 52 | |
| 86 | 1.887346723 | -0.3757330898 | 5.60723664 | 8 | 412 | |
| 87 | -1.212605241 | -3.634833529 | 9.852661553 | 9 | 218 | |
| 88 | 0.4575703952 | -3.776889826 | -0.6357365465 | 4 | 204 | |
| 89 | 1.000206856 | 1.180461692 | 7.183484281 | 10 | 434 | |
| 90 | 3.991980672 | -3.119541182 | -2.291057293 | 5 | 494 | |
| 91 | 3.148096685 | 0.660074024 | 1.646828236 | 7 | 135 | |
| 92 | 3.757003436 | 1.691072709 | 6.652611785 | 8 | 290 | |
| 93 | -1.175184091 | 0.253947733 | 4.06789772 | 7 | 330 | |
| 94 | -2.01266346 | -2.002267507 | 3.634406206 | 4 | 130 | |
| 95 | 1.51803949 | -3.716944736 | 0.1083323603 | 4 | 252 | |
| 96 | 0.8290121091 | -0.2510098422 | -12.32325899 | 10 | 471 | |
| 97 | 3.937185551 | 1.459966877 | -6.114019644 | 1 | 174 | |
| 98 | -3.801581684 | 0.2704052951 | -9.950370169 | 9 | 428 | |
| 99 | 4.400536621 | 0.8708577188 | 7.693085685 | 3 | 283 | |
| 100 | 0.7096924036 | -0.5269381067 | -3.745397591 | 9 | 355 | |
| 101 | 0.2508476169 | -0.7492739626 | 3.87423747 | 5 | 224 | |
| 102 | -3.534026131 | -0.004468464466 | 5.936880748 | 4 | 67 | |
| 103 | -2.998507112 | 1.488914432 | 7.114224987 | 8 | 490 | |
| 104 | 3.013481459 | -2.430649097 | 4.905641151 | 5 | 19 | |
| 105 | 1.29990998 | 1.372236091 | 5.140207336 | 5 | 295 | |
| 106 | -2.554991052 | 0.3667789531 | 4.058210317 | 6 | 167 | |
| 107 | 1.604996355 | 1.897431544 | -2.404243031 | 5 | 86 | |
| 108 | -1.709317063 | -1.566626738 | 0.7385438477 | 4 | 379 | |
| 109 | 3.642224823 | 3.047397772 | -1.991450451 | 6 | 325 | |
| 110 | 1.012055276 | 3.340189534 | -8.405616583 | 9 | 185 | |
| 111 | -0.6044469527 | 2.578390749 | 2.820234273 | 7 | 174 | |
| 112 | -5.137864626 | -6.041315028 | -2.535793246 | 5 | 437 | |
| 113 | -2.830461138 | -3.571706532 | 5.896343651 | 3 | 472 | |
| 114 | -4.18962624 | 0.4124038906 | 3.016398105 | 1 | 342 | |
| 115 | 3.703531729 | -1.59199886 | 0.6119123439 | 5 | 243 | |
| 116 | 3.464679941 | -0.1827347235 | -2.706711571 | 8 | 270 | |
| 117 | 1.774740376 | -2.63823051 | -6.881772605 | 1 | 473 | |
| 118 | 3.817522564 | -2.294583722 | -7.454056997 | 3 | 341 | |
| 119 | 1.512707243 | -3.294511769 | 1.108873827 | 2 | 274 | |
| 120 | -0.1773438082 | -0.1749495435 | -3.68120562 | 10 | 217 | |
| 121 | 4.465674328 | 1.408029384 | 2.027454682 | 7 | 444 | |
| 122 | -4.73226317 | -0.4261750287 | 0.04445084115 | 3 | 259 | |
| 123 | 0.8995207935 | -0.442625909 | -4.00290775 | 10 | 414 | |
| 124 | -6.602214586 | 0.5788109601 | -2.058200147 | 5 | 389 | |
| 125 | 2.348234861 | -0.1642339903 | 11.32243203 | 3 | 178 | |
| 126 | 1.54582728 | 3.38436122 | -4.171230038 | 3 | 46 | |
| 127 | -1.905651022 | -1.836132133 | -0.7930360171 | 4 | 335 | |
| 128 | 5.598196528 | 2.047962088 | -1.73243339 | 5 | 25 | |
| 129 | 1.265043109 | 1.511219884 | 0.8665718372 | 2 | 486 | |
| 130 | -1.723838267 | -1.863922558 | 5.741547344 | 1 | 260 | |
| 131 | 7.610274096 | -1.562715475 | -3.391796789 | 7 | 334 | |
| 132 | 0.7449588712 | -1.604241525 | 2.640844276 | 9 | 449 | |
| 133 | 3.009271787 | -1.908787681 | -0.3977628628 | 9 | 326 | |
| 134 | 0.9787898265 | -1.891361104 | -1.503800683 | 7 | 254 | |
| 135 | -0.3423956537 | -2.023428678 | -3.516815231 | 2 | 122 | |
| 136 | 0.4672862382 | -0.5797585737 | 4.022959292 | 7 | 213 | |
| 137 | 3.773642784 | -4.956875872 | 3.45526531 | 6 | 72 | |
| 138 | 0.5116408932 | -6.410042268 | 9.577598538 | 8 | 187 | |
| 139 | -0.9206394109 | 1.804133584 | -10.39355528 | 4 | 176 | |
| 140 | 0.6690137223 | -3.044678386 | -5.777699596 | 6 | 409 | |
| 141 | -3.402169216 | -2.09622438 | 3.949329111 | 3 | 277 | |
| 142 | 1.093508501 | 0.5896416473 | 1.289395682 | 7 | 28 | |
| 143 | 0.03018293409 | -0.4813050486 | -5.165644548 | 4 | 492 | |
| 144 | 2.855021128 | -2.854722329 | 10.13158759 | 6 | 16 | |
| 145 | 0.55912314 | -3.231235567 | 0.1702737766 | 1 | 75 | |
| 146 | 2.766385371 | 0.7562061905 | -7.903760785 | 7 | 134 | |
| 147 | -4.2539117 | -2.732028921 | -3.133456924 | 9 | 135 | |
| 148 | -0.02521865821 | 3.136838471 | 3.119469423 | 4 | 85 | |
| 149 | -1.314909327 | -2.01034686 | -5.37864583 | 1 | 405 | |
| 150 | 2.697082352 | 0.4900173748 | -1.642320691 | 6 | 29 | |
| 151 | 3.504188385 | -2.736478881 | -8.128141955 | 4 | 122 | |
| 152 | 2.173806393 | -2.020463585 | -2.610113285 | 9 | 360 | |
| 153 | 0.6231183111 | -0.8465809738 | 0.9140431289 | 1 | 192 | |
| 154 | -0.8319773373 | -1.827977706 | -2.844159501 | 5 | 227 | |
| 155 | -0.307455075 | -2.475200733 | -4.542229996 | 10 | 456 | |
| 156 | 3.319616071 | 1.079863401 | 2.893022188 | 4 | 103 | |
| 157 | 1.442338582 | -0.46234663 | 6.506135029 | 6 | 385 | |
| 158 | -4.269178223 | -1.4174265 | -2.349592638 | 7 | 117 | |
| 159 | 11.08371198 | 2.720121038 | -3.773052279 | 5 | 58 | |
| 160 | 2.88651955 | -1.927467624 | -4.362905513 | 10 | 7 | |
| 161 | -0.8630325965 | -2.855807777 | 1.954610226 | 7 | 140 | |
| 162 | 0.6140463988 | 4.912806043 | 12.14822075 | 2 | 250 | |
| 163 | -1.097776223 | 0.2253234193 | 1.214721325 | 2 | 339 | |
| 164 | 0.9169856765 | 3.468961752 | 7.511568162 | 7 | 39 | |
| 165 | 1.734757298 | -4.134320531 | 5.340284841 | 8 | 244 | |
| 166 | 0.9575602778 | 0.6440991922 | 0.6879637417 | 2 | 109 | |
| 167 | 2.082999527 | 1.31744689 | -5.323603858 | 6 | 224 | |
| 168 | 3.195904559 | 0.3078603374 | -0.4490530943 | 6 | 57 | |
| 169 | 7.788457731 | -2.893718465 | 1.892125032 | 5 | 337 | |
| 170 | 3.31851417 | -2.344642912 | 5.349601675 | 3 | 74 | |
| 171 | -0.2204259924 | -4.246707265 | -2.602960653 | 6 | 450 | |
| 172 | -1.50120167 | 2.182364771 | -8.134973938 | 7 | 206 | |
| 173 | 3.521490144 | -4.335186154 | -4.311449169 | 6 | 120 | |
| 174 | 0.1920023785 | 0.4446393539 | -6.83571217 | 8 | 421 | |
| 175 | 2.364651102 | 1.041621559 | -1.477080683 | 9 | 351 | |
| 176 | 4.064711382 | 0.112822511 | -1.750193036 | 1 | 302 | |
| 177 | 5.547667872 | 1.625080625 | 5.703752789 | 9 | 109 | |
| 178 | -2.156390532 | -1.231003224 | 0.971017726 | 2 | 469 | |
| 179 | 0.7468041114 | 2.998206892 | -4.246549821 | 3 | 364 | |
| 180 | -0.5937925872 | -1.725175117 | 2.853594058 | 5 | 182 | |
| 181 | 4.634091423 | -1.900343956 | -1.780078552 | 7 | 121 | |
| 182 | 4.322784234 | -0.02800943323 | 6.109667386 | 9 | 284 | |
| 183 | -0.1633564937 | -3.376072412 | 6.843331712 | 9 | 177 | |
| 184 | 3.71381409 | -0.7255510755 | -7.401172117 | 8 | 58 | |
| 185 | -0.4429915355 | -4.098828825 | -7.622207517 | 10 | 140 | |
| 186 | 4.626637212 | -2.818210453 | 4.412723695 | 10 | 473 | |
| 187 | 4.726871471 | 0.7745512648 | 0.5160346967 | 1 | 39 | |
| 188 | -2.048713617 | 3.680638344 | -4.480787577 | 2 | 10 | |
| 189 | 3.842468777 | -2.574667154 | -2.872819641 | 3 | 468 | |
| 190 | 0.5202150677 | -1.626831576 | -1.589327429 | 10 | 24 | |
| 191 | 5.855603553 | -0.7628637139 | 2.27208959 | 1 | 351 | |
| 192 | -1.445359447 | -2.724954853 | -5.498680548 | 7 | 20 | |
| 193 | 5.981980075 | -1.143839398 | -5.883979682 | 10 | 188 | |
| 194 | -0.1827975719 | -0.3986336841 | -1.978201805 | 7 | 22 | |
| 195 | 0.05038021122 | 0.8063352507 | 7.57544709 | 3 | 477 | |
| 196 | -1.995681238 | 3.074781574 | 5.98454445 | 3 | 200 | |
| 197 | 2.084807282 | -0.8099439468 | 10.55498706 | 5 | 88 | |
| 198 | -3.6163859 | -1.837353511 | -7.479888428 | 6 | 138 | |
| 199 | 1.525489218 | -2.768055416 | 4.605818247 | 2 | 173 | |
| 200 | 1.419045296 | -0.9217519312 | 5.081529479 | 3 | 129 | |
| 201 | -1.179410644 | -1.803355335 | -6.510394446 | 7 | 299 | |
| 202 | 8.174817451 | 1.671196348 | 3.670962478 | 10 | 77 | |
| 203 | 3.969456614 | -0.3769042039 | 3.153340024 | 2 | 14 | |
| 204 | -3.510521251 | -0.4885388305 | -0.1366992208 | 8 | 300 | |
| 205 | 1.826937405 | -4.720226667 | 2.499582127 | 10 | 23 | |
| 206 | 6.637764989 | -1.502159384 | 9.719033941 | 4 | 192 | |
| 207 | 2.659828708 | -2.735513466 | 2.525907392 | 1 | 432 | |
| 208 | 0.5974903032 | -2.354154695 | -3.491373781 | 9 | 226 | |
| 209 | -0.1991238014 | -4.099492796 | 2.955639501 | 5 | 259 | |
| 210 | -1.783764881 | 0.03963428585 | -3.416409343 | 2 | 428 | |
| 211 | 1.287861768 | -2.243651063 | -5.27727244 | 3 | 106 | |
| 212 | 1.403375596 | -0.2015628868 | 4.298266741 | 3 | 153 | |
| 213 | 6.221427915 | -0.1592802635 | 1.335541533 | 10 | 126 | |
| 214 | 1.770599719 | 0.8969798302 | -1.161481263 | 9 | 304 | |
| 215 | 2.890182445 | -0.5036565754 | -5.341659507 | 9 | 500 | |
| 216 | 5.527484607 | -0.5349384451 | 8.021744779 | 6 | 155 | |
| 217 | 2.070373964 | 3.151711974 | 6.786808143 | 6 | 458 | |
| 218 | 2.728852887 | 3.388031134 | -1.044565559 | 9 | 391 | |
| 219 | 1.323276056 | -0.5078843246 | -2.81834301 | 4 | 480 | |
| 220 | 0.5127549501 | 0.5688528009 | 1.024423159 | 7 | 89 | |
| 221 | 0.5475059809 | 0.0006064243935 | -6.007079703 | 3 | 412 | |
| 222 | -2.072244172 | 1.380716259 | -11.6743955 | 7 | 362 | |
| 223 | -5.268566173 | 0.9045962182 | 1.188833589 | 6 | 43 | |
| 224 | 2.205885669 | -1.313354087 | 0.0749670464 | 8 | 247 | |
| 225 | -0.1952395385 | 0.5891383005 | -0.6954121981 | 9 | 320 | |
| 226 | 1.990337079 | 1.345415097 | -11.44780535 | 6 | 403 | |
| 227 | 0.3818823362 | 0.3822895971 | -2.296285885 | 9 | 336 | |
| 228 | 2.146984162 | -2.617218909 | -1.879975304 | 8 | 491 | |
| 229 | 3.969698912 | 0.3608257731 | 2.057759671 | 7 | 144 | |
| 230 | 2.330484191 | -0.9218226967 | 8.908476341 | 2 | 203 | |
| 231 | -2.409326765 | 2.467323569 | 6.514733622 | 3 | 438 | |
| 232 | -0.374073876 | -0.294374026 | 2.034232889 | 4 | 102 | |
| 233 | -0.9638425012 | 1.177179979 | 1.442536631 | 8 | 125 | |
| 234 | -3.874384794 | 1.309375722 | -4.105864573 | 9 | 74 | |
| 235 | 2.508982046 | 3.816586775 | -6.455756243 | 8 | 168 | |
| 236 | -1.384928178 | -0.02861923486 | 2.165773286 | 3 | 158 | |
| 237 | 0.4020590467 | -1.744230452 | 2.900547132 | 7 | 237 | |
| 238 | -3.715680216 | -0.9877393895 | -0.8595520771 | 6 | 12 | |
| 239 | -0.2161101704 | -2.056877246 | 3.254626375 | 6 | 68 | |
| 240 | 1.667725533 | -1.84107345 | -1.732818476 | 7 | 57 | |
| 241 | 0.8498293351 | 0.3100162782 | -0.6953755836 | 7 | 278 | |
| 242 | -0.0406952062 | 0.3021411409 | -5.035428466 | 9 | 282 | |
| 243 | 7.972474491 | -2.214267653 | 6.679337266 | 3 | 34 | |
| 244 | -1.640587005 | -1.924811465 | -1.98742659 | 1 | 213 | |
| 245 | 2.030601793 | -0.5475607999 | 3.707307433 | 3 | 234 | |
| 246 | 1.427936203 | -0.8044619249 | -1.610625965 | 3 | 411 | |
| 247 | 2.32765769 | 1.832532742 | 2.367470721 | 2 | 441 | |
| 248 | -1.025494308 | 0.03107451884 | -4.572442628 | 7 | 245 | |
| 249 | -0.2847716563 | -1.422046008 | -0.3680170925 | 2 | 44 | |
| 250 | 6.91002173 | -1.453395911 | -8.136692442 | 5 | 43 | |
| 251 | 2.525896821 | -3.448849921 | 0.003623200085 | 1 | 44 | |
| 252 | 2.350368048 | -4.017176863 | 2.706762456 | 1 | 17 | |
| 253 | -3.731041131 | -2.109840253 | -3.536905592 | 4 | 230 | |
| 254 | 0.01777154189 | 0.5309864861 | 5.302710102 | 3 | 290 | |
| 255 | 4.660792805 | -1.974615035 | 5.50948696 | 5 | 62 |
| /* | |
| * @author zz85 / https://github.com/zz85 | |
| * @author mrdoob / http://mrdoob.com | |
| * Running this will allow you to drag three.js objects around the screen. | |
| * Modified for D3.JS / THREE.JS stack by | |
| * @author vkuchinov / https://github.com/vkuchinov | |
| * | |
| */ | |
| THREE.DragControls = function ( _object, _camera) { | |
| var _domElement = document; | |
| var rect = { | |
| bottom: window.innerHeight, | |
| height: window.innerHeight, | |
| left: 0, | |
| right: window.innerWidth, | |
| top: 0, | |
| width: window.innerWidth, | |
| x: 0, | |
| y: 0 | |
| }; | |
| var _plane = new THREE.Plane(); | |
| var _raycaster = new THREE.Raycaster(); | |
| var _mouse = new THREE.Vector2(); | |
| var _offset = new THREE.Vector3(); | |
| var _intersection = new THREE.Vector3(); | |
| var _mouseDown = false; | |
| var scope = this; | |
| function activate() { | |
| _domElement.addEventListener( "mousedown", onDocumentMouseDown, false ); | |
| _domElement.addEventListener( "mousemove", onDocumentMouseMove, false ); | |
| _domElement.addEventListener( "mouseup", onDocumentMouseUp, false ); | |
| _domElement.addEventListener( "mouseleave", onDocumentMouseUp, false ); | |
| } | |
| function deactivate() { | |
| _domElement.removeEventListener( "mousedown", onDocumentMouseDown, false ); | |
| _domElement.removeEventListener( "mousemove", onDocumentMouseMove, false ); | |
| _domElement.removeEventListener( "mouseup", onDocumentMouseUp, false ); | |
| _domElement.removeEventListener( "mouseleave", onDocumentMouseUp, false ); | |
| } | |
| function dispose() { deactivate(); } | |
| function onDocumentMouseDown( event_ ) { | |
| _mouseDown = true; | |
| event_.preventDefault(); | |
| _raycaster.setFromCamera( _mouse, _camera ); | |
| if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) { | |
| _offset.copy( _intersection ).sub( _object.position ); | |
| } | |
| document.getElementById("scatter3D").style.cursor = "move"; | |
| scope.dispatchEvent( { type: "dragstart", object: _object } ); | |
| } | |
| function onDocumentMouseMove( event_ ) { | |
| _plane.normal = new THREE.Vector3(_camera.position.x, _camera.position.y, _camera.position.z); | |
| _plane.normal.normalize(); | |
| event_.preventDefault(); | |
| if(_mouseDown){ | |
| _mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1; | |
| _mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1; | |
| _raycaster.setFromCamera( _mouse, _camera ); | |
| if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) { | |
| _object.position.copy( _intersection.sub( _offset ) ); | |
| } | |
| scope.dispatchEvent( { type: "drag", object: _object } ); | |
| return; | |
| } | |
| } | |
| function onDocumentMouseUp( event_ ) { | |
| _mouseDown = false; | |
| event_.preventDefault(); | |
| scope.dispatchEvent( { type: "dragend", object: _object } ); | |
| document.getElementById("scatter3D").style.cursor = "auto"; | |
| } | |
| // API | |
| this.enabled = false; | |
| this.activate = activate; | |
| this.deactivate = deactivate; | |
| this.dispose = dispose; | |
| // Backward compatibility | |
| this.setObjects = function () { | |
| console.error( "THREE.DragControls: setObjects() has been removed." ); | |
| }; | |
| this.on = function ( type, listener ) { | |
| console.warn( "THREE.DragControls: on() has been deprecated. Use addEventListener() instead." ); | |
| scope.addEventListener( type, listener ); | |
| }; | |
| this.off = function ( type, listener ) { | |
| console.warn( "THREE.DragControls: off() has been deprecated. Use removeEventListener() instead." ); | |
| scope.removeEventListener( type, listener ); | |
| }; | |
| this.notify = function ( type ) { | |
| console.error( "THREE.DragControls: notify() has been deprecated. Use dispatchEvent() instead." ); | |
| scope.dispatchEvent( { type: type } ); | |
| }; | |
| }; | |
| THREE.DragControls.prototype = Object.create( THREE.EventDispatcher.prototype ); | |
| THREE.DragControls.prototype.constructor = THREE.DragControls; |
| <!doctype html> | |
| <html> | |
| <head> | |
| <title>D3.JS & THREE.JS Hybrid Scatter Plot 3D</title> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | |
| <script src="https://d3js.org/d3.v4.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/98/three.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js"></script> | |
| <script src="OrbitControls.js"></script> | |
| <script src="DragControls4D3.js"></script> | |
| <link href="styles.css" rel="stylesheet"/> | |
| </head> | |
| <body> | |
| <button style="right:0" id="switch" class="ui" onclick="switchUI()">Rotate</button> | |
| <button style="right: 64px" id="showGrid" class="ui" onclick="turnGridOnOff()">Show Grid</button> | |
| <button style="right: 150px" id="scaleGrid" class="ui" onclick="turnOnOffScale()">Static Grid</button> | |
| <svg id="scatter3D" width="0" height="0"></svg> | |
| <div id="tooltip"> | |
| <div id="x_value" class="xl">x: 0</div> | |
| <div id="y_value" class="yl">y: 0</div> | |
| <div id="z_value" class="zl">z: 0</div> | |
| </div> | |
| <script src="main.js"></script> | |
| </body> | |
| </html> |
| var stats, scene, renderer, controls, dragControls; | |
| var camera, cameraControl; | |
| var pointCLoud, points = [], sorted = [], axes = [], labels = [], grids = []; | |
| var offset = new THREE.Vector3(); | |
| var drag = false; | |
| var limits = { x: { min: -10, max: 10 }, y: { min: -10, max: 10 }, z: { min: -10, max: 10 } } | |
| var svg; | |
| var colors = d3.scaleOrdinal(d3.schemeCategory10); | |
| var radiusRatio = 2.5E-2; | |
| var w = window.innerWidth, h = window.innerHeight; | |
| var xAxis, yAxis, zAxis; | |
| var scalable = false; | |
| var gridVisible = false; | |
| var xScale = d3.scaleLinear().range([0, window.innerWidth * 0.25]).domain([limits.x.min, limits.x.max]); | |
| var yScale = d3.scaleLinear().range([0, window.innerWidth * 0.25]).domain([limits.y.min, limits.y.max]); | |
| var zScale = d3.scaleLinear().range([0, window.innerWidth * 0.25]).domain([limits.z.min, limits.z.max]); | |
| d3.csv("data.csv", function(error_, data_) { | |
| if (error_) throw error_; | |
| data_.forEach(function(d_) { | |
| points.push({x: Number(d_.x), y: Number(d_.y), z: Number(d_.z), c: d_.colorid, r: d_.radius }) | |
| }); | |
| svg = d3.select("svg").attr("width", w).attr("height", h); | |
| xAxis = svg.append("g").attr("transform", "translate( " + (window.innerWidth - 32) + "," + ((window.innerHeight / 2) - window.innerHeight * 0.25) + ")").call(d3.axisLeft(xScale).ticks(6)); | |
| var xLabel = svg.append("text").attr("transform", "translate( " + (window.innerWidth - 40) + "," + ((window.innerHeight / 2) - window.innerHeight * 0.25 - 20) + ")").attr("font-family", "sans-serif").text("X"); | |
| yAxis = svg.append("g").attr("transform", "translate(" + + ((window.innerWidth / 2) - window.innerWidth * 0.125) + ", 32)").call(d3.axisTop(yScale).ticks(6)); | |
| var yLabel = svg.append("text").attr("transform", "translate(" + + ((window.innerWidth / 2) - window.innerWidth * 0.125 - 32) + ", 32)").attr("font-family", "sans-serif").text("Y"); | |
| zAxis = svg.append("g").attr("transform", "translate(32," + ((window.innerHeight / 2) - window.innerHeight * 0.25) + ")").call(d3.axisLeft(zScale).ticks(6)); | |
| var zLabel = svg.append("text").attr("transform", "translate(26," + ((window.innerHeight / 2) - window.innerHeight * 0.25 - 20) + ")").attr("font-family", "sans-serif").text("Z"); | |
| init(); | |
| }); | |
| function init(){ | |
| renderer = new THREE.WebGLRenderer(); | |
| renderer.setSize( window.innerWidth, window.innerHeight ); | |
| stats = new Stats(); | |
| stats.domElement.style.position = "absolute"; | |
| stats.domElement.style.bottom = "0px"; | |
| document.body.appendChild( stats.domElement ); | |
| scene = new THREE.Scene(); | |
| camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 10000 ); | |
| camera.position.set(256, 512, 512); | |
| camera.lookAt(0, 0, 0) | |
| scene.add(camera); | |
| var cloud = new THREE.Geometry(); | |
| points.forEach(function(d_) { | |
| var p = new THREE.Vector3(d_.x * 16 , d_.y * 16 , d_.z * 16); | |
| cloud.vertices.push( p ); | |
| }); | |
| var cloudmaterial = new THREE.PointsMaterial( { color: 0xFFFFFF } ); | |
| pointCloud = new THREE.Points( cloud , cloudmaterial ); | |
| scene.add( pointCloud ); | |
| controls = new THREE.OrbitControls( camera, document ); | |
| controls.enableDamping = true; | |
| controls.dampingFactor = 0.25; | |
| controls.screenSpacePanning = false; | |
| controls.minDistance = 100; | |
| controls.maxDistance = 500; | |
| controls.maxPolarAngle = Math.PI / 2; | |
| dragControls = new THREE.DragControls( pointCloud, camera ); | |
| animate(); | |
| } | |
| function animate() { | |
| var sv = new THREE.Vector3(0, 0, 0); | |
| var scale = 768.0 / sv.subVectors(new THREE.Vector3(0, 0, 0), camera.position).length(); | |
| if(!scalable){ | |
| axes = [ | |
| [new THREE.Vector3(-196.0 / scale, 1E-5, 1E-5), new THREE.Vector3(196.0 / scale, 1E-5, 1E-5)], | |
| [new THREE.Vector3(1E-5, -196.0 / scale, 1E-5), new THREE.Vector3(1E-5, 196.0 / scale, 1E-5)], | |
| [new THREE.Vector3(1E-5, 1E-5, -196.0 / scale), new THREE.Vector3(1E-5, 1E-5, 196.0 / scale)] | |
| ]; | |
| labels = [ | |
| new THREE.Vector3(212.0 / scale, 1E-5, 1E-5), | |
| new THREE.Vector3(1E-5, 212.0 / scale, 1E-5), | |
| new THREE.Vector3(1E-5, 1E-5, 222.0 / scale) | |
| ]; | |
| grids = []; | |
| for(var xz = 0; xz <= 147.0; xz += 12.25){ | |
| grids.push([new THREE.Vector3(xz / scale, 1E-5, 1E-5), new THREE.Vector3(xz / scale, 1E-5, 147 / scale)]); | |
| grids.push([new THREE.Vector3(1E-5, 1E-5, xz / scale), new THREE.Vector3(147.0 / scale, 1E-5, xz / scale)]); | |
| } | |
| } | |
| else { | |
| axes = [ | |
| [new THREE.Vector3(-196.0, 1E-5, 1E-5), new THREE.Vector3(196.0, 1E-5, 1E-5)], | |
| [new THREE.Vector3(1E-5, -196.0, 1E-5), new THREE.Vector3(1E-5, 196.0, 1E-5)], | |
| [new THREE.Vector3(1E-5, 1E-5, -196.0), new THREE.Vector3(1E-5, 1E-5, 196.0)] | |
| ]; | |
| labels = [ | |
| new THREE.Vector3(212.0, 1E-5, 1E-5), | |
| new THREE.Vector3(1E-5, 212.0, 1E-5), | |
| new THREE.Vector3(1E-5, 1E-5, 222.0) | |
| ]; | |
| grids = []; | |
| for(var xz = 0; xz <= 147.0; xz += 12.25){ | |
| grids.push([new THREE.Vector3(xz, 1E-5, 1E-5), new THREE.Vector3(xz, 1E-5, 147.0 / scale)]); | |
| grids.push([new THREE.Vector3(1E-5, 1E-5, xz), new THREE.Vector3(147, 1E-5, xz)]); | |
| } | |
| } | |
| controls.update(); | |
| renderSVG(pointCloud.position); | |
| requestAnimationFrame( animate ); | |
| stats.update(); | |
| renderer.render( scene, camera ); | |
| } | |
| function toScreenXY (x_, y_, z_, camera_) { | |
| var p = new THREE.Vector3(x_, y_, z_); | |
| var vector = p.project(camera_); | |
| vector.x = (vector.x + 1) / 2 * window.innerWidth; | |
| vector.y = -(vector.y - 1) / 2 * window.innerHeight; | |
| return {x: vector.x, y: vector.y }; | |
| } | |
| function renderSVG(p_){ | |
| limits = { | |
| x: { min: Number.POSITIVE_INFINITY, max: Number.NEGATIVE_INFINITY }, | |
| y: { min: Number.POSITIVE_INFINITY, max: Number.NEGATIVE_INFINITY }, | |
| z: { min: Number.POSITIVE_INFINITY, max: Number.NEGATIVE_INFINITY } | |
| }; | |
| var projectedPoints = svg.selectAll("circle").data(pointCloud.geometry.vertices); | |
| projectedPoints.enter() | |
| .append("circle") | |
| .attr("class", "_3d") | |
| .attr("opacity", 1.0) | |
| .merge(projectedPoints) | |
| .attr("cx", function(d_){ return valueValidation(toScreenXY(d_.x + p_.x, d_.y + p_.y, d_.z + p_.z, camera).x); }) | |
| .attr("cy", function(d_){ return valueValidation(toScreenXY(d_.x + p_.x, d_.y + p_.y, d_.z + p_.z, camera).y); }) | |
| .attr("r", function(d_, i_) { return points[i_].r * radiusRatio; }) | |
| .attr("fill", function(d_, i_) { return colors(points[i_].c); }) | |
| .attr("opacity", function(d_){ | |
| if(isPointOnScreen(d_, p_)){ | |
| limits.x.min = Math.min((d_.x + p_.x) / 16.0, limits.x.min); | |
| limits.x.max = Math.max((d_.x + p_.x) / 16.0, limits.x.max); | |
| limits.y.min = Math.min((d_.y + p_.y) / 16.0, limits.y.min); | |
| limits.y.max = Math.max((d_.y + p_.y) / 16.0, limits.y.max); | |
| limits.z.min = Math.min((d_.z + p_.z) / 16.0, limits.z.min); | |
| limits.z.max = Math.max((d_.z + p_.z) / 16.0, limits.z.max); | |
| return 0.6; | |
| } | |
| return 0.6; | |
| }) | |
| .on("mouseover", function(d_){ | |
| if(!drag){ | |
| d3.select(this).attr("stroke", "#DEDEDE") | |
| .attr("stroke-width", 6); | |
| var t = d3.select("#tooltip") | |
| .style("left", d3.select(this).attr("cx") + "px") | |
| .style("top", d3.select(this).attr("cy") + "px"); | |
| document.getElementById("x_value").innerHTML = "x: " + (d_.x / 16.0).toFixed(2); | |
| document.getElementById("y_value").innerHTML = "y: " + (d_.y / 16.0).toFixed(2); | |
| document.getElementById("z_value").innerHTML = "z: " + (d_.z / 16.0).toFixed(2); | |
| } | |
| }) | |
| .on("mouseout", function(d_){ | |
| if(!drag){ | |
| d3.select(this).attr("stroke", "none") | |
| var t = d3.select("#tooltip") | |
| .style("left","-999px") | |
| .style("top", "-999px"); | |
| } | |
| }) | |
| projectedPoints.exit().remove(); | |
| if(gridVisible){ | |
| var projectedGrids = svg.selectAll("line.Grids").data(grids); | |
| projectedGrids.enter() | |
| .append("line") | |
| .attr("class", "3d_ Grids") | |
| .merge(projectedGrids) | |
| .attr("x1", function(d_) { return valueValidation(toScreenXY(d_[0].x, d_[0].y, d_[0].z, camera).x); }) | |
| .attr("y1", function(d_) { return valueValidation(toScreenXY(d_[0].x, d_[0].y, d_[0].z, camera).y); }) | |
| .attr("x2", function(d_) { return valueValidation(toScreenXY(d_[1].x, d_[1].y, d_[1].z, camera).x); }) | |
| .attr("y2", function(d_,){ return valueValidation(toScreenXY(d_[1].x, d_[1].y, d_[1].z, camera).y); }) | |
| .attr("stroke", "#DEDEDE") | |
| .attr("stroke-width", 0.25); | |
| projectedGrids.exit().remove(); | |
| } | |
| var projectedAxes = svg.selectAll("line.Axes3").data(axes); | |
| projectedAxes.enter() | |
| .append("line") | |
| .attr("class", "3d_ Axes3") | |
| .merge(projectedAxes) | |
| .attr("x1", function(d_) { return valueValidation(toScreenXY(d_[0].x, d_[0].y, d_[0].z, camera).x); }) | |
| .attr("y1", function(d_) { return valueValidation(toScreenXY(d_[0].x, d_[0].y, d_[0].z, camera).y); }) | |
| .attr("x2", function(d_) { return valueValidation(toScreenXY(d_[1].x, d_[1].y, d_[1].z, camera).x); }) | |
| .attr("y2", function(d_,){ return valueValidation(toScreenXY(d_[1].x, d_[1].y, d_[1].z, camera).y); }) | |
| .attr("stroke", "#000000"); | |
| projectedAxes.exit().remove(); | |
| var projectedLabels = svg.selectAll("text.Labels").data(labels); | |
| projectedLabels.enter() | |
| .append("text") | |
| .attr("class", "Labels") | |
| .merge(projectedLabels) | |
| .attr("dx", function (d_) { | |
| var dx = valueValidation(toScreenXY(d_.x, d_.y, d_.z, camera).x); | |
| return dx; | |
| }) | |
| .attr("dy", function (d_) { | |
| var dy = valueValidation(toScreenXY(d_.x, d_.y, d_.z, camera).y); | |
| return dy; | |
| }) | |
| .attr("font-family", "sans-serif") | |
| .text(function(d_, i_) { var l = ["x", "y", "z"]; return l[i_]; }); | |
| projectedLabels.exit().remove(); | |
| xScale.domain([limits.x.min, limits.x.max]); | |
| yScale.domain([limits.y.min, limits.y.max]); | |
| zScale.domain([limits.z.min, limits.z.max]); | |
| xAxis.call(d3.axisLeft(xScale).ticks(6)); | |
| yAxis.call(d3.axisTop(yScale).ticks(6)); | |
| zAxis.call(d3.axisLeft(zScale).ticks(6)); | |
| } | |
| function isPointOnScreen(d_, p_){ | |
| var tmp = new THREE.Vector3(d_.x + p_.x, d_.y + p_.y, d_.z + p_.z); | |
| var xy = toScreenXY(tmp.x, tmp.y, tmp.z, camera); | |
| if(!xy.x.between([0, window.innerWidth])) { return false; } | |
| if(!xy.y.between([0, window.innerHeight])) { return false; } | |
| return true; | |
| } | |
| function valueValidation(v_){ return v_ || 0; }; | |
| function switchUI(){ | |
| var b = document.getElementById("switch"); | |
| if(b.innerHTML == "Rotate") { | |
| b.innerHTML = "Drag"; | |
| controls.enabled = false; | |
| drag = true; | |
| dragControls.enabled = true; | |
| dragControls.activate(); | |
| } | |
| else { | |
| b.innerHTML = "Rotate"; | |
| controls.enabled = true; | |
| drag = false; | |
| dragControls.enabled = false; | |
| dragControls.deactivate(); | |
| } | |
| } | |
| function turnOnOffScale(){ | |
| var b = document.getElementById("scaleGrid"); | |
| if(b.innerHTML == "Static Grid") { | |
| scalable = true; | |
| b.innerHTML = "Scalable Grid"; | |
| } | |
| else { | |
| scalable = false; | |
| b.innerHTML = "Static Grid"; | |
| } | |
| } | |
| function turnGridOnOff(){ | |
| var b = document.getElementById("showGrid"); | |
| if(b.innerHTML == "Show Grid") { | |
| gridVisible = true; | |
| b.innerHTML = "Hide Grid"; | |
| } | |
| else { | |
| gridVisible = false; | |
| b.innerHTML = "Show Grid"; | |
| d3.selectAll(".Grids").remove(); | |
| } | |
| } | |
| Number.prototype.between = function(domain_) { | |
| var min = Math.min.apply(Math, domain_); | |
| var max = Math.max.apply(Math, domain_); | |
| return this >= min && this <= max; | |
| }; |
| /** | |
| * @author qiao / https://github.com/qiao | |
| * @author mrdoob / http://mrdoob.com | |
| * @author alteredq / http://alteredqualia.com/ | |
| * @author WestLangley / http://github.com/WestLangley | |
| */ | |
| THREE.OrbitControls = function ( object, domElement ) { | |
| this.object = object; | |
| this.domElement = ( domElement !== undefined ) ? domElement : document; | |
| // API | |
| this.enabled = true; | |
| this.center = new THREE.Vector3(); | |
| this.userZoom = true; | |
| this.userZoomSpeed = 1.0; | |
| this.userRotate = true; | |
| this.userRotateSpeed = 1.0; | |
| this.userPan = true; | |
| this.userPanSpeed = 2.0; | |
| this.autoRotate = false; | |
| this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 | |
| this.minPolarAngle = 0; // radians | |
| this.maxPolarAngle = Math.PI; // radians | |
| this.minDistance = 0; | |
| this.maxDistance = Infinity; | |
| // 65 /*A*/, 83 /*S*/, 68 /*D*/ | |
| this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40, ROTATE: 65, ZOOM: 83, PAN: 68 }; | |
| // internals | |
| var scope = this; | |
| var EPS = 0.000001; | |
| var PIXELS_PER_ROUND = 1800; | |
| var rotateStart = new THREE.Vector2(); | |
| var rotateEnd = new THREE.Vector2(); | |
| var rotateDelta = new THREE.Vector2(); | |
| var zoomStart = new THREE.Vector2(); | |
| var zoomEnd = new THREE.Vector2(); | |
| var zoomDelta = new THREE.Vector2(); | |
| var phiDelta = 0; | |
| var thetaDelta = 0; | |
| var scale = 1; | |
| var lastPosition = new THREE.Vector3(); | |
| var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 }; | |
| var state = STATE.NONE; | |
| // events | |
| var changeEvent = { type: 'change' }; | |
| this.rotateLeft = function ( angle ) { | |
| if ( angle === undefined ) { | |
| angle = getAutoRotationAngle(); | |
| } | |
| thetaDelta -= angle; | |
| }; | |
| this.rotateRight = function ( angle ) { | |
| if ( angle === undefined ) { | |
| angle = getAutoRotationAngle(); | |
| } | |
| thetaDelta += angle; | |
| }; | |
| this.rotateUp = function ( angle ) { | |
| if ( angle === undefined ) { | |
| angle = getAutoRotationAngle(); | |
| } | |
| phiDelta -= angle; | |
| }; | |
| this.rotateDown = function ( angle ) { | |
| if ( angle === undefined ) { | |
| angle = getAutoRotationAngle(); | |
| } | |
| phiDelta += angle; | |
| }; | |
| this.zoomIn = function ( zoomScale ) { | |
| if ( zoomScale === undefined ) { | |
| zoomScale = getZoomScale(); | |
| } | |
| scale /= zoomScale; | |
| }; | |
| this.zoomOut = function ( zoomScale ) { | |
| if ( zoomScale === undefined ) { | |
| zoomScale = getZoomScale(); | |
| } | |
| scale *= zoomScale; | |
| }; | |
| this.pan = function ( distance ) { | |
| distance.transformDirection( this.object.matrix ); | |
| distance.multiplyScalar( scope.userPanSpeed ); | |
| this.object.position.add( distance ); | |
| this.center.add( distance ); | |
| }; | |
| this.update = function () { | |
| var position = this.object.position; | |
| var offset = position.clone().sub( this.center ); | |
| // angle from z-axis around y-axis | |
| var theta = Math.atan2( offset.x, offset.z ); | |
| // angle from y-axis | |
| var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y ); | |
| if ( this.autoRotate ) { | |
| this.rotateLeft( getAutoRotationAngle() ); | |
| } | |
| theta += thetaDelta; | |
| phi += phiDelta; | |
| // restrict phi to be between desired limits | |
| phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) ); | |
| // restrict phi to be betwee EPS and PI-EPS | |
| phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) ); | |
| var radius = offset.length() * scale; | |
| // restrict radius to be between desired limits | |
| radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) ); | |
| offset.x = radius * Math.sin( phi ) * Math.sin( theta ); | |
| offset.y = radius * Math.cos( phi ); | |
| offset.z = radius * Math.sin( phi ) * Math.cos( theta ); | |
| position.copy( this.center ).add( offset ); | |
| this.object.lookAt( this.center ); | |
| thetaDelta = 0; | |
| phiDelta = 0; | |
| scale = 1; | |
| if ( lastPosition.distanceTo( this.object.position ) > 0 ) { | |
| this.dispatchEvent( changeEvent ); | |
| lastPosition.copy( this.object.position ); | |
| } | |
| }; | |
| function getAutoRotationAngle() { | |
| return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; | |
| } | |
| function getZoomScale() { | |
| return Math.pow( 0.95, scope.userZoomSpeed ); | |
| } | |
| function onMouseDown( event ) { | |
| if ( scope.enabled === false ) return; | |
| if ( scope.userRotate === false ) return; | |
| event.preventDefault(); | |
| if ( state === STATE.NONE ) | |
| { | |
| if ( event.button === 0 ) | |
| state = STATE.ROTATE; | |
| if ( event.button === 1 ) | |
| state = STATE.ZOOM; | |
| if ( event.button === 2 ) | |
| state = STATE.PAN; | |
| } | |
| if ( state === STATE.ROTATE ) { | |
| //state = STATE.ROTATE; | |
| rotateStart.set( event.clientX, event.clientY ); | |
| } else if ( state === STATE.ZOOM ) { | |
| //state = STATE.ZOOM; | |
| zoomStart.set( event.clientX, event.clientY ); | |
| } else if ( state === STATE.PAN ) { | |
| //state = STATE.PAN; | |
| } | |
| document.addEventListener( 'mousemove', onMouseMove, false ); | |
| document.addEventListener( 'mouseup', onMouseUp, false ); | |
| } | |
| function onMouseMove( event ) { | |
| if ( scope.enabled === false ) return; | |
| event.preventDefault(); | |
| if ( state === STATE.ROTATE ) { | |
| rotateEnd.set( event.clientX, event.clientY ); | |
| rotateDelta.subVectors( rotateEnd, rotateStart ); | |
| scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed ); | |
| scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed ); | |
| rotateStart.copy( rotateEnd ); | |
| } else if ( state === STATE.ZOOM ) { | |
| zoomEnd.set( event.clientX, event.clientY ); | |
| zoomDelta.subVectors( zoomEnd, zoomStart ); | |
| if ( zoomDelta.y > 0 ) { | |
| scope.zoomIn(); | |
| } else { | |
| scope.zoomOut(); | |
| } | |
| zoomStart.copy( zoomEnd ); | |
| } else if ( state === STATE.PAN ) { | |
| var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; | |
| var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; | |
| scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) ); | |
| } | |
| } | |
| function onMouseUp( event ) { | |
| if ( scope.enabled === false ) return; | |
| if ( scope.userRotate === false ) return; | |
| document.removeEventListener( 'mousemove', onMouseMove, false ); | |
| document.removeEventListener( 'mouseup', onMouseUp, false ); | |
| state = STATE.NONE; | |
| } | |
| function onMouseWheel( event ) { | |
| if ( scope.enabled === false ) return; | |
| if ( scope.userZoom === false ) return; | |
| var delta = 0; | |
| if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 | |
| delta = event.wheelDelta; | |
| } else if ( event.detail ) { // Firefox | |
| delta = - event.detail; | |
| } | |
| if ( delta > 0 ) { | |
| scope.zoomOut(); | |
| } else { | |
| scope.zoomIn(); | |
| } | |
| } | |
| function onKeyDown( event ) { | |
| if ( scope.enabled === false ) return; | |
| if ( scope.userPan === false ) return; | |
| switch ( event.keyCode ) { | |
| /*case scope.keys.UP: | |
| scope.pan( new THREE.Vector3( 0, 1, 0 ) ); | |
| break; | |
| case scope.keys.BOTTOM: | |
| scope.pan( new THREE.Vector3( 0, - 1, 0 ) ); | |
| break; | |
| case scope.keys.LEFT: | |
| scope.pan( new THREE.Vector3( - 1, 0, 0 ) ); | |
| break; | |
| case scope.keys.RIGHT: | |
| scope.pan( new THREE.Vector3( 1, 0, 0 ) ); | |
| break; | |
| */ | |
| case scope.keys.ROTATE: | |
| state = STATE.ROTATE; | |
| break; | |
| case scope.keys.ZOOM: | |
| state = STATE.ZOOM; | |
| break; | |
| case scope.keys.PAN: | |
| state = STATE.PAN; | |
| break; | |
| } | |
| } | |
| function onKeyUp( event ) { | |
| switch ( event.keyCode ) { | |
| case scope.keys.ROTATE: | |
| case scope.keys.ZOOM: | |
| case scope.keys.PAN: | |
| state = STATE.NONE; | |
| break; | |
| } | |
| } | |
| this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); | |
| this.domElement.addEventListener( 'mousedown', onMouseDown, false ); | |
| this.domElement.addEventListener( 'mousewheel', onMouseWheel, false ); | |
| this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox | |
| window.addEventListener( 'keydown', onKeyDown, false ); | |
| window.addEventListener( 'keyup', onKeyUp, false ); | |
| }; | |
| THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype ); |
| body { | |
| overflow: hidden; | |
| margin: 0; | |
| } | |
| svg { z-index: 1; } | |
| .ui { position: absolute; z-index: 2; } | |
| button{ margin: 20px; } | |
| .xl { grid-area: xv; text-align: center; } | |
| .yl { grid-area: yv; text-align: center; } | |
| .zl { grid-area: zv; text-align: center; } | |
| #tooltip > div { | |
| color: #FEFEFE; font-size: 12px; | |
| -webkit-touch-callout: none; | |
| -webkit-user-select: none; | |
| -khtml-user-select: none; | |
| -moz-user-select: none | |
| -ms-user-select: none; | |
| user-select: none; | |
| } | |
| #tooltip { | |
| position: absolute; | |
| text-align: center; | |
| width: 192px; | |
| font: 10px sans-serif; | |
| border: 0px; | |
| border-radius: 6px; | |
| opacity: 0.6; | |
| top: -9999px; | |
| left: -9999px; | |
| display: grid; | |
| grid-template-areas: "xv yv zv"; | |
| grid-gap: 10px; | |
| background-color: #000000; | |
| padding: 10px; | |
| z-index: 99; | |
| } |