mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-15 21:05:22 +01:00
polynomial analysis
This commit is contained in:
parent
168fb3bacd
commit
2fafec904c
40 changed files with 1896 additions and 817 deletions
494
package-lock.json
generated
494
package-lock.json
generated
|
|
@ -1793,7 +1793,8 @@
|
|||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"optional": true
|
||||
},
|
||||
"assign-symbols": {
|
||||
"version": "1.0.0",
|
||||
|
|
@ -2110,12 +2111,6 @@
|
|||
"integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
|
||||
"dev": true
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
|
||||
"integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==",
|
||||
"dev": true
|
||||
},
|
||||
"bn.js": {
|
||||
"version": "4.11.8",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
|
||||
|
|
@ -2350,36 +2345,6 @@
|
|||
"integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
|
||||
"dev": true
|
||||
},
|
||||
"cacache": {
|
||||
"version": "11.3.1",
|
||||
"resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.1.tgz",
|
||||
"integrity": "sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bluebird": "^3.5.1",
|
||||
"chownr": "^1.0.1",
|
||||
"figgy-pudding": "^3.1.0",
|
||||
"glob": "^7.1.2",
|
||||
"graceful-fs": "^4.1.11",
|
||||
"lru-cache": "^4.1.3",
|
||||
"mississippi": "^3.0.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"move-concurrently": "^1.0.1",
|
||||
"promise-inflight": "^1.0.1",
|
||||
"rimraf": "^2.6.2",
|
||||
"ssri": "^6.0.0",
|
||||
"unique-filename": "^1.1.0",
|
||||
"y18n": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"y18n": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
|
||||
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"cache-base": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
|
||||
|
|
@ -2751,6 +2716,7 @@
|
|||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
|
||||
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
|
|
@ -2758,7 +2724,8 @@
|
|||
"commander": {
|
||||
"version": "2.20.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
|
||||
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ=="
|
||||
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
|
||||
"dev": true
|
||||
},
|
||||
"commondir": {
|
||||
"version": "1.0.1",
|
||||
|
|
@ -3357,7 +3324,8 @@
|
|||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"optional": true
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
|
|
@ -3682,9 +3650,9 @@
|
|||
}
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
|
||||
"integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"dev": true
|
||||
},
|
||||
"globals": {
|
||||
|
|
@ -3694,9 +3662,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.12.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
|
||||
"integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
|
|
@ -4161,7 +4129,8 @@
|
|||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
|
||||
"optional": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "1.1.0",
|
||||
|
|
@ -4479,7 +4448,8 @@
|
|||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
|
@ -4500,12 +4470,14 @@
|
|||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
|
@ -4520,17 +4492,20 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
|
@ -4647,7 +4622,8 @@
|
|||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
|
@ -4659,6 +4635,7 @@
|
|||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
|
@ -4673,6 +4650,7 @@
|
|||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
|
@ -4680,12 +4658,14 @@
|
|||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
|
@ -4704,6 +4684,7 @@
|
|||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
|
@ -4791,7 +4772,8 @@
|
|||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
|
@ -4803,6 +4785,7 @@
|
|||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
|
@ -4888,7 +4871,8 @@
|
|||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
|
@ -4924,6 +4908,7 @@
|
|||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
|
@ -4943,6 +4928,7 @@
|
|||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
|
@ -4986,12 +4972,14 @@
|
|||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -5270,9 +5258,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"handlebars": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
|
||||
"integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
|
||||
"integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
|
||||
"requires": {
|
||||
"neo-async": "^2.6.0",
|
||||
"optimist": "^0.6.1",
|
||||
|
|
@ -5723,6 +5711,12 @@
|
|||
"integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
|
||||
"dev": true
|
||||
},
|
||||
"infer-owner": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
|
||||
"integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
|
||||
"dev": true
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
|
|
@ -6174,7 +6168,8 @@
|
|||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"optional": true
|
||||
},
|
||||
"jsesc": {
|
||||
"version": "2.5.2",
|
||||
|
|
@ -6389,9 +6384,9 @@
|
|||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||
},
|
||||
"lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
|
|
@ -6760,9 +6755,9 @@
|
|||
}
|
||||
},
|
||||
"mixin-deep": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
|
||||
"integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
|
||||
"integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"for-in": "^1.0.2",
|
||||
|
|
@ -8273,27 +8268,75 @@
|
|||
}
|
||||
},
|
||||
"react": {
|
||||
"version": "16.4.1",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.4.1.tgz",
|
||||
"integrity": "sha512-3GEs0giKp6E0Oh/Y9ZC60CmYgUPnp7voH9fbjWsvXtYFb4EWtgQub0ADSq0sJR0BbHc4FThLLtzlcFaFXIorwg==",
|
||||
"version": "16.12.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.12.0.tgz",
|
||||
"integrity": "sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA==",
|
||||
"requires": {
|
||||
"fbjs": "^0.8.16",
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.0"
|
||||
"prop-types": "^15.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"requires": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-dom": {
|
||||
"version": "16.4.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.4.1.tgz",
|
||||
"integrity": "sha512-1Gin+wghF/7gl4Cqcvr1DxFX2Osz7ugxSwl6gBqCMpdrxHjIFUS7GYxrFftZ9Ln44FHw0JxCFD9YtZsrbR5/4A==",
|
||||
"version": "16.12.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.12.0.tgz",
|
||||
"integrity": "sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw==",
|
||||
"requires": {
|
||||
"fbjs": "^0.8.16",
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.0"
|
||||
"prop-types": "^15.6.2",
|
||||
"scheduler": "^0.18.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"requires": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.12.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
|
||||
"integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q=="
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
||||
|
|
@ -8731,6 +8774,15 @@
|
|||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
|
||||
"dev": true
|
||||
},
|
||||
"scheduler": {
|
||||
"version": "0.18.0",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz",
|
||||
"integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
|
||||
|
|
@ -8818,12 +8870,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz",
|
||||
"integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==",
|
||||
"dev": true
|
||||
},
|
||||
"serve-index": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
|
||||
|
|
@ -8884,9 +8930,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"set-value": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
|
||||
"integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
|
||||
"integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
|
|
@ -9161,6 +9207,24 @@
|
|||
"urix": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.5.16",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz",
|
||||
"integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"source-map-url": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
|
||||
|
|
@ -9592,65 +9656,60 @@
|
|||
"integrity": "sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==",
|
||||
"dev": true
|
||||
},
|
||||
"terser": {
|
||||
"version": "3.10.12",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-3.10.12.tgz",
|
||||
"integrity": "sha512-3ODPC1eVt25EVNb04s/PkHxOmzKBQUF6bwwuR6h2DbEF8/j265Y1UkwNtOk9am/pRxfJ5HPapOlUlO6c16mKQQ==",
|
||||
"terser-webpack-plugin": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz",
|
||||
"integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "~2.17.1",
|
||||
"source-map": "~0.6.1",
|
||||
"source-map-support": "~0.5.6"
|
||||
"cacache": "^12.0.2",
|
||||
"find-cache-dir": "^2.1.0",
|
||||
"is-wsl": "^1.1.0",
|
||||
"schema-utils": "^1.0.0",
|
||||
"serialize-javascript": "^2.1.2",
|
||||
"source-map": "^0.6.1",
|
||||
"terser": "^4.1.2",
|
||||
"webpack-sources": "^1.4.0",
|
||||
"worker-farm": "^1.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.17.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
|
||||
"integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
|
||||
"bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz",
|
||||
"integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==",
|
||||
"cacache": {
|
||||
"version": "12.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz",
|
||||
"integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
"bluebird": "^3.5.5",
|
||||
"chownr": "^1.1.1",
|
||||
"figgy-pudding": "^3.5.1",
|
||||
"glob": "^7.1.4",
|
||||
"graceful-fs": "^4.1.15",
|
||||
"infer-owner": "^1.0.3",
|
||||
"lru-cache": "^5.1.1",
|
||||
"mississippi": "^3.0.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"move-concurrently": "^1.0.1",
|
||||
"promise-inflight": "^1.0.1",
|
||||
"rimraf": "^2.6.3",
|
||||
"ssri": "^6.0.1",
|
||||
"unique-filename": "^1.1.1",
|
||||
"y18n": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"terser-webpack-plugin": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.1.0.tgz",
|
||||
"integrity": "sha512-61lV0DSxMAZ8AyZG7/A4a3UPlrbOBo8NIQ4tJzLPAdGOQ+yoNC7l5ijEow27lBAL2humer01KLS6bGIMYQxKoA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cacache": "^11.0.2",
|
||||
"find-cache-dir": "^2.0.0",
|
||||
"schema-utils": "^1.0.0",
|
||||
"serialize-javascript": "^1.4.0",
|
||||
"source-map": "^0.6.1",
|
||||
"terser": "^3.8.1",
|
||||
"webpack-sources": "^1.1.0",
|
||||
"worker-farm": "^1.5.2"
|
||||
},
|
||||
"dependencies": {
|
||||
},
|
||||
"find-cache-dir": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz",
|
||||
"integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
|
||||
"integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commondir": "^1.0.1",
|
||||
"make-dir": "^1.0.0",
|
||||
"make-dir": "^2.0.0",
|
||||
"pkg-dir": "^3.0.0"
|
||||
}
|
||||
},
|
||||
|
|
@ -9663,6 +9722,26 @@
|
|||
"locate-path": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
|
||||
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
|
||||
"dev": true
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
|
||||
|
|
@ -9673,10 +9752,29 @@
|
|||
"path-exists": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"make-dir": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
|
||||
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pify": "^4.0.1",
|
||||
"semver": "^5.6.0"
|
||||
}
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz",
|
||||
"integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==",
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
|
||||
"integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-try": "^2.0.0"
|
||||
|
|
@ -9692,9 +9790,15 @@
|
|||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz",
|
||||
"integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==",
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true
|
||||
},
|
||||
"pify": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
|
||||
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
|
||||
"dev": true
|
||||
},
|
||||
"pkg-dir": {
|
||||
|
|
@ -9706,11 +9810,68 @@
|
|||
"find-up": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz",
|
||||
"integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
},
|
||||
"terser": {
|
||||
"version": "4.6.1",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-4.6.1.tgz",
|
||||
"integrity": "sha512-w0f2OWFD7ka3zwetgVAhNMeyzEbj39ht2Tb0qKflw9PmW9Qbo5tjTh01QJLkhO9t9RDDQYvk+WXqpECI2C6i2A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "^2.20.0",
|
||||
"source-map": "~0.6.1",
|
||||
"source-map-support": "~0.5.12"
|
||||
}
|
||||
},
|
||||
"webpack-sources": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
|
||||
"integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"source-list-map": "^2.0.0",
|
||||
"source-map": "~0.6.1"
|
||||
}
|
||||
},
|
||||
"worker-farm": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
|
||||
"integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"errno": "~0.1.7"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -9871,7 +10032,8 @@
|
|||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"optional": true
|
||||
},
|
||||
"type-check": {
|
||||
"version": "0.3.2",
|
||||
|
|
@ -9921,15 +10083,21 @@
|
|||
"integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA=="
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
|
||||
"integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
|
||||
"version": "3.7.4",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.7.4.tgz",
|
||||
"integrity": "sha512-tinYWE8X1QfCHxS1lBS8yiDekyhSXOO6R66yNOCdUJeojxxw+PX2BHAz/BWyW7PQ7pkiWVxJfIEbiDxyLWvUGg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"commander": "~2.20.0",
|
||||
"commander": "~2.20.3",
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"optional": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
|
|
@ -9977,38 +10145,15 @@
|
|||
"dev": true
|
||||
},
|
||||
"union-value": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
|
||||
"integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
|
||||
"integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"arr-union": "^3.1.0",
|
||||
"get-value": "^2.0.6",
|
||||
"is-extendable": "^0.1.1",
|
||||
"set-value": "^0.4.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"extend-shallow": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-extendable": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"set-value": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
|
||||
"integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
"is-extendable": "^0.1.1",
|
||||
"is-plain-object": "^2.0.1",
|
||||
"to-object-path": "^0.3.0"
|
||||
}
|
||||
}
|
||||
"set-value": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"uniq": {
|
||||
|
|
@ -11411,15 +11556,6 @@
|
|||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
|
||||
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
|
||||
},
|
||||
"worker-farm": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz",
|
||||
"integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"errno": "~0.1.7"
|
||||
}
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
"clipper-lib": "6.2.1",
|
||||
"diff-match-patch": "1.0.0",
|
||||
"earcut": "2.1.1",
|
||||
"handlebars": "^4.1.2",
|
||||
"handlebars": "^4.5.3",
|
||||
"handlebars-loader": "1.7.1",
|
||||
"jquery": "^3.4.1",
|
||||
"less": "^3.8.1",
|
||||
|
|
@ -63,8 +63,8 @@
|
|||
"mousetrap": "1.6.1",
|
||||
"numeric": "1.2.6",
|
||||
"prop-types": "15.6.0",
|
||||
"react": "^16.4.0",
|
||||
"react-dom": "^16.4.0",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"sprintf": "0.1.5",
|
||||
"three": "0.89.0"
|
||||
}
|
||||
|
|
|
|||
89
web/app/sketcher/actions/constraintActions.js
Normal file
89
web/app/sketcher/actions/constraintActions.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import {AlgNumConstraint, ConstraintDefinitions} from "../constr/ANConstraints";
|
||||
import {EndPoint} from "../shapes/point";
|
||||
import {Circle} from "../shapes/circle";
|
||||
import {Segment} from "../shapes/segment";
|
||||
import {matchAll, matchTypes, sortSelectionByType} from "./matchUtils";
|
||||
|
||||
export default [
|
||||
|
||||
|
||||
{
|
||||
shortName: 'Coincident',
|
||||
description: 'Point Coincident',
|
||||
selectionMatcher: (selection, sortedByType) => matchAll(selection, EndPoint, 2),
|
||||
|
||||
invoke: viewer => {
|
||||
const [first, ...others] = viewer.selected;
|
||||
let pm = viewer.parametricManager;
|
||||
for (let obj of others) {
|
||||
pm.algnNumSystem.addConstraint(
|
||||
new AlgNumConstraint(ConstraintDefinitions.PCoincident, [first, obj])
|
||||
);
|
||||
}
|
||||
pm.refresh();
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
shortName: 'Tangent',
|
||||
description: 'Tangent Between Line And Circle',
|
||||
selectionMatcher: (selection, sortedByType) => matchTypes(sortedByType, Circle, 1, Segment, 1),
|
||||
|
||||
invoke: viewer => {
|
||||
const [circle, line] = sortSelectionByType(viewer.selected);
|
||||
let pm = viewer.parametricManager;
|
||||
const ang = line.params.ang.get();
|
||||
const w = line.params.w.get();
|
||||
const inverted = Math.cos(ang) * circle.c.x + Math.sin(ang) * circle.c.y < w ;
|
||||
|
||||
pm.algnNumSystem.addConstraint(new AlgNumConstraint(ConstraintDefinitions.TangentLC, [line, circle], {
|
||||
inverted
|
||||
}));
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
shortName: 'Point On Line',
|
||||
description: 'Point On Line',
|
||||
selectionMatcher: (selection, sortedByType) => matchTypes(sortedByType, EndPoint, 1, Segment, 1),
|
||||
|
||||
invoke: viewer => {
|
||||
const [pt, line] = sortSelectionByType(viewer.selected);
|
||||
let pm = viewer.parametricManager;
|
||||
pm.algnNumSystem.addConstraint(new AlgNumConstraint(ConstraintDefinitions.PointOnLine, [pt, line]));
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
shortName: 'Angle',
|
||||
description: 'Angle',
|
||||
selectionMatcher: (selection, sortedByType) => matchAll(sortedByType, Segment, 1),
|
||||
|
||||
invoke: viewer => {
|
||||
|
||||
const firstSegment = viewer.selected[0];
|
||||
|
||||
const firstConstr = new AlgNumConstraint(ConstraintDefinitions.Angle, [firstSegment]);
|
||||
firstConstr.initConstants();
|
||||
|
||||
viewer.streams.constraintEditRequest.next({
|
||||
constraint: firstConstr,
|
||||
onCancel: () => viewer.streams.constraintEditRequest.next(null),
|
||||
onApply: () => {
|
||||
viewer.streams.constraintEditRequest.next(null);
|
||||
const pm = viewer.parametricManager;
|
||||
pm.algnNumSystem.addConstraint(firstConstr);
|
||||
for (let i = 1; i < viewer.selected.length; ++i) {
|
||||
pm.algnNumSystem.addConstraint(new AlgNumConstraint(ConstraintDefinitions.Angle, viewer.selected[i], {...firstConstr.constants}));
|
||||
}
|
||||
pm.refresh();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
];
|
||||
25
web/app/sketcher/actions/index.js
Normal file
25
web/app/sketcher/actions/index.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import constraintActions from "./constraintActions";
|
||||
import {sortSelectionByType} from "./matchUtils";
|
||||
|
||||
const ALL_CONTEXTUAL_ACTIONS = [
|
||||
...constraintActions,
|
||||
//keep going here
|
||||
];
|
||||
|
||||
export function matchAvailableActions(selection) {
|
||||
|
||||
let sortedByType = sortSelectionByType(selection);
|
||||
let matched = [];
|
||||
|
||||
|
||||
if (selection.length) {
|
||||
for (let action of ALL_CONTEXTUAL_ACTIONS) {
|
||||
if (action.selectionMatcher(selection, sortedByType)) {
|
||||
matched.push(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matched;
|
||||
|
||||
}
|
||||
38
web/app/sketcher/actions/matchUtils.js
Normal file
38
web/app/sketcher/actions/matchUtils.js
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
|
||||
|
||||
export function matchAll(selection, shapeConstructor, min) {
|
||||
if (min !== undefined && selection.length < min) {
|
||||
return false;
|
||||
}
|
||||
for (let obj of selection) {
|
||||
if (obj._class !== shapeConstructor.prototype._class) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
export function matchTypes(selection) {
|
||||
let si = 0;
|
||||
let i = 1;
|
||||
for (; i < arguments.length; i+=2) {
|
||||
let shapeConstructor = arguments[i];
|
||||
let quantity = arguments[i+1];
|
||||
if (si === selection.length) {
|
||||
return false;
|
||||
}
|
||||
for (let j = 0; j < quantity && si < selection.length; j++) {
|
||||
let obj = selection[si++];
|
||||
if (obj._class !== shapeConstructor.prototype._class) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return si === selection.length && i === arguments.length;
|
||||
}
|
||||
|
||||
export function sortSelectionByType(selection) {
|
||||
return [...selection].sort((a, b) => a._class.localeCompare(b._class))
|
||||
}
|
||||
73
web/app/sketcher/components/ConstraintEditor.jsx
Normal file
73
web/app/sketcher/components/ConstraintEditor.jsx
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import React, {useState} from 'react';
|
||||
import Widget from "ui/components/Widget";
|
||||
import NumberControl from "ui/components/controls/NumberControl";
|
||||
import {DEG_RAD} from "../../math/math";
|
||||
import Stack from "ui/components/Stack";
|
||||
import ButtonGroup from "ui/components/controls/ButtonGroup";
|
||||
import Button from "ui/components/controls/Button";
|
||||
import connect from "../../../../modules/ui/connect";
|
||||
|
||||
|
||||
export const ConstraintEditor = connect(streams => streams.sketcherApp.constraintEditRequest)(
|
||||
function ConstraintEditor({constraint, onCancel, onApply}) {
|
||||
return <ConstraintEditorImpl constraint={constraint}
|
||||
onCancel={onCancel}
|
||||
onApply={onApply} />
|
||||
}
|
||||
);
|
||||
|
||||
export function ConstraintEditorImpl({constraint, onCancel, onApply}) {
|
||||
|
||||
if (!constraint) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [values, setValues] = useState({...constraint.constants});
|
||||
|
||||
const setValue = (name, value) => {
|
||||
setValues({...value, [name]: value});
|
||||
};
|
||||
|
||||
const apply = () => {
|
||||
Object.keys(constraint.schema.constants).map(name => {
|
||||
const val = values[name];
|
||||
if (val !== undefined) {
|
||||
constraint.constants[name] = val;
|
||||
}
|
||||
});
|
||||
onApply();
|
||||
};
|
||||
|
||||
return <Widget>
|
||||
|
||||
<Stack>
|
||||
|
||||
{Object.keys(constraint.schema.constants).sort().map(name => <div key={name}>
|
||||
|
||||
{
|
||||
(() => {
|
||||
const def = constraint.schema.constants[name];
|
||||
const val = values[name];
|
||||
if (def.type === 'number') {
|
||||
return <NumberControl value={val} onChange={value => setValue(name, value)} />
|
||||
} else {
|
||||
return <span >{val}</span>;
|
||||
}
|
||||
|
||||
})()
|
||||
|
||||
}
|
||||
|
||||
</div>)}
|
||||
|
||||
|
||||
<ButtonGroup>
|
||||
<Button onClick={onCancel}>CANCEL</Button>
|
||||
<Button type='accent' onClick={apply}>APPLY</Button>
|
||||
</ButtonGroup>
|
||||
|
||||
</Stack>
|
||||
|
||||
</Widget>;
|
||||
|
||||
}
|
||||
38
web/app/sketcher/components/ContextualControls.jsx
Normal file
38
web/app/sketcher/components/ContextualControls.jsx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import React from 'react';
|
||||
import ls from './ContextualControls.less';
|
||||
import connect from "../../../../modules/ui/connect";
|
||||
import {matchAvailableActions} from "../actions";
|
||||
import mapContext from "../../../../modules/ui/mapContext";
|
||||
|
||||
export const ContextualControls =
|
||||
mapContext(ctx => ({
|
||||
invokeAction: action => action.invoke(ctx.viewer)
|
||||
}))(
|
||||
connect(streams => streams.sketcherApp.selection.map(selection => ({selection})))(
|
||||
|
||||
|
||||
function ContextualControls({selection, invokeAction}) {
|
||||
|
||||
if (selection.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const availableActions = matchAvailableActions(selection);
|
||||
|
||||
return <div className={ls.root}>
|
||||
|
||||
{
|
||||
selection.map(s => <div className={ls.item}>{s.simpleClassName}: {s.id}</div>)
|
||||
}
|
||||
|
||||
<div className={ls.hr}>AVAILABLE ACTIONS:</div>
|
||||
|
||||
{
|
||||
availableActions.map(a => <button onClick={() => invokeAction(a)}
|
||||
title={a.description}>{a.shortName}</button>)
|
||||
}
|
||||
|
||||
</div>;
|
||||
|
||||
}
|
||||
));
|
||||
15
web/app/sketcher/components/ContextualControls.less
Normal file
15
web/app/sketcher/components/ContextualControls.less
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
.root {
|
||||
margin: 5px;
|
||||
padding: 3px 5px;
|
||||
background-color: #000D;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
.hr {
|
||||
.item;
|
||||
}
|
||||
14
web/app/sketcher/components/RightSideControls.jsx
Normal file
14
web/app/sketcher/components/RightSideControls.jsx
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react';
|
||||
import {ConstraintEditor} from "./ConstraintEditor";
|
||||
import {ContextualControls} from "./ContextualControls";
|
||||
|
||||
export function RightSideControls() {
|
||||
|
||||
return <React.Fragment>
|
||||
<ContextualControls />
|
||||
<ConstraintEditor />
|
||||
</React.Fragment>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
238
web/app/sketcher/constr/ANConstraints.js
Normal file
238
web/app/sketcher/constr/ANConstraints.js
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
import {R_DistancePP, R_Equal, R_PointOnLine} from "./residuals";
|
||||
import {indexById} from "../../../../modules/gems/iterables";
|
||||
import {DEG_RAD, distanceAB} from "../../math/math";
|
||||
import {COS_FN, Polynomial, POW_1_FN, POW_2_FN, SIN_FN} from "./polynomial";
|
||||
import {Types} from "../io";
|
||||
|
||||
export const ConstraintDefinitions = indexById([
|
||||
|
||||
{
|
||||
id: 'PCoincident',
|
||||
name: 'Two Points Coincidence',
|
||||
|
||||
defineParamsScope: ([p1, p2], callback) => {
|
||||
p1.visitParams(callback);
|
||||
p2.visitParams(callback);
|
||||
},
|
||||
|
||||
|
||||
collectPolynomials: (polynomials, [x1, y1, x2, y2]) => {
|
||||
polynomials.push(new Polynomial(0)
|
||||
.monomial(1)
|
||||
.term(x1, POW_1_FN)
|
||||
.monomial(-1)
|
||||
.term(x2, POW_1_FN)
|
||||
);
|
||||
polynomials.push(new Polynomial(0)
|
||||
.monomial(1)
|
||||
.term(y1, POW_1_FN)
|
||||
.monomial(-1)
|
||||
.term(y2, POW_1_FN)
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
id: 'TangentLC',
|
||||
name: 'Line & Circle Tangency',
|
||||
constants: {
|
||||
inverted: {
|
||||
type: 'boolean',
|
||||
description: 'whether the circle attached from the opposite side',
|
||||
initialValue: () => false
|
||||
}
|
||||
},
|
||||
|
||||
defineParamsScope: ([segment, circle], callback) => {
|
||||
callback(segment.params.ang);
|
||||
callback(segment.params.w);
|
||||
circle.c.visitParams(callback);
|
||||
callback(circle.r);
|
||||
},
|
||||
|
||||
|
||||
collectPolynomials: (polynomials, [ang, w, cx, cy, r], {inverted}) => {
|
||||
polynomials.push(new Polynomial(0)
|
||||
.monomial(1)
|
||||
.term(cx, POW_1_FN)
|
||||
.term(ang, COS_FN)
|
||||
.monomial(1)
|
||||
.term(cy, POW_1_FN)
|
||||
.term(ang, SIN_FN)
|
||||
.monomial(-1)
|
||||
.term(w, POW_1_FN)
|
||||
.monomial(- (inverted ? -1 : 1))
|
||||
.term(r, POW_1_FN)
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'PointOnLine',
|
||||
name: 'Point On Line',
|
||||
|
||||
defineParamsScope: ([pt, segment], callback) => {
|
||||
pt.visitParams(callback);
|
||||
callback(segment.params.ang);
|
||||
callback(segment.params.w);
|
||||
},
|
||||
|
||||
collectResiduals: (residuals, params) => {
|
||||
residuals.push([R_PointOnLine, params, []]);
|
||||
},
|
||||
|
||||
collectPolynomials: (polynomials, [x, y, ang, w]) => {
|
||||
polynomials.push(new Polynomial(0)
|
||||
.monomial(1)
|
||||
.term(x, POW_1_FN)
|
||||
.term(ang, COS_FN)
|
||||
.monomial(1)
|
||||
.term(y, POW_1_FN)
|
||||
.term(ang, SIN_FN)
|
||||
.monomial(-1)
|
||||
.term(w, POW_1_FN)
|
||||
);
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
id: 'DistancePP',
|
||||
name: 'Distance Between Two Point',
|
||||
constants: {
|
||||
distance: {
|
||||
type: 'number',
|
||||
description: 'the distance between two points',
|
||||
initialValue: (constraint) => {
|
||||
const [a, b] = constraint.object;
|
||||
return distanceAB(a, b).toFixed(2) + '';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
defineParamsScope: ([pt, segment], callback) => {
|
||||
pt.visitParams(callback);
|
||||
callback(segment.params.ang);
|
||||
callback(segment.params.w);
|
||||
},
|
||||
|
||||
collectResiduals: (residuals, params, {distance}) => {
|
||||
residuals.push([R_DistancePP, params, [distance]]);
|
||||
},
|
||||
|
||||
collectPolynomials: (polynomials, [x1, y1, x2, y2], {distance}) => {
|
||||
polynomials.push(new Polynomial( - distance * distance)
|
||||
.monomial(1)
|
||||
.term(x1, POW_2_FN)
|
||||
.monomial(1)
|
||||
.term(x2, POW_2_FN)
|
||||
.monomial(-2)
|
||||
.term(x1, POW_1_FN)
|
||||
.term(x2, POW_1_FN)
|
||||
|
||||
.monomial(1)
|
||||
.term(y1, POW_2_FN)
|
||||
.monomial(1)
|
||||
.term(y2, POW_2_FN)
|
||||
.monomial(-2)
|
||||
.term(y1, POW_1_FN)
|
||||
.term(y2, POW_1_FN)
|
||||
|
||||
);
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
id: 'Angle',
|
||||
name: 'Absolute Line Angle',
|
||||
constants: {
|
||||
angle: {
|
||||
type: 'number',
|
||||
description: 'line angle',
|
||||
initialValue: (constraint) => {
|
||||
let degrees = constraint.objects[0].params.ang.get() / DEG_RAD;
|
||||
degrees = (degrees + 360 - 90) % 360;
|
||||
return degrees.toFixed(2) + '';
|
||||
},
|
||||
transform: degree => ( (degree + 90) % 360 ) * DEG_RAD
|
||||
}
|
||||
},
|
||||
|
||||
defineParamsScope: ([segment], callback) => {
|
||||
callback(segment.params.ang);
|
||||
},
|
||||
|
||||
collectPolynomials: (polynomials, [x], {angle}) => {
|
||||
polynomials.push(new Polynomial( - angle).monomial(1).term(x, POW_1_FN));
|
||||
},
|
||||
},
|
||||
|
||||
]);
|
||||
|
||||
export class AlgNumConstraint {
|
||||
|
||||
static Counter = 0;
|
||||
|
||||
constructor(schema, objects, constants) {
|
||||
this.id = schema.id + ':' + (AlgNumConstraint.Counter ++); // only for debug purposes - not persisted
|
||||
this.objects = objects;
|
||||
this.constants = constants;
|
||||
this.resolvedConstants = undefined;
|
||||
this.internal = false;
|
||||
this.schema = schema;
|
||||
this.params = [];
|
||||
this.schema.defineParamsScope(this.objects, p => this.params.push(p));
|
||||
// this.paramSet = new Set(this.params);
|
||||
}
|
||||
|
||||
collectPolynomials(polynomials) {
|
||||
this.resolveConstants();
|
||||
this.schema.collectPolynomials(polynomials, this.params, this.resolvedConstants);
|
||||
}
|
||||
|
||||
resolveConstants() {
|
||||
if (this.constants) {
|
||||
if (!this.resolvedConstants) {
|
||||
this.resolvedConstants = {};
|
||||
}
|
||||
Object.keys(this.constants).map(name => {
|
||||
let def = this.schema.constants[name];
|
||||
if (def.type === 'number') {
|
||||
let val = parseFloat(this.constants[name]);
|
||||
if (def.transform) {
|
||||
val = def.transform(val);
|
||||
}
|
||||
this.resolvedConstants[name] = val;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
write() {
|
||||
return {
|
||||
typeId: this.schema.id,
|
||||
objects: this.objects.map(o => o.id),
|
||||
constants: this.constants
|
||||
}
|
||||
}
|
||||
|
||||
static read({typeId, objects, constants}, index) {
|
||||
const schema = ConstraintDefinitions[typeId];
|
||||
if (!schema) {
|
||||
throw "constraint schema ' + typeId + ' doesn't exist";
|
||||
}
|
||||
return new AlgNumConstraint(schema, objects.map(oId => index[oId]), constants);
|
||||
}
|
||||
|
||||
initConstants() {
|
||||
if (this.schema.constants) {
|
||||
this.constants = {};
|
||||
Object.keys(this.schema.constants).map(name => {
|
||||
this.constants[name] = this.schema.constants[name].initialValue(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
237
web/app/sketcher/constr/AlgNumSystem.js
Normal file
237
web/app/sketcher/constr/AlgNumSystem.js
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
import {createByConstraintName} from "./solverConstraints";
|
||||
import {Param, prepare} from "./solver";
|
||||
import {findConstructionCluster} from "./constructions";
|
||||
import {GCCircle, GCPoint} from "./constractibles";
|
||||
import {eqEps, eqTol} from "../../brep/geom/tolerance";
|
||||
import {Polynomial} from "./polynomial";
|
||||
import {NOOP} from "../../../../modules/gems/func";
|
||||
|
||||
export class AlgNumSubSystem {
|
||||
|
||||
|
||||
generator = NOOP;//new BoundaryObjectsGenerator();
|
||||
|
||||
constraints = [];
|
||||
|
||||
ownParams = new Set();
|
||||
|
||||
readOnlyParams = new Set();
|
||||
|
||||
generatedParams = new Set();
|
||||
|
||||
beingSolvedParams = new Set();
|
||||
|
||||
|
||||
// generators = [];
|
||||
subSystems = []; //subsystems are generated by generators only
|
||||
|
||||
polynomials = [];
|
||||
substitutedParams = [];
|
||||
polyToConstr = new Map();
|
||||
conflicting = new Set();
|
||||
redundant = new Set();
|
||||
|
||||
SubSystem(generator) {
|
||||
this.generator = generator;
|
||||
}
|
||||
|
||||
addConstraint(constraint, _ancestorParams) {
|
||||
|
||||
if (this.canBeAdded(constraint.params)) {
|
||||
// this.constraints.push(constraint);
|
||||
// this.constraints
|
||||
}
|
||||
|
||||
this.constraints.push(constraint);
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.polynomials = [];
|
||||
this.substitutedParams = [];
|
||||
this.polyToConstr.clear();
|
||||
this.conflicting.clear();
|
||||
this.redundant.clear();
|
||||
this.beingSolvedParams.clear();
|
||||
}
|
||||
|
||||
evaluatePolynomials() {
|
||||
this.constraints.forEach(c => {
|
||||
c.collectPolynomials(this.polynomials);
|
||||
this.polynomials.forEach(p => this.polyToConstr.set(p, c))
|
||||
});
|
||||
|
||||
|
||||
|
||||
const toEliminate = Array.from(this.readOnlyParams);
|
||||
|
||||
const toSubstitute = [];
|
||||
const linearSub = [];
|
||||
|
||||
let requirePass = true;
|
||||
|
||||
while (requirePass) {
|
||||
requirePass = false;
|
||||
for (let i = 0; i < this.polynomials.length; ++i) {
|
||||
const polynomial = this.polynomials[i];
|
||||
if (!polynomial) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (polynomial.monomials.length === 0) {
|
||||
if (!eqEps(polynomial.constant, 0)) {
|
||||
this.conflicting.add(this.polyToConstr.get(polynomial));
|
||||
}
|
||||
this.polynomials[i] = null;
|
||||
} else if (polynomial.monomials.length === 1) {
|
||||
const monomial = polynomial.monomials[0];
|
||||
const terms = monomial.terms;
|
||||
if (terms.length === 1) {
|
||||
const term = terms[0];
|
||||
if (term.fn.degree === 1) {
|
||||
term.param.set(- polynomial.constant / monomial.constant);
|
||||
toEliminate.push(term.param);
|
||||
}
|
||||
}
|
||||
|
||||
this.polynomials[i] = null;
|
||||
} else if (polynomial.monomials.length === 2 && polynomial.isLinear) {
|
||||
const [m1, m2] = polynomial.monomials;
|
||||
|
||||
const constant = - m2.constant / m1.constant;
|
||||
if (!eqEps(polynomial.constant, 0)) {
|
||||
toSubstitute.push([m1.param, m2.param, constant]);
|
||||
this.substitutedParams.push([m1.param, new Polynomial().monomial(constant).addParam(m2.param)]);
|
||||
} else {
|
||||
// linearSub.push([m1.param, m2.param, constant, - polynomial.constant / m1.constant]);
|
||||
}
|
||||
|
||||
|
||||
this.polynomials[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
while (toEliminate.length) {
|
||||
requirePass = true;
|
||||
const param = toEliminate.pop();
|
||||
for (let polynomial of this.polynomials) {
|
||||
if (polynomial) {
|
||||
polynomial.eliminate(param, param.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
while (toSubstitute.length) {
|
||||
requirePass = true;
|
||||
const [param, toParam, dotConstant] = toSubstitute.pop();
|
||||
for (let polynomial of this.polynomials) {
|
||||
if (polynomial) {
|
||||
polynomial.substitute(param, toParam, dotConstant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (requirePass) {
|
||||
this.polynomials.forEach(polynomial => polynomial && polynomial.compact());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
while (toEliminate.length || toSubstitute.length) {
|
||||
|
||||
|
||||
// while (linearSub.length) {
|
||||
// const [param, toParam, b, c] = linearSub.pop();
|
||||
// for (let polynomial of polynomials) {
|
||||
// if (polynomial) {
|
||||
// polynomial.linerSub(param, toParam, b, c);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
this.polynomials = this.polynomials.filter(p => p);
|
||||
|
||||
}
|
||||
|
||||
|
||||
prepare() {
|
||||
|
||||
this.reset();
|
||||
this.evaluatePolynomials();
|
||||
|
||||
console.log('solving system:');
|
||||
this.polynomials.forEach(p => console.log(p.toString()));
|
||||
|
||||
const residuals = [];
|
||||
|
||||
this.polynomials.forEach(p => residuals.push(p.asResidual()));
|
||||
|
||||
for (let residual of residuals) {
|
||||
residual.params.forEach(solverParam => {
|
||||
if (!this.beingSolvedParams.has(solverParam)) {
|
||||
solverParam.reset(solverParam.objectParam.get());
|
||||
this.beingSolvedParams.add(solverParam);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.numericalSolver = prepare(residuals);
|
||||
}
|
||||
|
||||
|
||||
solve(rough) {
|
||||
this.generator();
|
||||
|
||||
this.beingSolvedParams.forEach(solverParam => {
|
||||
solverParam.set(solverParam.objectParam.get());
|
||||
});
|
||||
|
||||
this.numericalSolver.solveSystem(rough);
|
||||
|
||||
this.beingSolvedParams.forEach(solverParam => {
|
||||
solverParam.objectParam.set(solverParam.get());
|
||||
});
|
||||
for (let i = this.substitutedParams.length - 1; i >= 0; i--) {
|
||||
let [param, expression] = this.substitutedParams[i];
|
||||
param.set(expression.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
canBeAdded(subjectParams, ancestorParams) {
|
||||
|
||||
for (let p of subjectParams) {
|
||||
if (!this.ownParams.has(p) && (!ancestorParams || !ancestorParams.has(p))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class AlgNumSystem {
|
||||
constraints = [];
|
||||
generators = [];
|
||||
locked = new Set();
|
||||
constantParams = new Set();
|
||||
|
||||
constructor(visitAllObjects) {
|
||||
this.visitAllObjects = visitAllObjects;
|
||||
}
|
||||
|
||||
addConstraint(constraint) {
|
||||
this.constraints.push(constraint);
|
||||
if (constraint.schema.generator) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
startTransaction(interactiveLock = []) {
|
||||
this.systemTransaction.prepare(interactiveLock);
|
||||
return this.systemTransaction;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
import {R_Distance, R_DistancePP, R_PointOnLine, R_TangentLC, R_UnitVector} from "./residuals";
|
||||
import {indexById} from "../../../../modules/gems/iterables";
|
||||
import {distanceAB} from "../../math/math";
|
||||
|
||||
export const ConstraintDefinitions = indexById([
|
||||
|
||||
{
|
||||
id: 'TangentLC',
|
||||
name: 'Line & Circle Tangency',
|
||||
constants: {
|
||||
inverted: {
|
||||
type: 'boolean',
|
||||
description: 'whether the circle attached from the opposite side',
|
||||
initialValue: () => false
|
||||
}
|
||||
},
|
||||
|
||||
constructibleObjects: ([line, circle]) => [line.gcLine, circle.gcCircle],
|
||||
|
||||
collectResiduals: (residuals, constraint) => {
|
||||
const [gcLine] = constraint.objects;
|
||||
residuals.push([R_TangentLC, constraint.params, [constraint.constants.inverted]]);
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
id: 'PointOnLine',
|
||||
name: 'Point On Line',
|
||||
|
||||
constructibleObjects: ([point, line]) => [point.gcPoint, line.gcLine],
|
||||
|
||||
collectResiduals: (residuals, constraint) => {
|
||||
residuals.push([R_PointOnLine, constraint.params, []]);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
id: 'DistancePP',
|
||||
name: 'Distance Between Two Point',
|
||||
constants: {
|
||||
distance: {
|
||||
type: 'number',
|
||||
description: 'the distance between two points',
|
||||
initialValue: (constraint) => {
|
||||
const [a, b] = constraint.object;
|
||||
return distanceAB(a, b)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
constructibleObjects: ([p1, p2]) => [p1.gcPoint, p2.gcPoint],
|
||||
|
||||
collectResiduals: (residuals, constraint) => {
|
||||
residuals.push([R_DistancePP, constraint.params, [constraint.constants.distance]]);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
]);
|
||||
|
||||
export class SEACConstraint {
|
||||
|
||||
static Counter = 0;
|
||||
|
||||
constructor(schema, attachedObjects, constants) {
|
||||
this.id = schema.id + ':' + (SEACConstraint.Counter ++); // only for debug purposes - not persisted
|
||||
this.attachedObjects = attachedObjects;
|
||||
this.objects = schema.constructibleObjects(attachedObjects);
|
||||
this.constants = constants;
|
||||
this.objects.forEach(o => {
|
||||
o.constraints.push(this);
|
||||
});
|
||||
this.internal = false;
|
||||
this.schema = schema;
|
||||
}
|
||||
|
||||
collectParams(params) {
|
||||
this.objects.forEach(o => o.collectParams(params));
|
||||
}
|
||||
|
||||
get params() {
|
||||
const params = [];
|
||||
this.collectParams(params);
|
||||
return params;
|
||||
}
|
||||
|
||||
visitAdjacentConstraints(fn) {
|
||||
this.objects.forEach(o => o.constraints.forEach(fn));
|
||||
}
|
||||
|
||||
collectResiduals(out) {
|
||||
return this.schema.collectResiduals(out, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,291 +0,0 @@
|
|||
import {createByConstraintName} from "./solverConstraints";
|
||||
import {Param, prepare} from "./solver";
|
||||
import {findConstructionCluster} from "./constructions";
|
||||
import {GCCircle, GCPoint} from "./constractibles";
|
||||
|
||||
|
||||
const ConstraintDegree = {
|
||||
PARTIALLY_SOLVABLE: 1,
|
||||
NOT_SOLVABLE: 2,
|
||||
SOLVABLE: 3
|
||||
};
|
||||
|
||||
|
||||
export class SEACSystem {
|
||||
constraints = [];
|
||||
locked = new Set();
|
||||
systemTransaction = new SystemTransaction(this);
|
||||
|
||||
addConstraint(constraint) {
|
||||
this.constraints.push(constraint);
|
||||
}
|
||||
|
||||
startTransaction(interactiveLock = []) {
|
||||
this.systemTransaction.prepare(interactiveLock);
|
||||
return this.systemTransaction;
|
||||
}
|
||||
}
|
||||
|
||||
export class SystemTransaction {
|
||||
|
||||
locked = new Set();
|
||||
scheduled = new Map();
|
||||
internalObjects = new Set();
|
||||
decayedObjects = new Set();
|
||||
clusters = [];
|
||||
|
||||
constructor(system) {
|
||||
this.system = system;
|
||||
}
|
||||
|
||||
constraintDegree(constraint) {
|
||||
|
||||
let hasNonFreeAgents = false;
|
||||
let hasFreeAgents = false;
|
||||
|
||||
for (let obj of constraint.objects) {
|
||||
|
||||
if (this.isLocked(obj) || this.decayedObjects.has(obj)) {
|
||||
hasNonFreeAgents = true;
|
||||
} else {
|
||||
hasFreeAgents = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasNonFreeAgents && hasFreeAgents) {
|
||||
return ConstraintDegree.PARTIALLY_SOLVABLE;
|
||||
} else if (hasNonFreeAgents) {
|
||||
return ConstraintDegree.NOT_SOLVABLE;
|
||||
} else {
|
||||
return ConstraintDegree.SOLVABLE;
|
||||
}
|
||||
}
|
||||
|
||||
findClusterForIsolated(constraint) {
|
||||
for (let i = this.clusters.length - 1; i >= 0; i--) {
|
||||
const cluster = this.clusters[i];
|
||||
if (constraint.objects.find(o => cluster.ownObjects.has(o))) {
|
||||
return cluster;
|
||||
}
|
||||
}
|
||||
console.log(`constraint ${constraint.id} can't be solved and will be skipped, most likely it's attached to read only geometry only`);
|
||||
return null;
|
||||
}
|
||||
|
||||
createCluster(constraints = []) {
|
||||
const cluster = new Cluster(this, constraints);
|
||||
this.clusters.push(cluster);
|
||||
return cluster;
|
||||
}
|
||||
|
||||
lock(object) {
|
||||
this.locked.add(object);
|
||||
}
|
||||
|
||||
isLocked = object => {
|
||||
return this.locked.has(object);
|
||||
};
|
||||
|
||||
schedule(constr, cluster) {
|
||||
this.scheduled.set(constr, cluster);
|
||||
}
|
||||
|
||||
isScheduled = constr => {
|
||||
return this.scheduled.has(constr);
|
||||
};
|
||||
|
||||
prepare(interactiveLock) {
|
||||
const schedule = queue => {
|
||||
|
||||
for (let constr of queue) {
|
||||
|
||||
if (this.isScheduled(constr)) {
|
||||
continue; // we're cool - solved as a part of construction cluster
|
||||
}
|
||||
|
||||
let clusterConstraints = findConstructionCluster(constr, this.isScheduled);
|
||||
clusterConstraints.forEach((c, i) => {
|
||||
if (this.constraintDegree(c) === ConstraintDegree.NOT_SOLVABLE) {
|
||||
console.log('isolation detected for constraint ' + constr.id);
|
||||
const neighbour = this.findClusterForIsolated(c);
|
||||
if (!neighbour) {
|
||||
console.warn('unable to resolve isolation for constraint ' + constr.id);
|
||||
return;
|
||||
}
|
||||
neighbour.add(c);
|
||||
clusterConstraints[i] = null;
|
||||
}
|
||||
});
|
||||
clusterConstraints = clusterConstraints.filter(c => c !== null);
|
||||
if (clusterConstraints.length) {
|
||||
this.createCluster(clusterConstraints);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.cleanup();
|
||||
|
||||
interactiveLock.forEach(l => this.locked.add(l));
|
||||
this.system.locked.forEach(l => this.locked.add(l));
|
||||
|
||||
this.system.constraints.forEach(c => c.objects.forEach(o => o.visitChildren( c => {
|
||||
this.internalObjects.add(c);
|
||||
if (this.isLocked(c)) {
|
||||
this.decayedObjects.add(o);
|
||||
}
|
||||
} )) );
|
||||
|
||||
const queue = [...this.system.constraints];
|
||||
const constraintRank = constr => {
|
||||
const pureSEAC = !constr.objects.find(o => o instanceof GCPoint);
|
||||
const hasLocks = !!constr.objects.find(o => this.locked.has(o) || this.decayedObjects.has(o));
|
||||
const referToInternals = !!constr.objects.find(o => this.internalObjects.has(o));
|
||||
let rank = 0;
|
||||
if (referToInternals) {
|
||||
rank += 1000;
|
||||
}
|
||||
if (!pureSEAC) {
|
||||
rank += 100
|
||||
}
|
||||
if (!hasLocks) {
|
||||
rank += 10;
|
||||
}
|
||||
return rank;
|
||||
};
|
||||
queue.sort((a,b) => constraintRank(a) - constraintRank(b));
|
||||
|
||||
schedule(queue);
|
||||
|
||||
console.log("SOLVER SCHEDULING RESULTS:");
|
||||
console.dir(this.clusters);
|
||||
|
||||
this.clusterTransactions = this.clusters.map(cluster => cluster.startTransaction());
|
||||
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
this.locked.clear();
|
||||
this.scheduled.clear();
|
||||
this.internalObjects.clear();
|
||||
this.decayedObjects.clear();
|
||||
this.clusters = [];
|
||||
this.clusterTransactions = undefined;
|
||||
}
|
||||
|
||||
relaxObjects() {
|
||||
this.clusterTransactions.forEach(ct => {
|
||||
ct.cluster.ownObjects.forEach(o => {
|
||||
if (o instanceof GCCircle) {
|
||||
if (o.r.get() <= 5) {
|
||||
o.r.set(20);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
solve = rough => {
|
||||
this.relaxObjects();
|
||||
this.clusterTransactions.forEach(t => t.solve(rough));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Cluster {
|
||||
|
||||
constructor(systemTransaction, constraints) {
|
||||
this.systemTransaction = systemTransaction;
|
||||
this.constraints = [];
|
||||
this.ownObjects = new Set();
|
||||
constraints.forEach(c => this.add(c));
|
||||
}
|
||||
|
||||
consumeObject(o) {
|
||||
this.systemTransaction.lock(o);
|
||||
this.ownObjects.add(o);
|
||||
}
|
||||
|
||||
add(constraint) {
|
||||
this.systemTransaction.schedule(constraint, this);
|
||||
constraint.objects.forEach(o => {
|
||||
if (!this.systemTransaction.isLocked(o)) {
|
||||
this.consumeObject(o);
|
||||
o.visitChildren(c => {
|
||||
if (!this.systemTransaction.isLocked(c)) {
|
||||
this.consumeObject(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
this.constraints.push(constraint);
|
||||
}
|
||||
|
||||
get capacity() {
|
||||
return this.constraints.length;
|
||||
}
|
||||
|
||||
startTransaction() {
|
||||
|
||||
const residuals = [];
|
||||
const solverConstrs = [];
|
||||
const transState = new TransactionState();
|
||||
|
||||
this.constraints.forEach(c => c.collectResiduals(residuals));
|
||||
|
||||
for (let i = 0; i < residuals.length; ++i) {
|
||||
|
||||
const [fn, gcParams, constants] = residuals[i];
|
||||
|
||||
const solverParams = gcParams.map(gcParam => {
|
||||
const solverParam = transState.createSolverParam(gcParam);
|
||||
|
||||
solverParam.constant = !this.ownObjects.has(gcParam.object);
|
||||
return solverParam;
|
||||
});
|
||||
|
||||
const constr = fn(solverParams, constants);
|
||||
solverConstrs.push(constr);
|
||||
}
|
||||
const solver = prepare(solverConstrs);
|
||||
return new ClusterTransaction(solver, transState, this);
|
||||
}
|
||||
}
|
||||
|
||||
class TransactionState {
|
||||
|
||||
paramMap = new Map();
|
||||
|
||||
createSolverParam(gcParam) {
|
||||
let solverParam = this.paramMap.get(gcParam);
|
||||
if (!solverParam) {
|
||||
solverParam = new Param(gcParam.get());
|
||||
this.paramMap.set(gcParam, solverParam);
|
||||
}
|
||||
return solverParam;
|
||||
}
|
||||
}
|
||||
|
||||
class ClusterTransaction {
|
||||
|
||||
constructor(solver, state, cluster) {
|
||||
this.solver = solver;
|
||||
this.state = state;
|
||||
this.cluster = cluster;
|
||||
}
|
||||
|
||||
solve(rough) {
|
||||
this.state.paramMap.forEach((solverParam, gcParam) => {
|
||||
solverParam.reset(gcParam.get());
|
||||
});
|
||||
|
||||
this.solver.solveSystem(rough);
|
||||
|
||||
this.state.paramMap.forEach((solverParam, gcParam) => {
|
||||
if (!solverParam.constant) {
|
||||
gcParam.set(solverParam.get());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
import {Param} from "./solver";
|
||||
import {Generator} from "../id-generator";
|
||||
|
||||
export class ContractibleObject {
|
||||
|
|
@ -6,28 +5,46 @@ export class ContractibleObject {
|
|||
constraints = [];
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
createParam(value) {
|
||||
return new GCParam(this, value);
|
||||
this.id = Generator.genID();
|
||||
}
|
||||
|
||||
collectParams(out) {
|
||||
this.visitParams(p => out.push(p));
|
||||
}
|
||||
|
||||
init() {};
|
||||
|
||||
visitParams() {};
|
||||
|
||||
visitChildren() {};
|
||||
|
||||
traverse(visitor) {
|
||||
visitor(this);
|
||||
}
|
||||
|
||||
write() {
|
||||
const out = [];
|
||||
this.visitChildren(c => out.push(c.id));
|
||||
return out;
|
||||
}
|
||||
|
||||
read(data, resolve) {
|
||||
this.init.apply(this, data.map(resolve));
|
||||
}
|
||||
}
|
||||
|
||||
export class GCPoint extends ContractibleObject {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.x = this.createParam(0);
|
||||
this.y = this.createParam(0);
|
||||
static TYPE = 'GCPoint';
|
||||
|
||||
static newInstance(x = 0, y = 0) {
|
||||
return new GCPoint().init(new GCParam(x), new GCParam(y));
|
||||
}
|
||||
|
||||
init(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
visitParams(visitor) {
|
||||
|
|
@ -35,14 +52,35 @@ export class GCPoint extends ContractibleObject {
|
|||
visitor(this.y);
|
||||
}
|
||||
|
||||
visitChildren(visitor) {
|
||||
visitor(this.x);
|
||||
visitor(this.y);
|
||||
}
|
||||
|
||||
traverse(visitor) {
|
||||
super.traverse(visitor);
|
||||
this.x.traverse(visitor);
|
||||
this.y.traverse(visitor);
|
||||
}
|
||||
|
||||
write() {
|
||||
return [this.x.id, this.y.id];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class GCLine extends ContractibleObject {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.ang = this.createParam(0);
|
||||
this.w = this.createParam(0);
|
||||
static TYPE = 'GCLine';
|
||||
|
||||
static newInstance(ang = 0, w = 0) {
|
||||
return new GCLine().init(new GCParam(ang), new GCParam(w));
|
||||
}
|
||||
|
||||
init(ang, w) {
|
||||
this.ang = ang;
|
||||
this.w = w;
|
||||
return this;
|
||||
}
|
||||
|
||||
visitParams(visitor) {
|
||||
|
|
@ -50,14 +88,31 @@ export class GCLine extends ContractibleObject {
|
|||
visitor(this.w);
|
||||
}
|
||||
|
||||
visitChildren(visitor) {
|
||||
visitor(this.ang);
|
||||
visitor(this.w);
|
||||
}
|
||||
|
||||
traverse(visitor) {
|
||||
super.traverse(visitor);
|
||||
this.ang.traverse(visitor)
|
||||
this.w.traverse(visitor)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class GCCircle extends ContractibleObject {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.c = new GCPoint();
|
||||
this.r = this.createParam(0);
|
||||
static TYPE = 'GCCircle';
|
||||
|
||||
static newInstance(x, y, r) {
|
||||
return GCCircle().init(new GCPoint(x, y), new GCParam(r))
|
||||
}
|
||||
|
||||
init(c, r) {
|
||||
this.c = c;
|
||||
this.r = r;
|
||||
return this;
|
||||
}
|
||||
|
||||
visitParams(visitor) {
|
||||
|
|
@ -67,14 +122,27 @@ export class GCCircle extends ContractibleObject {
|
|||
|
||||
visitChildren(visitor) {
|
||||
visitor(this.c);
|
||||
visitor(this.r);
|
||||
}
|
||||
|
||||
traverse(visitor) {
|
||||
visitor(this);
|
||||
this.c.traverse(visitor);
|
||||
this.r.traverse(visitor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class GCParam {
|
||||
export class GCParam extends ContractibleObject {
|
||||
|
||||
constructor(object, value) {
|
||||
this.object = object;
|
||||
static TYPE = 'GCParam';
|
||||
|
||||
static newInstance(value = 0) {
|
||||
return new GCParam(value);
|
||||
}
|
||||
|
||||
constructor(value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
|
@ -86,4 +154,28 @@ export class GCParam {
|
|||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
visitChildren(visitor) {
|
||||
}
|
||||
|
||||
visitParams(visitor) {
|
||||
visitor(this);
|
||||
}
|
||||
|
||||
write() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
read(data) {
|
||||
this.value = data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const GC_TYPES = {
|
||||
|
||||
[GCParam.TYPE]: GCParam,
|
||||
[GCPoint.TYPE]: GCPoint,
|
||||
[GCLine.TYPE]: GCLine,
|
||||
[GCCircle.TYPE]: GCCircle
|
||||
|
||||
};
|
||||
348
web/app/sketcher/constr/polynomial.js
Normal file
348
web/app/sketcher/constr/polynomial.js
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
import {eqEps} from "../../brep/geom/tolerance";
|
||||
import {sq} from "../../math/math";
|
||||
|
||||
export class Polynomial {
|
||||
|
||||
monomials = [];
|
||||
constant = 0;
|
||||
|
||||
constructor(constant) {
|
||||
this.constant = constant;
|
||||
}
|
||||
|
||||
term(p, fn) {
|
||||
this.monomials[this.monomials.length - 1].addParam(p, fn);
|
||||
return this;
|
||||
}
|
||||
|
||||
monomial(k = 1) {
|
||||
this.monomials.push(new Monomial(k));
|
||||
return this;
|
||||
}
|
||||
|
||||
eliminate(param, value) {
|
||||
for (let m of this.monomials) {
|
||||
for (let i = 0; i < m.terms.length; ++i) {
|
||||
if (m.terms[i].param === param) {
|
||||
m.eliminate(i, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
substitute(param, toParam, dotConstant) {
|
||||
for (let m of this.monomials) {
|
||||
for (let i = 0; i < m.terms.length; ++i) {
|
||||
if (m.terms[i].param === param) {
|
||||
m.substitute(i, toParam, dotConstant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
linerSub(param, toParam, b, c) {
|
||||
// for (let m of this.monomials) {
|
||||
// for (let i = 0; i < m.terms.length; ++i) {
|
||||
// if (m.terms[i].param === param) {
|
||||
// m.substitute(i, toParam, dotConstant);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
compact() {
|
||||
for (let i = 0; i < this.monomials.length; ++i) {
|
||||
const m1 = this.monomials[i];
|
||||
if (m1 === null) {
|
||||
continue;
|
||||
}
|
||||
for (let j = i + 1; j < this.monomials.length; ++j) {
|
||||
const m2 = this.monomials[j];
|
||||
if (m2 === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m1.equalVars(m2)) {
|
||||
m1.constant += m2.constant;
|
||||
this.monomials[j] = null;
|
||||
}
|
||||
}
|
||||
if (eqEps(m1.constant, 0)) {
|
||||
this.monomials[i] = null;
|
||||
} else if (m1.terms.length === 0) {
|
||||
this.constant += m1.constant;
|
||||
this.monomials[i] = null;
|
||||
}
|
||||
}
|
||||
this.monomials = this.monomials.filter(m => m !== null);
|
||||
}
|
||||
|
||||
get isLinear() {
|
||||
for (let m of this.monomials) {
|
||||
if (m.terms.length !== 1 || m.terms[0].fn.degree !== 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
value(valueFn = GET_VALUE) {
|
||||
let res = this.constant;
|
||||
for (let m of this.monomials) {
|
||||
res += m.value(valueFn);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
asResidual() {
|
||||
|
||||
const paramsSet = new Set();
|
||||
|
||||
for (let m of this.monomials) {
|
||||
for (let t of m.terms) {
|
||||
paramsSet.add(t.param.solverParam);
|
||||
}
|
||||
}
|
||||
|
||||
const params = Array.from(paramsSet);
|
||||
|
||||
const solverValue = p => p.solverParam.get();
|
||||
|
||||
return {
|
||||
|
||||
params,
|
||||
|
||||
error: () => this.value(solverValue),
|
||||
|
||||
gradient: out => {
|
||||
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
|
||||
out[i] = 0;
|
||||
|
||||
for (let m of this.monomials) {
|
||||
out[i] += m.differentiate(params[i].objectParam, solverValue);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
toString() {
|
||||
|
||||
return this.monomials.map(m => {
|
||||
|
||||
let out = '';
|
||||
if (m.constant === 1) {
|
||||
out += '+';
|
||||
} else if (m.constant === -1) {
|
||||
out += '-';
|
||||
} else {
|
||||
out += (m.constant >= 0 ? '+' : '') + m.constant.toFixed(2);
|
||||
if (m.terms.length) {
|
||||
out += '*';
|
||||
}
|
||||
}
|
||||
|
||||
out += m.terms.map(t => {
|
||||
let out = 'X' + t.param.id;
|
||||
if (t.fn.degree === 1) {
|
||||
|
||||
} else if (t.fn.degree !== Infinity) {
|
||||
out += t.fn.id;
|
||||
} else {
|
||||
out = t.fn.id + '(' + out + ')';
|
||||
}
|
||||
return out;
|
||||
}).join('*');
|
||||
|
||||
return out;
|
||||
}
|
||||
).join(' ') + (this.constant >= 0 ? ' + ' : ' ') + this.constant.toFixed(2);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class Monomial {
|
||||
|
||||
terms = [];
|
||||
constant = 1;
|
||||
|
||||
constructor(constant) {
|
||||
this.constant = constant;
|
||||
}
|
||||
|
||||
addParam(param, fn) {
|
||||
this.terms.push({param, fn});
|
||||
this.terms.sort(t => t.param.id);
|
||||
}
|
||||
|
||||
eliminate(i, value) {
|
||||
const fn = this.terms[i].fn;
|
||||
this.constant *= fn.apply(value);
|
||||
this.terms.splice(i, 1);
|
||||
}
|
||||
|
||||
substitute(i, toParam, dotConstant) {
|
||||
this.constant *= dotConstant;
|
||||
let wasMerge = false;
|
||||
for (let i = 0; i < this.terms.length; ++i) {
|
||||
const merger = this.terms[i];
|
||||
if (!merger) {
|
||||
continue;
|
||||
}
|
||||
for (let j = i + 1; j < this.terms.length; ++j) {
|
||||
const term = this.terms[j];
|
||||
if (merger.param === term.param) {
|
||||
let mergedFn = merger.fn.merge(term.fn);
|
||||
if (mergedFn) {
|
||||
merger.fn = mergedFn;
|
||||
this.terms[j] = null;
|
||||
wasMerge = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wasMerge) {
|
||||
this.terms = this.terms.filter(t => t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
equalVars(other) {
|
||||
if (this.terms.length !== other.terms.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.terms.length; ++i) {
|
||||
const t1 = this.terms[i];
|
||||
const t2 = other.terms[i];
|
||||
if (t1.fn.id !== t2.fn.id || t1.param.id !== t2.param.id) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
differentiate(partialParam, valueFn = GET_VALUE) {
|
||||
|
||||
let cnst = this.constant;
|
||||
|
||||
let diffProduct = 0;
|
||||
let freeProduct = 1;
|
||||
|
||||
for (let term of this.terms) {
|
||||
const pVal = valueFn(term.param);
|
||||
const d0 = term.fn.apply(pVal);
|
||||
if (partialParam === term.param) {
|
||||
const d1 = term.fn.derivative1(pVal);
|
||||
diffProduct = diffProduct*d0 + freeProduct * d1;
|
||||
freeProduct *= d0;
|
||||
} else {
|
||||
cnst *= d0;
|
||||
}
|
||||
}
|
||||
|
||||
return cnst * diffProduct;
|
||||
}
|
||||
|
||||
value(valueFn) {
|
||||
let res = this.constant;
|
||||
for (let t of this.terms) {
|
||||
res *= t.fn.apply(valueFn(t.param));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
export class ToThePowerFunction {
|
||||
|
||||
degree = 1;
|
||||
|
||||
static get(degree) {
|
||||
switch (degree) {
|
||||
case 0: return POW_0_FN;
|
||||
case 1: return POW_1_FN;
|
||||
case 2: return POW_2_FN;
|
||||
case 3: return POW_3_FN;
|
||||
case 4: return POW_4_FN;
|
||||
default: return new ToThePowerFunction(degree, x => {
|
||||
let val = 1;
|
||||
for (let i = 0; i < degree; ++i) {
|
||||
val *= x;
|
||||
}
|
||||
return val
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
constructor(degree, fn, d1) {
|
||||
this.fn = fn;
|
||||
this.d1 = d1;
|
||||
this.id = '^' + degree;
|
||||
}
|
||||
|
||||
apply(x) {
|
||||
return this.fn(x);
|
||||
}
|
||||
|
||||
merge(fn) {
|
||||
if (fn.constructor.name === this.constructor.name) {
|
||||
return ToThePowerFunction.get(fn.degree + this.degree);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
derivative1(x) {
|
||||
return this.d1(x)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export class FreeFunction {
|
||||
|
||||
fn;
|
||||
|
||||
constructor(fn, d1, id) {
|
||||
this.fn = fn;
|
||||
this.d1 = d1;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
apply(x) {
|
||||
return this.fn(x);
|
||||
}
|
||||
|
||||
get degree() {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
merge(fn) {
|
||||
return null;
|
||||
}
|
||||
|
||||
derivative1(x) {
|
||||
return this.d1(x)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const GET_VALUE = param => param.get();
|
||||
|
||||
export const POW_0_FN = new ToThePowerFunction(0, x => 1, x => 0);
|
||||
export const POW_1_FN = new ToThePowerFunction(1, x => x, x => 1);
|
||||
export const POW_2_FN = new ToThePowerFunction(2, x => x*x, x => 2*x);
|
||||
export const POW_3_FN = new ToThePowerFunction(3, x => x*x*x, x => 3*x*x);
|
||||
export const POW_4_FN = new ToThePowerFunction(3, x => x*x*x*x, x => 4*x*x*x);
|
||||
|
||||
export const COS_FN = new FreeFunction(x => Math.cos(x), x => -Math.sin(x), 'cos');
|
||||
export const SIN_FN = new FreeFunction(x => Math.sin(x), x => Math.cos(x), 'sin');
|
||||
|
||||
|
||||
|
|
@ -1,6 +1,19 @@
|
|||
import {NumericGradient} from "./solverConstraints";
|
||||
import {sq} from "../../math/math";
|
||||
|
||||
export function R_Equal(params, [value]) {
|
||||
|
||||
return {
|
||||
|
||||
params,
|
||||
|
||||
error: () => params[0].get() - value,
|
||||
|
||||
gradient: out => {
|
||||
out[0] = 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function R_TangentLC(params, [inverted]) {
|
||||
|
||||
const ANG = 0;
|
||||
|
|
|
|||
|
|
@ -7,14 +7,15 @@ import {dog_leg} from '../../math/optim'
|
|||
import {newVector} from '../../math/vec';
|
||||
|
||||
/** @constructor */
|
||||
function Param(value) {
|
||||
function Param(value, objectParam) {
|
||||
this.reset(value);
|
||||
this.constant = false;
|
||||
this.j = -1;
|
||||
this.objectParam = objectParam;
|
||||
}
|
||||
|
||||
Param.prototype.reset = function(value) {
|
||||
this.value = value;
|
||||
this.set(value);
|
||||
this.constant = false;
|
||||
this.j = -1;
|
||||
};
|
||||
|
||||
Param.prototype.set = function(value) {
|
||||
|
|
|
|||
5
web/app/sketcher/generators/boundaryGenerator.js
Normal file
5
web/app/sketcher/generators/boundaryGenerator.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
|
||||
export function boundaryGenerator() {
|
||||
|
||||
}
|
||||
|
|
@ -16,9 +16,10 @@ import exportTextData from 'gems/exportTextData';
|
|||
import NurbsCurve from '../brep/geom/curves/nurbsCurve';
|
||||
import {NurbsObject} from './shapes/nurbsObject';
|
||||
import {System} from './system';
|
||||
import {AlgNumConstraint} from "./constr/ANConstraints";
|
||||
|
||||
const Types = {
|
||||
END_POINT : 'TCAD.TWO.EndPoint',
|
||||
POINT : 'TCAD.TWO.EndPoint',
|
||||
SEGMENT : 'TCAD.TWO.Segment',
|
||||
ARC : 'TCAD.TWO.Arc',
|
||||
CIRCLE : 'TCAD.TWO.Circle',
|
||||
|
|
@ -51,22 +52,22 @@ IO.prototype._loadSketch = function(sketch) {
|
|||
|
||||
this.cleanUpData();
|
||||
|
||||
var index = {};
|
||||
const index = {};
|
||||
|
||||
function endPoint(p) {
|
||||
var id = p[0];
|
||||
var ep = index[id];
|
||||
const [id, [xref, x], [yref, y]] = p;
|
||||
let ep = index[id];
|
||||
if (ep !== undefined) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
ep = new EndPoint(p[1][1], p[2][1]);
|
||||
index[p[1][0]] = ep._x;
|
||||
index[p[2][0]] = ep._y;
|
||||
ep = new EndPoint(x, y);
|
||||
index[xref] = ep.params.x;
|
||||
index[yref] = ep.params.y;
|
||||
index[id] = ep;
|
||||
return ep;
|
||||
}
|
||||
|
||||
var layerIdGen = 0;
|
||||
let layerIdGen = 0;
|
||||
function getLayer(viewer, name) {
|
||||
if (name === undefined) {
|
||||
name = "layer_" + layerIdGen++;
|
||||
|
|
@ -74,7 +75,7 @@ IO.prototype._loadSketch = function(sketch) {
|
|||
if (name === viewer.dimLayer.name) {
|
||||
return viewer.dimLayer;
|
||||
}
|
||||
for (var i = 0; i < viewer.layers.length; ++i) {
|
||||
for (let i = 0; i < viewer.layers.length; ++i) {
|
||||
if (name === viewer.layers[i].name) {
|
||||
return viewer.layers[i];
|
||||
}
|
||||
|
|
@ -84,6 +85,7 @@ IO.prototype._loadSketch = function(sketch) {
|
|||
viewer.layers.push(layer);
|
||||
return layer;
|
||||
}
|
||||
const version = sketch.version || 1;
|
||||
var T = Types;
|
||||
var maxEdge = 0;
|
||||
var sketchLayers = sketch['layers'];
|
||||
|
|
@ -93,7 +95,7 @@ IO.prototype._loadSketch = function(sketch) {
|
|||
for (var l = 0; l < sketchLayers.length; ++l) {
|
||||
var ioLayer = sketchLayers[l];
|
||||
var layerName = ioLayer['name'];
|
||||
var boundaryProcessing = layerName == IO.BOUNDARY_LAYER_NAME && boundaryNeedsUpdate;
|
||||
var boundaryProcessing = layerName === IO.BOUNDARY_LAYER_NAME && boundaryNeedsUpdate;
|
||||
var layer = getLayer(this.viewer, layerName);
|
||||
if (!!ioLayer.style) layer.style = ioLayer.style;
|
||||
layer.readOnly = !!ioLayer.readOnly;
|
||||
|
|
@ -111,28 +113,28 @@ IO.prototype._loadSketch = function(sketch) {
|
|||
}
|
||||
|
||||
if (boundaryProcessing) {
|
||||
if (_class === T.SEGMENT && boundary.lines.length == 0) continue;
|
||||
else if (_class === T.ARC && boundary.arcs.length == 0) continue;
|
||||
else if (_class === T.CIRCLE && boundary.circles.length == 0) continue;
|
||||
if (_class === T.SEGMENT && boundary.lines.length === 0) continue;
|
||||
else if (_class === T.ARC && boundary.arcs.length === 0) continue;
|
||||
else if (_class === T.CIRCLE && boundary.circles.length === 0) continue;
|
||||
}
|
||||
|
||||
if (_class === T.SEGMENT) {
|
||||
const points = obj['points'];
|
||||
const a = endPoint(points[0]);
|
||||
const b = endPoint(points[1]);
|
||||
const [aRef, bRef] = obj.points;
|
||||
const a = endPoint(aRef);
|
||||
const b = endPoint(bRef);
|
||||
skobj = new Segment(a, b);
|
||||
} else if (_class === T.END_POINT) {
|
||||
skobj = endPoint(obj['location']);
|
||||
} else if (_class === T.POINT) {
|
||||
skobj = endPoint(obj.location);
|
||||
} else if (_class === T.ARC) {
|
||||
const points = obj['points'];
|
||||
const points = obj.points;
|
||||
const a = endPoint(points[0]);
|
||||
const b = endPoint(points[1]);
|
||||
const c = endPoint(points[2]);
|
||||
skobj = new Arc(a, b, c);
|
||||
} else if (_class === T.CIRCLE) {
|
||||
const c = endPoint(obj['c']);
|
||||
const c = endPoint(obj.c);
|
||||
skobj = new Circle(c);
|
||||
skobj.r.set(obj['r']);
|
||||
skobj.r.set(obj.r);
|
||||
} else if (_class === T.ELLIPSE) {
|
||||
const ep1 = endPoint(obj['ep1']);
|
||||
const ep2 = endPoint(obj['ep2']);
|
||||
|
|
@ -214,8 +216,12 @@ IO.prototype._loadSketch = function(sketch) {
|
|||
if (sketchConstraints !== undefined) {
|
||||
for (var i = 0; i < sketchConstraints.length; ++i) {
|
||||
try {
|
||||
const c = this.parseConstr(sketchConstraints[i], index);
|
||||
this.viewer.parametricManager._add(c);
|
||||
if (version > 1) {
|
||||
this.viewer.parametricManager.algnNumSystem.addConstraint(AlgNumConstraint.read(sketchConstraints[i], index));
|
||||
} else {
|
||||
const c = this.parseConstr(sketchConstraints[i], index);
|
||||
this.viewer.parametricManager._add(c);
|
||||
}
|
||||
} catch (msg) {
|
||||
console.info("Skipping. " + msg);
|
||||
}
|
||||
|
|
@ -232,7 +238,7 @@ IO.prototype.linkEndPoints = function(objects) {
|
|||
const index = HashTable.forVector2d();
|
||||
for (let obj of objects) {
|
||||
obj.accept((o) => {
|
||||
if (o._class == Types.END_POINT) {
|
||||
if (o._class == Types.POINT) {
|
||||
const equalPoint = index.get(o);
|
||||
if (equalPoint == null) {
|
||||
index.put(o, o);
|
||||
|
|
@ -336,9 +342,9 @@ IO.prototype.cleanUpData = function() {
|
|||
IO.prototype._serializeSketch = function(metadata) {
|
||||
var sketch = {};
|
||||
//sketch.boundary = boundary;
|
||||
sketch['layers'] = [];
|
||||
sketch.layers = [];
|
||||
function point(p) {
|
||||
return [ p.id, [p._x.id, p.x], [p._y.id, p.y] ];
|
||||
return [ p.id, [p.params.x.id, p.x], [p.params.y.id, p.y] ];
|
||||
}
|
||||
var T = Types;
|
||||
var toSave = [this.viewer.dimLayers, this.viewer.layers];
|
||||
|
|
@ -346,76 +352,74 @@ IO.prototype._serializeSketch = function(metadata) {
|
|||
var layers = toSave[t];
|
||||
for (var l = 0; l < layers.length; ++l) {
|
||||
var layer = layers[l];
|
||||
var toLayer = {'name' : layer.name, style : layer.style, readOnly: layer.readOnly, 'data' : []};
|
||||
sketch['layers'].push(toLayer);
|
||||
var toLayer = {name : layer.name, style : layer.style, readOnly: layer.readOnly, data : []};
|
||||
sketch.layers.push(toLayer);
|
||||
for (var i = 0; i < layer.objects.length; ++i) {
|
||||
var obj = layer.objects[i];
|
||||
var to = {'id': obj.id, '_class': obj._class, role: obj.role};
|
||||
var to = {id: obj.id, _class: obj._class, role: obj.role};
|
||||
if (obj.aux) to.aux = obj.aux;
|
||||
if (obj.edge !== undefined) to.edge = obj.edge;
|
||||
toLayer['data'].push(to);
|
||||
toLayer.data.push(to);
|
||||
if (obj._class === T.SEGMENT) {
|
||||
to['points'] = [point(obj.a), point(obj.b)];
|
||||
} else if (obj._class === T.END_POINT) {
|
||||
to['location'] = point(obj);
|
||||
to.points = [point(obj.a), point(obj.b)];
|
||||
} else if (obj._class === T.POINT) {
|
||||
to.location = point(obj);
|
||||
} else if (obj._class === T.ARC) {
|
||||
to['points'] = [point(obj.a), point(obj.b), point(obj.c)];
|
||||
to.points = [point(obj.a), point(obj.b), point(obj.c)];
|
||||
} else if (obj._class === T.CIRCLE) {
|
||||
to['c'] = point(obj.c);
|
||||
to['r'] = obj.r.get();
|
||||
to.c = point(obj.c);
|
||||
to.r = obj.r.get();
|
||||
} else if (obj._class === T.ELLIPSE) {
|
||||
to['ep1'] = point(obj.ep1);
|
||||
to['ep2'] = point(obj.ep2);
|
||||
to['r'] = obj.r.get();
|
||||
to.ep1 = point(obj.ep1);
|
||||
to.ep2 = point(obj.ep2);
|
||||
to.r = obj.r.get();
|
||||
} else if (obj._class === T.ELL_ARC) {
|
||||
to['ep1'] = point(obj.ep1);
|
||||
to['ep2'] = point(obj.ep2);
|
||||
to['a'] = point(obj.a);
|
||||
to['b'] = point(obj.b);
|
||||
to['r'] = obj.r.get();
|
||||
to.ep1 = point(obj.ep1);
|
||||
to.ep2 = point(obj.ep2);
|
||||
to.a = point(obj.a);
|
||||
to.b = point(obj.b);
|
||||
to.r = obj.r.get();
|
||||
} else if (obj._class === T.BEZIER) {
|
||||
to['a'] = point(obj.a);
|
||||
to['b'] = point(obj.b);
|
||||
to['cp1'] = point(obj.cp1);
|
||||
to['cp2'] = point(obj.cp2);
|
||||
to.a = point(obj.a);
|
||||
to.b = point(obj.b);
|
||||
to.cp1 = point(obj.cp1);
|
||||
to.cp2 = point(obj.cp2);
|
||||
} else if (obj._class === T.DIM || obj._class === T.HDIM || obj._class === T.VDIM) {
|
||||
to['a'] = obj.a.id;
|
||||
to['b'] = obj.b.id;
|
||||
to['flip'] = obj.flip;
|
||||
to.a = obj.a.id;
|
||||
to.b = obj.b.id;
|
||||
to.flip = obj.flip;
|
||||
} else if (obj._class === T.DDIM) {
|
||||
to['obj'] = obj.obj.id;
|
||||
to.obj = obj.obj.id;
|
||||
}
|
||||
const children = nonPointChildren(obj).map(c => c.id);
|
||||
if (children.length != 0) {
|
||||
to['children'] = children;
|
||||
if (children.length !== 0) {
|
||||
to.children = children;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var constrs = sketch['constraints'] = [];
|
||||
var subSystems = this.viewer.parametricManager.system.subSystems;
|
||||
for (var j = 0; j < subSystems.length; j++) {
|
||||
var sub = subSystems[j];
|
||||
for (i = 0; i < sub.constraints.length; ++i) {
|
||||
if (!sub.constraints[i].aux) {
|
||||
constrs.push(this.serializeConstr(sub.constraints[i]));
|
||||
}
|
||||
sketch.constraints = [];
|
||||
const systemConstraints = this.viewer.parametricManager.algnNumSystem.constraints;
|
||||
for (let sc of systemConstraints) {
|
||||
if (!sc.internal) {
|
||||
sketch.constraints.push(sc.write());
|
||||
}
|
||||
}
|
||||
|
||||
var constantDefinition = this.viewer.params.constantDefinition;
|
||||
if (constantDefinition !== undefined && constantDefinition != null && !/^\s*$/.test(constantDefinition)) {
|
||||
sketch['constants'] = constantDefinition;
|
||||
sketch.constants = constantDefinition;
|
||||
}
|
||||
sketch.metadata = metadata;
|
||||
sketch.version = 2;
|
||||
return sketch;
|
||||
};
|
||||
|
||||
function nonPointChildren(obj){
|
||||
const children = [];
|
||||
obj.accept((o) => {
|
||||
if (o._class !== Types.END_POINT) {
|
||||
if (o._class !== Types.POINT) {
|
||||
children.push(o);
|
||||
}
|
||||
return true;
|
||||
|
|
@ -440,9 +444,6 @@ IO.prototype.parseConstr = function (c, index) {
|
|||
return constrCreate(find, ps);
|
||||
};
|
||||
|
||||
IO.prototype.serializeConstr = function (c) {
|
||||
return c.serialize();
|
||||
};
|
||||
|
||||
function _format(str, args) {
|
||||
if (args.length == 0) return str;
|
||||
|
|
@ -499,7 +500,7 @@ function BBox() {
|
|||
if (obj._class === T.SEGMENT) {
|
||||
this.checkBounds(obj.a.x, obj.a.y);
|
||||
this.checkBounds(obj.b.x, obj.b.y);
|
||||
} else if (obj._class === T.END_POINT) {
|
||||
} else if (obj._class === T.POINT) {
|
||||
this.checkBounds(obj.x, obj.y);
|
||||
} else if (obj._class === T.ARC) {
|
||||
this.checkCircBounds(obj.c.x, obj.c.y, obj.r.get());
|
||||
|
|
@ -509,7 +510,7 @@ function BBox() {
|
|||
this.checkCircBounds(obj.centerX, obj.centerY, Math.max(obj.radiusX, obj.radiusY));
|
||||
} else if (obj) {
|
||||
obj.accept((o) => {
|
||||
if (o._class == T.END_POINT) {
|
||||
if (o._class == T.POINT) {
|
||||
this.checkBounds(o.x, o.y);
|
||||
}
|
||||
return true;
|
||||
|
|
@ -589,7 +590,7 @@ IO.prototype.svgExport = function () {
|
|||
out.fline('<g id="$" fill="$" stroke="$" stroke-width="$">', [layer.name, "none", color, '2']);
|
||||
for (var i = 0; i < layer.objects.length; ++i) {
|
||||
var obj = layer.objects[i];
|
||||
if (obj._class !== T.END_POINT) bbox.check(obj);
|
||||
if (obj._class !== T.POINT) bbox.check(obj);
|
||||
if (obj._class === T.SEGMENT) {
|
||||
out.fline('<line x1="$" y1="$" x2="$" y2="$" />', [obj.a.x, obj.a.y, obj.b.x, obj.b.y]);
|
||||
} else if (obj._class === T.ARC) {
|
||||
|
|
@ -686,7 +687,7 @@ IO.prototype.dxfExport = function () {
|
|||
var layer = toExport[l];
|
||||
for (i = 0; i < layer.objects.length; ++i) {
|
||||
var obj = layer.objects[i];
|
||||
if (obj._class === T.END_POINT) {
|
||||
if (obj._class === T.POINT) {
|
||||
out.line("0");
|
||||
out.line("POINT");
|
||||
out.line("8");
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class ParametricManager {
|
|||
constructor(viewer) {
|
||||
this.viewer = viewer;
|
||||
this.system = new System();
|
||||
this.seacSystem = new SEACSystem();
|
||||
this.algnNumSystem = new AlgNumSubSystem();
|
||||
this.constantTable = {};
|
||||
|
||||
this.viewer.params.define('constantDefinition', null);
|
||||
|
|
@ -23,55 +23,76 @@ class ParametricManager {
|
|||
this.externalConstantResolver = null;
|
||||
this.messageSink = msg => alert(msg);
|
||||
|
||||
setTimeout(() => {
|
||||
|
||||
let s1 = viewer.addSegment(100, 100, 300, 300, viewer.activeLayer);
|
||||
let s2 = viewer.addSegment(200, 100, 400, 300, viewer.activeLayer);
|
||||
let c1 = new Circle(new EndPoint(500, 500));
|
||||
c1.r.set(500);
|
||||
viewer.add(c1, viewer.activeLayer);
|
||||
let c2 = new Circle(new EndPoint(0, 0));
|
||||
c2.r.set(50);
|
||||
viewer.add(c2, viewer.activeLayer);
|
||||
|
||||
this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.TangentLC, [s1, c1], {
|
||||
inverted: false
|
||||
}));
|
||||
this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.TangentLC, [s2, c1], {
|
||||
inverted: true
|
||||
}));
|
||||
|
||||
this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.TangentLC, [s1, c2], {
|
||||
inverted: false
|
||||
}));
|
||||
this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.TangentLC, [s2, c2], {
|
||||
inverted: true
|
||||
}));
|
||||
|
||||
this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.PointOnLine, [s1.a, s1]));
|
||||
this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.PointOnLine, [s1.b, s1]));
|
||||
|
||||
|
||||
this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.PointOnLine, [s2.a, s2]));
|
||||
this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.PointOnLine, [s2.b, s2]));
|
||||
|
||||
this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.DistancePP, [s1.a, s1.b], {
|
||||
distance: 350
|
||||
}));
|
||||
|
||||
|
||||
this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.DistancePP, [s2.a, s2.b], {
|
||||
distance: 500
|
||||
}));
|
||||
|
||||
this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.DistancePP, [c1.c, c2.c], {
|
||||
distance: 700
|
||||
}));
|
||||
|
||||
|
||||
this.refresh();
|
||||
|
||||
});
|
||||
// setTimeout(() => {
|
||||
//
|
||||
// let s1 = viewer.addSegment(-100, 0, -100, 600, viewer.activeLayer);
|
||||
// let s2 = viewer.addSegment(700, 0, 700, 600, viewer.activeLayer);
|
||||
//
|
||||
// let s3 = viewer.addSegment(0, -100, 600, -100, viewer.activeLayer);
|
||||
// let s4 = viewer.addSegment(0, 700, 600, 700, viewer.activeLayer);
|
||||
//
|
||||
// const newCircle = (cx, cy) => {
|
||||
// let c1 = new Circle(new EndPoint(cx, cy));
|
||||
// c1.r.set(100);
|
||||
// viewer.add(c1, viewer.activeLayer);
|
||||
// return c1;
|
||||
// };
|
||||
//
|
||||
// const c1 = newCircle(600, 600);
|
||||
//
|
||||
// let c2 = newCircle(0, 0);
|
||||
//
|
||||
//
|
||||
// let c3 = newCircle(600, 0);
|
||||
// let c4 = newCircle(0, 600);
|
||||
//
|
||||
// //
|
||||
// // this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.TangentLC, [s1, c4], {
|
||||
// // inverted: true
|
||||
// // }));
|
||||
// // this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.TangentLC, [s1, c2], {
|
||||
// // inverted: true
|
||||
// // }));
|
||||
// // this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.TangentLC, [s2, c1], {
|
||||
// // inverted: false
|
||||
// // }));
|
||||
// // this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.TangentLC, [s2, c3], {
|
||||
// // inverted: false
|
||||
// // }));
|
||||
// //
|
||||
// // this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.TangentLC, [s4, c4], {
|
||||
// // inverted: true
|
||||
// // }));
|
||||
// //
|
||||
// // this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.TangentLC, [s4, c1], {
|
||||
// // inverted: true
|
||||
// // }));
|
||||
// //
|
||||
// //
|
||||
// // this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.TangentLC, [s3, c2], {
|
||||
// // inverted: false
|
||||
// // }));
|
||||
// //
|
||||
// // this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.TangentLC, [s3, c3], {
|
||||
// // inverted: false
|
||||
// // }));
|
||||
//
|
||||
//
|
||||
//
|
||||
// //
|
||||
// // this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.DistancePP, [s1.a, s1.b], {
|
||||
// // distance: 350
|
||||
// // }));
|
||||
//
|
||||
//
|
||||
// // this.seacSystem.addConstraint(new SEACConstraint(ConstraintDefinitions.DistancePP, [s2.a, s2.b], {
|
||||
// // distance: 500
|
||||
// // }));
|
||||
//
|
||||
//
|
||||
// this.refresh();
|
||||
//
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -79,8 +100,8 @@ class ParametricManager {
|
|||
return this.system.subSystems;
|
||||
}
|
||||
|
||||
addSEAC(constr) {
|
||||
this.seacSystem.addConstraint(constr);
|
||||
addAlgNum(constr) {
|
||||
this.algnNumSystem.addConstraint(constr);
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
|
|
@ -336,7 +357,14 @@ ParametricManager.prototype.tangent = function(objs) {
|
|||
this.add(new Constraints.CurveTangent(lines[0], curves[0]));
|
||||
} else {
|
||||
const arcs = fetch.generic(objs, ['TCAD.TWO.Arc', 'TCAD.TWO.Circle'], 1);
|
||||
this.addSEAC(new TangentLC(lines[0], arcs[0], falses));
|
||||
|
||||
this.addAlgNum(
|
||||
new AlgNumConstraint(ConstraintDefinitions.TangentLC, [lines[0], arcs[0]], {
|
||||
inverted: false
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -537,10 +565,21 @@ ParametricManager.prototype.findCoincidentConstraint = function(point1, point2)
|
|||
};
|
||||
|
||||
ParametricManager.prototype.coincident = function(objs) {
|
||||
if (objs.length == 0) return;
|
||||
this.linkObjects(objs);
|
||||
this.solve();
|
||||
this.viewer.refresh();
|
||||
|
||||
const [first, ...others] = objs;
|
||||
|
||||
for (let obj of others) {
|
||||
this.algnNumSystem.addConstraint(
|
||||
new AlgNumConstraint(ConstraintDefinitions.PCoincident, [first, obj])
|
||||
);
|
||||
}
|
||||
|
||||
this.refresh();
|
||||
|
||||
// if (objs.length === 0) return;
|
||||
// this.linkObjects(objs);
|
||||
// this.solve();
|
||||
// this.viewer.refresh();
|
||||
};
|
||||
|
||||
ParametricManager.prototype.getSolveData = function() {
|
||||
|
|
@ -563,9 +602,9 @@ ParametricManager.prototype.__getSolveData = function(constraints, out) {
|
|||
return out;
|
||||
};
|
||||
|
||||
ParametricManager.prototype.solve = function(lock, extraConstraints, disabledObjects) {
|
||||
const solver = this.prepare(lock, extraConstraints, disabledObjects);
|
||||
solver.solve(false);
|
||||
ParametricManager.prototype.solve = function() {
|
||||
this.algnNumSystem.prepare();
|
||||
this.algnNumSystem.solve(false);
|
||||
};
|
||||
|
||||
ParametricManager.prototype.prepare = function(locked, extraConstraints, disabledObjects) {
|
||||
|
|
@ -949,8 +988,8 @@ ParametricManager.prototype.updateConstraintConstants = function(constr) {
|
|||
|
||||
import {Constraints} from './constraints';
|
||||
import {askNumber} from '../utils/utils';
|
||||
import {SEACSystem} from "./constr/SEACSystem";
|
||||
import {ConstraintDefinitions, SEACConstraint, TangentLC} from "./constr/SEACConstraints";
|
||||
import {ConstraintDefinitions, AlgNumConstraint, TangentLC} from "./constr/ANConstraints";
|
||||
import {Circle} from "./shapes/circle";
|
||||
import {EndPoint} from "./shapes/point";
|
||||
import {AlgNumSubSystem} from "./constr/AlgNumSystem";
|
||||
export {Constraints, ParametricManager}
|
||||
26
web/app/sketcher/selectionMatcher.js
Normal file
26
web/app/sketcher/selectionMatcher.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
export function SelectionMatcher() {
|
||||
|
||||
|
||||
const lowerBounds = [];
|
||||
|
||||
return {
|
||||
|
||||
|
||||
moreThan(amount, type) {
|
||||
lowerBounds.push(amount, type);
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
match: selection => {
|
||||
|
||||
|
||||
for (let [amount, type] of lowerBounds) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import Vector from 'math/vector';
|
|||
import {Ref} from './ref'
|
||||
import {Constraints} from '../parametric'
|
||||
import {pointIterator, SketchObject} from './sketch-object';
|
||||
import {EndPoint} from "./point";
|
||||
|
||||
export class Arc extends SketchObject {
|
||||
|
||||
|
|
@ -140,3 +141,4 @@ export class Arc extends SketchObject {
|
|||
}
|
||||
|
||||
Arc.prototype._class = 'TCAD.TWO.Arc';
|
||||
Arc.prototype.TYPE = 'ARC';
|
||||
|
|
@ -6,6 +6,8 @@ import {ConvexHull2D} from '../../math/convex-hull'
|
|||
|
||||
import * as draw_utils from '../shapes/draw-utils'
|
||||
import * as math from '../../math/math';
|
||||
import {Arc} from "./arc";
|
||||
import {EndPoint} from "./point";
|
||||
|
||||
|
||||
export class BezierCurve extends SketchObject {
|
||||
|
|
@ -77,5 +79,6 @@ export class BezierCurve extends SketchObject {
|
|||
}
|
||||
}
|
||||
BezierCurve.prototype._class = 'TCAD.TWO.BezierCurve';
|
||||
BezierCurve.prototype.TYPE = 'BEZIER';
|
||||
|
||||
const RECOVER_LENGTH = 100;
|
||||
|
|
@ -5,18 +5,16 @@ import {EditCircleTool} from '../tools/circle'
|
|||
import {EndPoint} from './point'
|
||||
import {Ref} from './ref'
|
||||
import {SketchObject} from './sketch-object'
|
||||
import {GCCircle} from "../constr/constractibles";
|
||||
|
||||
export class Circle extends SketchObject {
|
||||
|
||||
|
||||
constructor(c) {
|
||||
super();
|
||||
this.gcCircle = new GCCircle();
|
||||
this.c = c;
|
||||
c.parent = this;
|
||||
this.children.push(c);
|
||||
this.r = this.gcCircle.r;
|
||||
this.c.coincideWith(this.gcCircle.c)
|
||||
this.r = new Ref(0);
|
||||
this.r.obj = this;
|
||||
}
|
||||
|
||||
visitParams(callback) {
|
||||
|
|
@ -34,7 +32,7 @@ export class Circle extends SketchObject {
|
|||
|
||||
drawImpl(ctx, scale) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.gcCircle.c.x.get(), this.gcCircle.c.y.get(), this.gcCircle.r.get(), 0, 2 * Math.PI);
|
||||
ctx.arc(this.c.x, this.c.y, this.r.get(), 0, 2 * Math.PI);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
|
|
@ -44,3 +42,4 @@ export class Circle extends SketchObject {
|
|||
}
|
||||
|
||||
Circle.prototype._class = 'TCAD.TWO.Circle';
|
||||
Circle.prototype.TYPE = 'CIRCLE';
|
||||
|
|
@ -3,6 +3,8 @@ import {SketchObject} from './sketch-object'
|
|||
import {Constraints} from '../parametric'
|
||||
|
||||
import * as math from '../../math/math';
|
||||
import {Circle} from "./circle";
|
||||
import {EndPoint} from "./point";
|
||||
|
||||
export class Ellipse extends SketchObject {
|
||||
|
||||
|
|
@ -91,6 +93,7 @@ export class Ellipse extends SketchObject {
|
|||
}
|
||||
}
|
||||
Ellipse.prototype._class = 'TCAD.TWO.Ellipse';
|
||||
Ellipse.prototype.TYPE = 'ELLIPSE';
|
||||
|
||||
const sq = (a) => a * a;
|
||||
const RECOVER_LENGTH = 100;
|
||||
|
|
@ -52,3 +52,4 @@ export class EllipticalArc extends Ellipse {
|
|||
}
|
||||
|
||||
EllipticalArc.prototype._class = 'TCAD.TWO.EllipticalArc';
|
||||
EllipticalArc.prototype.TYPE = 'ELLIPTICAL_ARC';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import {SketchObject} from './sketch-object'
|
||||
import * as vec from '../../math/vec';
|
||||
import {curveTessellate} from '../../brep/geom/impl/nurbs-ext';
|
||||
import {Ellipse} from "./ellipse";
|
||||
|
||||
const __v = [0, 0, 0];
|
||||
|
||||
|
|
@ -89,3 +90,4 @@ export class NurbsObject extends SketchObject {
|
|||
}
|
||||
|
||||
NurbsObject.prototype._class = 'TCAD.TWO.NurbsObject';
|
||||
NurbsObject.prototype.TYPE = 'NURBS';
|
||||
|
|
|
|||
20
web/app/sketcher/shapes/param.js
Normal file
20
web/app/sketcher/shapes/param.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import {Generator} from "../id-generator";
|
||||
import {Param as SolverParam} from '../constr/solver';
|
||||
|
||||
export class Param {
|
||||
|
||||
constructor(value) {
|
||||
this.id = Generator.genID();
|
||||
this.value = value;
|
||||
this.solverParam = new SolverParam(value, this);
|
||||
}
|
||||
|
||||
set(value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
get() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,46 +2,39 @@ import {SketchObject} from './sketch-object'
|
|||
import {DrawPoint} from './draw-utils'
|
||||
import {Generator} from '../id-generator'
|
||||
import Vector from 'math/vector';
|
||||
import {GCPoint} from "../constr/constractibles";
|
||||
import {Param} from "./param";
|
||||
|
||||
|
||||
export class EndPoint extends SketchObject {
|
||||
|
||||
constructor(x, y) {
|
||||
super();
|
||||
this.parent = null;
|
||||
this.gcPoint = new GCPoint();
|
||||
this._x = this.gcPoint.x; // legacy - yet to remove
|
||||
this._y = this.gcPoint.y;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.params = {
|
||||
x: new Param(x),
|
||||
y: new Param(y)
|
||||
};
|
||||
}
|
||||
|
||||
get x() {
|
||||
return this.gcPoint.x.get();
|
||||
return this.params.x.get();
|
||||
}
|
||||
|
||||
set x(val) {
|
||||
return this.gcPoint.x.set(val);
|
||||
return this.params.x.set(val);
|
||||
}
|
||||
|
||||
get y() {
|
||||
return this.gcPoint.y.get();
|
||||
return this.params.y.get();
|
||||
}
|
||||
|
||||
set y(val) {
|
||||
return this.gcPoint.y.set(val);
|
||||
}
|
||||
|
||||
coincideWith(gcPoint) {
|
||||
if (!this.parkedOwnGeometry) {
|
||||
this.parkedOwnGeometry = this.gcPoint;
|
||||
}
|
||||
this.gcPoint = gcPoint;
|
||||
return this.params.y.set(val);
|
||||
}
|
||||
|
||||
visitParams(callback) {
|
||||
callback(this._x);
|
||||
callback(this._y);
|
||||
callback(this.params.x);
|
||||
callback(this.params.y);
|
||||
}
|
||||
|
||||
normalDistance(aim) {
|
||||
|
|
@ -88,20 +81,7 @@ export class EndPoint extends SketchObject {
|
|||
dest.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
EndPoint.prototype._class = 'TCAD.TWO.EndPoint';
|
||||
EndPoint.prototype.TYPE = 'POINT';
|
||||
|
||||
export class Param {
|
||||
constructor(obj, prop) {
|
||||
this.id = Generator.genID();
|
||||
this.obj = obj;
|
||||
this.prop = prop;
|
||||
}
|
||||
|
||||
set(value) {
|
||||
this.obj[this.prop] = value;
|
||||
}
|
||||
|
||||
get() {
|
||||
return this.obj[this.prop];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,3 @@
|
|||
import {Generator} from '../id-generator'
|
||||
import {Param} from "./param";
|
||||
|
||||
export function Ref(value) {
|
||||
this.id = Generator.genID();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
Ref.prototype.set = function(value) {
|
||||
this.value = value;
|
||||
};
|
||||
|
||||
Ref.prototype.get = function() {
|
||||
return this.value;
|
||||
};
|
||||
export {Param as Ref};
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import {SketchObject} from './sketch-object'
|
||||
import Vector from 'math/vector';
|
||||
import {Constraints} from '../parametric'
|
||||
import * as math from '../../math/math'
|
||||
import {GCLine} from "../constr/constractibles";
|
||||
import {Styles} from "../styles";
|
||||
import * as draw_utils from "./draw-utils";
|
||||
import {Param} from "./param";
|
||||
import {Constraints} from "../constraints";
|
||||
import {ConstraintDefinitions, AlgNumConstraint} from "../constr/ANConstraints";
|
||||
import {Ellipse} from "./ellipse";
|
||||
|
||||
export class Segment extends SketchObject {
|
||||
|
||||
|
|
@ -14,23 +16,36 @@ export class Segment extends SketchObject {
|
|||
this.b = b;
|
||||
a.parent = this;
|
||||
b.parent = this;
|
||||
this.gcLine = new GCLine();
|
||||
this.children.push(a, b);
|
||||
this.params = {
|
||||
ang: new Param(undefined),
|
||||
w: new Param(undefined)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const dx = b.x - a.x;
|
||||
const dy = b.y - a.y;
|
||||
syncLine() {
|
||||
const dx = this.b.x - this.a.x;
|
||||
const dy = this.b.y - this.a.y;
|
||||
const l = Math.sqrt(dx*dx + dy*dy);
|
||||
|
||||
let nx = - dy / l;
|
||||
let ny = dx / l;
|
||||
let nx = (- dy / l) || 0;
|
||||
let ny = (dx / l) || 0;
|
||||
const ang = Math.atan2(ny, nx);
|
||||
|
||||
this.gcLine.ang.set(ang);
|
||||
this.gcLine.w.set(nx * a.x + ny * a.y);
|
||||
|
||||
this.children.push(a, b);
|
||||
this.params.ang.set(ang||0);
|
||||
this.params.w.set(nx * this.a.x + ny * this.a.y);
|
||||
}
|
||||
|
||||
|
||||
stabilize(viewer) {
|
||||
this.syncLine();
|
||||
const c1 = new AlgNumConstraint(ConstraintDefinitions.PointOnLine, [this.a, this]);
|
||||
const c2 = new AlgNumConstraint(ConstraintDefinitions.PointOnLine, [this.b, this]);
|
||||
c1.internal = true;
|
||||
c2.internal = true;
|
||||
viewer.parametricManager.addAlgNum(c1);
|
||||
viewer.parametricManager.addAlgNum(c2);
|
||||
}
|
||||
|
||||
recoverIfNecessary() {
|
||||
if (math.distanceAB(this.a, this.b) > math.TOLERANCE) {
|
||||
return false;
|
||||
|
|
@ -45,6 +60,8 @@ export class Segment extends SketchObject {
|
|||
visitParams(callback) {
|
||||
this.a.visitParams(callback);
|
||||
this.b.visitParams(callback);
|
||||
callback(this.params.ang);
|
||||
callback(this.params.w);
|
||||
}
|
||||
|
||||
normalDistance(aim) {
|
||||
|
|
@ -89,10 +106,10 @@ export class Segment extends SketchObject {
|
|||
// ctx.restore();
|
||||
|
||||
|
||||
let ang = this.gcLine.ang.get();
|
||||
let ang = this.params.ang.get();
|
||||
let nx = Math.cos(ang) ;
|
||||
let ny = Math.sin(ang) ;
|
||||
let w = this.gcLine.w.get();
|
||||
let w = this.params.w.get();
|
||||
|
||||
ctx.save();
|
||||
draw_utils.SetStyle(Styles.CONSTRUCTION_OF_OBJECT, ctx, scale );
|
||||
|
|
@ -122,3 +139,4 @@ export class Segment extends SketchObject {
|
|||
|
||||
Segment.prototype._class = 'TCAD.TWO.Segment';
|
||||
|
||||
Segment.prototype.TYPE = 'SEGMENT';
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ export class SketchObject extends Shape {
|
|||
|
||||
export function pointIterator(shape, func) {
|
||||
shape.accept(o => {
|
||||
if (o._class === Types.END_POINT) {
|
||||
if (o._class === Types.POINT) {
|
||||
func(o);
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import {Viewer} from './viewer2d.js'
|
||||
import * as ui from '../ui/ui'
|
||||
import {Terminal} from '../ui/terminal'
|
||||
import {IO, BBox} from './io'
|
||||
import {AddFreeDimTool, AddHorizontalDimTool, AddVerticalDimTool, AddCircleDimTool} from './tools/dim'
|
||||
import {BBox, IO} from './io'
|
||||
import {AddCircleDimTool, AddFreeDimTool, AddHorizontalDimTool, AddVerticalDimTool} from './tools/dim'
|
||||
import {AddPointTool} from './tools/point'
|
||||
import {AddSegmentTool} from './tools/segment'
|
||||
import {AddArcTool} from './tools/arc'
|
||||
|
|
@ -15,6 +15,10 @@ import {OffsetTool} from './tools/offset'
|
|||
import {ReferencePointTool} from './tools/origin'
|
||||
import {InputManager} from './input-manager'
|
||||
import genSerpinski from '../utils/genSerpinski';
|
||||
import context from 'context';
|
||||
import ReactDOM from "react-dom";
|
||||
import React from "react";
|
||||
import {RightSideControls} from "./components/RightSideControls";
|
||||
|
||||
function App2D() {
|
||||
var app = this;
|
||||
|
|
@ -54,8 +58,9 @@ function App2D() {
|
|||
this.terminalHandler = undefined;
|
||||
this.terminal = new Terminal(this.commandsWin, (command) => this.handleTerminalInput(command), () => this.getAllCommandList());
|
||||
this.bindToolsToTerminal();
|
||||
|
||||
|
||||
|
||||
startReact(this.viewer);
|
||||
|
||||
this.winManager.registerResize(dockEl, ui.DIRECTIONS.EAST, function() {$('body').trigger('layout'); });
|
||||
$('body').on('layout', this.viewer.onWindowResize);
|
||||
|
||||
|
|
@ -470,6 +475,20 @@ App2D.prototype.handleTerminalInput = function(commandStr) {
|
|||
}
|
||||
};
|
||||
|
||||
function startReact(viewer) {
|
||||
context.streams.sketcherApp = viewer.streams;
|
||||
context.viewer = viewer;
|
||||
let reactControls = document.getElementById('react-controls');
|
||||
reactControls.onkeydown = e => {
|
||||
e.stopPropagation();
|
||||
// e.preventDefault();
|
||||
};
|
||||
ReactDOM.render(
|
||||
<RightSideControls />,
|
||||
reactControls
|
||||
);
|
||||
}
|
||||
|
||||
App2D.STORAGE_PREFIX = "TCAD.projects.";
|
||||
|
||||
export default App2D;
|
||||
|
|
@ -17,5 +17,7 @@ export default function(viewer) {
|
|||
|
||||
streams.constraintsUpdate = stream();
|
||||
|
||||
streams.constraintEditRequest = state(null);
|
||||
|
||||
return streams;
|
||||
};
|
||||
|
|
@ -25,6 +25,10 @@ class SubSystem {
|
|||
});
|
||||
other.nativeParams.forEach(p => this.nativeParams.add(p));
|
||||
}
|
||||
|
||||
prepare() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class Index {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export class DragTool extends Tool {
|
|||
this.obj.translate(dx, dy);
|
||||
|
||||
if (!Tool.dumbMode(e)) {
|
||||
this.solverTransaction.solve(true);
|
||||
this.viewer.parametricManager.algnNumSystem.solve(true);
|
||||
}
|
||||
this.viewer.refresh();
|
||||
}
|
||||
|
|
@ -35,12 +35,12 @@ export class DragTool extends Tool {
|
|||
this.origin.y = e.offsetY;
|
||||
this.viewer.screenToModel2(e.offsetX, e.offsetY, this._point);
|
||||
|
||||
this.solverTransaction = this.viewer.parametricManager.seacSystem.startTransaction([this.obj.gcPoint]);
|
||||
this.viewer.parametricManager.algnNumSystem.prepare();
|
||||
|
||||
}
|
||||
|
||||
mouseup(e) {
|
||||
this.solverTransaction.solve(false);
|
||||
this.viewer.parametricManager.algnNumSystem.solve(false);
|
||||
this.viewer.refresh();
|
||||
this.viewer.toolManager.releaseControl();
|
||||
var traveled = math.distance(this.origin.x, this.origin.y, e.offsetX, e.offsetY);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import {Tool} from './tool'
|
||||
import {Constraints} from "../constraints";
|
||||
import {distanceAB} from "../../math/math";
|
||||
|
||||
export class AddSegmentTool extends Tool {
|
||||
|
||||
|
|
@ -45,7 +43,7 @@ export class AddSegmentTool extends Tool {
|
|||
}
|
||||
this.line = this.viewer.addSegment(a.x, a.y, b.x, b.y, this.viewer.activeLayer);
|
||||
if (needSnap) {
|
||||
this.viewer.parametricManager.linkObjects([this.line.a, a]);
|
||||
this.line.a.coincideWith(a);
|
||||
}
|
||||
this.firstPointPicked();
|
||||
this.viewer.refresh();
|
||||
|
|
@ -55,7 +53,7 @@ export class AddSegmentTool extends Tool {
|
|||
this.viewer.cleanSnap();
|
||||
this.line.b.x = p.x;
|
||||
this.line.b.y = p.y;
|
||||
this.viewer.parametricManager.linkObjects([this.line.b, p]);
|
||||
this.line.b.coincideWith(p);
|
||||
}
|
||||
this.nextPointPicked();
|
||||
}
|
||||
|
|
@ -63,11 +61,10 @@ export class AddSegmentTool extends Tool {
|
|||
|
||||
nextPointPicked() {
|
||||
this.pointPicked(this.line.b.x, this.line.b.y);
|
||||
this.viewer.parametricManager.add(new Constraints.P2PDistance(this.line.a, this.line.b, distanceAB(this.line.a, this.line.b)));
|
||||
if (this.multi) {
|
||||
const b = this.line.b;
|
||||
this.line = this.viewer.addSegment(b.x, b.y, b.x, b.y, this.viewer.activeLayer);
|
||||
this.viewer.parametricManager.linkObjects([this.line.a, b]);
|
||||
this.line.a.coincideWith(b);
|
||||
} else {
|
||||
this.restart()
|
||||
}
|
||||
|
|
@ -87,7 +84,7 @@ export class AddSegmentTool extends Tool {
|
|||
}
|
||||
|
||||
keydown(e) {
|
||||
if (e.keyCode == 27) {
|
||||
if (e.keyCode === 27) {
|
||||
this.cancelSegment();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ class Viewer {
|
|||
var b = new EndPoint(x2, y2);
|
||||
var line = new Segment(a, b);
|
||||
layer.add(line);
|
||||
line.stabilize(this);
|
||||
return line;
|
||||
};
|
||||
|
||||
|
|
@ -329,7 +330,7 @@ class Viewer {
|
|||
return out;
|
||||
};
|
||||
|
||||
accept(visitor) {
|
||||
accept = visitor => {
|
||||
for (let layer of this.layers) {
|
||||
for (let object of layer.objects) {
|
||||
if (!object.accept(visitor)) {
|
||||
|
|
|
|||
|
|
@ -346,4 +346,4 @@ input[type=checkbox], input[type=radio] {
|
|||
font-size: 11px;
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@
|
|||
<div id="viewer-container" style="background: #808080; overflow: hidden; height: 100%; position: relative">
|
||||
<div class="tool-hint" style="position: absolute; bottom: 5px; right: 5px;"></div>
|
||||
<canvas width="300" height="300" id="viewer"></canvas>
|
||||
<div id="react-controls" style="position: absolute; top: 0; right: 0; bottom: 0;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue