http://download.csdn.net/detail/hanqi0323/3408968c#中GDI+图形图像:GDI+中的椭圆和弧使用方法|实例
http://www.isstudy.com/cjc/1947.html

解决方案 »

  1.   

    好像根据文字长度,从中间往两边根据椭圆(应该跟外框还有个坐标偏差,就是再内部一个椭圆)进行计算旋转角度、坐标,每个字进行旋转绘制
    http://blog.csdn.net/alicehyxx/article/details/17009271
      

  2.   

    把文字拆分成N个字符
    旋转Graphics对象,绘制文本。
    关于旋转角度的计算和位置,其实都是数学问题,找本书翻翻看看就行了
      

  3.   

    大神们 我知道是gdi 绘图啊,现在我能实现圆形内切文字,但是椭圆形的文字的坐标我不会定位了,这个要怎么来计算呢
      

  4.   

    设椭圆为x^2/a^2+y^2/b^2=1,该点为P(x0,y0)
    则|OP|=√(x0^2+y0^2)=√(x0^2+b^2-b^2x0^2/a^2)=√(b^2+e^2x0^2),(e为椭圆离心率)
    椭圆的离心率:e=c/a(0,1)(c,半焦距;a,半长轴(椭圆)/半实轴(双曲线) )
      

  5.   

    大神 俺数学极差,你的这个公式我有点迷糊哦,现在已知的 椭圆信息
     g.DrawEllipse(new Pen(Brushes.Red, 5), new RectangleF(0, 0, 100, 50));
    那么他的内切文字要用你的公式的话 是怎么算呢? 
      

  6.   

    简单写了个效果
    如图
    lib文件using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Drawing;
    using System.Drawing.Drawing2D;namespace yangzhanglib
    {
        public class DrawString
        {
            /// <summary>
            /// 根据角度 获取椭圆上一点的坐标
            /// x2⒈/a2+y2/b2=1
            /// y = x * tanα
            /// </summary>
            /// <param name="a">长半轴</param>
            /// <param name="b">短半轴</param>
            /// <param name="rotate">角度</param>
            /// <returns></returns>
            public static Point GetCoordinate(int a, int b, float rotate) 
            {
                double x = 0, y = 0, tan = 0, Rad = 0;
                
                if (Math.Abs(rotate) > 90)
                    Rad = (Math.Abs(rotate) - 90);
                else
                    Rad = (90 - Math.Abs(rotate));
                Rad = Rad * 2 * Math.PI / 360;
                tan = Math.Tan(Rad);            x = Math.Sqrt((double)1 / ((double)1 / (a * a) + (tan * tan) / (b * b)));
                y = x * tan;            if (rotate < 0)
                    x = 0 - x;
                if (rotate > -90 && rotate < 90)
                    y = 0 - y;
                x = a + x;
                y = b + y;            return new Point((int)Math.Round(x), (int)Math.Round(y));
            }        public static Bitmap DrawText(string text) 
            {
                char[] texts = text.ToArray();
                int beginRotate = -120;
                int endRotate = 120;
                float Rotate = (float)(endRotate - beginRotate) / (texts.Length - 1);
                int ecllpse_width = 200;
                int ecllpse_height = 150;
                int fontsize = 18;            Bitmap map = new Bitmap(ecllpse_width *2, ecllpse_height *2);
                using (Graphics g = Graphics.FromImage(map)) 
                {
                    g.FillRectangle(new SolidBrush(Color.White),new Rectangle(0,0,(int)ecllpse_width *2, (int)ecllpse_height *2));
                    g.DrawEllipse(new Pen(new SolidBrush(Color.Black), 2) { DashStyle = DashStyle.Dot}, new Rectangle(0, 0, ecllpse_width * 2, ecllpse_height * 2));
                    g.DrawEllipse(new Pen(new SolidBrush(Color.Black), 4), new Rectangle((2 * ecllpse_width / 10), (2 * ecllpse_height / 10), (8 * ecllpse_width / 10) * 2, (8 * ecllpse_height / 10) * 2));                for (int i = 0; i < texts.Length; i++)
                    {
                        Matrix mtxSave = g.Transform;
                        float now_rotate = beginRotate + (Rotate * i);
                        Point p = GetCoordinate(13 * ecllpse_width / 20, 13 * ecllpse_height / 20, beginRotate + (Rotate * i));                    Matrix mtxRotate = g.Transform;
                        p.X +=  ecllpse_width / 4;
                        p.Y +=  ecllpse_height / 4;
                        mtxRotate.RotateAt(beginRotate + (Rotate * i), new PointF(p.X + fontsize, p.Y + fontsize));                    g.Transform = mtxRotate;                    g.DrawString(texts[i].ToString(), new Font("Arial", fontsize), new SolidBrush(Color.Black), p);                    g.Transform = mtxSave;  
                    }
                }
                return map;
            }
            
        }
    }
    页面cs代码using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using yangzhanglib;namespace yangzhang
    {
        public partial class _Default : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                Response.Clear();
                Response.CacheControl = "no-cache";
                Response.ContentType = "image/jpeg";
                using (System.Drawing.Bitmap map = DrawString.DrawText("北京开天科技有限公司样品章")) 
                {
                    byte[] bytes;
                    using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
                    {
                        System.Drawing.Imaging.ImageCodecInfo[] icis = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
                        System.Drawing.Imaging.ImageCodecInfo ici = null;
                        foreach (System.Drawing.Imaging.ImageCodecInfo i in icis)
                        {
                            if (i.MimeType == "image/jpeg")
                            {
                                ici = i;
                            }
                        }
                        System.Drawing.Imaging.EncoderParameters ep = new System.Drawing.Imaging.EncoderParameters(1);
                        ep.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)90);
                        map.Save(ms, ici, ep);                    bytes = ms.ToArray();                    ms.Close();
                        ms.Dispose();
                    }
                    Response.OutputStream.Write(bytes, 0, bytes.Length);
                }
                
            }
        }
    }
    设计页面代码<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="yangzhang._Default" %>
      

  7.   


    非常感谢你的代码,有一点不怎么明白啊,就是定位他的切点位置的算法,我引用了你的切点算法GetCoordinate(),效果是变形的,不知道你下面这句代码写的含义是什么,求解
    Point p = GetCoordinate(13 * ecllpse_width / 20, 13 * ecllpse_height / 20, beginRotate + (Rotate * i));
      

  8.   

    大概是旋转的问题。
    你可以把这句代码
    g.Transform = mtxRotate;
    先注释掉。跑出效果 看看。
    然后根据效果来修正。
      

  9.   


    注释掉会全部乱掉了下面是我的业务代码,调用你的方法后是乱的
    void DrawSealText(Graphics g, Brush myBrush)
            {            if (JianJu == 0)
                {
                    JianJu = 20;
                }
                //\r\n
                TextSealValue = TextSealValue.Replace("\r\n", "");
                int nChinese = TextSealValue.Length;
                String myText = TextSealValue;
                String[] chinese = new string[50];
                int i;            //将单个字保存在数组中
                for (i = 0; i < nChinese; i++)
                {
                    chinese[i] = myText.Substring(i, 1);
                }
                //定义字体大小
                SizeF sf = g.MeasureString(chinese[0], textFont);
                RectangleF rectF = new RectangleF(0, 0, sf.Width, sf.Height);
                //定义字中心到圆心的半径
                float r = Rectangle.Width / 2;
                //定义字的位置
                float xTemp, yTemp;
                //定义字旋转角度
                float angle;            //圆心
                Point cPoint = new Point();
                cPoint.X = this.Rectangle.X + Rectangle.Width / 2;
                cPoint.Y = Rectangle.Y + Rectangle.Height / 2;
                //显示签章单位
                //字体居中
                // Set format of string.
                StringFormat drawFormat = new StringFormat();
                //drawFormat.Trimming = StringTrimming.EllipsisCharacter;
                drawFormat.Alignment = StringAlignment.Center;            //g.TranslateTransform(point.X, point.Y);//设置新的坐标原点             
                //g.RotateTransform(-50);//旋转270度 
                //g.DrawString(myText, myFont, myBrush, rectF, drawFormat);//以新的原点画文本 
                //g.ResetTransform();//还原坐点原点             //字数为偶数时
                if (nChinese % 2 == 0)
                {
                    //显示左半边字
                    for (i = 0; i < nChinese / 2; i++)
                    {
                        angle = (float)((nChinese / 2 - i - 1.0 / 2) * JianJu);
                        sf = g.MeasureString(chinese[i], TextFont);
                        rectF = new RectangleF(0, 0, sf.Width, sf.Height);
                        Point p = GetCoordinate(sf.Width, sf.Height , -angle);
                        //xTemp = (float)(cPoint.X - r * Math.Sin(angle * Math.PI / 180) - sf.Width / 2 * Math.Cos(angle * Math.PI / 180));
                       // yTemp = (float)(cPoint.Y - r * Math.Cos(angle * Math.PI / 180) + sf.Height / 2 * Math.Sin(angle * Math.PI / 180));
                        //g.TranslateTransform(xTemp, yTemp);//设置新的坐标原点 
                        g.TranslateTransform(p.X, p.Y);
                        g.RotateTransform(-angle);//旋转 
                        g.DrawString(chinese[i], TextFont, myBrush, rectF, drawFormat);//以新的原点画文本 
                        g.ResetTransform();//还原坐点原点 
                    }                //显示右半边字
                    for (; i < nChinese; i++)
                    {
                        angle = (float)((i - nChinese / 2 + 1.0 / 2) * JianJu);
                        xTemp = (float)(cPoint.X + r * Math.Sin(angle * Math.PI / 180) - sf.Width / 2 * Math.Cos(angle * Math.PI / 180));
                        yTemp = (float)(cPoint.Y - r * Math.Cos(angle * Math.PI / 180) - sf.Height / 2 * Math.Sin(angle * Math.PI / 180));
                        sf = g.MeasureString(chinese[i], TextFont);
                        rectF = new RectangleF(0, 0, sf.Width, sf.Height);
                        g.TranslateTransform(xTemp, yTemp);//设置新的坐标原点             
                        g.RotateTransform(angle);//旋转 
                        g.DrawString(chinese[i], TextFont, myBrush, rectF, drawFormat);//以新的原点画文本 
                        g.ResetTransform();//还原坐点原点 
                    }
                }            //字数为奇数时
                else
                {
                    //显示左半边字和中间字
                    for (i = 0; i < (nChinese + 1) / 2; i++)
                    {
                        angle = (float)(((nChinese - 1) / 2 - i) * JianJu);
                        sf = g.MeasureString(chinese[i], TextFont);
                        rectF = new RectangleF(0, 0, sf.Width, sf.Height);
                        xTemp = (float)(cPoint.X - r * Math.Sin(angle * Math.PI / 180) - sf.Width / 2 * Math.Cos(angle * Math.PI / 180));
                        yTemp = (float)(cPoint.Y - r * Math.Cos(angle * Math.PI / 180) + sf.Height / 2 * Math.Sin(angle * Math.PI / 180));
                        g.TranslateTransform(xTemp, yTemp);//设置新的坐标原点             
                        g.RotateTransform(-angle);//旋转 
                        g.DrawString(chinese[i], TextFont, myBrush, rectF, drawFormat);//以新的原点画文本 
                        g.ResetTransform();//还原坐点原点 
                    }
                    //显示右半边字
                    for (; i < nChinese; i++)
                    {
                        angle = (float)((i - (nChinese - 1) / 2) * JianJu);//20  为字间距
                        xTemp = (float)(cPoint.X + r * Math.Sin(angle * Math.PI / 180) - sf.Width / 2 * Math.Cos(angle * Math.PI / 180));
                        yTemp = (float)(cPoint.Y - r * Math.Cos(angle * Math.PI / 180) - sf.Height / 2 * Math.Sin(angle * Math.PI / 180));                    sf = g.MeasureString(chinese[i], TextFont);
                        rectF = new RectangleF(0, 0, sf.Width, sf.Height);
                        g.TranslateTransform(xTemp, yTemp);//设置新的坐标原点             
                        g.RotateTransform(angle);//旋转 
                        g.DrawString(chinese[i], TextFont, myBrush, rectF, drawFormat);//以新的原点画文本 
                        g.ResetTransform();//还原坐点原点 
                    }
                }        }
      

  10.   


    GetCoordinate 这个方法传入的width 和 height 如图所示。
    和你传入的参数不一样。首先你要画一个椭圆,然后让文字在这个椭圆上的边上输出。
    达到效果后,把传入的参数传小一点 就可以了。所以我会子啊我的代码里面乘以13/20。
      

  11.   

    我给一个思路,就跟计算机图形学里的纹理映射差不多。可以把椭圆分成外圈和内圈,之间椭圆环是写字的地方。设文字字数为N,椭圆环平分为N+X份。(椭圆环底部不写字)现在问题就是把字符映射到扇形。扇形可能难做,可以把它视为梯形。所以用插值的方法把矩形的字符映射到梯形上。
      

  12.   

    lib 做了调整,画图的思路 使用椭圆内 等边多边形的思路来做。效果图
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Drawing;
    using System.Drawing.Drawing2D;namespace yangzhanglib
    {
        public class DrawString
        {
            /// <summary>
            /// 根据角度 获取椭圆上一点的坐标
            /// x2⒈/a2+y2/b2=1
            /// y = x * tanα
            /// </summary>
            /// <param name="a">长半轴</param>
            /// <param name="b">短半轴</param>
            /// <param name="rotate">角度</param>
            /// <returns></returns>
            public static Point GetCoordinate(int a, int b, float rotate) 
            {
                double x = 0, y = 0, tan = 0, Rad = 0;
                
                if (Math.Abs(rotate) > 90)
                    Rad = (Math.Abs(rotate) - 90);
                else
                    Rad = (90 - Math.Abs(rotate));
                Rad = Rad * 2 * Math.PI / 360;
                tan = Math.Tan(Rad);            x = Math.Sqrt((double)1 / ((double)1 / (a * a) + (tan * tan) / (b * b)));
                y = x * tan;            if (rotate < 0)
                    x = 0 - x;
                if (rotate > -90 && rotate < 90)
                    y = 0 - y;
                x = a + x;
                y = b + y;            return new Point((int)Math.Round(x), (int)Math.Round(y));
            }        public static Bitmap DrawText(string text) 
            {
                char[] texts = text.ToArray();
                int beginRotate = -120;
                int endRotate = 120;
                float Rotate = (float)(endRotate - beginRotate) / (texts.Length - 1);
                int ecllpse_width = 200;
                int ecllpse_height = 150;
                int fontsize = 18;            Bitmap map = new Bitmap(ecllpse_width *2, ecllpse_height *2);
                using (Graphics g = Graphics.FromImage(map)) 
                {
                    g.FillRectangle(new SolidBrush(Color.White),new Rectangle(0,0,(int)ecllpse_width *2, (int)ecllpse_height *2));
                    g.DrawEllipse(new Pen(new SolidBrush(Color.Black), 2) { DashStyle = DashStyle.Dot}, new Rectangle(0, 0, ecllpse_width * 2, ecllpse_height * 2));
                    g.DrawEllipse(new Pen(new SolidBrush(Color.Black), 4), new Rectangle((2 * ecllpse_width / 10), (2 * ecllpse_height / 10), (8 * ecllpse_width / 10) * 2, (8 * ecllpse_height / 10) * 2));                for (int i = 0; i < texts.Length; i++)
                    {
                        Matrix mtxSave = g.Transform;
                        float now_rotate = beginRotate + (Rotate * i);
                        Point p = GetCoordinate(13 * ecllpse_width / 20, 13 * ecllpse_height / 20, beginRotate + (Rotate * i));                    Matrix mtxRotate = g.Transform;
                        p.X +=  ecllpse_width / 4;
                        p.Y +=  ecllpse_height / 4;
                        mtxRotate.RotateAt(beginRotate + (Rotate * i), new PointF(p.X + fontsize, p.Y + fontsize));
                        
                        g.Transform = mtxRotate;                    g.DrawString(texts[i].ToString(), new Font("Arial", fontsize), new SolidBrush(Color.Black), p);                    g.Transform = mtxSave;  
                    }
                }
                return map;
            }        public struct Coordinate
            {
                public int x;
                public int y;
            }        /// <summary>
            /// 获取角度
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <returns></returns>
            public static double GetRotate(double x, double y) 
            {
                if(x < 0 && y < 0)
                    return -270 - Math.Atan2(y, x) * 180 / Math.PI;
                else
                    return 90 - Math.Atan2(y, x) * 180 / Math.PI;
            }        /// <summary>
            /// 一元1次方程求解
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <param name="c"></param>
            /// <param name="d"></param>
            /// <param name="e"></param>
            /// <returns></returns>
            public static double m1(double a, double b)
            {
                return (-1 *  b) / a;
            }        /// <summary>
            /// 一元2次方程求解
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <param name="c"></param>
            /// <param name="d"></param>
            /// <param name="e"></param>
            /// <returns></returns>
            public static double[] m2(double a, double b, double c)
            {
                if (a == 0) return new double[] { m1(b, c) };
                if (c == 0) return new double[] { m1(a, b), 0 };            double Discriminant = b * b - 4 * a * c;
                return new double[]{
                    (-1 * b + Math.Sqrt(Discriminant)) / (2 * a) ,(-1 * b - Math.Sqrt(Discriminant)) / ( 2 * a)
                };
            }        /// <summary>
            /// 盛金公式法 一元3次方程求解
            /// 当A=B=0时,方程有一个三重实根。
            /// 当Δ=B^2-4AC>0时,方程有一个实根和一对共轭虚根。
            /// 当Δ=B^2-4AC=0时,方程有三个实根,其中有一个二重根。
            /// 当Δ=B^2-4AC<0时,方程有三个不相等的实根。
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <param name="c"></param>
            /// <param name="d"></param>
            /// <param name="e"></param>
            /// <returns></returns>
            public static double[] m3(double a, double b, double c, double d)
            {
                if (a == 0) return m2(b, c, d);
                if (d == 0) return m2(a, b, c).Concat(new double[] { 0 }).ToArray();            //重根判别式
                double A = b * b - 3 * a * c;
                double B = b * c - 9 * a * d;
                double C = c * c - 3 * b * d;            //总判别式
                double Discriminant = B * B - 4 * A * C;            if (A == 0 && B == 0) return new double[] { -1 * b / 3 * a };            if (Discriminant > 0) {
                    double Y1 = A * b + 3 * a * (-1 * B + Math.Sqrt(Discriminant)) / 2;
                    double Y2 = A * b + 3 * a * (-1 * B - Math.Sqrt(Discriminant)) / 2;
                    return new double[] { -1 * b - (Math.Pow(Y1, 1.0 / 3.0) + Math.Pow(Y2, 1.0 / 3.0)) / 3 * a };
                }            if (Discriminant == 0) {
                    double K = B / A;
                    return new double[] { (-1 * b / a) + K, -1 * K / 2 };
                }            if (Discriminant < 0) {
                    double T = (2 * A * b - 3 * a * B) / (a * Math.Sqrt(Math.Pow(A, 3)));
                    double O = Math.Acos(T);
                    return new double[] { 
                        (-1 * b - 2 * Math.Sqrt(A) * Math.Cos(O/3))/(3*a),
                        (-1 * b + Math.Sqrt(A) * (Math.Cos(O/3) + Math.Sqrt(3) * Math.Sin(O/3)))/(3*a),
                        (-1 * b + Math.Sqrt(A) * (Math.Cos(O/3) - Math.Sqrt(3) * Math.Sin(O/3)))/(3*a)
                    };
                }            return new double[] { };
            }
      

  13.   

            /// <summary>
            /// 费拉里法 一元4次方程求解
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <param name="c"></param>
            /// <param name="d"></param>
            /// <param name="e"></param>
            /// <returns></returns>
            public static double[] m4(double a, double b, double c, double d, double e)
            {
                if (a == 0) return m3(b, c, d, e);
                if (e == 0) return m3(a, b, c, d).Concat(new double[] { 0 }).ToArray();
                if (a != 1) {
                    b /= a;
                    c /= a;
                    d /= a;
                    e /= a;
                }            // Coefficients for cubic solver
                double cb, cc, cd;
                double discrim, q, r, RRe, RIm, DRe, DIm, dum1, ERe, EIm, s, t, term1, r13, sqR, y1, z1Re, z1Im, z2Re;
                cb = -c;
                cc = -4.0 * e + d * b;
                cd = -(b * b * e + d * d) + 4.0 * c * e;
                q = (3.0 * cc - (cb * cb)) / 9.0;
                r = -(27.0 * cd) + cb * (9.0 * cc - 2.0 * (cb * cb));
                r /= 54.0;
                discrim = q * q * q + r * r;
                term1 = (cb / 3.0);
                if (discrim > 0)
                {
                    // 1 root real, 2 are complex
                    s = r + Math.Sqrt(discrim);
                    s = ((s < 0) ? -Math.Pow(-s, (1.0 / 3.0)) : Math.Pow(s, (1.0 / 3.0)));
                    t = r - Math.Sqrt(discrim);
                    t = ((t < 0) ? -Math.Pow(-t, (1.0 / 3.0)) : Math.Pow(t, (1.0 / 3.0)));
                    y1 = -term1 + s + t;
                }
                else
                {
                    if (discrim == 0)
                    {
                        r13 = ((r < 0) ? -Math.Pow(-r, (1.0 / 3.0)) : Math.Pow(r, (1.0 / 3.0)));
                        y1 = -term1 + 2.0 * r13;
                    }
                    else
                    {
                        q = -q;
                        dum1 = q * q * q;
                        dum1 = Math.Acos(r / Math.Sqrt(dum1));
                        r13 = 2.0 * Math.Sqrt(q);
                        y1 = -term1 + r13 * Math.Cos(dum1 / 3.0);
                    }
                }
                // Determined y1, a real root of the resolvent cubic.
                term1 = b / 4.0;
                sqR = -c + term1 * b + y1;
                RRe = RIm = DRe = DIm = ERe = EIm = z1Re = z1Im = z2Re = 0;
                if (sqR >= 0)
                {
                    if (sqR == 0)
                    {
                        dum1 = -(4.0 * e) + y1 * y1;
                        if (dum1 < 0) //D and E will be complex
                            z1Im = 2.0 * Math.Sqrt(-dum1);
                        else
                        {                      //else (dum1 >= 0)
                            z1Re = 2.0 * Math.Sqrt(dum1);
                            z2Re = -z1Re;
                        }
                    }
                    else
                    {
                        RRe = Math.Sqrt(sqR);
                        z1Re = -(8.0 * d + b * b * b) / 4.0 + b * c;
                        z1Re /= RRe;
                        z2Re = -z1Re;
                    }
                }
                else
                {
                    RIm = Math.Sqrt(-sqR);
                    z1Im = -(8.0 * d + b * b * b) / 4.0 + b * c;
                    z1Im /= RIm;
                    z1Im = -z1Im;
                }
                z1Re += -(2.0 * c + sqR) + 3.0 * b * term1;
                z2Re += -(2.0 * c + sqR) + 3.0 * b * term1;            //At this point, z1 and z2 should be the terms under the square root for D and E
                if (z1Im == 0)
                {               // Both z1 and z2 real
                    if (z1Re >= 0)
                    {
                        DRe = Math.Sqrt(z1Re);
                    }
                    else
                    {
                        DIm = Math.Sqrt(-z1Re);
                    }
                    if (z2Re >= 0)
                    {
                        ERe = Math.Sqrt(z2Re);
                    }
                    else
                    {
                        EIm = Math.Sqrt(-z2Re);
                    }
                }
                else
                {
                    r = Math.Sqrt(z1Re * z1Re + z1Im * z1Im);
                    r = Math.Sqrt(r);
                    dum1 = Math.Atan2(z1Im, z1Re);
                    dum1 /= 2; //Divide this angle by 2
                    ERe = DRe = r * Math.Cos(dum1);
                    DIm = r * Math.Sin(dum1);
                    EIm = -DIm;
                }            return new double[] { 
                    -term1 + (RRe + DRe) / 2 + (RIm + DIm) / 2 ,
                    -(term1 + DRe / 2) + RRe / 2 +  (-DIm + RIm) / 2,
                    -(term1 + RRe / 2) + ERe / 2 + (-RIm + EIm) / 2,
                    -(term1 + (RRe + ERe) / 2) - (RIm + EIm) / 2
                };
            }        public static Coordinate[] GetIntersection(double polygonWidth, double x, double y, double width, double height) 
            {            List<Coordinate> list = new List<Coordinate>();
                double a, b, c, d, e, tan, A, B, C;
                tan = GetRotate(x, y);            A = 1 - (double)Math.Pow(width, 2) / Math.Pow(height, 2);
                B = -2 * y;
                C = Math.Pow(x, 2) + Math.Pow(y, 2) - Math.Pow(polygonWidth, 2) + Math.Pow(width, 2);
                a = Math.Pow(A, 2);
                b = 2 * A * B;
                c = 2 * A * C + Math.Pow(B, 2) + 4 * Math.Pow(x, 2) * Math.Pow(width, 2) / Math.Pow(height, 2);
                d = 2 * B * C;
                e = Math.Pow(C, 2) - 4 * Math.Pow(x, 2) * Math.Pow(width, 2);
                double[] array = m4(a, b, c, d, e);
                for (int i = 0; i < array.Length; i++)
                {
                    double y1 = array[i];
                    if (Math.Abs(y1) > height) continue;                double x1 = width * Math.Sqrt(1 - Math.Pow(y1, 2) / Math.Pow(height, 2));
                    list.Add(new Coordinate() { x = (int)Math.Round(x1), y = (int)Math.Round(y1) });
                    x1 = -1 * x1;
                    list.Add(new Coordinate() { x = (int)Math.Round(x1), y = (int)Math.Round(y1) });
                }
                return list.ToArray(); ;
            }        /// <summary>
            /// 根据椭圆上的一点,求出它顺时针另外的一个点,使这2个点的距离等于一个定值
            /// </summary>
            /// <param name="polygonWidth"></param>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="width"></param>
            /// <param name="height"></param>
            /// <returns></returns>
            public static Coordinate GetNextCoordinate(double polygonWidth, double x, double y, double width, double height)
            {            double tan = GetRotate(x, y);
                Coordinate[] array = GetIntersection(polygonWidth, x, y, width, height);
                
                for (int i = 0; i < array.Length; i++)
                {
                    double y1 = array[i].y ;
                    double x1 = array[i].x;
                    if (GetRotate(x1 , y1) >= tan)
                        return new Coordinate() { x = (int)Math.Round(x1), y = (int)Math.Round(y1) };
                }
                return new Coordinate() { x = 0, y = 0 };
            }        /// <summary>
            /// 根据椭圆上的一点,求出它逆时针另外的一个点,使这2个点的距离等于一个定值
            /// </summary>
            /// <param name="polygonWidth"></param>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="width"></param>
            /// <param name="height"></param>
            /// <returns></returns>
            public static Coordinate GetPrevCoordinate(double polygonWidth, double x, double y, double width, double height)
            {
                double tan = GetRotate(x, y);
                Coordinate[] array = GetIntersection(polygonWidth, x, y, width, height);            for (int i = 0; i < array.Length; i++)
                {
                    double y1 = array[i].y;
                    double x1 = array[i].x;
                    if (GetRotate(x1, y1) <= tan)
                        return new Coordinate() { x = (int)Math.Round(x1), y = (int)Math.Round(y1) };
                }
                return new Coordinate() { x = 0, y = 0 };
            }        /// <summary>
            /// 根据字数的个数,获取指定椭圆内的 等边多边形 各个顶点的直角坐标系的坐标,以数组形式返回
            /// </summary>
            /// <param name="polygonWidth"></param>
            /// <param name="textLength"></param>
            /// <param name="width"></param>
            /// <param name="height"></param>
            /// <returns></returns>
            public static Coordinate[] GetCoordinateArray(int polygonWidth, int textLength, int width, int height)
            {
                Coordinate[] result = new Coordinate[textLength];
                if (textLength % 2 == 0)
                {
                    //偶数个字符
                    int x = polygonWidth / 2;
                    int y = (int)Math.Sqrt(height * height * (1 - (x * x) / (width * width)));                result[textLength / 2] = new Coordinate() { x = -1 * x, y = y };
                    result[(textLength / 2) - 1] = new Coordinate() { x = x, y = y };
                    for (int i = (textLength / 2) - 2; i >= 0; i--)
                    {
                        result[i] = GetPrevCoordinate(polygonWidth, result[i + 1].x, result[i + 1].y, width, height);
                    }
                    for (int i = (textLength / 2) + 1; i < textLength; i++)
                    {
                        result[i] = GetNextCoordinate(polygonWidth, result[i - 1].x, result[i - 1].y, width, height);
                    }
                }
                else
                {
                    //奇数个字符
                    result[(textLength - 1) / 2] = new Coordinate() { x = 0, y = height };                for (int i = (textLength - 1) / 2 - 1; i >= 0; i--)
                    {
                        result[i] = GetPrevCoordinate(polygonWidth, result[i + 1].x, result[i + 1].y, width, height);
                    }
                    for (int i = (textLength - 1) / 2 + 1; i < textLength; i++)
                    {
                        result[i] = GetNextCoordinate(polygonWidth, result[i - 1].x, result[i - 1].y, width, height);
                    }
                }
                return result;
            }
      

  14.   


            public static Bitmap DrawText2(string text)
            {
                int PolygonWidth = 43;
                int ecllpse_width = 200;
                int ecllpse_height = 150;
                int fontsize = 18;            char[] texts = text.ToArray();
                Coordinate[] arrayCoordinate = GetCoordinateArray(PolygonWidth, texts.Length, ecllpse_width * 65 / 100, ecllpse_height * 65 / 100);            Bitmap map = new Bitmap(ecllpse_width * 2, ecllpse_height * 2);
                using (Graphics g = Graphics.FromImage(map))
                {
                    g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, (int)ecllpse_width * 2, (int)ecllpse_height * 2));
                    g.DrawEllipse(new Pen(new SolidBrush(Color.Black), 2) { DashStyle = DashStyle.Dot }, new Rectangle(0, 0, ecllpse_width * 2, ecllpse_height * 2));
                    g.DrawEllipse(new Pen(new SolidBrush(Color.Black), 4), new Rectangle((2 * ecllpse_width / 10), (2 * ecllpse_height / 10), (8 * ecllpse_width / 10) * 2, (8 * ecllpse_height / 10) * 2));
                    for (int i = 0; i < texts.Length; i++)
                    {
                        Matrix mtxSave = g.Transform;
                        float now_rotate = (float)GetRotate(arrayCoordinate[i].x, arrayCoordinate[i].y);
                        Point p = new Point(arrayCoordinate[i].x + ecllpse_width, ecllpse_height - arrayCoordinate[i].y);
                        int fontwidth = (int)g.MeasureString(texts[i].ToString(), new Font("Arial", fontsize)).Width;
                        int fontheight = (int)g.MeasureString(texts[i].ToString(), new Font("Arial", fontsize)).Height;
                        Matrix mtxRotate = g.Transform;
                        p.X -= fontwidth / 2;
                        p.Y -= fontheight / 2;
                        mtxRotate.RotateAt(now_rotate, new PointF(p.X + fontwidth / 2, p.Y + fontheight / 2));
                        g.Transform = mtxRotate;                    g.DrawString(texts[i].ToString(), new Font("Arial", fontsize), new SolidBrush(Color.Black), p);                    g.Transform = mtxSave;
                    }
                }
                return map;
            }
        }
    }
      

  15.   


    const double RAD_ANG = 57.295779513082320876798154814105;void DrawBitmap(Bitmap bitmap, string text, Font font, int startAngle, int endAngle, Color color, float padding)
            {
                if(String.IsNullOrEmpty(text))
                    return;
                if (endAngle < startAngle)
                    endAngle += 360;
                int width = bitmap.Width;
                int height = bitmap.Height;
                char[] textArray = text.ToArray();
                int length = textArray.Length;
                double aAngle = (1.0d * (endAngle - startAngle)) / Math.Max(length - 1, 1);
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    Pen pen = new Pen(color, 4f);
                    SolidBrush brushFont = new SolidBrush(color);
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    g.PageUnit = GraphicsUnit.Pixel;
                    SizeF sf = g.MeasureString(textArray[0].ToString(), font);
                    double a = (width - 1 - sf.Width - padding) / 2 - pen.Width;
                    double b = (height - 1 - sf.Height - padding) / 2 - pen.Width;
                    double x0 = width / 2f;
                    double y0 = height / 2f;
                    g.DrawEllipse(pen, (float)(x0 - a) - (sf.Width + padding + pen.Width) / 2, (float)(y0 - b) - (sf.Height + padding + pen.Width) / 2, (float)(2 * a) + sf.Width + padding + pen.Width, (float)(2 * b) + sf.Height + padding + pen.Width);
                    for (int i = 0; i < length; i++)
                    {
                        double r = (startAngle + (i * aAngle)) / RAD_ANG;
                        double x = x0 + (float)(a * Math.Cos(r));
                        double y = y0 + (float)(b * Math.Sin(r));
                        double k = -(((b * b) * (x - x0)) / ((a * a) * (y - y0)));
                        double kAngle = (Math.Atan(k) / (Math.PI / 180d));
                        //g.DrawLine(SystemPens.WindowText, (float)x0, (float)y0, (float)x, (float)y);//test
                        Matrix matrixSave = g.Transform;
                        Matrix matrixNow = g.Transform;                    sf = g.MeasureString(textArray[i].ToString(), font);
                        PointF pointFont = new PointF((float)(x - sf.Width / 2), (float)(y - sf.Height / 2));
                        kAngle += x < x0 ? -180 : 180;
                        kAngle += y < y0 ? 180 : 0;                    matrixNow.RotateAt((float)kAngle, new PointF((float)x, (float)y));
                        g.Transform = matrixNow;
                        //g.DrawRectangle(SystemPens.WindowText, pointFont.X, pointFont.Y, sf.Width, sf.Height);//test
                        g.DrawString(textArray[i].ToString(), font, brushFont, pointFont);
                        g.Transform = matrixSave;
                    }
                    pen.Dispose();
                    brushFont.Dispose();
                }
            }test codeprotected override void OnPaint(PaintEventArgs e)
            {
                string text = "中华人民共和国";
                using (Font font = new System.Drawing.Font(Font.FontFamily, 18f, FontStyle.Bold))
                {
                    using (Bitmap bitmap = new Bitmap(Width, Height))
                    {
                        DrawBitmap(bitmap, text, font, 150, 30, Color.Black, 10f);
                        using (Graphics g = e.Graphics)
                        {
                            g.DrawImage(bitmap, 0, 0, Width, Height);
                        }
                    }
                }
                base.OnPaint(e);
            }
      

  16.   


    思路改了下
    计算出来坐标 增加了验证功能。
    内部的椭圆不是百分比计算 而是减少固定的长度
    文字旋转率 是椭圆切线率  而不是到原点的角度。static Coordinate[] GetIntersection(double polygonWidth, double x, double y, double width, double height) 
            {            List<Coordinate> list = new List<Coordinate>();
                double a, b, c, d, e, tan, A, B, C;
                tan = GetRotate(x, y);            A = 1 - (double)Math.Pow(width, 2) / Math.Pow(height, 2);
                B = -2 * y;
                C = Math.Pow(x, 2) + Math.Pow(y, 2) - Math.Pow(polygonWidth, 2) + Math.Pow(width, 2);
                a = Math.Pow(A, 2);
                b = 2 * A * B;
                c = 2 * A * C + Math.Pow(B, 2) + 4 * Math.Pow(x, 2) * Math.Pow(width, 2) / Math.Pow(height, 2);
                d = 2 * B * C;
                e = Math.Pow(C, 2) - 4 * Math.Pow(x, 2) * Math.Pow(width, 2);
                double[] array = m4(a, b, c, d, e);
                for (int i = 0; i < array.Length; i++)
                {
                    double y1 = array[i];
                    if (Math.Abs(y1) > height) continue;
                    double x1 = width * Math.Sqrt(1 - Math.Pow(y1, 2) / Math.Pow(height, 2));
                    if ( Math.Round((double)Math.Pow(x1, 2) / Math.Pow(width, 2) + (double)Math.Pow(y1, 2) / Math.Pow(height, 2)) == 1) 
                        if (Math.Round((double)Math.Pow(x1 - x, 2) + (double)Math.Pow(y1 - y, 2)) == Math.Pow(polygonWidth,2))
                            list.Add(new Coordinate() { x = (int)Math.Round(x1), y = (int)Math.Round(y1) });                x1 = -1 * x1;
                    if (Math.Round((double)Math.Pow(x1, 2) / Math.Pow(width, 2) + (double)Math.Pow(y1, 2) / Math.Pow(height, 2)) == 1)
                        if (Math.Round((double)Math.Pow(x1 - x, 2) + (double)Math.Pow(y1 - y, 2)) == Math.Pow(polygonWidth, 2))
                            list.Add(new Coordinate() { x = (int)Math.Round(x1), y = (int)Math.Round(y1) });
                }
                return list.ToArray(); ;
            }public static Bitmap DrawText2(string text)
            {
                int PolygonWidth = 33;
                int ecllpse_width = 150;
                int ecllpse_height = 100;
                int fontsize = 18;
                int firstpadding = 10;
                int secondpadding = 30;            char[] texts = text.ToArray();
                Coordinate[] arrayCoordinate = GetCoordinateArray(PolygonWidth, texts.Length, ecllpse_width - secondpadding, ecllpse_height - secondpadding);            Bitmap map = new Bitmap(ecllpse_width * 2, ecllpse_height * 2);
                using (Graphics g = Graphics.FromImage(map))
                {
                    g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, (int)ecllpse_width * 2, (int)ecllpse_height * 2));
                    g.DrawEllipse(new Pen(new SolidBrush(Color.Black), 2) { DashStyle = DashStyle.Dot }, new Rectangle(0, 0, ecllpse_width * 2, ecllpse_height * 2));
                    g.DrawEllipse(new Pen(new SolidBrush(Color.Black), 4), new Rectangle(10, 10, (ecllpse_width - firstpadding) * 2, (ecllpse_height - firstpadding) * 2));
                    
                    for (int i = 0; i < texts.Length; i++)
                    {
                        Matrix mtxSave = g.Transform;
                        float now_rotate = (float)(-1 * Math.Pow(ecllpse_height - secondpadding, 2) * arrayCoordinate[i].x / (Math.Pow(ecllpse_width - secondpadding, 2) * arrayCoordinate[i].y));
                        now_rotate = (float)Math.Atan(now_rotate);
                        if (arrayCoordinate[i].y > 0)
                            now_rotate = (float)(-1 * now_rotate * 180 / Math.PI);
                        else
                            now_rotate = (float)(180 -1 * now_rotate * 180 / Math.PI);                    Point p = new Point(arrayCoordinate[i].x + ecllpse_width, ecllpse_height - arrayCoordinate[i].y);                    int fontwidth = (int)g.MeasureString(texts[i].ToString(), new Font("Arial", fontsize)).Width;
                        int fontheight = (int)g.MeasureString(texts[i].ToString(), new Font("Arial", fontsize)).Height;                    Matrix mtxRotate = g.Transform;
                        p.X -= fontwidth / 2;
                        p.Y -= fontheight / 2;
                        mtxRotate.RotateAt(now_rotate, new PointF(p.X + fontwidth / 2, p.Y + fontheight / 2));
                        //mtxRotate.RotateAt(now_rotate, new PointF(p.X + fontwidth / 2, p.Y));
                        g.Transform = mtxRotate;                    g.DrawString(texts[i].ToString(), new Font("Arial", fontsize), new SolidBrush(Color.Black), p);                    g.Transform = mtxSave;
                    }
                }
                return map;
            }
      

  17.   


                    Graphics g2 = e.Graphics;
                    PointF cnter = new PointF(300, 300);//中心点
                    float radX = 200F, radY = 130F, totalArcAng = 260;//x半径、y半径和所在弧角度
                    float minRat = 6f;//从边线向中心的移动因子
                    string text = "北京开天科技有限公司样品章";
                    //
                    g2.DrawEllipse(pen, cnter.X - radX, cnter.Y - radY, radX * 2, radY * 2);
                    Font font = new Font("宋体", 23F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(134)));
                    double startAng = -90F - totalArcAng / 2f, endAng = -90f + totalArcAng / 2f;
                    int count = text.Length;
                    double accArcLen = 0.0, step = 0.5;
                    int alCount = (int)Math.Ceiling(totalArcAng / step);
                    double[] angArr = new double[alCount];
                    double[] arcLenArr = new double[alCount];
                    int num = 0;
                    for (double i = startAng; i < endAng; i += step)
                    {
                        double angR = i * Math.PI / 180.0;
                        double x = radX * Math.Cos(angR) + cnter.X, y = radY * Math.Sin(angR) + cnter.Y;
                        angR = (i + step) * Math.PI / 180.0;
                        double x2 = radX * Math.Cos(angR) + cnter.X, y2 = radY * Math.Sin(angR) + cnter.Y;
                        accArcLen += Math.Sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y));
                        angArr[num] = i + step;
                        arcLenArr[num] = accArcLen;
                        num++;
                    }
                    double arcPer = accArcLen / count;
                    //
                    for (int i = 0; i < count; i++)
                    {
                        double myt = i * arcPer + arcPer / 2.0;
                        //
                        double ang = 0.0;
                        for (int p = 0; p < arcLenArr.Length - 1; p++)
                        {
                            if (arcLenArr[p] <= myt && myt <= arcLenArr[p + 1])
                            {
                                ang = angArr[p + 1];
                                break;
                            }
                        }
                        double angR = (ang * Math.PI / 180f);
                        float x = radX * (float)Math.Cos(angR) + cnter.X, y = radY * (float)Math.Sin(angR) + cnter.Y;
                        double qxang = Math.Atan2(radY * Math.Cos(angR), -radX * Math.Sin(angR)), fxang = qxang + Math.PI / 2.0;
                        string c = text.Substring(i, 1);
                        float w = g2.MeasureString(c, font).Width, h = g2.MeasureString(c, font).Height;
                        //
                        Matrix mat = g2.Transform;
                        g2.TranslateTransform(-w / 2f * (float)Math.Cos(qxang), -w / 2f * (float)Math.Sin(qxang));
                        g2.TranslateTransform(h / minRat * (float)Math.Cos(fxang), h / minRat * (float)Math.Sin(fxang));
                        g2.TranslateTransform(x, y);
                        g2.RotateTransform((float)(fxang * 180.0 / Math.PI - 90));
                        g2.TranslateTransform(-x, -y);
                        g2.DrawString(c, font, Brushes.Black, x, y);
                        g2.Transform = mat;
                    }
      

  18.   


            /// <summary>
            /// 
            /// </summary>
            /// <param name="g2"></param>
            /// <param name="font"></param>
            /// <param name="center"></param>
            /// <param name="radiusX"></param>
            /// <param name="radiusY"></param>
            /// <param name="totalArcAng">总的角跨度</param>
            /// <param name="minRat">从边线向中心的移动因子</param>
            /// <param name="text">字符串</param>
            /// <param name="top">是上边吗?</param>
            private void PaintOneText(Graphics g2, Font font, PointF center, float radiusX, float radiusY,//
                float totalArcAng, float minRat, string text, bool top)
            {
                double startAng = top ? -90F - totalArcAng / 2f : 90F - totalArcAng / 2f;
                double endAng = top ? -90f + totalArcAng / 2f : 90F + totalArcAng / 2f;
                int count = text.Length;
                double step = 0.5;
                int alCount = (int)Math.Ceiling(totalArcAng / step) + 1;
                double[] angArr = new double[alCount];
                double[] arcLenArr = new double[alCount];
                int num = 0;
                double accArcLen = 0.0;
                angArr[num] = startAng;
                arcLenArr[num] = accArcLen;
                num++;
                double angR = startAng * Math.PI / 180.0;
                double lastX = radiusX * Math.Cos(angR) + center.X;
                double laxtY = radiusY * Math.Sin(angR) + center.Y;
                for (double i = startAng + step; num < alCount; i += step)
                {
                    angR = i * Math.PI / 180.0;
                    double x = radiusX * Math.Cos(angR) + center.X, y = radiusY * Math.Sin(angR) + center.Y;
                    accArcLen += Math.Sqrt((lastX - x) * (lastX - x) + (laxtY - y) * (laxtY - y));
                    angArr[num] = i;
                    arcLenArr[num] = accArcLen;
                    lastX = x;
                    laxtY = y;
                    num++;
                }
                double arcPer = accArcLen / count;
                //
                for (int i = 0; i < count; i++)
                {
                    double arcL = i * arcPer + arcPer / 2.0;
                    //
                    double ang = 0.0;
                    for (int p = 0; p < arcLenArr.Length - 1; p++)
                    {
                        if (arcLenArr[p] <= arcL && arcL <= arcLenArr[p + 1])
                        {
                            ang = (arcL >= ((arcLenArr[p] + arcLenArr[p + 1]) / 2.0)) ? angArr[p + 1] : angArr[p];
                            break;
                        }
                    }
                    angR = (ang * Math.PI / 180f);
                    float x = radiusX * (float)Math.Cos(angR) + center.X, y = radiusY * (float)Math.Sin(angR) + center.Y;
                    double qxang = Math.Atan2(radiusY * Math.Cos(angR), -radiusX * Math.Sin(angR)), fxang = qxang + Math.PI / 2.0;
                    string c = text.Substring(top ? i : text.Length - 1 - i, 1);
                    float w = g2.MeasureString(c, font).Width, h = g2.MeasureString(c, font).Height;
                    if (top)
                    {
                        x += h * minRat * (float)Math.Cos(fxang);
                        y += h * minRat * (float)Math.Sin(fxang);
                        x += -w / 2f * (float)Math.Cos(qxang);
                        y += -w / 2f * (float)Math.Sin(qxang);
                    }
                    else
                    {
                        x += (h * minRat + h) * (float)Math.Cos(fxang);
                        y += (h * minRat + h) * (float)Math.Sin(fxang);
                        x += w / 2f * (float)Math.Cos(qxang);
                        y += w / 2f * (float)Math.Sin(qxang);
                    }
                    //
                    Matrix mat = g2.Transform;
                    g2.TranslateTransform(x, y);
                    if (top)
                        g2.RotateTransform((float)(fxang * 180.0 / Math.PI - 90));
                    else
                        g2.RotateTransform((float)(fxang * 180.0 / Math.PI + 180 - 90));
                    g2.TranslateTransform(-x, -y);
                    g2.DrawString(c, font, Brushes.Black, x, y);
                    g2.Transform = mat;
                }
            }        /// <summary>
            /// 绘制印章
            /// 给定椭圆的中心,两个半径和文字所跨的角度来绘制。先求总的弧长,然后均分,每个字所占据的弧长相等。
            /// 难点在于如何求弧长和角度的对应关系,我采取的办法是先求出一个对应表:从最小角度到最大角度,每0.5度
            /// 递增,求出各段弧长累加即得到对应表。
            /// 由弧长查角度的时候,从表中找到该弧长所在的闭区间,就得到对应的角度
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void PainYinZhang(object sender, PaintEventArgs e)
            {
                Graphics g2 = e.Graphics;
                PointF center = new PointF(300, 300);//中心点
                float radiusX = 200F, radiusY = 130F;//x半径、y半径
                Font font = new Font("宋体", 23F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(134)));
                //
                g2.DrawEllipse(pen, center.X - radiusX, center.Y - radiusY, radiusX * 2, radiusY * 2);
                PaintOneText(g2, font, center, radiusX, radiusY, 160, 0.20f, "山西开天电子有限公司", true);
                PaintOneText(g2, font, center, radiusX, radiusY, 90, -0.05f, "发票专用章", false);
            }