├── .eslintrc.cjs ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── babel.config.cjs ├── dist ├── index.d.ts ├── mz-math.esm.js ├── mz-math.esm.js.map ├── mz-math.min.js ├── mz-math.min.js.map ├── mz-math.node.cjs └── mz-math.node.cjs.map ├── docs ├── CNAME ├── css │ └── styles.1721034616071.css ├── favicon.ico ├── img │ └── favicon │ │ ├── android-chrome-192.png │ │ ├── android-chrome-512.png │ │ ├── apple-touch-icon.png │ │ ├── browserconfig.xml │ │ ├── favicon-128.png │ │ ├── favicon-16.png │ │ ├── favicon-256.png │ │ ├── favicon-32.png │ │ ├── favicon-48.png │ │ ├── favicon-96.png │ │ ├── favicon.ico │ │ ├── favicon.svg │ │ ├── manifest.json │ │ └── mstile-150.png ├── index.html ├── js │ ├── index.1721034616071.js │ └── index.1721034616071.js.map ├── pages │ ├── Check-if-value-is-number.html │ ├── adjugate-matrix.html │ ├── angle-between-vectors.html │ ├── angles-distance.html │ ├── animation.html │ ├── append-or-prepend-column.html │ ├── append-or-prepend-row.html │ ├── arithmetic-sequence-sum.html │ ├── bezier-curves.html │ ├── bounding-box.html │ ├── browser-usage.html │ ├── check-if-ranges-overlap.html │ ├── circle-movement.html │ ├── circles-collision.html │ ├── circumference.html │ ├── color.html │ ├── combinatorics.html │ ├── convert-colors.html │ ├── convert-range.html │ ├── convert-string-to-number.html │ ├── convex-polygons-collision.html │ ├── cross-product.html │ ├── degrees-and-radians.html │ ├── distance-between-vectors.html │ ├── divide-by-scalar.html │ ├── divide-vector-by-scalar.html │ ├── dot-product.html │ ├── ellipse-movement.html │ ├── extrema.html │ ├── factorial.html │ ├── general-case.html │ ├── get-animation-data.html │ ├── get-column.html │ ├── get-linear-equation-by-2-points.html │ ├── get-matrix-minor.html │ ├── get-normal.html │ ├── get-point-on-cubic-bezier-curve.html │ ├── get-point-on-quadratic-bezier-curve.html │ ├── get-random-boolean.html │ ├── get-random-integer.html │ ├── get-random-item-from-array.html │ ├── get-random-number-in-range.html │ ├── greatest-common-divisor.html │ ├── inverse-matrix.html │ ├── is-angle-between.html │ ├── is-angle-in-circle-arc.html │ ├── is-clockwise.html │ ├── lerp.html │ ├── linear-equation.html │ ├── lissajous-curve.html │ ├── matrix-deep-copy.html │ ├── matrix-determinant.html │ ├── matrix-equality.html │ ├── matrix-initialization.html │ ├── matrix-multiplication.html │ ├── matrix-singularity.html │ ├── matrix-subtraction.html │ ├── matrix-sum.html │ ├── matrix-to-CSS-transform.html │ ├── matrix-transposition.html │ ├── matrix.html │ ├── modulo.html │ ├── multiply-by-scalar.html │ ├── multiply-matrix-by-vector.html │ ├── multiply-vector-by-scalar.html │ ├── natural-numbers-sequence-sum.html │ ├── nodejs-usage.html │ ├── normal.html │ ├── normalize-vector.html │ ├── percent-to-angle.html │ ├── polar-to-cartesian.html │ ├── polynomial.html │ ├── quadratic-equation.html │ ├── random-color.html │ ├── random-id-or-GUID.html │ ├── rectangles-collision.html │ ├── reflection-matrix.html │ ├── remove-row-or-column.html │ ├── reset-matrix.html │ ├── rotate-around-point.html │ ├── rotation-matrix.html │ ├── scale-and-stretch-matrix.html │ ├── scale-around-point.html │ ├── series.html │ ├── set-decimal-places.html │ ├── shearing-matrix.html │ ├── shift-colors.html │ ├── similar-colors.html │ ├── sine-wave-movement.html │ ├── square-in-circle.html │ ├── system-of-linear-equations.html │ ├── tangent.html │ ├── temperature-conversion.html │ ├── translation-matrix.html │ ├── trigonometric-functions.html │ ├── typescript-usage.html │ ├── vector-angle.html │ ├── vector-initialization.html │ ├── vector-length.html │ ├── vectors-equality.html │ ├── vectors-subtraction.html │ ├── vectors-sum.html │ └── vectors.html └── sitemap.txt ├── examples ├── bezier-curves │ ├── bezier-cubic-curve-bbox.html │ └── bezier-quadratic-curve-bbox.html ├── circular-movement │ ├── circle-movement-1.html │ ├── circle-movement-2.html │ ├── circle-movement-3.html │ ├── circle-movement-4.html │ ├── circle-movement-mouse-1.html │ ├── circle-movement-with-rotation.html │ ├── ellipse-movement-2.html │ └── ellipse-movement-3.html ├── css │ ├── styles-1.css │ ├── styles-2.css │ ├── styles-3.css │ ├── styles-4.css │ └── styles-5.css ├── lissajous-curves │ └── lissajous-curves-canvas.html ├── matrix-to-css-rotation.html ├── physics │ ├── fireworks-2.html │ ├── fireworks.html │ └── throw.html └── wave-movement │ ├── wave-movement-1.html │ └── wave-movement-2.html ├── jest.config.ts ├── package-lock.json ├── package.json ├── run ├── es6.js ├── esm.js ├── node.js └── settings.js ├── src ├── docs │ ├── client-side │ │ ├── css │ │ │ └── index.css │ │ └── js │ │ │ ├── dark-mode.ts │ │ │ ├── index.tsx │ │ │ └── menu │ │ │ ├── mobile-menu.ts │ │ │ └── side-menu.ts │ ├── data │ │ ├── config.json │ │ ├── layouts │ │ │ ├── page-layout.html │ │ │ └── special-page-layout.html │ │ ├── pages │ │ │ ├── 10-main │ │ │ │ ├── 1-typescript-usage.md │ │ │ │ ├── 2-browser-usage.md │ │ │ │ └── 3-nodejs-usage.md │ │ │ ├── 100-color │ │ │ │ ├── 1-color.md │ │ │ │ ├── 2-random-color.md │ │ │ │ ├── 3-convert-colors.md │ │ │ │ ├── 4-shift-colors.md │ │ │ │ └── 5-similar-colors.md │ │ │ ├── 1000-other │ │ │ │ ├── 1-set-decimal-places.md │ │ │ │ ├── 10-series.md │ │ │ │ ├── 11-greatest-common-divisor.md │ │ │ │ ├── 2-convert-string-to-number.md │ │ │ │ ├── 3-square-in-circle.md │ │ │ │ ├── 4-modulo.md │ │ │ │ ├── 5-convert-range.md │ │ │ │ ├── 6-check-if-ranges-overlap.md │ │ │ │ ├── 7-check-if-value-is-number.md │ │ │ │ ├── 8-polar-to-cartesian.md │ │ │ │ └── 9-temperature-conversion.md │ │ │ ├── 105-linear-interpolation │ │ │ │ ├── 1-lerp.md │ │ │ │ └── 2-general-case.md │ │ │ ├── 110-derivatives │ │ │ │ ├── 1-polynomial.md │ │ │ │ ├── 2-trigonometric-functions.md │ │ │ │ └── 3-bezier-curves.md │ │ │ ├── 120-collision-detection │ │ │ │ ├── 1-rectangles-collision.md │ │ │ │ ├── 2-circles-collision.md │ │ │ │ └── 3-convex-polygons-collision.md │ │ │ ├── 130-animation │ │ │ │ ├── 1-animation.md │ │ │ │ └── 2-get-animation-data.md │ │ │ ├── 140-circle-and-ellipse │ │ │ │ ├── 1-circumference.md │ │ │ │ └── 2-is-angle-in-circle-arc.md │ │ │ ├── 150-sequence │ │ │ │ ├── 1-natural-numbers-sequence-sum.md │ │ │ │ └── 2-arithmetic-sequence-sum.md │ │ │ ├── 160-combinatorics │ │ │ │ ├── 1-factorial.md │ │ │ │ └── 2-combinatorics.md │ │ │ ├── 20-vectors │ │ │ │ ├── 1-vectors.md │ │ │ │ ├── 10-distance-between-vectors.md │ │ │ │ ├── 11-vector-initialization.md │ │ │ │ ├── 12-vectors-equality.md │ │ │ │ ├── 13-get-normal.md │ │ │ │ ├── 2-vectors-sum.md │ │ │ │ ├── 3-vectors-subtraction.md │ │ │ │ ├── 4-multiply-vector-by-scalar.md │ │ │ │ ├── 5-divide-vector-by-scalar.md │ │ │ │ ├── 6-vector-length.md │ │ │ │ ├── 7-normalize-vector.md │ │ │ │ ├── 8-dot-product.md │ │ │ │ └── 9-cross-product.md │ │ │ ├── 30-matrix │ │ │ │ ├── 1-matrix.md │ │ │ │ ├── 10-inverse-matrix.md │ │ │ │ ├── 11-matrix-singularity.md │ │ │ │ ├── 12-adjugate-matrix.md │ │ │ │ ├── 12-get-matrix-minor.md │ │ │ │ ├── 2-matrix-sum.md │ │ │ │ ├── 3-matrix-subtraction.md │ │ │ │ ├── 4-multiply-by-scalar.md │ │ │ │ ├── 5-divide-by-scalar.md │ │ │ │ ├── 6-matrix-transposition.md │ │ │ │ ├── 7-matrix-multiplication.md │ │ │ │ ├── 8-multiply-matrix-by-vector.md │ │ │ │ └── 9-matrix-determinant.md │ │ │ ├── 40-matrix-manipulation │ │ │ │ ├── 1-matrix-initialization.md │ │ │ │ ├── 2-matrix-equality.md │ │ │ │ ├── 3-matrix-deep-copy.md │ │ │ │ ├── 4-append-or-prepend-row.md │ │ │ │ ├── 5-append-or-prepend-column.md │ │ │ │ ├── 6-remove-row-or-column.md │ │ │ │ ├── 7-get-column.md │ │ │ │ └── 8-reset-matrix.md │ │ │ ├── 45-transformation-matrices │ │ │ │ ├── 1-translation-matrix.md │ │ │ │ ├── 2-rotation-matrix.md │ │ │ │ ├── 3-rotate-around-point.md │ │ │ │ ├── 4-scale-and-stretch-matrix.md │ │ │ │ ├── 5-scale-around-point.md │ │ │ │ ├── 6-reflection-matrix.md │ │ │ │ ├── 7-shearing-matrix.md │ │ │ │ └── 8-matrix-to-CSS-transform.md │ │ │ ├── 50-angles │ │ │ │ ├── 1-vector-angle.md │ │ │ │ ├── 2-angle-between-vectors.md │ │ │ │ ├── 3-degrees-and-radians.md │ │ │ │ ├── 4-angles-distance.md │ │ │ │ ├── 5-is-angle-between.md │ │ │ │ ├── 6-is-clockwise.md │ │ │ │ └── 7-percent-to-angle.md │ │ │ ├── 60-random │ │ │ │ ├── 1-get-random-number-in-range.md │ │ │ │ ├── 2-get-random-integer.md │ │ │ │ ├── 3-get-random-boolean.md │ │ │ │ ├── 4-get-random-item-from-array.md │ │ │ │ └── 5-random-id-or-GUID.md │ │ │ ├── 70-bezier-curve │ │ │ │ ├── 1-get-point-on-quadratic-bezier-curve.md │ │ │ │ ├── 2-get-point-on-cubic-bezier-curve.md │ │ │ │ ├── 3-tangent.md │ │ │ │ ├── 4-normal.md │ │ │ │ ├── 5-extrema.md │ │ │ │ └── 6-bounding-box.md │ │ │ ├── 80-equations │ │ │ │ ├── 1-linear-equation.md │ │ │ │ ├── 2-system-of-linear-equations.md │ │ │ │ ├── 3-quadratic-equation.md │ │ │ │ └── 4-get-linear-equation-by-2-points.md │ │ │ ├── 90-path-movement │ │ │ │ ├── 1-circle-movement.md │ │ │ │ ├── 2-ellipse-movement.md │ │ │ │ ├── 3-sine-wave-movement.md │ │ │ │ └── 4-lissajous-curve.md │ │ │ └── pages-config.json │ │ └── special-pages │ │ │ └── index.html │ └── generator │ │ ├── client-side │ │ ├── css-provider.js │ │ └── js-provider.js │ │ ├── common-provider.js │ │ ├── index.js │ │ ├── markdown-config.js │ │ └── render │ │ ├── macros-provider.js │ │ ├── pages-provider.js │ │ ├── side-menu-provider.js │ │ ├── sitemap-provider.js │ │ └── special-pages-provider.js ├── index-esm.ts ├── index.ts ├── main │ ├── angle.ts │ ├── animation.ts │ ├── bezier-curves │ │ ├── bezier-curve.ts │ │ └── bezier-formula-with-weights.svg │ ├── circle-ellipse.ts │ ├── collision-detection.ts │ ├── color.ts │ ├── combinatorics │ │ ├── combinatorics.ts │ │ └── factorial.ts │ ├── convert.ts │ ├── derivative.ts │ ├── equations │ │ ├── linear-equations.ts │ │ └── quadratic-equations.ts │ ├── format.ts │ ├── id.ts │ ├── linear-algebra │ │ ├── matrix-transformations.ts │ │ ├── matrix.ts │ │ └── vector.ts │ ├── linear-interpolation.ts │ ├── ml.ts │ ├── other.ts │ ├── path-movement.ts │ ├── physics.ts │ ├── random.ts │ ├── sequence.ts │ ├── series.ts │ ├── statistics.ts │ └── temperature.ts └── types.ts ├── test ├── angle.test.ts ├── bezier-curve.test.ts ├── browser │ └── index.html ├── circle-ellipse.test.ts ├── collision-detection.test.ts ├── color.test.ts ├── combinatorics.test.ts ├── convert.test.ts ├── derivative.test.ts ├── equations.test.ts ├── factorial.test.ts ├── format.test.ts ├── linear-interpolation.test.ts ├── matrix-transformations.test.ts ├── matrix.test.ts ├── ml.test.ts ├── other.test.ts ├── sequence.test.ts ├── series.test.ts ├── statistics.test.ts ├── temperature.test.ts └── verctor.test.ts └── tsconfig.json /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "node": true, 6 | }, 7 | "extends": [ 8 | "eslint:recommended", 9 | "plugin:@typescript-eslint/eslint-recommended", 10 | "plugin:@typescript-eslint/recommended" 11 | ], 12 | 13 | "parser": "@typescript-eslint/parser", 14 | "parserOptions": { 15 | "ecmaVersion": "latest", 16 | "sourceType": "module" 17 | }, 18 | "plugins": [ 19 | "@typescript-eslint" 20 | ], 21 | "rules": { 22 | "@typescript-eslint/ban-ts-comment": "off", 23 | "@typescript-eslint/no-unused-vars": ["error", {argsIgnorePattern: "^_", destructuredArrayIgnorePattern: "^_"}] 24 | } 25 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | TODO 2 | 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | lerna-debug.log* 10 | .pnpm-debug.log* 11 | 12 | types/ 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # Snowpack dependency directory (https://snowpack.dev/) 50 | web_modules/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Optional stylelint cache 62 | .stylelintcache 63 | 64 | # Microbundle cache 65 | .rpt2_cache/ 66 | .rts2_cache_cjs/ 67 | .rts2_cache_es/ 68 | .rts2_cache_umd/ 69 | 70 | # Optional REPL history 71 | .node_repl_history 72 | 73 | # Output of 'npm pack' 74 | *.tgz 75 | 76 | # Yarn Integrity file 77 | .yarn-integrity 78 | 79 | # dotenv environment variable files 80 | #.env 81 | #.env.development.local 82 | #.env.test.local 83 | #.env.production.local 84 | #.env.local 85 | 86 | # parcel-bundler cache (https://parceljs.org/) 87 | .cache 88 | .parcel-cache 89 | 90 | # Next.static run output 91 | .next 92 | out 93 | 94 | # Nuxt.static run / generate output 95 | .nuxt 96 | 97 | # Gatsby files 98 | .cache/ 99 | # Comment in the public line in if your project uses Gatsby and not Next.static 100 | # https://nextjs.org/blog/next-9-1#public-directory-support 101 | # public 102 | 103 | # vuepress run output 104 | .vuepress/dist 105 | 106 | # vuepress v2.x temp and cache directory 107 | .temp 108 | .cache 109 | 110 | # Docusaurus cache and generated files 111 | .docusaurus 112 | 113 | # Serverless directories 114 | .serverless/ 115 | 116 | # FuseBox cache 117 | .fusebox/ 118 | 119 | # DynamoDB Local files 120 | .dynamodb/ 121 | 122 | # TernJS port file 123 | .tern-port 124 | 125 | # Stores VSCode versions used for testing VSCode extensions 126 | .vscode-test 127 | 128 | # yarn v2 129 | .yarn/cache 130 | .yarn/unplugged 131 | .yarn/build-state.yml 132 | .yarn/install-state.gz 133 | .pnp.* 134 | 135 | # jetbrains 136 | .idea 137 | 138 | # diff 139 | .DS_Store 140 | *.cache -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # CONTRIBUTING 2 | 3 | See [Contribution Guidelines here](https://github.com/mzusin/index/blob/main/CONTRIBUTING.md). -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## License 2 | 3 | The project has two types of licenses: open-source and commercial. In general, the project is free for non-commercial, trial and educational use, and paid for commercial use. 4 | 5 | ## Open source license 6 | 7 | The open source license can be used to create open source, trial and personal projects. The project uses the [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) open source license. 8 | 9 | Please note that releasing your application that uses this project under the [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) license, in turn, requires your application to be licensed under the GPLv3 license. 10 | 11 | ## Commercial license 12 | 13 | The commercial license should be used to create commercial products and applications, without the provisions of the [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) license. With the commercial license, your code is kept proprietary, to yourself. If you want to use this project to develop commercial websites, themes, projects, and applications, the commercial license is the way to go. 14 | 15 | - [Purchase commercial license here](https://payhip.com/b/SeBVQ) 16 | - [Read more about commercial license](https://github.com/mzusin/index/blob/main/LICENSE.md) -------------------------------------------------------------------------------- /babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current' 8 | } 9 | } 10 | ] 11 | ] 12 | }; -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | math.mzsoft.org -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzusin/mz-math/2eeab90d17b4a42bf4f6c31120e2c00b77ec749a/docs/favicon.ico -------------------------------------------------------------------------------- /docs/img/favicon/android-chrome-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzusin/mz-math/2eeab90d17b4a42bf4f6c31120e2c00b77ec749a/docs/img/favicon/android-chrome-192.png -------------------------------------------------------------------------------- /docs/img/favicon/android-chrome-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzusin/mz-math/2eeab90d17b4a42bf4f6c31120e2c00b77ec749a/docs/img/favicon/android-chrome-512.png -------------------------------------------------------------------------------- /docs/img/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzusin/mz-math/2eeab90d17b4a42bf4f6c31120e2c00b77ec749a/docs/img/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/img/favicon/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/img/favicon/favicon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzusin/mz-math/2eeab90d17b4a42bf4f6c31120e2c00b77ec749a/docs/img/favicon/favicon-128.png -------------------------------------------------------------------------------- /docs/img/favicon/favicon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzusin/mz-math/2eeab90d17b4a42bf4f6c31120e2c00b77ec749a/docs/img/favicon/favicon-16.png -------------------------------------------------------------------------------- /docs/img/favicon/favicon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzusin/mz-math/2eeab90d17b4a42bf4f6c31120e2c00b77ec749a/docs/img/favicon/favicon-256.png -------------------------------------------------------------------------------- /docs/img/favicon/favicon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzusin/mz-math/2eeab90d17b4a42bf4f6c31120e2c00b77ec749a/docs/img/favicon/favicon-32.png -------------------------------------------------------------------------------- /docs/img/favicon/favicon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzusin/mz-math/2eeab90d17b4a42bf4f6c31120e2c00b77ec749a/docs/img/favicon/favicon-48.png -------------------------------------------------------------------------------- /docs/img/favicon/favicon-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzusin/mz-math/2eeab90d17b4a42bf4f6c31120e2c00b77ec749a/docs/img/favicon/favicon-96.png -------------------------------------------------------------------------------- /docs/img/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzusin/mz-math/2eeab90d17b4a42bf4f6c31120e2c00b77ec749a/docs/img/favicon/favicon.ico -------------------------------------------------------------------------------- /docs/img/favicon/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/img/favicon/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mzMath", 3 | "short_name": "mzMath", 4 | "icons": [ 5 | { 6 | "src": "/img/favicons/android-chrome-192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/img/favicons/android-chrome-512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } -------------------------------------------------------------------------------- /docs/img/favicon/mstile-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzusin/mz-math/2eeab90d17b4a42bf4f6c31120e2c00b77ec749a/docs/img/favicon/mstile-150.png -------------------------------------------------------------------------------- /examples/bezier-curves/bezier-cubic-curve-bbox.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Bezier Cubic Curve BBox 6 | 7 | 8 | 9 | 10 |

Bezier Cubic Curve BBox

11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 89 | 90 | -------------------------------------------------------------------------------- /examples/bezier-curves/bezier-quadratic-curve-bbox.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Bezier Quadratic Curve BBox 6 | 7 | 8 | 9 | 10 |

Bezier Quadratic Curve BBox

11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 86 | 87 | -------------------------------------------------------------------------------- /examples/circular-movement/circle-movement-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Circle Movement using "m2hToCSS" Function 6 | 7 | 8 | 9 | 10 |

Circle Movement using "m2hToCSS" Function

11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 | 23 | 24 | 89 | 90 | -------------------------------------------------------------------------------- /examples/circular-movement/circle-movement-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Simple rotation using circle equation 6 | 7 | 8 | 9 | 10 |

Simple rotation using circle equation

11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 | 23 | 24 | 95 | 96 | -------------------------------------------------------------------------------- /examples/circular-movement/circle-movement-mouse-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Circle movement after mouse 6 | 7 | 8 | 9 | 10 |

Circle movement after mouse

11 |
12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 |
24 | 25 | 26 | 51 | 52 | -------------------------------------------------------------------------------- /examples/circular-movement/circle-movement-with-rotation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Circle movement with rotation 6 | 7 | 8 | 9 | 10 |

Circle movement with rotation

11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 | 23 | 24 | 96 | 97 | -------------------------------------------------------------------------------- /examples/circular-movement/ellipse-movement-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ellipse movement using "m2hToCSS" Function 6 | 7 | 8 | 9 | 10 |

Ellipse movement using "m2hToCSS" Function

11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 | 23 | 24 | 89 | 90 | -------------------------------------------------------------------------------- /examples/circular-movement/ellipse-movement-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Simple rotation using ellipse equation 6 | 7 | 8 | 9 | 10 |

Simple rotation using ellipse equation

11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 | 23 | 24 | 96 | 97 | -------------------------------------------------------------------------------- /examples/css/styles-1.css: -------------------------------------------------------------------------------- 1 | html, body{ 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | body{ 7 | width: 100vw; 8 | height: 100vh; 9 | background: #232323; 10 | color: #efefef; 11 | display: flex; 12 | align-items: center; 13 | justify-content: center; 14 | } 15 | 16 | h1{ 17 | position: absolute; 18 | top: 1rem; 19 | font-size: 1rem; 20 | font-weight: normal; 21 | } 22 | 23 | #center { 24 | width: 1rem; 25 | height: 1rem; 26 | background: red; 27 | position: absolute; 28 | top: 50%; 29 | left: 50%; 30 | border-radius: 100%; 31 | transform: translate(-0.5rem, -0.5rem); 32 | } 33 | 34 | #star{ 35 | box-shadow: 0 0 1rem #fff; 36 | border-radius: 100%; 37 | } -------------------------------------------------------------------------------- /examples/css/styles-2.css: -------------------------------------------------------------------------------- 1 | html, body{ 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | body{ 7 | width: 100vw; 8 | height: 100vh; 9 | background: #232323; 10 | color: #efefef; 11 | display: flex; 12 | align-items: center; 13 | justify-content: center; 14 | } 15 | 16 | h1{ 17 | position: absolute; 18 | top: 1rem; 19 | font-size: 1rem; 20 | font-weight: normal; 21 | } 22 | 23 | #center { 24 | width: 1rem; 25 | height: 1rem; 26 | background: red; 27 | position: absolute; 28 | top: 50%; 29 | left: 50%; 30 | border-radius: 100%; 31 | transform: translate(-50%, -50%); 32 | } 33 | 34 | #star{ 35 | box-shadow: 0 0 1rem #fff; 36 | border-radius: 100%; 37 | background: #000; 38 | transform: translate(-50%, -50%); 39 | } 40 | 41 | .circle{ 42 | width: 270px; 43 | height: 270px; 44 | border: 5px solid #81b2d6; 45 | border-radius: 100%; 46 | } -------------------------------------------------------------------------------- /examples/css/styles-3.css: -------------------------------------------------------------------------------- 1 | html, body{ 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | body{ 7 | width: 100vw; 8 | height: 100vh; 9 | background: #232323; 10 | color: #efefef; 11 | display: flex; 12 | align-items: center; 13 | justify-content: center; 14 | } 15 | 16 | h1{ 17 | position: absolute; 18 | top: 0.5rem; 19 | font-size: 1rem; 20 | font-weight: normal; 21 | } 22 | 23 | canvas{ 24 | border: 1px solid red; 25 | box-sizing: border-box; 26 | display: block; 27 | padding: 0; 28 | margin: 0; 29 | width: 800px; 30 | height: 800px; 31 | } 32 | -------------------------------------------------------------------------------- /examples/css/styles-4.css: -------------------------------------------------------------------------------- 1 | html, body{ 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | body{ 7 | width: 100vw; 8 | height: 100vh; 9 | background: #232323; 10 | color: #efefef; 11 | display: flex; 12 | align-items: center; 13 | justify-content: center; 14 | } 15 | 16 | h1{ 17 | position: absolute; 18 | top: 0.5rem; 19 | font-size: 1rem; 20 | font-weight: normal; 21 | } 22 | 23 | canvas{ 24 | border: 1px solid #808080; 25 | box-sizing: border-box; 26 | display: block; 27 | padding: 0; 28 | margin: 0; 29 | width: 800px; 30 | height: 800px; 31 | } 32 | -------------------------------------------------------------------------------- /examples/css/styles-5.css: -------------------------------------------------------------------------------- 1 | html, body{ 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | body{ 7 | width: 100vw; 8 | height: 100vh; 9 | display: flex; 10 | justify-content: center; 11 | } 12 | 13 | h1{ 14 | top: 1rem; 15 | font-size: 1rem; 16 | font-weight: normal; 17 | } 18 | 19 | svg{ 20 | border: 1px solid #b4b4b4; 21 | display: block; 22 | } 23 | 24 | #wrapper { 25 | margin: 3rem auto; 26 | } -------------------------------------------------------------------------------- /examples/matrix-to-css-rotation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Matrix to CSS matrix() function (rotation example) 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 | 81 | 82 | -------------------------------------------------------------------------------- /examples/physics/fireworks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Fireworks 6 | 7 | 8 | 9 | 10 |

Fireworks

11 | 12 | 13 | 14 | 106 | 107 | -------------------------------------------------------------------------------- /examples/physics/throw.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | A Throw 6 | 7 | 8 | 9 | 10 |

A Throw

11 | 12 | 13 | 14 | 71 | 72 | -------------------------------------------------------------------------------- /examples/wave-movement/wave-movement-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Sine Wave Movement 6 | 7 | 8 | 9 | 10 |

Sine Wave Movement

11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 60 | 61 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mz-math", 3 | "version": "3.0.27", 4 | "description": "mzMath - a collection of TypeScript-based math helpers.", 5 | "main": "./dist/mz-math.min.js", 6 | "module": "./dist/mz-math.esm.js", 7 | "types": "./dist/index.d.ts", 8 | "exports": { 9 | "import": "./dist/mz-math.esm.js", 10 | "require": "./dist/mz-math.node.cjs", 11 | "default": "./dist/mz-math.esm.js" 12 | }, 13 | "scripts": { 14 | "build:all": "npm run build:es6 & npm run build:node & npm run build:esm", 15 | "watch:all": "npm run watch:es6 & npm run watch:node & npm run watch:esm", 16 | "build:es6": "node run/es6.js", 17 | "watch:es6": "node run/es6.js -- watch", 18 | "build:node": "node run/node.js", 19 | "watch:node": "node run/node.js -- watch", 20 | "build:esm": "node run/esm.js", 21 | "watch:esm": "node run/esm.js -- watch", 22 | "test": "jest", 23 | "test:watch": "jest --watch", 24 | "eslint": "eslint ./src/**", 25 | "typescript-declarations": "tsc --emitDeclarationOnly", 26 | "docs:website": "http-server ./docs", 27 | "docs:build": "node ./src/docs/generator/index.js", 28 | "docs:watch": "nodemon ./src/docs/generator/index.js" 29 | }, 30 | "type": "module", 31 | "keywords": [ 32 | "math", 33 | "mathematics", 34 | "vector", 35 | "matrix", 36 | "angle", 37 | "linear algebra", 38 | "algebra", 39 | "random", 40 | "modulo", 41 | "range", 42 | "Bézier curve", 43 | "Bézier", 44 | "Bezier curve", 45 | "Bezier", 46 | "transformation matrix", 47 | "rotation matrix", 48 | "rotation", 49 | "scale matrix", 50 | "scale", 51 | "system of equations", 52 | "equation", 53 | "translation matrix", 54 | "reflection", 55 | "reflection matrix", 56 | "shearing", 57 | "shearing matrix", 58 | "css transform", 59 | "color", 60 | "derivatives", 61 | "lerp", 62 | "linear interpolation", 63 | "collision detection", 64 | "statistics", 65 | "combinatorics" 66 | ], 67 | "author": "Miriam Zusin ", 68 | "license": "SEE LICENSE IN LICENSE.md", 69 | "browserslist": [ 70 | ">0.2%", 71 | "not dead", 72 | "not op_mini all" 73 | ], 74 | "repository": { 75 | "type": "git", 76 | "url": "https://github.com/mzusin/mz-math.git" 77 | }, 78 | "devDependencies": { 79 | "@babel/preset-env": "^7.20.2", 80 | "@types/jest": "^29.2.3", 81 | "@typescript-eslint/eslint-plugin": "^5.43.0", 82 | "@typescript-eslint/parser": "^5.43.0", 83 | "esbuild": "^0.16.3", 84 | "eslint": "^8.27.0", 85 | "highlight.js": "^11.7.0", 86 | "jest": "^29.3.1", 87 | "markdown-documentation-maker": "^1.0.13", 88 | "mz-particles": "^1.0.5", 89 | "ts-jest": "^29.0.3", 90 | "ts-node": "^10.9.1" 91 | }, 92 | "nodemonConfig": { 93 | "restartable": "rs", 94 | "ignore": [ 95 | ".git", 96 | "node_modules/**/node_modules" 97 | ], 98 | "verbose": false, 99 | "watch": [ 100 | "src/" 101 | ], 102 | "ext": "js,json,html,css,md,ts,tsx,glsl" 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /run/es6.js: -------------------------------------------------------------------------------- 1 | import esbuild from 'esbuild'; 2 | import { settings } from './settings.js'; 3 | 4 | const args = process.argv.slice(2); 5 | const watch = args.length > 1 && args[1].trim().toLowerCase() === 'watch'; 6 | 7 | if(watch){ 8 | // ------------- watch --------------- 9 | settings.watch = { 10 | onRebuild(error, result) { 11 | 12 | if (error){ 13 | // console.error(error); 14 | } 15 | else { 16 | console.log('Succeeded.'); 17 | } 18 | }, 19 | }; 20 | } 21 | 22 | esbuild 23 | .build(settings) 24 | .then(result => { 25 | console.log(watch ? 'Watching...' : 'Done.'); 26 | }) 27 | .catch(() => process.exit(1)); 28 | -------------------------------------------------------------------------------- /run/esm.js: -------------------------------------------------------------------------------- 1 | import esbuild from 'esbuild'; 2 | import { settings } from './settings.js'; 3 | 4 | const args = process.argv.slice(2); 5 | const watch = args.length > 1 && args[1].trim().toLowerCase() === 'watch'; 6 | 7 | settings.platform = 'neutral'; 8 | settings.format = 'esm'; 9 | settings.entryPoints = ['./src/index-esm.ts']; 10 | settings.outfile = './dist/mz-math.esm.js'; 11 | 12 | if(watch){ 13 | // ------------- watch --------------- 14 | settings.watch = { 15 | onRebuild(error, result) { 16 | 17 | if (error){ 18 | // console.error(error); 19 | } 20 | else { 21 | console.log('Succeeded.'); 22 | } 23 | }, 24 | }; 25 | } 26 | 27 | esbuild 28 | .build(settings) 29 | .then(result => { 30 | console.log(watch ? 'Watching...' : 'Done.'); 31 | }) 32 | .catch(() => process.exit(1)); 33 | -------------------------------------------------------------------------------- /run/node.js: -------------------------------------------------------------------------------- 1 | import esbuild from 'esbuild'; 2 | import { settings } from './settings.js'; 3 | 4 | const args = process.argv.slice(2); 5 | const watch = args.length > 1 && args[1].trim().toLowerCase() === 'watch'; 6 | 7 | settings.platform = 'node'; 8 | settings.entryPoints = ['./src/index-esm.ts']; 9 | settings.outfile = './dist/mz-math.node.cjs'; 10 | 11 | if(watch){ 12 | // ------------- watch --------------- 13 | settings.watch = { 14 | onRebuild(error, result) { 15 | 16 | if (error){ 17 | // console.error(error); 18 | } 19 | else { 20 | console.log('Succeeded.'); 21 | } 22 | }, 23 | }; 24 | } 25 | 26 | esbuild 27 | .build(settings) 28 | .then(result => { 29 | console.log(watch ? 'Watching...' : 'Done.'); 30 | }) 31 | .catch(() => process.exit(1)); 32 | -------------------------------------------------------------------------------- /run/settings.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | 4 | const packageJson = fs.readFileSync(path.join(process.cwd(), './package.json'), 'utf-8'); 5 | let version = '1.0.0'; 6 | 7 | try { 8 | const parsed = JSON.parse(packageJson); 9 | version = parsed.version; 10 | } catch (ex) {} 11 | 12 | export const settings = { 13 | entryPoints: ['./src/index.ts'], 14 | bundle: true, 15 | sourcemap: 'linked', // external 16 | minify: true, 17 | target: ['es6'], 18 | outfile: './dist/mz-math.min.js', 19 | banner: { 20 | js: `/* 21 | mzMath v${ version } 22 | A collection of TypeScript-based math helpers. 23 | https://github.com/mzusin/mz-math 24 | Licensed GPLv3 for open source use, or Commercial License for commercial use - https://github.com/mzusin/index/blob/main/LICENSE.md 25 | Copyright (c) 2023-present, Miriam Zusin 26 | */`, 27 | }, 28 | }; -------------------------------------------------------------------------------- /src/docs/client-side/css/index.css: -------------------------------------------------------------------------------- 1 | /*! 2 | Theme: Tokyo-night-Dark 3 | origin: https://github.com/enkia/tokyo-night-vscode-theme 4 | Description: Original highlight.js style 5 | Author: (c) Henri Vandersleyen 6 | License: see project LICENSE 7 | Touched: 2022 8 | */ 9 | pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs-comment,.hljs-meta{color:#565f89}.hljs-deletion,.hljs-doctag,.hljs-regexp,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-selector-pseudo,.hljs-tag,.hljs-template-tag,.hljs-variable.language_{color:#f7768e}.hljs-link,.hljs-literal,.hljs-number,.hljs-params,.hljs-template-variable,.hljs-type,.hljs-variable{color:#ff9e64}.hljs-attribute,.hljs-built_in{color:#e0af68}.hljs-keyword,.hljs-property,.hljs-subst,.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#7dcfff}.hljs-selector-tag{color:#73daca}.hljs-addition,.hljs-bullet,.hljs-quote,.hljs-string,.hljs-symbol{color:#9ece6a}.hljs-code,.hljs-formula,.hljs-section{color:#7aa2f7}.hljs-attr,.hljs-char.escape_,.hljs-keyword,.hljs-name,.hljs-operator{color:#bb9af7}.hljs-punctuation{color:#c0caf5}.hljs{background:#1a1b26;color:#9aa5ce}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} 10 | 11 | @tailwind base; 12 | @tailwind components; 13 | 14 | @media (prefers-reduced-motion: no-preference){ 15 | :root { 16 | scroll-behavior: smooth; 17 | } 18 | } 19 | 20 | .dark { 21 | color-scheme: dark; 22 | } 23 | 24 | .hp-gradient { 25 | background: radial-gradient(#366d8c, #111927); 26 | } 27 | 28 | #hp-animation { 29 | pointer-events: none; 30 | } 31 | 32 | #hp-animation canvas { 33 | width: 100%; 34 | height: 100%; 35 | } 36 | 37 | .text-shadow { 38 | text-shadow: 0 0 1rem #081f2a; 39 | } 40 | 41 | @layer components { 42 | .w-350{ 43 | width: 350px; 44 | } 45 | 46 | .w-100-350{ 47 | width: calc(100% - 350px); 48 | } 49 | 50 | .w-800{ 51 | width: 800px; 52 | } 53 | 54 | .side-menu{ 55 | left: -100%; 56 | transition: left 0.5s ease; 57 | } 58 | 59 | .mobile-menu-opened .side-menu{ 60 | left: 0; 61 | } 62 | 63 | .min-w-270{ 64 | min-width: 270px; 65 | } 66 | } 67 | 68 | @tailwind utilities; -------------------------------------------------------------------------------- /src/docs/client-side/js/dark-mode.ts: -------------------------------------------------------------------------------- 1 | const MODE_STORAGE_KEY = 'mode'; 2 | 3 | export const handleDarkLightModes = () => { 4 | 5 | const mode = window.localStorage.getItem(MODE_STORAGE_KEY) || 'light'; 6 | document.documentElement.classList.toggle('dark', mode === 'dark'); 7 | 8 | const $moveToDarkBtn = document.getElementById('move-to-dark-mode-btn') as HTMLButtonElement; 9 | const $moveToLightBtn = document.getElementById('move-to-light-mode-btn') as HTMLButtonElement; 10 | 11 | const moveToDark = () => { 12 | document.documentElement.classList.add('dark'); 13 | $moveToDarkBtn.classList.add('hidden'); 14 | $moveToLightBtn.classList.remove('hidden'); 15 | window.localStorage.setItem(MODE_STORAGE_KEY, 'dark'); 16 | }; 17 | 18 | const moveToLight = () => { 19 | document.documentElement.classList.remove('dark'); 20 | $moveToLightBtn.classList.add('hidden'); 21 | $moveToDarkBtn.classList.remove('hidden'); 22 | window.localStorage.setItem(MODE_STORAGE_KEY, 'light'); 23 | }; 24 | 25 | if(mode === 'dark'){ 26 | moveToDark(); 27 | } 28 | else{ 29 | moveToLight(); 30 | } 31 | 32 | $moveToDarkBtn?.addEventListener('click', moveToDark); 33 | $moveToLightBtn?.addEventListener('click', moveToLight); 34 | }; 35 | -------------------------------------------------------------------------------- /src/docs/client-side/js/index.tsx: -------------------------------------------------------------------------------- 1 | import { initMenuCollapsible, initMenuScroll } from './menu/side-menu'; 2 | import { initMobileMenu } from './menu/mobile-menu'; 3 | import { handleDarkLightModes } from './dark-mode'; 4 | // import hljs from 'highlight.js'; 5 | import particles from 'mz-particles'; 6 | 7 | const initAnimation = () => { 8 | const $placeholder = document.getElementById('hp-animation'); 9 | if(!$placeholder) return; 10 | 11 | particles({ 12 | $placeholder, 13 | particlesNumber: 100, 14 | 15 | minSize: 10, 16 | maxSize: 30, 17 | 18 | particlesColors: [ 19 | '#366d8c', '#368c8c', '#fffc00', '#92fae7', 20 | '#5daed2', '#366d8c' 21 | ], 22 | connectionColor: '#7fb2b7', 23 | 24 | // stars ------------- 25 | svgPathData: [ 26 | 'm14.5 21.75-8.52289 4.48075 1.62773-9.49038-6.89516-6.72112 9.52888-1.38462L14.5 0l4.26144 8.63463 9.52888 1.38462-6.89516 6.72112 1.62773 9.49038z', 27 | 'M14.5 21.75 4.24695 24.75305 7.25 14.5 4.24695 4.24695 14.5 7.25l10.25305-3.00305L21.75 14.5l3.00305 10.25305z', 28 | 'm14.5 21.75-5.54891 6.14625.42239-8.26973-8.26973.42239L7.25 14.5 1.10375 8.95109l8.26973.42239-.42239-8.26973L14.5 7.25l5.54891-6.14625-.42239 8.26973 8.26973-.42239L21.75 14.5l6.14625 5.54891-8.26973-.42239.42239 8.26973z', 29 | ], 30 | 31 | // effects ------------ 32 | rotate: true, 33 | // fadeInOut: true, 34 | 35 | // scale effect ------- 36 | scaleInOut: true, 37 | maxScale: 1.2, 38 | minScale: 0.7, 39 | scaleStep: 0.005, 40 | }); 41 | }; 42 | 43 | const init = () => { 44 | const $special = document.getElementById('special-page'); 45 | if($special) { 46 | initAnimation(); 47 | 48 | /*if(hljs){ 49 | hljs.highlightAll(); 50 | }*/ 51 | return; 52 | } 53 | 54 | initMobileMenu(); 55 | initMenuScroll(); 56 | initMenuCollapsible(); 57 | handleDarkLightModes(); 58 | }; 59 | 60 | document.addEventListener('DOMContentLoaded', () => { 61 | init(); 62 | }); 63 | 64 | export {}; 65 | -------------------------------------------------------------------------------- /src/docs/client-side/js/menu/mobile-menu.ts: -------------------------------------------------------------------------------- 1 | export const initMobileMenu = () => { 2 | const $btn = document.getElementById('mobile-menu-btn'); 3 | if(!$btn) return; 4 | 5 | $btn.addEventListener('click', (evt) => { 6 | evt.stopPropagation(); 7 | document.body.classList.toggle('mobile-menu-opened'); 8 | }); 9 | 10 | document.body.addEventListener('click', () => { 11 | document.body.classList.remove('mobile-menu-opened'); 12 | }); 13 | 14 | const $sideMenu = document.getElementById('side-menu'); 15 | if(!$sideMenu) return; 16 | 17 | $sideMenu.addEventListener('click', (evt) => { 18 | evt.stopPropagation(); 19 | }); 20 | 21 | const $close = document.getElementById('mobile-menu-close-btn'); 22 | if(!$close) return; 23 | 24 | $close.addEventListener('click', () => { 25 | document.body.classList.remove('mobile-menu-opened'); 26 | }); 27 | }; 28 | -------------------------------------------------------------------------------- /src/docs/client-side/js/menu/side-menu.ts: -------------------------------------------------------------------------------- 1 | const COLLAPSIBLE_STORAGE_KEY = 'side-menu'; 2 | 3 | interface ICollapsible { 4 | id: string; 5 | opened: boolean; 6 | } 7 | 8 | export const initMenuScroll = () => { 9 | const $menu = document.querySelector('.side-menu'); 10 | if(!$menu) return; 11 | 12 | const path = window.location.pathname; 13 | const $link = $menu.querySelector(`a[href='${ path }']`); 14 | if(!$link) return; 15 | 16 | $link.scrollIntoView({ 17 | block: 'center', 18 | }); 19 | }; 20 | 21 | const getStateFromStorage = (): ICollapsible[] => { 22 | const data = window.localStorage.getItem(COLLAPSIBLE_STORAGE_KEY); 23 | if(!data) return []; 24 | 25 | let menu: ICollapsible[] = []; 26 | 27 | try{ 28 | menu = JSON.parse(data) || []; 29 | } 30 | catch(ex){ 31 | // ... 32 | } 33 | 34 | return menu; 35 | }; 36 | 37 | const saveStateToStorage = () => { 38 | const $titles = document.querySelectorAll('.side-menu [data-collapsible-title]'); 39 | const menu: ICollapsible[] = []; 40 | 41 | for(const $title of $titles){ 42 | const id = $title.getAttribute('data-id') || ''; 43 | if(!id) continue; 44 | 45 | const opened = $title.getAttribute('data-opened') === 'true'; 46 | 47 | menu.push({ 48 | id, 49 | opened 50 | }); 51 | } 52 | 53 | window.localStorage.setItem(COLLAPSIBLE_STORAGE_KEY, JSON.stringify(menu)); 54 | }; 55 | 56 | const restoreCollapsible = () => { 57 | const menu = getStateFromStorage(); 58 | if(!Array.isArray(menu)) return; 59 | 60 | for(const menuItem of menu){ 61 | const $title = document.querySelector(`.side-menu [data-id="${ menuItem.id }"]`) as HTMLElement; 62 | if(!$title) continue; 63 | 64 | toggle($title, menuItem.opened, false); 65 | } 66 | }; 67 | 68 | const toggle = ($title: HTMLElement, opened: boolean, saveToStorage: boolean) => { 69 | 70 | $title.setAttribute('data-opened', opened.toString()); 71 | 72 | const $arrow = $title.querySelector('[data-arrow]'); 73 | if(!$arrow) return; 74 | 75 | $arrow.classList.toggle('rotate-90', opened); 76 | $title.nextElementSibling?.classList.toggle('hidden', !opened); 77 | 78 | if(saveToStorage){ 79 | saveStateToStorage(); 80 | } 81 | }; 82 | 83 | export const initMenuCollapsible = () => { 84 | const $titles = document.querySelectorAll('.side-menu [data-collapsible-title]') as NodeListOf; 85 | 86 | for(const $title of $titles){ 87 | 88 | $title.addEventListener('click', () => { 89 | const isOpened = $title.getAttribute('data-opened') === 'true'; 90 | toggle($title, !isOpened, true); 91 | }); 92 | } 93 | 94 | // try to restore collapsible state on page load 95 | restoreCollapsible(); 96 | }; -------------------------------------------------------------------------------- /src/docs/data/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "website": { 3 | "name": "mzMath", 4 | "url": "https://math.mzsoft.org" 5 | }, 6 | "social": { 7 | "github": "https://github.com/mzusin/mz-math", 8 | "email": "miriam.zusin@gmail.com" 9 | }, 10 | "analytics": { 11 | "gtag": "" 12 | } 13 | } -------------------------------------------------------------------------------- /src/docs/data/layouts/special-page-layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% website-name %} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | {% page-content %} 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/docs/data/pages/10-main/1-typescript-usage.md: -------------------------------------------------------------------------------- 1 | ## TypeScript Usage 2 | 3 | To use the library with TypeScript, you need to install the module from npm: 4 | 5 | ```shell 6 | npm install mz-math 7 | ``` 8 | 9 | Or using Yarn: 10 | 11 | ```shell 12 | yarn add mz-math 13 | ``` 14 | 15 | The import any function like **v2Sum**: 16 | ```js 17 | import { v2Sum, Vector2 } from 'mz-math'; 18 | 19 | const v1: Vector2 = [1, 2]; 20 | const v2: Vector2 = [3, 4]; 21 | const sum = v2Sum(v1, v2); // [4, 6] 22 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/10-main/2-browser-usage.md: -------------------------------------------------------------------------------- 1 | ## Browser Usage 2 | 3 | The library can also be used directly in browsers without TypeScript. First, download the [mz-math.min.js](https://github.com/mzusin/mz-math/blob/main/dist/mz-math.min.js) file from the GitHub repository. Then use the **mzMath** global namespace to call any API or function. 4 | 5 | ```html 6 | 7 | 11 | ``` 12 | 13 | The library is also available on the [jsDelivr CND](https://cdn.jsdelivr.net/npm/mz-math/dist/mz-math.min.js): 14 | 15 | ```html 16 | 17 | 21 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/10-main/3-nodejs-usage.md: -------------------------------------------------------------------------------- 1 | ## Node.js Usage 2 | 3 | The library can also be used in Node.js. 4 | 5 | ```shell 6 | npm install mz-math 7 | ``` 8 | 9 | Or using Yarn: 10 | 11 | ```shell 12 | yarn add mz-svg 13 | ``` 14 | 15 | Call any mzMath API or function: 16 | 17 | ```js 18 | const { setDecimalPlaces } = require('mz-math'); 19 | 20 | const rounded = setDecimalPlaces(Math.PI, 2); 21 | console.log(rounded); 22 | ``` 23 | -------------------------------------------------------------------------------- /src/docs/data/pages/100-color/1-color.md: -------------------------------------------------------------------------------- 1 | # Color 2 | 3 | The library contains several color helper functions. It works with the following color types: 4 | 5 | ```js 6 | import { HSLColor, RGBColor, LABColor } from 'mz-math'; 7 | 8 | // [hue, saturation, lightness] 9 | const hslColor: HSLColor = [0, 0, 0]; // [0-360, 0-100, 0-100] 10 | 11 | // [r, g, b] 12 | const rgbColor: RGBColor = [255, 255, 255]; // [0, 255, 0, 255, 0, 255] 13 | 14 | // [l, a, b] 15 | const labColor: LABColor = [100, 0, 0]; 16 | ``` 17 | -------------------------------------------------------------------------------- /src/docs/data/pages/100-color/2-random-color.md: -------------------------------------------------------------------------------- 1 | # Get random color 2 | 3 | ```js 4 | import { 5 | HSLColor, RGBColor, getRandomHexColor, 6 | getRandomRGBColor, getRandomHSLColor, 7 | getRandomHSLColorWithHue, getRandomHSLColorWithSaturation, 8 | getRandomHSLColorWithinRanges, getRandomGrayscaleHSLColor 9 | } from 'mz-math'; 10 | 11 | // get random HEX color 12 | const hexColor: string = getRandomHexColor(); 13 | 14 | // get random RGB color 15 | const rgbColor: RGBColor = getRandomRGBColor(); 16 | 17 | // get random HSL color 18 | const hslColor1: HSLColor = getRandomHSLColor(); 19 | 20 | // get random HSL color with the specified hue 21 | const hslColor2: HSLColor = getRandomHSLColorWithHue(300); // hue = 300 22 | 23 | // get random HSL color with the specified saturation 24 | const hslColor2: HSLColor = getRandomHSLColorWithSaturation(50); // saturation = 50 25 | 26 | // get random HSL color with the specified lightness 27 | const hslColor3: HSLColor = getRandomHSLColorWithLightness(50); // lightness = 50 28 | 29 | // get random HSL color with the specified ranges: 30 | // hue: [10, 20], saturation: [0, 100], lightness: [30, 50] 31 | const hslColor4: HSLColor = getRandomHSLColorWithinRanges( 32 | 10, 20, // hue range 33 | 0, 100, // saturation range 34 | 30, 50, // lightness range 35 | ); 36 | 37 | // get random gray color 38 | const hslColor5: HSLColor = getRandomGrayscaleHSLColor(); 39 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/100-color/3-convert-colors.md: -------------------------------------------------------------------------------- 1 | # Convert Colors 2 | 3 | ```js 4 | import { 5 | HSLColor, RGBColor, LABColor, 6 | hslToRgb, rgbToHsl, 7 | hslToHex, rgbToHex, hexToRgb, 8 | rgbToLab, labToRgb, 9 | } from 'mz-math'; 10 | 11 | const decimalPlaces = 2; // optional 12 | 13 | // convert RGB color to HSL color 14 | const hslColor: HSLColor = rgbToHsl([255, 0, 0], decimalPlaces); // [0, 100, 50] - red 15 | 16 | // convert HSL color to RGB color 17 | const rgbColor: RGBColor = hslToRgb([100, 100, 100], decimalPlaces); 18 | 19 | // convert HSL color to hex 20 | const hex: string = hslToHex([10, 10, 10]); // #1c1817 21 | 22 | // convert RGB color to hex 23 | const hex: string = rgbToHex([235, 64, 52]); // #eb4034 24 | 25 | // convert HEX color to RGB 26 | const rgbColor: RGBColor = hexToRgb('#eb4034'); // [235, 64, 52] 27 | 28 | // convert RGB color to LAB 29 | const labColor: LABColor = rgbToLab([255, 255, 255], decimalPlaces); // [100, 0, 0] 30 | 31 | // convert LAB color to RGB 32 | const rgbColor: RGBColor = labToRgb([100, 0, 0], decimalPlaces); // [255, 255, 255] 33 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/100-color/4-shift-colors.md: -------------------------------------------------------------------------------- 1 | # Shift colors 2 | 3 | ```js 4 | import { HSLColor, getShiftedHue, getShiftedSaturation, getShiftedLightness } from 'mz-math'; 5 | 6 | // shift hue in [0, 0, 39] by -10 degrees 7 | const hslColor1: HSLColor = getShiftedHue([0, 0, 39], -10); // [350, 0, 39] 8 | 9 | // shift saturation in [0, 0, 39] by 10 10 | const hslColor2: HSLColor = getShiftedSaturation([0, 100, 39], 10); // [0, 10, 39] 11 | 12 | // shift lightness in [0, 0, 39] by 10 13 | const hslColor3: HSLColor = getShiftedLightness([0, 0, 39], 10); // [10, 0, 39] 14 | ``` 15 | -------------------------------------------------------------------------------- /src/docs/data/pages/100-color/5-similar-colors.md: -------------------------------------------------------------------------------- 1 | # Similar Colors 2 | 3 | ```js 4 | import { getColorsDelta, RGBColor } from 'mz-math'; 5 | 6 | const decimalPlaces = 2; // optional 7 | 8 | const rgb1: RGBColor = [255, 0, 0]; 9 | const rgb2: RGBColor = [255, 0, 0]; 10 | 11 | const delta: number = getColorsDelta(rgb1, rgb2, decimalPlaces); 12 | ``` 13 |
14 | 15 | **Result** 16 | 17 | | Value | Description | 18 | |---------|----------------------------------------| 19 | | <= 1.0 | Not perceptible by human eyes. | 20 | | 1 - 2 | Perceptible through close observation. | 21 | | 2 - 10 | Perceptible at a glance. | 22 | | 11 - 49 | Colors are more similar than opposite | 23 | | 100 | Colors are exact opposite | 24 | 25 | 26 | [Source - RGB-LAB Repo](https://github.com/antimatter15/rgb-lab) -------------------------------------------------------------------------------- /src/docs/data/pages/1000-other/1-set-decimal-places.md: -------------------------------------------------------------------------------- 1 | # Set Decimal Places 2 | 3 | This helper allows to format a number to show a selected number of decimal places. 4 | 5 | ```js 6 | import { setDecimalPlaces } from 'mz-math'; 7 | 8 | const res = setDecimalPlaces(1.2345, 2); // 1.23 9 | const res = setDecimalPlaces(1.2399, 2); // 1.24 10 | const res = setDecimalPlaces(1.2399, 0); // 1 11 | ``` 12 | 13 | The result of this function is a number (not a string), so sometimes fewer decimal places will be displayed after rounding: 14 | 15 | ```js 16 | const res = setDecimalPlaces(1.239999, 4); // 1.2400 = 1.24 17 | ``` 18 | -------------------------------------------------------------------------------- /src/docs/data/pages/1000-other/10-series.md: -------------------------------------------------------------------------------- 1 | # Series 2 | 3 | ```js 4 | import { naturalNumbersSum1ToN } from 'mz-math'; 5 | 6 | // 1 + 2 + 3 7 | const sum = naturalNumbersSum1ToN(3); // 6; 8 | ``` 9 | 10 | ```js 11 | import { naturalNumbersSumMToN } from 'mz-math'; 12 | 13 | // 5 + 6 + 7 14 | const sum = naturalNumbersSumMToN(5, 7); // 18 15 | ``` 16 | -------------------------------------------------------------------------------- /src/docs/data/pages/1000-other/11-greatest-common-divisor.md: -------------------------------------------------------------------------------- 1 | # Greatest common divisor (GCD) 2 | 3 | ```js 4 | import { gcd } from 'mz-math'; 5 | 6 | const res1 = gcd(18, 6); // 6; 7 | const res2 = gcd(18, -6); // 6; 8 | ``` 9 | -------------------------------------------------------------------------------- /src/docs/data/pages/1000-other/2-convert-string-to-number.md: -------------------------------------------------------------------------------- 1 | # Convert string to number 2 | 3 | This function converts a numeric string to a number. If the string is not a number, it returns the provided default value. 4 | 5 | ```js 6 | import { stringToNumber } from 'mz-math'; 7 | 8 | const res = stringToNumber('10.1234', 10); // 10.1234 9 | const res = stringToNumber(undefined, 10); // 10 10 | const res = stringToNumber(null, 10); // 10 11 | const res = stringToNumber('aaa', 10); // 10 12 | ``` 13 | -------------------------------------------------------------------------------- /src/docs/data/pages/1000-other/3-square-in-circle.md: -------------------------------------------------------------------------------- 1 | # Square in circle 2 | 3 | Get the side of a square inscribed in a circle of a given radius: 4 | 5 | ```js 6 | import { getSquareInCircleSide } from 'mz-math'; 7 | 8 | const circleRadius = 10; 9 | const decimalPlaces = 2; // optional 10 | 11 | const squareSide = getSquareInCircleSide(10); // 14.14 12 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/1000-other/4-modulo.md: -------------------------------------------------------------------------------- 1 | # Modulo 2 | 3 | Calculate the modulo for positive or negative numbers. 4 | 5 | ```js 6 | import { mod } from 'mz-math'; 7 | 8 | const res1 = mod(-21, 4); // 3 9 | const res2 = mod(7, 3); // 1 10 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/1000-other/5-convert-range.md: -------------------------------------------------------------------------------- 1 | # Convert range 2 | 3 | Converting a number from the range [a,b] to the range [c,d]. 4 | 5 | ```js 6 | import { convertRange } from 'mz-math'; 7 | 8 | // convert the value 0.5 from the range [0,1] to the range [100,200] 9 | const res = convertRange(0.5, 0, 1, 100, 200); // 150 10 | ``` 11 | -------------------------------------------------------------------------------- /src/docs/data/pages/1000-other/6-check-if-ranges-overlap.md: -------------------------------------------------------------------------------- 1 | # Check if two ranges overlap 2 | 3 | ```js 4 | import { doRangesOverlap } from 'mz-math'; 5 | 6 | // [0,1] and [100,200] don't overlap 7 | const res1 = doRangesOverlap(0, 1, 100, 200); // false 8 | 9 | // [0,1] and [0.5, 1.5] overlap 10 | const res2 = doRangesOverlap(0, 1, 0.5, 1.5); // true 11 | ``` 12 | -------------------------------------------------------------------------------- /src/docs/data/pages/1000-other/7-check-if-value-is-number.md: -------------------------------------------------------------------------------- 1 | # Check if value can be converted to number 2 | 3 | ```js 4 | import { isNumber } from 'mz-math'; 5 | 6 | const res = isNumber('12'); // true 7 | const res = isNumber(12.5); // true 8 | const res = isNumber('0'); // true 9 | const res = isNumber(0); // true 10 | 11 | const res = isNumber('aaa'); // false 12 | const res = isNumber(null); // false 13 | const res = isNumber(undefined); // false 14 | const res = isNumber(Infinity); // false 15 | ``` 16 | -------------------------------------------------------------------------------- /src/docs/data/pages/1000-other/8-polar-to-cartesian.md: -------------------------------------------------------------------------------- 1 | # Conversion between polar & cartesian coordinates 2 | 3 | ```js 4 | import { polarToCartesian, Vector2 } from 'mz-math'; 5 | 6 | const center: Vector2 = [0, 0]; 7 | const radii: Vector2 = [10, 20]; 8 | const angleInRad = Math.PI / 4; 9 | const decimalPlaces = 2; // optional 10 | 11 | const res: Vector2 = polarToCartesian(center, radii, angleInRad, decimalPlaces); // 7.07, 14.14 12 | ``` 13 | -------------------------------------------------------------------------------- /src/docs/data/pages/1000-other/9-temperature-conversion.md: -------------------------------------------------------------------------------- 1 | # Temperature Conversions 2 | 3 | These functions allow conversion between different temperature scales. They accept a temperature value in one scale and return the equivalent temperature in another scale, with optional rounding to a specified number of decimal places. 4 | 5 | ```js 6 | import { celsiusToFahrenheit } from 'mz-math'; 7 | 8 | const fahrenheit = celsiusToFahrenheit(0); // 32 9 | 10 | const fahrenheitRoundedTo2 = celsiusToFahrenheit(32.698034, 2); // 90.86; 11 | ``` 12 | 13 | ```js 14 | import { celsiusToKelvin } from 'mz-math'; 15 | 16 | const kelvin = celsiusToKelvin(-273.15); // 0 17 | ``` 18 | 19 | ```js 20 | import { fahrenheitToCelsius } from 'mz-math'; 21 | 22 | const celsius = fahrenheitToCelsius(32); // 0 23 | ``` 24 | 25 | ```js 26 | import { fahrenheitToKelvin } from 'mz-math'; 27 | 28 | const kelvin = fahrenheitToKelvin(32); // 273.15 29 | ``` 30 | 31 | ```js 32 | import { kelvinToCelsius } from 'mz-math'; 33 | 34 | const celsius = kelvinToCelsius(273.15); // 0 35 | ``` 36 | 37 | ```js 38 | import { kelvinToFahrenheit } from 'mz-math'; 39 | 40 | const fahrenheit = kelvinToFahrenheit(273.15); // 32 41 | ``` 42 | -------------------------------------------------------------------------------- /src/docs/data/pages/105-linear-interpolation/1-lerp.md: -------------------------------------------------------------------------------- 1 | # Lerp 2 | 3 | Lerp function performs a linear interpolation in the given range. 4 | Here **x** is a value that linearly interpolates between the **start** parameter and the **end** parameter. 5 | 6 | ```js 7 | import { lerp } from 'mz-math'; 8 | 9 | const x = 5; 10 | const start = 0; 11 | const end = 100; 12 | const decimalPlaces = 2; // optional 13 | 14 | const result = lerp(x, start, end, decimalPlaces); // 500 15 | ``` 16 | 17 | There are also versions of the lerp function for working with vectors of numbers: 18 | 19 | **2D Vector** 20 | 21 | ```js 22 | import { v2Lerp, Vector2 } from 'mz-math'; 23 | 24 | const x = 15; 25 | const start: Vector2 = [0, 100]; 26 | const end: Vector2 = [50, 1000]; 27 | const decimalPlaces = 2; // optional 28 | 29 | const result: Vector2 = v2Lerp(x, start, end, decimalPlaces); 30 | ``` 31 | 32 | **3D Vector** 33 | 34 | ```js 35 | import { v3Lerp, Vector3 } from 'mz-math'; 36 | 37 | const x = 15; 38 | const start: Vector3 = [0, 100, 500]; 39 | const end: Vector3 = [50, 400, 900]; 40 | const decimalPlaces = 2; // optional 41 | 42 | const result: Vector3 = v3Lerp(x, start, end, decimalPlaces); 43 | ``` 44 | 45 | **General Case** 46 | 47 | ```js 48 | import { vLerp, Vector } from 'mz-math'; 49 | 50 | const x = 15; 51 | const start: Vector = [0, 100, 500, 1500]; 52 | const end: Vector = [50, 400, 900, 2000]; 53 | const decimalPlaces = 2; // optional 54 | 55 | const result: Vector = vLerp(x, start, end, decimalPlaces); 56 | ``` 57 | 58 | There are also versions of the lerp function for working with matrices of numbers: 59 | 60 | **2D Matrix** 61 | 62 | ```js 63 | import { m2Lerp, Matrix2 } from 'mz-math'; 64 | 65 | const x = 15; 66 | const start: Matrix2 = [ 67 | [1, 2], 68 | [3, 4], 69 | ]; 70 | const end: Matrix2 = [ 71 | [100, 200], 72 | [300, 400], 73 | ]; 74 | const decimalPlaces = 2; // optional 75 | 76 | const result: Matrix2 = m2Lerp(x, start, end, decimalPlaces); 77 | ``` 78 | 79 | **3D Matrix** 80 | 81 | ```js 82 | import { m3Lerp, Matrix3 } from 'mz-math'; 83 | 84 | const x = 15; 85 | const start: Matrix3 = [ 86 | [1, 2, 3], 87 | [4, 5, 6], 88 | ]; 89 | const end: Matrix3 = [ 90 | [100, 200, 300], 91 | [400, 500, 600], 92 | ]; 93 | const decimalPlaces = 2; // optional 94 | 95 | const result: Matrix3 = m3Lerp(x, start, end, decimalPlaces); 96 | ``` 97 | 98 | **General Case** 99 | 100 | ```js 101 | import { mLerp, Matrix } from 'mz-math'; 102 | 103 | const x = 25; 104 | const start: Matrix = [ 105 | [1, 2, 3, 4], 106 | [4, 5, 6, 12], 107 | ]; 108 | const end: Matrix = [ 109 | [100, 200, 300, 800], 110 | [400, 500, 600, 1200], 111 | ]; 112 | const decimalPlaces = 2; // optional 113 | 114 | const result: Matrix = mLerp(x, start, end, decimalPlaces); 115 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/105-linear-interpolation/2-general-case.md: -------------------------------------------------------------------------------- 1 | # General linear interpolation 2 | 3 | The **linearInterpolation()** function calculates linear interpolation using the following formula: `Y = ((X - X1) * (Y2 - Y1) / (X2 - X1)) + Y1`. 4 | 5 | ```js 6 | import { linearInterpolation, Vector2 } from 'mz-math'; 7 | 8 | const x = 25; 9 | const start: Vector2 = [10, 50]; 10 | const end: Vector2 = [100, 350]; 11 | const decimalPlaces = 2; // optional 12 | 13 | const result = linearInterpolation(x, start, end, decimalPlaces); 14 | ``` 15 | -------------------------------------------------------------------------------- /src/docs/data/pages/110-derivatives/1-polynomial.md: -------------------------------------------------------------------------------- 1 | # Derivatives of Polynomials 2 | 3 | To take derivatives of a polynomial, you can use **dxPolynomial()** function. 4 | The polynomial is represented as an array, where each element is [coefficient, power]. For example, **y = 3x+2** is represented as **[[3, 1], [2, 0]]**. 5 | 6 | ```js 7 | import { dxPolynomial } from 'mz-math'; 8 | 9 | const x = 10; 10 | 11 | // y = 3x+2 12 | const polynomial = [[3, 1], [2, 0]]; 13 | 14 | const decimalPlaces = 2; // optional 15 | 16 | const result = dxPolynomial(x, polynomial, decimalPlaces); 17 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/110-derivatives/2-trigonometric-functions.md: -------------------------------------------------------------------------------- 1 | # Derivatives of trigonometric functions 2 | 3 | **Sine Function** 4 | 5 | ```js 6 | import { dxSin } from 'mz-math'; 7 | 8 | const decimalPlaces = 2; // optional 9 | const result = dxSin(Math.PI, decimalPlaces); // -1 10 | ``` 11 | 12 | **Cosine Function** 13 | 14 | ```js 15 | import { dxCos } from 'mz-math'; 16 | 17 | const decimalPlaces = 2; // optional 18 | const result = dxCos(Math.PI/2, decimalPlaces); // -1 19 | ``` 20 | 21 | **Tangent Function** 22 | 23 | ```js 24 | import { dxTan } from 'mz-math'; 25 | 26 | const decimalPlaces = 2; // optional 27 | const result = dxTan(Math.PI, decimalPlaces); // 1 28 | ``` 29 | 30 | **Cotangent Function** 31 | 32 | ```js 33 | import { dxCot } from 'mz-math'; 34 | 35 | const decimalPlaces = 2; // optional 36 | const result = dxCot(Math.PI/2, decimalPlaces); // -1 37 | ``` 38 | 39 | **ArcSine Function** 40 | 41 | ```js 42 | import { dxArcSin } from 'mz-math'; 43 | 44 | const decimalPlaces = 2; // optional 45 | const result = dxArcSin(Math.PI/4, decimalPlaces); // 1.62 46 | ``` 47 | 48 | **ArcCosine Function** 49 | 50 | ```js 51 | import { dxArcCos } from 'mz-math'; 52 | 53 | const decimalPlaces = 2; // optional 54 | const result = dxArcCos(Math.PI/4, decimalPlaces); // -1.62 55 | ``` 56 | 57 | **ArcTangent Function** 58 | 59 | ```js 60 | import { dxArcTan } from 'mz-math'; 61 | 62 | const decimalPlaces = 2; // optional 63 | const result = dxArcTan(Math.PI/4, decimalPlaces); // 0.62 64 | ``` 65 | 66 | **ArcCotangent Function** 67 | 68 | ```js 69 | import { dxArcCot } from 'mz-math'; 70 | 71 | const decimalPlaces = 2; // optional 72 | const result = dxArcCot(Math.PI/4, decimalPlaces); // -0.62 73 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/110-derivatives/3-bezier-curves.md: -------------------------------------------------------------------------------- 1 | # Derivatives of Bézier Curves 2 | 3 | To take derivatives of a quadratic Bézier Curve, you can use **dxV2QuadraticBezierCurve()** or **dxV3QuadraticBezierCurve()** functions. 4 | 5 | ```js 6 | import { dxV2QuadraticBezierCurve, Vector2 } from 'mz-math'; 7 | 8 | const t = 0.6; // mast be in range [0, 1] 9 | const startControlPoint: Vector2 = [150, 550]; 10 | const centerControlPoint: Vector2 = [400, 300]; 11 | const endControlPoint: Vector2 = [50, 550]; 12 | const decimalPlaces = 2; // optional 13 | 14 | const result: Vector2 = dxV2QuadraticBezierCurve( 15 | t, 16 | startControlPoint, 17 | centerControlPoint, 18 | endControlPoint, 19 | decimalPlaces 20 | ); 21 | ``` 22 | 23 | ```js 24 | import { dxV3QuadraticBezierCurve, Vector3 } from 'mz-math'; 25 | 26 | const t = 0.6; // mast be in range [0, 1] 27 | const startControlPoint: Vector3 = [150, 550, 0]; 28 | const centerControlPoint: Vector3 = [400, 300, 0]; 29 | const endControlPoint: Vector3 = [50, 550, 0]; 30 | const decimalPlaces = 2; // optional 31 | 32 | const result: Vector3 = dxV3QuadraticBezierCurve( 33 | t, 34 | startControlPoint, 35 | centerControlPoint, 36 | endControlPoint, 37 | decimalPlaces 38 | ); 39 | ``` 40 | 41 | To take derivatives of a cubic Bézier Curve, you can use **dxV2CubicBezierCurve()** or **dxV3CubicBezierCurve()** functions. 42 | 43 | ```js 44 | import { dxV2CubicBezierCurve, Vector2 } from 'mz-math'; 45 | 46 | const t = 0.6; // mast be in range [0, 1] 47 | const startControlPoint: Vector2 = [100, 200]; 48 | const center1ControlPoint: Vector2 = [100, 50]; 49 | const center2ControlPoint: Vector2 = [200, 150]; 50 | const endControlPoint: Vector2 = [300, 250]; 51 | const decimalPlaces = 2; // optional 52 | 53 | const result: Vector2 = dxV2CubicBezierCurve( 54 | t, 55 | startControlPoint, 56 | center1ControlPoint, 57 | center2ControlPoint, 58 | endControlPoint, 59 | decimalPlaces 60 | ); 61 | ``` 62 | 63 | ```js 64 | import { dxV3CubicBezierCurve, Vector3 } from 'mz-math'; 65 | 66 | const t = 0.6; // mast be in range [0, 1] 67 | const startControlPoint: Vector3 = [100, 200, 0]; 68 | const center1ControlPoint: Vector3 = [100, 50, 0]; 69 | const center2ControlPoint: Vector3 = [200, 150, 0]; 70 | const endControlPoint: Vector3 = [300, 250, 0]; 71 | const decimalPlaces = 2; // optional 72 | 73 | const result: Vector3 = dxV3CubicBezierCurve( 74 | t, 75 | startControlPoint, 76 | center1ControlPoint, 77 | center2ControlPoint, 78 | endControlPoint, 79 | decimalPlaces 80 | ); 81 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/120-collision-detection/1-rectangles-collision.md: -------------------------------------------------------------------------------- 1 | # Rectangles Collision 2 | 3 | This function **rectCollide()** returns true if the rectangles collide. 4 | 5 | ```ts 6 | import { rectCollide } from 'mz-math'; 7 | 8 | const rect1 = { x: 0, y: 0, w: 10, h: 10 }; 9 | const rect2 = { x: 5, y: 5, w: 10, h: 10 }; 10 | 11 | const isCollide = rectCollide(rect1, rect2); // true 12 | ``` 13 | 14 | **IRect** TypeScript interface is defined as follows: 15 | 16 | ```ts 17 | export interface IRect { 18 | x: number; 19 | y: number; 20 | w: number; 21 | h: number; 22 | } 23 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/120-collision-detection/2-circles-collision.md: -------------------------------------------------------------------------------- 1 | # Circles Collision 2 | 3 | This function **circleCollide()** returns true if the circles collide. 4 | 5 | ```ts 6 | import { circleCollide } from 'mz-math'; 7 | 8 | const circle1 = { cx: 0, cy: 0, r: 10 }; 9 | const circle2 = { cx: 20, cy: 20, r: 5 }; 10 | 11 | const isCollide = circleCollide(rect1, rect2); // false 12 | ``` 13 | 14 | **ICircle** TypeScript interface is defined as follows: 15 | 16 | ```ts 17 | export interface ICircle { 18 | cx: number; 19 | cy: number; 20 | r: number; 21 | } 22 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/120-collision-detection/3-convex-polygons-collision.md: -------------------------------------------------------------------------------- 1 | # Convex Polygons Collision 2 | 3 | This function **convexPolygonsCollide()** returns true if the convex polygons collide. It implements Separating Axis Theorem (SAT). 4 | 5 | ```ts 6 | import { convexPolygonsCollide } from 'mz-math'; 7 | 8 | const poly1: Vector2[] = [[0, 0], [10, 0], [5, 10]]; 9 | const poly2: Vector2[] = [[5, 5], [15, 5], [10, 15]]; 10 | 11 | const isCollide = convexPolygonsCollide(poly1, poly2); // true 12 | ``` 13 | 14 | **IPolygon** type is defined as follows: 15 | 16 | ```ts 17 | export type IPolygon = Vector2[]; 18 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/130-animation/1-animation.md: -------------------------------------------------------------------------------- 1 | # Animation 2 | 3 | The library contains an animation API that can control the animation flow. Basic usage: 4 | 5 | ```ts 6 | import { animate, IAnimationResult } from 'mz-math'; 7 | 8 | const api: IAnimationResult = animate({ 9 | 10 | // A function to be called on each animation frame. 11 | // It receives an object of type IAnimationResult. 12 | callback: (result: IAnimationResult) => { 13 | // DO ANY RENDERING LOGIC HERE 14 | }, 15 | 16 | // Optional property. 17 | // The duration of the animation in milliseconds. 18 | // If not provided, the animation will continue indefinitely. 19 | duration: 1000, 20 | 21 | // Optional property. 22 | // If true, the animation will restart whenever 23 | // the size of the document body changes. Default is false. 24 | restartOnResize: true, 25 | 26 | // Optional property. 27 | resizeCallback: (_entries: ResizeObserverEntry[], _observer: ResizeObserver) => { 28 | // Do something on resize 29 | } 30 | }); 31 | 32 | // Starts the animation. 33 | api.start(); 34 | 35 | /* 36 | // Stops the animation. 37 | api.stop(); 38 | 39 | // Pauses the animation. 40 | api.pause(); 41 | 42 | // Resumes the animation from where it was paused. 43 | api.resume(); 44 | 45 | // Restarts the animation from the beginning. 46 | api.restart(); 47 | */ 48 | ``` 49 | 50 | 51 | The **IAnimationResult** interface defines the methods and properties returned by the animate function. 52 | 53 | ```ts 54 | export interface IAnimationResult { 55 | start: () => void; 56 | stop: () => void; 57 | pause: () => void; 58 | resume: () => void; 59 | restart: () => void; 60 | isAnimating: () => boolean; 61 | getStartTime: () => number|undefined; 62 | getElapsedTime: () => number|undefined; 63 | getPercent: () => number|undefined; 64 | getResizeObserver: () => ResizeObserver|undefined; 65 | } 66 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/130-animation/2-get-animation-data.md: -------------------------------------------------------------------------------- 1 | # Get Animation Data 2 | 3 | The animation API has various helpers for getting information about the current animation. 4 | 5 | ```ts 6 | // Returns true if the animation is currently running, false otherwise. 7 | const animating: boolean = api.isAnimating(); 8 | ``` 9 | 10 | ```ts 11 | // Returns the timestamp (in milliseconds) when the animation was started. 12 | const animating: number = api.getStartTime(); 13 | ``` 14 | 15 | ```ts 16 | // Returns the time elapsed (in milliseconds) since the animation was started. 17 | const animating: number = api.getElapsedTime(); 18 | ``` 19 | 20 | ```ts 21 | // Returns the percentage of the animation that has been completed (0 to 100). 22 | // Returns undefined if the duration is infinite, or if the animation hasn't started yet. 23 | const percent: number = api.getPercent(); 24 | ``` 25 | 26 | ```ts 27 | // Returns the ResizeObserver used by the animation to detect changes in the size of the document body. 28 | // Returns undefined if restartOnResize property is false. 29 | const observer: ResizeObserve = api.getResizeObserver(); 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /src/docs/data/pages/140-circle-and-ellipse/1-circumference.md: -------------------------------------------------------------------------------- 1 | # Get Circle & Ellipse Circumference 2 | 3 | **Get Circle Circumference** 4 | 5 | ```js 6 | import { getCircleCircumference } from 'mz-math'; 7 | 8 | const radius = 10; 9 | const decimalPlaces = 2; // optional 10 | 11 | const circumference = getCircleCircumference(radius, decimalPlaces); // 62.83 12 | ``` 13 | 14 | **Get Ellipse Circumference** 15 | 16 | ```js 17 | import { getEllipseCircumference } from 'mz-math'; 18 | 19 | const radius1 = 10; 20 | const radius1 = 20; 21 | const decimalPlaces = 2; // optional 22 | 23 | const circumference = getEllipseCircumference(radius1, radius2, decimalPlaces); // 99.35 24 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/140-circle-and-ellipse/2-is-angle-in-circle-arc.md: -------------------------------------------------------------------------------- 1 | # Get Circle & Ellipse Circumference 2 | 3 | The isAngleInCircleArc() function checks whether a given angle falls within a circular arc defined by a start angle and an end angle. It considers the possibility of the arc crossing the 360-degree mark and handles it accordingly. 4 | 5 | ```js 6 | import { isAngleInCircleArc } from 'mz-math'; 7 | 8 | const startAngleDeg = 0; 9 | const endAngleDeg = 90; 10 | const currentDegrees = 45; 11 | 12 | const isInAcr = isAngleInCircleArc(startAngleDeg, endAngleDeg, currentDegrees); // true 13 | ``` 14 | 15 | ```js 16 | import { isAngleInCircleArc } from 'mz-math'; 17 | 18 | const startAngleDeg = 0; 19 | const endAngleDeg = 90; 20 | const currentDegrees = 180; 21 | 22 | const isInAcr = isAngleInCircleArc(startAngleDeg, endAngleDeg, currentDegrees); // false 23 | ``` 24 | -------------------------------------------------------------------------------- /src/docs/data/pages/150-sequence/1-natural-numbers-sequence-sum.md: -------------------------------------------------------------------------------- 1 | # Natural Numbers Sequence Sum 2 | 3 | ```js 4 | import { arithmeticSequenceSum } from 'mz-math'; 5 | 6 | const sum = arithmeticSequenceSum(5); // 15 7 | ``` 8 | -------------------------------------------------------------------------------- /src/docs/data/pages/150-sequence/2-arithmetic-sequence-sum.md: -------------------------------------------------------------------------------- 1 | # Arithmetic Sequence Sum 2 | 3 | ```js 4 | import { naturalNumbersSequenceSum } from 'mz-math'; 5 | 6 | // n = the number of terms to be added 7 | const n = 4; 8 | 9 | // a = the first term in the sequence 10 | const a = 2; 11 | 12 | // d = the constant value between terms 13 | const d = 2; 14 | 15 | // 2 + 4 + 6 + 8 16 | const sum = naturalNumbersSequenceSum(n, a, d); // 20 17 | ``` 18 | -------------------------------------------------------------------------------- /src/docs/data/pages/160-combinatorics/1-factorial.md: -------------------------------------------------------------------------------- 1 | # Factorial 2 | 3 | ```js 4 | import { factorial } from 'mz-math'; 5 | 6 | const res1 = factorial(5); // 1*2*3*4*5 = 120 7 | const res2 = factorial(5, 3); // 3*4*5 = 60 8 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/160-combinatorics/2-combinatorics.md: -------------------------------------------------------------------------------- 1 | # Combinatorics 2 | 3 | ```js 4 | import { 5 | permutationsWithRepetition, 6 | permutationsWithoutRepetition, 7 | combinationsWithoutRepetition, 8 | combinationsWithRepetition, 9 | } from 'mz-math'; 10 | 11 | const res1 = permutationsWithRepetition(3, 2); // 9 12 | const res2 = permutationsWithoutRepetition(4, 4); // 24 13 | const res3 = combinationsWithoutRepetition(16, 3); // 560 14 | const res4 = combinationsWithRepetition(5, 3); // 35 15 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/1-vectors.md: -------------------------------------------------------------------------------- 1 | # Vectors 2 | 3 | There are the following types of vectors: 4 | **Vector2** for a 2D vector, **Vector3** for a 3D vector, and **Vector** for the general case. 5 | 6 | ```js 7 | import { Vector2, Vector3, Vector4, Vector } from 'mz-math'; 8 | 9 | const v2: Vector2 = [1, 2]; 10 | const v3: Vector3 = [1, 2, 3]; 11 | const v4: Vector4 = [1, 2, 3, 4]; 12 | 13 | const v5: Vector = [1, 2, 3, 4, 5]; 14 | const v6: Vector = [1, 2, 3, 4, 5, 6]; 15 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/10-distance-between-vectors.md: -------------------------------------------------------------------------------- 1 | ## Get distance between 2 vectors 2 | 3 | **2D vectors** 4 | 5 | ```js 6 | import { v2Distance, Vector2 } from 'mz-math'; 7 | 8 | const v1: Vector2 = [1, 2]; 9 | const v2: Vector2 = [4, 5]; 10 | const distance = v2Distance(v1, v2); 11 | ``` 12 | 13 | **3D vectors** 14 | 15 | ```js 16 | import { v3Distance, Vector2 } from 'mz-math'; 17 | 18 | const v1: Vector2 = [1, 2, 3]; 19 | const v2: Vector2 = [4, 5, 6]; 20 | const distance = v3Distance(v1, v2); 21 | ``` 22 | 23 | **General case** 24 | 25 | ```js 26 | import { vDistance, Vector } from 'mz-math'; 27 | 28 | const v1: Vector = [1, 2, 3]; 29 | const v2: Vector = [4, 5, 6]; 30 | const distance = vDistance(v1, v2); 31 | ``` 32 | -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/11-vector-initialization.md: -------------------------------------------------------------------------------- 1 | ## Vector Initialization Helpers 2 | 3 | There are helpers for creating v2, v3 and vN vectors with a default value. If no default value is specified, it will be zero. 4 | 5 | ```js 6 | import { v2, v3, v4, vN } from 'mz-math'; 7 | 8 | const v2 = v2(); // [0, 0] 9 | const v2_10 = v2(10); // [10, 10] 10 | 11 | const v3 = v3(); // [0, 0, 0] 12 | const v3_10 = v3(10); // [10, 10, 10] 13 | 14 | const v4 = v4(); // [0, 0, 0, 0] 15 | const v4_10 = v4(10); // [10, 10, 10, 10] 16 | 17 | const v5 = vN(5); // [0, 0, 0, 0, 0] 18 | const v5_10 = vN(5, 10); // [10, 10, 10, 10, 10] 19 | ``` 20 | 21 | **Initialize vector using polar coordinates** 22 | 23 | ```js 24 | import { Vector2 } from 'mz-math'; 25 | 26 | const distance = 10; 27 | const angleRad = Math.PI/4; 28 | const v2: Vector2 = v2FromPolarCoords(distance, angleRad); 29 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/12-vectors-equality.md: -------------------------------------------------------------------------------- 1 | ## Check if 2 vectors are equal 2 | 3 | It's possible to perform a deep comparison of two vectors using the **vEqual** function: 4 | 5 | ```js 6 | import { vEqual } from 'mz-math'; 7 | 8 | const res1 = vEqual([1, 0], [1, 0]); // true 9 | const res2 = vEqual([1, 0], [0, 1]); // false 10 | const res3 = vEqual([0, 0, 0], [0, 0]); // false 11 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/13-get-normal.md: -------------------------------------------------------------------------------- 1 | ## Get Vector Normal 2 | 3 | ```js 4 | import { v2GetNormal, Vector2 } from 'mz-math'; 5 | 6 | const vector1: Vector2 = [10, 20]; 7 | const vector2: Vector2 = [20, 30]; 8 | const decimalPlaces = 2; // optional 9 | 10 | const res: Vector2 = v2GetNormal(vector1, vector2, decimalPlaces); // [-10, 10] 11 | ``` 12 | -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/2-vectors-sum.md: -------------------------------------------------------------------------------- 1 | ## Vectors Sum 2 | 3 | The following functions are used to add vectors: **v2Sum** for a 2D vector, **v3Sum** for a 3D vector, and **vSum** for the general case. Each function receives an optional **decimalPlaces** parameter. 4 | 5 | **2D Vector** 6 | ```js 7 | import { v2Sum, Vector2 } from 'mz-math'; 8 | 9 | const sum1 = v2Sum([1, 2], [3, 4]); // [4, 6] 10 | 11 | const vector1: Vector2 = [3.12456, 4.56734]; 12 | const vector2: Vector2 = [5.12323, 6.001234]; 13 | const sum2 = v2Sum(vector1, vector2, 2); // [8.25, 10.57] 14 | ``` 15 | 16 | **3D Vector** 17 | ```js 18 | import { v3Sum, Vector3 } from 'mz-math'; 19 | 20 | const sum1 = v3Sum([1, 2, 3], [3, 4, 4]); // [4, 6, 7] 21 | 22 | const vector1: Vector3 = [3.2345, 4.0013234, 5.2523453]; 23 | const vector2: Vector3 = [6.111, 7.222, 8.333]; 24 | const sum2 = v3Sum(vector1, vector2, 2); // [9.35, 11.22, 13.59] 25 | ``` 26 | 27 | **General Case** 28 | ```js 29 | import { vSum, Vector } from 'mz-math'; 30 | 31 | const v1: Vector = [1, 2, 3, 4]; 32 | const v2: Vector = [5, 6, 7, 8]; 33 | const sum = vSum(v1, v2); // [6, 8, 10, 12]; 34 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/3-vectors-subtraction.md: -------------------------------------------------------------------------------- 1 | ## Vectors Subtraction 2 | 3 | The following functions are used to add vectors: **v2Sub** for a 2D vector, **v3Sub** for a 3D vector, and **vSub** for the general case. Each function receives an optional **decimalPlaces** parameter. 4 | 5 | **2D Vector** 6 | ```js 7 | import { v2Sub, Vector2 } from 'mz-math'; 8 | 9 | const sub1 = v2Sub([1, 2], [3, 4]); // [-2, -2] 10 | 11 | const vector1: Vector2 = [-1.125324, -2.23453245]; 12 | const vector2: Vector2 = [3.2345, 4.3574365]; 13 | const sub2 = v2Sub(vector1, vector2, 2); // [-4.36, -6.59] 14 | ``` 15 | 16 | **3D Vector** 17 | ```js 18 | import { v3Sub, Vector3 } from 'mz-math'; 19 | 20 | const sub1 = v3Sub([1, 2, 3], [3, 4, 4]); // [-2, -2, -1] 21 | 22 | const vector1: Vector3 = [1.12754, 2.999345, 3.34653456]; 23 | const vector2: Vector3 = [7.352345, 8.35734, 9.2345]; 24 | const sub2 = v3Sub(vector1, vector2, 2); // [-6.22, -5.36, -5.89] 25 | ``` 26 | 27 | **General Case** 28 | ```js 29 | import { vSub, Vector } from 'mz-math'; 30 | 31 | const v1: Vector = [1, 2, 3, 4]; 32 | const v2: Vector = [5, 6, 7, 8]; 33 | const sum = vSub(v1, v2); // [-4, -4, -4, -4] 34 | ``` 35 | -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/4-multiply-vector-by-scalar.md: -------------------------------------------------------------------------------- 1 | ## Multiply vector by scalar 2 | 3 | The following functions are used to multiply a vector by a scalar: **v2MulScalar** for a 2D vector, **v3MulScalar** for a 3D vector, and **vMulScalar** for the general case. Each function receives an optional **decimalPlaces** parameter. 4 | 5 | **2D Vector** 6 | ```js 7 | import { v2MulScalar } from 'mz-math'; 8 | 9 | const res = v2MulScalar([1, 2], 2); // [2, 4] 10 | const res = v2MulScalar([1, 2], 0.5); // [0.5, 1] 11 | const res = v2MulScalar([1, 2], Math.PI); // [3.141592653589793, 6.283185307179586] 12 | const res = v2MulScalar([1, 2], Math.PI, 2); // [3.14, 6.28] 13 | ``` 14 | 15 | **3D Vector** 16 | ```js 17 | import { v3MulScalar } from 'mz-math'; 18 | 19 | const res = v3MulScalar([1, 2, 3], 2); // [2, 4, 6] 20 | const res = v3MulScalar([1, 2, 3], 0.5); // [0.5, 1, 1.5] 21 | const res = v3MulScalar([1, 2, 3], Math.PI); // [3.141592653589793, 6.283185307179586, 9.42477796076938] 22 | const res = v3MulScalar([1, 2, 3], Math.PI, 2); // [3.14, 6.28, 9.42] 23 | ``` 24 | 25 | **General Case** 26 | ```js 27 | import { vMulScalar } from 'mz-math'; 28 | 29 | const res = v3MulScalar([1, 2, 3, 4], 2); // [2, 4, 6, 8] 30 | ``` 31 | -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/5-divide-vector-by-scalar.md: -------------------------------------------------------------------------------- 1 | ## Divide vector by scalar 2 | 3 | The following functions are used to divide a vector by a scalar: **v2DivideScalar** for a 2D vector, **v3DivideScalar** for a 3D vector, and **vDivideScalar** for the general case. Each function receives an optional **decimalPlaces** parameter. 4 | 5 | **2D Vector** 6 | ```js 7 | import { v2DivideScalar } from 'mz-math'; 8 | 9 | const res = v2DivideScalar([1, 2], 2); // [0.5, 1] 10 | const res = v2DivideScalar([1, 2], 0.5); // [2, 4] 11 | const res = v2DivideScalar([1, 2], Math.PI); // [0.3183098861837907, 0.6366197723675814] 12 | const res = v2DivideScalar([1, 2], Math.PI, 2); // [0.32, 0.64] 13 | ``` 14 | 15 | **3D Vector** 16 | ```js 17 | import { v3DivideScalar } from 'mz-math'; 18 | 19 | const res = v3DivideScalar([1, 2, 3], 2); // [0.5, 1, 1.5] 20 | const res = v3DivideScalar([1, 2, 3], 0.5); // [2, 4, 6] 21 | const res = v3DivideScalar([1, 2, 3], Math.PI); // [0.3183098861837907, 0.6366197723675814, 0.954929658551372] 22 | const res = v3DivideScalar([1, 2, 3], Math.PI, 2); // [0.32, 0.64, 0.95] 23 | ``` 24 | 25 | **General Case** 26 | ```js 27 | import { vDivideScalar } from 'mz-math'; 28 | 29 | const res = vDivideScalar([1, 2, 3, 4], 2); // [0.5, 1, 1.5, 2] 30 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/6-vector-length.md: -------------------------------------------------------------------------------- 1 | ## Get Vector Length 2 | 3 | Vector length can be found using the **v2Length**, **v3Length**, and **vLength** functions. Each function receives an optional **decimalPlaces** parameter. 4 | 5 | ```js 6 | import { v2Length, v3Length, vLength } from 'mz-math'; 7 | 8 | // 2D vector 9 | const len1 = v2Length([1, 2]); // 2.23606797749979 10 | const len2 = v2Length([1, 2], 2); // 2.24 11 | 12 | // 3D vector 13 | const len3 = v3Length([1, 2, 3]); // 3.7416573867739413 14 | const len4 = v3Length([1, 2, 3], 2); // 3.74 15 | 16 | // General case 17 | const len5 = vLength([1, 2, 3, 4]); // 5.477225575051661 18 | const len6 = vLength([1, 2, 3, 4], 2); // 5.48 19 | ``` 20 | 21 | ## Set Vector Length 22 | 23 | It's possible to update vector length using **v2SetLength** function. The function receives an optional **decimalPlaces** parameter. 24 | 25 | ```js 26 | import { v2SetLength } from 'mz-math'; 27 | 28 | const res1 = v2SetLength([1, 2], 10); // [4.4721359549995805, 8.94427190999916] 29 | const res2 = v2SetLength([1, 2], 10, 2); // [4.47, 8.94] 30 | ``` 31 | -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/7-normalize-vector.md: -------------------------------------------------------------------------------- 1 | ## Normalized Vector (Unit Vector) 2 | 3 | It's possible to normalize vectors using the **v2Normalize**, **v3Normalize**, and **vNormalize** functions. Each function receives an optional **decimalPlaces** parameter. 4 | 5 | ```js 6 | import { v2Normalize, v3Normalize, vNormalize } from 'mz-math'; 7 | 8 | // 2D vector 9 | const res1 = v2Normalize([10, 20]); // [0.4472135954999579, 0.8944271909999159] 10 | const res2 = v2Normalize([10, 20], 2); // [0.45, 0.89] 11 | 12 | // 3D vector 13 | const res3 = v3Normalize([10, 20, 30]); // [0.2672612419124244, 0.5345224838248488, 0.8017837257372731] 14 | const res4 = v3Normalize([10, 20, 30], 2); // [0.27, 0.53, 0.8] 15 | 16 | // General case 17 | const res5 = vNormalize([10, 20, 30, 40]); // [0.18257418583505536, 0.3651483716701107, 0.5477225575051661, 0.7302967433402214] 18 | const res6 = vNormalize([10, 20, 30, 40], 2); // [0.18, 0.37, 0.55, 0.73] 19 | ``` 20 | -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/8-dot-product.md: -------------------------------------------------------------------------------- 1 | ## Vectors Dot Product 2 | 3 | It's possible to calculate vector dot product using the **v2DotProduct**, **v3DotProduct**, and **vDotProduct** functions. Each function receives an optional **decimalPlaces** parameter. 4 | 5 | ```js 6 | import { v2DotProduct, v3DotProduct, vDotProduct } from 'mz-math'; 7 | 8 | // 2D vector 9 | const res1 = v2DotProduct([1, 2], [3, 4]); // 11 10 | const res2 = v2DotProduct([1.1234, 2.35678], [3.1265, 4.91355], 2); // 15.09 11 | 12 | // 3D vector 13 | const res3 = v3DotProduct([1, 2, 3], [4, 5, 6]); // 32 14 | const res4 = v3DotProduct([1.73845, 2.88465, 3.000111], [4.1163, 5.5501, 6.120777], 2); // 41.53 15 | 16 | // General case 17 | const res5 = vDotProduct([1, 2, 3, 4], [5, 6, 7, 8]); // 70 18 | const res6 = vDotProduct([1.123, 2.123, 3.123, 4.123], [5.123, 6.123, 7.123, 8.123], 1); // 74.5 19 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/20-vectors/9-cross-product.md: -------------------------------------------------------------------------------- 1 | ## Vectors Cross Product 2 | 3 | ```js 4 | import { v3CrossProduct, Vector3 } from 'mz-math'; 5 | 6 | const v1: Vector3 = [1, 2, 3]; 7 | const v2: Vector3 = [4, 5, 6]; 8 | const res1 = v3CrossProduct(v1, v2); // [-3, 6, -3] 9 | 10 | const v3: Vector3 = [1.1143, 2.1205, 3.57294]; 11 | const v4: Vector3 = [4.8294, 5.0001111, 6.48634]; 12 | // round to 2 decimal places after the dot 13 | const res2 = v3CrossProduct(v3, v4, 2); // [-4.11, 10.03, -4.67] 14 | ``` 15 | -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/1-matrix.md: -------------------------------------------------------------------------------- 1 | # Matrix 2 | 3 | There are the following types of matrices: 4 | **Matrix2**, **Matrix3**, and **Matrix** for the general case. 5 | 6 | **Matrix2** 7 | 8 | ```js 9 | import { Matrix2 } from 'mz-math'; 10 | 11 | const m2: Matrix2 = [ 12 | [1, 2], 13 | ]; 14 | 15 | const m2: Matrix2 = [ 16 | [1, 2], 17 | [3, 4], 18 | ]; 19 | 20 | // or 21 | 22 | const m2: Matrix2 = [ 23 | [1, 2], 24 | [3, 4], 25 | [5, 6], 26 | ]; 27 | 28 | // etc... 29 | ``` 30 | 31 | **Matrix3** 32 | 33 | ```js 34 | import { Matrix3 } from 'mz-math'; 35 | 36 | const m3: Matrix3 = [ 37 | [1, 2, 3], 38 | ]; 39 | 40 | // or 41 | 42 | const m3: Matrix3 = [ 43 | [1, 2, 3], 44 | [4, 5, 6], 45 | ]; 46 | 47 | // or 48 | 49 | const m3: Matrix3 = [ 50 | [1, 2, 3], 51 | [4, 5, 6], 52 | [7, 8, 9], 53 | ]; 54 | 55 | // etc... 56 | ``` 57 | 58 | **Matrix4** 59 | 60 | ```js 61 | import { Matrix4 } from 'mz-math'; 62 | 63 | const m4: Matrix4 = [ 64 | [1, 2, 3, 4], 65 | ]; 66 | 67 | // or 68 | 69 | const m4: Matrix4 = [ 70 | [1, 2, 3, 4], 71 | [5, 6, 7, 8], 72 | ]; 73 | 74 | // or 75 | 76 | const m4: Matrix4 = [ 77 | [1, 2, 3, 4], 78 | [5, 6, 7, 8], 79 | [9, 10, 11, 12], 80 | [13, 14, 15, 16], 81 | ]; 82 | 83 | // etc... 84 | ``` 85 | 86 | The generic **Matrix** type is used for all other cases: 87 | 88 | ```js 89 | import { Matrix } from 'mz-math'; 90 | 91 | const m: Matrix = [ 92 | [1, 2, 3, 4, 5], 93 | [1, 2, 3, 4, 5], 94 | [1, 2, 3, 4, 5], 95 | [1, 2, 3, 4, 5], 96 | [1, 2, 3, 4, 5], 97 | ]; 98 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/10-inverse-matrix.md: -------------------------------------------------------------------------------- 1 | # Inverse Matrix 2 | 3 | To inverse matrices, you can use the **m2Inverse**, **m3Inverse**, or **mInverse** functions. Each function supports an optional **decimalPlaces** parameter. If matrix is not invertible, the functions return **null**. 4 | 5 | **2x2 matrix** 6 | 7 | ```js 8 | import { Matrix2, m2Inverse } from 'mz-math'; 9 | 10 | const m2x2: Matrix2 = [ 11 | [3, 5], 12 | [-7, 2], 13 | ]; 14 | 15 | const inverted: Matrix2|null = m2Inverse(m2x2, 3); // round to 3 decimal places 16 | /* 17 | [ 18 | [0.049, -0.122], 19 | [0.171, 0.073], 20 | ] 21 | */ 22 | ``` 23 | 24 | **3x3 matrix** 25 | 26 | ```js 27 | import { Matrix3, m3Inverse } from 'mz-math'; 28 | 29 | const m3x3: Matrix3 = [ 30 | [-1, -2, 2], 31 | [2, 1, 1], 32 | [3, 4, 5] 33 | ]; 34 | 35 | const inverted: Matrix3|null = m3Inverse(m3x3, 2); // round to 2 decimal places 36 | /* 37 | [ 38 | [0.04, 0.78, -0.17], 39 | [-0.30, -0.48, 0.22], 40 | [0.22, -0.09, 0.13] 41 | ] 42 | */ 43 | ``` 44 | 45 | **3x3 matrix or above** 46 | 47 | ```js 48 | import { Matrix, mInverse } from 'mz-math'; 49 | 50 | const m4x4: Matrix = [ 51 | [1, 1, 1, -1], 52 | [1, 1, -1, 1], 53 | [1, -1, 1, 1], 54 | [-1, 1, 1, 1], 55 | ]; 56 | 57 | const inverted: Matrix|null = mInverse(m4x4); 58 | /* 59 | [ 60 | [0.25, 0.25, 0.25, -0.25], 61 | [0.25, 0.25, -0.25, 0.25], 62 | [0.25, -0.25, 0.25, 0.25], 63 | [-0.25, 0.25, 0.25, 0.25], 64 | ] 65 | */ 66 | ``` 67 | -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/11-matrix-singularity.md: -------------------------------------------------------------------------------- 1 | # Check if matrix is singular 2 | 3 | ```js 4 | import { Matrix, isSingularMatrix } from 'mz-math'; 5 | 6 | const m: Matrix = [ 7 | [3, 5], 8 | [-7, 2], 9 | ]; 10 | 11 | const isSingular = isSingularMatrix(m); // false 12 | ``` 13 | 14 | ```js 15 | import { Matrix, isSingularMatrix } from 'mz-math'; 16 | 17 | const m: Matrix = [ 18 | [2, 4, 6], 19 | [2, 0, 2], 20 | [6, 8, 14], 21 | ]; 22 | 23 | const isSingular = isSingularMatrix(m); // true 24 | ``` 25 | -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/12-adjugate-matrix.md: -------------------------------------------------------------------------------- 1 | # Adjugate Matrix 2 | 3 | To adjugate matrices, you can use the **m2Adjugate**, **m3Adjugate**, or **mAdjugate** functions. Each function supports an optional **decimalPlaces** parameter. If matrix can't be adjugated, the functions return **null**. 4 | 5 | **2x2 matrix** 6 | 7 | ```js 8 | import { Matrix2, m2Adjugate } from 'mz-math'; 9 | 10 | const m2x2: Matrix2 = [ 11 | [3, 5], 12 | [-7, 2], 13 | ]; 14 | 15 | const adj: Matrix2 | null = m2Adjugate(m2x2); 16 | 17 | /* 18 | [ 19 | [2, -5], 20 | [7, 3], 21 | ] 22 | */ 23 | ``` 24 | 25 | **3x3 matrix** 26 | 27 | ```js 28 | import { Matrix3, m3Adjugate } from 'mz-math'; 29 | 30 | const m3x3: Matrix3 = [ 31 | [3, 5, 1], 32 | [-7, 2, 5], 33 | [1, 2, 3], 34 | ]; 35 | 36 | const adj: Matrix3 | null = m3Adjugate(m3x3); 37 | 38 | /* 39 | [ 40 | [-4, -13, 23], 41 | [26, 8, -22], 42 | [-16, -1, 41], 43 | ] 44 | */ 45 | ``` 46 | 47 | **4x4 matrix or above** 48 | 49 | ```js 50 | import { Matrix, mAdjugate } from 'mz-math'; 51 | 52 | const m4x4: Matrix = [ 53 | [1, 1, 1, -1], 54 | [1, 1, -1, 1], 55 | [1, -1, 1, 1], 56 | [-1, 1, 1, 1], 57 | ]; 58 | 59 | const adj: Matrix | null = mAdjugate(m4x4); 60 | 61 | /* 62 | [ 63 | [-4, -4, -4, 4], 64 | [-4, -4, 4, -4], 65 | [-4, 4, -4, -4], 66 | [4, -4, -4, -4], 67 | ] 68 | */ 69 | ``` 70 | -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/12-get-matrix-minor.md: -------------------------------------------------------------------------------- 1 | # Get Matrix Minor 2 | 3 | ```js 4 | import { Matrix, mMinor } from 'mz-math'; 5 | 6 | const m: Matrix = [ 7 | [4, 3, 2, 2], 8 | [0, 1, -3, 3], 9 | [0, -1, 3, 3], 10 | [0, 3, 1, 1], 11 | ]; 12 | 13 | // get minor for the row = 0 and column = 0 14 | const minor: Matrix = mMinor(m, 0, 0); // -60 15 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/2-matrix-sum.md: -------------------------------------------------------------------------------- 1 | # Matrix Sum 2 | 3 | The following functions are used to add matrices: **m2Sum** for a 2D matrices, **m3Sum** for a 3D matrices, and **mSum** for the general case. Each function receives an optional **decimalPlaces** parameter. 4 | 5 | **2D Matrix** 6 | 7 | ```js 8 | import { m2Sum, Matrix2 } from 'mz-math'; 9 | 10 | const matrix1: Matrix2 = [ 11 | [1, 2], 12 | [3, 4], 13 | ]; 14 | 15 | const matrix2: Matrix2 = [ 16 | [5, 6], 17 | [7, 8], 18 | ]; 19 | 20 | const sum = m2Sum(matrix1, matrix2); 21 | /* 22 | [ 23 | [6, 8], 24 | [10, 12], 25 | ] 26 | */ 27 | ``` 28 | 29 | **3D Matrix** 30 | ```js 31 | import { m3Sum, Matrix3 } from 'mz-math'; 32 | 33 | const matrix1: Matrix3 = [ 34 | [1, 2, 10], 35 | [3, 4, 20], 36 | ]; 37 | 38 | const matrix2: Matrix3 = [ 39 | [5, 6, 30], 40 | [7, 8, 40], 41 | ]; 42 | 43 | const sum = m3Sum(matrix1, matrix2); 44 | /* 45 | [ 46 | [6, 8, 40], 47 | [10, 12, 60], 48 | ] 49 | */ 50 | ``` 51 | 52 | **General Case** 53 | ```js 54 | import { mSum, Matrix } from 'mz-math'; 55 | 56 | const matrix1: Matrix = [ 57 | [1, 2, 3, 4], 58 | [5, 6, 7, 8], 59 | ]; 60 | 61 | const matrix2: Matrix = [ 62 | [9, 10, 11, 12], 63 | [13, 14, 15, 16], 64 | ]; 65 | 66 | const sum = mSum(matrix1, matrix2); 67 | /* 68 | [ 69 | [10, 12, 14, 16], 70 | [18, 20, 22, 24], 71 | ] 72 | */ 73 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/3-matrix-subtraction.md: -------------------------------------------------------------------------------- 1 | # Matrix Subtraction 2 | 3 | The following functions are used to subtract matrices: **m2Sub** for a 2D matrices, **m3Sub** for a 3D matrices, and **mSub** for the general case. Each function receives an optional **decimalPlaces** parameter. 4 | 5 | **2D Matrix** 6 | ```js 7 | import { m2Sub, Matrix2 } from 'mz-math'; 8 | 9 | const matrix1: Matrix2 = [ 10 | [1, 2], 11 | [3, 4], 12 | ]; 13 | 14 | const matrix2: Matrix2 = [ 15 | [5, 6], 16 | [7, 8], 17 | ]; 18 | 19 | const sub = m2Sub(matrix1, matrix2); 20 | /* 21 | [ 22 | [-4, -4], 23 | [-4, -4], 24 | ] 25 | */ 26 | ``` 27 | 28 | **3D Matrix** 29 | ```js 30 | import { m2Sub, Matrix3 } from 'mz-math'; 31 | 32 | const matrix1: Matrix3 = [ 33 | [1, 2, 10], 34 | [3, 4, 20], 35 | ]; 36 | 37 | const matrix2: Matrix3 = [ 38 | [5, 6, 30], 39 | [7, 8, 40], 40 | ]; 41 | 42 | const sub = m2Sub(matrix1, matrix2); 43 | /* 44 | [ 45 | [-4, -4, -20], 46 | [-4, -4, -20], 47 | ] 48 | */ 49 | ``` 50 | 51 | **General Case** 52 | 53 | ```js 54 | import { mSub, Matrix } from 'mz-math'; 55 | 56 | const matrix1: Matrix = [ 57 | [1, 2, 3, 4], 58 | [5, 6, 7, 8], 59 | ]; 60 | 61 | const matrix2: Matrix = [ 62 | [9, 10, 11, 12], 63 | [13, 14, 15, 16], 64 | ]; 65 | 66 | const sum = mSub(matrix1, matrix2); 67 | /* 68 | [ 69 | [-8, -8, -8, -8], 70 | [-8, -8, -8, -8], 71 | ] 72 | */ 73 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/4-multiply-by-scalar.md: -------------------------------------------------------------------------------- 1 | # Multiply matrix by scalar 2 | 3 | You can multiply a matrix by a scalar using the **m2MulScalar**, **m3MulScalar**, or **mMulScalar** functions. Each function receives an optional **decimalPlaces** parameter. 4 | 5 | **2D Matrix** 6 | 7 | ```js 8 | import { m2MulScalar, Matrix2 } from 'mz-math'; 9 | 10 | const m2: Matrix2 = [ 11 | [1, 2], 12 | [3, 4], 13 | ]; 14 | 15 | const res = m2MulScalar(m2, 5); 16 | /* 17 | [ 18 | [5, 10], 19 | [15, 20], 20 | ] 21 | */ 22 | ``` 23 | 24 | ```js 25 | import { m2MulScalar, Matrix2 } from 'mz-math'; 26 | 27 | const m2: Matrix2 = [ 28 | [1.12345, 12.66746776], 29 | [15.74432, -12.345345], 30 | ]; 31 | 32 | const res = m2MulScalar(m2, 10, 2); // 2 decimal places 33 | /* 34 | [ 35 | [11.23, 126.67], 36 | [157.44, -123.45], 37 | ] 38 | */ 39 | ``` 40 | 41 | **3D Matrix** 42 | 43 | ```js 44 | import { m3MulScalar, Matrix3 } from 'mz-math'; 45 | 46 | const m3: Matrix3 = [ 47 | [1, 2, 3], 48 | [4, 5, 6], 49 | ]; 50 | 51 | const res = m3MulScalar(m3, 2); 52 | /* 53 | [ 54 | [2, 4, 6], 55 | [8, 10, 12], 56 | ] 57 | */ 58 | ``` 59 | 60 | ```js 61 | import { m3MulScalar, Matrix3 } from 'mz-math'; 62 | 63 | const m3: Matrix3 = [ 64 | [1, 2, 3], 65 | [4, 5, 6], 66 | ]; 67 | 68 | const res = m3MulScalar(m3, 1.5123123, 1); // 1 decimal place 69 | /* 70 | [ 71 | [1.5, 3, 4.5], 72 | [6, 7.6, 9.1], 73 | ] 74 | */ 75 | ``` 76 | -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/5-divide-by-scalar.md: -------------------------------------------------------------------------------- 1 | # Divide matrix by scalar 2 | 3 | You can multiply a matrix by a scalar using the **m2DivideScalar**, **m3DivideScalar**, or **mDivideScalar** functions. Each function receives an optional **decimalPlaces** parameter. 4 | 5 | **2D Matrix** 6 | 7 | ```js 8 | import { m2DivideScalar, Matrix2 } from 'mz-math'; 9 | 10 | const m2: Matrix2 = [ 11 | [1, 2], 12 | [3, 4], 13 | ]; 14 | 15 | const res = m2DivideScalar(m2, 5); 16 | /* 17 | [ 18 | [0.2, 0.4], 19 | [0.6, 0.8], 20 | ] 21 | */ 22 | ``` 23 | 24 | ```js 25 | import { m2DivideScalar, Matrix2 } from 'mz-math'; 26 | 27 | const m2: Matrix2 = [ 28 | [1.12345, 12.66746776], 29 | [15.74432, -12.345345], 30 | ]; 31 | 32 | const res = m2DivideScalar(m2, 10, 2); // 2 decimal places 33 | /* 34 | [ 35 | [0.01, 0.13], 36 | [0.16, -0.12],, 37 | ] 38 | */ 39 | ``` 40 | 41 | **3D Matrix** 42 | 43 | ```js 44 | import { m3DivideScalar, Matrix3 } from 'mz-math'; 45 | 46 | const m3: Matrix3 = [ 47 | [1, 2, 3], 48 | [4, 5, 6], 49 | ]; 50 | 51 | const res = m3DivideScalar(m3, 2); 52 | /* 53 | [ 54 | [0.5, 1, 1.5], 55 | [2, 2.5, 3], 56 | ] 57 | */ 58 | ``` 59 | 60 | ```js 61 | import { m3DivideScalar, Matrix3 } from 'mz-math'; 62 | 63 | const m3: Matrix3 = [ 64 | [1, 2, 3], 65 | [4, 5, 6], 66 | ]; 67 | 68 | const res = m3DivideScalar(m3, 1.5123123, 1); // 1 decimal place 69 | /* 70 | [ 71 | [0.7, 1.3, 2], 72 | [2.6, 3.3, 4], 73 | ] 74 | */ 75 | ``` 76 | 77 | **General Case** 78 | 79 | ```js 80 | import { mDivideScalar, Matrix } from 'mz-math'; 81 | 82 | const matrix: Matrix = [ 83 | [1, 2, 3, 4], 84 | [5, 6, 7, 8], 85 | ]; 86 | 87 | const res = mDivideScalar(matrix, 5); 88 | /* 89 | [ 90 | [0.2, 0.4, 0.6, 0.8], 91 | [1, 1.2, 1.4, 1.6], 92 | ] 93 | */ 94 | ``` 95 | -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/6-matrix-transposition.md: -------------------------------------------------------------------------------- 1 | # Matrix Transposition 2 | 3 | You can transpose a matrix using the **m2Transpose**, **m3Transpose**, or **mTranspose** functions. 4 | 5 | **2D Matrix** 6 | 7 | ```js 8 | import { m2Transpose, Matrix2 } from 'mz-math'; 9 | 10 | const m2: Matrix2 = [ 11 | [-1, 5], 12 | [Math.PI, 3], 13 | ]; 14 | 15 | const res = m2Transpose(m2); 16 | /* 17 | [ 18 | [-1, Math.PI], 19 | [5, 3], 20 | ] 21 | */ 22 | ``` 23 | 24 | **3D Matrix** 25 | 26 | ```js 27 | import { m3Transpose, Matrix3 } from 'mz-math'; 28 | 29 | const m3: Matrix3 = [ 30 | [1, 3, 7], 31 | [-2, 0, 5], 32 | ]; 33 | 34 | const res = m3Transpose(m3); 35 | /* 36 | [ 37 | [1, -2], 38 | [3, 0], 39 | [7, 5], 40 | ] 41 | */ 42 | ``` 43 | 44 | **General Case** 45 | 46 | ```js 47 | import { mTranspose, Matrix } from 'mz-math'; 48 | 49 | const matrix: Matrix = [ 50 | [1, 2, 3, 4], 51 | [5, 6, 7, 8], 52 | ]; 53 | 54 | const res = mTranspose(matrix); 55 | /* 56 | [ 57 | [1, 5], 58 | [2, 6], 59 | [3, 7], 60 | [4, 8], 61 | ] 62 | */ 63 | ``` 64 | -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/7-matrix-multiplication.md: -------------------------------------------------------------------------------- 1 | # Matrix Multiplication 2 | 3 | You can multiply matrices using the **mMul** function. The function receives an optional **decimalPlaces** parameter. 4 | 5 | ```js 6 | import { mMul, Matrix3, Matrix2 } from 'mz-math'; 7 | 8 | const matrix1: Matrix3 = [ 9 | [0, 3, 5], 10 | [5, 5, 2], 11 | ]; 12 | 13 | const matrix2: Matrix2 = [ 14 | [3, 4], 15 | [3, -2], 16 | [4, -2], 17 | ]; 18 | 19 | const res = mMul(matrix1, matrix2); 20 | 21 | /* 22 | [ 23 | [29, -16], 24 | [38, 6], 25 | ] 26 | */ 27 | ``` 28 | 29 | ```js 30 | import { mMul, Matrix2 } from 'mz-math'; 31 | 32 | const matrix1: Matrix2 = [ 33 | [2.092345, -2.2345234], 34 | [5.56745, 3.235479], 35 | ]; 36 | 37 | const matrix2: Matrix2 = [ 38 | [-1.46874567, 4.23453245], 39 | [7.234505, -6.93245], 40 | ]; 41 | 42 | const res = mMul(matrix1, matrix2, 2); // round to 2 decimal places 43 | 44 | /* 45 | [ 46 | [-19.24, 24.35], 47 | [15.23, 1.15], 48 | ] 49 | */ 50 | ``` 51 | -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/8-multiply-matrix-by-vector.md: -------------------------------------------------------------------------------- 1 | # Multiply matrix by vector 2 | 3 | You can multiply matrix by vector using the **mMulVector** function. The function receives an optional **decimalPlaces** parameter. 4 | 5 | ```js 6 | import { mMulVector, Matrix3 } from 'mz-math'; 7 | 8 | const matrix: Matrix3 = [ 9 | [0, 3, 5], 10 | [5, 5, 2], 11 | ]; 12 | 13 | const vector: Vector3 = [3, 4, 3]; 14 | 15 | const res = mMulVector(matrix, vector); // [27, 41] 16 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/30-matrix/9-matrix-determinant.md: -------------------------------------------------------------------------------- 1 | # Matrix Determinant 2 | 3 | The determinant can be calculated for any square matrix using the **m2Determinant** function for a 2x2 matrix, using the **m3Determinant** function for a 3x3 matrix, or using **mDeterminant** for the general case. 4 | 5 | Calculating the determinant for a 2x2 matrix: 6 | 7 | ```js 8 | import { Matrix2, m2Determinant } from 'mz-math'; 9 | 10 | const m2x2: Matrix2 = [ 11 | [5, 3], 12 | [-1, 4], 13 | ]; 14 | 15 | const d = m2Determinant(m2x2); // 23 16 | ``` 17 | 18 | Calculating the determinant for a 3x3 matrix: 19 | 20 | ```js 21 | import { Matrix3, m3Determinant } from 'mz-math'; 22 | 23 | const m3x3: Matrix3 = [ 24 | [4, -1, 1], 25 | [4, 5, 3], 26 | [-2, 0, 0], 27 | ]; 28 | 29 | const d = m3Determinant(m3x3); // 16 30 | ``` 31 | 32 | Calculating the determinant for a 4x4 matrix or above: 33 | 34 | ```js 35 | import { Matrix, mDeterminant } from 'mz-math'; 36 | 37 | const m4x4: Matrix = [ 38 | [4, 3, 2, 2], 39 | [0, 1, -3, 3], 40 | [0, -1, 3, 3], 41 | [0, 3, 1, 1] 42 | ]; 43 | 44 | const d = mDeterminant(m4x4); // -240 45 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/40-matrix-manipulation/1-matrix-initialization.md: -------------------------------------------------------------------------------- 1 | ## Matrix Initialization Helpers 2 | 3 | ### m2x2, m3x3, and mNxM 4 | 5 | There are helpers for creating **m2x2**, **m3x3**, and **mNxM** matrices with a default value. If no default value is specified, it will be zero. 6 | 7 | ```js 8 | import { m2x2, m3x3, m4x4, mNxM } from 'mz-math'; 9 | 10 | const mat2x2 = m2x2(); 11 | /* 12 | [ 13 | [0, 0], 14 | [0, 0], 15 | ] 16 | */ 17 | 18 | const mat2x2_10 = m2x2(10); 19 | /* 20 | [ 21 | [10, 10], 22 | [10, 10], 23 | ] 24 | */ 25 | 26 | const mat3x3 = m3x3(); 27 | /* 28 | [ 29 | [0, 0, 0], 30 | [0, 0, 0], 31 | [0, 0, 0], 32 | ] 33 | */ 34 | 35 | const mat3x3_20 = m3x3(20); 36 | /* 37 | [ 38 | [20, 20, 20], 39 | [20, 20, 20], 40 | [20, 20, 20], 41 | ] 42 | */ 43 | 44 | const mat4x4_5 = m5x5(5); 45 | /* 46 | [ 47 | [5, 5, 5, 5], 48 | [5, 5, 5, 5], 49 | [5, 5, 5, 5], 50 | [5, 5, 5, 5], 51 | ] 52 | */ 53 | 54 | const matNxM = mNxM(1, 5); 55 | /* 56 | [ 57 | [0, 0, 0, 0, 0], 58 | ] 59 | */ 60 | 61 | const matNxM = mNxM(2, 3, 1); 62 | /* 63 | [ 64 | [1, 1, 1], 65 | [1, 1, 1], 66 | ] 67 | */ 68 | 69 | ``` 70 | 71 | ### Identity Matrix 72 | 73 | There are helpers for creating identity matrices: **identity2**, **identity3**, and **identityN**. 74 | 75 | ```js 76 | import { identity2, identity3, identity4, identityN } from 'mz-math'; 77 | 78 | const idt2 = identity2(); 79 | /* 80 | [ 81 | [1, 0], 82 | [0, 1], 83 | ] 84 | */ 85 | 86 | const idt3 = identity3(); 87 | /* 88 | [ 89 | [1, 0, 0], 90 | [0, 1, 0], 91 | [0, 0, 1], 92 | ] 93 | */ 94 | 95 | const idt4 = identity4(); 96 | /* 97 | [ 98 | [1, 0, 0, 0], 99 | [0, 1, 0, 0], 100 | [0, 0, 1, 0], 101 | [0, 0, 0, 1], 102 | ] 103 | */ 104 | 105 | const idt5 = identityN(5); 106 | /* 107 | [ 108 | [1, 0, 0, 0, 0], 109 | [0, 1, 0, 0, 0], 110 | [0, 0, 1, 0, 0], 111 | [0, 0, 0, 1, 0], 112 | [0, 0, 0, 0, 1], 113 | ] 114 | */ 115 | 116 | ``` 117 | -------------------------------------------------------------------------------- /src/docs/data/pages/40-matrix-manipulation/2-matrix-equality.md: -------------------------------------------------------------------------------- 1 | # Check if two matrices are equal 2 | 3 | It's possible to perform a deep comparison of two matrices using the **mEqual** function: 4 | 5 | ```js 6 | import { mEqual } from 'mz-math'; 7 | 8 | const res1 = mEqual( 9 | [ 10 | [0, 0], 11 | [0, 0], 12 | ], 13 | [ 14 | [0, 0], 15 | [0, 0], 16 | ]); // true 17 | 18 | const res2 = mEqual( 19 | [ 20 | [1, 0], 21 | [0, 0], 22 | ], 23 | [ 24 | [0, 0], 25 | [0, 1], 26 | ]); // false 27 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/40-matrix-manipulation/3-matrix-deep-copy.md: -------------------------------------------------------------------------------- 1 | # Matrix Deep Copy 2 | 3 | There are 3 function for matrices deep copy: **m2DeepCopy** for 2D matrices, **m3DeepCopy** for 3D matrices, and **mDeepCopy** for the general case: 4 | 5 | ```js 6 | import { Matrix2, m2DeepCopy } from 'mz-math'; 7 | 8 | const m2: Matrix2 = [ 9 | [3, 5], 10 | [-7, 2], 11 | ]; 12 | const copyM2 = m2DeepCopy(m2); 13 | ``` 14 | 15 | ```js 16 | import { Matrix3, m3DeepCopy } from 'mz-math'; 17 | 18 | const m2: Matrix3 = [ 19 | [3, 5, 1], 20 | [-7, 2, 6], 21 | ]; 22 | const copyM3 = m2DeepCopy(m3); 23 | ``` 24 | 25 | ```js 26 | import { Matrix, mDeepCopy } from 'mz-math'; 27 | 28 | const m: Matrix = [ 29 | [1, 0, 1, 2, 4], 30 | [1, 7, 8, 6, 12], 31 | ]; 32 | const copy = mDeepCopy(m); 33 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/40-matrix-manipulation/4-append-or-prepend-row.md: -------------------------------------------------------------------------------- 1 | # Append or prepend a row to a matrix 2 | 3 | ```js 4 | import { Matrix2, Vector2, m2AppendRow, m2PrependRow } from 'mz-math'; 5 | 6 | const m2: Matrix2 = [ 7 | [3, 5], 8 | [-7, 2], 9 | ]; 10 | const v2: Vector2 = [3, 4]; 11 | const res1 = m2AppendRow(m2, v2); 12 | /* 13 | [ 14 | [3, 5], 15 | [-7, 2], 16 | [3, 4] 17 | ] 18 | */ 19 | 20 | const res2 = m2PrependRow(m2, v2); 21 | /* 22 | [ 23 | [3, 4], 24 | [3, 5], 25 | [-7, 2], 26 | ] 27 | */ 28 | ``` 29 | 30 | ```js 31 | import { Matrix3, Vector3, m3AppendRow, m3PrependRow } from 'mz-math'; 32 | 33 | const m3: Matrix3 = [ 34 | [1, 2, 3], 35 | [4, 5, 6], 36 | ]; 37 | const v3: Vector3 = [7, 8, 9]; 38 | const res1 = m3AppendRow(m3, v3); 39 | /* 40 | [ 41 | [1, 2, 3], 42 | [4, 5, 6], 43 | [7, 8, 9], 44 | ] 45 | */ 46 | const res2 = m3PrependRow(m3, v3); 47 | /* 48 | [ 49 | [7, 8, 9], 50 | [1, 2, 3], 51 | [4, 5, 6], 52 | ] 53 | */ 54 | ``` 55 | 56 | ```js 57 | import { Matrix, Vector, mAppendRow, mPrependRow } from 'mz-math'; 58 | 59 | const m: Matrix = [ 60 | [1, 2, 3, 4], 61 | [5, 6, 7, 8], 62 | ]; 63 | const v: Vector = [9, 10, 11, 12]; 64 | const res1 = mAppendRow(m, v); 65 | /* 66 | [ 67 | [1, 2, 3, 4], 68 | [5, 6, 7, 8], 69 | [9, 10, 11, 12], 70 | ] 71 | */ 72 | const res2 = mPrependRow(m, v); 73 | /* 74 | [ 75 | [9, 10, 11, 12], 76 | [1, 2, 3, 4], 77 | [5, 6, 7, 8], 78 | ] 79 | */ 80 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/40-matrix-manipulation/5-append-or-prepend-column.md: -------------------------------------------------------------------------------- 1 | # Append or prepend a column to a matrix 2 | 3 | ```js 4 | import { Matrix, Vector, mAppendCol, mPrependCol } from 'mz-math'; 5 | 6 | const m: Matrix = [ 7 | [1, 2, 3, 4], 8 | [5, 6, 7, 8], 9 | ]; 10 | const v: Vector = [9, 10]; 11 | const res1 = mAppendCol(m, v); 12 | /* 13 | [ 14 | [1, 2, 3, 4, 9], 15 | [5, 6, 7, 8, 10], 16 | ] 17 | */ 18 | const res2 = mPrependCol(m, v); 19 | /* 20 | [ 21 | [9, 1, 2, 3, 4], 22 | [10, 5, 6, 7, 8], 23 | ] 24 | */ 25 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/40-matrix-manipulation/6-remove-row-or-column.md: -------------------------------------------------------------------------------- 1 | # Remove row or column from matrix 2 | 3 | **Delete last row** 4 | 5 | ```js 6 | import { mDelLastRow } from 'mz-math'; 7 | 8 | const res = mDelLastRow( 9 | [ 10 | [3, 5], 11 | [-7, 2], 12 | ] 13 | ); 14 | /* 15 | [ 16 | [3, 5], 17 | ] 18 | */ 19 | ``` 20 | 21 | **Delete first row** 22 | 23 | ```js 24 | import { mDelFirstRow } from 'mz-math'; 25 | 26 | const res = mDelFirstRow( 27 | [ 28 | [3, 5], 29 | [-7, 2], 30 | ] 31 | ); 32 | /* 33 | [ 34 | [-7, 2], 35 | ] 36 | */ 37 | ``` 38 | 39 | **Delete last column** 40 | 41 | ```js 42 | import { mDelLastColumn } from 'mz-math'; 43 | 44 | const res = mDelLastColumn( 45 | [ 46 | [3, 5], 47 | [-7, 2], 48 | ] 49 | ); 50 | /* 51 | [ 52 | [3], 53 | [-7], 54 | ] 55 | */ 56 | ``` 57 | 58 | **Delete first column** 59 | 60 | ```js 61 | import { mDelFirstColumn } from 'mz-math'; 62 | 63 | const res = mDelFirstColumn( 64 | [ 65 | [3, 5], 66 | [-7, 2], 67 | ] 68 | ); 69 | /* 70 | [ 71 | [5], 72 | [2], 73 | ] 74 | */ 75 | ``` 76 | -------------------------------------------------------------------------------- /src/docs/data/pages/40-matrix-manipulation/7-get-column.md: -------------------------------------------------------------------------------- 1 | # Get column from matrix 2 | 3 | ```js 4 | import { Matrix, mGetFirstColumn, mGetLastColumn, mGetColumn } from 'mz-math'; 5 | 6 | const m: Matrix = [ 7 | [1, 0, 1, 1], 8 | [1, 0, 1, 1], 9 | [0, 0, 1, 1], 10 | [0, 0, 1, -1], 11 | ]; 12 | 13 | const firstColumn = mGetFirstColumn(m); // [1, 1, 0, 0] 14 | const lastColumn = mGetLastColumn(m); // [1, 1, 1, -1] 15 | const col2 = mGetColumn(m, 2); // [1, 1, 1, 1] - column at index 2 16 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/40-matrix-manipulation/8-reset-matrix.md: -------------------------------------------------------------------------------- 1 | # Reset matrix with a default value 2 | 3 | It is possible to reset all matrix values with some default value. If no default value is specified, it will be **zero**. 4 | 5 | **2D Matrix** 6 | 7 | ```js 8 | import { Matrix2, m2Reset } from 'mz-math'; 9 | 10 | const m2: Matrix2 = [ 11 | [1, 2], 12 | [3, 4], 13 | ]; 14 | 15 | const res = m2Reset(m2); 16 | /* 17 | [ 18 | [0, 0], 19 | [0, 0], 20 | ] 21 | */ 22 | ``` 23 | 24 | ```js 25 | import { Matrix2, m2Reset } from 'mz-math'; 26 | 27 | const m2: Matrix2 = [ 28 | [1, 2], 29 | [3, 4], 30 | ]; 31 | 32 | const res = m2Reset(m2, 10); 33 | /* 34 | [ 35 | [10, 10], 36 | [10, 10], 37 | ] 38 | */ 39 | ``` 40 | 41 | **3D Matrix** 42 | 43 | ```js 44 | import { Matrix3, m3Reset } from 'mz-math'; 45 | 46 | const m3: Matrix3 = [ 47 | [1, 2, 3], 48 | [4, 5, 6], 49 | ]; 50 | 51 | const res = m3Reset(m3); 52 | /* 53 | [ 54 | [0, 0, 0], 55 | [0, 0, 0], 56 | ] 57 | */ 58 | ``` 59 | 60 | ```js 61 | import { Matrix3, m3Reset } from 'mz-math'; 62 | 63 | const m3: Matrix3 = [ 64 | [1, 2, 3], 65 | [4, 5, 6], 66 | ]; 67 | 68 | const res = m3Reset(m3, 1.5); 69 | /* 70 | [ 71 | [1.5, 1.5, 1.5], 72 | [1.5, 1.5, 1.5], 73 | ] 74 | */ 75 | ``` 76 | 77 | **General Case** 78 | 79 | ```js 80 | import { Matrix, m3Reset } from 'mz-math'; 81 | 82 | const m: Matrix = [ 83 | [1, 2, 3, 4, 5], 84 | [6, 7, 8, 9, 10], 85 | ]; 86 | 87 | const res = m3Reset(m); 88 | /* 89 | [ 90 | [0, 0, 0, 0, 0], 91 | [0, 0, 0, 0, 0], 92 | ] 93 | */ 94 | ``` 95 | 96 | ```js 97 | import { Matrix, m3Reset } from 'mz-math'; 98 | 99 | const m: Matrix = [ 100 | [1, 2, 3, 4, 5], 101 | [6, 7, 8, 9, 10], 102 | ]; 103 | 104 | const res = m3Reset(m, 50); 105 | /* 106 | [ 107 | [50, 50, 50, 50, 50], 108 | [50, 50, 50, 50, 50], 109 | ] 110 | */ 111 | ``` 112 | -------------------------------------------------------------------------------- /src/docs/data/pages/45-transformation-matrices/1-translation-matrix.md: -------------------------------------------------------------------------------- 1 | # Translation Matrix 2 | 3 | It's possible to get a translation matrix using the functions below. Each function supports an optional **decimalPlaces** parameter. 4 | 5 | **Translation in non-homogeneous coordinates** 6 | 7 | ```js 8 | import { m2Translation, m3Translation, Matrix2, Matrix3 } from 'mz-math'; 9 | 10 | // translation matrix for the position [10, 20] 11 | const mat1: Matrix2 = m2Translation([10, 20]); 12 | 13 | /* 14 | [ 15 | [1, 0], 16 | [0, 1], 17 | [10, 20], 18 | ]; 19 | */ 20 | 21 | // translation matrix for the position [10, 20, 30] 22 | const mat2: Matrix3 = m3Translation([10, 20, 30]); 23 | 24 | /* 25 | [ 26 | [1, 0, 0], 27 | [0, 1, 0], 28 | [0, 0, 1], 29 | [10, 20, 30], 30 | ]; 31 | */ 32 | ``` 33 | 34 | **Translation in homogeneous coordinates** 35 | 36 | ```js 37 | import { m2TranslationH, m3TranslationH, Matrix3, Matrix4 } from 'mz-math'; 38 | 39 | // translation matrix for the position [10, 20] in homogeneous coordinates. 40 | const mat1: Matrix3 = m2TranslationH([10, 20, 1]); 41 | 42 | /* 43 | [ 44 | [1, 0, 10], 45 | [0, 1, 20], 46 | [0, 0, 1], 47 | ]; 48 | */ 49 | 50 | // translation matrix for the position [10, 20, 30] in homogeneous coordinates. 51 | const mat2: Matrix4 = m3TranslationH([10, 20, 30, 1]); 52 | 53 | /* 54 | [ 55 | [1, 0, 0, 10], 56 | [0, 1, 0, 20], 57 | [0, 0, 1, 30], 58 | [0, 0, 0, 1], 59 | ]; 60 | */ 61 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/45-transformation-matrices/3-rotate-around-point.md: -------------------------------------------------------------------------------- 1 | # Rotate Around Point 2 | 3 | It's possible to rotate a point [x, y] (in homogeneous coordinates) around the given origin as follows: 4 | 5 | ```js 6 | import { Vector3, m2RotateAroundPointH, m2RotationAroundPointH } from 'mz-math'; 7 | 8 | const angle = Math.PI/4; // radians 9 | const transformOrigin = [100, 100, 1]; // in homogeneous coordinates 10 | const point: Vector3 = [150, 150, 1]; // [x, y, 1] 11 | const isClockwise = true; // optional 12 | const decimalPlaces = 2; // optional 13 | 14 | // get the new position after rotation 15 | const pos: Vector3 = m2RotateAroundPointH( 16 | angle, 17 | transformOrigin, 18 | point, 19 | isClockwise, 20 | decimalPlaces 21 | ); 22 | 23 | // it's also possible to get the appropriate rotation matrix 24 | const mat3: Matrix3 = m2RotationAroundPointH( 25 | angle, 26 | transformOrigin, 27 | isClockwise, 28 | decimalPlaces 29 | ); 30 | ``` 31 | 32 | [Circle Movement Example](https://github.com/mzusin/mz-math/blob/main/examples/circular-movement/circle-movement-1.html) 33 | -------------------------------------------------------------------------------- /src/docs/data/pages/45-transformation-matrices/5-scale-around-point.md: -------------------------------------------------------------------------------- 1 | # Scale around an arbitrary pivot point P 2 | 3 | It's possible to scale a point [x, y] (in homogeneous coordinates) around the given pivot point as follows: 4 | 5 | ```js 6 | import { Vector3, m2ScaleAtPointH, m2ScaleAtPointHMatrix } from 'mz-math'; 7 | 8 | const scaleVector: Vector3 = [2, 4, 1]; // in homogeneous coordinates 9 | const transformOrigin = [100, 100, 1]; // in homogeneous coordinates 10 | const point: Vector3 = [150, 150, 1]; // [x, y, 1] 11 | const decimalPlaces = 2; // optional 12 | 13 | // get the new vector after the scale 14 | const res: Vector3 = m2ScaleAtPointH( 15 | scaleVector, 16 | transformOrigin, 17 | point, 18 | decimalPlaces 19 | ); 20 | 21 | // it's also possible to get the appropriate scale matrix 22 | const mat3: Matrix3 = m2ScaleAtPointHMatrix( 23 | scaleVector, 24 | transformOrigin, 25 | decimalPlaces 26 | ); 27 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/45-transformation-matrices/7-shearing-matrix.md: -------------------------------------------------------------------------------- 1 | # Shearing Matrix 2 | 3 | **2D shearing matrix** 4 | 5 | ```js 6 | import { m2ShearingX, m2ShearingY, Matrix2 } from 'mz-math'; 7 | 8 | // shearing in x-axis, with y-axis fixed with (1,0) moving to (1, factor) 9 | const factor = 5; 10 | const mat1: Matrix2 = m2ShearingX(factor); 11 | /* 12 | [ 13 | [1, 0], 14 | [5, 1], 15 | ]; 16 | */ 17 | 18 | // shearing in y-axis, with x-axis fixed with (0,1) moving to (factor, 1) 19 | const factor = 5; 20 | const mat2: Matrix2 = m2ShearingY(factor); 21 | /* 22 | [ 23 | [1, 5], 24 | [0, 1], 25 | ]; 26 | */ 27 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/45-transformation-matrices/8-matrix-to-CSS-transform.md: -------------------------------------------------------------------------------- 1 | # Matrix to CSS transform 2 | 3 | The functions below help to convert the matrix to the following CSS functions: [matrix()](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix) and [matrix3d()](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix3d). 4 | 5 | ```js 6 | import { Matrix3, m2hToCSS } from 'mz-math'; 7 | 8 | // 2d matrix in homogeneous coordinates 9 | const mat: Matrix3 = [ 10 | [1, 2, 0], 11 | [3, 4, 0], 12 | [0, 0, 1], 13 | ]; 14 | const str1 = m2hToCSS(mat); // matrix(1, 3, 2, 4, 0, 4) 15 | ``` 16 | 17 | It can be used as: 18 | 19 | ```css 20 | .box{ 21 | transform: matrix(1, 3, 2, 4, 0, 4); 22 | } 23 | ``` 24 | 25 | [matrix3d()](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix3d) representation: 26 | 27 | ```js 28 | import { Matrix3, m2hToCSS3d } from 'mz-math'; 29 | 30 | // 2d matrix in homogeneous coordinates 31 | const mat: Matrix3 = [ 32 | [1, 2, 0], 33 | [3, 4, 0], 34 | [0, 0, 1], 35 | ]; 36 | const str1 = m2hToCSS3d(mat); // matrix3d(1, 3, 0, 0, 2, 4, 0, 0, 0, 0, 1, 0, 0, 4, 0, 1) 37 | ``` 38 | 39 | Non-homogeneous coordinates version: 40 | 41 | ```js 42 | import { Matrix2, m2ToCSS } from 'mz-math'; 43 | 44 | // 2d matrix in homogeneous coordinates 45 | const mat: Matrix2 = [ 46 | [1, 2], 47 | [3, 4], 48 | ]; 49 | const str1 = m2ToCSS(mat); // matrix(1, 3, 2, 4, 0, 0) 50 | ``` 51 | 52 | 3D matrix in homogeneous coordinates: 53 | 54 | ```js 55 | import { Matrix4, m3hToCSS3d } from 'mz-math'; 56 | 57 | // 2d matrix in homogeneous coordinates 58 | const mat: Matrix4 = [ 59 | [1, 0, 0, 10], 60 | [0, 1, 0, 20], 61 | [0, 0, 1, 30], 62 | [0, 0, 0, 1], 63 | ]; 64 | const str1 = m3hToCSS3d(mat); 65 | /* 66 | matrix3d( 67 | 1, 0, 0, 10, 68 | 0, 1, 0, 20, 69 | 0, 0, 1, 30, 70 | 0, 0, 0, 1 71 | ) 72 | */ 73 | ``` 74 | 75 | [Matrix to CSS transform example (rotation)](https://github.com/mzusin/mz-math/blob/main/examples/matrix-to-css-rotation.html) -------------------------------------------------------------------------------- /src/docs/data/pages/50-angles/1-vector-angle.md: -------------------------------------------------------------------------------- 1 | ## Get vector angle 2 | 3 | The **getV2Angle** function returns the angle **in radians** between the positive x-axis and the ray from (0, 0) to the vector (x, y). It supports an optional **decimalPlaces** parameter. Each function returns a result in the range [0, Math.PI]. 4 | 5 | ```js 6 | import { getV2Angle } from 'mz-math'; 7 | 8 | const angle1 = getV2Angle([10, 20]); // 1.1071487177940904 radians 9 | const angle2 = getV2Angle([10, 20], 2); // 1.11 radians 10 | ``` 11 | 12 | ## Set vector angle 13 | 14 | If a 2D vector is given, change it to have the new angle (in radians). This function supports an optional **decimalPlaces** parameter. 15 | 16 | ```js 17 | import { setV2Angle } from 'mz-math'; 18 | 19 | const updatedVector1 = setV2Angle([10, 20], 1.22); // [7.684152489413291, 20.99889998355732] 20 | const updatedVector2 = setV2Angle([10, 20], 1.22, 2); // [7.68, 21] 21 | ``` 22 | 23 | ## getV2AngleInEllipse() 24 | 25 | ```js 26 | import { getV2AngleInEllipse } from 'mz-math'; 27 | 28 | const v2: Vector2 = [10, 20]; 29 | const radii: Vector2 = [100, 200]; 30 | const decimalPlaces = 2; // optional 31 | 32 | const angle = getV2AngleInEllipse(v2, radii, decimalPlaces); // 0.79 radians 33 | ``` 34 | 35 | -------------------------------------------------------------------------------- /src/docs/data/pages/50-angles/2-angle-between-vectors.md: -------------------------------------------------------------------------------- 1 | # Get angle between two vectors 2 | 3 | The following functions can be used to find the angle between two vectors. Each function returns a result in the range [0, Math.PI]. 4 | 5 | **2D vectors:** 6 | 7 | ```js 8 | import { getV2AngleBetween, Vector2 } from 'mz-math'; 9 | 10 | const vector1: Vector2 = [10, 20]; 11 | const vector2: Vector2 = [100, 150]; 12 | const decimalPlaces = 2; // optional 13 | const angle = getV2AngleBetween(vector1, vector2, decimalPlaces); 14 | ``` 15 | 16 | **3D vectors:** 17 | 18 | ```js 19 | import { getV3AngleBetween, Vector3 } from 'mz-math'; 20 | 21 | const vector1: Vector3 = [10, 20, 1]; 22 | const vector2: Vector3 = [100, 150, 1]; 23 | const decimalPlaces = 2; // optional 24 | const angle = getV3AngleBetween(vector1, vector2, decimalPlaces); 25 | ``` 26 | 27 | **General case:** 28 | 29 | ```js 30 | import { getVNAngleBetween, Vector } from 'mz-math'; 31 | 32 | const vector1: Vector = [10, 20, 1]; 33 | const vector2: Vector = [100, 150, 1]; 34 | const decimalPlaces = 2; // optional 35 | const angle = getVNAngleBetween(vector1, vector2, decimalPlaces); 36 | ``` 37 | -------------------------------------------------------------------------------- /src/docs/data/pages/50-angles/3-degrees-and-radians.md: -------------------------------------------------------------------------------- 1 | ## Degrees to radians 2 | 3 | ```js 4 | import { degreesToRadians } from 'mz-math'; 5 | 6 | const res1 = degreesToRadians(90); // 1.5707963267948966 7 | const res2 = degreesToRadians(90, 2); // 1.57 8 | ``` 9 | 10 | ## Radians to degrees 11 | 12 | ```js 13 | import { radiansToDegrees } from 'mz-math'; 14 | 15 | const res = radiansToDegrees(1.5708); // 90.00021045914971 16 | const res = radiansToDegrees(1.5708, 0); // 90 17 | const res = radiansToDegrees(3.14159, 3); // 180 18 | const res = radiansToDegrees(4.71239, 3); // 270 19 | ``` 20 | -------------------------------------------------------------------------------- /src/docs/data/pages/50-angles/4-angles-distance.md: -------------------------------------------------------------------------------- 1 | ## Get Angles Distance 2 | 3 | The getAnglesDistance() function calculates the distance between two angles, considering a start angle as the reference. It returns the shortest distance between the angles, taking into account both clockwise and counterclockwise directions. 4 | 5 | ```js 6 | import { getAnglesDistance } from 'mz-math'; 7 | 8 | const distance1 = getAnglesDistance(0, 90); // 90 degrees 9 | const distance2 = getAnglesDistance(270, 90); // 180 degrees 10 | ``` 11 | 12 | The function signature is: 13 | ```ts 14 | const getAnglesDistance: (angle1Deg: number, angle2Deg: number, startAngleDeg?: number, decimalPlaces?: number) => number; 15 | ``` 16 | 17 | - **angle1Deg** (number): The first angle in degrees. 18 | - **angle2Deg** (number): The second angle in degrees. 19 | - **startAngleDeg** (number, optional): The start angle in degrees. The default value is 0. 20 | - **decimalPlaces** (number, optional): The number of decimal places to round the result. The default value is Infinity (no rounding). 21 | 22 | 23 | ## Angles Subtraction (Angular Distance) 24 | 25 | The getAnglesSub() function calculates the absolute difference between two angles, considering them as subtractions, and returns the result. It determines the shortest angular distance between the two angles, considering angles within the range of 0 to 360 degrees. 26 | 27 | ```js 28 | import { getAnglesSub } from 'mz-math'; 29 | 30 | const angleDegrees1 = 315; 31 | const angleDegrees2 = 0; 32 | const decimalPlaces = 2; // optional 33 | 34 | const angle1 = getAnglesSub(angleDegrees1, angleDegrees2, decimalPlaces); // 45 degrees 35 | ``` 36 | 37 | The function signature: 38 | 39 | ```ts 40 | const getAnglesSub: (angleDegrees1: number, angleDegrees2: number, decimalPlaces?: number) => number; 41 | ``` 42 | 43 | - **angleDegrees1** (number): The first angle in degrees. 44 | - **angleDegrees2** (number): The second angle in degrees. 45 | - **decimalPlaces** (number, optional): The number of decimal places to round the result. The default value is Infinity (no rounding). 46 | 47 | -------------------------------------------------------------------------------- /src/docs/data/pages/50-angles/5-is-angle-between.md: -------------------------------------------------------------------------------- 1 | ## Is angle between two other angles? 2 | 3 | This function checks if the given angle is between two other angles (inclusive). Angles are in degrees. 4 | 5 | ```js 6 | import { isAngleBetween } from 'mz-math'; 7 | 8 | const isBetween1 = isAngleBetween(45, 0, 90); // true 9 | const isBetween2 = isAngleBetween(180, 0, 90); // false 10 | ``` 11 | 12 | -------------------------------------------------------------------------------- /src/docs/data/pages/50-angles/6-is-clockwise.md: -------------------------------------------------------------------------------- 1 | ## Is angle rotation clockwise? 2 | 3 | The isClockwise() function determines whether a given pair of angles represents a clockwise rotation or not, considering a start angle as the reference. 4 | 5 | ```js 6 | import { isClockwise } from 'mz-math'; 7 | 8 | const isClockwise1 = isClockwise(0, 90); // true 9 | const isClockwise2 = isClockwise(90, 0); // false 10 | const isClockwise3 = isClockwise(90, 270, 270); // false 11 | ``` 12 | 13 | The function signature is: 14 | 15 | ```ts 16 | const isClockwise: (angle1Deg: number, angle2Deg: number, startAngleDeg?: number) => boolean; 17 | ``` 18 | 19 | - **angle1Deg** (number): The first angle in degrees. 20 | - **angle2Deg** (number): The second angle in degrees. 21 | - **startAngleDeg** (number, optional): The start angle in degrees. The default value is 0. 22 | 23 | -------------------------------------------------------------------------------- /src/docs/data/pages/50-angles/7-percent-to-angle.md: -------------------------------------------------------------------------------- 1 | ## Convert Percent to Angle (in circle) 2 | 3 | The percentToAngle() function calculates the angle corresponding to a given percentage value within a specified range of start and end angles. It considers a circle start angle as a reference and returns the resulting angle based on whether the rotation is clockwise or counterclockwise. 4 | 5 | ```js 6 | import { percentToAngle } from 'mz-math'; 7 | 8 | const angle1 = percentToAngle(0, 0, 90); // 0 degrees 9 | const angle2 = percentToAngle(percentToAngle(50, 0, 90)); // 45 degrees 10 | const angle3 = percentToAngle(percentToAngle(100, 0, 90)); // 90 degrees 11 | ``` 12 | 13 | The function signature is: 14 | ```ts 15 | const percentToAngle: (percent: number, startAngleDeg: number, endAngleDeg: number, circleStartAngle?: number) => number; 16 | ``` 17 | 18 | - **percent** (number): The percentage value between 0 and 100. 19 | - **startAngleDeg** (number): The starting angle in degrees. 20 | - **endAngleDeg** (number): The ending angle in degrees. 21 | - **circleStartAngle** (number, optional): The circle start angle in degrees. The default value is 0. 22 | 23 | -------------------------------------------------------------------------------- /src/docs/data/pages/60-random/1-get-random-number-in-range.md: -------------------------------------------------------------------------------- 1 | # Get random number in range 2 | 3 | This function returns a random number in the range [min, max]. It supports an optional **decimalPlaces** parameter. 4 | 5 | ```js 6 | import { getRandom } from 'mz-math'; 7 | 8 | const res1 = getRandom(10, 100); // 93.57877355999018 9 | const res2 = getRandom(10, 100, 2); // 80.28 10 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/60-random/2-get-random-integer.md: -------------------------------------------------------------------------------- 1 | # Get random integer 2 | 3 | This function returns a random integer number in the range [min, max]. 4 | 5 | ```js 6 | import { getRandomInt } from 'mz-math'; 7 | 8 | const res = getRandomInt(0, 100); // 63 9 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/60-random/3-get-random-boolean.md: -------------------------------------------------------------------------------- 1 | # Get random boolean value 2 | 3 | ```js 4 | import { getRandomBoolean } from 'mz-math'; 5 | 6 | const res = getRandomBoolean(); // true or false 7 | ``` 8 | -------------------------------------------------------------------------------- /src/docs/data/pages/60-random/4-get-random-item-from-array.md: -------------------------------------------------------------------------------- 1 | # Get random item from array 2 | 3 | ```js 4 | import { getRandomItemFromArray } from 'mz-math'; 5 | 6 | const item1 = getRandomItemFromArray([1,2,3,4,5]); // 2 7 | const item2 = getRandomItemFromArray(['a', 'b', 'c']); // 'a' 8 | const item3 = getRandomItemFromArray([{ test: 1 }, { test: 2 }, { test: 3 }]); // { test: 3 } 9 | ``` 10 | -------------------------------------------------------------------------------- /src/docs/data/pages/60-random/5-random-id-or-GUID.md: -------------------------------------------------------------------------------- 1 | # Random ID or GUID 2 | 3 | ```js 4 | import { guid, newId } from 'mz-math'; 5 | 6 | const res1 = newId(); // a string like 'df4unio1opulby2uqh4' 7 | const res2 = guid(); // a guid like '932ade5e-c515-4807-ac01-73b20ab3fb66' 8 | ``` 9 | -------------------------------------------------------------------------------- /src/docs/data/pages/70-bezier-curve/1-get-point-on-quadratic-bezier-curve.md: -------------------------------------------------------------------------------- 1 | # Get a point on a quadratic Bézier curve 2 | 3 | Get a point on a quadratic Bézier curve as a function of time, where t is in the range [0, 1]. 4 | 5 | **2D Vector** 6 | 7 | ```js 8 | import { v2QuadraticBezierCurve } from 'mz-math'; 9 | 10 | const decimalPlaces = 2; // optional 11 | 12 | const v2 = v2QuadraticBezierCurve( 13 | 0.5, 14 | [0, 100], 15 | [50, 0], 16 | [100, 100], 17 | decimalPlaces 18 | ); // [50, 50] 19 | 20 | const v2 = v2QuadraticBezierCurve( 21 | 0, 22 | [0, 100], 23 | [50, 0], 24 | [100, 100], 25 | decimalPlaces 26 | ); // [0, 100] 27 | 28 | const v2 = v2QuadraticBezierCurve( 29 | 1, 30 | [0, 100], 31 | [50, 0], 32 | [100, 100], 33 | decimalPlaces 34 | ); // [100, 100] 35 | ``` 36 | 37 | **3D Vector** 38 | 39 | ```js 40 | import { v3QuadraticBezierCurve } from 'mz-math'; 41 | 42 | const decimalPlaces = 2; // optional 43 | 44 | const v3 = v3QuadraticBezierCurve( 45 | 0.5, 46 | [0, 100, 0], 47 | [50, 0, 0], 48 | [100, 100, 0], 49 | decimalPlaces 50 | ); // [50, 50, 0] 51 | 52 | const v3 = v3QuadraticBezierCurve( 53 | 0, 54 | [0, 100, 0], 55 | [50, 0, 0], 56 | [100, 100, 0], 57 | decimalPlaces 58 | ); // [0, 100, 0] 59 | 60 | const v3 = v3QuadraticBezierCurve( 61 | 1, 62 | [0, 100, 0], 63 | [50, 0, 0], 64 | [100, 100, 0], 65 | decimalPlaces 66 | ); // [100, 100, 0] 67 | ``` 68 | 69 | 70 | -------------------------------------------------------------------------------- /src/docs/data/pages/70-bezier-curve/2-get-point-on-cubic-bezier-curve.md: -------------------------------------------------------------------------------- 1 | # Get a point on a cubic Bézier curve 2 | 3 | Get a point on a cubic Bézier curve as a function of time, where t is in the range [0, 1]. 4 | 5 | **2D Vector** 6 | 7 | ```js 8 | import { v2CubicBezierCurve } from 'mz-math'; 9 | 10 | const decimalPlaces = 2; // optional 11 | 12 | const v2 = v2CubicBezierCurve( 13 | 0.5, 14 | [0, 100], 15 | [0, 0], 16 | [100, 0], 17 | [100, 100], 18 | decimalPlaces 19 | ); // [50, 25] 20 | 21 | const v2 = v2CubicBezierCurve( 22 | 0, 23 | [0, 100], 24 | [0, 0], 25 | [100, 0], 26 | [100, 100], 27 | decimalPlaces 28 | ); // [0, 100] 29 | 30 | const v2 = v2CubicBezierCurve( 31 | 1, 32 | [0, 100], 33 | [0, 0], 34 | [100, 0], 35 | [100, 100], 36 | decimalPlaces 37 | ); // [100, 100] 38 | ``` 39 | 40 | **3D Vector** 41 | 42 | ```js 43 | import { v3CubicBezierCurve } from 'mz-math'; 44 | 45 | const decimalPlaces = 2; // optional 46 | 47 | const v3 = v3CubicBezierCurve( 48 | 0.5, 49 | [0, 100, 0], 50 | [0, 0, 0], 51 | [100, 0, 0], 52 | [100, 100, 0], 53 | decimalPlaces 54 | ); // [50, 25, 0] 55 | 56 | const v3 = v3CubicBezierCurve( 57 | 0, 58 | [0, 100, 0], 59 | [0, 0, 0], 60 | [100, 0, 0], 61 | [100, 100, 0], 62 | decimalPlaces 63 | ); // [0, 100, 0] 64 | 65 | const v3 = v3CubicBezierCurve( 66 | 1, 67 | [0, 100, 0], 68 | [0, 0, 0], 69 | [100, 0, 0], 70 | [100, 100, 0], 71 | decimalPlaces 72 | ); // [100, 100, 0] 73 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/70-bezier-curve/3-tangent.md: -------------------------------------------------------------------------------- 1 | # Bezier Curve Tangent Vector 2 | 3 | **Cubic Bézier curve tangent for 2D Vector** 4 | 5 | ```js 6 | import { v2CubicBezierCurveTangent, Vector2 } from 'mz-math'; 7 | 8 | const t = 0.6; // mast be in range [0, 1] 9 | const startControlPoint: Vector2 = [100, 200]; 10 | const center1ControlPoint: Vector2 = [100, 50]; 11 | const center2ControlPoint: Vector2 = [200, 150]; 12 | const endControlPoint: Vector2 = [300, 250]; 13 | const decimalPlaces = 2; // optional 14 | 15 | const result: Vector2 = v2CubicBezierCurveTangent( 16 | t, 17 | startControlPoint, 18 | center1ControlPoint, 19 | center2ControlPoint, 20 | endControlPoint, 21 | decimalPlaces 22 | ); 23 | ``` 24 | 25 | **Cubic Bézier curve tangent for 3D Vector** 26 | 27 | ```js 28 | import { v3CubicBezierCurveTangent, Vector2 } from 'mz-math'; 29 | 30 | const t = 0.6; // mast be in range [0, 1] 31 | const startControlPoint: Vector3 = [100, 200, 0]; 32 | const center1ControlPoint: Vector3 = [100, 50, 0]; 33 | const center2ControlPoint: Vector3 = [200, 150, 0]; 34 | const endControlPoint: Vector3 = [300, 250, 0]; 35 | const decimalPlaces = 2; // optional 36 | 37 | const result: Vector3 = v3CubicBezierCurveTangent( 38 | t, 39 | startControlPoint, 40 | center1ControlPoint, 41 | center2ControlPoint, 42 | endControlPoint, 43 | decimalPlaces 44 | ); 45 | ``` 46 | 47 | **Quadratic Bézier curve tangent for 2D Vector** 48 | 49 | ```js 50 | import { dxV2QuadraticBezierCurve, Vector2 } from 'mz-math'; 51 | 52 | const t = 0.6; // mast be in range [0, 1] 53 | const startControlPoint: Vector2 = [150, 550]; 54 | const centerControlPoint: Vector2 = [400, 300]; 55 | const endControlPoint: Vector2 = [50, 550]; 56 | const decimalPlaces = 2; // optional 57 | 58 | const result: Vector2 = dxV2QuadraticBezierCurve( 59 | t, 60 | startControlPoint, 61 | centerControlPoint, 62 | endControlPoint, 63 | decimalPlaces 64 | ); 65 | ``` 66 | 67 | **Quadratic Bézier curve tangent for 3D Vector** 68 | 69 | ```js 70 | import { dxV3QuadraticBezierCurve, Vector3 } from 'mz-math'; 71 | 72 | const t = 0.6; // mast be in range [0, 1] 73 | const startControlPoint: Vector3 = [150, 550, 0]; 74 | const centerControlPoint: Vector3 = [400, 300, 0]; 75 | const endControlPoint: Vector3 = [50, 550, 0]; 76 | const decimalPlaces = 2; // optional 77 | 78 | const result: Vector3 = dxV3QuadraticBezierCurve( 79 | t, 80 | startControlPoint, 81 | centerControlPoint, 82 | endControlPoint, 83 | decimalPlaces 84 | ); 85 | ``` 86 | -------------------------------------------------------------------------------- /src/docs/data/pages/70-bezier-curve/4-normal.md: -------------------------------------------------------------------------------- 1 | # Bezier Curve Normal Vector 2 | 3 | **Cubic Bézier curve normal** 4 | 5 | ```js 6 | import { v2CubicBezierCurveNormal, Vector2 } from 'mz-math'; 7 | 8 | const t = 0.6; // mast be in range [0, 1] 9 | const startControlPoint: Vector2 = [100, 200]; 10 | const center1ControlPoint: Vector2 = [100, 50]; 11 | const center2ControlPoint: Vector2 = [200, 150]; 12 | const endControlPoint: Vector2 = [300, 250]; 13 | const decimalPlaces = 2; // optional 14 | 15 | const result: Vector2 = v2CubicBezierCurveNormal( 16 | t, 17 | startControlPoint, 18 | center1ControlPoint, 19 | center2ControlPoint, 20 | endControlPoint, 21 | decimalPlaces 22 | ); 23 | ``` 24 | 25 | **Quadratic Bézier curve normal** 26 | 27 | ```js 28 | import { v2QuadraticBezierCurveNormal, Vector2 } from 'mz-math'; 29 | 30 | const t = 0.6; // mast be in range [0, 1] 31 | const startControlPoint: Vector2 = [150, 550]; 32 | const centerControlPoint: Vector2 = [400, 300]; 33 | const endControlPoint: Vector2 = [50, 550]; 34 | const decimalPlaces = 2; // optional 35 | 36 | const result: Vector2 = v2QuadraticBezierCurveNormal( 37 | t, 38 | startControlPoint, 39 | centerControlPoint, 40 | endControlPoint, 41 | decimalPlaces 42 | ); 43 | ``` 44 | -------------------------------------------------------------------------------- /src/docs/data/pages/70-bezier-curve/5-extrema.md: -------------------------------------------------------------------------------- 1 | # Bezier Curve Extrema 2 | 3 | **Cubic Bézier Extrema** 4 | 5 | ```js 6 | import { v2QuadraticBezierCurveExtrema, Vector2, Vector } from 'mz-math'; 7 | 8 | const startControlPoint: Vector2 = [100, 200]; 9 | const center1ControlPoint: Vector2 = [100, 50]; 10 | const center2ControlPoint: Vector2 = [200, 150]; 11 | const endControlPoint: Vector2 = [300, 250]; 12 | const decimalPlaces = 2; // optional 13 | 14 | const result: Vector = v2QuadraticBezierCurveExtrema( 15 | startControlPoint, 16 | center1ControlPoint, 17 | center2ControlPoint, 18 | endControlPoint, 19 | decimalPlaces 20 | ); 21 | ``` 22 | 23 | **Quadratic Bézier Extrema** 24 | 25 | ```js 26 | import { v2CubicBezierCurveExtrema, Vector2 } from 'mz-math'; 27 | 28 | const startControlPoint: Vector2 = [150, 550]; 29 | const centerControlPoint: Vector2 = [400, 300]; 30 | const endControlPoint: Vector2 = [50, 550]; 31 | const decimalPlaces = 2; // optional 32 | 33 | const result: Vector2|null = v2CubicBezierCurveExtrema( 34 | startControlPoint, 35 | centerControlPoint, 36 | endControlPoint, 37 | decimalPlaces 38 | ); 39 | ``` 40 | -------------------------------------------------------------------------------- /src/docs/data/pages/70-bezier-curve/6-bounding-box.md: -------------------------------------------------------------------------------- 1 | # Bezier Curve Bounding Box 2 | 3 | **Cubic Bézier Bounding Box** 4 | 5 | ```js 6 | import { v2CubicBezierBBox, Vector2 } from 'mz-math'; 7 | 8 | const startControlPoint: Vector2 = [100, 200]; 9 | const center1ControlPoint: Vector2 = [100, 50]; 10 | const center2ControlPoint: Vector2 = [200, 150]; 11 | const endControlPoint: Vector2 = [300, 250]; 12 | const decimalPlaces = 2; // optional 13 | 14 | const result: IBBox = v2CubicBezierBBox( 15 | startControlPoint, 16 | center1ControlPoint, 17 | center2ControlPoint, 18 | endControlPoint, 19 | decimalPlaces 20 | ); 21 | ``` 22 | 23 | **Quadratic Bézier Bounding Box** 24 | 25 | ```js 26 | import { v2QuadraticBezierBBox, Vector2 } from 'mz-math'; 27 | 28 | const startControlPoint: Vector2 = [150, 550]; 29 | const centerControlPoint: Vector2 = [400, 300]; 30 | const endControlPoint: Vector2 = [50, 550]; 31 | const decimalPlaces = 2; // optional 32 | 33 | const result: IBBox = v2QuadraticBezierBBox( 34 | startControlPoint, 35 | centerControlPoint, 36 | endControlPoint, 37 | decimalPlaces 38 | ); 39 | ``` 40 | 41 | **IBBox Interface** 42 | 43 | ```ts 44 | export interface IBBox { 45 | x: number; // left top corner x 46 | y: number; // left top corner y 47 | w: number; 48 | h: number; 49 | x2: number; // right bottom corner x 50 | y2: number; // right bottom corner y 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /src/docs/data/pages/80-equations/1-linear-equation.md: -------------------------------------------------------------------------------- 1 | # Linear Equation 2 | 3 | Using the **linearEquation()** function, you can a simple linear equation. 4 | 5 | ```js 6 | import { linearEquation, Vector3 } from 'mz-math'; 7 | 8 | const equation: Vector3 = [1, 3, 5]; // x + 3 = 5 9 | const decimalPlaces = 2; // optional 10 | 11 | const result: number = linearEquation(equation, decimalPlaces); // 2 12 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/80-equations/2-system-of-linear-equations.md: -------------------------------------------------------------------------------- 1 | # System of linear Equations 2 | 3 | **System of 2 linear equations** 4 | 5 | Using the **linearEquationSystem2()** function, you can solve a system of 2 linear equations. It receives **2 vectors** of equation parameters and an optional **decimalPlaces** parameter. 6 | 7 | If the system of equations has no solution, then **null** is returned. 8 | 9 | For example: 10 | 11 | ```js 12 | import { linearEquationSystem2, Vector2, Vector3 } from 'mz-math'; 13 | 14 | // 3x + 2y = 7 15 | // -6x + 6y = 6 16 | 17 | const equation1: Vector3 = [3, 2, 7]; 18 | const equation2: Vector3 = [-6, 6, 6]; 19 | const result: Vector2|null = linearEquationSystem2(equation1, equation2); // [1, 2] i.e. x=1, y=2 20 | ``` 21 | 22 | **System of 3 linear equations** 23 | 24 | Using the **linearEquationSystem3()** function, you can solve a system of 3 linear equations. It receives **3 vectors** of equation parameters and an optional **decimalPlaces** parameter. 25 | 26 | If the system of equations has no solution, then **null** is returned. 27 | 28 | For example: 29 | ```js 30 | import { linearEquationSystem3, Vector3, Vector } from 'mz-math'; 31 | 32 | // 2x + y + 2z = -2 33 | // -2x + 2y -z = -5 34 | // 4x + y + 2x = 0 35 | 36 | const equation1: Vector = [2, 1, 2, -2]; 37 | const equation2: Vector = [-2, 2, -1, -5]; 38 | const equation3: Vector = [4, 1, 2, 0]; 39 | const result: Vector3|null = linearEquationSystem3(equation1, equation2, equation3); // [1, -2, -1] i.e. x=1, y=-2, z=-1 40 | ``` 41 | 42 | **System of N linear equations** 43 | 44 | Using the **linearEquationSystemN()** function, you can solve a system of N linear equations. It receives a matrix of equation parameters, and an optional **decimalPlaces** parameter. 45 | 46 | If the system of equations has no solution, then **null** is returned. 47 | 48 | For example: 49 | ```js 50 | import { linearEquationSystem, Vector } from 'mz-math'; 51 | 52 | /* 53 | y + z - 2w = -3 54 | x + 2y - z = 2 55 | 2x + 4y + z - 3w = -2 56 | x - 4y - 7z - w = -19 57 | */ 58 | 59 | const parameters: Matrix = [ 60 | [0, 1, 1, -2, -3], 61 | [1, 2, -1, 0, 2], 62 | [2, 4, 1, -3, -2], 63 | [1, -4, -7, -1, -19], 64 | ]; 65 | 66 | const result: Vector|null = linearEquationSystemN(parameters, 2); // round to 2 decimal places 67 | 68 | // The result: [-1, 2, 1, 3] i.e. x = -1, y = 2, z = 1, w = 3 69 | ``` 70 | -------------------------------------------------------------------------------- /src/docs/data/pages/80-equations/3-quadratic-equation.md: -------------------------------------------------------------------------------- 1 | # Quadratic Equation 2 | 3 | Using the **quadraticEquation()** function, you can solve a quadratic equation. 4 | 5 | ```js 6 | import { quadraticEquation, Vector } from 'mz-math'; 7 | 8 | const equation: Vector = [-4, 28, -49, 0]; // -4x^2 + 28x - 49 = 0 9 | const decimalPlaces = 2; // optional 10 | 11 | // 1 result 12 | const result: Vector = quadraticEquation(equation, decimalPlaces); // [3.5] 13 | ``` 14 | 15 | ```js 16 | import { quadraticEquation, Vector } from 'mz-math'; 17 | 18 | const equation: Vector = [1, -1, 0, 0]; // x^2 - x = 0 19 | const decimalPlaces = 2; // optional 20 | 21 | // 2 results 22 | const result: Vector = quadraticEquation(equation, decimalPlaces); // [1, 0] 23 | ``` 24 | 25 | ```js 26 | import { quadraticEquation, Vector } from 'mz-math'; 27 | 28 | const equation: Vector = [3, -4, 94, 0]; // 3x^2 - 4x + 94 = 0 29 | const decimalPlaces = 2; // optional 30 | 31 | // no results 32 | const result: Vector = quadraticEquation(equation, decimalPlaces); // [] 33 | ``` 34 | 35 | ```js 36 | import { quadraticEquation, Vector } from 'mz-math'; 37 | 38 | const equation: Vector = [1, 0, -10, 39]; // x^2 - 10 = 39 39 | const decimalPlaces = 2; // optional 40 | 41 | // 2 results 42 | const result: Vector = quadraticEquation(equation, decimalPlaces); // [7, -7] 43 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/80-equations/4-get-linear-equation-by-2-points.md: -------------------------------------------------------------------------------- 1 | # Get linear equation by two points 2 | 3 | The **getLinearEquationBy2Points()** function calculates the equation of a line given two points in a 2D space. The equation is in the form of **y = ax + b**, where **'a'** represents the slope of the line and **'b'** represents the y-intercept. 4 | 5 | ```js 6 | import { getLinearEquationBy2Points, Vector2 } from 'mz-math'; 7 | 8 | const point1: Vector2 = [2, 3]; 9 | const point2: Vector2 = [4, 7]; 10 | const result = getLinearEquationBy2Points(point1, point2); 11 | 12 | /* 13 | Result: 14 | ------- 15 | { 16 | formula: "y = 2x - 1", 17 | slope: 2, 18 | yIntercept: -1, 19 | xIntercept: undefined, 20 | } 21 | */ 22 | ``` 23 | 24 | ```js 25 | import { getLinearEquationBy2Points, Vector2 } from 'mz-math'; 26 | 27 | const point1: Vector2 = [1, 5]; 28 | const point2: Vector2 = [3, 5]; 29 | const result = getLinearEquationBy2Points(point1, point2); 30 | 31 | /* 32 | Result: 33 | ------- 34 | { 35 | formula: "y = 5", 36 | slope: 0, 37 | yIntercept: 5, 38 | xIntercept: undefined, 39 | } 40 | */ 41 | ``` 42 | 43 | ```js 44 | import { getLinearEquationBy2Points, Vector2 } from 'mz-math'; 45 | 46 | const point1: Vector2 = [2, 3]; 47 | const point2: Vector2 = [2, 7]; 48 | const result = getLinearEquationBy2Points(point1, point2); 49 | 50 | /* 51 | Result: 52 | ------- 53 | { 54 | formula: "x = 2", 55 | slope: undefined, 56 | yIntercept: undefined, 57 | xIntercept: 2, 58 | } 59 | */ 60 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/90-path-movement/1-circle-movement.md: -------------------------------------------------------------------------------- 1 | # Circle Movement 2 | 3 | ```js 4 | import { circleMovement, Vector2 } from 'mz-math'; 5 | 6 | const center: Vector2 = [100, 100]; 7 | const radiansAngle = Math.PI/2; // Angle should be in the range [0, Math.PI] 8 | const radius = 250; 9 | const newPosition: Vector2 = circleMovement(center, radiansAngle, radius); 10 | ``` 11 | 12 | [Example](https://github.com/mzusin/mz-math/blob/main/examples/circular-movement/circle-movement-3.html) 13 | 14 | ## Circle movement after mouse 15 | 16 | ```js 17 | import { circleMovementAfterMouse, Vector2 } from 'mz-math'; 18 | 19 | const mouse = [evt.clientX, evt.clientY]; 20 | const center: Vector2 = [100, 100]; 21 | const radius = 250; 22 | 23 | const position: Vector2 = circleMovementAfterMouse(mouse, center, radius); 24 | ``` 25 | 26 | [Example](https://github.com/mzusin/mz-math/blob/main/examples/circular-movement/circle-movement-mouse-1.html) 27 | -------------------------------------------------------------------------------- /src/docs/data/pages/90-path-movement/2-ellipse-movement.md: -------------------------------------------------------------------------------- 1 | # Ellipse Movement 2 | 3 | ```js 4 | import { ellipseMovement, Vector2 } from 'mz-math'; 5 | 6 | const center: Vector2 = [100, 100]; 7 | const radiansAngle = Math.PI/2; // Angle should be in the range [0, Math.PI] 8 | const radius1 = 350; 9 | const radius2 = 150; 10 | const newPosition: Vector2 = ellipseMovement(center, radiansAngle, radius1, radius2); 11 | ``` 12 | 13 | [Example](https://github.com/mzusin/mz-math/blob/main/examples/circular-movement/ellipse-movement-3.html) 14 | 15 | 16 | ## Ellipse movement after mouse 17 | 18 | ```js 19 | import { ellipseMovementAfterMouse, Vector2 } from 'mz-math'; 20 | 21 | const mouse = [evt.clientX, evt.clientY]; 22 | const center: Vector2 = [100, 100]; 23 | const radii = [250, 300]; 24 | 25 | const position: Vector2 = ellipseMovementAfterMouse(mouse, center, radii); 26 | ``` -------------------------------------------------------------------------------- /src/docs/data/pages/90-path-movement/3-sine-wave-movement.md: -------------------------------------------------------------------------------- 1 | # Sine Wave Movement 2 | 3 | ```js 4 | import { ellipseMovement, Vector2 } from 'mz-math'; 5 | 6 | const amplitude = 100; // the peak deviation of the function from zero 7 | const frequency = 0.003; // number of cycles 8 | const phase = 0; // starting point "shifting" 9 | const x = 0; // changes from 0 to .... N 10 | const newPosition: Vector2 = ellipseMovement(x, amplitude, frequency, phase); 11 | ``` 12 | 13 | [Example](https://github.com/mzusin/mz-math/blob/main/examples/wave-movement/wave-movement-1.html) -------------------------------------------------------------------------------- /src/docs/data/pages/90-path-movement/4-lissajous-curve.md: -------------------------------------------------------------------------------- 1 | # Lissajous curve 2 | 3 | ```js 4 | import { lissajousCurve, Vector2, getRandom } from 'mz-math'; 5 | 6 | const m = 0; 7 | const p = 0; 8 | const t = 1; 9 | 10 | const k = getRandom(0, Math.PI * 2); // [0, 360] 11 | const n = getRandom(0, Math.PI * 2); // [0, 360] 12 | 13 | const A = getRandom(0, 100); // [0, 100] - width 14 | const B = getRandom(0, 100); // [0, 100] - height 15 | 16 | const newPosition: Vector2 = mzMath.lissajousCurve( 17 | A, // width 18 | B, // height 19 | t, 20 | k, 21 | n, 22 | m, 23 | p 24 | ); 25 | 26 | /* 27 | Parametric equation 28 | f(t) = A * cos(k * t - m) 29 | f(t) = B * cos(n * t - p) 30 | */ 31 | ``` 32 | 33 | [Example](https://github.com/mzusin/mz-math/blob/main/examples/lissajous-curves/lissajous-curves-canvas.html) -------------------------------------------------------------------------------- /src/docs/data/pages/pages-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "3-nodejs-usage.md": { 3 | "title": "Node.js Usage" 4 | }, 5 | "4-multiply-vector-by-scalar.md": { 6 | "title": "Multiply by Scalar" 7 | }, 8 | "5-divide-vector-by-scalar.md": { 9 | "title": "Divide by Scalar" 10 | }, 11 | "7-normalize-vector.md": { 12 | "title": "Normalized (Unit) Vector" 13 | } 14 | } -------------------------------------------------------------------------------- /src/docs/generator/client-side/css-provider.js: -------------------------------------------------------------------------------- 1 | import postcss from "postcss"; 2 | import tailwindcss from "tailwindcss"; 3 | import cssnano from "cssnano"; 4 | import autoprefixer from "autoprefixer"; 5 | import path from "path"; 6 | import fs from "fs"; 7 | 8 | /** 9 | * compile client side CSS 10 | * @param {number} cssTimeStamp 11 | * @returns {Promise} 12 | */ 13 | export const compileClientSideCSS = async (cssTimeStamp) => { 14 | // defined postcss handler 15 | const postcssHandler = postcss([ 16 | // postcssImport({}), 17 | tailwindcss({ 18 | 19 | // purge -------- 20 | content: [ 21 | './docs/**/*.html', 22 | ], 23 | theme: { 24 | 25 | // https://tailwindcss.com/docs/font-family 26 | fontFamily: { 27 | roboto: '"Roboto",system-ui,-apple-system,"Segoe UI","Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"' 28 | }, 29 | }, 30 | variants: { 31 | extend: {}, 32 | }, 33 | 34 | darkMode: 'class', 35 | }), 36 | cssnano({ preset: 'default' }), 37 | autoprefixer, 38 | ]); 39 | 40 | const cssSourcePath = path.join(process.cwd(), './src/docs/client-side/css/index.css'); 41 | const css = fs.readFileSync(cssSourcePath, 'utf-8'); 42 | const cssRes = await postcssHandler.process(css, { 43 | from: cssSourcePath 44 | }); 45 | 46 | const cssTargetPath = path.join(process.cwd(), `./docs/css/styles.${ cssTimeStamp }.css`); 47 | fs.writeFileSync(cssTargetPath, cssRes.css, 'utf8'); 48 | }; -------------------------------------------------------------------------------- /src/docs/generator/client-side/js-provider.js: -------------------------------------------------------------------------------- 1 | import esbuild from 'esbuild'; 2 | import path from 'path'; 3 | 4 | /** 5 | * compile client side javascript 6 | * @param {number} jsTimeStamp 7 | */ 8 | export const compileClientSideScripts = (jsTimeStamp) => { 9 | esbuild 10 | .build({ 11 | entryPoints: [path.join(process.cwd(), './src/docs/client-side/js/index.tsx')], 12 | bundle: true, 13 | sourcemap: 'linked', // external 14 | minify: true, 15 | target: ['es6'], 16 | outfile: `./docs/js/index.${ jsTimeStamp }.js`, 17 | loader: { 18 | '.png': 'text', 19 | '.svg': 'dataurl', 20 | }, 21 | }) 22 | .then(() => { 23 | // console.log('Done.'); 24 | }) 25 | .catch(() => process.exit(1)); 26 | }; -------------------------------------------------------------------------------- /src/docs/generator/common-provider.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import appRoot from 'app-root-path'; 3 | import fs from 'fs'; 4 | 5 | export const changeExtension = (filePath, newExtension) => { 6 | const basename = path.basename(filePath, path.extname(filePath)); 7 | return path.join(path.dirname(filePath), basename + newExtension); 8 | }; 9 | 10 | export const removeNumberOnStart = (fileName) => { 11 | let result = fileName; 12 | 13 | const index = fileName.indexOf('-'); 14 | if(index !== -1){ 15 | result = result.substring(index + 1); 16 | } 17 | 18 | return result; 19 | }; 20 | 21 | export const toTitleCase = (str) => { 22 | str = str.replaceAll('-', ' '); 23 | 24 | return str.replace( 25 | /\w\S*/g, 26 | function(txt) { 27 | return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); 28 | } 29 | ); 30 | }; 31 | 32 | export const getTimeStamp = () => { 33 | return new Date().getTime(); 34 | }; 35 | 36 | export const getRoot = () => { 37 | const userRoot = appRoot.path; 38 | const docsModuleRoot = path.join(userRoot, 'node_modules/markdown-documentation-maker'); 39 | return fs.existsSync(docsModuleRoot) ? docsModuleRoot : userRoot; 40 | }; -------------------------------------------------------------------------------- /src/docs/generator/index.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import fs from 'fs'; 3 | import fse from 'fs-extra'; 4 | import { compileClientSideCSS } from './client-side/css-provider.js'; 5 | import { compileClientSideScripts } from './client-side/js-provider.js'; 6 | import { configureMarkdown, initMarkDown } from './markdown-config.js'; // https://highlightjs.org 7 | import emoji from 'markdown-it-emoji'; // https://github.com/markdown-it/markdown-it-emoji 8 | import { loadConfig, renderPages } from './render/pages-provider.js'; 9 | import { collectSideMenuData, getPagesList } from './render/side-menu-provider.js'; 10 | import { getTimeStamp } from './common-provider.js'; 11 | import { renderSpecialPages } from './render/special-pages-provider.js'; 12 | import { renderSitemap, updateReadmeDocs } from './render/sitemap-provider.js'; 13 | 14 | export const DATA_FOLDER = path.join(process.cwd(), './src/docs/data'); 15 | export const OUTPUT_FOLDER = path.join(process.cwd(), './docs'); 16 | 17 | // markdown ------------------- 18 | const md = initMarkDown(); 19 | md.use(emoji); 20 | configureMarkdown(md); 21 | 22 | const init = async () => { 23 | const sourceRootPath = path.join(DATA_FOLDER, './pages'); 24 | const targetRootPath = path.join(OUTPUT_FOLDER, './pages'); 25 | 26 | const cssTimeStamp = getTimeStamp(); 27 | const jsTimeStamp = getTimeStamp(); 28 | 29 | // empty destination folders 30 | fse.emptyDirSync(targetRootPath); 31 | fse.emptyDirSync(path.join(OUTPUT_FOLDER, './css')); 32 | fse.emptyDirSync(path.join(OUTPUT_FOLDER, './js')); 33 | 34 | // load layout 35 | const layoutPath = path.join(DATA_FOLDER, './layouts/page-layout.html'); 36 | const layout = fs.readFileSync(layoutPath, 'utf8'); 37 | 38 | // load config files 39 | const mainConfig = loadConfig(path.join(DATA_FOLDER, './config.json')); 40 | const pagesConfig = loadConfig(path.join(DATA_FOLDER, './pages/pages-config.json')); 41 | 42 | // collect side menu data 43 | const sideMenuMap = new Map(); 44 | collectSideMenuData(sourceRootPath, null, sideMenuMap); 45 | 46 | // pages list is used for prev / next section at the bottom of the pages 47 | const pagesList = getPagesList(sideMenuMap); 48 | 49 | // render all pages in the given folder recursively - markdown to html 50 | renderPages(sourceRootPath, targetRootPath, { 51 | layout, 52 | sideMenuMap, 53 | pagesConfig, 54 | cssTimeStamp, 55 | jsTimeStamp, 56 | pagesList, 57 | mainConfig, 58 | }, md); 59 | 60 | // render all pages like index.html 61 | const specialPagesLayoutPath = path.join(DATA_FOLDER, './layouts/special-page-layout.html'); 62 | const specialPagesLayout = fs.readFileSync(specialPagesLayoutPath, 'utf8'); 63 | 64 | renderSpecialPages( 65 | path.join(DATA_FOLDER, './special-pages'), 66 | path.join(OUTPUT_FOLDER), 67 | { 68 | layout: specialPagesLayout, 69 | cssTimeStamp, 70 | jsTimeStamp, 71 | mainConfig, 72 | } 73 | ); 74 | 75 | // render sitemap 76 | renderSitemap( 77 | mainConfig?.website?.url || '', 78 | path.join(OUTPUT_FOLDER), 79 | pagesList 80 | ); 81 | 82 | compileClientSideScripts(jsTimeStamp); 83 | await compileClientSideCSS(cssTimeStamp); 84 | 85 | updateReadmeDocs( 86 | mainConfig?.website?.url || '', 87 | path.join(OUTPUT_FOLDER), 88 | sideMenuMap, 89 | pagesConfig 90 | ); 91 | }; 92 | 93 | await init(); -------------------------------------------------------------------------------- /src/docs/generator/render/macros-provider.js: -------------------------------------------------------------------------------- 1 | export const setMacros = (html, data) => { 2 | let result = html; 3 | 4 | result = result.replaceAll('{% css-hash %}', data.cssTimeStamp); 5 | result = result.replaceAll('{% js-hash %}', data.jsTimeStamp); 6 | result = result.replaceAll('{% website-name %}', data.mainConfig.website.name); 7 | result = result.replaceAll('{% github %}', data.mainConfig.social.github); 8 | result = result.replaceAll('{% twitter %}', data.mainConfig.social.twitter); 9 | result = result.replaceAll('{% email %}', data.mainConfig.social.email); 10 | result = result.replaceAll('{% google-analytics-gtag %}', data.mainConfig.analytics.gtag); 11 | 12 | return result; 13 | }; -------------------------------------------------------------------------------- /src/docs/generator/render/sitemap-provider.js: -------------------------------------------------------------------------------- 1 | import { removeNumberOnStart, toTitleCase } from '../common-provider.js'; 2 | import fs from 'fs'; 3 | import path from 'path'; 4 | 5 | export const renderSitemap = (websiteUrl, rootPath, pagesList) => { 6 | let siteMap = `${ websiteUrl }\n`; 7 | 8 | for(const link of pagesList){ 9 | const formatted = `${ websiteUrl }/pages/${ removeNumberOnStart(link) }.html\n`; 10 | siteMap += formatted; 11 | } 12 | 13 | const targetFilePath = path.join(rootPath, 'sitemap.txt') 14 | fs.writeFileSync(targetFilePath, siteMap, 'utf8'); 15 | }; 16 | 17 | export const updateReadmeDocs = (websiteUrl, rootPath, sideMenuMap, pagesConfig) => { 18 | const DOCS_START = '## Documentation 🔖'; 19 | const DOCS_END = '------------------------------'; 20 | 21 | const readmePath = path.join(process.cwd(), './README.md'); 22 | let readme = fs.readFileSync(readmePath, 'utf8'); 23 | if(!readme.includes(DOCS_START)) return; 24 | 25 | // create the 'Table of contents' 26 | let md = `${ DOCS_START }\n`; 27 | 28 | const sections = Array.from(sideMenuMap.keys()); 29 | 30 | // sort sections (folders) in the alphanumeric order 31 | // before removing the beginning number with dash 32 | sections.sort((item1, item2) => { 33 | return item1.localeCompare(item2, undefined, { 34 | numeric: true, 35 | sensitivity: 'base' 36 | }); 37 | }); 38 | 39 | for(const section of sections) { 40 | // check if section title appears in pages-config.json 41 | // otherwise remove dashes and apply title case 42 | const sectionConfigValue = pagesConfig[`${ section }`]; 43 | const sectionTitle = sectionConfigValue ? sectionConfigValue.title : toTitleCase(removeNumberOnStart(section)); 44 | 45 | // find all section links and sort them in alphanumeric order 46 | // before removing the beginning number with dash 47 | const links = Array.from(sideMenuMap.get(section)); 48 | links.sort((item1, item2) => { 49 | return item1.localeCompare(item2, undefined, { 50 | numeric: true, 51 | sensitivity: 'base' 52 | }); 53 | }); 54 | 55 | // add title -------- 56 | md += `### ${ sectionTitle } \n`; 57 | 58 | for (let i = 0; i < links.length; i++) { 59 | const link = links[i]; 60 | const codeName = removeNumberOnStart(link); 61 | 62 | // check if page titles appears in pages-config.json 63 | // otherwise remove dashes and apply title case 64 | const pagesConfigValue = pagesConfig[`${ link }.md`]; 65 | const title = pagesConfigValue ? pagesConfigValue.title : toTitleCase(codeName); 66 | 67 | const url = `${ websiteUrl }/pages/${ codeName }.html`; 68 | md += `- [${ title }](${ url })\n`; 69 | } 70 | } 71 | 72 | md += `${ DOCS_END }\n`; 73 | 74 | // replace the value in readme 75 | const regex = new RegExp(`${ DOCS_START }([\\s\\S]*)${ DOCS_END }`, 'gim'); 76 | readme = readme.replace(regex, md); 77 | 78 | fs.writeFileSync(readmePath, readme, 'utf8'); 79 | }; -------------------------------------------------------------------------------- /src/docs/generator/render/special-pages-provider.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { removeNumberOnStart } from '../common-provider.js'; 4 | import fse from 'fs-extra'; 5 | import { setMacros } from './macros-provider.js'; 6 | 7 | /** 8 | * render all pages special pages like index.html 9 | * @param {string} sourceRootPath 10 | * @param {string} targetRootPath 11 | * @param {object} data 12 | */ 13 | export const renderSpecialPages = (sourceRootPath, targetRootPath, data) => { 14 | 15 | const items = fs.readdirSync(sourceRootPath); 16 | 17 | // loop through all the nested files and folders 18 | for (const item of items) { 19 | 20 | if(item === '.DS_Store') continue; 21 | 22 | // get the absolute file / folder path 23 | const sourceItemPath = path.join(sourceRootPath, item); 24 | const targetItemPath = path.join(targetRootPath, removeNumberOnStart(item)); 25 | 26 | // console.log(`Working on ${ sourceItemPath }`); 27 | 28 | const stat = fs.statSync( sourceItemPath ); 29 | 30 | // in case it's a file 31 | if(stat.isFile()){ 32 | 33 | const ext = path.extname(item); 34 | 35 | if(ext === '.html'){ 36 | const html = fs.readFileSync(sourceItemPath, 'utf8'); 37 | 38 | let result = data.layout.replaceAll('{% page-content %}', html); 39 | result = setMacros(result, data); 40 | 41 | // write the output HTML to the destination 42 | const targetFilePath = targetItemPath; 43 | fse.ensureFileSync(targetFilePath); 44 | fs.writeFileSync(targetFilePath, result, 'utf8'); 45 | } 46 | } 47 | 48 | // in case it's a folder - > render recursively 49 | else{ 50 | renderSpecialPages(sourceItemPath, targetRootPath, data); 51 | } 52 | } 53 | }; -------------------------------------------------------------------------------- /src/index-esm.ts: -------------------------------------------------------------------------------- 1 | export * from './main/linear-algebra/vector'; 2 | export * from './main/linear-algebra/matrix'; 3 | export * from './main/linear-algebra/matrix-transformations'; 4 | export * from './main/format'; 5 | export * from './main/angle'; 6 | export * from './main/random'; 7 | export * from './main/other'; 8 | export * from './main/convert'; 9 | export * from './main/bezier-curves/bezier-curve'; 10 | export * from './main/equations/linear-equations'; 11 | export * from './main/path-movement'; 12 | export * from './main/color'; 13 | export * from './main/physics'; 14 | export * from './main/id'; 15 | export * from './main/derivative'; 16 | export * from './main/collision-detection'; 17 | export * from './main/animation'; 18 | export * from './main/circle-ellipse'; 19 | export * from './main/sequence'; 20 | export * from './main/statistics'; 21 | export * from './main/ml'; 22 | export * from './main/series'; 23 | export * from './main/combinatorics/factorial'; 24 | export * from './main/combinatorics/combinatorics'; -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as vector from './main/linear-algebra/vector'; 2 | import * as matrix from './main/linear-algebra/matrix'; 3 | import * as matrixTransformations from './main/linear-algebra/matrix-transformations'; 4 | import * as format from './main/format'; 5 | import * as angle from './main/angle'; 6 | import * as random from './main/random'; 7 | import * as other from './main/other'; 8 | import * as convert from './main/convert'; 9 | import * as bezierCurve from './main/bezier-curves/bezier-curve'; 10 | import * as equations from './main/equations/linear-equations'; 11 | import * as pathMovement from './main/path-movement'; 12 | import * as color from './main/color'; 13 | import * as physics from './main/physics'; 14 | import * as id from './main/id'; 15 | import * as derivative from './main/derivative'; 16 | import * as collisions from './main/collision-detection'; 17 | import * as animation from './main/animation'; 18 | import * as circleEllipse from './main/circle-ellipse'; 19 | import * as sequence from './main/sequence'; 20 | import * as statistics from './main/statistics'; 21 | import * as ml from './main/ml'; 22 | import * as series from './main/series'; 23 | import * as factorial from './main/combinatorics/factorial'; 24 | import * as combinatorics from './main/combinatorics/combinatorics'; 25 | 26 | const api = { 27 | ...vector, 28 | ...matrix, 29 | ...matrixTransformations, 30 | ...format, 31 | ...angle, 32 | ...random, 33 | ...other, 34 | ...convert, 35 | ...bezierCurve, 36 | ...equations, 37 | ...pathMovement, 38 | ...color, 39 | ...physics, 40 | ...id, 41 | ...derivative, 42 | ...collisions, 43 | ...animation, 44 | ...circleEllipse, 45 | ...sequence, 46 | ...statistics, 47 | ...ml, 48 | ...series, 49 | ...factorial, 50 | ...combinatorics, 51 | }; 52 | 53 | declare global { 54 | interface Window { 55 | mzMath: typeof api, 56 | } 57 | } 58 | 59 | window.mzMath = window.mzMath || api; 60 | 61 | export * from './main/linear-algebra/vector'; 62 | export * from './main/linear-algebra/matrix'; 63 | export * from './main/linear-algebra/matrix-transformations'; 64 | export * from './main/format'; 65 | export * from './main/angle'; 66 | export * from './main/random'; 67 | export * from './main/other'; 68 | export * from './main/convert'; 69 | export * from './main/bezier-curves/bezier-curve'; 70 | export * from './main/equations/linear-equations'; 71 | export * from './main/path-movement'; 72 | export * from './main/color'; 73 | export * from './main/physics'; 74 | export * from './main/id'; 75 | export * from './main/derivative'; 76 | export * from './main/collision-detection'; 77 | export * from './main/animation'; 78 | export * from './main/circle-ellipse'; 79 | export * from './main/sequence'; 80 | export * from './main/statistics'; 81 | export * from './main/ml'; 82 | export * from './main/series'; 83 | export * from './main/combinatorics/factorial'; 84 | export * from './main/combinatorics/combinatorics'; -------------------------------------------------------------------------------- /src/main/circle-ellipse.ts: -------------------------------------------------------------------------------- 1 | import { setDecimalPlaces } from './format'; 2 | 3 | export const getCircleCircumference = (radius: number, decimalPlaces = Infinity) => { 4 | return setDecimalPlaces(2 * Math.PI * radius, decimalPlaces); 5 | }; 6 | 7 | export const getEllipseCircumference = (radius1: number, radius2: number, decimalPlaces = Infinity) => { 8 | return setDecimalPlaces(2 * Math.PI * Math.sqrt((radius1 ** 2 + radius2 ** 2) / 2), decimalPlaces); 9 | }; 10 | 11 | export const isAngleInCircleArc = (startAngleDeg: number, endAngleDeg: number, currentDegrees: number) : boolean => { 12 | 13 | if(startAngleDeg > endAngleDeg) { 14 | endAngleDeg += 360; 15 | } 16 | 17 | return currentDegrees >= startAngleDeg && currentDegrees <= endAngleDeg || 18 | (currentDegrees + 360) >= startAngleDeg && (currentDegrees + 360) <= endAngleDeg; 19 | }; 20 | 21 | /** 22 | * get the side of a square inscribed in a circle 23 | */ 24 | export const getSquareInCircleSide = (radius: number, decimalPlaces = Infinity) => { 25 | return setDecimalPlaces(radius * 2 / Math.sqrt(2), decimalPlaces); 26 | }; 27 | -------------------------------------------------------------------------------- /src/main/collision-detection.ts: -------------------------------------------------------------------------------- 1 | import { ICircle, IPolygon, IRect, Matrix2, Vector2 } from '../types'; 2 | import { mod } from './other'; 3 | import { v2GetNormal, v2DotProduct } from './linear-algebra/vector'; 4 | 5 | /** 6 | * Rectangles collision detection. 7 | * Rectangles should not be rotated. 8 | * The algorithm works by ensuring there is no gap between any of the 4 sides of the rectangles. 9 | * Any gap means a collision does not exist. 10 | * Returns true if collision is detected. 11 | */ 12 | export const rectCollide = (rect1: IRect, rect2: IRect) : boolean => { 13 | return rect1.x <= rect2.x + rect2.w && 14 | rect1.x + rect1.w >= rect2.x && 15 | rect1.y <= rect2.y + rect2.h && 16 | rect1.h + rect1.y >= rect2.y; 17 | }; 18 | 19 | /** 20 | * Circles collision detection. 21 | * This algorithm works by taking the center points of the two circles 22 | * and ensuring the distance between the center points 23 | * are less than the two radii added together. 24 | * Returns true if collision is detected. 25 | */ 26 | export const circleCollide = (circle1: ICircle, circle2: ICircle) => { 27 | const dx = Math.abs(circle1.cx - circle2.cx); 28 | const dy = Math.abs(circle1.cy - circle2.cy); 29 | const distance = Math.sqrt(dx * dx + dy * dy); 30 | return distance <= circle1.r + circle2.r; 31 | }; 32 | 33 | //-------------------- Separating Axis Theorem (SAT) Collision detection ------------------------- 34 | 35 | const getEdges = (poly: IPolygon) : Matrix2[] => { 36 | const edges: Matrix2[] = []; 37 | 38 | for(let i= 0; i { 48 | const edges: Matrix2[] = []; 49 | 50 | // collect polygon edges, and combine then into a single array 51 | edges.push(...getEdges(poly1)); 52 | edges.push(...getEdges(poly2)); 53 | 54 | // for each edge, find the normal vector and project both polygons onto it 55 | for (const edge of edges) { 56 | const normal = v2GetNormal(edge[0], edge[1]); 57 | const p1Proj = projectPolygon(poly1, normal); 58 | const p2Proj = projectPolygon(poly2, normal); 59 | 60 | // Check if the projections overlap 61 | const isOverlap = p1Proj.max >= p2Proj.min && p2Proj.max >= p1Proj.min; 62 | 63 | // Check if the projections overlap; if not, the polygons do not collide 64 | if (!isOverlap) return false; 65 | } 66 | 67 | // If all tests pass, the polygons overlap and collide 68 | return true; 69 | }; 70 | 71 | /** 72 | * Project every polygon point onto the normal. 73 | * Then find min and max. 74 | */ 75 | const projectPolygon = (polygon: IPolygon, normal: Vector2): { min: number, max: number } => { 76 | let min = Infinity; 77 | let max = -Infinity; 78 | 79 | // Project each vertex of the polygon onto the axis 80 | for (const vertex of polygon) { 81 | const projection = v2DotProduct(vertex, normal); 82 | min = Math.min(min, projection); 83 | max = Math.max(max, projection); 84 | } 85 | 86 | return { min, max }; 87 | }; -------------------------------------------------------------------------------- /src/main/convert.ts: -------------------------------------------------------------------------------- 1 | export const stringToNumber = (value: string|undefined|null|number, defaultNumber: number) => { 2 | if(value === undefined || value === null) return defaultNumber; 3 | const res = Number(value) ?? defaultNumber; 4 | return isNaN(res) ? defaultNumber : res; 5 | }; -------------------------------------------------------------------------------- /src/main/equations/quadratic-equations.ts: -------------------------------------------------------------------------------- 1 | import { Vector } from '../../types'; 2 | import { setDecimalPlaces } from '../format'; 3 | import { linearEquation } from './linear-equations'; 4 | import { isNumber } from '../other'; 5 | 6 | /** 7 | * Quadratic Equation. 8 | * ax^2 + bx + c = d 9 | */ 10 | export const quadraticEquation = (equation: Vector, decimalPlaces = Infinity) : Vector => { 11 | const a = equation[0]; 12 | const b = equation[1]; 13 | const c = equation[2]; 14 | const d = equation[3]; 15 | 16 | if(a === 0){ 17 | // it's a linear equation ------------------------------------------- 18 | const res = linearEquation([b, c, d], decimalPlaces); 19 | if(isNumber(res)) return [res]; 20 | return []; 21 | } 22 | 23 | const diff = c - d; 24 | 25 | const discriminant = b * b - (4 * a * diff); 26 | 27 | if(discriminant < 0){ 28 | return []; // no results 29 | } 30 | 31 | if(discriminant === 0){ 32 | return [ setDecimalPlaces(-b / (2 * a), decimalPlaces) ]; // 1 result 33 | } 34 | 35 | // if(determinant > 0) ---> 2 results 36 | const t1 = 2 * a; 37 | const t2 = Math.sqrt(discriminant); 38 | 39 | return [ 40 | setDecimalPlaces((-b + t2) / t1, decimalPlaces), 41 | setDecimalPlaces((-b - t2) / t1, decimalPlaces), 42 | ]; 43 | }; -------------------------------------------------------------------------------- /src/main/format.ts: -------------------------------------------------------------------------------- 1 | export const setDecimalPlaces = (num: number, decimalPlaces: number | undefined = Infinity) => { 2 | if(decimalPlaces === Infinity) return num; 3 | 4 | if(decimalPlaces < 0){ 5 | decimalPlaces = 0; 6 | } 7 | 8 | const coefficient = 10 ** decimalPlaces; 9 | return Math.round(num * coefficient) / coefficient; 10 | }; -------------------------------------------------------------------------------- /src/main/id.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * guid like '932ade5e-c515-4807-ac01-73b20ab3fb66' 3 | */ 4 | export const guid = () => { 5 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { 6 | const r = Math.random() * 16 | 0; 7 | return (c == 'x' ? r : r & 0x3 | 0x8).toString(16); 8 | }); 9 | }; 10 | 11 | /** 12 | * id like 'df4unio1opulby2uqh4' 13 | */ 14 | export const newId = () => { 15 | return Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36); 16 | }; 17 | -------------------------------------------------------------------------------- /src/main/ml.ts: -------------------------------------------------------------------------------- 1 | import { setDecimalPlaces } from './format'; 2 | import { getArithmeticMean, getStandardDeviation } from './statistics'; 3 | import { IMlNormalizeResult, IMlStandardizeResult } from '../types'; 4 | 5 | // --------------------- NORMALIZE -------------------------------- 6 | 7 | /** 8 | * Changes value to be in the range [0, 1]. 9 | */ 10 | export const mlNormalizeValue = (value: number, min: number, max: number, decimalPlaces = Infinity) : number => { 11 | const diff = max - min; 12 | if(diff === 0) return 0; 13 | return setDecimalPlaces((value - min) / diff, decimalPlaces); 14 | }; 15 | 16 | /** 17 | * Returns a copy of array, where each value will be in the range [0, 1]. 18 | */ 19 | export const mlNormalizeArray = (data: number[], min: number, max: number, decimalPlaces = Infinity): number[] => { 20 | const copy = [...data]; 21 | 22 | for(let i=0; i { 30 | const min = Math.min(...data); 31 | const max = Math.max(...data); 32 | const _data = mlNormalizeArray(data, min, max, decimalPlaces); 33 | 34 | return { 35 | min: setDecimalPlaces(min, decimalPlaces), 36 | max: setDecimalPlaces(max, decimalPlaces), 37 | data: _data, 38 | }; 39 | }; 40 | 41 | /** 42 | * Alias. 43 | */ 44 | export const mlNormalizeUnseenData = (data: number[], min: number, max: number, decimalPlaces = Infinity): number[] => { 45 | return mlNormalizeArray(data, min, max, decimalPlaces); 46 | }; 47 | 48 | // --------------------- STANDARDIZE -------------------------------- 49 | 50 | /** 51 | * Changes value to be in the range [-1, 1]. 52 | */ 53 | export const mlStandardizeValue = (value: number, mean: number, stdDev: number, decimalPlaces = Infinity) : number => { 54 | if(stdDev === 0) return 0; 55 | return setDecimalPlaces((value - mean) / stdDev, decimalPlaces); 56 | }; 57 | 58 | /** 59 | * Returns a copy of array, where each value will be in the range [-1, 1]. 60 | */ 61 | export const mlStandardizeArray = (data: number[], mean: number, stdDev: number, decimalPlaces = Infinity) : number[] => { 62 | return [...data].map(value => mlStandardizeValue(value, mean, stdDev, decimalPlaces)); 63 | }; 64 | 65 | export const mlStandardizeTestData = (data: number[], decimalPlaces = Infinity): IMlStandardizeResult => { 66 | const mean = getArithmeticMean(data) ?? 0; 67 | const stdDev = getStandardDeviation(data); 68 | const _data = mlStandardizeArray(data, mean, stdDev, decimalPlaces); 69 | 70 | return { 71 | mean: setDecimalPlaces(mean, decimalPlaces), 72 | stdDev: setDecimalPlaces(stdDev, decimalPlaces), 73 | data: _data, 74 | }; 75 | }; 76 | 77 | /** 78 | * Alias. 79 | */ 80 | export const mlStandardizeUnseenData = (data: number[], mean: number, stdDev: number, decimalPlaces = Infinity): number[] => { 81 | return mlStandardizeArray(data, mean, stdDev, decimalPlaces); 82 | }; -------------------------------------------------------------------------------- /src/main/other.ts: -------------------------------------------------------------------------------- 1 | import { Vector2 } from '../types'; 2 | import { setDecimalPlaces } from './format'; 3 | 4 | export const mod = (n: number, m: number) => { 5 | return ((n % m) + m) % m; 6 | }; 7 | 8 | /** 9 | * Convert range [a, b] to [c, d]. 10 | * f(x) = (d - c) * (x - a) / (b - a) + c 11 | */ 12 | export const convertRange = (x: number, a: number, b: number, c: number, d: number) => { 13 | return (d - c) * (x - a) / (b - a) + c; 14 | }; 15 | 16 | /** 17 | * Check if 2 ranges [a,b] and [c,d] overlap. 18 | */ 19 | export const doRangesOverlap = (a: number, b: number, c: number, d: number) => { 20 | return Math.max(a, c) <= Math.min(b, d) ; 21 | }; 22 | 23 | // eslint-disable-next-line 24 | export const isNumber = (value: any) => { 25 | return !isNaN(parseFloat(value)) && isFinite(value); 26 | }; 27 | 28 | /** 29 | * Convert polar coordinates to cartesian coordinates. 30 | */ 31 | export const polarToCartesian = (center: Vector2, radii: Vector2, angleInRad: number, decimalPlaces = Infinity) : Vector2 => { 32 | const [cx, cy] = center; 33 | const [rx, ry] = radii; 34 | 35 | return [ 36 | setDecimalPlaces(cx + (rx * Math.cos(angleInRad)), decimalPlaces), 37 | setDecimalPlaces(cy + (ry * Math.sin(angleInRad)), decimalPlaces), 38 | ]; 39 | }; 40 | 41 | /** 42 | * Greatest common divisor (GCD) - Euclidean algorithm. 43 | * O( log(min(num1, num2)) ). 44 | * 45 | * GCD is always defined as a non-negative number. 46 | * If num2 is 0, then the GCD is num1. 47 | * Otherwise, the GCD of num1 and num2 is the same as the GCD of num2 and num1 % num2. 48 | * 49 | * a=48,𝑏=18 ---> 48 % 18 = 12 50 | * a=18,b=12 ---> 18 % 12 = 6 51 | * a=12,b=6 ---> 12 % 6 = 0 52 | * a=6,b=0 ---> result is 6 53 | */ 54 | export const gcd = (num1: number, num2: number): number => { 55 | num1 = Math.abs(num1); 56 | num2 = Math.abs(num2); 57 | 58 | while (num2 !== 0) { 59 | const temp = num2; 60 | num2 = num1 % num2; 61 | num1 = temp; 62 | } 63 | 64 | return num1; 65 | }; -------------------------------------------------------------------------------- /src/main/physics.ts: -------------------------------------------------------------------------------- 1 | import { Vector2 } from '../types'; 2 | 3 | /** 4 | * Speed = how far something moves in a given amount of time. 5 | * Speed is also a vector: 6 | * magnitude = distance 7 | * direction = time 8 | */ 9 | export type Speed = Vector2; 10 | 11 | /** 12 | * Velocity is a measure of how fast an object is moving in a particular direction. 13 | * Velocity = Distance traveled / Time taken 14 | * It has a magnitude and direction, and can be represented as a vector. 15 | */ 16 | export type Velocity = Vector2; 17 | 18 | /** 19 | * Acceleration is a measure of how quickly an object's velocity changes over time. 20 | * Acceleration = (Final velocity - Initial velocity) / Time taken 21 | * a = (vf - v0)/t. 22 | * Distance = Initial velocity * time + (acceleration * time^2) / 2 23 | * It also has a magnitude and direction, and can be represented as a vector. 24 | * When the direction is negative ----> it's a "slowdown" movement 25 | */ 26 | export type Acceleration = Vector2; 27 | 28 | /** 29 | * Gravity is the force that attracts two objects with mass toward each other. 30 | * Newton's law of universal gravitation formula: 31 | * Gravitational force = (Gravitational constant * Mass of object 1 * Mass of object 2) / Distance between objects^2 32 | * It also has a magnitude and direction, and can be represented as a vector. 33 | * magnitude = the strength of the gravitational force 34 | * direction = the direction in which the force is acting (the direction of the gravitational force is always toward the center of mass of the objects involved) 35 | */ 36 | export type Gravity = Vector2; 37 | 38 | -------------------------------------------------------------------------------- /src/main/random.ts: -------------------------------------------------------------------------------- 1 | import { setDecimalPlaces } from './format'; 2 | 3 | /** 4 | * Returns a random number in the [min,max] range. 5 | */ 6 | export const getRandom = (min: number, max: number, decimalPlaces = Infinity): number => { 7 | return setDecimalPlaces(Math.random() * (max - min) + min, decimalPlaces); 8 | }; 9 | 10 | /** 11 | * Returns a random integer number in the [min,max] range. 12 | */ 13 | export const getRandomInt = (min: number, max: number): number => { 14 | return Math.floor(Math.random() * (max - min + 1) + min); 15 | }; 16 | 17 | export const getRandomBoolean = () => Math.random() < 0.5; 18 | 19 | /* eslint-disable @typescript-eslint/no-explicit-any */ 20 | export const getRandomItemFromArray = (array: any[]) => { 21 | const randomIndex = getRandomInt(0, array.length - 1); 22 | return array[randomIndex]; 23 | }; -------------------------------------------------------------------------------- /src/main/sequence.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 1 + 2 + ... + n = n * (n + 1) / 2 3 | */ 4 | export const naturalNumbersSequenceSum = (n: number) => { 5 | return n * (n + 1) / 2; 6 | }; 7 | 8 | /** 9 | * n = the number of terms to be added 10 | * a = the first term in the sequence 11 | * d = the constant value between terms 12 | */ 13 | export const arithmeticSequenceSum = (n: number, a: number, d: number) => { 14 | return (n / 2) * (2 * a + (n - 1) * d); 15 | }; -------------------------------------------------------------------------------- /src/main/series.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Sum of 1 to n numbers: 3 | * (n * (n + 1)) / 2 4 | */ 5 | export const naturalNumbersSum1ToN = (n: number): number => { 6 | return (n / 2) * (n + 1); 7 | }; 8 | 9 | /** 10 | * Sum of m to n numbers. 11 | */ 12 | export const naturalNumbersSumMToN = (m: number, n: number): number => { 13 | return (n - m + 1) * (m + n) / 2; 14 | }; -------------------------------------------------------------------------------- /src/main/temperature.ts: -------------------------------------------------------------------------------- 1 | import { setDecimalPlaces } from './format'; 2 | 3 | export const celsiusToFahrenheit = (celsius: number, decimalPlaces = Infinity) => { 4 | return setDecimalPlaces(celsius * 1.80 + 32.00, decimalPlaces); 5 | }; 6 | 7 | export const celsiusToKelvin = (celsius: number, decimalPlaces = Infinity) => { 8 | return setDecimalPlaces(celsius + 273.15, decimalPlaces); 9 | }; 10 | 11 | export const fahrenheitToCelsius = (fahrenheit: number, decimalPlaces = Infinity) => { 12 | return setDecimalPlaces((fahrenheit - 32) * 5 / 9, decimalPlaces); 13 | }; 14 | 15 | export const fahrenheitToKelvin = (fahrenheit: number, decimalPlaces = Infinity) => { 16 | return setDecimalPlaces((fahrenheit - 32) * 5 / 9 + 273.15, decimalPlaces); 17 | }; 18 | 19 | export const kelvinToCelsius = (kelvin: number, decimalPlaces = Infinity) => { 20 | return setDecimalPlaces(kelvin - 273.15, decimalPlaces); 21 | }; 22 | 23 | export const kelvinToFahrenheit = (kelvin: number, decimalPlaces = Infinity) => { 24 | return setDecimalPlaces((kelvin - 273.15) * 1.80 + 32, decimalPlaces); 25 | }; -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | export type Vector2 = [number, number]; 2 | export type Vector3 = [number, number, number]; 3 | export type Vector4 = [number, number, number, number]; 4 | export type Vector = number[]; 5 | 6 | export type Matrix2 = Vector2[]; 7 | export type Matrix3 = Vector3[]; 8 | export type Matrix4 = Vector4[]; 9 | export type Matrix = Vector[]; 10 | 11 | export type HSLColor = [number, number, number]; // [hue, saturation, lightness] [0-360, 0-100, 0-100] 12 | export type RGBColor = [number, number, number]; // [r, g, b] [0, 255, 0, 255, 0, 255] 13 | export type LABColor = [number, number, number]; // [l, a, b] [0, 255, 0, 255, 0, 255] lab(29.2345%, 39.3825, 20.0664); 14 | 15 | export interface IBBox { 16 | x: number; 17 | y: number; 18 | w: number; 19 | h: number; 20 | x2: number; 21 | y2: number; 22 | } 23 | 24 | export interface IRect { 25 | x: number; 26 | y: number; 27 | w: number; 28 | h: number; 29 | } 30 | 31 | export interface ICircle { 32 | cx: number; 33 | cy: number; 34 | r: number; 35 | } 36 | 37 | export type IPolygon = Vector2[]; 38 | 39 | export interface IMlStandardizeResult { 40 | mean: number; 41 | stdDev: number; 42 | data: number[]; 43 | } 44 | 45 | export interface IMlNormalizeResult { 46 | min: number; 47 | max: number; 48 | data: number[]; 49 | } -------------------------------------------------------------------------------- /test/browser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TypeScript Math Helpers 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /test/circle-ellipse.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | getSquareInCircleSide, 3 | getCircleCircumference, 4 | getEllipseCircumference, 5 | isAngleInCircleArc, 6 | } from '../src/main/circle-ellipse'; 7 | 8 | describe('Circle / Ellipse', () => { 9 | 10 | describe('getSquareInCircleSide()', () => { 11 | test('square side in circle with radius = 10', () => { 12 | expect(getSquareInCircleSide(10)).toStrictEqual(14.14213562373095); 13 | }); 14 | 15 | test('square side in circle with radius = 10 and 2 decimal places', () => { 16 | expect(getSquareInCircleSide(10, 2)).toStrictEqual(14.14); 17 | }); 18 | }); 19 | 20 | describe('getCircleCircumference()', () => { 21 | test('getCircleCircumference(10)', () => { 22 | expect(getCircleCircumference(10, 2)).toStrictEqual(62.83); 23 | }); 24 | }); 25 | 26 | describe('getEllipseCircumference()', () => { 27 | test('getEllipseCircumference(10, 20)', () => { 28 | expect(getEllipseCircumference(10, 20, 2)).toStrictEqual(99.35); 29 | }); 30 | }); 31 | 32 | describe('isAngleInCircleArc()', () => { 33 | test('isAngleInCircleArc(0, 90, 45)', () => { 34 | expect(isAngleInCircleArc(0, 90, 45)).toStrictEqual(true); 35 | }); 36 | 37 | test('isAngleInCircleArc(0, 90, 45)', () => { 38 | expect(isAngleInCircleArc(0, 90, 180)).toStrictEqual(false); 39 | }); 40 | }); 41 | }); -------------------------------------------------------------------------------- /test/convert.test.ts: -------------------------------------------------------------------------------- 1 | import { stringToNumber } from '../src/main/convert'; 2 | 3 | describe('String to Number', () => { 4 | test('If undefined is provided => return the default value', () => { 5 | expect(stringToNumber(undefined, 10)).toStrictEqual(10); 6 | }); 7 | 8 | test('If null is provided => return the default value', () => { 9 | expect(stringToNumber(null, 10)).toStrictEqual(10); 10 | }); 11 | 12 | test('If 0 is provided => return 0', () => { 13 | expect(stringToNumber(0, 10)).toStrictEqual(0); 14 | }); 15 | 16 | test('If "0" is provided => return 0', () => { 17 | expect(stringToNumber('0', 10)).toStrictEqual(0); 18 | }); 19 | 20 | test('If "10.1234" is provided => return 10.1234', () => { 21 | expect(stringToNumber('10.1234', 10)).toStrictEqual(10.1234); 22 | }); 23 | 24 | test('If "aaa" is provided => return the default value', () => { 25 | expect(stringToNumber('aaa', 20)).toStrictEqual(20); 26 | }); 27 | }); -------------------------------------------------------------------------------- /test/derivative.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | dxPolynomial, 3 | dxSin, 4 | dxCos, 5 | dxTan, 6 | dxCot, 7 | dxArcSin, 8 | dxArcCos, 9 | dxArcTan, 10 | dxArcCot 11 | } from '../src/main/derivative'; 12 | 13 | describe('Derivative', () => { 14 | 15 | describe('Polynomial', () => { 16 | 17 | test('y = 2, x = 5', () => { 18 | expect(dxPolynomial(5, [[2, 0]])).toStrictEqual(0); 19 | }); 20 | 21 | test('y = 2x, x = 5', () => { 22 | expect(dxPolynomial(5, [[2, 1]])).toStrictEqual(2); 23 | }); 24 | 25 | test('y = 5x^3 + 9x^2 + 7x + 3, x = 2', () => { 26 | expect(dxPolynomial(2, [[5, 3], [9, 2], [7, 1], [3, 0]])).toStrictEqual(103); 27 | }); 28 | 29 | test('y = 3x+2, x = 10', () => { 30 | expect(dxPolynomial(10, [[3, 1], [2, 0]])).toStrictEqual(3); 31 | }); 32 | 33 | test('y = 5x^3 + 9x^2 + 7x + 3, x = 2', () => { 34 | expect(dxPolynomial(2, [[5, 3], [9, 2], [7, 1], [3, 0]])).toStrictEqual(103); 35 | }); 36 | 37 | test('y = 5x^(1/3), x = 2', () => { 38 | expect(dxPolynomial(2, [[5, 1/3]], 2)).toStrictEqual(1.05); 39 | }); 40 | 41 | test('y = 5x^(-1/3), x = 2', () => { 42 | expect(dxPolynomial(2, [[5, -1/3]], 2)).toStrictEqual(-0.66); 43 | }); 44 | 45 | }); 46 | 47 | describe('Trigonometric Functions', () => { 48 | 49 | test('dxSin(Math.PI, 2)', () => { 50 | expect(dxSin(Math.PI, 2)).toStrictEqual(-1); 51 | }); 52 | 53 | test('dxCos(Math.PI/2, 2)', () => { 54 | expect(dxCos(Math.PI/2, 2)).toStrictEqual(-1); 55 | }); 56 | 57 | test('dxTan(Math.PI, 2)', () => { 58 | expect(dxTan(Math.PI, 2)).toStrictEqual(1); 59 | }); 60 | 61 | test('dxCot(Math.PI/2, 2)', () => { 62 | expect(dxCot(Math.PI/2, 2)).toStrictEqual(-1); 63 | }); 64 | 65 | test('dxArcSin(Math.PI/4, 2)', () => { 66 | expect(dxArcSin(Math.PI/4, 2)).toStrictEqual(1.62); 67 | }); 68 | 69 | test('dxArcCos(Math.PI/4, 2)', () => { 70 | expect(dxArcCos(Math.PI/4, 2)).toStrictEqual(-1.62); 71 | }); 72 | 73 | test('dxArcTan(Math.PI/4, 2)', () => { 74 | expect(dxArcTan(Math.PI/4, 2)).toStrictEqual(0.62); 75 | }); 76 | 77 | test('dxArcCot(Math.PI/4, 2)', () => { 78 | expect(dxArcCot(Math.PI/4, 2)).toStrictEqual(-0.62); 79 | }); 80 | }); 81 | 82 | }); -------------------------------------------------------------------------------- /test/format.test.ts: -------------------------------------------------------------------------------- 1 | import { setDecimalPlaces } from '../src/main/format'; 2 | 3 | describe('Set Decimal Places', () => { 4 | test('2 decimal places of 1.2345 => 1.23', () => { 5 | expect(setDecimalPlaces(1.2345, 2)).toStrictEqual(1.23); 6 | }); 7 | 8 | test('2 decimal places of 1.2399 => 1.24', () => { 9 | expect(setDecimalPlaces(1.2399, 2)).toStrictEqual(1.24); 10 | }); 11 | 12 | test('if parameter is Infinity => the value should not change', () => { 13 | expect(setDecimalPlaces(1.2399, Infinity)).toStrictEqual(1.2399); 14 | }); 15 | 16 | test('if parameter is 0 => the value is integer', () => { 17 | expect(setDecimalPlaces(1.2399, 0)).toStrictEqual(1); 18 | }); 19 | 20 | test('if parameter is negative => the value is integer', () => { 21 | expect(setDecimalPlaces(1.2399, -1)).toStrictEqual(1); 22 | }); 23 | 24 | test('4 decimal places of 1.2399 => 1.2399', () => { 25 | expect(setDecimalPlaces(1.2399, 4)).toStrictEqual(1.2399); 26 | }); 27 | 28 | test('provided number of decimal places > the real number of decimal places => the number should not change', () => { 29 | expect(setDecimalPlaces(1.2399, 10)).toStrictEqual(1.2399); 30 | }); 31 | 32 | test('4 decimal places of 1.239999 => 1.2399', () => { 33 | expect(setDecimalPlaces(1.239999, 4)).toStrictEqual(1.24); 34 | }); 35 | 36 | test('-4 with Infinite negative places', () => { 37 | expect(setDecimalPlaces(-4, Infinity)).toStrictEqual(-4); 38 | }); 39 | 40 | test('-4.22222 with 2 negative places', () => { 41 | expect(setDecimalPlaces(-4.22222, 2)).toStrictEqual(-4.22); 42 | }); 43 | 44 | }); -------------------------------------------------------------------------------- /test/linear-interpolation.test.ts: -------------------------------------------------------------------------------- 1 | import { lerp } from '../src/main/linear-interpolation'; 2 | 3 | describe('Linear Interpolation', () => { 4 | 5 | test('lerp(5, 0, 100)', () => { 6 | expect(lerp(5, 0, 100)).toStrictEqual(500); 7 | }); 8 | }); -------------------------------------------------------------------------------- /test/ml.test.ts: -------------------------------------------------------------------------------- 1 | import { mlNormalizeValue, mlStandardizeValue } from '../src/main/ml'; 2 | 3 | describe('ML', () => { 4 | 5 | describe('mlNormalizeValue()', () => { 6 | 7 | it('10, 5, 5', () => { 8 | expect(mlNormalizeValue(10, 5, 5)).toBe(0); 9 | }); 10 | 11 | it('10, 5, 15', () => { 12 | expect(mlNormalizeValue(10, 5, 15)).toBe(0.5); 13 | }); 14 | 15 | it('10, 5, 15, 2', () => { 16 | expect(mlNormalizeValue(10, 5, 15, 2)).toBe(0.5); 17 | }); 18 | 19 | it('10, -5, 15', () => { 20 | expect(mlNormalizeValue(10, -5, 15)).toBe(0.75); 21 | }); 22 | }); 23 | 24 | describe('mlStandardizeValue()', () => { 25 | it('10, 5, 0', () => { 26 | expect(mlStandardizeValue(10, 5, 0)).toStrictEqual(0); 27 | }); 28 | 29 | it('10, 5, 2', () => { 30 | expect(mlStandardizeValue(10, 5, 2)).toStrictEqual(2.5); 31 | }); 32 | 33 | it('10, 5, 2, 2', () => { 34 | expect(mlStandardizeValue(10, 5, 2, 2)).toStrictEqual(2.5); 35 | }); 36 | 37 | it('10, -5, -2', () => { 38 | expect(mlStandardizeValue(10, -5, -2)).toStrictEqual(-7.5); 39 | }); 40 | }); 41 | }); -------------------------------------------------------------------------------- /test/sequence.test.ts: -------------------------------------------------------------------------------- 1 | import { naturalNumbersSequenceSum, arithmeticSequenceSum } from '../src/main/sequence'; 2 | 3 | describe('Sequence', () => { 4 | 5 | describe('naturalNumbersSequenceSum()', () => { 6 | 7 | test('test numbers from 1 to', () => { 8 | expect(naturalNumbersSequenceSum(1)).toStrictEqual(1); 9 | expect(naturalNumbersSequenceSum(2)).toStrictEqual(3); 10 | expect(naturalNumbersSequenceSum(3)).toStrictEqual(6); 11 | expect(naturalNumbersSequenceSum(5)).toStrictEqual(15); 12 | expect(naturalNumbersSequenceSum(6)).toStrictEqual(21); 13 | }); 14 | }); 15 | 16 | describe('arithmeticSequenceSum()', () => { 17 | test('2 + 4 + 6 + 8', () => { 18 | expect(arithmeticSequenceSum(4, 2, 2)).toStrictEqual(20); 19 | }); 20 | }); 21 | }); -------------------------------------------------------------------------------- /test/series.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | naturalNumbersSum1ToN, 3 | naturalNumbersSumMToN, 4 | } from '../src/main/series'; 5 | 6 | describe('Series', () => { 7 | 8 | describe('naturalNumbersSum1ToN()', () => { 9 | test('1', () => { 10 | expect(naturalNumbersSum1ToN(1)).toStrictEqual(1); 11 | }); 12 | 13 | test('2', () => { 14 | expect(naturalNumbersSum1ToN(2)).toStrictEqual(3); 15 | }); 16 | 17 | test('3', () => { 18 | expect(naturalNumbersSum1ToN(3)).toStrictEqual(6); 19 | }); 20 | }); 21 | 22 | describe('naturalNumbersSumMToN()', () => { 23 | test('1, 1', () => { 24 | expect(naturalNumbersSumMToN(1,1)).toStrictEqual(1); 25 | }); 26 | 27 | test('5, 7', () => { 28 | expect(naturalNumbersSumMToN(5,7)).toStrictEqual(18); 29 | }); 30 | }); 31 | }); -------------------------------------------------------------------------------- /test/temperature.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | celsiusToFahrenheit, 3 | celsiusToKelvin, 4 | fahrenheitToCelsius, 5 | fahrenheitToKelvin, 6 | kelvinToCelsius, 7 | kelvinToFahrenheit, 8 | } from '../src/main/temperature'; 9 | 10 | describe('Temperature Conversion', () => { 11 | 12 | describe('Celsius to Fahrenheit', () => { 13 | test('should convert 0°C to 32°F', () => { 14 | expect(celsiusToFahrenheit(0)).toStrictEqual(32); 15 | }); 16 | 17 | test('should convert -40°C to -40°F', () => { 18 | expect(celsiusToFahrenheit(-40)).toStrictEqual(-40); 19 | }); 20 | 21 | test('Test rounding', () => { 22 | expect(celsiusToFahrenheit(32.698034, 2)).toStrictEqual(90.86); 23 | }); 24 | }); 25 | 26 | describe('Celsius to Kelvin', () => { 27 | test('should convert 0°C to 273.15K', () => { 28 | expect(celsiusToKelvin(0)).toStrictEqual(273.15); 29 | }); 30 | 31 | test('should convert -273.15°C to 0K', () => { 32 | expect(celsiusToKelvin(-273.15)).toStrictEqual(0); 33 | }); 34 | }); 35 | 36 | describe('Fahrenheit to Celsius', () => { 37 | test('should convert 32°F to 0°C', () => { 38 | expect(fahrenheitToCelsius(32)).toStrictEqual(0); 39 | }); 40 | 41 | test('should convert -40°F to -40°C', () => { 42 | expect(fahrenheitToCelsius(-40)).toStrictEqual(-40); 43 | }); 44 | }); 45 | 46 | describe('Fahrenheit to Kelvin', () => { 47 | test('should convert 32°F to 273.15K', () => { 48 | expect(fahrenheitToKelvin(32)).toBeCloseTo(273.15); 49 | }); 50 | 51 | test('should convert 212°F to 373.15K', () => { 52 | expect(fahrenheitToKelvin(212)).toBeCloseTo(373.15); 53 | }); 54 | }); 55 | 56 | describe('Kelvin to Celsius', () => { 57 | test('should convert 273.15K to 0°C', () => { 58 | expect(kelvinToCelsius(273.15)).toBeCloseTo(0); 59 | }); 60 | 61 | test('should convert 0K to -273.15°C', () => { 62 | expect(kelvinToCelsius(0)).toBeCloseTo(-273.15); 63 | }); 64 | }); 65 | 66 | describe('Kelvin to Fahrenheit', () => { 67 | test('should convert 273.15K to 32°F', () => { 68 | expect(kelvinToFahrenheit(273.15)).toBeCloseTo(32); 69 | }); 70 | 71 | test('should convert 373.15K to 212°F', () => { 72 | expect(kelvinToFahrenheit(373.15)).toBeCloseTo(212); 73 | }); 74 | }); 75 | }); -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "es2015", 5 | "moduleResolution": "node", 6 | "outDir": "./types", 7 | "allowJs": true, 8 | "isolatedModules": true, 9 | "esModuleInterop": true, 10 | "useDefineForClassFields": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "importHelpers": true, 13 | "suppressImplicitAnyIndexErrors": true, 14 | "declaration": true, 15 | "declarationMap": false, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "noImplicitThis": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "strictNullChecks": true, 23 | "strictBindCallApply": true, 24 | "jsx": "react", 25 | "skipLibCheck": true 26 | }, 27 | "include": [ 28 | "src", 29 | ], 30 | "exclude": [ 31 | "types", 32 | "node_modules", 33 | "dist", 34 | "**/*.test.ts" 35 | ] 36 | } --------------------------------------------------------------------------------