{"id":33922646,"url":"https://github.com/radevgit/nfp","last_synced_at":"2025-12-12T09:07:36.291Z","repository":{"id":323125882,"uuid":"1092181122","full_name":"radevgit/nfp","owner":"radevgit","description":"No Fit Polygon","archived":false,"fork":false,"pushed_at":"2025-11-08T07:45:16.000Z","size":7,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-08T09:15:33.543Z","etag":null,"topics":["collision","collision-detection","nfp","no-fit-polygon"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/radevgit.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-08T06:21:57.000Z","updated_at":"2025-11-08T07:46:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/radevgit/nfp","commit_stats":null,"previous_names":["radevgit/nfp"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/radevgit/nfp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radevgit%2Fnfp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radevgit%2Fnfp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radevgit%2Fnfp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radevgit%2Fnfp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/radevgit","download_url":"https://codeload.github.com/radevgit/nfp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radevgit%2Fnfp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27679837,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-12T02:00:06.775Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["collision","collision-detection","nfp","no-fit-polygon"],"created_at":"2025-12-12T09:07:34.913Z","updated_at":"2025-12-12T09:07:36.281Z","avatar_url":"https://github.com/radevgit.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NFP - No Fit Polygon\n\n[![Crates.io](https://img.shields.io/crates/v/nfp.svg?color=blue)](https://crates.io/crates/nfp)\n[![Documentation](https://docs.rs/nfp/badge.svg)](https://docs.rs/nfp)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n\nA Rust library for computing the No Fit Polygon (Minkowski sum) of two convex polygons for nesting and packing optimization.\n\n## What is NFP?\n\nThe No Fit Polygon defines the forbidden region where one polygon cannot be placed relative to another without collision. When polygon B's origin is **outside** the NFP, the polygons do **not** overlap. When it's **inside**, they **do** collide.\n\n## Installation\n\nAdd this to your `Cargo.toml`:\n\n```toml\n[dependencies]\nnfp = \"0.3\"\n```\n\n## Quick Start\n\n```rust\nuse nfp::prelude::*;\n\n// Two convex polygons at origin (CCW orientation)\nlet square_a = vec![\n    point(0.0, 0.0),\n    point(10.0, 0.0),\n    point(10.0, 10.0),\n    point(0.0, 10.0),\n];\n\nlet square_b = vec![\n    point(0.0, 0.0),\n    point(5.0, 0.0),\n    point(5.0, 5.0),\n    point(0.0, 5.0),\n];\n\n// Compute NFP\nmatch NFPConvex::nfp(\u0026square_a, \u0026square_b) {\n    Ok(nfp) =\u003e {\n        println!(\"NFP has {} vertices\", nfp.len());\n        // Now use NFP for collision detection:\n        // point inside NFP → collision, point outside → no collision\n    }\n    Err(e) =\u003e eprintln!(\"Error: {}\", e),\n}\n```\n\n## Collision Detection\n\nOnce you have the NFP, detect collisions by testing if B's origin is inside or outside:\n\n```rust\nuse nfp::prelude::*;\n\nfn point_in_polygon(pt: Point, polygon: \u0026[Point]) -\u003e bool {\n    let mut inside = false;\n    let mut p1 = polygon[polygon.len() - 1];\n    for p2 in polygon {\n        if ((p2.y \u003e pt.y) != (p1.y \u003e pt.y))\n            \u0026\u0026 (pt.x \u003c (p1.x - p2.x) * (pt.y - p2.y) / (p1.y - p2.y) + p2.x)\n        {\n            inside = !inside;\n        }\n        p1 = *p2;\n    }\n    inside\n}\n\n// Compute NFP first\nlet square_a = vec![point(0.0, 0.0), point(10.0, 0.0), point(10.0, 10.0), point(0.0, 10.0)];\nlet square_b = vec![point(0.0, 0.0), point(5.0, 0.0), point(5.0, 5.0), point(0.0, 5.0)];\nlet nfp = NFPConvex::nfp(\u0026square_a, \u0026square_b).unwrap();\n\n// Check if placing B at (15.0, 15.0) causes collision\nlet test_position = point(15.0, 15.0);\nif point_in_polygon(test_position, \u0026nfp) {\n    println!(\"Collision detected!\");\n} else {\n    println!(\"Safe placement\");\n}\n```\n\n## Requirements\n\n- Both input polygons **must be convex**\n- Both polygons must have **at least 3 vertices**\n- Polygons should be in **counter-clockwise (CCW) orientation** \n- Polygons must be **closed** (last point connects to first conceptually)\n\n## API Reference\n\n`NFPConvex::nfp(poly_a, poly_b) -\u003e Result\u003cVec\u003cPoint\u003e, NfpError\u003e`\n\nComputes the No Fit Polygon for two convex polygons using Minkowski sum.\n\nArguments:\n- `poly_a` - First convex polygon as slice of points\n- `poly_b` - Second convex polygon as slice of points\n\nReturns:\n- `Ok(Vec\u003cPoint\u003e)` - NFP as counter-clockwise convex polygon\n- `Err(NfpError)` - If input validation fails\n\nTime Complexity: O(n·m log(n·m)) where n = |A| vertices, m = |B| vertices\n\n`NfpError`\n\nError enumeration for NFP operations.\n\nVariants:\n- `EmptyPolygon` - One or both input polygons are empty\n- `InsufficientVertices` - One or both polygons have fewer than 3 vertices\n\n**Example:**\n```rust\nuse nfp::prelude::*;\n\nmatch NFPConvex::nfp(\u0026a, \u0026b) {\n    Ok(nfp) =\u003e { /* use nfp */ }\n    Err(NfpError::EmptyPolygon) =\u003e eprintln!(\"Empty polygon provided\"),\n    Err(NfpError::InsufficientVertices) =\u003e eprintln!(\"Polygon needs ≥3 vertices\"),\n}\n```\n\n`Point`\n\n2D coordinate point from the `togo` geometry library.\n\nFields:\n- `x: f64` - X coordinate\n- `y: f64` - Y coordinate\n\n`point(x, y) -\u003e Point`\n\nHelper function to create a new Point.\n\n```rust\nuse nfp::prelude::*;\n\nlet p = point(1.5, 2.5);\nassert_eq!(p.x, 1.5);\nassert_eq!(p.y, 2.5);\n```\n\n\n## Algorithm\n\nThe implementation uses the **Minkowski Sum via Vertex Combinations**:\n\n1. Validate inputs (non-empty, convex, ≥3 vertices)\n2. Ensure counter-clockwise orientation\n3. Negate polygon B (reflection through origin)\n4. Generate all vertex sum combinations: {a + b | a ∈ A, b ∈ -B}\n5. Compute convex hull of sum points using Graham scan\n6. Return convex hull boundary as NFP\n\n## Limitations\n\n- Current version supports **Convex polygons only**\n\n\n## References\n\n- Minkowski sum: https://en.wikipedia.org/wiki/Minkowski_addition\n- No-Fit Polygon: https://en.wikipedia.org/wiki/No-fit_polygon\n- Graham scan: https://en.wikipedia.org/wiki/Graham_scan\n\n## Related Projects\n\nNFP is part of the [Nest2D](https://nest2d.com) collection of nesting and packing tools.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradevgit%2Fnfp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fradevgit%2Fnfp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradevgit%2Fnfp/lists"}