示例#1
0
            public VariableVector GetBestConnector(VariableVector farAway)
            {
                // Current algorithm: There are 360°/_connectors equal-sized sectors;
                // the "best connector" is the intersection of a sector center line
                // nearest to the line from center to farAway.
                // Other ideas:
                // - Divide the circumference of the box into equal-sized lengths.
                // - Like before, but with guaranteed connectors at corners.
                // - Like before, but with additional guaranteed connectors at edge midpoints.

                var result = new VariableVector("Connector", _solver);

                UnidirectionalComputationConstraint.CreateUnidirectionalComputationConstraint(input: new[] { farAway.X, farAway.Y, _center.X, _center.Y, _diagonal.X, _diagonal.Y },
                                                                                              output: new[] { result.X, result.Y },
                                                                                              computation: (input, output) => {
                    // float[] inputValues = _input.Select(v => (float) v.Value.Lo).ToArray();
                    // ... I ignore "input" here and use the fields and local variables ... well ... ... should work ...
                    VectorF centerF   = _center.AsVectorF();
                    VectorF diagonalF = _diagonal.AsVectorF();
                    var farAwayF      = farAway.AsVectorF();

                    VectorF d           = farAwayF - centerF;
                    double angle        = Math.Atan2(d.GetY(), d.GetX());
                    double roundedAngle =
                        NormalizedAngle(Math.Round(angle / _sectorAngle) * _sectorAngle);
                    double diagX         = diagonalF.GetX() / 2;
                    double diagY         = diagonalF.GetY() / 2;
                    double diagonalAngle = NormalizedAngle(Math.Atan2(diagY, diagX));
                    double x, y;
                    if (roundedAngle < diagonalAngle)
                    {
                        x = diagX;
                        y = x * Math.Tan(roundedAngle);
                    }
                    else if (roundedAngle < Math.PI - diagonalAngle)
                    {
                        y = diagY;
                        x = y * Math.Tan(Math.PI / 2 - roundedAngle);
                    }
                    else if (roundedAngle < Math.PI + diagonalAngle)
                    {
                        x = -diagX;
                        y = x * Math.Tan(roundedAngle);
                    }
                    else if (roundedAngle < 2 * Math.PI - diagonalAngle)
                    {
                        y = -diagY;
                        x = y * Math.Tan(Math.PI / 2 - roundedAngle);
                    }
                    else
                    {
                        x = diagX;
                        y = x * Math.Tan(roundedAngle);
                    }

                    result.X.Set(centerF.GetX() + x);
                    result.Y.Set(centerF.GetY() + y);
                });
                return(result);
            }
示例#2
0
        private static void DrawText(Graphics graphics, string text, Font textFont, Color textColor, VectorF textCenter, Matrix m)
        {
            StringFormat centered = new StringFormat {
                Alignment = StringAlignment.Center
            };
            float  halfFontHeight = textFont.GetHeight() / 2;
            PointF position       = (textCenter + new VectorF(0, halfFontHeight, "font/2 " + halfFontHeight)).AsMirroredPointF();

            if (DEBUG)
            {
                graphics.FillEllipse(new SolidBrush(Color.Red), textCenter.AsMirroredPointF().X - 3, textCenter.AsMirroredPointF().Y - 3, 6, 6);
                graphics.DrawString(text, textFont, new SolidBrush(Color.LightGray), position, centered);
            }

            GraphicsContainer containerForTextPlacement = graphics.BeginContainer();

            graphics.MultiplyTransform(m);
            graphics.DrawString(text, textFont, new SolidBrush(textColor), position, centered);

            graphics.EndContainer(containerForTextPlacement);
        }
示例#3
0
            public void Draw(Graphics graphics, StringBuilder htmlForClicks)
            {
                VectorF tailF    = _tail.AsVectorF();
                VectorF headF    = _head.AsVectorF();
                VectorF textBoxF = _textBox.AsVectorF();
                float   fWidth   = (float)_width;

                PointF tailPoint = tailF.AsMirroredPointF();
                PointF headPoint = headF.AsMirroredPointF();

                if (tailPoint != headPoint)
                {
                    float absoluteArrowSize = Math.Min(10 * fWidth, (headF - tailF).Length() / 4);
                    float relativeArrowSize = absoluteArrowSize / fWidth;
                    //Console.WriteLine(_name + ">S=" + relativeArrowSize);
                    var pen = new Pen(_color, fWidth)
                    {
                        StartCap = LineCap.RoundAnchor,
                        // arrowsize is relative to line width, therefore we divide by fWidth
                        CustomEndCap = new AdjustableArrowCap(relativeArrowSize / 2, relativeArrowSize, isFilled: false)
                    };
                    graphics.DrawLine(pen, tailPoint, headPoint);
                }
                else
                {
                    graphics.FillEllipse(new SolidBrush(_color), headPoint.X - fWidth / 2, headPoint.Y - fWidth / 2, fWidth, fWidth);
                }

                if (DEBUG)
                {
                    graphics.FillEllipse(new SolidBrush(Color.GreenYellow), headPoint.X - fWidth / 2, headPoint.Y - fWidth / 2, fWidth, fWidth);
                    graphics.FillEllipse(new SolidBrush(Color.Aqua), tailPoint.X - fWidth / 2, tailPoint.Y - fWidth / 2, fWidth, fWidth);
                }

                VectorF textCenterF = _textLocation >= 0
                    ? tailF * (1 - _textLocation) + headF * _textLocation
                    : tailF + (headF - tailF).Unit() * -_textLocation;
                float halfTextWidth    = textBoxF.GetX() / 2;
                float lineAngleDegrees = (float)(-Math.Atan2(headF.GetY() - tailF.GetY(), headF.GetX() - tailF.GetX()) * 180 / Math.PI);

                var textTransform = new Matrix();

                switch (_lineTextPlacement)
                {
                case LineTextPlacement.Left:
                    textTransform.Translate(-halfTextWidth, 0);
                    break;

                case LineTextPlacement.Center:
                    break;

                case LineTextPlacement.Right:
                    textTransform.Translate(halfTextWidth, 0);
                    break;

                case LineTextPlacement.LeftInclined:
                    textTransform.RotateAt(lineAngleDegrees, textCenterF.AsMirroredPointF());
                    textTransform.Translate(-halfTextWidth, 0);
                    break;

                case LineTextPlacement.CenterInclined:
                    textTransform.RotateAt(lineAngleDegrees, textCenterF.AsMirroredPointF());
                    break;

                case LineTextPlacement.RightInclined:
                    textTransform.RotateAt(lineAngleDegrees, textCenterF.AsMirroredPointF());
                    textTransform.Translate(halfTextWidth, 0);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
                // Move text away from line; needs improvement for steeply inclined lines
                textTransform.Translate(0, -textBoxF.GetY() / 3);
                DrawText(graphics, _text, _textFont, _textColor, textCenterF, textTransform);

                if (!string.IsNullOrWhiteSpace(_edgeInfo))
                {
                    WriteToolTipHtml(graphics, htmlForClicks, _edgeInfo, tailPoint, headPoint);
                }
            }
示例#4
0
            public void Draw(Graphics graphics, StringBuilder htmlForClicks)
            {
                var     diagonalF  = _diagonal.AsVectorF();
                var     textBoxF   = _textBox.AsVectorF();
                var     centerF    = _center.AsVectorF();
                VectorF upperLeftF = _center.AsVectorF() - ~diagonalF / 2;

                FillBox(graphics, new SolidBrush(_borderColor), upperLeftF.GetX(), -upperLeftF.GetY(), diagonalF.GetX(), diagonalF.GetY());

                VectorF borderDiagonalF = new VectorF(_borderWidth, _borderWidth, "45°@" + _borderWidth);
                VectorF upperLeftInnerF = upperLeftF + ~borderDiagonalF;
                VectorF diagonalInnerF  = diagonalF - 2 * borderDiagonalF;

                FillBox(graphics, new SolidBrush(_color), upperLeftInnerF.GetX(), -upperLeftInnerF.GetY(), diagonalInnerF.GetX(), diagonalInnerF.GetY());

                Matrix m = new Matrix();

                switch (_boxTextPlacement)
                {
                case BoxTextPlacement.Left:
                    m.Translate(-(diagonalF - textBoxF).GetX() / 2, 0);
                    break;

                case BoxTextPlacement.Center:
                    break;

                case BoxTextPlacement.Right:
                    m.Translate((diagonalF - textBoxF).GetX() / 2, 0);
                    break;

                case BoxTextPlacement.LeftUp:
                    m.Translate(0, -(diagonalF - textBoxF).AsMirroredPointF().Y / 2);
                    m.RotateAt(-90, centerF.AsMirroredPointF());
                    break;

                case BoxTextPlacement.CenterUp:
                    m.RotateAt(-90, centerF.AsMirroredPointF());
                    break;

                case BoxTextPlacement.RightUp:
                    m.Translate(0, (diagonalF - textBoxF).AsMirroredPointF().Y / 2);
                    m.RotateAt(-90, centerF.AsMirroredPointF());
                    break;

                case BoxTextPlacement.LeftDown:
                    m.Translate(0, (diagonalF - textBoxF).AsMirroredPointF().Y / 2);
                    m.RotateAt(90, centerF.AsMirroredPointF());
                    break;

                case BoxTextPlacement.CenterDown:
                    m.RotateAt(90, centerF.AsMirroredPointF());
                    break;

                case BoxTextPlacement.RightDown:
                    m.Translate(0, -(diagonalF - textBoxF).AsMirroredPointF().Y / 2);
                    m.RotateAt(90, centerF.AsMirroredPointF());
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(_boxTextPlacement), _boxTextPlacement, null);
                }

                var     lineHeight   = new VectorF(0, _textFont.GetHeight() * 1.1f, "lineHeight");
                VectorF textLocation = centerF + new VectorF(0, lineHeight.GetY() / 2 * (_text.Length - 1), "textOffset");

                for (int i = 0; i < _text.Length; i++, textLocation -= lineHeight)
                {
                    DrawText(graphics, _text[i], _textFont, _textColor, textLocation, m);
                }

                if (_htmlRef != null)
                {
                    VectorF lowerRightF = _center.AsVectorF() + ~diagonalF / 2;
                    WriteBoxHtml(graphics, htmlForClicks, _htmlRef, upperLeftF.AsMirroredPointF(),
                                 lowerRightF.AsMirroredPointF(), _text.Length > 0 ? _text[0] : "");
                }
            }