MODULE Tetra; (* A simple module to test constraints and drawing in 3D. *) CONST Duration = 10, ShowLabels = 0, Shades = 21, Colored = 1, Hue = Color.YellowHue; FUNC l = Length2(p) IS (E px, py :: p = (px, py) AND l = (px * px) + (py * py)) END; FUNC d = Dist2Sqr(a, b) IS d = Length2(R2.Minus(b, a)) END; FUNC d = Dist3Sqr(a, b) IS d = R3.Length2(R3.Minus(b, a)) END; PRED Cong3(a, b, c, d) IS Dist3Sqr(a, b) = Dist3Sqr(c, d) END; PROC ShowLabel(a, A) IS PS.Type(a, Unparse.Value(A)) END; PRIVATE PROC r := Discrete(x) IS VAR k = Shades - 1 IN r := ROUND(k * x) / k END END; PRIVATE PROC c := ShadeColor(z) IS IF Colored > 0 -> c := Color.FromHSV(Hue, 1, z) | c := Color.FromGrey(z) FI END; PRIVATE PROC PaintFace(a, b, c) IS PS.MoveTo(a); PS.LineTo(b); PS.LineTo(c); PS.Close(); SAVE PS IN PS.Fill() END; PS.SetColor(Color.Black); PS.Stroke() END; PRIVATE FUNC z = UCross(v1, v2) IS z = R3.Normalize(R3.Cross(v1, v2)) END; PRIVATE PROC PaintTri(A, B, C, a, b, c) IS VAR v1 = R3.Minus(B, A), v2 = R3.Minus(C, A), z = R3.Z(UCross(v1, v2)) IN IF z >= 0 -> PS.SetColor(ShadeColor(Discrete(z))); PaintFace(a, b, c) | SKIP FI END END; PROC PaintTetra(A, B, C, D) IS VAR a = R3.ToR2(A), b = R3.ToR2(B), c = R3.ToR2(C), d = R3.ToR2(D) IN PaintTri(A, B, C, a, b, c); PaintTri(A, C, D, a, c, d); PaintTri(A, D, B, a, d, b); PaintTri(C, B, D, c, b, d) END END; PROC TetraAtT(A, b, c1, c2, t) IS IF VAR a ~ (100, 300), d ~ (0.8245, 0.7164) REL (a, b), B ~ [242, 334.9, 79.71], C ~ [109.8, 434.6, 97.56], D ~ [192.1, 430.5, -47.19], theta = 2 * Math.Pi * t, c = (COS(theta), SIN(theta)) REL (c2, c1) IN Cong3(A, B, B, C) AND Cong3(B, C, C, A) AND Cong3(A, B, A, D) AND Cong3(A, B, B, D) AND Cong3(A, B, C, D) AND a = R3.ToR2(A) AND b = R3.ToR2(B) AND c = R3.ToR2(C) AND d = R3.ToR2(D) -> PS.SetWidth(2); PS.SetJointStyle(PS.RoundJoints); PaintTetra(A, B, C, D); IF ShowLabels > 0 -> ShowLabel(a, A); ShowLabel(b, B); ShowLabel(c, C); ShowLabel(d, D) | SKIP FI END FI END; PROC Go(A, b, c1, c2) IS Anim.Play((CLOSE(TetraAtT, A, b, c1, c2), Duration)) END; PROC Cmd0() IS IF VAR b = (242, 334.9), c1 = (98.46, 434.6), A = [100, 300, 0], c2 = (112.1, 434.6) IN Go(A, b, c1, c2); PS.Reset() END FI END;