计算一条直线在指定的平行距离和端点距离的感应矩形区
/// <summary>
/// 计算P1P2直线的感应矩形区
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="parallelOffset">平行间距</param>
/// <param name="endPointOffset">端点间距</param>
/// <returns></returns>
public PointF[] CalculateInductionRect(PointF p1, PointF p2, double parallelOffset, double endPointOffset)
{
var p1New = p1;
var p2New = p2;
var p_a = new PointF();
var p_b = new PointF();
var p_c = new PointF();
var p_d = new PointF();
if (p2.X == p1.X)
{//平行Y轴
#region 平行Y轴
var minY = Math.Min(p1.Y, p2.Y);
var maxY = Math.Max(p1.Y, p2.Y);
//计算端点偏移距离后的P1点
var y1New_1 = p1.Y + endPointOffset;
var y1New_2 = p1.Y - endPointOffset;
//由于新点必须在P1P2直线的两端延长线上,所以Y不可能在P1P2点的Y之间
var y1New = (y1New_1 > minY && y1New_1 < maxY) ? y1New_2 : y1New_1;
//计算端点偏移距离后的P1点
var y2New_1 = p2.Y + endPointOffset;
var y2New_2 = p2.Y - endPointOffset;
//由于新点必须在P1P2直线的两端延长线上,所以Y不可能在P1P2点的Y之间
var y2New = (y2New_1 > minY && y2New_1 < maxY) ? y2New_2 : y2New_1;
p1New = new PointF(p1.X, (float)y1New);
p2New = new PointF(p2.X, (float)y2New);
//P1P2平行Y轴,平行偏移就即X的偏移
p_a.X = (float)(p1New.X - parallelOffset);
p_a.Y = p1New.Y;
p_b.X = (float)(p1New.X + parallelOffset);
p_b.Y = p1New.Y;
p_c.X = (float)(p2New.X + parallelOffset);
p_c.Y = p2New.Y;
p_d.X = (float)(p2New.X - parallelOffset);
p_d.Y = p2New.Y;
#endregion
}
else
{//不平行Y轴
//斜率
double k = (p2.Y - p1.Y) / (p2.X - p1.X);
//k平方
double kSquare = k * k;
#region 计算端点距离延伸的新点
if (endPointOffset != 0)
{
var minX = Math.Min(p1.X, p2.X);
var maxX = Math.Max(p1.X, p2.X);
//依据距离公式和新点到P2点的斜率相等形成两个方程式,推导得出
var factorXForEndPoint = endPointOffset / Math.Sqrt(kSquare + 1);
//计算端点偏移距离后的P1点
var x1New_1 = p1.X + factorXForEndPoint;
var x1New_2 = p1.X - factorXForEndPoint;
//由于新点必须在P1P2直线的两端延长线上,所以X不可能在P1P2点的X之间
var x1New = (x1New_1 > minX && x1New_1 < maxX) ? x1New_2 : x1New_1;
//计算端点偏移距离后的P2点
var x2New_1 = p2.X + factorXForEndPoint;
var x2New_2 = p2.X - factorXForEndPoint;
//由于新点必须在P1P2直线的两端延长线上,所以X不可能在P1P2点的X之间
var x2New = (x2New_1 > minX && x2New_1 < maxX) ? x2New_2 : x2New_1;
//y=kx+b
//计算P1P2直线方程的截距
var b = p1.Y - k * p1.X;
//基于截距式直线方程计算新的P1和P2点
var y1New = k * x1New + b;
var y2New = k * x2New + b;
p1New = new PointF((float)x1New, (float)y1New);
p2New = new PointF((float)x2New, (float)y2New);
}
#endregion
#region 计算与P1P2两边平行的四个点
//依据距离公式和新点到P2点的斜率相等形成两个方程式,推导得出
double factorX = parallelOffset * k / Math.Sqrt(kSquare + 1);
p_a.X = (float)(p1New.X - factorX);
p_b.X = (float)(p1New.X + factorX);
p_c.X = (float)(p2New.X + factorX);
p_d.X = (float)(p2New.X - factorX);
//依据距离公式和新点到P2点的斜率相等形成两个方程式,推导得出
double factorY = parallelOffset / Math.Sqrt(kSquare + 1);
p_a.Y = (float)(p1New.Y + factorY);
p_b.Y = (float)(p1New.Y - factorY);
p_c.Y = (float)(p2New.Y - factorY);
p_d.Y = (float)(p2New.Y + factorY);
#endregion
}
return new PointF[] { p_a, p_b, p_c, p_d };
}
效果图
转载请注明出处。