我不知道你能做到这一点,但对于你的特定目标,你可以用这样的东西重新计算路径(使用双缓冲):
float px = 0;
float py = 0;
float dxy = 0;
float centerx;
float centery;
float mainAngle = 0;
private List<PointF> myCircle(int points, float radius)
{
List<PointF> result = new List<PointF>();
for (int i = 0; i < points; i++)
{
result.Add(new PointF(radius * (float)Math.Cos(2 * Math.PI * (double)i / (points - 1)), radius * (float)Math.Sin(2 * Math.PI * (double)i / (points - 1))));
}
return result;
}
private List<PointF> myBlendedCircles(int points,float radius)
{
List<PointF> result = new List<PointF>();
float linkcircle = radius / 2f;
float A = radius + linkcircle;
float B = dxy / 2f;
float angle = (float)Math.Acos(B / A);
float angle2 = ((float)Math.PI/2f - angle);
// circle 1
for (int i = 0; i < points; i++)
{
result.Add(new PointF(radius * (float)Math.Cos(angle + (2 * Math.PI - 2f*angle) * (double)i / (points - 1)), radius * (float)Math.Sin(angle + (2 * Math.PI - 2f*angle) * (double)i / (points - 1))));
}
// link1
for (int i = 0; i < points; i++)
{
result.Add(new PointF(linkcircle * (float)Math.Cos(-(float)Math.PI * 3.0 / 2.0 + angle2 - (2.0 * angle2) * (double)i / (points - 1)) + dxy / 2f, linkcircle * (float)Math.Sin(-(float)Math.PI * 3.0 / 2.0 + angle2 - (2.0 * angle2) * (double)i / (points - 1)) - A * (float)Math.Sin(angle)));
}
//circle2
for (int i = 0; i < points; i++)
{
result.Add(new PointF(radius * (float)Math.Cos((float)Math.PI + angle + (2 * Math.PI - 2f * angle) * (double)i / (points - 1)) + dxy, radius * (float)Math.Sin((float)Math.PI + angle + (2 * Math.PI - 2f * angle) * (double)i / (points - 1))));
}
//link2
for (int i = 0; i < points; i++)
{
result.Add(new PointF(linkcircle * (float)Math.Cos((float)Math.PI * 3.0 / 2.0 + angle2 - (2.0 * angle2) * (double)i / (points - 1)) + dxy / 2f, linkcircle * (float)Math.Sin((float)Math.PI * 3.0 / 2.0 + angle2 - (2.0 * angle2) * (double)i / (points - 1)) + A * (float)Math.Sin(angle)));
}
return result;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
centerx = (float)this.Width / 2f;
centery = (float)this.Height / 2f;
GraphicsPath gp1 = new GraphicsPath();
gp1.AddLines(myCircle(36,40).ToArray());
e.Graphics.TranslateTransform(centerx, centery);
e.Graphics.DrawPath(Pens.Black, gp1);
e.Graphics.TranslateTransform(-centerx, -centery);
e.Graphics.TranslateTransform(px, py);
e.Graphics.DrawPath(Pens.Blue, gp1);
e.Graphics.TranslateTransform(-px, -py);
if(dxy<40f*2f)
{
GraphicsPath gp2 = new GraphicsPath();
gp2.AddLines(myBlendedCircles(36, 40).ToArray());
e.Graphics.TranslateTransform(centerx, centery);
e.Graphics.RotateTransform(mainAngle);
e.Graphics.DrawPath(new Pen(Color.Red,2f), gp2);
e.Graphics.RotateTransform(-mainAngle);
e.Graphics.TranslateTransform(-centerx, -centery);
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
px = e.X;
py = e.Y;
dxy = (float)Math.Sqrt((px - centerx) * (px - centerx) + (py - centery) * (py - centery));
mainAngle = (float)Math.Atan2(py - centery, px - centerx)*180f/(float)Math.PI;
label1.Text = mainAngle.ToString();
this.Invalidate();
}
该函数可以直接返回路径。对于不同半径的圆(我没有尝试两个椭圆的更复杂的情况),你可以使用这样的东西:
private GraphicsPath myBlendedCircles(float radius1, float radius2)
{
GraphicsPath result = new GraphicsPath();
float radiusL = (radius1 + radius2) / 4;
float pif = (float)Math.PI;
float l1 = radius1 + radiusL;
float l2 = radius2 + radiusL;
//angle calculation: Al'Kashi
float alpha = (float)Math.Acos((l1 * l1 + dxy * dxy - l2 * l2) / (2f * l1 * dxy));
float beta = (float)Math.Acos((l2 * l2 + dxy * dxy - l1 * l1) / (2f * l2 * dxy));
float gamma = (float)Math.Acos((l1 * l1 + l2 * l2 - dxy * dxy) / (2f * l1 * l2));
// position of link circles
float lx = l1 * (float)Math.Cos(alpha);
float ly = l1 * (float)Math.Sin(alpha);
result.AddArc(-radius1, -radius1, 2 * radius1, 2 * radius1, 180 * alpha / pif, 360 - 2 * alpha * 180 / pif);
result.AddArc(lx - radiusL, -ly - radiusL, 2 * radiusL, 2 * radiusL, 180-180 * alpha / pif, -180 * gamma / pif);
result.AddArc(dxy - radius2, -radius2, 2 * radius2, 2 * radius2, -180 + beta * 180 / pif, 360 - 2 * beta * 180 / pif);
result.AddArc(lx - radiusL, ly - radiusL, 2 * radiusL, 2 * radiusL, 180+180 * (alpha+gamma) / pif, -180 * gamma / pif);
return result;
}
它应该与逻辑测试一起使用,例如:
if (dxy < (radius1 + radius2) && (dxy+Math.Min(radius1,radius2))>Math.Max(radius1,radius2))