{"id":28067442,"url":"https://github.com/ManevilleF/hexx","last_synced_at":"2025-05-12T16:01:53.116Z","repository":{"id":65607246,"uuid":"450800670","full_name":"ManevilleF/hexx","owner":"ManevilleF","description":"Hexagonal tools lib in rust","archived":false,"fork":false,"pushed_at":"2025-05-11T11:02:16.000Z","size":15698,"stargazers_count":318,"open_issues_count":9,"forks_count":29,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-11T11:34:16.002Z","etag":null,"topics":["coordinates","game-development","gamedev","geometry","mathematics","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ManevilleF.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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}},"created_at":"2022-01-22T11:41:46.000Z","updated_at":"2025-05-11T11:15:39.000Z","dependencies_parsed_at":"2023-02-22T09:45:49.739Z","dependency_job_id":"78e0ef98-85bb-4ca8-b008-cf2c03d8943c","html_url":"https://github.com/ManevilleF/hexx","commit_stats":{"total_commits":171,"total_committers":10,"mean_commits":17.1,"dds":"0.052631578947368474","last_synced_commit":"166df134e63ac2305c16575b4754ed2c4661d52f"},"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ManevilleF%2Fhexx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ManevilleF%2Fhexx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ManevilleF%2Fhexx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ManevilleF%2Fhexx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ManevilleF","download_url":"https://codeload.github.com/ManevilleF/hexx/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253560888,"owners_count":21927758,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coordinates","game-development","gamedev","geometry","mathematics","rust"],"created_at":"2025-05-12T16:01:26.438Z","updated_at":"2025-05-12T16:01:53.089Z","avatar_url":"https://github.com/ManevilleF.png","language":"Rust","funding_links":[],"categories":["Rust","Misc"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/hexx.png?\" alt=\"Hexx\"\u003e\n\u003c/p\u003e\n\n[![CI](https://img.shields.io/github/check-runs/ManevilleF/hexx/main?style=flat-square\u0026label=CI)](https://github.com/ManevilleF/hexx/actions/workflows/rust.yml)\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue?style=flat-square)](./LICENSE)\n[![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success?style=flat-square)](https://github.com/rust-secure-code/safety-dance/)\n[![Crates.io](https://img.shields.io/crates/v/hexx?style=flat-square)](https://crates.io/crates/hexx)\n[![Downloads](https://img.shields.io/crates/d/hexx?style=flat-square)](https://crates.io/crates/hexx)\n[![Docs.rs](https://img.shields.io/docsrs/hexx?style=flat-square)](https://docs.rs/hexx)\n[![dependency status](https://deps.rs/crate/hexx/0.20.0/status.svg?style=flat-square)](https://deps.rs/crate/hexx)\n\n\u003c!-- cargo-sync-readme start --\u003e\n\n Hexagonal tools lib in rust.\n\n \u003e Inspired by this [`RedBlobGames` article](https://www.redblobgames.com/grids/hexagons/implementation.html)\n \u003e and [Sander Evers](https://sanderevers.github.io/) work\n\n This lib allows you to:\n\n * Manipulate hexagon coordinates\n * Generate hexagonal maps with custom layouts and orientation\n * Generate hexagon meshes (planes or columns)\n\n I made the choice to use *Axial Coordinates* for performance and utility\n reasons, but the [`Hex`](https://docs.rs/hexx/latest/hexx/hex/struct.Hex.html) type has conversion utilities with\n *cubic*, *doubled*, *hexmod* and *offset* coordinates.\n\n \u003e See the [hexagonal coordinate systems](https://www.redblobgames.com/grids/hexagons/#coordinates)\n\n ## Installation\n\n Run `cargo add hexx` in your project or add the following line to your\n `Cargo.toml`:\n\n * `hexx = \"0.20\"`\n\n ### Cargo features\n\n `hexx` provides the following cargo features:\n * `serde`: Enables [serde](https://github.com/serde-rs/serde) support for\n   most types\n * `packed`: Makes [`Hex`](https://docs.rs/hexx/latest/hexx/hex/struct.Hex.html) `repr(C)`, useful to use it\n   accross the FII\n * `bevy`: Enables [Bevy](https://bevyengine.org/) support\n * `bevy_platform`: Enables [Bevy Platform](https://docs.rs/bevy_platform/latest/bevy_platform)\n   for `HashMap`\n * `bevy_reflect`: Enables [Bevy Reflection](https://docs.rs/bevy_reflect/latest/bevy_reflect)\n   for most types\n * `grid`: Enables support for Face/Vertex/Edge [grid handling](https://www.redblobgames.com/grids/parts/#hexagon-coordinates)\n   using `Hex` as Face, `GridVertex` as vertex and `GridEdge` as edge.\n * `algorithms`: Enables the [algorithms](https://docs.rs/hexx/latest/hexx/algorithms/) module with:\n   * Field of Movement\n   * A Star Pathfinding\n   * Field of view\n * `mesh`: Enables procedural mesh generation\n\n _Some features are enabled by default, it is recommended to enable only\n what is needed for your usage_\n\n ## Features\n\n `hexx` provides the [`Hex`](https://docs.rs/hexx/latest/hexx/hex/struct.Hex.html) coordinates with:\n\n * Distances\n * Neighbors and directions\n * Lines\n * Ranges\n * Rings\n * Edges\n * Wedges\n * Spirals\n * Rotation\n * Symmetry\n * Vector operations\n * Conversions to other coordinate systems:\n     * Cubic coordinates\n     * Offset coordinates\n     * Doubled coordinates\n     * Hexmod coordinates\n * Multiple hex resolution\n\n ## Basic usage\n\n```rust\n use hexx::*;\n\n // Declare points in hexagonal spaces\n let point_a = hex(10, -5); // Equivalent of `Hex::new(10, -5)`\n let point_b = hex(-8, 15);\n // Find distance between them\n let dist = point_a.unsigned_distance_to(point_b);\n // Compute a line between points\n let line: Vec\u003cHex\u003e = point_a.line_to(point_b).collect();\n // Compute a ring from `point_a` containing `point_b`\n let ring: Vec\u003cHex\u003e = point_a.ring(dist).collect();\n // Rotate `point_b` around `point_a` by 2 times 60 degrees clockwise\n let rotated = point_b.rotate_cw_around(point_a, 2);\n // Find the direction between the two points\n let dir_a = point_a.main_direction_to(point_b);\n let dir_b = point_b.main_direction_to(point_a);\n assert!(dir_a == -dir_b);\n // Compute a wedge from `point_a` to `point_b`\n let wedge = point_a.wedge_to(point_b);\n // Get the average value of the wedge\n let avg = wedge.average();\n ```\n\n ## Layout usage\n\n [`HexLayout`](https://docs.rs/hexx/latest/hexx/layout/struct.HexLayout.html) is the bridge between your\n world/screen/pixel coordinate system and the hexagonal coordinates system.\n\n```rust\n use hexx::*;\n\n // Define your layout\n let layout = HexLayout {\n     scale: Vec2::new(1.0, 1.0),\n     orientation: HexOrientation::Flat,\n     ..Default::default()\n };\n // Get the hex coordinate at the world position `world_pos`.\n let world_pos = Vec2::new(53.52, 189.28);\n let point = layout.world_pos_to_hex(world_pos);\n // Get the world position of `point`\n let point = hex(123, 45);\n let world_pos = layout.hex_to_world_pos(point);\n ```\n\n ## Wrapping\n\n [`HexBounds`](https://docs.rs/hexx/latest/hexx/bounds/struct.HexBounds.html) defines a bounding hexagon around a\n center coordinate. It can be used for boundary and interesection checks but\n also for wrapping coordinates.\n Coordinate wrapping transform a point outside of the bounds to a point\n inside. This allows for seamless or repeating [wraparound](https://www.redblobgames.com/grids/hexagons/#wraparound)\n maps.\n\n ```rust\n use hexx::*;\n\n let center = hex(23, -45);\n let radius = 5;\n let bounds = HexBounds::new(center, radius);\n let outside_coord = hex(12345, 98765);\n assert!(!bounds.is_in_bounds(outside_coord));\n let wrapped_coord = bounds.wrap(outside_coord);\n assert!(bounds.is_in_bounds(wrapped_coord));\n ```\n\n ## Resolutions and chunks\n\n [`Hex`](https://docs.rs/hexx/latest/hexx/hex/struct.Hex.html) support multi-resolution coordinates.\n In practice this means that you may convert a coordinate to a different\n resolution:\n\n * To a lower resolution, meaning retrieving a *parent* coordinate\n * to a higher resolution, meaning retrieving the center *child* coordinate\n\n Resolutions are abstract, the only useful information is the resolution\n **radius**.\n\n For example, if you use a big grid, with a radius of a 100, you might want\n to split that grid evenly in larger hexagons containing a 10 radius of\n coordinates and maybe do operations locally inside of these chunks.\n\n So instead of using a big range directly:\n\n ```rust\n use hexx::*;\n\n const MAP_RADIUS: u32 = 100;\n\n // Our big grid with hundreds of hexagons\n let big_grid = Hex::ZERO.range(MAP_RADIUS);\n ```\n\n You may define a smaller grid you will then divide to a higher resolution\n\n ```rust\n use hexx::*;\n\n const CHUNK_RADIUS: u32 = 10;\n const MAP_RADIUS: u32 = 20;\n\n let chunks = Hex::ZERO.range(MAP_RADIUS);\n for chunk in chunks {\n     // We can retrieve the center of that chunk by increasing the resolution\n     let center = chunk.to_higher_res(CHUNK_RADIUS);\n     // And retrieve the other coordinates in the chunk\n     let children = center.range(CHUNK_RADIUS);\n     // We can retrieve the chunk coordinates from any coordinate..\n     for coord in children {\n         // .. by reducing the resolution\n         assert_eq!(coord.to_lower_res(CHUNK_RADIUS), chunk);\n     }\n }\n ```\n\n An other usage could be to draw an infinite hex grid, with different\n resolutions displayed, dynamically changing according to user zoom level.\n\n ## Dense map storage\n\n [`Hex`](https://docs.rs/hexx/latest/hexx/hex/struct.Hex.html) implements `Hash`, and most users store hexagonal\n maps in a `HashMap`. But for some cases `hexx` provides *dense storage*\n  [collections](https://docs.rs/hexx/latest/hexx/storage/) with more performant accessors:\n\n - [`HexagonalMap\u003cT\u003e`](https://docs.rs/hexx/latest/hexx/storage/hexagonal/struct.HexagonalMap.html)\n - [`RombusMap\u003cT\u003e`](https://docs.rs/hexx/latest/hexx/storage/rombus/struct.RombusMap.html)\n\n ## Procedural meshes\n\n \u003e Requires the `mesh` feature\n\n `hexx` provides 3 built-in procedural mesh construction utilies:\n - [`PlaneMeshBuilder`](https://docs.rs/hexx/latest/hexx/mesh/plane_builder/struct.PlaneMeshBuilder.html) for\n   hexagonal planes\n - [`ColumnMeshBuilder`](https://docs.rs/hexx/latest/hexx/mesh/column_builder/struct.ColumnMeshBuilder.html)  for\n   hexagonal columns\n - [`HeightMapMeshBuilder`](https://docs.rs/hexx/latest/hexx/mesh/heightmap_builder/struct.HeightMapMeshBuilder.html)\n   for hexagonal height maps\n\n All those builders have a lot of customization options and will output a\n [`MeshInfo`](https://docs.rs/hexx/latest/hexx/mesh/struct.MeshInfo.html) struct containing vertex positions,\n normals and uvs\n\n ### Usage in [Bevy](https://bevyengine.org/)\n\n If you want to integrate the procedural meshes in [bevy](bevyengine.org) you\n may do it this way:\n\n```rust\n use bevy::{\n     prelude::Mesh,\n     render::{\n         mesh::Indices, render_asset::RenderAssetUsages, render_resource::PrimitiveTopology,\n     },\n };\n use hexx::MeshInfo;\n\n pub fn hexagonal_mesh(mesh_info: MeshInfo) -\u003e Mesh {\n     Mesh::new(\n         PrimitiveTopology::TriangleList,\n         // Means you won't interact with the mesh on the CPU afterwards\n         // Check bevy docs for more information\n         RenderAssetUsages::RENDER_WORLD,\n     )\n     .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, mesh_info.vertices)\n     .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, mesh_info.normals)\n     .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, mesh_info.uvs)\n     .with_inserted_indices(Indices::U16(mesh_info.indices))\n }\n ```\n\n\u003c!-- cargo-sync-readme end --\u003e\n\n\u003e See the [examples](examples) for bevy usage\n\n## Q\u0026A\n\n\u003e Why not derive `PartialOrd, Ord` on `Hex` ?\n\nAdding these traits to `Hex` would mean to define an absolute rule on how to solve\nthis:\n\n```rust\nlet a = hex(-10, 20);\nlet b = hex(1, 2);\na \u003e b\n```\n\nDepending on how you consider this there are at least 3 possible rules:\n\n* `a.y` is greater than `b.y` so it's `true`\n* `a.x` is lower than `b.x` so it's `false`\n* `a`'s length is greater than `b`'s so it's `true`\n\n\u003e What if I want to use it in a `BtreeMap`, `BTreeSet` or `BinaryHeap` ?\n\nUse a wrapper with the `Ord` and `PartialOrd` trait. You can copy and paste this\ncode snippet into your project:\n\n```rust\n/// [`Ordering`] wrapper around [`Hex`], comparing [`Hex::y`] then [`Hex::x`].\n#[derive(Debug, Clone, Copy, PartialEq, Eq)]\npub struct OrdByYX(pub Hex);\n\nimpl Ord for OrdByYX {\n    fn cmp(\u0026self, other: \u0026Self) -\u003e Ordering {\n        self.0.y.cmp(\u0026other.0.y).then(self.0.x.cmp(\u0026other.0.x))\n    }\n}\n\nimpl PartialOrd for OrdByYX {\n    fn partial_cmp(\u0026self, other: \u0026Self) -\u003e Option\u003cOrdering\u003e {\n        Some(self.cmp(other))\n    }\n}\n```\n\n## Examples\n\n`hexx` provides interactive examples showcasing various features:\n\n### Hex grid\n\n![hex_grid](docs/hex_grid.png \"hex grid example\")\n\n\u003e `cargo run --example hex_grid`\n\nThis example showcases hex ranges, rings, wedges, rotation, and lines\n\n### Hex Area\n\n![hex_grid](docs/hex_area.png \"hex area example\")\n\n\u003e `cargo run --example hex_area`\n\nThis example showcases how to generate hexagonal areas using grid utilities and gizmos\nand how to use two layouts on the same grid.\n\n### Scroll Map\n\n![scroll_map](docs/scroll_map.gif \"scroll map example\")\n\n\u003e `cargo run --example scroll_map`\n\nThis example showcases the `HexMap` struct for scrolling maps\n\n### Wrap Map\n\n![wrap_map](docs/wrap_map.gif \"wrap map example\")\n\n\u003e `cargo run --example wrap_map`\n\nThis example showcases the `HexMap` struct for looping/wrapping map\n\n### A Star pathfinding\n\n![a_star](docs/a_star.png \"A star example\")\n\n\u003e `cargo run --example a_star`\n\nThis example showcases the A star algorithm, with an interactive pathfinding\nbetween the origin and your cursor. Clicking on tile toggles their availability\n\n### Field of view\n\n![fov](docs/fov.png \"Field of View example\")\n\n\u003e `cargo run --example field_of_view`\n\nThis example showcases the FOV algorithm, with an interactive range fov around\nyour cursor.\nClicking on tile toggles their visibility.\n\n### Field of movement\n\n![fov](docs/field_of_movement.gif \"Field of movement example\")\n\n\u003e `cargo run --example field_of_movement`\n\nThis example showcases the field of movement algorithm, interactively displaying\nthe accessible range of movement around the cursor.\n\n### 3d columns\n\n![columns](docs/3d_columns.png \"3d columns example\")\n\n\u003e `cargo run --example 3d_columns`\n\nThis example showcases the 3d hexagon columns procedural generation\n\n### 3d picking\n\n![picking](docs/3d_picking.png \"3d picking example\")\n\n\u003e `cargo run --example 3d_picking`\n\nThis example showcases how to use the camera ray to detect hovered 3d columns\n\n### Mesh builder\n\n![mesh](docs/mesh_builder.png \"Mesh builder example\")\n\n\u003e `cargo run --example mesh_builder --features bevy_reflect`\n\nThis example showcases the hexagon columns procedural generation customization options\n\n### Height Map Mesh builder\n\n![mesh](docs/heightmap_builder.png \"Height Map Mesh builder example\")\n\n\u003e `cargo run --example heightmap_builder --features bevy_reflect`\n\nThis example showcases the hexagon 3D height map procedural generation customization options\n\n### Chunks\n\n![chunks](docs/chunks.png \"Chunks example\")\n\n\u003e `cargo run --example chunks`\n\nThis example showcases the hexagon resolution system, allowing to tile coordinates\nin evenly sized chunks\n\n### Dynamic resolutions\n\n![chunks](docs/resolutions.png \"Resolutions example\")\n\n\u003e `cargo run --example resolutions --feature bevy_reflect`\n\nThis example showcases the hexagon resolution system, with multiple configurable\nchunk sizes and dynamic visualization\n\n### Merged Chunks\n\n![merged_chunks](docs/merged_columns.png \"Merged Chunks example\")\n\n\u003e `cargo run --example merged_columns --features bevy_reflect`\n\nThis example showcases how to build a simple hex chunk system with each chunk\nbeing a single mesh\n\n### Sprite Sheet\n\n![sprite_sheet](docs/sprite_sheet.png \"Sprite Sheet example\")\n\n\u003e `cargo run --example sprite_sheet`\n\nThis example showcases how to use hexx with 2D sprite sheet.\n\n### Shapes\n\n![shapes](docs/shapes.png \"Shapes example\")\n\n\u003e `cargo run --example shapes --features bevy_reflect`\n\nThis example showcases how to use hexx shapes module\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FManevilleF%2Fhexx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FManevilleF%2Fhexx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FManevilleF%2Fhexx/lists"}