[−][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:
- Convert the list of points to a list of segments, tracking whether they are blank or lit.
- Convert the segments to a graph where the nodes are points. Only a single node for each unique position is stored.
- Convert the point graph to a euler graph, determining the minimum number of blanks necessary to do so.
- Find the optimal euler circuit within the euler graph. This represents the new path that the LASER should travel.
- 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:
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.
Re-exports
pub use petgraph::Incoming; |
pub use petgraph::Outgoing; |
Structs
EdgeProfile | Capture a profile of each edge to assist the interpolation process. |
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
Direction | Edge direction. |
EdgeProfileKind | Edge profile data specific to the kind of edge. |
SegmentKind | describes whether a line segment between two points is blank or not. |
Constants
BLANK_MIN_POINTS | For the blank ab: |
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_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). |
ec_edge_end | Given some Euler Circuit edge |
ec_edge_start | Given some Euler Circuit edge |
euler_circuit_to_segments | Produce an iterator yielding |
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 |
interpolate_path | The same as |
interpolate_profiled_path | Interpolate the path described by the given |
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. |
profile_path | Traverse a path described by an iterator yielding edges, profiling the edges along the way. |
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 an 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. |