예제 #1
0
        protected void GetArrowLinePoints(Context context, double x1, double y1, double x2, double y2,
                                          double lineWidth, double connectorSize, double extraThickness = 0)
        {
            double widthX  = (x2 - x1);
            double lengthX = Math.Max(60, Math.Abs(widthX / 2));
            double lengthY = 0;

            if (widthX < 120)
            {
                lengthX = 60;
            }

            double yB = ((y1 + y2) / 2) + lengthY;
            double yC = y2 + yB;
            double xC = (x1 + x2) / 2;
            double xA = x1 + lengthX;
            double xB = x2 - lengthX;

            CubicBezier bezier = new CubicBezier();

            bezier.ControlPoints.Add(new PointD(x1, y1));
            bezier.ControlPoints.Add(new PointD(xA, y1));
            bezier.ControlPoints.Add(new PointD(xB, y2));
            bezier.ControlPoints.Add(new PointD(x2 - connectorSize - extraThickness, y2));

            double t  = 1;
            double yA = (yB * t) + (yC * (1 - t));

            if (widthX <= 12)
            {
                bezier.ControlPoints.Insert(2, new PointD(xB, yA));
                bezier.ControlPoints.Insert(2, new PointD(xC, yA));
                bezier.ControlPoints.Insert(2, new PointD(xA, yA));
            }

            List <PointD> points = bezier.Interpolate(0.25);

            PointD[] angles      = new PointD[points.Count - 1];
            double[] lengths     = new double[points.Count - 1];
            double   totalLength = 0;

            points.Add(points[points.Count - 1]);
            for (int i = 0; i < points.Count - 2; i++)
            {
                PointD pt1    = points[i];
                PointD pt2    = points[i + 1];
                PointD pt3    = points[i + 2];
                PointD delta  = pt2.Substract(pt1).Addition(pt3.Substract(pt2));
                double length = delta.Length();

                if (length <= 1.0)
                {
                    points.RemoveAt(i);
                    i--;
                    continue;
                }

                lengths[i]   = length;
                totalLength += length;
                angles[i]    = delta.Division(length);
            }

            double        startWidth    = extraThickness + 0.75;
            double        endWidth      = extraThickness + (connectorSize / 3.5);
            double        currentLength = 0;
            List <PointD> newPoints     = new List <PointD>();

            newPoints.Add(points[0]);

            for (int i = 0; i < points.Count - 2; i++)
            {
                PointD angle     = angles[i];
                PointD point     = points[i + 1];
                double length    = lengths[i];
                double width     = (((currentLength * (endWidth - startWidth)) / totalLength) + startWidth);
                double angleX    = angle.X * width;
                double angleY    = angle.Y * width;
                double newLength = currentLength + length;
                PointD pt1       = new PointD(point.X - angleY, point.Y + angleX);
                PointD pt2       = new PointD(point.X + angleY, point.Y - angleX);

                if (Math.Abs(newPoints[newPoints.Count - 1].X - pt1.X) > 1.0 ||
                    Math.Abs(newPoints[newPoints.Count - 1].Y - pt1.Y) > 1.0)
                {
                    newPoints.Add(pt1);
                }

                if (Math.Abs(newPoints[0].X - pt2.X) > 1.0 ||
                    Math.Abs(newPoints[0].Y - pt2.Y) > 1.0)
                {
                    newPoints.Insert(0, pt2);
                }

                currentLength = newLength;
            }

            context.LineWidth = lineWidth;
            context.MoveTo(newPoints[0]);
            for (int i = 1; i < newPoints.Count; ++i)
            {
                context.LineTo(newPoints[i]);
            }
            context.ClosePath();
        }