(* This file contains procedures to test the qualitative performance of the constraint solver. In particular, it can be used to demonstrate that the use of the Gram-Schmidt algorithm to compute an orthonormal basis and thereby determine the smallest Newton step at each iteration in the underconstrained case is important to achieving intuitive performance. When run, each of the test procedures below shows the solutions found by the constraint solver when a point is constrained to lie on a particular geometric object (a line, circle, ellipse, Bezier curve, or rectangle, respectively). In each figure "NumPts" points around a circle of radius "Rad" are used as the hints for the constraint solver. For each point on the circle, an arrow is drawn from the hint location to the solution produced by the solver. *) CONST Rad = 2 * Unit.In, NumPts = 41, DeltaT = 2 * Math.Pi / NumPts, ArrowSize = 10; PROC DrawAnnotations(a) IS SAVE PS IN Arrow.SetSize(ArrowSize); PtLabel.SetDotSize(4); PtLabel.None(a); Circle.Draw(a, R2.Plus(a, (Rad, 0))); PS.SetColor(Color.Grey50); PS.Stroke() END END; PROC Test(a, cl) IS DrawAnnotations(a); SAVE PS IN VAR t = 0, p0 IN DO t < 2 * Math.Pi -> p0 := R2.Plus(a, R2.Times(Rad, (COS(t), SIN(t)))); APPLY(cl, p0); PS.Stroke(); t := t + DeltaT OD END END END; PROC DirLine(a, b) IS VAR c IN c := Geometry.Mid(a, b); IF Geometry.Dist(a, c) > ArrowSize -> Arrow.Straight(a, c) | Line.Draw(a, c) FI; Line.Draw(c, b); PS.Stroke() END END; PROC FailPoint(a) IS SAVE PS IN PS.SetColor(Color.Red); PtLabel.None(a) END END; PROC CircleProc(a, b, p0) IS IF VAR p ~ p0 IN (b, a) CONG (a, p) -> DirLine(p0, p) END | FailPoint(p0) FI END; PROC EllipseProc(a, b, c, p0) IS IF VAR p ~ p0 IN Ellipse.On(p, a, b, c) -> DirLine(p0, p) END | FailPoint(p0) FI END; PROC LineProc(a, b, p0) IS IF VAR p ~ p0 IN Geometry.Colinear(a, b, p) -> DirLine(p0, p) END | FailPoint(p0) FI END; PROC BezierProc(a, b, c, d, p0) IS IF VAR p ~ p0 IN Bezier.On(p, a, b, c, d) -> DirLine(p0, p) END | FailPoint(p0) FI END; PROC RectProc(a, b, p0) IS IF VAR p1 = Rect.OnCHint(a, b, p0), p ~ p1, c = (-1, 0) REL (a, b) IN Rect.On(p, c, b) -> Line.Draw(p0, p1); DirLine(p1, p) END | FailPoint(p0) FI END; PROC LineTest(a, b) IS SAVE PS IN Test(a, CLOSE(LineProc, a, b)); PS.MoveTo((-1, 0) REL (a, b)); PS.LineTo((1, 0) REL (a, b)); PS.SetWidth(3); PS.Stroke() END END; UI PointTool(LineTest); PROC CircleTest(a, b) IS SAVE PS IN Test(a, CLOSE(CircleProc, a, b)); Circle.Draw(a, b); PS.SetWidth(3); PS.Stroke() END END; UI PointTool(CircleTest); PROC EllipseTest(a, b, c) IS SAVE PS IN Test(a, CLOSE(EllipseProc, a, b, c)); Ellipse.Draw(a, b, c); PS.SetWidth(3); PS.Stroke() END END; UI PointTool(EllipseTest); PROC BezierTest(a, b, c, d, e) IS SAVE PS IN Test(a, CLOSE(BezierProc, b, c, d, e)); PS.MoveTo(b); PS.CurveTo(c, d, e); PS.SetWidth(3); PS.Stroke() END END; UI PointTool(BezierTest); PROC RectTest(a, b) IS SAVE PS IN Test(a, CLOSE(RectProc, a, b)); Rect.DrawC(a, b); PS.SetWidth(3); PS.Stroke() END END; UI PointTool(RectTest); PROC LineTests() IS IF VAR a = (-14.39, 210.1), b ~ (134.1, 357.2), c ~ (-14.39, -151.7), d ~ (11.36, -306.4) IN a VER c -> LineTest(a, b); LineTest(c, d) END FI END; UI Template(LineTests); PROC CircleTests() IS IF VAR a = (3.787, 173.7), b = (184, 165.4), c = (3.787, -192.7), d = (49.23, -175.2) IN a VER c -> CircleTest(a, b); CircleTest(c, d) END FI END; UI Template(CircleTests); PROC EllipseTests() IS IF VAR a = (-4.544, 185.1), b ~ (30.3, 105.4), c ~ (34.08, 191.9), d ~ (-4.544, -182), e ~ (141.6, -317.8), f ~ (29.54, -147.9) IN a VER d -> EllipseTest(a, b, c); EllipseTest(d, e, f) END FI END; UI Template(EllipseTests); PROC BezierTests() IS VAR a = (-3.787, 183.6), b = (-71.19, 40.2), c = (-118.9, 305.7), d = (106, 307.9), e = (67.41, 37.17), f = (-12.88, -176), g = (-117.4, -300.4), h = (-126.5, -44.75), i = (80.28, -333.7), j = (98.46, -42.48) IN BezierTest(a, b, c, d, e); BezierTest(f, g, h, i, j) END END; UI Template(BezierTests); PROC RectTests() IS VAR a = (-5.68, 165.4), b = (57.18, 105.5), c = (-2.84, -151.9), d = (168.5, -35.96) IN RectTest(a, b); RectTest(c, d) END END; UI Template(RectTests); PROC Cmd0() IS VAR a = (-15.15, 26.55), b = (66.65, -47.78), c = (23.48, 50.06) IN EllipseTest(a, b, c) END END;