求助!
怎样在屏幕坐标系中,画出给定多边形各个顶点角的角平分线?

解决方案 »

  1.   

    假设你的多边形都是凸多边形
            private void DrawMidLine(Point startPoint, Point endPoint1,Point endPoint2)
            {
                double angle1 = GetLineAngle(startPoint, endPoint1);
                double angle2 = GetLineAngle(startPoint, endPoint2);            if (angle1 == angle2) return;            double linesAngle = Math.Abs(angle2 - angle1);            double newAngle = 0;
                if (linesAngle <= Math.PI)
                    newAngle = angle1 < angle2 ? angle1 + linesAngle / 2 : angle2 + linesAngle / 2;
                else
                {
                    linesAngle = Math.PI * 2 - linesAngle;
                    newAngle = angle1 > angle2 ? angle1 + linesAngle / 2 : angle2 + linesAngle / 2;
                }            DrawAtAngle(newAngle);
            }        private double GetLineAngle(Point start, Point end)
            {
                double diffX = end.X - start.X;
                double diffY = end.Y - start.Y;            double tan=0,angle=0;
                if (diffY!=0)
                {
                    tan = Math.Abs(diffX / diffY);
                    angle  = Math.Atan(tan);
                }
                else
                    tan = Math.PI / 2;
                if (diffX >= 0)
                {
                    if (diffY > 0)
                        angle = Math.PI - angle;
                }
                else
                {
                    if (diffY > 0)
                        angle = Math.PI + angle;
                    else
                        angle = Math.PI * 2 - angle;
                }
                return angle;
            }        private void DrawAtAngle(double angle)
            {
                while (angle > Math.PI * 2)
                    angle = angle - Math.PI * 2;
                
                double calAngle = angle;            if ((angle > Math.PI / 2) && (angle <= Math.PI))
                {
                    calAngle = Math.PI - angle;
                }
                else if ((angle > Math.PI) && (angle <= Math.PI * 1.5))
                {
                    calAngle = angle - Math.PI;
                }
                else if ((angle > Math.PI * 1.5) && (angle <= Math.PI * 2))
                {
                    calAngle = Math.PI * 2 - angle;
                }            int y = 50;
                int x = (int)(Math.Tan(calAngle) * y);
                Point newPoint = new Point(-1, -1); ;            if (angle <= Math.PI / 2)
                {
                    newPoint.X = startPoint.X + x;
                    newPoint.Y = startPoint.Y - y;
                }
                else if ((angle > Math.PI / 2) && (angle <= Math.PI))
                {
                    newPoint.X = startPoint.X + x;
                    newPoint.Y = startPoint.Y + y;
                }
                else if ((angle > Math.PI) && (angle <= Math.PI * 1.5))
                {
                    newPoint.X = startPoint.X - x;
                    newPoint.Y = startPoint.Y + y;
                }
                else if ((angle > Math.PI * 1.5) && (angle <= Math.PI * 2))
                {
                    newPoint.X = startPoint.X - x;
                    newPoint.Y = startPoint.Y - y;
                }            Graphics g = this.CreateGraphics();
                Pen blackPen = new Pen(Color.Black, 1);            g.DrawLine(blackPen, startPoint, newPoint);
            }思路,分别计算出两条线和坐标系Y轴正方向的夹角,相减得到两条线之间的夹角,算出平分线和Y轴正方向的夹角,找到这条线上的一个点,就可以从顶点处到这个点间划线。
      

  2.   

    感谢noahfang的解答,多边形为凸多边形,各个定点存储在数组中,您的函数DrawMidLine(Point   startPoint,   Point   endPoint1,Point   endPoint2)怎么调用,我试了一下怎么没有什么变化,是不是我调用函数不对?
     还有您为什么要从Y轴的夹角着手,这样有什么优点么。拜托不吝赐教!急等
      

  3.   

    以Y轴正方向为基准没有什么特别的理由,用X轴也一样。
    主函数就是DrawMidLine,我不知道你每个点是用什么格式存储的,我用的是Point类。另外我也不清楚你是要在什么地方画图,我直接画在窗体上的,如果你要画到其他控件,修改一下DrawAtAngle方法,调用那个控件的CreateGraphics方法获得Graphics类。
      

  4.   

    谢谢回复!
    我也是用POINT类来存储数据的,直接在窗体上绘图。
    不好意思数学功底差,我还没有看懂您分类的依据,您能帮我解释一下您的代码吗?
      

  5.   

    GetLineAngle(Point   start,   Point   end)方法是计算start和end决定的直线和Y轴正方向之间的夹角,以start为原点,end和start X坐标的差就是end到Y轴的垂直距离,用diffX表示,end和start Y坐标的差就是end到X轴的垂直距离,用diffY表示,diffX/diffY就是此线和Y轴夹角的tan值,用反tan函数得到角度a。但是我这里用的是diffX/diffY绝对值计算的,因此得到的是和Y轴之间的锐角。画个图应该直观些,可惜加不了附件。总之,end在第1象限,这个角就是我们要求的角,在第2象限,这个角是此线和Y轴负方向的夹角,因此要用PI(180度)-a才是我们要的角。同样,在第3象限,是PI+a,在第4象限是2PI-a。这样算出两条线的角度a1,a2,假设a1<a2,a2-a1就是他们的夹角b,但是这里要注意,因为处理的是凸多边形,夹角必须小于PI,而有时候这样算出来会大于PI,比如一条线在第1象限而另一条在第3象限,这种情况实际我们需要的是b的对顶角,即2PI-b。如果a2-a1<PI,平分线的角度就是a1+b/2,如果a2-a1>PI,平分线的角度就是a2+b/2.DrawAtAngle(double   angle)方法画出和Y轴正方向夹角是angle的线,其实就是找出这条线上的一个点,假设这个点和start点的Y坐标差是50,用根据已知角度的TAN值可以算出X坐标差,从而得到这个点的坐标,就能画出平分线了。我有一个疏忽,DrawAtAngle方法中我用到了一个startPoint,这个我是定义在窗体级的,这个实际就是角的顶点,把DrawAtAngle方法定义改为DrawAtAngle(point startPoint,double angle),在DrawMidLine方法中把调用的这句改为DrawAtAngle(startPoint,newAngle)看看是否能工作。
      

  6.   

    感谢noahfang的悉心解释。基本原理已经明白了,参考解释,我觉得calangle已经为锐角了,所以x与y应该是大于零的数字,按照calangle定义及象限分法以下代码中计算newpoint的坐标时应该改为
    if   (angle   <=   Math.PI   /   2) 
                            { 
                                    newPoint.X   =   startPoint.X   +   x; 
                                    newPoint.Y   =   startPoint.Y   +   y; 
                            } 
                            else   if   ((angle   >   Math.PI   /   2)   &&   (angle   <=   Math.PI)) 
                            { 
                                    newPoint.X   =   startPoint.X   +   x; 
                                    newPoint.Y   =   startPoint.Y   -   y; 
                            } 
                            else   if   ((angle   >   Math.PI)   &&   (angle   <=   Math.PI   *   1.5)) 
                            { 
                                    newPoint.X   =   startPoint.X   -   x; 
                                    newPoint.Y   =   startPoint.Y   -   y; 
                            } 
                            else   if   ((angle   >   Math.PI   *   1.5)   &&   (angle   <=   Math.PI   *   2)) 
                            { 
                                    newPoint.X   =   startPoint.X   -   x; 
                                    newPoint.Y   =   startPoint.Y   +   y; 
                            } 
    不知道合适否?请高手帮我看看,解释原因!
      

  7.   

    坐标系是否是这么定义的吗?
    ^X
    |
    |
    |
    |___________________>Y
    (0,0)
    to:烟头上的探戈
    具体怎么实现。估计这样比现在讨论的这个方法还要计算麻烦吧?
      

  8.   

    最后算出的坐标是窗体坐标系里的,以窗体左上角为原点,越往下Y坐标越大。而我们计算出的角度是以顶点为原点的,不要搞混了。因此,如果newpoint在以顶点为原点的坐标系中位于第1象限,也就是在顶点上方,那么在窗体坐标系里的Y坐标要小于顶点。其他象限类推。
      

  9.   

    TO:noahfang
    我刚刚接触这一块还不是很懂,想请教您:如何给一个多边形中画半径R以d递增的圆,使得圆与多边形至少两个边相切,且始终保证圆范围落在多边形内。
    如何的得到圆的圆心坐标和半径?还请大虾多多指导,最好给个示例!万分感谢!!!