/// <summary> /// 根据弧的起点,终点,半径,绘制方向,返回圆心点 /// </summary> /// <param name="startPoint">点1</param> /// <param name="endPoint">点2</param> /// <param name="radius">半径</param> /// <param name="sweepDirection">绘制方向</param> /// <returns>坐标</returns> /// <!--作者: 韦腾 时间:2008.12.16--> public static Point GetRoundCenter(Point startPoint, Point endPoint, double radius, SweepDirection sweepDirection, bool isLargeArc) { if (startPoint == endPoint) { throw new Exception("起点与终点不能重合."); } //弧连线的长 double width = Math.Sqrt((startPoint.Y - endPoint.Y) * (startPoint.Y - endPoint.Y) + (startPoint.X - endPoint.X) * (startPoint.X - endPoint.X)); if (width / 2 > radius) { throw new RadiusException("半径不能小于起点与终点的距离."); } //中点,即交点 Point crossingPoint = new Point((startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2); //弧连线斜率 double k1 = (startPoint.Y - endPoint.Y) / (startPoint.X - endPoint.X); //圆心连线斜率 double k2; //弧于圆心的距离 double distance; distance = Math.Sqrt(radius * radius - (width * width) / 4); //圆心点 Point roundCenterLeft = new Point(); Point roundCenterRight = new Point(); if (double.IsInfinity(k1)) { roundCenterLeft = new Point(crossingPoint.X + distance, crossingPoint.Y); roundCenterRight = new Point(crossingPoint.X - distance, crossingPoint.Y); } else if (k1 == 0) { roundCenterLeft = new Point(crossingPoint.X, crossingPoint.Y + distance); roundCenterRight = new Point(crossingPoint.X, crossingPoint.Y - distance); } else { k2 = (-1) / k1; double xOffset = distance / (Math.Sqrt(1 + k2 * k2)); double xTemp, yTemp; #region 第一个圆心点 xTemp = crossingPoint.X + xOffset; yTemp = k2 * (xTemp - crossingPoint.X) + crossingPoint.Y; roundCenterLeft = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); #endregion #region 第二个圆心点 xTemp = crossingPoint.X - xOffset; yTemp = k2 * (xTemp - crossingPoint.X) + crossingPoint.Y; roundCenterRight = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); #endregion } if (-1 == MathExtension.GetPointLeftOrRight(startPoint, endPoint, roundCenterLeft)) { Point pointTemp = roundCenterLeft; roundCenterLeft = roundCenterRight; roundCenterRight = pointTemp; } //大弧(注意坐标已经发先水平翻转) if (isLargeArc) { //顺时针 取左边圆心 if (sweepDirection == SweepDirection.Clockwise) { return(roundCenterRight); } else//逆时针 取右边圆心 { return(roundCenterLeft); } } else //小弧 { //顺时针 取右边圆心 if (sweepDirection == SweepDirection.Clockwise) { return(roundCenterLeft); } else//逆时针 取左边圆心 { return(roundCenterRight); } } }
/// <summary> /// 设置位置 /// </summary> public void SetPosition() { #region 弧线 this.lineElement.Point = this.EndPoint; this.LinePathFigureElement.StartPoint = this.StartPoint; this.lineElement.IsLargeArc = this.IsLargeArc; this.lineElement.SweepDirection = this.LineSweepDirection; this.lineElement.Size = new Size(this.Radius, this.Radius); #endregion #region 箭头 Point roundCenter = new Point(); double k1; //求圆心 try { roundCenter = MathExtension.GetRoundCenter(this.StartPoint, this.EndPoint, this.Radius, this.LineSweepDirection, this.IsLargeArc); //圆心与箭头点连线的斜率 k1 = (roundCenter.Y - this.EndPoint.Y) / (roundCenter.X - this.EndPoint.X); } catch (Exception ex) { if (ex is RadiusException) { k1 = (-1) * (this.StartPoint.X - this.EndPoint.X) / (this.StartPoint.Y - this.EndPoint.Y); this.lineElement.Size = new Size(0, 1); } else { return; } } Point centerPoint1, centerPoint2, endPoint11, endPoint12, endPoint21, endPoint22; //切线斜率 double k2 = 0; if (double.IsInfinity(k1)) //与Y轴平行 { //中间点 this._CenterPoint.X = (this.StartPoint.X + this.EndPoint.X) / 2; this._CenterPoint.Y = (this.StartPoint.Y + this.EndPoint.Y) / 2; //如果是直线,直线与X轴平行 if (this.IsBeeline) { if (this.StartPoint.X < this.EndPoint.X) { this.arrowStartElement.StartPoint = new Point(this.EndPoint.X - this.ArrowSize.Height, this.EndPoint.Y - this.ArrowSize.Width); this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(this.EndPoint); this.arrowElement.Points.Add(new Point(this.EndPoint.X - this.ArrowSize.Height, this.EndPoint.Y + this.ArrowSize.Width)); } else { this.arrowStartElement.StartPoint = new Point(this.EndPoint.X + this.ArrowSize.Height, this.EndPoint.Y - this.ArrowSize.Width); this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(this.EndPoint); this.arrowElement.Points.Add(new Point(this.EndPoint.X + this.ArrowSize.Height, this.EndPoint.Y + this.ArrowSize.Width)); } } } else if (Math.Round(k1, 4) == 0)//与X轴平行 { //中间点 this._CenterPoint.X = (this.StartPoint.X + this.EndPoint.X) / 2; this._CenterPoint.Y = (this.StartPoint.Y + this.EndPoint.Y) / 2; //如果是直线 if (this.IsBeeline) { if (this.StartPoint.Y < this.EndPoint.Y) { this.arrowStartElement.StartPoint = new Point(this.EndPoint.X - this.ArrowSize.Width, this.EndPoint.Y - this.ArrowSize.Height); this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(this.EndPoint); this.arrowElement.Points.Add(new Point(this.EndPoint.X + this.ArrowSize.Width, this.EndPoint.Y - this.ArrowSize.Height)); } else { this.arrowStartElement.StartPoint = new Point(this.EndPoint.X - this.ArrowSize.Width, this.EndPoint.Y + this.ArrowSize.Height); this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(this.EndPoint); this.arrowElement.Points.Add(new Point(this.EndPoint.X + this.ArrowSize.Width, this.EndPoint.Y + this.ArrowSize.Height)); } } } else { k2 = (-1) / k1; double xOffset = this.ArrowSize.Height / (Math.Sqrt(1 + k2 * k2)); double xTemp, yTemp; #region 第一个点 xTemp = this.EndPoint.X + xOffset; yTemp = k2 * (xTemp - this.EndPoint.X) + this.EndPoint.Y; centerPoint1 = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); #endregion #region 第二个点 xTemp = this.EndPoint.X - xOffset; yTemp = k2 * (xTemp - this.EndPoint.X) + this.EndPoint.Y; centerPoint2 = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); #endregion k2 = k1; xOffset = this.ArrowSize.Width / (Math.Sqrt(1 + k2 * k2)); #region 第一个点对应的两个箭头端点 xTemp = centerPoint1.X + xOffset; yTemp = k2 * (xTemp - centerPoint1.X) + centerPoint1.Y; endPoint11 = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); xTemp = centerPoint1.X - xOffset; yTemp = k2 * (xTemp - centerPoint1.X) + centerPoint1.Y; endPoint12 = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); #endregion #region 第二个点对应的两个箭头端点 xTemp = centerPoint2.X + xOffset; yTemp = k2 * (xTemp - centerPoint2.X) + centerPoint2.Y; endPoint21 = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); xTemp = centerPoint2.X - xOffset; yTemp = k2 * (xTemp - centerPoint2.X) + centerPoint2.Y; endPoint22 = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); #endregion //小弧 if (!this.IsLargeArc) { #region 小弧 //如果是直线,则比较点与起点的距离,取距离近的两点 if (this.IsBeeline) { double d1 = (endPoint11.X - this.StartPoint.X) * (endPoint11.X - this.StartPoint.X) + (endPoint11.Y - this.StartPoint.Y) * (endPoint11.Y - this.StartPoint.Y); double d2 = (endPoint21.X - this.StartPoint.X) * (endPoint21.X - this.StartPoint.X) + (endPoint21.Y - this.StartPoint.Y) * (endPoint21.Y - this.StartPoint.Y); if (d1 < d2) { this.arrowStartElement.StartPoint = endPoint11; this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(this.EndPoint); this.arrowElement.Points.Add(endPoint12); } else { this.arrowStartElement.StartPoint = endPoint21; this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(this.EndPoint); this.arrowElement.Points.Add(endPoint22); } } else { //是否是同一边 if (MathExtension.GetPointLeftOrRight(roundCenter, this.EndPoint, this.StartPoint) == MathExtension.GetPointLeftOrRight(roundCenter, this.EndPoint, centerPoint1)) { this.arrowStartElement.StartPoint = endPoint11; this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(this.EndPoint); this.arrowElement.Points.Add(endPoint12); } else { this.arrowStartElement.StartPoint = endPoint21; this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(this.EndPoint); this.arrowElement.Points.Add(endPoint22); } } #endregion } else { #region 大弧 //如果是直线,则比较点与起点的距离,取距离近的两点 if (this.IsBeeline) { double d1 = (endPoint11.X - this.StartPoint.X) * (endPoint11.X - this.StartPoint.X) + (endPoint11.Y - this.StartPoint.Y) * (endPoint11.Y - this.StartPoint.Y); double d2 = (endPoint21.X - this.StartPoint.X) * (endPoint21.X - this.StartPoint.X) + (endPoint21.Y - this.StartPoint.Y) * (endPoint21.Y - this.StartPoint.Y); if (d1 < d2) { this.arrowStartElement.StartPoint = endPoint11; this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(this.EndPoint); this.arrowElement.Points.Add(endPoint12); } else { this.arrowStartElement.StartPoint = endPoint21; this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(this.EndPoint); this.arrowElement.Points.Add(endPoint22); } } else { //是否是不同一边 if (MathExtension.GetPointLeftOrRight(roundCenter, this.EndPoint, this.StartPoint) == (-1) * MathExtension.GetPointLeftOrRight(roundCenter, this.EndPoint, centerPoint1)) { this.arrowStartElement.StartPoint = endPoint11; this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(this.EndPoint); this.arrowElement.Points.Add(endPoint12); } else { this.arrowStartElement.StartPoint = endPoint21; this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(this.EndPoint); this.arrowElement.Points.Add(endPoint22); } } #endregion } this.GetCenterPositen(roundCenter); } #endregion }
/// <summary> /// 设置位置 /// </summary> public void SetPosition() { #region 弧线 lineElement.Point2 = new Point(EndPointX, EndPointY); LinePathFigureElement.StartPoint = new Point(StartPointX, StartPointY); #endregion #region 箭头 Point roundCenter = new Point(); Point textCenterPoint; double k1; //求圆心 try { roundCenter = MathExtension.GetBezierCenter(LinePathFigureElement.StartPoint, lineElement.Point2, RadiusRadio * Length, this.LineSweepDirection); var cp = new Point() { X = (StartPointX + EndPointX) / 2, Y = (StartPointY + EndPointY) / 2, }; textCenterPoint = new Point() { X = (cp.X + roundCenter.X) / 2, Y = (cp.Y + roundCenter.Y) / 2, }; //圆心与箭头点连线的斜率 k1 = (roundCenter.Y - this.EndPointY) / (roundCenter.X - this.EndPointX); } catch (Exception ex) { if (ex is RadiusException) { k1 = (-1) * (this.StartPointX - this.EndPointX) / (this.StartPointY - this.EndPointY); textCenterPoint = roundCenter = new Point() { X = (this.StartPointX + this.EndPointX) / 2, Y = (this.StartPointY + this.EndPointY) / 2 }; SetLinePosition(); textBoxElement.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); Canvas.SetLeft(textBoxElement, textCenterPoint.X - textBoxElement.DesiredSize.Width / 2); Canvas.SetTop(textBoxElement, textCenterPoint.Y - textBoxElement.DesiredSize.Height / 2); return; } else { return; } } this.lineElement.Point1 = roundCenter; Point centerPoint1, centerPoint2, endPoint11, endPoint12, endPoint21, endPoint22; //切线斜率 double k2 = 0; { k2 = k1; double xOffset = this.ArrowSize.Height / (Math.Sqrt(1 + k2 * k2)); double xTemp, yTemp; #region 第一个点 xTemp = this.EndPointX + xOffset; yTemp = k2 * (xTemp - this.EndPointX) + this.EndPointY; centerPoint1 = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); #endregion #region 第二个点 xTemp = this.EndPointX - xOffset; yTemp = k2 * (xTemp - this.EndPointX) + this.EndPointY; centerPoint2 = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); #endregion k2 = (-1) / k1; xOffset = this.ArrowSize.Width / (Math.Sqrt(1 + k2 * k2)); #region 第一个点对应的两个箭头端点 xTemp = centerPoint1.X + xOffset; yTemp = k2 * (xTemp - centerPoint1.X) + centerPoint1.Y; endPoint11 = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); xTemp = centerPoint1.X - xOffset; yTemp = k2 * (xTemp - centerPoint1.X) + centerPoint1.Y; endPoint12 = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); #endregion #region 第二个点对应的两个箭头端点 xTemp = centerPoint2.X + xOffset; yTemp = k2 * (xTemp - centerPoint2.X) + centerPoint2.Y; endPoint21 = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); xTemp = centerPoint2.X - xOffset; yTemp = k2 * (xTemp - centerPoint2.X) + centerPoint2.Y; endPoint22 = new Point(Math.Round(xTemp, 4), Math.Round(yTemp, 4)); #endregion //小弧 #region 永远找和圆心距离近的那组点 { double d1 = (endPoint11.X - roundCenter.X) * (endPoint11.X - roundCenter.X) + (endPoint11.Y - roundCenter.Y) * (endPoint11.Y - roundCenter.Y); double d2 = (endPoint21.X - roundCenter.X) * (endPoint21.X - roundCenter.X) + (endPoint21.Y - roundCenter.Y) * (endPoint21.Y - roundCenter.Y); //if (this.LineSweepDirection== SweepDirection.Clockwise) if (d1 < d2) { this.arrowStartElement.StartPoint = endPoint11; this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(lineElement.Point2); this.arrowElement.Points.Add(endPoint12); } else { this.arrowStartElement.StartPoint = endPoint21; this.arrowElement.Points.Clear(); this.arrowElement.Points.Add(lineElement.Point2); this.arrowElement.Points.Add(endPoint22); } } #endregion } #endregion textBoxElement.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); Canvas.SetLeft(textBoxElement, textCenterPoint.X - textBoxElement.DesiredSize.Width / 2); Canvas.SetTop(textBoxElement, textCenterPoint.Y - textBoxElement.DesiredSize.Height / 2); }