【问题标题】:How to join or blend two ellipses together when they overlap当两个椭圆重叠时如何将它们连接或混合在一起
【发布时间】:2014-12-06 05:27:02
【问题描述】:

想知道当椭圆相互接触时是否有混合椭圆的功能。我在考虑一个 GraphicsPath 对象,因为它将对象添加到它的路径中。如果有一个术语,我不知道它会是什么,所以到目前为止搜索还没有发现任何东西。感谢您的指导。

目标图片(大致):

【问题讨论】:

    标签: gdi+ graphicspath


    【解决方案1】:

    我不知道你能做到这一点,但为了你的特定目标,你可以用这样的东西重新计算路径(使用双缓冲):

        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))
    

    【讨论】:

    • 谢谢。我会试试的。我从哪里获得 dxy 值?
    • dxy 是两个圆的中心之间的距离:dxy = Math.Sqrt ( (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
    猜你喜欢
    • 2017-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    • 2023-02-25
    • 1970-01-01
    • 2015-10-31
    相关资源
    最近更新 更多