{"id":19551834,"url":"https://github.com/basics/vector","last_synced_at":"2025-04-26T20:31:21.999Z","repository":{"id":32852283,"uuid":"144403143","full_name":"basics/vector","owner":"basics","description":"This library provides 3D Vector in js including arithmetic operator overloading (+ - * / % **).","archived":false,"fork":false,"pushed_at":"2025-04-25T06:29:46.000Z","size":3531,"stargazers_count":14,"open_issues_count":10,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-25T07:31:02.021Z","etag":null,"topics":["arithmetic","basic","javascript","math","operator","operator-overloading","valueof","vec2","vec3","vector"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/basics.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-08-11T16:58:06.000Z","updated_at":"2025-03-22T10:57:55.000Z","dependencies_parsed_at":"2024-01-23T10:33:31.528Z","dependency_job_id":"e945c8fc-2170-42c5-88f7-66ea51b537f5","html_url":"https://github.com/basics/vector","commit_stats":{"total_commits":773,"total_committers":15,"mean_commits":51.53333333333333,"dds":0.7710219922380337,"last_synced_commit":"09b379c52f166f56233b6963f4d7724c59ca934a"},"previous_names":[],"tags_count":169,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/basics%2Fvector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/basics%2Fvector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/basics%2Fvector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/basics%2Fvector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/basics","download_url":"https://codeload.github.com/basics/vector/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250777843,"owners_count":21485692,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arithmetic","basic","javascript","math","operator","operator-overloading","valueof","vec2","vec3","vector"],"created_at":"2024-11-11T04:15:30.810Z","updated_at":"2025-04-26T20:31:21.986Z","avatar_url":"https://github.com/basics.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# basics - vector\n\n[![GitHub package version](https://img.shields.io/github/package-json/v/basics/vector.svg)](https://github.com/basics/vector)\n[![npm version](https://img.shields.io/npm/v/@js-basics/vector.svg)](https://www.npmjs.com/package/@js-basics/vector)\n[![license](https://img.shields.io/github/license/basics/vector.svg)](https://github.com/basics/vector)\n\n![main action pipeline](https://github.com/basics/vector/actions/workflows/main.yml/badge.svg)\n![beta action pipeline](https://github.com/basics/vector/actions/workflows/beta.yml/badge.svg)\n[![Renovate](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com)\n\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=basics_vector\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=basics_vector)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=basics_vector\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=basics_vector)\n[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=basics_vector\u0026metric=code_smells)](https://sonarcloud.io/summary/new_code?id=basics_vector)\n\nThis library provides 3D Vector in js including arithmetic operator overloading (`+ - * / % **`).\n\nNormally vector implementations in javascript handle arithmetic operation by methods `aVec.multiply(bVec).substract(dVec)`.\nOther languages provide operator overloading, that coders can create Vector class which can handle operation similar to number handling `aVec * bVec - dVec`.\n\nThis library gives javascript coders a way to handle operators with a single statement `() =\u003e aVec * bVec - dVec`.\nThe calculation can be combined with numbers `() =\u003e aVec * bVec * 4 - dVec - 1.5`.\nVector objects can be create with number `new Vector(5, 6, 7)` or directly with assigned statement `new Vector(() =\u003e 5 * 30 + 2)`.\n\n## Implementation details\n\n```javascript\n// typical implementation of vector in js\nconst vec = aVec.multiply(bVec).multiply(4).substract(dVec).substract(1.5);\n\n                    ⇓\n\n// better readable, but much more complicated\nconst vec = new Vec(aVec.x * bVec.x * 4 - dVec.x - 1.5,\n                    aVec.y * bVec.y * 4 - dVec.y - 1.5,\n                    aVec.z * bVec.z * 4 - dVec.z - 1.5);\n\n                    ⇓\n\n// inspired by smart array handling\n// first version of calling assigned function three times\nconst vec = oldCalc(  aVec, bVec, dVec,\n                    ( aVec, bVec, dVec) =\u003e aVec * bVec * 4 - dVec - 1.5\n                   );\n\n                    ⇓\n\n// final version with overwritten valueOf() method\nconst vec = calc(() =\u003e aVec * bVec * 4 - dVec - 1.5);\n```\n\nJavascript has this one peculiarity called `valueOf()` this method is designed for primitive handling (numbers and strings) when handling arithmetic operations.\nEvery class can overwrite this method to give it special behavior. This Vector class calls the assigned statement three times for `x`, `y` and `z`.\nComparable to trigger arithmetic operation manually for every axis.\n\nInternally the `valueOf()` implementation returns `x` in first call, `y` in second call and `z` in last call, these results are put into an new Vector object and can be reused further.\n\n## Usage\n\n### load via hmtl\n\n```html\n\u003cscript\n  type=\"text/javascript\"\n  src=\"https://unpkg.com/@js-basics/vector/build/iife\"\n\u003e\u003c/script\u003e\n```\n\n```javascript\nconst { calc, vector, victor, point, ipoint } = basics.vector;\n```\n\n### load via npm\n\n\\$ `npm i @js-basics/vector`\n\n```javascript\nimport { calc, vector, victor, point, ipoint } from \"@js-basics/vector\";\n```\n\n## working with Vector classes\n\n### create vector by numbers\n\n```javascript\nconst pos = vector(5, 6, 7);\nconst dir = vector(1, 0, 0);\nconsole.log(debug`pos:${pos}, dir: ${dir}`);\n// pos: { x: 5, y: 6, z: 7 }  dir: { x: 1, y: 0, z: 0 }\n```\n\n### create vector by calculating other vectors and number\n\n```javascript\nconst offsetA = vector(() =\u003e dir * 30 + pos);\nconsole.log(debug`offsetA: ${offsetA}`);\n// offsetA: { x: 35, y: 6, z: 7 }\n```\n\n### calculate cross product\n\n```javascript\nconst dir1 = vector(0, 1, 0);\nconst dir2 = vector(-1, 0, 1);\nconst cross = dir1.cross(dir2);\n\nconsole.log(debug`cross: ${cross}`);\n// cross: { x: 1, y: 0, z: 1 }\n```\n\n### directly normalize the cross product\n\n```javascript\nconst crossNorm = dir1.crossNormalize(dir2);\n\nconsole.log(debug`crossNorm: ${crossNorm}`);\n// crossNorm: { x: 0.7071, y: 0, z: 0.7071 }\n```\n\n### cross product handling works also with operator handling\n\n```javascript\nconst crossNormCalc = vector(() =\u003e dir1.crossNormalize(dir2) * 50);\n\nconsole.log(debug`crossNormCalc: ${crossNormCalc}`);\n// crossNormCalc: { x: 35.36, y: 0, z: 35.36 }\n```\n\n### normalize with arithmetic only\n\n```javascript\nconst norm = vector(() =\u003e offsetA / offsetA.length);\nconsole.log(debug`norm: ${norm}`);\n// norm: { x: 0.967, y: 0.1658, z: 0.1934 }\n```\n\n### mutable 3D vector called Vector\n\n```javascript\nconst v1 = vector(5, 6, 7);\n\nv1.x = 27;\nconsole.log(debug`v1: ${v1}`);\n// v1: { x: 27, y: 6, z: 7 }\n\nv1.calc(p =\u003e (p + 1) * 12);\nconsole.log(debug`v1: ${v1}`);\n// v1: { x: 336, y: 84, z: 96 }\n```\n\n### immutable 3D vector called Victor\n\nbehaves exactly like Vector but code cant change its `x`, `y` and `z` axes.\n\n```javascript\nconst v2 = victor(5, 6, 7);\n\ntry {\n  v2.x = 27;\n} catch (error) {\n  console.log(`error: ${error}`);\n  // error: Error: set x() not implemented\n}\n```\n\n### mutable 2D vector called Point\n\n```javascript\nconst p1 = point(5, 6);\n\np1.x = 27;\nconsole.log(debug`p1: ${p1}`);\n// p1: { x: 27, y: 6 }\n\np1.calc(p =\u003e (p + 1) * 12);\nconsole.log(debug`v1: ${v1}`);\n// p1: { x: 336, y: 84 }\n```\n\n### immutable 2D vector called IPoint\n\nbehaves exactly like Point but code cant change its `x` and `y` axes.\n\n```javascript\nconst p2 = ipoint(5, 6);\n\ntry {\n  p2.x = 27;\n} catch (error) {\n  console.log('error:', error.toString());\n  // error: Error: set x() not implemented\n}\n```\n\n### creating vector inside calculation\n\nworks fine thanks to caching in factory function.\n\n```javascript\n// creating vector inside calculation works fine,\n// thanks to caching in factory function\nconst inlineVec = victor(() =\u003e victor(25, 30, 0) / 2);\nconsole.log(debug`inlineVec: ${inlineVec}`);\n// inlineVec: { x: 12.5, y: 15, z: 0 }\n```\n\n### mixing 2D and 3D space\n\n```javascript\n// mix 2D and 3D space\nconst from2d = victor(() =\u003e point(25, 30) / 2);\nconst from3d = ipoint(() =\u003e from2d.xy * 2);\nconsole.log(debug`from2d: ${from2d}`);\nconsole.log(debug`from3d: ${from3d}`);\n// from2d: { x: 12.5, y: 15, z: 0 }\n// from3d: { x: 25, y: 30 }\n```\n\n## Not another vector lib\n\nYou are happy with your current vector library and definitely don’t want to change 1000 lines of code already written in your projects. Then you can only use the valueOf extension and the calc function.\n\n## working with Operator class\n\n### load via hmtl\n\n```html\n\u003cscript\n  type=\"text/javascript\"\n  src=\"https://unpkg.com/@js-basics/vector/build/iife/operator.js\"\n\u003e\u003c/script\u003e\n```\n\n```javascript\nconst { cachedValueOf, cachedFactory, operatorCalc } = basics.vector.operator;\n```\n\n### load via npm\n\n\\$ `npm i @js-basics/vector`\n\n```javascript\nimport {\n  cachedValueOf,\n  cachedFactory,\n  operatorCalc\n} from \"@js-basics/vector/operator\";\n```\n\n### override valueOf in own class\n\n```javascript\nclass Tuple {\n  constructor(x, y, z) {\n    this.x = x;\n    this.y = y;\n    this.z = z;\n  }\n}\ncachedValueOf(Tuple);\n```\n\n### write own factory function\n\n```javascript\nconst tuple = (() =\u003e {\n  const tupleFactory = cachedFactory(Tuple);\n  return (x, y, z) =\u003e {\n    if (typeof x === 'function') {\n      return operatorCalc(x, new Tuple());\n    }\n    return tupleFactory(x, y, z);\n  };\n})();\n\nconst t1 = tuple(3, 4, 5);\nconst t2 = tuple(6, 7, 8);\nconst t = tuple(() =\u003e t1 + t2 * 2);\n\nconsole.log(`t: ${JSON.stringify(t)}`);\n// t: {\"x\":15,\"y\":18,\"z\":21}\n```\n\n## Predefined adapters\n\nexisting operator overloading for game engines or other vector libraries\n\n- [playcanvas](https://github.com/basics/vector/tree/master/src/adapter)\n  ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbasics%2Fvector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbasics%2Fvector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbasics%2Fvector/lists"}