├── docs-gen ├── .gitignore ├── src │ ├── js │ │ ├── i_shape │ │ │ ├── ishape_wasm_bg.wasm │ │ │ └── ishape_wasm_bg.wasm.d.ts │ │ ├── overlay_editor │ │ │ ├── overlay_editor_bg.wasm │ │ │ ├── web_app.js │ │ │ ├── overlay_editor_bg.wasm.d.ts │ │ │ └── overlay_editor.d.ts │ │ └── overlay │ │ │ ├── segment.js │ │ │ ├── stroke_data.js │ │ │ ├── outline_data.js │ │ │ └── stars.js │ ├── triangle │ │ ├── demo.md │ │ ├── triangle.md │ │ ├── delaunay.md │ │ ├── tessellation.md │ │ ├── triangulation.md │ │ └── performance │ │ │ ├── test_1.svg │ │ │ └── test_0.svg │ ├── overlay │ │ ├── filling_rules │ │ │ └── filling_rules.md │ │ ├── demo.md │ │ ├── overlay_rules │ │ │ ├── overlay_rules.md │ │ │ └── difference_ba.svg │ │ ├── overlay.md │ │ ├── contours │ │ │ └── contours.md │ │ ├── doc.md │ │ ├── overlay_editor.md │ │ ├── overlay_graph │ │ │ └── overlay_graph.md │ │ ├── webgpu.svg │ │ ├── outline.md │ │ ├── shapes_editor.md │ │ ├── stars_demo.md │ │ ├── extract │ │ │ └── extract_shapes.md │ │ └── stroke.md │ └── SUMMARY.md └── book.toml ├── src ├── triangle │ ├── mod.rs │ └── triangulator.rs ├── lib.rs ├── bool │ ├── mod.rs │ ├── shape_type.rs │ ├── fill_rule.rs │ ├── overlay_rule.rs │ ├── buffering.rs │ ├── overlay.rs │ └── style.rs ├── logger.rs └── data.rs ├── run_mdbook-server.sh ├── run_public_npm.sh ├── examples └── html │ ├── run_http_server.sh │ ├── ishape │ ├── ishape_wasm_bg.wasm │ ├── ishape_wasm_bg.wasm.d.ts │ └── ishape_wasm.d.ts │ └── index.html ├── docs ├── .nojekyll ├── favicon.png ├── js │ ├── i_shape │ │ ├── ishape_wasm_bg.wasm │ │ └── ishape_wasm_bg.wasm.d.ts │ ├── overlay_editor │ │ ├── overlay_editor_bg.wasm │ │ ├── web_app.js │ │ ├── overlay_editor_bg.wasm.d.ts │ │ └── overlay_editor.d.ts │ └── overlay │ │ ├── segment.js │ │ ├── stroke_data.js │ │ ├── outline_data.js │ │ └── stars.js ├── FontAwesome │ └── fonts │ │ ├── FontAwesome.ttf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 ├── fonts │ ├── open-sans-v17-all-charsets-300.woff2 │ ├── open-sans-v17-all-charsets-600.woff2 │ ├── open-sans-v17-all-charsets-700.woff2 │ ├── open-sans-v17-all-charsets-800.woff2 │ ├── open-sans-v17-all-charsets-italic.woff2 │ ├── open-sans-v17-all-charsets-300italic.woff2 │ ├── open-sans-v17-all-charsets-600italic.woff2 │ ├── open-sans-v17-all-charsets-700italic.woff2 │ ├── open-sans-v17-all-charsets-800italic.woff2 │ ├── open-sans-v17-all-charsets-regular.woff2 │ ├── source-code-pro-v11-all-charsets-500.woff2 │ ├── fonts.css │ └── SOURCE-CODE-PRO-LICENSE.txt ├── css │ └── print.css ├── ayu-highlight.css ├── highlight.css ├── favicon.svg ├── tomorrow-night.css ├── overlay │ ├── webgpu.svg │ └── overlay_rules │ │ └── difference_ba.svg ├── triangle │ └── performance │ │ ├── test_1.svg │ │ └── test_0.svg ├── toc.html └── toc.js ├── run_build-wasm.sh ├── pkg ├── ishape_wasm_bg.wasm ├── package.json ├── LICENSE ├── ishape_wasm_bg.wasm.d.ts └── README.md ├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md └── readme └── difference_ba.svg /docs-gen/.gitignore: -------------------------------------------------------------------------------- 1 | book 2 | -------------------------------------------------------------------------------- /src/triangle/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod triangulator; -------------------------------------------------------------------------------- /run_mdbook-server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd docs-gen 4 | mdbook serve --open -------------------------------------------------------------------------------- /run_public_npm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd pkg 4 | npm login 5 | npm publish -------------------------------------------------------------------------------- /examples/html/run_http_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd html 4 | python3 -m http.server -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | This file makes sure that Github Pages doesn't process mdBook's output. 2 | -------------------------------------------------------------------------------- /docs/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/favicon.png -------------------------------------------------------------------------------- /run_build-wasm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | wasm-pack build --release --target web 4 | wasm-pack pack -------------------------------------------------------------------------------- /pkg/ishape_wasm_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/pkg/ishape_wasm_bg.wasm -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | extern crate alloc; 3 | 4 | pub mod data; 5 | pub mod triangle; 6 | pub mod bool; 7 | mod logger; -------------------------------------------------------------------------------- /docs/js/i_shape/ishape_wasm_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/js/i_shape/ishape_wasm_bg.wasm -------------------------------------------------------------------------------- /docs/FontAwesome/fonts/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/FontAwesome/fonts/FontAwesome.ttf -------------------------------------------------------------------------------- /examples/html/ishape/ishape_wasm_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/examples/html/ishape/ishape_wasm_bg.wasm -------------------------------------------------------------------------------- /docs-gen/src/js/i_shape/ishape_wasm_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs-gen/src/js/i_shape/ishape_wasm_bg.wasm -------------------------------------------------------------------------------- /docs/js/overlay_editor/overlay_editor_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/js/overlay_editor/overlay_editor_bg.wasm -------------------------------------------------------------------------------- /src/bool/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod buffering; 2 | pub mod fill_rule; 3 | pub mod overlay; 4 | pub mod overlay_rule; 5 | pub mod shape_type; 6 | pub mod style; -------------------------------------------------------------------------------- /docs/FontAwesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/FontAwesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/FontAwesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/FontAwesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/FontAwesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/FontAwesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/FontAwesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/FontAwesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/fonts/open-sans-v17-all-charsets-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/fonts/open-sans-v17-all-charsets-300.woff2 -------------------------------------------------------------------------------- /docs/fonts/open-sans-v17-all-charsets-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/fonts/open-sans-v17-all-charsets-600.woff2 -------------------------------------------------------------------------------- /docs/fonts/open-sans-v17-all-charsets-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/fonts/open-sans-v17-all-charsets-700.woff2 -------------------------------------------------------------------------------- /docs/fonts/open-sans-v17-all-charsets-800.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/fonts/open-sans-v17-all-charsets-800.woff2 -------------------------------------------------------------------------------- /docs/fonts/open-sans-v17-all-charsets-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/fonts/open-sans-v17-all-charsets-italic.woff2 -------------------------------------------------------------------------------- /docs-gen/src/js/overlay_editor/overlay_editor_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs-gen/src/js/overlay_editor/overlay_editor_bg.wasm -------------------------------------------------------------------------------- /docs/fonts/open-sans-v17-all-charsets-300italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/fonts/open-sans-v17-all-charsets-300italic.woff2 -------------------------------------------------------------------------------- /docs/fonts/open-sans-v17-all-charsets-600italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/fonts/open-sans-v17-all-charsets-600italic.woff2 -------------------------------------------------------------------------------- /docs/fonts/open-sans-v17-all-charsets-700italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/fonts/open-sans-v17-all-charsets-700italic.woff2 -------------------------------------------------------------------------------- /docs/fonts/open-sans-v17-all-charsets-800italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/fonts/open-sans-v17-all-charsets-800italic.woff2 -------------------------------------------------------------------------------- /docs/fonts/open-sans-v17-all-charsets-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/fonts/open-sans-v17-all-charsets-regular.woff2 -------------------------------------------------------------------------------- /docs/fonts/source-code-pro-v11-all-charsets-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iShape-Rust/iShape-js/HEAD/docs/fonts/source-code-pro-v11-all-charsets-500.woff2 -------------------------------------------------------------------------------- /docs-gen/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Nail Sharipov"] 3 | language = "en" 4 | multilingual = false 5 | src = "src" 6 | title = "iShape" 7 | 8 | [output.html] 9 | mathjax-support = true 10 | 11 | [build] 12 | build-dir = "../docs" 13 | -------------------------------------------------------------------------------- /docs-gen/src/triangle/demo.md: -------------------------------------------------------------------------------- 1 | # Demo 2 | 3 | This section contains interactive examples that demonstrate how **iTriangle** performs triangulation and tessellation. 4 | 5 | - **[Triangulation](./triangulation.md)** – Basic polygon triangulation. 6 | - **[Tessellation](./tessellation.md)** – Subdivision of polygons into smaller. 7 | -------------------------------------------------------------------------------- /src/bool/shape_type.rs: -------------------------------------------------------------------------------- 1 | use i_triangle::i_overlay::core::overlay::ShapeType as RustShapeType; 2 | use wasm_bindgen::prelude::*; 3 | 4 | #[wasm_bindgen] 5 | pub enum ShapeType { 6 | Subject, 7 | Clip, 8 | } 9 | 10 | impl From for RustShapeType { 11 | fn from(shape_type: ShapeType) -> Self { 12 | match shape_type { 13 | ShapeType::Subject => RustShapeType::Subject, 14 | ShapeType::Clip => RustShapeType::Clip 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/logger.rs: -------------------------------------------------------------------------------- 1 | // use std::panic; 2 | // use std::sync::Once; 3 | // // use log::info; 4 | // 5 | // pub(crate) struct Logger {} 6 | // 7 | // static INIT_LOGGER: Once = Once::new(); 8 | // 9 | // impl Logger { 10 | // pub(crate) fn prepare() { 11 | // panic::set_hook(Box::new(console_error_panic_hook::hook)); 12 | // INIT_LOGGER.call_once(|| { 13 | // console_log::init_with_level(log::Level::Debug).expect("error initializing log"); 14 | // }); 15 | // } 16 | // } 17 | -------------------------------------------------------------------------------- /docs-gen/src/triangle/triangle.md: -------------------------------------------------------------------------------- 1 | # iTriangle 2 | 3 | ![Eagle triangulation](eagle.svg) 4 | 5 | 6 | ## Introduction 7 | 8 | - Easy way to get your triangulation! 9 | 10 | ## Features 11 | 12 | - Delaunay triangulation 13 | - Break into convex polygons 14 | - Support any kind of polygons 15 | - Self-Intersection Resolving 16 | 17 | ## Source Code 18 | 19 | - Swift Version: [iShape-Swift/iTriangle](https://github.com/iShape-Swift/iTriangle) 20 | - Rust Version: [iShape-Rust/iTriangle](https://github.com/iShape-Rust/iTriangle) -------------------------------------------------------------------------------- /docs-gen/src/overlay/filling_rules/filling_rules.md: -------------------------------------------------------------------------------- 1 | # Filling Rules 2 | 3 | ## Even-Odd 4 | ![Even-Odd](even-odd.svg) 5 | 6 | ## Non-Zero 7 | ![Non-Zero](non-zero.svg) 8 | 9 | ## Positive 10 | ![Positive](positive.svg) 11 | 12 | ## Negative 13 | ![Negative](negative.svg) 14 | 15 | 16 | ## Filling Rules: 17 | 18 | - **Even-Odd**: Only odd numbered sub-regions are filled 19 | - **Non-Zero**: Only non-zero sub-regions are filled 20 | - **Positive**: Only positive sub-regions are filled 21 | - **Negative**: Only negative sub-regions are filled -------------------------------------------------------------------------------- /docs-gen/src/overlay/demo.md: -------------------------------------------------------------------------------- 1 | # Demo 2 | 3 | This section showcases interactive examples built using **iOverlay**. 4 | 5 | Use the demos below to explore how the library performs boolean operations on 2D shapes in real time. 6 | 7 | - **[Stars Rotation](./stars_demo.md)** – See overlapping polygons rotate and combine. 8 | - **[Shapes Editor](./shapes_editor.md)** – Draw and modify shapes live in the browser. 9 | - **[Stroke](./stroke.md)** – Test stroke generation. 10 | - **[Outline](./outline.md)** – Test outline generation. 11 | - **[Overlay Editor](./overlay_editor.md)** – Wasm interactive editor. -------------------------------------------------------------------------------- /docs-gen/src/overlay/overlay_rules/overlay_rules.md: -------------------------------------------------------------------------------- 1 | # Overlay Rules 2 | 3 | AB 4 | 5 | ## Union, A or B 6 | Union 7 | 8 | ## Intersection, A and B 9 | Intersection 10 | 11 | ## Difference, A - B 12 | Difference 13 | 14 | ## Inverse Difference, B - A 15 | Inverse Difference 16 | 17 | ## Exclusion, A xor B 18 | Exclusion 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | 16 | # IntelliJ IDEA specific 17 | .idea/ 18 | *.iml 19 | 20 | # Visual Studio Code specific 21 | .vscode/ 22 | 23 | # macOS system files 24 | .DS_Store -------------------------------------------------------------------------------- /examples/html/ishape/ishape_wasm_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export const memory: WebAssembly.Memory; 4 | export function __wbg_overlay_free(a: number, b: number): void; 5 | export function overlay_new_with_subj_and_clip(a: number, b: number): number; 6 | export function overlay_overlay(a: number, b: number, c: number): number; 7 | export function overlay_separate_vectors(a: number, b: number): number; 8 | export function __wbindgen_malloc(a: number, b: number): number; 9 | export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number; 10 | export function __wbindgen_exn_store(a: number): void; 11 | -------------------------------------------------------------------------------- /src/bool/fill_rule.rs: -------------------------------------------------------------------------------- 1 | use i_triangle::i_overlay::core::fill_rule::FillRule as RustFillRule; 2 | use wasm_bindgen::prelude::wasm_bindgen; 3 | 4 | #[wasm_bindgen] 5 | pub enum FillRule { 6 | EvenOdd, 7 | NonZero, 8 | Positive, 9 | Negative, 10 | } 11 | 12 | impl From for RustFillRule { 13 | fn from(js_fill_rule: FillRule) -> Self { 14 | match js_fill_rule { 15 | FillRule::EvenOdd => RustFillRule::EvenOdd, 16 | FillRule::NonZero => RustFillRule::NonZero, 17 | FillRule::Positive => RustFillRule::Positive, 18 | FillRule::Negative => RustFillRule::Negative 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ishape_wasm", 3 | "type": "module", 4 | "collaborators": [ 5 | "Nail Sharipov " 6 | ], 7 | "description": "Triangulation and Boolean Operations for 2D Polygons. Supported operations: intersection, union, difference, XOR, and self-intersections for all polygon varieties.", 8 | "version": "2.3.0", 9 | "license": "MIT", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/iShape-Rust/iShape-js" 13 | }, 14 | "files": [ 15 | "ishape_wasm_bg.wasm", 16 | "ishape_wasm.js", 17 | "ishape_wasm.d.ts" 18 | ], 19 | "main": "ishape_wasm.js", 20 | "types": "ishape_wasm.d.ts", 21 | "sideEffects": [ 22 | "./snippets/*" 23 | ] 24 | } -------------------------------------------------------------------------------- /docs-gen/src/overlay/overlay.md: -------------------------------------------------------------------------------- 1 | # iOverlay 2 | 3 | ![Balloons](balloons.svg) 4 | 5 | 6 | ## Introduction 7 | 8 | - The iOverlay is a poly-bool library that supports main operations such as union, intersection, difference, xor, and self-intersection. 9 | 10 | ## Features 11 | 12 | - **Operations**: union, intersection, difference, and exclusion. 13 | - **Polygons**: with holes, self-intersections, and multiple paths. 14 | - **Simplification**: removes degenerate vertices and merges collinear edges. 15 | - **Buffering**: offsets paths and polygons. 16 | - **Fill Rules**: even-odd, non-zero, positive and negative. 17 | 18 | ## Source Code 19 | 20 | - Rust Version: [iShape-Rust/iOverlay](https://github.com/iShape-Rust/iOverlay) 21 | - JS Version: [iShape-Rust/iShape-js](https://github.com/iShape-Rust/iShape-js) -------------------------------------------------------------------------------- /docs/js/overlay_editor/web_app.js: -------------------------------------------------------------------------------- 1 | import init, {WebApp} from './overlay_editor.js'; 2 | 3 | async function run() { 4 | await init(); 5 | console.log('wasm module loaded'); 6 | 7 | const booleanData = await fetch('./../js/overlay_editor/tests/boolean_tests.json').then((res) => res.text()); 8 | const stringData = await fetch('./../js/overlay_editor/tests/string_tests.json').then((res) => res.text()); 9 | const strokeData = await fetch('./../js/overlay_editor/tests/stroke_tests.json').then((res) => res.text()); 10 | const outlineData = await fetch('./../js/overlay_editor/tests/outline_tests.json').then((res) => res.text()); 11 | console.log('json files loaded'); 12 | 13 | const app = new WebApp(); 14 | console.log('WebApp starting'); 15 | app.start(booleanData, stringData, strokeData, outlineData); 16 | console.log('WebApp started'); 17 | } 18 | 19 | run(); -------------------------------------------------------------------------------- /docs-gen/src/js/overlay_editor/web_app.js: -------------------------------------------------------------------------------- 1 | import init, {WebApp} from './overlay_editor.js'; 2 | 3 | async function run() { 4 | await init(); 5 | console.log('wasm module loaded'); 6 | 7 | const booleanData = await fetch('./../js/overlay_editor/tests/boolean_tests.json').then((res) => res.text()); 8 | const stringData = await fetch('./../js/overlay_editor/tests/string_tests.json').then((res) => res.text()); 9 | const strokeData = await fetch('./../js/overlay_editor/tests/stroke_tests.json').then((res) => res.text()); 10 | const outlineData = await fetch('./../js/overlay_editor/tests/outline_tests.json').then((res) => res.text()); 11 | console.log('json files loaded'); 12 | 13 | const app = new WebApp(); 14 | console.log('WebApp starting'); 15 | app.start(booleanData, stringData, strokeData, outlineData); 16 | console.log('WebApp started'); 17 | } 18 | 19 | run(); -------------------------------------------------------------------------------- /docs/css/print.css: -------------------------------------------------------------------------------- 1 | 2 | #sidebar, 3 | #menu-bar, 4 | .nav-chapters, 5 | .mobile-nav-chapters { 6 | display: none; 7 | } 8 | 9 | #page-wrapper.page-wrapper { 10 | transform: none !important; 11 | margin-inline-start: 0px; 12 | overflow-y: initial; 13 | } 14 | 15 | #content { 16 | max-width: none; 17 | margin: 0; 18 | padding: 0; 19 | } 20 | 21 | .page { 22 | overflow-y: initial; 23 | } 24 | 25 | code { 26 | direction: ltr !important; 27 | } 28 | 29 | pre > .buttons { 30 | z-index: 2; 31 | } 32 | 33 | a, a:visited, a:active, a:hover { 34 | color: #4183c4; 35 | text-decoration: none; 36 | } 37 | 38 | h1, h2, h3, h4, h5, h6 { 39 | page-break-inside: avoid; 40 | page-break-after: avoid; 41 | } 42 | 43 | pre, code { 44 | page-break-inside: avoid; 45 | white-space: pre-wrap; 46 | } 47 | 48 | .fa { 49 | display: none !important; 50 | } 51 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ishape_wasm" 3 | version = "2.3.0" 4 | authors = ["Nail Sharipov "] 5 | edition = "2021" 6 | description = "Triangulation and Boolean Operations for 2D Polygons. Supported operations: intersection, union, difference, XOR, and self-intersections for all polygon varieties." 7 | license = "MIT" 8 | repository = "https://github.com/iShape-Rust/iShape-js" 9 | 10 | [profile.release] 11 | opt-level = 3 12 | lto = false 13 | codegen-units = 1 14 | 15 | [lib] 16 | crate-type = ["cdylib"] 17 | 18 | [dependencies] 19 | i_triangle = { version = "~0.33", features = ["serde"] } 20 | #i_triangle = { path = "../iTriangle/iTriangle", features = ["serde"] } 21 | log = "0.4.22" 22 | console_log = "^1.0.0" 23 | console_error_panic_hook = "^0" 24 | 25 | 26 | wasm-bindgen = "^0.2" 27 | serde = { version = "^1.0", default-features = false, features = ["derive", "alloc"] } 28 | serde-wasm-bindgen = "^0.6" 29 | 30 | -------------------------------------------------------------------------------- /src/bool/overlay_rule.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | use i_triangle::i_overlay::core::overlay_rule::OverlayRule as RustOverlayRule; 3 | 4 | #[wasm_bindgen] 5 | pub enum OverlayRule { 6 | Subject, 7 | Clip, 8 | Intersect, 9 | Union, 10 | Difference, 11 | InverseDifference, 12 | Xor, 13 | } 14 | 15 | impl From for RustOverlayRule { 16 | fn from(overlay_rule: OverlayRule) -> Self { 17 | match overlay_rule { 18 | OverlayRule::Subject => RustOverlayRule::Subject, 19 | OverlayRule::Clip => RustOverlayRule::Clip, 20 | OverlayRule::Intersect => RustOverlayRule::Intersect, 21 | OverlayRule::Union => RustOverlayRule::Union, 22 | OverlayRule::Difference => RustOverlayRule::Difference, 23 | OverlayRule::InverseDifference => RustOverlayRule::InverseDifference, 24 | OverlayRule::Xor => RustOverlayRule::Xor 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /docs-gen/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | # iShape 4 | 5 | - [iOverlay](./overlay/overlay.md) 6 | - [Demo](./overlay/demo.md) 7 | - [Stars Rotation](./overlay/stars_demo.md) 8 | - [Shapes Editor](./overlay/shapes_editor.md) 9 | - [Stroke](./overlay/stroke.md) 10 | - [Outline](./overlay/outline.md) 11 | - [Overlay Editor](./overlay/overlay_editor.md) 12 | - [Performance Comparison](./overlay/performance/performance.md) 13 | - [Documentation](./overlay/doc.md) 14 | - [Filling Rules](./overlay/filling_rules/filling_rules.md) 15 | - [Overlay Rules](./overlay/overlay_rules/overlay_rules.md) 16 | - [Contours](overlay/contours/contours.md) 17 | - [Overlay Graph](overlay/overlay_graph/overlay_graph.md) 18 | - [Extract Shapes](overlay/extract/extract_shapes.md) 19 | 20 | - [iTriangle](./triangle/triangle.md) 21 | - [Demo](./triangle/demo.md) 22 | - [Triangulation](./triangle/triangulation.md) 23 | - [Tessellation](./triangle/tessellation.md) 24 | - [Performance Comparison](./triangle/performance/performance.md) 25 | - [Delaunay](./triangle/delaunay.md) -------------------------------------------------------------------------------- /docs-gen/src/overlay/contours/contours.md: -------------------------------------------------------------------------------- 1 | # Contours 2 | ## Outer and Inner 3 | ![Contour](contour.svg) 4 | In the context of the [Overlay Graph](../overlay_graph/overlay_graph.md), contours are used to represent the boundaries of geometric objects. These contours are classified into two types: **outer** contours and **inner** contours. 5 | 6 | ### Outer Contour: 7 | 8 | - An outer contour is a sequence of points ordered in a **counterclockwise** direction. 9 | - The outer contour defines the external boundary of a shape, enclosing the exterior space. 10 | 11 | ### Inner Contour (Hole or Cave): 12 | - An inner contour is a sequence of points ordered in a **clockwise** direction. 13 | - Inner contours represent enclosed areas within an outer contour, often referred to as "holes" or "caves." 14 | 15 | _Both **outer** and **inner** contours must be simple, meaning they must not self-intersect and must not share edges with other contours._ 16 | 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 iShape-Rust 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /pkg/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 iShape-Rust 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/ayu-highlight.css: -------------------------------------------------------------------------------- 1 | /* 2 | Based off of the Ayu theme 3 | Original by Dempfi (https://github.com/dempfi/ayu) 4 | */ 5 | 6 | .hljs { 7 | display: block; 8 | overflow-x: auto; 9 | background: #191f26; 10 | color: #e6e1cf; 11 | } 12 | 13 | .hljs-comment, 14 | .hljs-quote { 15 | color: #5c6773; 16 | font-style: italic; 17 | } 18 | 19 | .hljs-variable, 20 | .hljs-template-variable, 21 | .hljs-attribute, 22 | .hljs-attr, 23 | .hljs-regexp, 24 | .hljs-link, 25 | .hljs-selector-id, 26 | .hljs-selector-class { 27 | color: #ff7733; 28 | } 29 | 30 | .hljs-number, 31 | .hljs-meta, 32 | .hljs-builtin-name, 33 | .hljs-literal, 34 | .hljs-type, 35 | .hljs-params { 36 | color: #ffee99; 37 | } 38 | 39 | .hljs-string, 40 | .hljs-bullet { 41 | color: #b8cc52; 42 | } 43 | 44 | .hljs-title, 45 | .hljs-built_in, 46 | .hljs-section { 47 | color: #ffb454; 48 | } 49 | 50 | .hljs-keyword, 51 | .hljs-selector-tag, 52 | .hljs-symbol { 53 | color: #ff7733; 54 | } 55 | 56 | .hljs-name { 57 | color: #36a3d9; 58 | } 59 | 60 | .hljs-tag { 61 | color: #00568d; 62 | } 63 | 64 | .hljs-emphasis { 65 | font-style: italic; 66 | } 67 | 68 | .hljs-strong { 69 | font-weight: bold; 70 | } 71 | 72 | .hljs-addition { 73 | color: #91b362; 74 | } 75 | 76 | .hljs-deletion { 77 | color: #d96c75; 78 | } 79 | -------------------------------------------------------------------------------- /docs/js/overlay_editor/overlay_editor_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export const memory: WebAssembly.Memory; 4 | export const __wbg_webapp_free: (a: number, b: number) => void; 5 | export const webapp_create: () => number; 6 | export const webapp_start: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void; 7 | export const __externref_table_alloc: () => number; 8 | export const __wbindgen_export_1: WebAssembly.Table; 9 | export const __wbindgen_exn_store: (a: number) => void; 10 | export const __wbindgen_malloc: (a: number, b: number) => number; 11 | export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; 12 | export const __wbindgen_free: (a: number, b: number, c: number) => void; 13 | export const __wbindgen_export_6: WebAssembly.Table; 14 | export const closure797_externref_shim: (a: number, b: number, c: any) => void; 15 | export const closure802_externref_shim: (a: number, b: number, c: any, d: any) => void; 16 | export const _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h0b04ab15c83a5854: (a: number, b: number) => void; 17 | export const closure1475_externref_shim: (a: number, b: number, c: any) => void; 18 | export const __wbindgen_start: () => void; 19 | -------------------------------------------------------------------------------- /docs-gen/src/js/overlay_editor/overlay_editor_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export const memory: WebAssembly.Memory; 4 | export const __wbg_webapp_free: (a: number, b: number) => void; 5 | export const webapp_create: () => number; 6 | export const webapp_start: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void; 7 | export const __externref_table_alloc: () => number; 8 | export const __wbindgen_export_1: WebAssembly.Table; 9 | export const __wbindgen_exn_store: (a: number) => void; 10 | export const __wbindgen_malloc: (a: number, b: number) => number; 11 | export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; 12 | export const __wbindgen_free: (a: number, b: number, c: number) => void; 13 | export const __wbindgen_export_6: WebAssembly.Table; 14 | export const closure797_externref_shim: (a: number, b: number, c: any) => void; 15 | export const closure802_externref_shim: (a: number, b: number, c: any, d: any) => void; 16 | export const _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h0b04ab15c83a5854: (a: number, b: number) => void; 17 | export const closure1475_externref_shim: (a: number, b: number, c: any) => void; 18 | export const __wbindgen_start: () => void; 19 | -------------------------------------------------------------------------------- /docs/highlight.css: -------------------------------------------------------------------------------- 1 | /* 2 | * An increased contrast highlighting scheme loosely based on the 3 | * "Base16 Atelier Dune Light" theme by Bram de Haan 4 | * (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) 5 | * Original Base16 color scheme by Chris Kempson 6 | * (https://github.com/chriskempson/base16) 7 | */ 8 | 9 | /* Comment */ 10 | .hljs-comment, 11 | .hljs-quote { 12 | color: #575757; 13 | } 14 | 15 | /* Red */ 16 | .hljs-variable, 17 | .hljs-template-variable, 18 | .hljs-attribute, 19 | .hljs-attr, 20 | .hljs-tag, 21 | .hljs-name, 22 | .hljs-regexp, 23 | .hljs-link, 24 | .hljs-name, 25 | .hljs-selector-id, 26 | .hljs-selector-class { 27 | color: #d70025; 28 | } 29 | 30 | /* Orange */ 31 | .hljs-number, 32 | .hljs-meta, 33 | .hljs-built_in, 34 | .hljs-builtin-name, 35 | .hljs-literal, 36 | .hljs-type, 37 | .hljs-params { 38 | color: #b21e00; 39 | } 40 | 41 | /* Green */ 42 | .hljs-string, 43 | .hljs-symbol, 44 | .hljs-bullet { 45 | color: #008200; 46 | } 47 | 48 | /* Blue */ 49 | .hljs-title, 50 | .hljs-section { 51 | color: #0030f2; 52 | } 53 | 54 | /* Purple */ 55 | .hljs-keyword, 56 | .hljs-selector-tag { 57 | color: #9d00ec; 58 | } 59 | 60 | .hljs { 61 | display: block; 62 | overflow-x: auto; 63 | background: #f6f7f6; 64 | color: #000; 65 | } 66 | 67 | .hljs-emphasis { 68 | font-style: italic; 69 | } 70 | 71 | .hljs-strong { 72 | font-weight: bold; 73 | } 74 | 75 | .hljs-addition { 76 | color: #22863a; 77 | background-color: #f0fff4; 78 | } 79 | 80 | .hljs-deletion { 81 | color: #b31d28; 82 | background-color: #ffeef0; 83 | } 84 | -------------------------------------------------------------------------------- /docs/js/overlay/segment.js: -------------------------------------------------------------------------------- 1 | function normalize(vector) { 2 | const magnitude = Math.sqrt(vector.x ** 2 + vector.y ** 2); 3 | return { x: vector.x / magnitude, y: vector.y / magnitude }; 4 | } 5 | 6 | function sub(vectorA, vectorB) { 7 | return { x: vectorA.x - vectorB.x, y: vectorA.y - vectorB.y }; 8 | } 9 | 10 | function add(vectorA, vectorB) { 11 | return { x: vectorA.x + vectorB.x, y: vectorA.y + vectorB.y }; 12 | } 13 | 14 | function mul(vector, scalar) { 15 | return { x: vector.x * scalar, y: vector.y * scalar }; 16 | } 17 | 18 | export class Segment { 19 | constructor(link) { 20 | this.start = { x: link.ax, y: link.ay }; 21 | this.end = { x: link.bx, y: link.by }; 22 | } 23 | 24 | get subjTopPos() { 25 | const n = normalize(sub(this.start, this.end)); 26 | const o = { x: n.y, y: -n.x }; 27 | return add( 28 | mul(add(this.start, this.end), 0.5), 29 | add(mul(o, 6), mul(n, 4)) 30 | ); 31 | } 32 | 33 | get subjBottomPos() { 34 | const n = normalize(sub(this.start, this.end)); 35 | const o = { x: -n.y, y: n.x }; 36 | return add( 37 | mul(add(this.start, this.end), 0.5), 38 | add(mul(o, 6), mul(n, 4)) 39 | ); 40 | } 41 | 42 | get clipTopPos() { 43 | const n = normalize(sub(this.start, this.end)); 44 | const o = { x: n.y, y: -n.x }; 45 | return add( 46 | mul(add(this.start, this.end), 0.5), 47 | add(mul(o, 6), mul(n, -4)) 48 | ); 49 | } 50 | 51 | get clipBottomPos() { 52 | const n = normalize(sub(this.start, this.end)); 53 | const o = { x: -n.y, y: n.x }; 54 | return add( 55 | mul(add(this.start, this.end), 0.5), 56 | add(mul(o, 6), mul(n, -4)) 57 | ); 58 | } 59 | } -------------------------------------------------------------------------------- /docs/js/overlay/stroke_data.js: -------------------------------------------------------------------------------- 1 | const a = 0.2 * Math.PI; 2 | const a0 = 0.5 * a + Math.PI; 3 | const r = 200; 4 | export const tests = [ 5 | { 6 | name: "M", 7 | paths: [ 8 | [[200, 450], [300, 200], [400, 450], [500, 200], [600, 450]] 9 | ] 10 | }, 11 | { 12 | name: "Snake", 13 | paths: [ 14 | [[200, 200], [600, 200], [600, 300], [200, 300], [200, 400], [600, 400], [600, 500], [200, 500], [200, 600], [600, 600]] 15 | ] 16 | }, 17 | { 18 | name: "PlugIn", 19 | paths: [ 20 | [ 21 | [300, 200], [100, 200], [100, 400], [300, 400] 22 | ], 23 | [ 24 | [200, 300], [400, 300], [400, 500], [600, 500] 25 | ], 26 | [ 27 | [500, 400], [700, 400], [700, 600], [500, 600] 28 | ] 29 | ] 30 | }, 31 | { 32 | name: "Tetris", 33 | paths: [ 34 | [[250, 300], [350, 300], [350, 400], [450, 400]], 35 | [[250, 400], [250, 500], [450, 500]], 36 | [[450, 300], [550, 300], [550, 500]], 37 | ] 38 | }, 39 | { 40 | name: "Star", 41 | paths: [ 42 | [ 43 | [400 + r * Math.cos(14 * a + a0), 400 + r * Math.sin(14 * a + a0)], 44 | [400 + r * Math.cos(18 * a + a0), 400 + r * Math.sin(18 * a + a0)], 45 | [400 + r * Math.cos(2 * a + a0), 400 + r * Math.sin(2 * a + a0)], 46 | [400 + r * Math.cos(6 * a + a0), 400 + r * Math.sin(6 * a + a0)], 47 | [400 + r * Math.cos(10 * a + a0), 400 + r * Math.sin(10 * a + a0)] 48 | ] 49 | ] 50 | } 51 | ] -------------------------------------------------------------------------------- /docs-gen/src/js/overlay/segment.js: -------------------------------------------------------------------------------- 1 | function normalize(vector) { 2 | const magnitude = Math.sqrt(vector.x ** 2 + vector.y ** 2); 3 | return { x: vector.x / magnitude, y: vector.y / magnitude }; 4 | } 5 | 6 | function sub(vectorA, vectorB) { 7 | return { x: vectorA.x - vectorB.x, y: vectorA.y - vectorB.y }; 8 | } 9 | 10 | function add(vectorA, vectorB) { 11 | return { x: vectorA.x + vectorB.x, y: vectorA.y + vectorB.y }; 12 | } 13 | 14 | function mul(vector, scalar) { 15 | return { x: vector.x * scalar, y: vector.y * scalar }; 16 | } 17 | 18 | export class Segment { 19 | constructor(link) { 20 | this.start = { x: link.ax, y: link.ay }; 21 | this.end = { x: link.bx, y: link.by }; 22 | } 23 | 24 | get subjTopPos() { 25 | const n = normalize(sub(this.start, this.end)); 26 | const o = { x: n.y, y: -n.x }; 27 | return add( 28 | mul(add(this.start, this.end), 0.5), 29 | add(mul(o, 6), mul(n, 4)) 30 | ); 31 | } 32 | 33 | get subjBottomPos() { 34 | const n = normalize(sub(this.start, this.end)); 35 | const o = { x: -n.y, y: n.x }; 36 | return add( 37 | mul(add(this.start, this.end), 0.5), 38 | add(mul(o, 6), mul(n, 4)) 39 | ); 40 | } 41 | 42 | get clipTopPos() { 43 | const n = normalize(sub(this.start, this.end)); 44 | const o = { x: n.y, y: -n.x }; 45 | return add( 46 | mul(add(this.start, this.end), 0.5), 47 | add(mul(o, 6), mul(n, -4)) 48 | ); 49 | } 50 | 51 | get clipBottomPos() { 52 | const n = normalize(sub(this.start, this.end)); 53 | const o = { x: -n.y, y: n.x }; 54 | return add( 55 | mul(add(this.start, this.end), 0.5), 56 | add(mul(o, 6), mul(n, -4)) 57 | ); 58 | } 59 | } -------------------------------------------------------------------------------- /docs-gen/src/js/overlay/stroke_data.js: -------------------------------------------------------------------------------- 1 | const a = 0.2 * Math.PI; 2 | const a0 = 0.5 * a + Math.PI; 3 | const r = 200; 4 | export const tests = [ 5 | { 6 | name: "M", 7 | paths: [ 8 | [[200, 450], [300, 200], [400, 450], [500, 200], [600, 450]] 9 | ] 10 | }, 11 | { 12 | name: "Snake", 13 | paths: [ 14 | [[200, 200], [600, 200], [600, 300], [200, 300], [200, 400], [600, 400], [600, 500], [200, 500], [200, 600], [600, 600]] 15 | ] 16 | }, 17 | { 18 | name: "PlugIn", 19 | paths: [ 20 | [ 21 | [300, 200], [100, 200], [100, 400], [300, 400] 22 | ], 23 | [ 24 | [200, 300], [400, 300], [400, 500], [600, 500] 25 | ], 26 | [ 27 | [500, 400], [700, 400], [700, 600], [500, 600] 28 | ] 29 | ] 30 | }, 31 | { 32 | name: "Tetris", 33 | paths: [ 34 | [[250, 300], [350, 300], [350, 400], [450, 400]], 35 | [[250, 400], [250, 500], [450, 500]], 36 | [[450, 300], [550, 300], [550, 500]], 37 | ] 38 | }, 39 | { 40 | name: "Star", 41 | paths: [ 42 | [ 43 | [400 + r * Math.cos(14 * a + a0), 400 + r * Math.sin(14 * a + a0)], 44 | [400 + r * Math.cos(18 * a + a0), 400 + r * Math.sin(18 * a + a0)], 45 | [400 + r * Math.cos(2 * a + a0), 400 + r * Math.sin(2 * a + a0)], 46 | [400 + r * Math.cos(6 * a + a0), 400 + r * Math.sin(6 * a + a0)], 47 | [400 + r * Math.cos(10 * a + a0), 400 + r * Math.sin(10 * a + a0)] 48 | ] 49 | ] 50 | } 51 | ] -------------------------------------------------------------------------------- /docs/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/bool/buffering.rs: -------------------------------------------------------------------------------- 1 | use crate::data::NestedData; 2 | use crate::bool::style::{OutlineStyle, StrokeStyle}; 3 | use i_triangle::i_overlay::mesh::outline::offset::OutlineOffset; 4 | use i_triangle::i_overlay::mesh::stroke::offset::StrokeOffset; 5 | use wasm_bindgen::prelude::wasm_bindgen; 6 | use wasm_bindgen::JsValue; 7 | 8 | #[wasm_bindgen] 9 | pub struct StrokeBuilder { 10 | pub style: StrokeStyle, 11 | } 12 | 13 | #[wasm_bindgen] 14 | pub struct OutlineBuilder { 15 | pub style: OutlineStyle, 16 | } 17 | 18 | #[wasm_bindgen] 19 | impl StrokeBuilder { 20 | #[wasm_bindgen] 21 | pub fn with_style(style: StrokeStyle) -> StrokeBuilder { 22 | StrokeBuilder { style } 23 | } 24 | 25 | #[wasm_bindgen] 26 | pub fn build(&self, path_js: JsValue, is_closed_path: bool) -> JsValue { 27 | let style = self.style.rust_style(); 28 | 29 | let path_data = NestedData::with_json(path_js).unwrap(); 30 | let shapes = match path_data { 31 | NestedData::Contour(contour) => contour.stroke(style, is_closed_path), 32 | NestedData::Shape(shape) => shape.stroke(style, is_closed_path), 33 | NestedData::Shapes(shapes) => shapes.stroke(style, is_closed_path), 34 | }; 35 | 36 | serde_wasm_bindgen::to_value(&shapes).unwrap() 37 | } 38 | } 39 | 40 | #[wasm_bindgen] 41 | impl OutlineBuilder { 42 | #[wasm_bindgen] 43 | pub fn with_style(style: OutlineStyle) -> OutlineBuilder { 44 | OutlineBuilder { style } 45 | } 46 | 47 | #[wasm_bindgen] 48 | pub fn build(&self, path_js: JsValue) -> JsValue { 49 | let style = self.style.rust_style(); 50 | 51 | let path_data = NestedData::with_json(path_js).unwrap(); 52 | let shapes = match path_data { 53 | NestedData::Contour(contour) => contour.outline(&style), 54 | NestedData::Shape(shape) => shape.outline(&style), 55 | NestedData::Shapes(shapes) => shapes.outline(&style), 56 | }; 57 | 58 | serde_wasm_bindgen::to_value(&shapes).unwrap() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /examples/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | iShape 7 | 23 | 44 | 45 | 46 | 47 | 48 | 49 |

50 | 
51 | 
52 | 


--------------------------------------------------------------------------------
/docs/tomorrow-night.css:
--------------------------------------------------------------------------------
  1 | /* Tomorrow Night Theme */
  2 | /* https://github.com/jmblog/color-themes-for-highlightjs */
  3 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */
  4 | /* https://github.com/jmblog/color-themes-for-highlightjs */
  5 | 
  6 | /* Tomorrow Comment */
  7 | .hljs-comment {
  8 |   color: #969896;
  9 | }
 10 | 
 11 | /* Tomorrow Red */
 12 | .hljs-variable,
 13 | .hljs-attribute,
 14 | .hljs-attr,
 15 | .hljs-tag,
 16 | .hljs-regexp,
 17 | .ruby .hljs-constant,
 18 | .xml .hljs-tag .hljs-title,
 19 | .xml .hljs-pi,
 20 | .xml .hljs-doctype,
 21 | .html .hljs-doctype,
 22 | .css .hljs-id,
 23 | .css .hljs-class,
 24 | .css .hljs-pseudo {
 25 |   color: #cc6666;
 26 | }
 27 | 
 28 | /* Tomorrow Orange */
 29 | .hljs-number,
 30 | .hljs-preprocessor,
 31 | .hljs-pragma,
 32 | .hljs-built_in,
 33 | .hljs-literal,
 34 | .hljs-params,
 35 | .hljs-constant {
 36 |   color: #de935f;
 37 | }
 38 | 
 39 | /* Tomorrow Yellow */
 40 | .ruby .hljs-class .hljs-title,
 41 | .css .hljs-rule .hljs-attribute {
 42 |   color: #f0c674;
 43 | }
 44 | 
 45 | /* Tomorrow Green */
 46 | .hljs-string,
 47 | .hljs-value,
 48 | .hljs-inheritance,
 49 | .hljs-header,
 50 | .hljs-name,
 51 | .ruby .hljs-symbol,
 52 | .xml .hljs-cdata {
 53 |   color: #b5bd68;
 54 | }
 55 | 
 56 | /* Tomorrow Aqua */
 57 | .hljs-title,
 58 | .hljs-section,
 59 | .css .hljs-hexcolor {
 60 |   color: #8abeb7;
 61 | }
 62 | 
 63 | /* Tomorrow Blue */
 64 | .hljs-function,
 65 | .python .hljs-decorator,
 66 | .python .hljs-title,
 67 | .ruby .hljs-function .hljs-title,
 68 | .ruby .hljs-title .hljs-keyword,
 69 | .perl .hljs-sub,
 70 | .javascript .hljs-title,
 71 | .coffeescript .hljs-title {
 72 |   color: #81a2be;
 73 | }
 74 | 
 75 | /* Tomorrow Purple */
 76 | .hljs-keyword,
 77 | .javascript .hljs-function {
 78 |   color: #b294bb;
 79 | }
 80 | 
 81 | .hljs {
 82 |   display: block;
 83 |   overflow-x: auto;
 84 |   background: #1d1f21;
 85 |   color: #c5c8c6;
 86 | }
 87 | 
 88 | .coffeescript .javascript,
 89 | .javascript .xml,
 90 | .tex .hljs-formula,
 91 | .xml .javascript,
 92 | .xml .vbscript,
 93 | .xml .css,
 94 | .xml .hljs-cdata {
 95 |   opacity: 0.5;
 96 | }
 97 | 
 98 | .hljs-addition {
 99 |   color: #718c00;
100 | }
101 | 
102 | .hljs-deletion {
103 |   color: #c82829;
104 | }
105 | 


--------------------------------------------------------------------------------
/docs/js/overlay/outline_data.js:
--------------------------------------------------------------------------------
 1 | export const tests = [
 2 |     {
 3 |         name: "Square",
 4 |         shapes: [
 5 |             [
 6 |                 [[300.0, 300.0], [500.0, 300.0], [500.0, 500.0],[300.0, 500.0]]
 7 |             ]
 8 |         ]
 9 |     },
10 |     {
11 |         name: "Window",
12 |         shapes: [
13 |             [
14 |                 [[200, 200], [600, 200], [600, 600], [200, 600]],
15 |                 [[300, 300], [300, 500], [500, 500], [500, 300]]
16 |             ]
17 |         ]
18 |     },
19 |     {
20 |         name: "Squares",
21 |         shapes: [
22 |             [[[100, 100], [200, 100], [200, 200], [100, 200]]],
23 |             [[[350, 100], [450, 100], [450, 200], [350, 200]]],
24 |             [[[600, 100], [700, 100], [700, 200], [600, 200]]],
25 |             [[[225, 350], [325, 350], [325, 450], [225, 450]]],
26 |             [[[475, 350], [575, 350], [575, 450], [475, 450]]],
27 |             [[[100, 600], [200, 600], [200, 700], [100, 700]]],
28 |             [[[350, 600], [450, 600], [450, 700], [350, 700]]],
29 |             [[[600, 600], [700, 600], [700, 700], [600, 700]]]
30 |         ]
31 |     },
32 |     {
33 |         name: "Fortress",
34 |         shapes: [
35 |             [
36 |                 [[300, 100], [300, 200], [500, 200], [500, 100], [700, 100], [700, 300], [600, 300], [600, 500], [700, 500], [700, 700], [500, 700], [500, 600], [300, 600], [300, 700], [100, 700], [100, 500], [200, 500], [200, 300], [100, 300], [100, 100]],
37 |                 [[300, 300], [300, 500], [500, 500], [500, 300]]
38 |             ]
39 |         ]
40 |     },
41 |     {
42 |         name: "Butterfly",
43 |         shapes: [
44 |             [
45 |                 [[300, 100], [400, 200], [500, 100], [700, 100], [700, 300], [600, 400], [700, 500], [700, 700], [500, 700], [400, 600], [300, 700], [100, 700], [100, 500], [200, 400], [100, 300], [100, 100]],
46 |                 [[300, 400], [400, 500], [500, 400], [400, 300]],
47 |                 [[200, 200], [200, 300], [300, 300], [300, 200]],
48 |                 [[500, 200], [500, 300], [600, 300], [600, 200]],
49 |                 [[200, 500], [200, 600], [300, 600], [300, 500]],
50 |                 [[500, 500], [500, 600], [600, 600], [600, 500]]
51 |             ]
52 |         ]
53 |     },
54 | ]


--------------------------------------------------------------------------------
/docs-gen/src/js/overlay/outline_data.js:
--------------------------------------------------------------------------------
 1 | export const tests = [
 2 |     {
 3 |         name: "Square",
 4 |         shapes: [
 5 |             [
 6 |                 [[300.0, 300.0], [500.0, 300.0], [500.0, 500.0],[300.0, 500.0]]
 7 |             ]
 8 |         ]
 9 |     },
10 |     {
11 |         name: "Window",
12 |         shapes: [
13 |             [
14 |                 [[200, 200], [600, 200], [600, 600], [200, 600]],
15 |                 [[300, 300], [300, 500], [500, 500], [500, 300]]
16 |             ]
17 |         ]
18 |     },
19 |     {
20 |         name: "Squares",
21 |         shapes: [
22 |             [[[100, 100], [200, 100], [200, 200], [100, 200]]],
23 |             [[[350, 100], [450, 100], [450, 200], [350, 200]]],
24 |             [[[600, 100], [700, 100], [700, 200], [600, 200]]],
25 |             [[[225, 350], [325, 350], [325, 450], [225, 450]]],
26 |             [[[475, 350], [575, 350], [575, 450], [475, 450]]],
27 |             [[[100, 600], [200, 600], [200, 700], [100, 700]]],
28 |             [[[350, 600], [450, 600], [450, 700], [350, 700]]],
29 |             [[[600, 600], [700, 600], [700, 700], [600, 700]]]
30 |         ]
31 |     },
32 |     {
33 |         name: "Fortress",
34 |         shapes: [
35 |             [
36 |                 [[300, 100], [300, 200], [500, 200], [500, 100], [700, 100], [700, 300], [600, 300], [600, 500], [700, 500], [700, 700], [500, 700], [500, 600], [300, 600], [300, 700], [100, 700], [100, 500], [200, 500], [200, 300], [100, 300], [100, 100]],
37 |                 [[300, 300], [300, 500], [500, 500], [500, 300]]
38 |             ]
39 |         ]
40 |     },
41 |     {
42 |         name: "Butterfly",
43 |         shapes: [
44 |             [
45 |                 [[300, 100], [400, 200], [500, 100], [700, 100], [700, 300], [600, 400], [700, 500], [700, 700], [500, 700], [400, 600], [300, 700], [100, 700], [100, 500], [200, 400], [100, 300], [100, 100]],
46 |                 [[300, 400], [400, 500], [500, 400], [400, 300]],
47 |                 [[200, 200], [200, 300], [300, 300], [300, 200]],
48 |                 [[500, 200], [500, 300], [600, 300], [600, 200]],
49 |                 [[200, 500], [200, 600], [300, 600], [300, 500]],
50 |                 [[500, 500], [500, 600], [600, 600], [600, 500]]
51 |             ]
52 |         ]
53 |     },
54 | ]


--------------------------------------------------------------------------------
/src/data.rs:
--------------------------------------------------------------------------------
 1 | use alloc::vec::Vec;
 2 | use i_triangle::i_overlay::i_float::adapter::FloatPointAdapter;
 3 | use i_triangle::i_overlay::vector::edge::VectorEdge;
 4 | use core::fmt;
 5 | use wasm_bindgen::JsValue;
 6 | 
 7 | pub type ShapesData = Vec;
 8 | pub type ShapeData = Vec;
 9 | pub type ContourData = Vec<[f64; 2]>;
10 | 
11 | #[derive(serde::Deserialize)]
12 | #[serde(untagged)]
13 | pub(super) enum NestedData {
14 |     Contour(ContourData),
15 |     Shape(ShapeData),
16 |     Shapes(ShapesData),
17 | }
18 | 
19 | impl NestedData {
20 |     pub(super) fn with_json(js_value: JsValue) -> Option {
21 |         let nested_data: Result = serde_wasm_bindgen::from_value(js_value);
22 |         if let Ok(data) = nested_data {
23 |             Some(data)
24 |         } else {
25 |             None
26 |         }
27 |     }
28 | }
29 | 
30 | #[derive(serde::Serialize, serde::Deserialize)]
31 | pub struct VectorData {
32 |     pub ax: f64,
33 |     pub ay: f64,
34 |     pub bx: f64,
35 |     pub by: f64,
36 |     pub fill: u8,
37 | }
38 | 
39 | #[derive(serde::Serialize, serde::Deserialize)]
40 | pub struct VectorsData {
41 |     pub vectors: Vec,
42 | }
43 | 
44 | impl VectorsData {
45 |     pub(super) fn create(
46 |         vectors: Vec,
47 |         adapter: &FloatPointAdapter<[f64; 2], f64>,
48 |     ) -> Self {
49 |         let mut list = Vec::with_capacity(vectors.len());
50 |         for vector in vectors.into_iter() {
51 |             let a = adapter.int_to_float(&vector.a);
52 |             let b = adapter.int_to_float(&vector.b);
53 |             let fill = vector.fill;
54 | 
55 |             list.push(VectorData {
56 |                 ax: a[0],
57 |                 ay: a[1],
58 |                 bx: b[0],
59 |                 by: b[1],
60 |                 fill,
61 |             });
62 |         }
63 |         Self { vectors: list }
64 |     }
65 | }
66 | 
67 | impl fmt::Display for NestedData {
68 |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69 |         match self {
70 |             NestedData::Contour(data) => write!(f, "Contour: {:?}]", data),
71 |             NestedData::Shape(data) => write!(f, "Shape: {:?}]", data),
72 |             NestedData::Shapes(data) => write!(f, "Shapes: {:?}]", data),
73 |         }
74 |     }
75 | }
76 | 


--------------------------------------------------------------------------------
/docs-gen/src/overlay/doc.md:
--------------------------------------------------------------------------------
 1 | # Documentation
 2 | 
 3 | ---
 4 | 
 5 | ## Filling Rules
 6 | 
 7 | Filling rules determine how the interior of a shape is defined. iOverlay supports 4 filling rules:
 8 | 
 9 | - **Even-Odd**: A point is inside the shape if a ray drawn from the point crosses the shape's edges an odd number of times.
10 | - **Non-Zero**: A point is inside the shape if the total winding number around the point is non-zero.
11 | - **Positive**: Only regions with a positive winding number are considered inside.
12 | - **Negative**: Only regions with a negative winding number are considered inside.
13 | 
14 | ---
15 | 
16 | ## Overlay Rules
17 | 
18 | Overlay rules define how two shapes interact during Boolean operations:
19 | 
20 | - **Union (A ∪ B)**: Combines the areas of both shapes.
21 | - **Intersection (A ∩ B)**: Retains only the overlapping area of both shapes.
22 | - **Difference (A - B)**: Subtracts the area of shape B from shape A.
23 | - **Exclusion (A ⊕ B)**: Combines the areas of both shapes but excludes the overlapping region.
24 | 
25 | ---
26 | 
27 | ## Contours
28 | 
29 | Contours represent the boundaries of shapes and are categorized as:
30 | 
31 | - **Outer Contours**: Define the external boundary of a shape, ordered in a counterclockwise direction.
32 | - **Inner Contours (Holes)**: Define holes within a shape, ordered in a clockwise direction.
33 | 
34 | ---
35 | 
36 | ## Overlay Graph
37 | 
38 | The overlay graph is a data structure that represents the intersections and overlays of two geometric objects. It is constructed by dividing all segments of the object contours into non-intersecting parts, where segments can only touch at their endpoints. Each segment in the graph contains information about its association with the original shapes, facilitating efficient Boolean operations.
39 | 
40 | ---
41 | 
42 | ## Extract Shapes
43 | 
44 | After applying Boolean operations, the resulting shapes are extracted through a series of steps:
45 | 
46 | 1. **Build Contour**: Starting from the leftmost node, the algorithm traverses connected segments to form contours, marking each segment as visited to prevent duplication.
47 | 2. **Define Contour**: Determines whether a contour is outer or inner based on its orientation and position.
48 | 3. **Matching Contours**: Associates inner contours with their corresponding outer contours by analyzing spatial relationships.
49 | 
50 | ---


--------------------------------------------------------------------------------
/docs-gen/src/overlay/overlay_editor.md:
--------------------------------------------------------------------------------
 1 | 
45 | 
46 | 
47 |

Overlay Editor

48 |
49 |

Your browser does not support WebGPU.

50 |

Please use a WebGPU-supported browser, such as the latest version of Chrome.

51 | WebGPU not supported 52 |
53 | 54 |
55 | 56 | 94 | -------------------------------------------------------------------------------- /docs/js/overlay_editor/overlay_editor.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export class WebApp { 4 | free(): void; 5 | constructor(); 6 | start(boolean_data: string, string_data: string, stroke_data: string, outline_data: string): void; 7 | } 8 | 9 | export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; 10 | 11 | export interface InitOutput { 12 | readonly memory: WebAssembly.Memory; 13 | readonly __wbg_webapp_free: (a: number, b: number) => void; 14 | readonly webapp_create: () => number; 15 | readonly webapp_start: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void; 16 | readonly __externref_table_alloc: () => number; 17 | readonly __wbindgen_export_1: WebAssembly.Table; 18 | readonly __wbindgen_exn_store: (a: number) => void; 19 | readonly __wbindgen_malloc: (a: number, b: number) => number; 20 | readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; 21 | readonly __wbindgen_free: (a: number, b: number, c: number) => void; 22 | readonly __wbindgen_export_6: WebAssembly.Table; 23 | readonly closure797_externref_shim: (a: number, b: number, c: any) => void; 24 | readonly closure802_externref_shim: (a: number, b: number, c: any, d: any) => void; 25 | readonly _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h0b04ab15c83a5854: (a: number, b: number) => void; 26 | readonly closure1475_externref_shim: (a: number, b: number, c: any) => void; 27 | readonly __wbindgen_start: () => void; 28 | } 29 | 30 | export type SyncInitInput = BufferSource | WebAssembly.Module; 31 | /** 32 | * Instantiates the given `module`, which can either be bytes or 33 | * a precompiled `WebAssembly.Module`. 34 | * 35 | * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated. 36 | * 37 | * @returns {InitOutput} 38 | */ 39 | export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput; 40 | 41 | /** 42 | * If `module_or_path` is {RequestInfo} or {URL}, makes a request and 43 | * for everything else, calls `WebAssembly.instantiate` directly. 44 | * 45 | * @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated. 46 | * 47 | * @returns {Promise} 48 | */ 49 | export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; 50 | -------------------------------------------------------------------------------- /docs-gen/src/js/overlay_editor/overlay_editor.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export class WebApp { 4 | free(): void; 5 | constructor(); 6 | start(boolean_data: string, string_data: string, stroke_data: string, outline_data: string): void; 7 | } 8 | 9 | export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; 10 | 11 | export interface InitOutput { 12 | readonly memory: WebAssembly.Memory; 13 | readonly __wbg_webapp_free: (a: number, b: number) => void; 14 | readonly webapp_create: () => number; 15 | readonly webapp_start: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void; 16 | readonly __externref_table_alloc: () => number; 17 | readonly __wbindgen_export_1: WebAssembly.Table; 18 | readonly __wbindgen_exn_store: (a: number) => void; 19 | readonly __wbindgen_malloc: (a: number, b: number) => number; 20 | readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; 21 | readonly __wbindgen_free: (a: number, b: number, c: number) => void; 22 | readonly __wbindgen_export_6: WebAssembly.Table; 23 | readonly closure797_externref_shim: (a: number, b: number, c: any) => void; 24 | readonly closure802_externref_shim: (a: number, b: number, c: any, d: any) => void; 25 | readonly _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h0b04ab15c83a5854: (a: number, b: number) => void; 26 | readonly closure1475_externref_shim: (a: number, b: number, c: any) => void; 27 | readonly __wbindgen_start: () => void; 28 | } 29 | 30 | export type SyncInitInput = BufferSource | WebAssembly.Module; 31 | /** 32 | * Instantiates the given `module`, which can either be bytes or 33 | * a precompiled `WebAssembly.Module`. 34 | * 35 | * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated. 36 | * 37 | * @returns {InitOutput} 38 | */ 39 | export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput; 40 | 41 | /** 42 | * If `module_or_path` is {RequestInfo} or {URL}, makes a request and 43 | * for everything else, calls `WebAssembly.instantiate` directly. 44 | * 45 | * @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated. 46 | * 47 | * @returns {Promise} 48 | */ 49 | export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; 50 | -------------------------------------------------------------------------------- /examples/html/ishape/ishape_wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | */ 5 | export enum ShapeType { 6 | Subject = 0, 7 | Clip = 1, 8 | } 9 | /** 10 | */ 11 | export enum OverlayRule { 12 | Subject = 0, 13 | Clip = 1, 14 | Intersect = 2, 15 | Union = 3, 16 | Difference = 4, 17 | InverseDifference = 5, 18 | Xor = 6, 19 | } 20 | /** 21 | */ 22 | export enum FillRule { 23 | EvenOdd = 0, 24 | NonZero = 1, 25 | Positive = 2, 26 | Negative = 3, 27 | } 28 | /** 29 | */ 30 | export class Overlay { 31 | free(): void; 32 | /** 33 | * @param {any} subj_js 34 | * @param {any} clip_js 35 | * @returns {Overlay | undefined} 36 | */ 37 | static new_with_subj_and_clip(subj_js: any, clip_js: any): Overlay | undefined; 38 | /** 39 | * @param {OverlayRule} overlay_rule 40 | * @param {FillRule} fill_rule 41 | * @returns {any} 42 | */ 43 | overlay(overlay_rule: OverlayRule, fill_rule: FillRule): any; 44 | /** 45 | * @param {FillRule} fill_rule 46 | * @returns {any} 47 | */ 48 | separate_vectors(fill_rule: FillRule): any; 49 | } 50 | 51 | export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; 52 | 53 | export interface InitOutput { 54 | readonly memory: WebAssembly.Memory; 55 | readonly __wbg_overlay_free: (a: number, b: number) => void; 56 | readonly overlay_new_with_subj_and_clip: (a: number, b: number) => number; 57 | readonly overlay_overlay: (a: number, b: number, c: number) => number; 58 | readonly overlay_separate_vectors: (a: number, b: number) => number; 59 | readonly __wbindgen_malloc: (a: number, b: number) => number; 60 | readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; 61 | readonly __wbindgen_exn_store: (a: number) => void; 62 | } 63 | 64 | export type SyncInitInput = BufferSource | WebAssembly.Module; 65 | /** 66 | * Instantiates the given `module`, which can either be bytes or 67 | * a precompiled `WebAssembly.Module`. 68 | * 69 | * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated. 70 | * 71 | * @returns {InitOutput} 72 | */ 73 | export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput; 74 | 75 | /** 76 | * If `module_or_path` is {RequestInfo} or {URL}, makes a request and 77 | * for everything else, calls `WebAssembly.instantiate` directly. 78 | * 79 | * @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated. 80 | * 81 | * @returns {Promise} 82 | */ 83 | export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; 84 | -------------------------------------------------------------------------------- /docs-gen/src/overlay/overlay_graph/overlay_graph.md: -------------------------------------------------------------------------------- 1 | # Overlay Graph 2 | ![Example](example.svg) 3 | An Overlay Graph is a data structure representing the intersections and overlays of two geometric objects (**A** and **B**) defined by closed contours in 2D space. 4 | 5 | The graph is constructed by dividing all the segments of the object contours into non-intersecting parts, where segments can only touch at their endpoints. 6 | Each segment in the graph contains the following properties: 7 | 8 | - For each side of the segment, it stores information about its membership to object **A** and object **B** 9 | - Segments do not intersect each other, but they may touch at their endpoints. 10 | 11 | for more Overlay Graph examples see [Shape Editor](../shapes_editor.md) 12 | 13 | ## Filter Segments 14 | 15 | ### Difference, C = A - B 16 | The resulting segments of **C** must not be inside body **B** and must belong to body **A** on one side. 17 | The side associated solely with body **A** will represent the inner part of the resulting shape. 18 | 19 | ![Example](difference_ab.svg) 20 | 21 | ### Difference, C = B - A 22 | The resulting segments of **C** must not be inside body **A** and must belong to body **B** on one side. 23 | The side associated solely with body **B** will represent the inner part of the resulting shape. 24 | ![Example](difference_ba.svg) 25 | 26 | ### Union, C = A or B 27 | The resulting segments of **C** must belong to either body **A** or body **B**, or to both. The opposite side of each segment must not belong to anybody. 28 | The side associated with one of the bodies will represent the inner part of the resulting shape. 29 | ![Example](union.svg) 30 | 31 | ### Intersection, C = A and B 32 | The resulting segments of **C** must belong to both bodies **A** and **B**. The opposite side of each segment must not belong to both bodies simultaneously. 33 | The side associated with both bodies **A** and **B** will represent the inner part of the resulting shape. 34 | ![Example](intersection.svg) 35 | 36 | ### Exclusion, C = A xor B 37 | The resulting segments of **C** must belong to either body **A** or body **B**, but not to both simultaneously. The opposite side of each segment must either belong to both bodies or to neither. 38 | The side associated with one of the bodies (**A** or **B**) will represent the inner part of the resulting shape. 39 | ![Example](exclusion.svg) -------------------------------------------------------------------------------- /src/bool/overlay.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | use crate::data::{NestedData, VectorsData}; 3 | use crate::bool::fill_rule::FillRule; 4 | use crate::bool::overlay_rule::OverlayRule; 5 | use i_triangle::i_overlay::core::fill_rule::FillRule as RustFillRule; 6 | use i_triangle::i_overlay::core::overlay_rule::OverlayRule as RustOverlayRule; 7 | use i_triangle::i_overlay::float::overlay::FloatOverlay; 8 | use wasm_bindgen::prelude::*; 9 | 10 | #[wasm_bindgen] 11 | pub struct Overlay { 12 | overlay: FloatOverlay<[f64; 2], f64>, 13 | } 14 | 15 | #[wasm_bindgen] 16 | impl Overlay { 17 | #[wasm_bindgen] 18 | pub fn new_with_subj_and_clip(subj_js: JsValue, clip_js: JsValue) -> Option { 19 | 20 | let subj = NestedData::with_json(subj_js)?; 21 | let clip = NestedData::with_json(clip_js)?; 22 | 23 | Some(Overlay::new_with_native_subj_and_clip(subj, clip)) 24 | } 25 | 26 | fn new_with_native_subj_and_clip(subj: NestedData, clip: NestedData) -> Overlay { 27 | let overlay = match (subj, clip) { 28 | (NestedData::Contour(subj), NestedData::Contour(clip)) => { 29 | FloatOverlay::with_subj_and_clip(&subj, &clip) 30 | } 31 | (NestedData::Contour(subj), NestedData::Shape(clip)) => { 32 | FloatOverlay::with_subj_and_clip(&subj, &clip) 33 | } 34 | (NestedData::Contour(subj), NestedData::Shapes(clip)) => { 35 | FloatOverlay::with_subj_and_clip(&subj, &clip) 36 | } 37 | (NestedData::Shape(subj), NestedData::Contour(clip)) => { 38 | FloatOverlay::with_subj_and_clip(&subj, &clip) 39 | } 40 | (NestedData::Shape(subj), NestedData::Shape(clip)) => { 41 | FloatOverlay::with_subj_and_clip(&subj, &clip) 42 | } 43 | (NestedData::Shape(subj), NestedData::Shapes(clip)) => { 44 | FloatOverlay::with_subj_and_clip(&subj, &clip) 45 | } 46 | (NestedData::Shapes(subj), NestedData::Contour(clip)) => { 47 | FloatOverlay::with_subj_and_clip(&subj, &clip) 48 | } 49 | (NestedData::Shapes(subj), NestedData::Shape(clip)) => { 50 | FloatOverlay::with_subj_and_clip(&subj, &clip) 51 | } 52 | (NestedData::Shapes(subj), NestedData::Shapes(clip)) => { 53 | FloatOverlay::with_subj_and_clip(&subj, &clip) 54 | } 55 | }; 56 | Overlay { overlay } 57 | } 58 | 59 | #[wasm_bindgen] 60 | pub fn overlay(mut self, overlay_rule: OverlayRule, fill_rule: FillRule) -> JsValue { 61 | let overlay_rule = RustOverlayRule::from(overlay_rule); 62 | let fill_rule = RustFillRule::from(fill_rule); 63 | 64 | let shapes = self.overlay.overlay(overlay_rule, fill_rule); 65 | 66 | serde_wasm_bindgen::to_value(&shapes).unwrap() 67 | } 68 | 69 | #[wasm_bindgen] 70 | pub fn separate_vectors(mut self, fill_rule: FillRule) -> JsValue { 71 | let fill_rule = RustFillRule::from(fill_rule); 72 | let data = if let Some(float_graph) = self.overlay.build_graph_view(fill_rule) { 73 | let vectors = float_graph.graph.extract_separate_vectors(); 74 | VectorsData::create(vectors, &float_graph.adapter) 75 | } else { 76 | VectorsData { 77 | vectors: Vec::new() 78 | } 79 | }; 80 | serde_wasm_bindgen::to_value(&data).unwrap() 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /docs-gen/src/triangle/delaunay.md: -------------------------------------------------------------------------------- 1 | 22 | 23 | 50 | 51 | ## Delaunay 52 |

Click on the canvas to drag the points

53 | 54 | 55 | ### What is the Delaunay Condition? 56 | 57 | 58 | When creating a triangulation network, the Delaunay condition aims to form triangles such that their circumscribed circles do not contain any other points from the dataset. In simpler terms, it ensures that triangles are "well-shaped" rather than "skinny," making the network more balanced and useful for various applications. 59 | 60 |
61 | 62 | ![Delaunay condition](delaunay_condition.svg) 63 | 64 |
65 | 66 | If the condition \\(\alpha + \beta < \pi\\) holds, it implies that the point \\(P\\) will lie outside the circumscribed circle. This confirms that a pair of triangles satisfies the Delaunay condition. 67 | 68 | $$ 69 | \alpha + \beta < \pi \Rightarrow \sin(\alpha + \beta) > 0 70 | $$ 71 | 72 | $$ 73 | \sin(\alpha + \beta) = \sin(\alpha)\cos(\beta) + \cos(\alpha)\sin(\beta) 74 | $$ 75 | 76 | Calculating \\(\cos(\alpha)\\) and \\(\sin(\alpha)\\): 77 | 78 | $$ 79 | \cos(\alpha) = \frac{\vec{a} \cdot \vec{b}}{|a||b|} = \frac{a_{x}b_{x} + a_{y}b_{y}}{|a||b|} 80 | $$ 81 | 82 | $$ 83 | \sin(\alpha) = \sqrt{1- \cos^2(\alpha)} = ... = \frac{|a_{x}b_{y} - b_{x}a_{y}|}{|a||b|} = \frac{|\vec{a} \times \vec{b}|}{|a||b|} 84 | $$ 85 | 86 | 87 | Calculating \\(\cos(\beta)\\) and \\(\sin(\beta)\\): 88 | 89 | 90 | $$ 91 | \cos(\beta) = \frac{\vec{c} \cdot \vec{d}}{|c||d|} = \frac{c_{x}d_{x} + c_{y}d_{y}}{|c||d|} 92 | $$ 93 | 94 | $$ 95 | \sin(\beta) = \frac{|\vec{c} \times \vec{d}|}{|c||d|} = \frac{|c_{x}d_{y} - d_{x}c_{y}|}{|c||d|} 96 | $$ 97 | 98 | Final Equation: 99 | 100 | $$ 101 | \sin(\alpha + \beta) = \frac{|a_{x}b_{y} - b_{x}a_{y}|\cdot(c_{x}d_{x} + c_{y}d_{y}) + (a_{x}b_{x} + a_{y}b_{y})\cdot|c_{x}d_{y} - c_{x}d_{y}|}{|a||b||c||d|} > 0 102 | $$ 103 | 104 | $$ 105 | |a_{x}b_{y} - b_{x}a_{y}|\cdot(c_{x}d_{x} + c_{y}d_{y}) + (a_{x}b_{x} + a_{y}b_{y})\cdot|c_{x}d_{y} - d_{x}c_{y}| > 0 106 | $$ 107 | 108 | Or in vector form: 109 | 110 | $$ 111 | |\vec{a} \times \vec{b}|(\vec{c} \cdot \vec{d}) + (\vec{a} \cdot \vec{b})|\vec{c} \times \vec{d}| > 0 112 | $$ 113 | -------------------------------------------------------------------------------- /src/triangle/triangulator.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | use crate::data::NestedData; 3 | use i_triangle::float::delaunay::Delaunay as RustDelaunay; 4 | use i_triangle::float::triangulatable::Triangulatable; 5 | use i_triangle::float::triangulation::{RawTriangulation as RustRawTriangulation, Triangulation}; 6 | use wasm_bindgen::prelude::wasm_bindgen; 7 | use wasm_bindgen::JsValue; 8 | 9 | #[wasm_bindgen] 10 | pub struct RawTriangulation { 11 | raw: RustRawTriangulation<[f64; 2], f64>, 12 | } 13 | 14 | #[wasm_bindgen] 15 | pub struct Delaunay { 16 | delaunay: RustDelaunay<[f64; 2], f64>, 17 | } 18 | 19 | #[wasm_bindgen] 20 | pub struct Triangulator {} 21 | 22 | #[wasm_bindgen] 23 | impl Triangulator { 24 | 25 | #[wasm_bindgen(constructor)] 26 | pub fn create() -> Self { 27 | Self {} 28 | } 29 | 30 | #[wasm_bindgen] 31 | pub fn triangulate(&self, path_js: JsValue) -> RawTriangulation { 32 | let path_data = NestedData::with_json(path_js).unwrap(); 33 | let raw = match path_data { 34 | NestedData::Contour(contour) => contour.triangulate(), 35 | NestedData::Shape(shape) => shape.triangulate(), 36 | NestedData::Shapes(shapes) => shapes.triangulate(), 37 | }; 38 | 39 | RawTriangulation { raw } 40 | } 41 | 42 | #[wasm_bindgen] 43 | pub fn triangulate_with_points(&self, path_js: JsValue, points_js: JsValue) -> RawTriangulation { 44 | let points_data: Result, _> = serde_wasm_bindgen::from_value(points_js); 45 | let points = points_data.unwrap(); 46 | let path_data = NestedData::with_json(path_js).unwrap(); 47 | let raw = match path_data { 48 | NestedData::Contour(contour) => contour.triangulate_with_steiner_points(&points), 49 | NestedData::Shape(shape) => shape.triangulate_with_steiner_points(&points), 50 | NestedData::Shapes(shapes) => shapes.triangulate_with_steiner_points(&points), 51 | }; 52 | 53 | RawTriangulation { raw } 54 | } 55 | } 56 | 57 | #[wasm_bindgen] 58 | impl RawTriangulation { 59 | #[wasm_bindgen] 60 | pub fn to_triangulation(&self) -> JsValue { 61 | let triangulation: Triangulation<[f64; 2], usize> = self.raw.to_triangulation(); 62 | serde_wasm_bindgen::to_value(&triangulation).unwrap() 63 | } 64 | 65 | #[wasm_bindgen] 66 | pub fn into_delaunay(self) -> Delaunay { 67 | Delaunay { 68 | delaunay: self.raw.into_delaunay(), 69 | } 70 | } 71 | } 72 | 73 | #[wasm_bindgen] 74 | impl Delaunay { 75 | #[wasm_bindgen] 76 | pub fn to_triangulation(&self) -> JsValue { 77 | let triangulation: Triangulation<[f64; 2], usize> = self.delaunay.to_triangulation(); 78 | serde_wasm_bindgen::to_value(&triangulation).unwrap() 79 | } 80 | 81 | #[wasm_bindgen] 82 | pub fn to_convex_polygons(&self) -> JsValue { 83 | let polygons = self.delaunay.to_convex_polygons(); 84 | serde_wasm_bindgen::to_value(&polygons).unwrap() 85 | } 86 | 87 | #[wasm_bindgen] 88 | pub fn refine_with_circumcenters(&mut self, min_area: f64) { 89 | self.delaunay.refine_with_circumcenters_mut(min_area); 90 | } 91 | 92 | #[wasm_bindgen] 93 | pub fn refine_with_circumcenters_by_obtuse_angle(&mut self, min_area: f64) { 94 | self.delaunay.refine_with_circumcenters_by_obtuse_angle_mut(min_area); 95 | } 96 | 97 | #[wasm_bindgen] 98 | pub fn to_centroid_net(&self, min_area: f64) -> JsValue { 99 | let centroids = self.delaunay.to_centroid_net(min_area); 100 | serde_wasm_bindgen::to_value(¢roids).unwrap() 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /docs/overlay/webgpu.svg: -------------------------------------------------------------------------------- 1 | 46 | -------------------------------------------------------------------------------- /docs-gen/src/overlay/webgpu.svg: -------------------------------------------------------------------------------- 1 | 46 | -------------------------------------------------------------------------------- /docs/fonts/fonts.css: -------------------------------------------------------------------------------- 1 | /* Open Sans is licensed under the Apache License, Version 2.0. See http://www.apache.org/licenses/LICENSE-2.0 */ 2 | /* Source Code Pro is under the Open Font License. See https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL */ 3 | 4 | /* open-sans-300 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 5 | @font-face { 6 | font-family: 'Open Sans'; 7 | font-style: normal; 8 | font-weight: 300; 9 | src: local('Open Sans Light'), local('OpenSans-Light'), 10 | url('open-sans-v17-all-charsets-300.woff2') format('woff2'); 11 | } 12 | 13 | /* open-sans-300italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 14 | @font-face { 15 | font-family: 'Open Sans'; 16 | font-style: italic; 17 | font-weight: 300; 18 | src: local('Open Sans Light Italic'), local('OpenSans-LightItalic'), 19 | url('open-sans-v17-all-charsets-300italic.woff2') format('woff2'); 20 | } 21 | 22 | /* open-sans-regular - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 23 | @font-face { 24 | font-family: 'Open Sans'; 25 | font-style: normal; 26 | font-weight: 400; 27 | src: local('Open Sans Regular'), local('OpenSans-Regular'), 28 | url('open-sans-v17-all-charsets-regular.woff2') format('woff2'); 29 | } 30 | 31 | /* open-sans-italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 32 | @font-face { 33 | font-family: 'Open Sans'; 34 | font-style: italic; 35 | font-weight: 400; 36 | src: local('Open Sans Italic'), local('OpenSans-Italic'), 37 | url('open-sans-v17-all-charsets-italic.woff2') format('woff2'); 38 | } 39 | 40 | /* open-sans-600 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 41 | @font-face { 42 | font-family: 'Open Sans'; 43 | font-style: normal; 44 | font-weight: 600; 45 | src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), 46 | url('open-sans-v17-all-charsets-600.woff2') format('woff2'); 47 | } 48 | 49 | /* open-sans-600italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 50 | @font-face { 51 | font-family: 'Open Sans'; 52 | font-style: italic; 53 | font-weight: 600; 54 | src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), 55 | url('open-sans-v17-all-charsets-600italic.woff2') format('woff2'); 56 | } 57 | 58 | /* open-sans-700 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 59 | @font-face { 60 | font-family: 'Open Sans'; 61 | font-style: normal; 62 | font-weight: 700; 63 | src: local('Open Sans Bold'), local('OpenSans-Bold'), 64 | url('open-sans-v17-all-charsets-700.woff2') format('woff2'); 65 | } 66 | 67 | /* open-sans-700italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 68 | @font-face { 69 | font-family: 'Open Sans'; 70 | font-style: italic; 71 | font-weight: 700; 72 | src: local('Open Sans Bold Italic'), local('OpenSans-BoldItalic'), 73 | url('open-sans-v17-all-charsets-700italic.woff2') format('woff2'); 74 | } 75 | 76 | /* open-sans-800 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 77 | @font-face { 78 | font-family: 'Open Sans'; 79 | font-style: normal; 80 | font-weight: 800; 81 | src: local('Open Sans ExtraBold'), local('OpenSans-ExtraBold'), 82 | url('open-sans-v17-all-charsets-800.woff2') format('woff2'); 83 | } 84 | 85 | /* open-sans-800italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 86 | @font-face { 87 | font-family: 'Open Sans'; 88 | font-style: italic; 89 | font-weight: 800; 90 | src: local('Open Sans ExtraBold Italic'), local('OpenSans-ExtraBoldItalic'), 91 | url('open-sans-v17-all-charsets-800italic.woff2') format('woff2'); 92 | } 93 | 94 | /* source-code-pro-500 - latin_vietnamese_latin-ext_greek_cyrillic-ext_cyrillic */ 95 | @font-face { 96 | font-family: 'Source Code Pro'; 97 | font-style: normal; 98 | font-weight: 500; 99 | src: url('source-code-pro-v11-all-charsets-500.woff2') format('woff2'); 100 | } 101 | -------------------------------------------------------------------------------- /docs-gen/src/triangle/tessellation.md: -------------------------------------------------------------------------------- 1 | 107 |
108 | 136 |

Tessellation

137 |
138 |
139 | 140 | 145 |
146 |
147 |
148 |
149 | 150 | 151 |
152 |
153 |
154 | 155 |

Title

156 | 157 |
158 | 159 |
-------------------------------------------------------------------------------- /docs-gen/src/triangle/triangulation.md: -------------------------------------------------------------------------------- 1 | 107 |
108 | 136 |

Triangulation

137 |
138 |
139 | 140 | 145 |
146 |
147 |
148 |
149 | 150 | 151 |
152 |
153 |
154 | 155 |

Title

156 | 157 |
158 | 159 |
-------------------------------------------------------------------------------- /docs/triangle/performance/test_1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 86 | -------------------------------------------------------------------------------- /docs-gen/src/triangle/performance/test_1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 86 | -------------------------------------------------------------------------------- /docs/triangle/performance/test_0.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 80 | -------------------------------------------------------------------------------- /docs-gen/src/triangle/performance/test_0.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 80 | -------------------------------------------------------------------------------- /src/bool/style.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::wasm_bindgen; 2 | use i_triangle::i_overlay::mesh::style::StrokeStyle as RustStrokeStyle; 3 | use i_triangle::i_overlay::mesh::style::OutlineStyle as RustOutlineStyle; 4 | use i_triangle::i_overlay::mesh::style::LineCap as RustLineCap; 5 | use i_triangle::i_overlay::mesh::style::LineJoin as RustLineJoin; 6 | 7 | #[wasm_bindgen] 8 | #[derive(Debug, Clone, Copy)] 9 | pub struct StrokeStyle { 10 | pub start_cap: LineCap, 11 | pub end_cap: LineCap, 12 | pub join: LineJoin, 13 | pub width: f64, 14 | pub round_angle: f64, 15 | pub miter_limit: f64, 16 | } 17 | 18 | #[wasm_bindgen] 19 | #[derive(Debug, Clone, Copy)] 20 | pub struct OutlineStyle { 21 | pub join: LineJoin, 22 | pub outer_offset: f64, 23 | pub inner_offset: f64, 24 | pub round_angle: f64, 25 | pub miter_limit: f64, 26 | } 27 | 28 | #[wasm_bindgen] 29 | #[derive(Debug, Clone, Copy, PartialEq)] 30 | pub enum LineCap { 31 | Butt, 32 | Round, 33 | Square 34 | } 35 | 36 | #[wasm_bindgen] 37 | #[derive(Debug, Clone, Copy, PartialEq)] 38 | pub enum LineJoin { 39 | Bevel, 40 | Miter, 41 | Round, 42 | } 43 | 44 | #[wasm_bindgen] 45 | impl StrokeStyle { 46 | 47 | #[wasm_bindgen(constructor)] 48 | pub fn create() -> Self { 49 | StrokeStyle { 50 | start_cap: LineCap::Butt, 51 | end_cap: LineCap::Butt, 52 | join: LineJoin::Bevel, 53 | width: 1.0, 54 | round_angle: 0.1, 55 | miter_limit: 0.1, 56 | } 57 | } 58 | 59 | #[wasm_bindgen] 60 | pub fn set_width(&mut self, width: f64) { 61 | self.width = width; 62 | } 63 | 64 | #[wasm_bindgen] 65 | pub fn get_width(&self) -> f64 { 66 | self.width 67 | } 68 | 69 | #[wasm_bindgen] 70 | pub fn get_line_join(&self) -> LineJoin { 71 | self.join.clone() 72 | } 73 | 74 | #[wasm_bindgen] 75 | pub fn set_line_join(&mut self, join: LineJoin) { 76 | self.join = join; 77 | } 78 | 79 | #[wasm_bindgen] 80 | pub fn set_round_angle(&mut self, angle: f64) { 81 | self.round_angle = angle; 82 | } 83 | 84 | #[wasm_bindgen] 85 | pub fn set_miter_limit(&mut self, limit: f64) { 86 | self.miter_limit = limit; 87 | } 88 | 89 | #[wasm_bindgen] 90 | pub fn get_start_cap(&self) -> LineCap { 91 | self.start_cap.clone() 92 | } 93 | 94 | #[wasm_bindgen] 95 | pub fn set_start_cap(&mut self, cap: LineCap) { 96 | self.start_cap = cap; 97 | } 98 | 99 | #[wasm_bindgen] 100 | pub fn get_end_cap(&self) -> LineCap { 101 | self.end_cap.clone() 102 | } 103 | 104 | #[wasm_bindgen] 105 | pub fn set_end_cap(&mut self, cap: LineCap) { 106 | self.end_cap = cap; 107 | } 108 | 109 | pub(crate) fn rust_style(&self) -> RustStrokeStyle<[f64; 2], f64> { 110 | let start_cap = match self.start_cap { 111 | LineCap::Butt => RustLineCap::Butt, 112 | LineCap::Round => RustLineCap::Round(self.round_angle), 113 | LineCap::Square => RustLineCap::Square, 114 | }; 115 | let end_cap = match self.end_cap { 116 | LineCap::Butt => RustLineCap::Butt, 117 | LineCap::Round => RustLineCap::Round(self.round_angle), 118 | LineCap::Square => RustLineCap::Square, 119 | }; 120 | 121 | let join = match self.join { 122 | LineJoin::Bevel => RustLineJoin::Bevel, 123 | LineJoin::Miter => RustLineJoin::Miter(self.miter_limit), 124 | LineJoin::Round => RustLineJoin::Round(self.round_angle), 125 | }; 126 | 127 | RustStrokeStyle { 128 | width: self.width, 129 | start_cap, 130 | end_cap, 131 | join, 132 | } 133 | } 134 | } 135 | 136 | #[wasm_bindgen] 137 | impl OutlineStyle { 138 | #[wasm_bindgen(constructor)] 139 | pub fn create() -> Self { 140 | OutlineStyle { 141 | join: LineJoin::Bevel, 142 | outer_offset: 1.0, 143 | inner_offset: 1.0, 144 | round_angle: 0.1, 145 | miter_limit: 0.1, 146 | } 147 | } 148 | 149 | pub(crate) fn rust_style(&self) -> RustOutlineStyle { 150 | let join = match self.join { 151 | LineJoin::Bevel => RustLineJoin::Bevel, 152 | LineJoin::Miter => RustLineJoin::Miter(self.miter_limit), 153 | LineJoin::Round => RustLineJoin::Round(self.round_angle), 154 | }; 155 | 156 | RustOutlineStyle { 157 | outer_offset: self.outer_offset, 158 | inner_offset: self.inner_offset, 159 | join, 160 | } 161 | } 162 | } -------------------------------------------------------------------------------- /docs/toc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
  1. iShape
  2. iOverlay
    1. Demo
      1. Stars Rotation
      2. Shapes Editor
      3. Stroke
      4. Outline
      5. Overlay Editor
    2. Performance Comparison
    3. Documentation
      1. Filling Rules
      2. Overlay Rules
      3. Contours
      4. Overlay Graph
      5. Extract Shapes
  3. iTriangle
    1. Demo
      1. Triangulation
      2. Tessellation
    2. Performance Comparison
    3. Delaunay
31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/fonts/SOURCE-CODE-PRO-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /docs-gen/src/overlay/outline.md: -------------------------------------------------------------------------------- 1 | 107 |
108 | 136 |

Outline

137 |
138 |
139 | 140 | 141 |
142 |
143 |
144 |
145 | 146 | 147 |
148 |
149 |
150 |
151 | 152 | 153 |
154 |
155 |
156 |
157 | 158 | 159 |
160 |
161 |
162 |
163 | 164 | 169 |
170 |
171 |
172 | 173 |

Title

174 | 175 |
176 | 177 |
-------------------------------------------------------------------------------- /docs-gen/src/overlay/shapes_editor.md: -------------------------------------------------------------------------------- 1 | 93 |
94 | 122 |

Shapes Editor

123 |
124 | 125 | 134 |
135 |
136 | 137 | 141 |
142 |
143 |
144 |
145 | 146 | 147 |
148 |
149 |
150 |
151 | 152 | 153 |
154 |
155 |
156 |
157 | 158 | 159 |
160 |
161 |
162 |
163 | 164 |

Title

165 | 166 |
167 | 168 |
-------------------------------------------------------------------------------- /pkg/ishape_wasm_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export const memory: WebAssembly.Memory; 4 | export const __wbg_delaunay_free: (a: number, b: number) => void; 5 | export const __wbg_triangulator_free: (a: number, b: number) => void; 6 | export const triangulator_create: () => number; 7 | export const triangulator_triangulate: (a: number, b: any) => number; 8 | export const triangulator_triangulate_with_points: (a: number, b: any, c: any) => number; 9 | export const rawtriangulation_to_triangulation: (a: number) => any; 10 | export const rawtriangulation_into_delaunay: (a: number) => number; 11 | export const delaunay_to_triangulation: (a: number) => any; 12 | export const delaunay_to_convex_polygons: (a: number) => any; 13 | export const delaunay_refine_with_circumcenters: (a: number, b: number) => void; 14 | export const delaunay_refine_with_circumcenters_by_obtuse_angle: (a: number, b: number) => void; 15 | export const delaunay_to_centroid_net: (a: number, b: number) => any; 16 | export const __wbg_strokebuilder_free: (a: number, b: number) => void; 17 | export const __wbg_get_strokebuilder_style: (a: number) => number; 18 | export const __wbg_set_strokebuilder_style: (a: number, b: number) => void; 19 | export const __wbg_outlinebuilder_free: (a: number, b: number) => void; 20 | export const __wbg_get_outlinebuilder_style: (a: number) => number; 21 | export const __wbg_set_outlinebuilder_style: (a: number, b: number) => void; 22 | export const strokebuilder_with_style: (a: number) => number; 23 | export const strokebuilder_build: (a: number, b: any, c: number) => any; 24 | export const outlinebuilder_with_style: (a: number) => number; 25 | export const outlinebuilder_build: (a: number, b: any) => any; 26 | export const __wbg_overlay_free: (a: number, b: number) => void; 27 | export const overlay_new_with_subj_and_clip: (a: any, b: any) => number; 28 | export const overlay_overlay: (a: number, b: number, c: number) => any; 29 | export const overlay_separate_vectors: (a: number, b: number) => any; 30 | export const __wbg_get_strokestyle_start_cap: (a: number) => number; 31 | export const __wbg_set_strokestyle_start_cap: (a: number, b: number) => void; 32 | export const __wbg_get_strokestyle_end_cap: (a: number) => number; 33 | export const __wbg_set_strokestyle_end_cap: (a: number, b: number) => void; 34 | export const __wbg_get_strokestyle_join: (a: number) => number; 35 | export const __wbg_set_strokestyle_join: (a: number, b: number) => void; 36 | export const __wbg_get_outlinestyle_join: (a: number) => number; 37 | export const __wbg_set_outlinestyle_join: (a: number, b: number) => void; 38 | export const __wbg_get_outlinestyle_outer_offset: (a: number) => number; 39 | export const __wbg_set_outlinestyle_outer_offset: (a: number, b: number) => void; 40 | export const __wbg_get_outlinestyle_inner_offset: (a: number) => number; 41 | export const __wbg_set_outlinestyle_inner_offset: (a: number, b: number) => void; 42 | export const __wbg_get_outlinestyle_round_angle: (a: number) => number; 43 | export const __wbg_set_outlinestyle_round_angle: (a: number, b: number) => void; 44 | export const __wbg_get_outlinestyle_miter_limit: (a: number) => number; 45 | export const __wbg_set_outlinestyle_miter_limit: (a: number, b: number) => void; 46 | export const strokestyle_create: () => number; 47 | export const strokestyle_set_width: (a: number, b: number) => void; 48 | export const strokestyle_get_width: (a: number) => number; 49 | export const strokestyle_get_line_join: (a: number) => number; 50 | export const strokestyle_set_line_join: (a: number, b: number) => void; 51 | export const strokestyle_set_round_angle: (a: number, b: number) => void; 52 | export const strokestyle_set_miter_limit: (a: number, b: number) => void; 53 | export const strokestyle_get_start_cap: (a: number) => number; 54 | export const strokestyle_set_start_cap: (a: number, b: number) => void; 55 | export const strokestyle_get_end_cap: (a: number) => number; 56 | export const strokestyle_set_end_cap: (a: number, b: number) => void; 57 | export const outlinestyle_create: () => number; 58 | export const __wbg_get_strokestyle_width: (a: number) => number; 59 | export const __wbg_get_strokestyle_round_angle: (a: number) => number; 60 | export const __wbg_get_strokestyle_miter_limit: (a: number) => number; 61 | export const __wbg_rawtriangulation_free: (a: number, b: number) => void; 62 | export const __wbg_set_strokestyle_width: (a: number, b: number) => void; 63 | export const __wbg_set_strokestyle_round_angle: (a: number, b: number) => void; 64 | export const __wbg_set_strokestyle_miter_limit: (a: number, b: number) => void; 65 | export const __wbg_strokestyle_free: (a: number, b: number) => void; 66 | export const __wbg_outlinestyle_free: (a: number, b: number) => void; 67 | export const __wbindgen_exn_store: (a: number) => void; 68 | export const __externref_table_alloc: () => number; 69 | export const __wbindgen_export_2: WebAssembly.Table; 70 | export const __wbindgen_malloc: (a: number, b: number) => number; 71 | export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; 72 | export const __wbindgen_start: () => void; 73 | -------------------------------------------------------------------------------- /docs/js/i_shape/ishape_wasm_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export const memory: WebAssembly.Memory; 4 | export const __wbg_delaunay_free: (a: number, b: number) => void; 5 | export const __wbg_triangulator_free: (a: number, b: number) => void; 6 | export const triangulator_create: () => number; 7 | export const triangulator_triangulate: (a: number, b: any) => number; 8 | export const triangulator_triangulate_with_points: (a: number, b: any, c: any) => number; 9 | export const rawtriangulation_to_triangulation: (a: number) => any; 10 | export const rawtriangulation_into_delaunay: (a: number) => number; 11 | export const delaunay_to_triangulation: (a: number) => any; 12 | export const delaunay_to_convex_polygons: (a: number) => any; 13 | export const delaunay_refine_with_circumcenters: (a: number, b: number) => void; 14 | export const delaunay_refine_with_circumcenters_by_obtuse_angle: (a: number, b: number) => void; 15 | export const delaunay_to_centroid_net: (a: number, b: number) => any; 16 | export const __wbg_strokebuilder_free: (a: number, b: number) => void; 17 | export const __wbg_get_strokebuilder_style: (a: number) => number; 18 | export const __wbg_set_strokebuilder_style: (a: number, b: number) => void; 19 | export const __wbg_outlinebuilder_free: (a: number, b: number) => void; 20 | export const __wbg_get_outlinebuilder_style: (a: number) => number; 21 | export const __wbg_set_outlinebuilder_style: (a: number, b: number) => void; 22 | export const strokebuilder_with_style: (a: number) => number; 23 | export const strokebuilder_build: (a: number, b: any, c: number) => any; 24 | export const outlinebuilder_with_style: (a: number) => number; 25 | export const outlinebuilder_build: (a: number, b: any) => any; 26 | export const __wbg_overlay_free: (a: number, b: number) => void; 27 | export const overlay_new_with_subj_and_clip: (a: any, b: any) => number; 28 | export const overlay_overlay: (a: number, b: number, c: number) => any; 29 | export const overlay_separate_vectors: (a: number, b: number) => any; 30 | export const __wbg_get_strokestyle_start_cap: (a: number) => number; 31 | export const __wbg_set_strokestyle_start_cap: (a: number, b: number) => void; 32 | export const __wbg_get_strokestyle_end_cap: (a: number) => number; 33 | export const __wbg_set_strokestyle_end_cap: (a: number, b: number) => void; 34 | export const __wbg_get_strokestyle_join: (a: number) => number; 35 | export const __wbg_set_strokestyle_join: (a: number, b: number) => void; 36 | export const __wbg_get_outlinestyle_join: (a: number) => number; 37 | export const __wbg_set_outlinestyle_join: (a: number, b: number) => void; 38 | export const __wbg_get_outlinestyle_outer_offset: (a: number) => number; 39 | export const __wbg_set_outlinestyle_outer_offset: (a: number, b: number) => void; 40 | export const __wbg_get_outlinestyle_inner_offset: (a: number) => number; 41 | export const __wbg_set_outlinestyle_inner_offset: (a: number, b: number) => void; 42 | export const __wbg_get_outlinestyle_round_angle: (a: number) => number; 43 | export const __wbg_set_outlinestyle_round_angle: (a: number, b: number) => void; 44 | export const __wbg_get_outlinestyle_miter_limit: (a: number) => number; 45 | export const __wbg_set_outlinestyle_miter_limit: (a: number, b: number) => void; 46 | export const strokestyle_create: () => number; 47 | export const strokestyle_set_width: (a: number, b: number) => void; 48 | export const strokestyle_get_width: (a: number) => number; 49 | export const strokestyle_get_line_join: (a: number) => number; 50 | export const strokestyle_set_line_join: (a: number, b: number) => void; 51 | export const strokestyle_set_round_angle: (a: number, b: number) => void; 52 | export const strokestyle_set_miter_limit: (a: number, b: number) => void; 53 | export const strokestyle_get_start_cap: (a: number) => number; 54 | export const strokestyle_set_start_cap: (a: number, b: number) => void; 55 | export const strokestyle_get_end_cap: (a: number) => number; 56 | export const strokestyle_set_end_cap: (a: number, b: number) => void; 57 | export const outlinestyle_create: () => number; 58 | export const __wbg_get_strokestyle_width: (a: number) => number; 59 | export const __wbg_get_strokestyle_round_angle: (a: number) => number; 60 | export const __wbg_get_strokestyle_miter_limit: (a: number) => number; 61 | export const __wbg_rawtriangulation_free: (a: number, b: number) => void; 62 | export const __wbg_set_strokestyle_width: (a: number, b: number) => void; 63 | export const __wbg_set_strokestyle_round_angle: (a: number, b: number) => void; 64 | export const __wbg_set_strokestyle_miter_limit: (a: number, b: number) => void; 65 | export const __wbg_strokestyle_free: (a: number, b: number) => void; 66 | export const __wbg_outlinestyle_free: (a: number, b: number) => void; 67 | export const __wbindgen_exn_store: (a: number) => void; 68 | export const __externref_table_alloc: () => number; 69 | export const __wbindgen_export_2: WebAssembly.Table; 70 | export const __wbindgen_malloc: (a: number, b: number) => number; 71 | export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; 72 | export const __wbindgen_start: () => void; 73 | -------------------------------------------------------------------------------- /docs-gen/src/js/i_shape/ishape_wasm_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export const memory: WebAssembly.Memory; 4 | export const __wbg_delaunay_free: (a: number, b: number) => void; 5 | export const __wbg_triangulator_free: (a: number, b: number) => void; 6 | export const triangulator_create: () => number; 7 | export const triangulator_triangulate: (a: number, b: any) => number; 8 | export const triangulator_triangulate_with_points: (a: number, b: any, c: any) => number; 9 | export const rawtriangulation_to_triangulation: (a: number) => any; 10 | export const rawtriangulation_into_delaunay: (a: number) => number; 11 | export const delaunay_to_triangulation: (a: number) => any; 12 | export const delaunay_to_convex_polygons: (a: number) => any; 13 | export const delaunay_refine_with_circumcenters: (a: number, b: number) => void; 14 | export const delaunay_refine_with_circumcenters_by_obtuse_angle: (a: number, b: number) => void; 15 | export const delaunay_to_centroid_net: (a: number, b: number) => any; 16 | export const __wbg_strokebuilder_free: (a: number, b: number) => void; 17 | export const __wbg_get_strokebuilder_style: (a: number) => number; 18 | export const __wbg_set_strokebuilder_style: (a: number, b: number) => void; 19 | export const __wbg_outlinebuilder_free: (a: number, b: number) => void; 20 | export const __wbg_get_outlinebuilder_style: (a: number) => number; 21 | export const __wbg_set_outlinebuilder_style: (a: number, b: number) => void; 22 | export const strokebuilder_with_style: (a: number) => number; 23 | export const strokebuilder_build: (a: number, b: any, c: number) => any; 24 | export const outlinebuilder_with_style: (a: number) => number; 25 | export const outlinebuilder_build: (a: number, b: any) => any; 26 | export const __wbg_overlay_free: (a: number, b: number) => void; 27 | export const overlay_new_with_subj_and_clip: (a: any, b: any) => number; 28 | export const overlay_overlay: (a: number, b: number, c: number) => any; 29 | export const overlay_separate_vectors: (a: number, b: number) => any; 30 | export const __wbg_get_strokestyle_start_cap: (a: number) => number; 31 | export const __wbg_set_strokestyle_start_cap: (a: number, b: number) => void; 32 | export const __wbg_get_strokestyle_end_cap: (a: number) => number; 33 | export const __wbg_set_strokestyle_end_cap: (a: number, b: number) => void; 34 | export const __wbg_get_strokestyle_join: (a: number) => number; 35 | export const __wbg_set_strokestyle_join: (a: number, b: number) => void; 36 | export const __wbg_get_outlinestyle_join: (a: number) => number; 37 | export const __wbg_set_outlinestyle_join: (a: number, b: number) => void; 38 | export const __wbg_get_outlinestyle_outer_offset: (a: number) => number; 39 | export const __wbg_set_outlinestyle_outer_offset: (a: number, b: number) => void; 40 | export const __wbg_get_outlinestyle_inner_offset: (a: number) => number; 41 | export const __wbg_set_outlinestyle_inner_offset: (a: number, b: number) => void; 42 | export const __wbg_get_outlinestyle_round_angle: (a: number) => number; 43 | export const __wbg_set_outlinestyle_round_angle: (a: number, b: number) => void; 44 | export const __wbg_get_outlinestyle_miter_limit: (a: number) => number; 45 | export const __wbg_set_outlinestyle_miter_limit: (a: number, b: number) => void; 46 | export const strokestyle_create: () => number; 47 | export const strokestyle_set_width: (a: number, b: number) => void; 48 | export const strokestyle_get_width: (a: number) => number; 49 | export const strokestyle_get_line_join: (a: number) => number; 50 | export const strokestyle_set_line_join: (a: number, b: number) => void; 51 | export const strokestyle_set_round_angle: (a: number, b: number) => void; 52 | export const strokestyle_set_miter_limit: (a: number, b: number) => void; 53 | export const strokestyle_get_start_cap: (a: number) => number; 54 | export const strokestyle_set_start_cap: (a: number, b: number) => void; 55 | export const strokestyle_get_end_cap: (a: number) => number; 56 | export const strokestyle_set_end_cap: (a: number, b: number) => void; 57 | export const outlinestyle_create: () => number; 58 | export const __wbg_get_strokestyle_width: (a: number) => number; 59 | export const __wbg_get_strokestyle_round_angle: (a: number) => number; 60 | export const __wbg_get_strokestyle_miter_limit: (a: number) => number; 61 | export const __wbg_rawtriangulation_free: (a: number, b: number) => void; 62 | export const __wbg_set_strokestyle_width: (a: number, b: number) => void; 63 | export const __wbg_set_strokestyle_round_angle: (a: number, b: number) => void; 64 | export const __wbg_set_strokestyle_miter_limit: (a: number, b: number) => void; 65 | export const __wbg_strokestyle_free: (a: number, b: number) => void; 66 | export const __wbg_outlinestyle_free: (a: number, b: number) => void; 67 | export const __wbindgen_exn_store: (a: number) => void; 68 | export const __externref_table_alloc: () => number; 69 | export const __wbindgen_export_2: WebAssembly.Table; 70 | export const __wbindgen_malloc: (a: number, b: number) => number; 71 | export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; 72 | export const __wbindgen_start: () => void; 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iShape-js 2 | 3 |

4 | 5 |

6 | A fast 2D geometry library in WebAssembly for JavaScript and TypeScript. Supports polygon boolean operations, buffering, and triangulation. 7 | 8 | ## [Demo](https://ishape-rust.github.io/iShape-js/overlay/stars_demo.html) 9 | Try out iShape with an interactive demo. 10 | 11 | - [Stars Rotation](https://ishape-rust.github.io/iShape-js/overlay/stars_demo.html) 12 | - [Shapes Editor](https://ishape-rust.github.io/iShape-js/overlay/shapes_editor.html) 13 | - [Path Offset](https://ishape-rust.github.io/iShape-js/overlay/stroke.html) 14 | - [Polygon Offset](https://ishape-rust.github.io/iShape-js/overlay/outline.html) 15 | - [Triangulation](https://ishape-rust.github.io/iShape-js/triangle/triangulation.html) 16 | 17 | ## Features 18 | 19 | - **Boolean Operations**: union, intersection, difference, and exclusion. 20 | - **Polygons**: with holes, self-intersections, and multiple paths. 21 | - **Simplification**: removes degenerate vertices and merges collinear edges. 22 | - **Fill Rules**: even-odd, non-zero, positive and negative. 23 | 24 | ## Getting Started 25 | 26 | 27 | ### Direct include 28 | 29 | #### Download Library Files: 30 | 31 | - *ishape_wasm.js* 32 | - *ishape_bg_wasm.wasm* 33 | 34 | You can find it at: [pkg](pkg) 35 | 36 | #### Place Files: 37 | Place these files in a directory that your HTML file can access; in this example, the directory is named *./ishape* 38 | 39 | 40 | ### NPM 41 | 42 | #### Installation 43 | You can install the iShape library from NPM: 44 | 45 | ```bash 46 | npm install ishape_wasm 47 | ``` 48 | 49 | The NPM package is available [here](https://www.npmjs.com/package/ishape_wasm) 50 | 51 | 52 | #### Import and Usage 53 | 54 | After installing the NPM package, you can import it in your JavaScript or TypeScript file as follows: 55 | 56 | ```javascript 57 | import init, { Overlay, OverlayRule, FillRule } from './ishape/ishape_wasm.js'; 58 | 59 | // Your code here 60 | 61 | ``` 62 | 63 | 64 | ### Example 65 | Here is a simple HTML example that demonstrates how to use the iShape library for union operation. 66 | Full example is available [here](https://github.com/iShape-Rust/iShape-js/tree/main/examples/html) 67 | ```html 68 | 69 | 70 | 71 | 72 | 73 | iShape 74 | 90 | 114 | 115 | 116 | 117 | 118 | 119 |

120 | 
121 | 
122 | ```
123 | 
124 | #### Explanation:
125 | 
126 | Import classes and initialize the WebAssembly module using init().
127 | Use the imported classes to perform geometric operations.
128 | 
129 | # Overlay Rules
130 | | A,B | A ∪ B | A ∩ B | A - B | B - A | A ⊕ B |
131 | |---------|---------------|----------------------|----------------|--------------------|----------------|
132 | | AB | Union | Intersection | Difference | Inverse Difference | Exclusion |
133 | 


--------------------------------------------------------------------------------
/pkg/README.md:
--------------------------------------------------------------------------------
  1 | # iShape-js
  2 | 
  3 | 

4 | 5 |

6 | A fast 2D geometry library in WebAssembly for JavaScript and TypeScript. Supports polygon boolean operations, buffering, and triangulation. 7 | 8 | ## [Demo](https://ishape-rust.github.io/iShape-js/overlay/stars_demo.html) 9 | Try out iShape with an interactive demo. 10 | 11 | - [Stars Rotation](https://ishape-rust.github.io/iShape-js/overlay/stars_demo.html) 12 | - [Shapes Editor](https://ishape-rust.github.io/iShape-js/overlay/shapes_editor.html) 13 | - [Path Offset](https://ishape-rust.github.io/iShape-js/overlay/stroke.html) 14 | - [Polygon Offset](https://ishape-rust.github.io/iShape-js/overlay/outline.html) 15 | - [Triangulation](https://ishape-rust.github.io/iShape-js/triangle/triangulation.html) 16 | 17 | ## Features 18 | 19 | - **Boolean Operations**: union, intersection, difference, and exclusion. 20 | - **Polygons**: with holes, self-intersections, and multiple paths. 21 | - **Simplification**: removes degenerate vertices and merges collinear edges. 22 | - **Fill Rules**: even-odd, non-zero, positive and negative. 23 | 24 | ## Getting Started 25 | 26 | 27 | ### Direct include 28 | 29 | #### Download Library Files: 30 | 31 | - *ishape_wasm.js* 32 | - *ishape_bg_wasm.wasm* 33 | 34 | You can find it at: [pkg](pkg) 35 | 36 | #### Place Files: 37 | Place these files in a directory that your HTML file can access; in this example, the directory is named *./ishape* 38 | 39 | 40 | ### NPM 41 | 42 | #### Installation 43 | You can install the iShape library from NPM: 44 | 45 | ```bash 46 | npm install ishape_wasm 47 | ``` 48 | 49 | The NPM package is available [here](https://www.npmjs.com/package/ishape_wasm) 50 | 51 | 52 | #### Import and Usage 53 | 54 | After installing the NPM package, you can import it in your JavaScript or TypeScript file as follows: 55 | 56 | ```javascript 57 | import init, { Overlay, OverlayRule, FillRule } from './ishape/ishape_wasm.js'; 58 | 59 | // Your code here 60 | 61 | ``` 62 | 63 | 64 | ### Example 65 | Here is a simple HTML example that demonstrates how to use the iShape library for union operation. 66 | Full example is available [here](https://github.com/iShape-Rust/iShape-js/tree/main/examples/html) 67 | ```html 68 | 69 | 70 | 71 | 72 | 73 | iShape 74 | 90 | 114 | 115 | 116 | 117 | 118 | 119 |

120 | 
121 | 
122 | ```
123 | 
124 | #### Explanation:
125 | 
126 | Import classes and initialize the WebAssembly module using init().
127 | Use the imported classes to perform geometric operations.
128 | 
129 | # Overlay Rules
130 | | A,B | A ∪ B | A ∩ B | A - B | B - A | A ⊕ B |
131 | |---------|---------------|----------------------|----------------|--------------------|----------------|
132 | | AB | Union | Intersection | Difference | Inverse Difference | Exclusion |
133 | 


--------------------------------------------------------------------------------
/docs-gen/src/overlay/stars_demo.md:
--------------------------------------------------------------------------------
  1 | 
 77 | 
78 | 106 |

Stars Rotation

107 |
108 |
109 |

Subject Star

110 |
111 | 112 | 113 |
114 |
115 | 116 | 117 |
118 |
119 | 120 | 121 |
122 |
123 | 124 | 125 |
126 |
127 |
128 |

Clip Star

129 |
130 | 131 | 132 |
133 |
134 | 135 | 136 |
137 |
138 | 139 | 140 |
141 |
142 | 143 | 144 |
145 |
146 |
147 |
148 | 149 | 158 |
159 | 160 |
161 | -------------------------------------------------------------------------------- /docs-gen/src/overlay/extract/extract_shapes.md: -------------------------------------------------------------------------------- 1 | # Extract Shapes 2 | 3 | Once we apply boolean filter to [Overlay Graph](../overlay_graph/overlay_graph.md), we can begin extract contours. 4 | 5 | ## Build Contour 6 | 7 | ### Outer Contour 8 | ![Extract Contour](extract_outer_contour_clockwise.svg) 9 | ### Inner Contour 10 | ![Extract Contour](extract_inner_clockwise.svg) 11 | 12 | The algorithm starts by selecting the leftmost node and proceeds by choosing the topmost segment connected to that node. The process continues by traversing to the next node along the selected segment. 13 | 14 | At each node, the algorithm selects the next segment by rotating around the current node in a clockwise/counterclockwise direction for outer/inner contours and taking the first nearest segment. 15 | 16 | To prevent segments from being visited twice, each segment is marked as visited upon traversal. 17 | 18 | This process continues until the contour is complete, forming either an **outer** or **inner** contour. 19 | 20 | By following this approach, **outer** contours are extracted in a counter-clockwise direction, while **inner** contours are extracted in a clockwise direction. 21 | 22 | ## Define Contour 23 | ![Define Contour](define_contour.svg) 24 | 25 | To define a contour, the algorithm begins by identifying the leftmost and topmost segment in the contour. The classification of the contour is determined as follows: 26 | 27 | - If the left-top side of the segment is classified as the **outer** side, then the contour is an **outer** contour. 28 | - If the left-top side of the segment is classified as the **inner** side, then the contour is an **inner** contour. 29 | 30 | This method ensures each contour is correctly classified based on its orientation in 2D space. 31 | 32 | ## Define Shape 33 | ![Define Shape](define_shape.svg) 34 | 35 | A shape is defined as a group of contours, where the first contour is always an **outer** contour, and the subsequent contours (if any) are **inner** contours. 36 | 37 | ## Matching Contours 38 | ![Matching Contours](matching_contours.svg) 39 | To match **inner** contours to their corresponding **outer** contours: 40 | 1. Draw a line **downward** from any point on the **inner** (**target**) contour. 41 | 2. Identify the first segment encountered along the line that does not belong to the **target** contour. 42 | - If the segment belongs to an **outer** contour, that contour is the container for the **target** contour. 43 | - If the segment belongs to another **inner** contour, the container of that **inner** contour is also the container for the **target** contour. 44 | ## Define Segment under Point 45 | 46 | ## Segment under Point 47 | ![Segment Under Point](segment_under_point.svg) 48 | 49 | To determine whether a segment **AB** is below a point **P**, one may be tempted to compute the value of ym at the point of intersection **M**, where a vertical line is dropped from **P** onto **AB** (i.e., xp = xm): 50 | 51 | $$ 52 | y_{m} = \frac{y_{a} - y_{b}}{x_{a} - x_{b}}\cdot(x_{m} - x_{a}) + y_{a} 53 | $$ 54 | 55 | However, this approach can introduce precision issues due to the division involved. 56 | 57 | A more reliable method involves using the order of traversal around the vertices of the triangle **APB**. If segment **AB** is below point **P**, the vertices **A**, **P**, and **B** will appear in a clockwise order. 58 | 59 | This method uses the cross product of vectors **PA** and **PB**: 60 | 61 | $$ 62 | a \times b = a_x b_y - a_y b_x 63 | $$ 64 | 65 | Since this method avoids division, it eliminates precision issues, making it stable for determining whether a segment is below a point. 66 | 67 | ## Selecting the Closest Segment under Point 68 | 69 | When multiple segments are positioned below point **P**, we need to determine which segment is the closest to **P**. This scenario can be divided into three distinct cases based on the configuration of the segments relative to **P**. 70 | 71 | ### Left Case 72 | ![Left Case](segment_under_segment_a.svg) 73 | 74 | When both segments share a common left vertex **A**, we check the positions of their right endpoints. If the vertices **B0**, **B1**, and **A** form a clockwise pattern, then **AB0** is closer to **P** than **AB1**. 75 | 76 | ### Right Case 77 | ![Right Case](segment_under_segment_b.svg) 78 | 79 | When both segments share a common right vertex **B**, we check the positions of their left endpoints. If the vertices **A0**, **A1**, and **B** form a clockwise pattern, then **A1B** is closer to **P** than **A0B**. 80 | 81 | ### Middle Case 82 | ![Middle Case](segment_under_segment_ab.svg) 83 | 84 | In this case, one of the vertices (e.g., **A1** or **B0**) lies inside the opposite segment. We use the point-segment comparison method to determine which of the segments is closer to **P**. -------------------------------------------------------------------------------- /docs-gen/src/overlay/stroke.md: -------------------------------------------------------------------------------- 1 | 107 |
108 | 136 |

Stroke Offset

137 |
138 |
139 | 140 | 141 |
142 |
143 |
144 |
145 | 146 | 147 |
148 |
149 |
150 |
151 | 152 | 153 |
154 |
155 |
156 |
157 | 158 | 163 |
164 |
165 |
166 |
167 | 168 | 173 |
174 |
175 |
176 |
177 | 178 | 183 |
184 |
185 |
186 |
187 | 188 | 189 |
190 |
191 |
192 | 193 |

Title

194 | 195 |
196 | 197 |
-------------------------------------------------------------------------------- /docs/js/overlay/stars.js: -------------------------------------------------------------------------------- 1 | import init, { Overlay, FillRule, OverlayRule} from '../i_shape/ishape_wasm.js'; 2 | 3 | const canvas = document.getElementById('starCanvas'); 4 | const ctx = canvas.getContext('2d'); 5 | let subjAngle = 0; 6 | let clipAngle = 0; 7 | 8 | let lastFrameTime = 0; 9 | const maxFPS = 60; 10 | const frameDuration = 1000 / maxFPS; 11 | 12 | const subjFirstRadiusSlider = document.getElementById('subjFirstRadius'); 13 | const subjSecondRadiusSlider = document.getElementById('subjSecondRadius'); 14 | const subjRotationSpeedSlider = document.getElementById('subjRotationSpeed'); 15 | const subjAngleCountSlider = document.getElementById('subjAngleCount'); 16 | 17 | const clipFirstRadiusSlider = document.getElementById('clipFirstRadius'); 18 | const clipSecondRadiusSlider = document.getElementById('clipSecondRadius'); 19 | const clipRotationSpeedSlider = document.getElementById('clipRotationSpeed'); 20 | const clipAngleCountSlider = document.getElementById('clipAngleCount'); 21 | 22 | const operationTypeSelect = document.getElementById('operationType'); 23 | 24 | const colorStore = [ 25 | "#FF9500", // Orange 26 | "#5856D6", // Purple 27 | "#FF2D55", // Pink 28 | "#5AC8FA", // Blue 29 | "#4CD964", // Green 30 | "#FFCC00", // Yellow 31 | "#8E8E93", // Gray 32 | "#FF3B30", // Red 33 | "#34C759", // Green 34 | "#007AFF", // Blue 35 | "#AF52DE", // Indigo 36 | "#FFD60A" // Teal 37 | ]; 38 | 39 | run(); 40 | 41 | async function run() { 42 | await init(); // Initialize the wasm module 43 | 44 | requestAnimationFrame(draw); 45 | } 46 | 47 | function draw(currentTime) { 48 | const deltaTime = currentTime - lastFrameTime; 49 | 50 | const a = 0.45 * 0.01 * Math.min(canvas.width, canvas.height); 51 | 52 | if (deltaTime < frameDuration) { 53 | requestAnimationFrame(draw); 54 | return; 55 | } 56 | 57 | lastFrameTime = currentTime; 58 | 59 | ctx.clearRect(0, 0, canvas.width, canvas.height); 60 | 61 | const subjFirstRadius = a * parseInt(subjFirstRadiusSlider.value, 12); 62 | const subjSecondRadius = a * parseInt(subjSecondRadiusSlider.value, 10); 63 | const subjRotationSpeed = parseInt(subjRotationSpeedSlider.value, 10) * 0.0005; 64 | const subjAngleCount = parseInt(subjAngleCountSlider.value, 10); 65 | 66 | const clipFirstRadius = a * parseInt(clipFirstRadiusSlider.value, 10); 67 | const clipSecondRadius = a * parseInt(clipSecondRadiusSlider.value, 10); 68 | const clipRotationSpeed = parseInt(clipRotationSpeedSlider.value, 10) * 0.0005; 69 | const clipAngleCount = parseInt(clipAngleCountSlider.value, 10); 70 | 71 | const selectedOperation = operationTypeSelect.value; 72 | 73 | let overlayRule; 74 | switch (selectedOperation) { 75 | case 'Union': 76 | overlayRule = OverlayRule.Union; 77 | break; 78 | case 'Intersect': 79 | overlayRule = OverlayRule.Intersect; 80 | break; 81 | case 'Difference': 82 | overlayRule = OverlayRule.Difference; 83 | break; 84 | case 'InverseDifference': 85 | overlayRule = OverlayRule.InverseDifference; 86 | break; 87 | case 'Xor': 88 | overlayRule = OverlayRule.Xor; 89 | break; 90 | case 'Subject': 91 | overlayRule = OverlayRule.Subject; // Replace with the actual value 92 | break; 93 | case 'Clip': 94 | overlayRule = OverlayRule.Clip; // Replace with the actual value 95 | break; 96 | } 97 | 98 | let x0 = 0.5 * canvas.width; 99 | let y0 = 0.5 * canvas.height; 100 | 101 | const subj = createStar({ x: x0, y: y0 }, subjFirstRadius, subjSecondRadius, subjAngleCount, subjAngle); 102 | const clip = createStar({ x: x0, y: y0 }, clipFirstRadius, clipSecondRadius, clipAngleCount, clipAngle); 103 | 104 | const overlay = Overlay.new_with_subj_and_clip(subj, clip); 105 | const result = overlay.overlay(overlayRule, FillRule.EvenOdd); 106 | 107 | var index = 0; 108 | result.forEach((shape) => { 109 | const stroke = getColorByIndex(index); 110 | const fill = getColorByIndex(index, 0.5); 111 | 112 | 113 | drawShape(ctx, shape, fill, stroke, 8); 114 | index += 1; 115 | }); 116 | 117 | subjAngle += subjRotationSpeed; 118 | clipAngle -= clipRotationSpeed; 119 | 120 | requestAnimationFrame(draw); 121 | } 122 | 123 | function createStar(center, r0, r1, count, angle) { 124 | const da = Math.PI / count; 125 | let a = angle; 126 | const x0 = center.x; 127 | const y0 = center.y; 128 | 129 | const points = []; 130 | 131 | for (let i = 0; i < count; i++) { 132 | const xr0 = r0 * Math.cos(a); 133 | const yr0 = r0 * Math.sin(a); 134 | 135 | a += da; 136 | 137 | const xr1 = r1 * Math.cos(a); 138 | const yr1 = r1 * Math.sin(a); 139 | 140 | a += da; 141 | 142 | points.push([x0 + xr0, y0 + yr0]); 143 | points.push([x0 + xr1, y0 + yr1]); 144 | } 145 | 146 | return points; 147 | } 148 | 149 | function drawShape(ctx, shape, fillColor, strokeColor, lineWidth) { 150 | ctx.lineCap = 'round'; 151 | ctx.lineJoin = 'round'; 152 | 153 | let region = new Path2D(); 154 | 155 | shape.forEach((points) => { 156 | const [x0, y0] = points[0]; 157 | region.moveTo(x0, y0); 158 | 159 | for (let i = 1; i < points.length; i++) { 160 | const [x, y] = points[i]; 161 | region.lineTo(x, y); 162 | } 163 | 164 | region.closePath(); 165 | }); 166 | 167 | ctx.fillStyle = fillColor; 168 | ctx.strokeStyle = strokeColor; 169 | ctx.lineWidth = lineWidth; 170 | 171 | ctx.stroke(region); 172 | ctx.fill(region, 'evenodd'); 173 | } 174 | 175 | function getColorByIndex(index, opacity = 1) { 176 | const n = colorStore.length; 177 | const i = index % n; 178 | const color = colorStore[i]; 179 | 180 | if (opacity === 1) { 181 | return color; 182 | } 183 | 184 | const alpha = Math.round(opacity * 255).toString(16).padStart(2, '0'); 185 | return color + alpha; 186 | } -------------------------------------------------------------------------------- /docs-gen/src/js/overlay/stars.js: -------------------------------------------------------------------------------- 1 | import init, { Overlay, FillRule, OverlayRule} from '../i_shape/ishape_wasm.js'; 2 | 3 | const canvas = document.getElementById('starCanvas'); 4 | const ctx = canvas.getContext('2d'); 5 | let subjAngle = 0; 6 | let clipAngle = 0; 7 | 8 | let lastFrameTime = 0; 9 | const maxFPS = 60; 10 | const frameDuration = 1000 / maxFPS; 11 | 12 | const subjFirstRadiusSlider = document.getElementById('subjFirstRadius'); 13 | const subjSecondRadiusSlider = document.getElementById('subjSecondRadius'); 14 | const subjRotationSpeedSlider = document.getElementById('subjRotationSpeed'); 15 | const subjAngleCountSlider = document.getElementById('subjAngleCount'); 16 | 17 | const clipFirstRadiusSlider = document.getElementById('clipFirstRadius'); 18 | const clipSecondRadiusSlider = document.getElementById('clipSecondRadius'); 19 | const clipRotationSpeedSlider = document.getElementById('clipRotationSpeed'); 20 | const clipAngleCountSlider = document.getElementById('clipAngleCount'); 21 | 22 | const operationTypeSelect = document.getElementById('operationType'); 23 | 24 | const colorStore = [ 25 | "#FF9500", // Orange 26 | "#5856D6", // Purple 27 | "#FF2D55", // Pink 28 | "#5AC8FA", // Blue 29 | "#4CD964", // Green 30 | "#FFCC00", // Yellow 31 | "#8E8E93", // Gray 32 | "#FF3B30", // Red 33 | "#34C759", // Green 34 | "#007AFF", // Blue 35 | "#AF52DE", // Indigo 36 | "#FFD60A" // Teal 37 | ]; 38 | 39 | run(); 40 | 41 | async function run() { 42 | await init(); // Initialize the wasm module 43 | 44 | requestAnimationFrame(draw); 45 | } 46 | 47 | function draw(currentTime) { 48 | const deltaTime = currentTime - lastFrameTime; 49 | 50 | const a = 0.45 * 0.01 * Math.min(canvas.width, canvas.height); 51 | 52 | if (deltaTime < frameDuration) { 53 | requestAnimationFrame(draw); 54 | return; 55 | } 56 | 57 | lastFrameTime = currentTime; 58 | 59 | ctx.clearRect(0, 0, canvas.width, canvas.height); 60 | 61 | const subjFirstRadius = a * parseInt(subjFirstRadiusSlider.value, 12); 62 | const subjSecondRadius = a * parseInt(subjSecondRadiusSlider.value, 10); 63 | const subjRotationSpeed = parseInt(subjRotationSpeedSlider.value, 10) * 0.0005; 64 | const subjAngleCount = parseInt(subjAngleCountSlider.value, 10); 65 | 66 | const clipFirstRadius = a * parseInt(clipFirstRadiusSlider.value, 10); 67 | const clipSecondRadius = a * parseInt(clipSecondRadiusSlider.value, 10); 68 | const clipRotationSpeed = parseInt(clipRotationSpeedSlider.value, 10) * 0.0005; 69 | const clipAngleCount = parseInt(clipAngleCountSlider.value, 10); 70 | 71 | const selectedOperation = operationTypeSelect.value; 72 | 73 | let overlayRule; 74 | switch (selectedOperation) { 75 | case 'Union': 76 | overlayRule = OverlayRule.Union; 77 | break; 78 | case 'Intersect': 79 | overlayRule = OverlayRule.Intersect; 80 | break; 81 | case 'Difference': 82 | overlayRule = OverlayRule.Difference; 83 | break; 84 | case 'InverseDifference': 85 | overlayRule = OverlayRule.InverseDifference; 86 | break; 87 | case 'Xor': 88 | overlayRule = OverlayRule.Xor; 89 | break; 90 | case 'Subject': 91 | overlayRule = OverlayRule.Subject; // Replace with the actual value 92 | break; 93 | case 'Clip': 94 | overlayRule = OverlayRule.Clip; // Replace with the actual value 95 | break; 96 | } 97 | 98 | let x0 = 0.5 * canvas.width; 99 | let y0 = 0.5 * canvas.height; 100 | 101 | const subj = createStar({ x: x0, y: y0 }, subjFirstRadius, subjSecondRadius, subjAngleCount, subjAngle); 102 | const clip = createStar({ x: x0, y: y0 }, clipFirstRadius, clipSecondRadius, clipAngleCount, clipAngle); 103 | 104 | const overlay = Overlay.new_with_subj_and_clip(subj, clip); 105 | const result = overlay.overlay(overlayRule, FillRule.EvenOdd); 106 | 107 | var index = 0; 108 | result.forEach((shape) => { 109 | const stroke = getColorByIndex(index); 110 | const fill = getColorByIndex(index, 0.5); 111 | 112 | 113 | drawShape(ctx, shape, fill, stroke, 8); 114 | index += 1; 115 | }); 116 | 117 | subjAngle += subjRotationSpeed; 118 | clipAngle -= clipRotationSpeed; 119 | 120 | requestAnimationFrame(draw); 121 | } 122 | 123 | function createStar(center, r0, r1, count, angle) { 124 | const da = Math.PI / count; 125 | let a = angle; 126 | const x0 = center.x; 127 | const y0 = center.y; 128 | 129 | const points = []; 130 | 131 | for (let i = 0; i < count; i++) { 132 | const xr0 = r0 * Math.cos(a); 133 | const yr0 = r0 * Math.sin(a); 134 | 135 | a += da; 136 | 137 | const xr1 = r1 * Math.cos(a); 138 | const yr1 = r1 * Math.sin(a); 139 | 140 | a += da; 141 | 142 | points.push([x0 + xr0, y0 + yr0]); 143 | points.push([x0 + xr1, y0 + yr1]); 144 | } 145 | 146 | return points; 147 | } 148 | 149 | function drawShape(ctx, shape, fillColor, strokeColor, lineWidth) { 150 | ctx.lineCap = 'round'; 151 | ctx.lineJoin = 'round'; 152 | 153 | let region = new Path2D(); 154 | 155 | shape.forEach((points) => { 156 | const [x0, y0] = points[0]; 157 | region.moveTo(x0, y0); 158 | 159 | for (let i = 1; i < points.length; i++) { 160 | const [x, y] = points[i]; 161 | region.lineTo(x, y); 162 | } 163 | 164 | region.closePath(); 165 | }); 166 | 167 | ctx.fillStyle = fillColor; 168 | ctx.strokeStyle = strokeColor; 169 | ctx.lineWidth = lineWidth; 170 | 171 | ctx.stroke(region); 172 | ctx.fill(region, 'evenodd'); 173 | } 174 | 175 | function getColorByIndex(index, opacity = 1) { 176 | const n = colorStore.length; 177 | const i = index % n; 178 | const color = colorStore[i]; 179 | 180 | if (opacity === 1) { 181 | return color; 182 | } 183 | 184 | const alpha = Math.round(opacity * 255).toString(16).padStart(2, '0'); 185 | return color + alpha; 186 | } -------------------------------------------------------------------------------- /docs/toc.js: -------------------------------------------------------------------------------- 1 | // Populate the sidebar 2 | // 3 | // This is a script, and not included directly in the page, to control the total size of the book. 4 | // The TOC contains an entry for each page, so if each page includes a copy of the TOC, 5 | // the total size of the page becomes O(n**2). 6 | class MDBookSidebarScrollbox extends HTMLElement { 7 | constructor() { 8 | super(); 9 | } 10 | connectedCallback() { 11 | this.innerHTML = '
  1. iShape
  2. iOverlay
    1. Demo
      1. Stars Rotation
      2. Shapes Editor
      3. Stroke
      4. Outline
      5. Overlay Editor
    2. Performance Comparison
    3. Documentation
      1. Filling Rules
      2. Overlay Rules
      3. Contours
      4. Overlay Graph
      5. Extract Shapes
  3. iTriangle
    1. Demo
      1. Triangulation
      2. Tessellation
    2. Performance Comparison
    3. Delaunay
'; 12 | // Set the current, active page, and reveal it if it's hidden 13 | let current_page = document.location.href.toString(); 14 | if (current_page.endsWith("/")) { 15 | current_page += "index.html"; 16 | } 17 | var links = Array.prototype.slice.call(this.querySelectorAll("a")); 18 | var l = links.length; 19 | for (var i = 0; i < l; ++i) { 20 | var link = links[i]; 21 | var href = link.getAttribute("href"); 22 | if (href && !href.startsWith("#") && !/^(?:[a-z+]+:)?\/\//.test(href)) { 23 | link.href = path_to_root + href; 24 | } 25 | // The "index" page is supposed to alias the first chapter in the book. 26 | if (link.href === current_page || (i === 0 && path_to_root === "" && current_page.endsWith("/index.html"))) { 27 | link.classList.add("active"); 28 | var parent = link.parentElement; 29 | if (parent && parent.classList.contains("chapter-item")) { 30 | parent.classList.add("expanded"); 31 | } 32 | while (parent) { 33 | if (parent.tagName === "LI" && parent.previousElementSibling) { 34 | if (parent.previousElementSibling.classList.contains("chapter-item")) { 35 | parent.previousElementSibling.classList.add("expanded"); 36 | } 37 | } 38 | parent = parent.parentElement; 39 | } 40 | } 41 | } 42 | // Track and set sidebar scroll position 43 | this.addEventListener('click', function(e) { 44 | if (e.target.tagName === 'A') { 45 | sessionStorage.setItem('sidebar-scroll', this.scrollTop); 46 | } 47 | }, { passive: true }); 48 | var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll'); 49 | sessionStorage.removeItem('sidebar-scroll'); 50 | if (sidebarScrollTop) { 51 | // preserve sidebar scroll position when navigating via links within sidebar 52 | this.scrollTop = sidebarScrollTop; 53 | } else { 54 | // scroll sidebar to current active section when navigating via "next/previous chapter" buttons 55 | var activeSection = document.querySelector('#sidebar .active'); 56 | if (activeSection) { 57 | activeSection.scrollIntoView({ block: 'center' }); 58 | } 59 | } 60 | // Toggle buttons 61 | var sidebarAnchorToggles = document.querySelectorAll('#sidebar a.toggle'); 62 | function toggleSection(ev) { 63 | ev.currentTarget.parentElement.classList.toggle('expanded'); 64 | } 65 | Array.from(sidebarAnchorToggles).forEach(function (el) { 66 | el.addEventListener('click', toggleSection); 67 | }); 68 | } 69 | } 70 | window.customElements.define("mdbook-sidebar-scrollbox", MDBookSidebarScrollbox); 71 | -------------------------------------------------------------------------------- /readme/difference_ba.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 40 | 57 | 58 | 60 | 77 | 78 | 82 | 85 | 90 | 95 | 96 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /docs/overlay/overlay_rules/difference_ba.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 40 | 57 | 58 | 60 | 77 | 78 | 82 | 85 | 90 | 95 | 96 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /docs-gen/src/overlay/overlay_rules/difference_ba.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 40 | 57 | 58 | 60 | 77 | 78 | 82 | 85 | 90 | 95 | 96 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 161 | 162 | --------------------------------------------------------------------------------