///|
fn report(
name : String,
result : Result[@sketch.Solution, @sketch.SketchError],
) -> @sketch.Solution? {
match result {
Err(e) => {
println("\{name}: input error: \{e.message()}")
None
}
Ok(s) => {
let r = s.report
let status = match r.status {
Satisfied => "satisfied"
Stalled => "stalled"
IterationLimit => "iteration limit"
}
println(
"\{name}: \{status}; local DOF=\{r.local_dof}; iterations=\{r.iterations}; max tolerance ratio=\{r.max_tolerance_ratio}",
)
Some(s)
}
}
}
///|
fn rectangle() -> Unit {
let s = @sketch.Sketch::new()
let a = s.add_point(0.2, -0.1)
let b = s.add_point(9.5, 0.4)
let c = s.add_point(10.8, 5.4)
let d = s.add_point(-0.3, 6.3)
let ab = s.add_line(a, b)
let bc = s.add_line(b, c)
let cd = s.add_line(c, d)
let da = s.add_line(d, a)
s.constrain(Fix(a, 0.0, 0.0)) |> ignore
s.constrain(Horizontal(ab)) |> ignore
s.constrain(Horizontal(cd)) |> ignore
s.constrain(Vertical(bc)) |> ignore
s.constrain(Vertical(da)) |> ignore
let width = s.constrain(DistanceX(a, b, 10.0))
s.constrain(DistanceY(b, c, 6.0)) |> ignore
match report("rectangle 10x6", s.solve_and_apply()) {
Some(r) =>
for p in [a, b, c, d] {
let point = r.point(p).unwrap()
println(" (\{point.x}, \{point.y})")
}
None => ()
}
s.set_constraint(width, DistanceX(a, b, 15.0)) |> ignore
report("rectangle resized to 15x6", s.solve_and_apply()) |> ignore
}
///|
fn triangle() -> Unit {
let s = @sketch.Sketch::new()
let a = s.add_point(0.0, 0.0)
let b = s.add_point(4.5, 0.3)
let c = s.add_point(2.0, 2.2)
s.constrain(Fix(a, 0.0, 0.0)) |> ignore
s.constrain(Horizontal(s.add_line(a, b))) |> ignore
s.constrain(Distance(a, b, 5.0)) |> ignore
s.constrain(Distance(a, c, 3.0)) |> ignore
s.constrain(Distance(b, c, 4.0)) |> ignore
match report("3-4-5 triangle", s.solve()) {
Some(r) => {
let p = r.point(c).unwrap()
println(" expected C=(1.8, 2.4); actual C=(\{p.x}, \{p.y})")
}
None => ()
}
}
///|
fn tangent() -> Unit {
let s = @sketch.Sketch::new()
let a = s.add_point(0.0, 0.0)
let b = s.add_point(4.0, 1.0)
let c = s.add_circle(a, 2.5)
let d = s.add_circle(b, 1.5)
s.constrain(Fix(a, 0.0, 0.0)) |> ignore
s.constrain(DistanceY(a, b, 0.0)) |> ignore
s.constrain(Radius(c, 3.0)) |> ignore
s.constrain(Radius(d, 2.0)) |> ignore
s.constrain(ExternalTangent(c, d)) |> ignore
report("externally tangent circles", s.solve()) |> ignore
}
///|
fn impossible() -> Unit {
let s = @sketch.Sketch::new()
let p = s.add_point(0.0, 0.0)
s.constrain(Fix(p, 0.0, 0.0)) |> ignore
s.constrain(Fix(p, 10.0, 0.0)) |> ignore
match report("contradictory positions", s.solve()) {
Some(r) =>
for residual in r.report.unsatisfied() {
println(
" constraint \{residual.id.index()}: length error=\{residual.length_error}",
)
}
None => ()
}
}
///|
fn main {
rectangle()
triangle()
tangent()
impossible()
}