Skip to main content

Crate ezpz

Crate ezpz 

Source
Expand description

§Ezpz

This is a 2D constraint solver, for use in CAD or graphics applications.

§Usage

use ezpz::{Config, solve, Constraint, ConstraintRequest, datatypes::inputs::DatumPoint, IdGenerator};

// Define the geometry.
// These entities don't have known positions or dimensions yet, the solver
// will place them for us.
let mut ids = IdGenerator::default();
let p = DatumPoint::new(&mut ids);
let q = DatumPoint::new(&mut ids);

// Define constraints on the geometry.
// These could constraint the entities themselves
// (e.g. the position of a point or the radius of a circle),
// or their relationship to each other
// (e.g. these two lines must be parallel, or this point must lie on this arc).
let requests = [
    // Fix P to the origin
    ConstraintRequest::highest_priority(Constraint::Fixed(p.id_x(), 0.0)),
    ConstraintRequest::highest_priority(Constraint::Fixed(p.id_y(), 0.0)),
    // P and Q should be 4 units apart.
    ConstraintRequest::highest_priority(Constraint::Distance(p, q, 4.0)),
];

// Provide some initial guesses to the solver for their locations.
let initial_guesses = vec![
    (p.id_x(), 0.0),
    (p.id_y(), -0.02),
    (q.id_x(), 4.39),
    (q.id_y(), 4.38),
];

// Run the solver!
let outcome = solve(
    &requests,
    initial_guesses,
    // You can customize the config, but for this example, we'll just use the default.
    Config::default(),
);

// Check the outcome.
match outcome {
  Ok(solution) => {
    // If you give incompatible constraints, then your constraints cannot possibly
    // be satisfied. But in this example, there should be a solution.
    assert!(solution.is_satisfied());
    assert!(solution.unsatisfied().is_empty());
    let solved_p = solution.final_value_point(&p);
    let solved_q = solution.final_value_point(&q);
    println!("P = ({}, {})", solved_p.x, solved_p.y);
    println!("Q = ({}, {})", solved_q.x, solved_q.y);
  }
  Err(e) => {
    eprintln!("ezpz could not solve this constraint system: {}", e.error);
  }
}

§Constraint problem files

ezpz defines a text format for writing out constraint problems. You don’t have to use this format – you can use the Rust library directly – but it’s a very convenient format. It looks like this:

# constraints
point p
point q
p.x = 0
p.y = 0
q.y = 0
vertical(p, q)

# guesses
p roughly (3, 4)
q roughly (5, 6)

There’s two sections, Constraints and Guesses. You define each point (like p and q) and once defined, you can write constraints that use them. For example, you can fix a point’s X or Y component (p.x = 0). Or you can relate two points, e.g. vertical(p, q).

For more examples, see the test_cases/ directory.

Modules§

datatypes
Geometric data (lines, points, etc).
textual
Parser for textual representation of these problems.

Structs§

Config
Configuration for how to solve a system.
ConstraintRequest
A constraint that EZPZ should solve for.
FailureOutcome
Returned when ezpz could not solve a system.
FreedomAnalysis
Results from analyzing the freedom of each variable. Created from crate::solve_analysis.
IdGenerator
Generates an incrementing sequence of IDs starting from 0.
SolveOutcome
Data from a successful solved system.
SolveOutcomeFreedomAnalysis
Just like SolveOutcome except it also contains the result of expensive numeric analysis on the final solved system. Created from crate::solve_analysis.
Warning
Something bad that users should know about.

Enums§

Constraint
Each geometric constraint we support.
NonLinearSystemError
Errors that could occur when running the core Newton-Gauss solve.
TextualError
Errors from parsing and executing ezpz’s textual representation.
WarningContent
What went wrong, or should be done differently.

Functions§

solve
Given some initial guesses, constrain them. Returns the same variables in the same order, but constrained.
solve_analysis
Just like solve except it also does some expensive analysis steps at the end. This lets it calculate helpful data for the user, like degrees of freedom. Should not be called on every iteration of a system when you change the initial values! Just call this when you change the constraint structure.

Type Aliases§

Id
The ID of a variable which could be constrained, whose value could be found by ezpz.