[][src]Crate lasy

A small library dedicated to LASER path optimisation.

The goal for the library is to provide a suite of useful tools for optimising linear vector images for galvanometer-based LASER projection. To allow lasy LASERs to get more done.

This crate implements the full suite of optimisations covered in Accurate and Efficient Drawing Method for Laser Projection by Purkhet Abderyim et al. These include Graph optimisation, draw order optimisation, blanking delays and sharp angle delays. See the paper for more details.

Optimising a Vector Image

Optimising a single frame of input_points is achieved by the following steps:

  1. Convert the list of points to a list of segments, tracking whether they are blank or lit.
  2. Convert the segments to a graph where the nodes are points. Only a single node for each unique position is stored.
  3. Convert the point graph to a euler graph, determining the minimum number of blanks necessary to do so.
  4. Find the optimal euler circuit within the euler graph. This represents the new path that the LASER should travel.
  5. Interpolate the euler circuit. This step will attempt to distribute the "target count" number of points across the euler circuit while accounting for blanking and sharp angle delays in accordance with the provided configuration.

In code, these steps look like so:

This example is not tested
let segs = points_to_segments(&input_points);
let pg = segments_to_point_graph(&input_points, segs);
let eg = point_graph_to_euler_graph(&pg);
let ec = euler_graph_to_euler_circuit(&input_points, &eg);
let output_points = interpolate_euler_circuit(&input_points, &ec, &eg, target_count, config);

Optimising Animation

It is worth keeping in mind that, if you are working with an animated stream of frames, some consideration must be taken in how to move from the end of one frame to the beginning of the next.

For the most part, this simply requires blanking from the last point of the previous frame to the first point of the current one (or in other words, the first point of the euler circuit for the current frame).

The blank_segment_points function can be useful for generating these points, as this same function is used for generating blank segment points during interpolation.

Point Types

In order to have your points be compatible with the functions provided by this crate, the Position, IsBlank, Weight, Blanked and Lerp traits should be implemented as necessary. Please see their respective documentation for more information.

Note that the optimisation steps above are intended to work with two different point types: an input point type describing the user's original frame and an output (or raw) point type representing the fully interpolated, optimised path. The main difference between these two types is that the output point type does not to store its weight, as point weighting is applied during the interpolation process. See the Weight docs for more details.

Graph Storage

The graphs used within the optimisation steps above will never store points directly, and instead will store indices into the original slice of input_points. This allows for a smaller memory footprint and to avoid complicated generics propagating up through the graph types.

Structs

InterpolationConfig

Configuration options for eulerian circuit interpolation.

Segment

Represents a line segment over which the laser scanner will travel.

Segments

An iterator yielding all lit line segments.

Enums

SegmentKind

describes whether a line segment between two points is blank or not.

Constants

BLANK_MIN_POINTS

For the blank ab: [a, a.blanked(), b.blanked(), (0..delay).map(|_| b.blanked())].

Traits

Blanked

Point types that can produce a blanked copy of themselves.

IsBlank

Point types that can describe whether or not they are blank (black).

Lerp

Types that can be linearly interpolated.

Position

Point types that may describe position.

Weight

Point types that have a weight associated with them.

Functions

blank_segment_point_count

The number of points used per blank segment given the blank_delay_points from a config.

blank_segment_points

Returns the points used to blank between two given lit points a and b.

corner_point_count

The number of points added at a lit corner given its angle and angular delay rate.

distance_min_point_count

The minimum points for traversing a lit segment (not including end corner delays).

euler_graph_to_euler_circuit

Given a Euler Graph describing the vector image to be drawn, return the optimal Euler Circuit describing the path over which the laser should travel.

interpolate_euler_circuit

Interpolate the given EulerCircuit with the given configuration in order to produce a path ready to be submitted to the DAC.

lit_segment_min_point_count

The minimum number of points used for a lit segment of the given distance and end angle.

lit_segment_points

Returns the points that make up a lit segment between a and b including delay for the end corner.

point_graph_to_euler_graph

Convert a point graph to a euler graph.

points_to_segments

Create an iterator yielding segments from an iterator yielding points.

segments_to_point_graph

Convert the given laser frame vector segments to a graph of points.

Type Definitions

EulerCircuit

A type used to represent a eulerian circuit through a eulerian graph.

EulerGraph

A type used to represent a graph of points that contains at least one euler circuit.

PointGraph

A type used to represent graph describing the points in a frame and how they are joined.

PointIndex

An index into a slice of points.