public void TestUnidirectionalComputationConstraint() { { var solver = new SimpleConstraintSolver(); var x = solver.CreateVariable("x"); var y = solver.CreateVariable("y"); var r = solver.CreateVariable("r"); var phi = solver.CreateVariable("phi"); UnidirectionalComputationConstraint.CreateUnidirectionalComputationConstraint(new[] { x, y }, new[] { r, phi }, CartesianToPolar); var rx = new Range(20, 40, EPS); x.RestrictRange(rx); var ry = new Range(30, 50, EPS); y.RestrictRange(ry); solver.Solve(_noAbortCheck); Assert.AreEqual(new Range(50, 50, EPS), r.Value); } { //var solver = new SimpleConstraintSolver(); //var x = solver.Create("a"); //var y = solver.Create("b"); //var r = solver.Create("r"); //var phi = solver.Create("phi"); //new UnidirectionalComputationConstraint(new[] { x, y }, new[] { r, phi }, CartesianToPolar); } }
public void TestIsInverseConstraint() { { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); IsInverseConstraint.CreateIsInverseConstraint(a, b); var r = new Range(3, 4, EPS); a.RestrictRange(r); solver.Solve(_noAbortCheck); Assert.AreEqual(-r, b.Value); } { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); IsInverseConstraint.CreateIsInverseConstraint(a, b); var r = new Range(3, 4, EPS); b.RestrictRange(r); solver.Solve(_noAbortCheck); Assert.AreEqual(-r, a.Value); } }
public void TestRangeConstraint() { { var solver = new SimpleConstraintSolver(); NumericVariable a = solver.CreateVariable("a"); var r = new Range(3, 4, EPS); RangeConstraint.CreateRangeConstraint(a, r); solver.Solve(_noAbortCheck); Assert.AreEqual(r, a.Value); } }
public void TestSimpleSumDownwards() { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); var c = a + b; a.RestrictRange(2, 2); c.RestrictRange(5, 5); solver.Solve(_noAbortCheck); Assert.AreEqual(new Range(3, 3, EPS), b.Value); }
public void TestSimpleSum() { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); var c = a + b; a.RestrictRange(2, 2); b.RestrictRange(3, 3); solver.Solve(_noAbortCheck); Assert.AreEqual(5, c.Value.Lo); Assert.AreEqual(5, c.Value.Hi); }
public void TestSumIs0Constraint() { { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); var c = solver.CreateVariable("c"); SumIs0Constraint.CreateSumIs0Constraint(a, b, c); a.RestrictRange(new Range(30, 50, EPS)); b.RestrictRange(new Range(10, double.PositiveInfinity, EPS)); solver.Solve(_noAbortCheck); Assert.AreEqual(new Range(double.NegativeInfinity, -40, EPS), c.Value); } }
public void TestConstraintPropagation() { { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); var c = solver.CreateVariable("c"); var d = solver.CreateVariable("d"); UnidirectionalComputationConstraint.CreateUnidirectionalComputationConstraint(new[] { a }, new[] { b }, OneMore); UnidirectionalComputationConstraint.CreateUnidirectionalComputationConstraint(new[] { b }, new[] { c }, OneMore); UnidirectionalComputationConstraint.CreateUnidirectionalComputationConstraint(new[] { c }, new[] { d }, OneMore); a.Set(10); solver.Solve(_noAbortCheck); Assert.AreEqual(10, a.GetValue()); Assert.AreEqual(11, b.GetValue()); Assert.AreEqual(12, c.GetValue()); Assert.AreEqual(13, d.GetValue()); } }
public void TestTimes() { { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = a * 3; a.RestrictRange(2, 3); solver.Solve(_noAbortCheck); Assert.AreEqual(new Range(6, 9, EPS), b.Value); } { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = a * 3; b.RestrictRange(2, 3); solver.Solve(_noAbortCheck); Assert.AreEqual(new Range(2 / 3.0, 1, EPS), a.Value); } }
public void TestProportionalConstraint() { { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); ProportionalConstraint.CreateProportionalConstraint(5, a, b); b.RestrictRange(new Range(30, 40, EPS)); solver.Solve(_noAbortCheck); Assert.AreEqual(new Range(6, 8, EPS), a.Value); } { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); ProportionalConstraint.CreateProportionalConstraint(5, a, b); a.RestrictRange(new Range(30, 40, EPS)); solver.Solve(_noAbortCheck); Assert.AreEqual(new Range(150, 200, EPS), b.Value); } }
public void TestAtLeastConstraint() { { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); AtLeastConstraint.CreateAtLeastConstraint(a, b); a.RestrictRange(new Range(3, 4, EPS)); solver.Solve(_noAbortCheck); // (3..4) >= (x..y) means that y is at most 4 Assert.AreEqual(new Range(double.NegativeInfinity, 4, EPS), b.Value); } { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); AtLeastConstraint.CreateAtLeastConstraint(a, b); b.RestrictRange(new Range(3, 4, EPS)); solver.Solve(_noAbortCheck); Assert.AreEqual(new Range(3, double.PositiveInfinity, EPS), a.Value); } }
public void TestMinus() { { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); var c = a - b; a.RestrictRange(2, 3); b.RestrictRange(5, 6); solver.Solve(_noAbortCheck); Assert.AreEqual(new Range(-4, -2, EPS), c.Value); } { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); var c = a - b; a.RestrictRange(2, 3); c.RestrictRange(5, 6); solver.Solve(_noAbortCheck); Assert.AreEqual(new Range(-4, -2, EPS), b.Value); } { var solver = new SimpleConstraintSolver(); var a = solver.CreateVariable("a"); var b = solver.CreateVariable("b"); var c = a - b; b.RestrictRange(2, 3); c.RestrictRange(5, 6); solver.Solve(_noAbortCheck); Assert.AreEqual(new Range(7, 9, EPS), a.Value); } }
private Bitmap Render([NotNull, ItemNotNull] IEnumerable <Dependency> dependencies, float minTextHeight, ref int width, ref int height, StringBuilder htmlForClicks, [NotNull] Action checkAbort) { PlaceObjects(dependencies); // I tried it with SVG - but SVG support in .Net seems to be non-existent. // The library at https://github.com/managed-commons/SvgNet is a nice attempet (a 2015 resurrection of a 2003 attempt), // but it closes off the SVG objects in such a way that adding edgeInfos ("mouse hoverings") seems very hard. // If someone knows more about SVG than I (who doesn't know a bit ...), feel free to try it with SVG! // A helper Bitmap is used to measure strings; only afterwards can // we compute the actual width and height from the solved vectors. using (Graphics graphics = Graphics.FromImage(new Bitmap(1000, 1000))) { foreach (var b in _builders) { b.FullyRestrictBoundingVectors(graphics); } } try { _solver.Solve(checkAbort); } catch (SolverException) { Console.WriteLine(_solver.GetState(maxLines: 20000)); throw; } float minX = float.MaxValue; float maxX = -float.MaxValue; float minY = float.MaxValue; float maxY = -float.MaxValue; StringBuilder errors = new StringBuilder(); foreach (var b in _builders.OrderBy(b => b.DrawingOrder).ThenBy(b => b.CreationOrder)) { foreach (var v in b.GetBoundingVectors()) { float x = v.GetX(); if (float.IsInfinity(x)) { errors.AppendLine($"Dimensions of {b.Name} not fully computed - no value for {v.Definition}.x"); } else { minX = Math.Min(minX, x); maxX = Math.Max(maxX, x); } float y = v.GetY(); if (float.IsInfinity(y)) { errors.AppendLine($"Dimensions of {b.Name} not fully computed - no value for {v.Definition}.y"); } else { minY = Math.Min(minY, y); maxY = Math.Max(maxY, y); } } } if (errors.Length > 0) { throw new InvalidOperationException(errors + _solver.GetState(maxLines: 20000)); } // 1% margin on all sides const float BORDER = 0.02f; if (width <= 0) { if (height <= 0) { float?smallestTextHeight = null; foreach (var b in _builders) { float?h = b.GetTextSizeInPoints(); if (h.HasValue) { smallestTextHeight = smallestTextHeight.HasValue ? Math.Min(smallestTextHeight.Value, h.Value) : h.Value; } } float textBasedScale = minTextHeight / smallestTextHeight ?? 1; height = (int)(textBasedScale * (maxY - minY)); width = (int)(textBasedScale * (maxX - minX)); } else { width = (int)(height / (maxY - minY) * (maxX - minX)); } } else { if (height <= 0) { height = (int)(width / (maxX - minX) * (maxY - minY)); } else { // nothing to compute } } if (width + height > 20000) { // scale back enormous diagrams float hugeScale = 20000f / (width + height); width = (int)(width * hugeScale); height = (int)(height * hugeScale); } double scaleX = width * (1 - 2 * BORDER) / (maxX - minX); double scaleY = height * (1 - 2 * BORDER) / (maxY - minY); float scale = (float)Math.Min(scaleX, scaleY); // No distortion! Log.WriteInfo($"Creating image of size {width}x{height}px"); var bitmap = new Bitmap(width, height); using (Graphics graphics = Graphics.FromImage(bitmap)) { graphics.Clear(GetBackGroundColor); graphics.Transform = new Matrix(scale, 0, 0, scale, -scale * minX + width * BORDER, scale * maxY + height * BORDER); List <IBuilder> openBuilders = _builders.OrderBy(b => b.DrawingOrder).ThenBy(b => b.CreationOrder).ToList(); foreach (var b in openBuilders.ToArray()) { b.Draw(graphics, htmlForClicks); } } return(bitmap); }