コード例 #1
0
        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);
            }
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
        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);
            }
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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);
            }
        }
コード例 #7
0
 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());
     }
 }
コード例 #8
0
        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);
            }
        }
コード例 #9
0
        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);
            }
        }
コード例 #10
0
        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);
            }
        }
コード例 #11
0
        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);
            }
        }
コード例 #12
0
        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);
        }