| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2234 人关注过本帖
标题:GDI+中,如何沿路径输入文字?
只看楼主 加入收藏
itcat1990
Rank: 1
等 级:新手上路
帖 子:16
专家分:0
注 册:2011-4-16
结帖率:100%
收藏
 问题点数:0 回复次数:7 
GDI+中,如何沿路径输入文字?
GraphicsPath中有一个方法是AddString(..),
然后摆放的文字的坐标通过数学计算也可得出来,
问题是,这些字斜着摆放是怎么实现的呢?
搜索更多相关主题的帖子: 输入文字 
2011-05-31 21:59
vxbb
Rank: 6Rank: 6
等 级:侠之大者
帖 子:163
专家分:440
注 册:2008-8-18
收藏
得分:0 



图片附件: 游客没有浏览图片的权限,请 登录注册


[ 本帖最后由 vxbb 于 2011-5-31 22:12 编辑 ]

QQ:491697374  Mail:vxbb@
2011-05-31 22:10
itcat1990
Rank: 1
等 级:新手上路
帖 子:16
专家分:0
注 册:2011-4-16
收藏
得分:0 
回复 2楼 vxbb
怎么实现的???
2011-05-31 22:12
vxbb
Rank: 6Rank: 6
等 级:侠之大者
帖 子:163
专家分:440
注 册:2008-8-18
收藏
得分:0 

主要用到了高中的数学三角函数、点和直线

 
程序代码:
/*======================================================================
        命名空间名:        DrawContour
        CLR版本:           2.0.50727.1882
        Mail:              vxbb@vip. 491697374
        Created by vxbb    2009-5-3 23:10:44
        Site:              <span style="color: #008000; text-decoration: underline;">http://aocdell.[/color]
======================================================================*/
    // 等值线的定义
    class Isogram
    {
        #region Members

        private int mTagNum;                //标签数量
        private float mInterval;             //间隔
        private float mLength;               //等值线长度
        private GeneralClass mGeneral;
        private TagStru mTagStru;           //标签
        private List<List<Point>> mPoints;  //数据点
        private List<Segment> mTagSegs;     //标签线段

        #endregion Members

        #region Properties

        public int TagNum
        {
            get { return mTagNum; }
            set { mTagNum = value; }
        }

        public float Interval
        {
            get { return mInterval; }
            set { mInterval = value; }
        }

        public float Length
        {
            get { return mLength; }
            set { mLength = value; }
        }

        public TagStru TagStru
        {
            get
            {
                if (mTagStru.Equals(null))
                    mTagStru = new TagStru();
                return mTagStru;
            }
            set
            {
                if (!mTagStru.Equals(null))
                    mTagStru = value;
            }
        }

        public List<List<Point>> Points
        {
            get
            {
                if (mPoints == null)
                    mPoints = new List<List<Point>>();
                return mPoints;
            }
            set
            {
                RemoveAlllist();
                if (value != null)
                {
                    foreach (List<Point> list in value)
                        AddPointList(list);
                }
            }
        }

        public List<Segment> TagSegs
        {
            get
            {
                if (mTagSegs == null)
                    mTagSegs = new List<Segment>();
                return mTagSegs;
            }
            set
            {
                RemoveAllSegment();
                if (value != null)
                {
                    foreach (Segment oSegment in value)
                        AddSegment(oSegment);
                }
            }
        }


        #endregion Properties

        #region Constructors

        public Isogram()
        {
            mGeneral = new GeneralClass();
            mTagSegs = new List<Segment>();
            mPoints = new List<List<Point>>();
        }

        #endregion Constructors

        #region Private Methods

        private void AddPointList(List<Point> list)
        {
            if (list == null)
                return;
            if (mPoints == null)
                mPoints = new List<List<Point>>();
            mPoints.Add(list);
        }
        private List<Point> GetPointList(int index)
        {
            List<Point> list;
            if (mPoints == null)
                list = new List<Point>();
            else
                list = mPoints[index];
            return list;
        }
        private void RemoveList(List<Point> oldlist)
        {
            if (oldlist == null)
                return;
            if (mPoints != null)
                if (mPoints.Contains(oldlist))
                    mPoints.Remove(oldlist);
        }
        private void RemoveAlllist()
        {
            if (mPoints != null)
                mPoints.Clear();
        }

        private void AddSegment(Segment newSegment)
        {
            if (newSegment.GetType() == null)
                return;
            if (mTagSegs == null)
                mTagSegs = new List<Segment>();
            // if (!_tagSegs.Contains(newSegment)) //影响速度
            mTagSegs.Add(newSegment);
        }
        private Segment GetSegment(int index)
        {
            Segment segment;
            if (mTagSegs == null)
                segment = new Segment();
            else
                segment = mTagSegs[index];
            return segment;
        }
        private void RemoveSegment(Segment oldSegment)
        {
            if (oldSegment.GetType() == null)
                return;
            if (mTagSegs != null)
                if (mTagSegs.Contains(oldSegment))
                    mTagSegs.Remove(oldSegment);
        }
        private void RemoveAllSegment()
        {
            if (mTagSegs != null)
                mTagSegs.Clear();
        }


        #endregion Private Methods

        #region Public Methods
      
        //计算等值线注释点
        public void ConIsoLine(List<Point> Points)
        {
            int count = Points.Count;
            List<Point> list = new List<Point>();

            #region 计算等值线总长度

            Point point1, point2;
            for (int i = 0; i < count - 1; i++)
            {
                point1 = Points[i];
                point2 = Points[i + 1];
                mLength += mGeneral.Distance(point1, point2);
            }
         
            #endregion

            #region 计算标签间隔长度

            mInterval = (mLength-mTagStru.Width*mTagNum)/ (mTagNum + 1);
            if (mInterval <= 10)
                throw new Exception("标签数量设置错误");
            float distance = 0;
            Point startPoint = Points[0];

            #endregion

            #region 计算等值线注释点

            for (int i = 0; i < count - 1; i++)
            {
                distance += mGeneral.Distance(startPoint, Points[i + 1]);
                if (distance > mInterval)
                {
                    float R = mInterval - (distance - mGeneral.Distance(startPoint, Points[i + 1]));

                    #region 计算标签 起点、终点

                    Segment lbPoint = new Segment();
                    list.Add(startPoint);
                    lbPoint.StartPoint = mGeneral.GetNextPoint(startPoint, Points[i + 1], R, true);
                    list.Add(lbPoint.StartPoint);
                    mPoints.Add(list);
                    float dis = mGeneral.Distance(lbPoint.StartPoint, Points[i + 1]);
                    if (dis > mTagStru.Width)
                    {
                        lbPoint.EndPoint = mGeneral.GetNextPoint(lbPoint.StartPoint, Points[i + 1], mTagStru.Width, true);
                        i++;
                    }
                    else
                    {
                        for (int j = i + 1; j < count - 1; j++)
                        {
                            dis = mGeneral.Distance(lbPoint.StartPoint, Points[j + 1]);
                            if (dis > mTagStru.Width)
                            {
                                float r = mGeneral.Calculate(lbPoint.StartPoint, Points[j], Points[j + 1], mTagStru.Width);
                                lbPoint.EndPoint = mGeneral.GetNextPoint(Points[j], Points[j + 1], r, true);
                                i = j +1;
                                break;
                            }
                            else if (dis == mTagStru.Width)
                            {
                                lbPoint.EndPoint = Points[j + 1];
                                i = j + 2;
                                break;
                            }
                        }
                    }

                    #endregion
                    if (lbPoint.EndPoint.IsEmpty)
                        continue;
                    mTagSegs.Add(lbPoint);
                    startPoint = lbPoint.EndPoint;
                    list = new List<Point>();
                    distance = 0;
                }
                else if (distance == mInterval)
                {
                    #region 计算标签 起点、终点

                    Segment lbPoint = new Segment();
                    list.Add(startPoint);
                    lbPoint.StartPoint = Points[i + 1];
                    list.Add(lbPoint.StartPoint);
                    mPoints.Add(list);
                    if (mGeneral.Distance(lbPoint.StartPoint, Points[i + 2]) > mTagStru.Width)
                    {
                        lbPoint.EndPoint = mGeneral.GetNextPoint(lbPoint.StartPoint, Points[i + 2], mTagStru.Width, true);
                        i++;
                    }
                    else
                    {
                        for (int j = i + 2; j < count - 2; j++)
                        {
                            float dis = mGeneral.Distance(lbPoint.StartPoint, Points[j + 1]);
                            if (dis > mTagStru.Width)
                            {
                                float r = mGeneral.Calculate(lbPoint.StartPoint, Points[j], Points[j + 1], mTagStru.Width);
                                lbPoint.EndPoint = mGeneral.GetNextPoint(Points[j], Points[j + 1], r, true);
                                i = j + 1;
                                break;
                            }
                            else if (dis == mTagStru.Width)
                            {
                                lbPoint.EndPoint = Points[j + 1];
                                i = j + 2;
                                break;
                            }
                        }
                    }

                    #endregion
                    if (lbPoint.EndPoint.IsEmpty)
                        continue;
                    mTagSegs.Add(lbPoint);
                    startPoint = lbPoint.EndPoint;
                    list = new List<Point>();
                    distance = 0;

                }
                else
                {
                    list.Add(startPoint);
                    startPoint = Points[i + 1];
                }
                if (mTagSegs.Count == mTagNum)
                {
                    list.Add(startPoint);
                    while (i < count)
                    {
                        list.Add(Points[i]);
                        i++;
                    }
                    mPoints.Add(list);
                    break;
                }
            }

            #endregion
        }

        #endregion Public Methods
    }
}



QQ:491697374  Mail:vxbb@
2011-06-01 00:18
vxbb
Rank: 6Rank: 6
等 级:侠之大者
帖 子:163
专家分:440
注 册:2008-8-18
收藏
得分:0 
程序代码:
/*======================================================================
        命名空间名:        DrawContour
        CLR版本:           2.0.50727.1882
        Mail:              vxbb@vip. 491697374
        Created by vxbb    2009-5-3 23:10:44
        Site:              <span style="color: #008000; text-decoration: underline;">http://aocdell.[/color]
======================================================================*/
    class GeneralClass
    {
        //绘制矩形框及文字
        public void RotationAngle(Point start, Point end, Graphics g, Isogram isogram)
        {
            float Heigth, Width;
            Heigth = isogram.TagStru.Heigth;
            Width = isogram.TagStru.Width;
            PointPair pair1 = new PointPair();
            PointPair pair2 = new PointPair();
            pair1 = GetPointPair(start, end, Heigth, true);
            pair2 = GetPointPair(end, start, Heigth, false);

            #region 两线的斜率、截距、角度、趋势和是否存在斜率

            float k12, alpha12;
            float angle;
            bool flag = false;          //是否存在斜率
            bool IsincrX = false;  //趋势

            if (start.X < end.X)
            {
                IsincrX = true;
                flag = false;
            }
            else if (start.X == end.X)
            {
                IsincrX = false;
                flag = true;    //不存在斜率
            }
            else
            {
                IsincrX = false;
                flag = false;
            }

            #endregion

            #region 计算并返回转角

            if (flag)  //斜率不存在时
            {
                if (start.Y > end.Y)
                    angle = 90;
                else
                    angle = 270;
            }
            else
            {
                k12 = (float)(end.Y - start.Y) / (end.X - start.X);
                alpha12 = (float)Math.Atan(k12);
                angle = (float)(180 / Math.PI * alpha12);
            }

            #endregion

            #region 根据有向线段(start,end)绘制文字。

            if (IsincrX)
            {
                Point point = pair1.PointDown;
                g.TranslateTransform(point.X, point.Y);
                g.RotateTransform(angle);
                Pen pen = new Pen(Color.Blue, 1);
                RectangleF myRectangleF =
                                        new RectangleF(0, 0, Width, Heigth);
                Rectangle myRectangle =
                                        new Rectangle(0, 0, Convert.ToInt32(Width), Convert.ToInt32(Heigth));
                //g.FillRectangle(new SolidBrush(Color.FromArgb(120, Color.Black)), myRectangle);
                g.DrawRectangle(pen, myRectangle);
                g.DrawString(isogram.TagStru.Text, isogram.TagStru.Font, Brushes.Red, myRectangleF);
                g.ResetTransform();
            }
            else
            {
                Point point = pair2.PointUp;
                g.TranslateTransform(point.X, point.Y);
                g.RotateTransform(angle);
                Pen pen = new Pen(Color.Red, 1);
                RectangleF myRectangleF =
                                        new RectangleF(0, 0, Width, Heigth);
                Rectangle myRectangle =
                                        new Rectangle(0, 0, Convert.ToInt32(Width), Convert.ToInt32(Heigth));
                //g.FillRectangle(new SolidBrush(Color.FromArgb(120, Color.Black)), myRectangle);
                g.DrawRectangle(pen, myRectangle);
                g.DrawString(isogram.TagStru.Text, isogram.TagStru.Font, Brushes.Blue, myRectangleF);
                g.ResetTransform();
            }

            #endregion

        }
        //余玄定理
        public float Calculate(PointF start, PointF mid, PointF end, float Length)
        {

            float alpha, beta, gamma;//定义角
            PointF a1, a2;//定义向量a1,a2
            a1 = new PointF();
            a2 = new PointF();
            a1.X = start.X - mid.X;
            a1.Y = start.Y - mid.Y;
            a2.X = end.X - mid.X;
            a2.Y = end.Y - mid.Y;

            float length01 = (float)Math.Sqrt(a1.X * a1.X + a1.Y * a1.Y);
            float length12 = (float)Math.Sqrt(a2.X * a2.X + a2.Y * a2.Y);
            alpha = (float)Math.Acos((a1.X * a2.X + a1.Y * a2.Y) / (length01 * length12));//可能有错误!
            beta = (float)Math.Asin(Math.Abs(Math.Sin(alpha) * length01 / Length));//由正玄定理得到B角
            gamma = (float)Math.PI - alpha - beta;
            if (gamma <= 0.18)
            {
                return Length - length01;
            }
            float x = (float)Math.Abs(Length * Math.Sin(gamma) / Math.Sin(alpha));//由正玄定理的到所要求的边
            return x;
        }

        //获取起点沿线段方向移动Length后的坐标,线段:(start-----end),Isforward计算方向
        public Point GetNextPoint(Point start, Point end, float Length, bool Isforward)
        {
            #region 两线的斜率、截距、角度、趋势和是否存在斜率

            float k12, b12, alpha12;
            bool flag = false;          //是否存在斜率
            bool IsincrX = false, IsincrY = false;  //趋势
            IsincrX = start.X < end.X ? true : false;
            IsincrY = start.Y < end.Y ? true : false;
            if (start.X == end.X)
                flag = true;

            #endregion

            #region 计算并返回指定点

            Point point;
            if (flag)  //斜率不存在时
            {
                if (IsincrY)
                    point = new Point(start.X, Convert.ToInt32(start.Y + Length));
                else
                    point = new Point(start.X, Convert.ToInt32(start.Y - Length));
            }
            else
            {
                k12 = (float)(end.Y - start.Y) / (end.X - start.X);
                b12 = start.Y - k12 * start.X;
                alpha12 = (float)Math.Atan(k12);
                point = GetNextPoint(start, alpha12, Length, IsincrX, Isforward);
            }

            #endregion

            return point;
        }

        //获取指定点的下一个点,Isincrease指定直线趋势 ,Isforward计算方向
        public Point GetNextPoint(Point start, float alpha, float Length, bool Isincrease, bool Isforward)
        {
            float deltaX, deltaY;  //坐标增量
            Point point;
            if (Isincrease)
            {
                float Cos = (float)Math.Cos(alpha);
                float Sin = (float)Math.Sin(alpha);
                deltaX = Cos * Length;
                deltaY = Sin * Length;
            }
            else
            {
                float Cos = (float)Math.Cos(alpha);
                float Sin = (float)Math.Sin(alpha);
                deltaX = -1 * Cos * Length;
                deltaY = -1 * Sin * Length;
            }
            try
            {
                if (Isforward)
                    point = new Point(Convert.ToInt32(start.X + deltaX), Convert.ToInt32(start.Y + deltaY));
                else
                    point = new Point(Convert.ToInt32(start.X - deltaX), Convert.ToInt32(start.Y - deltaY));
            }
            catch
            {
                return start;
            }
            return point;
        }

        //获取直线的起点对(方向颠倒时Isforward设置为false)
        public PointPair GetPointPair(Point start, Point end, float width, bool Isforward)
        {
            float k, alpha;
            if (start.X == end.X)
            {
                end.X += 1;
            }
            k = (float)(end.Y - start.Y) / (end.X - start.X);
            alpha = (float)Math.Atan(k);

            float xup, xdown, yup, ydown;
            if (start.X < end.X)
            {
                xup = start.X - (width / 2) * (float)Math.Sin(alpha);
                yup = start.Y + (width / 2) * (float)Math.Cos(alpha);
                xdown = start.X + (width / 2) * (float)Math.Sin(alpha);
                ydown = start.Y - (width / 2) * (float)Math.Cos(alpha);
            }
            else
            {
                xup = start.X + (width / 2) * (float)Math.Sin(alpha);
                yup = start.Y - (width / 2) * (float)Math.Cos(alpha);
                xdown = start.X - (width / 2) * (float)Math.Sin(alpha);
                ydown = start.Y + (width / 2) * (float)Math.Cos(alpha);
            }
            PointPair pointPair = new PointPair();
            if (Isforward)
            {
                pointPair.PointUp = new Point(Convert.ToInt32(xup), Convert.ToInt32(yup));
                pointPair.PointDown = new Point(Convert.ToInt32(xdown), Convert.ToInt32(ydown));
            }
            else
            {
                pointPair.PointUp = new Point(Convert.ToInt32(xdown), Convert.ToInt32(ydown));
                pointPair.PointDown = new Point(Convert.ToInt32(xup), Convert.ToInt32(yup));
            }
            return pointPair;
        }

        //计算两点间的距离
        public float Distance(Point point1, Point point2)
        {
            float length;
            length = (float)Math.Sqrt(Math.Pow((point2.Y - point1.Y), 2) + Math.Pow((point2.X - point1.X), 2));
            return length;
        }
    }


QQ:491697374  Mail:vxbb@
2011-06-01 00:19
vxbb
Rank: 6Rank: 6
等 级:侠之大者
帖 子:163
专家分:440
注 册:2008-8-18
收藏
得分:0 

主要就上面  一个线定义  和 点计算。  剩下画线画字都浮云了

QQ:491697374  Mail:vxbb@
2011-06-01 00:21
vxbb
Rank: 6Rank: 6
等 级:侠之大者
帖 子:163
专家分:440
注 册:2008-8-18
收藏
得分:0 

数据点:
Data.rar (8.06 KB)


Demo
DrawContour.rar (8.86 KB)


QQ:491697374  Mail:vxbb@
2011-06-01 00:27
itcat1990
Rank: 1
等 级:新手上路
帖 子:16
专家分:0
注 册:2011-4-16
收藏
得分:0 
回复 7楼 vxbb
3Q!先学习一下~
2011-06-01 10:28
快速回复:GDI+中,如何沿路径输入文字?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.067472 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved