{"id":"codyduong/polybool","name":"polybool","scope":"codyduong","platform":"roblox","description":"Boolean operations on polygons (union, intersection, difference, xor)","version":"0.1.2","latest":"0.1.2","versions":["0.1.0","0.1.1","0.1.2"],"license":"0BSD","licenseRating":"safe","licenseCaveats":[],"licenseVerified":false,"dependencies":{},"integrity":"2067532efd28a1d152051f45d7a33978e263955f0ee8322504592f3cc433846e","likes":0,"downloads":0,"install":"forest install codyduong/polybool","url":"https://forest.dev/p/roblox/codyduong/polybool","files":"https://api.forest.dev/ai/package/roblox/codyduong/polybool/files","readme":"# rbxts-polybool\n\n> [!NOTE]\n> This is a port of the https://github.com/velipso/polybool specifically for the [`roblox-ts`](https://roblox-ts.com/) environment\n\nThis means it is available both as a package for those using roblox-ts or as a lua library.\n\n## Installing\n\nIf you are using roblox-ts:\n- `npm install @rbxts/polybool`\n- `yarn install @rbxts/polybool`\n- `pnpm install @rbxts/polybool`\n\nIf you are using a lua package manager:\n- `wally install codyduong/polybool`\n\nIf you want the raw files (if you are using lua you only need lua files):\n- See latest release: https://github.com/codyduong/rbxts-polybool/releases/latest\n- Or simply look in /out/\n\n## Example and Usage\n\n![Example](./docs/example.png)\n\nThe below examples will recreate this polygon\n\n<ol>\n  <li><a href=\"#using-polybool-in-roblox-ts\">Using polybool in roblox-ts</a></li>\n  <li><a href=\"#using-polybool-in-lualuau\">Using polybool in lua/luau</a></li>\n</ol>\n\n### Using polybool in roblox-ts\n\nMore documentation is available at the original repository: https://github.com/velipso/polybool\n\nIt'll look pretty similiar and can be used the exact same as any example shown if you are using `roblox-ts`.\n\n> [!IMPORTANT]\n> Please read: [Vec2 vs Vector2](#vec2-vs-vector2) before proceeding\n\nUsing the Simplified Polygonal API:\n\n```typescript\nimport polybool from '@velipso/polybool';\n\nconsole.log(polybool.intersect(\n  {\n    regions: [\n      [[50,50], [150,150], [190,50]],\n      [[130,50], [290,150], [290,50]]\n    ],\n    inverted: false\n  },\n  {\n    regions: [\n      [[110,20], [110,110], [20,20]],\n      [[130,170], [130,20], [260,20], [260,170]]\n    ],\n    inverted: false\n  }\n));\n\n// output:\n// {\n//   regions: [\n//     [[50,50], [110,50], [110,110]],\n//     [[178,80], [130,50], [130,130], [150,150]],\n//     [[178,80], [190,50], [260,50], [260,131.25]]\n//   ],\n//   inverted: false\n// }\n```\n\nUsing the Polygonal API:\n\n```typescript\nimport polybool from '@velipso/polybool';\n\nconst poly1 = {\n  regions: [\n    [[50,50], [150,150], [190,50]],\n    [[130,50], [290,150], [290,50]]\n  ],\n  inverted: false\n};\n\nconst poly2 = {\n  regions: [\n    [[110,20], [110,110], [20,20]],\n    [[130,170], [130,20], [260,20], [260,170]]\n  ],\n  inverted: false\n};\n\nconst segs1 = polybool.segments(poly1);\nconst segs2 = polybool.segments(poly2);\nconst combined = polybool.combine(segs1, segs2);\nconst segs3 = polybool.selectIntersect(combined);\nconst result = polybool.polygon(segs3);\n\nconsole.log(result);\n\n// output:\n// {\n//   regions: [\n//     [[50,50], [110,50], [110,110]],\n//     [[178,80], [130,50], [130,130], [150,150]],\n//     [[178,80], [190,50], [260,50], [260,131.25]]\n//   ],\n//   inverted: false\n// }\n```\n\nUsing the Instructional API:\n\n```typescript\nimport polybool from '@velipso/polybool';\n\nconst shape1 = polybool.shape()\n  .beginPath()\n  .moveTo(50, 50)\n  .lineTo(150, 150)\n  .lineTo(190, 50)\n  .closePath()\n  .moveTo(130, 50)\n  .lineTo(290, 150)\n  .lineTo(290, 50)\n  .closePath();\n\nconst shape2 = polybool.shape()\n  .beginPath()\n  .moveTo(110, 20)\n  .lineTo(110, 110)\n  .lineTo(20, 20)\n  .closePath()\n  .moveTo(130, 170)\n  .lineTo(130, 20)\n  .lineTo(260, 20)\n  .lineTo(260, 170)\n  .closePath();\n\nconst receiver = {\n  beginPath: () => { console.log('beginPath'); },\n  moveTo: (x: number, y: number) => { console.log('moveTo', x, y); },\n  lineTo: (x: number, y: number) => { console.log('lineTo', x, y); },\n  bezierCurveTo: (\n    cp1x: number,\n    cp1y: number,\n    cp2x: number,\n    cp2y: number,\n    x: number,\n    y: number,\n  ) => { console.log('bezierCurveTo', cp1x, cp1y, cp2x, cp2y, x, y); },\n  closePath: () => { console.log('closePath'); }\n}\n\n// start with the first shape\nshape1\n  // combine it with the second shape\n  .combine(shape2)\n  // perform the operation\n  .intersect()\n  // output results to the receiver object\n  .output(receiver);\n\n// output:\n//   beginPath\n//   moveTo 110 110\n//   lineTo 50 50\n//   lineTo 110 50\n//   lineTo 110 110\n//   closePath\n//   moveTo 150 150\n//   lineTo 178 80\n//   lineTo 130 50\n//   lineTo 130 130\n//   lineTo 150 150\n//   closePath\n//   moveTo 260 131.25\n//   lineTo 178 80\n//   lineTo 190 50\n//   lineTo 260 50\n//   lineTo 260 131.25\n//   closePath\n```\n\n### Using polybool in lua/luau\n\n> **TODO**\n>\n> Feel free to make a pull request showcasing this code similarly as the typescript section\n\n## `Vec2` vs `Vector2`\n\nThe primary concern is that the intermediary data format used by polybool for `Vec2` is `[x: number, y: number]`.\nHowever, if you are familiar with Roblox you'll know that there is a \n[`Vector2`](https://create.roblox.com/docs/reference/engine/datatypes/Vector2) datatype.\n\nFor sake of compatibility with the original library, we do not modify this intermediate format.\n\nTo this end we have provided a utility API to convert between the two\n\n#### In typescript:\n```ts\nimport polybool, { intoVec2, intoVector2, Vec2 } from \"@rbxts/polybool\";\n// or if it is confusing, you can rename them\n// import polybool, { intoVec2 as intoPolyboolVector2, intoRobloxVector2, Vec2 } from \"@rbxts/polybool\";\n\nconst vec2: Vec2 = [0.5, 0.5];\nconst vector2 = intoVector2(vec2); // Vector2 datatype from roblox\nconst vec2again = intoVec2(vector2); // back into [0.5, 0.5]\n\n```\n```ts\nconst robloxVectors: Vector2[] = [\n  new Vector2(0, 0),\n  new Vector2(0.5, 0),\n  new Vector2(0, 0.5),\n] // right triangle\nconst readyForPolybool = myVectorsFromSomewhere.map(intoVec2)\n```\n\n```ts\n// ...\nconst result = polybool.polygon(segs3);\n\nconsole.log(result);\n// output:\n// {\n//   regions: [\n//     [[50,50], [110,50], [110,110]],\n//     [[178,80], [130,50], [130,130], [150,150]],\n//     [[178,80], [190,50], [260,50], [260,131.25]]\n//   ],\n//   inverted: false\n// }\n\nconst robloxRegions = {\n  regions: result.regions.map((region) => region.map(intoVector2)),\n  inverted: result.inverted,\n}\n```\n\n#### In lua/luau:\n\n> **TODO**\n>\n> Feel free to make a pull request showcasing this code similarly as the typescript section\n\n","readmeTruncated":false}