plexus 0.0.5

3D mesh generation and manipulation.
Documentation
![Plexus](https://raw.githubusercontent.com/olson-sean-k/plexus/master/doc/plexus.png)

**Plexus** is a Rust library for generating and manipulating 3D meshes.

[![Build Status](https://travis-ci.org/olson-sean-k/plexus.svg?branch=master)](https://travis-ci.org/olson-sean-k/plexus)
[![Build Status](https://ci.appveyor.com/api/projects/status/0uy6rcg3tvbu6cms?svg=true)](https://ci.appveyor.com/project/olson-sean-k/plexus)
[![Documentation](https://docs.rs/plexus/badge.svg)](https://docs.rs/plexus)
[![Crate](https://img.shields.io/crates/v/plexus.svg)](https://crates.io/crates/plexus)

## Generation and Iterator Expressions

Meshes can be generated from primitives like cubes and spheres using iterator
expressions. Primitives emit topological structures like `Triangle`s or
`Quad`s, which contain arbitrary geometric data in their vertices. These can be
transformed and decomposed into other topologies and geometric data via
triangulation, tesselation, and conversion into rendering pipeline data.

```rust
use nalgebra::Point3;
use plexus::buffer::MeshBuffer;
use plexus::generate::sphere;
use plexus::prelude::*;

// Example module in the local crate that provides basic rendering.
use render::{self, Color, Vertex};

// Construct a buffer of index and vertex data from a sphere primitive.
let buffer = sphere::UVSphere::<f32>::with_unit_radius(16, 16)
    .polygons_with_position()
    .map_vertices(|position| -> Point3<_> { position.into() })
    .map_vertices(|position| position * 10.0)
    .map_vertices(|position| Vertex::new(position, Color::white()))
    .collect::<MeshBuffer<u32, Vertex>>();
render::draw(buffer.as_index_slice(), buffer.as_vertex_slice());
```

## Half-Edge Graph Meshes

Generators are flexible and easy to use, but only represent vertex geometry and
are difficult to query and manipulate. A `Mesh`, represented as a [half-edge
graph](https://en.wikipedia.org/wiki/doubly_connected_edge_list), supports
arbitrary geometry for vertices, edges, and faces. The graph can also be
queried and manipulated in ways that generators and iterator expressions
cannot.

```rust
use nalgebra::Point3;
use plexus::generate::sphere;
use plexus::graph::Mesh;
use plexus::prelude::*;

// Construct a mesh from a sphere primitive. The vertex geometry is convertible
// to `Point3` via the `FromGeometry` trait in this example.
let mut mesh = sphere::UVSphere::<f32>::with_unit_radius(8, 8)
    .polygons_with_position()
    .map_vertices(|position| position.into_hash())
    .collect::<Mesh<Point3<f32>>>();
// Extrude a face in the mesh.
let key = mesh.faces().nth(0).unwrap().key();
let face = mesh.face_mut(key).unwrap().extrude(1.0).unwrap();
```

## Geometric Traits

Meshes support arbitrary geometry via optional traits. Implementing these
traits allows more operations to be supported, but only two basic traits are
required: `Geometry` and `Attribute`.

```rust
use nalgebra::{Point3, Vector3};
use plexus::geometry::{Attribute, Geometry};
use plexus::geometry::convert::AsPosition;

#[derive(Clone, Copy)]
pub struct VertexGeometry {
    pub position: Point3<f32>,
    pub normal: Vector3<f32>,
}

impl Attribute for VertexGeometry {}

impl Geometry for VertexGeometry {
    type Vertex = Self;
    type Edge = ();
    type Face = ();
}

impl AsPosition for VertexGeometry {
    type Target = Point3<f32>;

    fn as_position(&self) -> &Self::Target {
        &self.position
    }

    fn as_position_mut(&mut self) -> &mut Self::Target {
        &mut self.position
    }
}
```

Geometric traits are optionally implemented for types in the
[nalgebra](https://crates.io/crates/nalgebra) and
[cgmath](https://crates.io/crates/cgmath) crates so that common types can be
used right away for vertex geometry.

## Hashing Floating-Point Values

When collecting an iterator expression into a graph or buffer, an indexer is
used to transform the geometry into raw buffers. `HashIndexer` is fast and
reliable, and is used by `collect` (which can be overridden via
`collect_with_indexer`). However, geometry often contains floating point
values, which do not implement `Hash`. An `LruIndexer` can also be used, but
can be slower and requires a sufficient capacity to work correctly.

The [ordered-float](https://crates.io/crates/ordered-float) crate is used by
the `ordered` module to ease this problem. Common geometric types implement
traits that provide conversions to and from a conjugate type that implements
`Hash` (via the `into_hash` and `from_hash` functions). Some geometric types
can be constructed from these conjugate types, as seen in the `Mesh` example.

The `ordered` module also exposes some hashing functions for floating point
primitives, which can be used to directly implement `Hash`. With the
[derivative](https://crates.io/crates/derivative) crate, floating point fields
can be hashed using one of these functions while deriving `Hash`. The `Vertex`
type used in the above example could be defined as follows:

```rust
use plexus::ordered;

#[derive(Derivative)]
#[derivative(Hash)]
pub struct Vertex {
    #[derivative(Hash(hash_with = "ordered::hash_float_array"))]
    pub position: [f32; 3],
    ...
}
```