前言 本人在業余時間,開發了一款電子印章制作軟件。印章制作軟件看似簡單,其實不然。
比如對橢圓形印章而言,要求公司名稱中的每一個字間隔相等,要求字的方向與橢圓曲線垂直。
要滿足這些條件,需要復雜的計算,並且要有一定的幾何學基礎。軟件界面如下:
本文主要講述橢圓形印章制作思路,對於圓形印章 ,軟件開發難度並不大。
橢圓印章要滿足以下兩個條件:
1 公司名稱字體間隔大小要一樣。
2 字體方向與對應的橢圓曲線是相切的。
下面分析如何通過程序滿足這兩點要求。
1 計算橢圓的弧線長度
假設公司名稱占了橢圓220度邊長,如何計算出220度弧線的長度? 肯定有數學公式可以計算。我沒有用公式計算。我聯想到了“微積分”的概念。可以將這一段弧線切成幾千份小的弧線,把小的弧線段長度加起來就是總的長度。小的弧線段長度非常小,可以用兩點之間的直線長度代替。
假設將弧線分成n份,將這n個線段長度加起來就是弧線長度。
/// <summary> /// 將弧線分成splitCount份,計算弧線上的點 /// </summary> /// <param name="startDegree">弧線起始度數</param> /// <param name="splitCount">分成多少份</param> /// <returns></returns> List<PointDouble> GetDrawPoint(double startDegree, int splitCount) { double a = EllipseWidth / 2; double b = EllipseHeight / 2; List<PointDouble> result = new List<PointDouble>(); Graphics g = Graphics; for (int i = 0; i < splitCount; i++) { double degree = startDegree + (i * CompanySpanDegree) / splitCount; double k = Math.Tan(ToArc(degree)); //Debug.WriteLine(string.Format("degree:{0}", degree)); PointDouble ptDraw = new PointDouble(); if (degree < 90) { if (intersections[0].X < 0) { ptDraw = intersections[0]; } else if (intersections[0].X > 0) { ptDraw = intersections[1]; } else { } } else if (degree > 90) { if (intersections[0].X > 0) { ptDraw = intersections[0]; } else if (intersections[0].X < 0) { ptDraw = intersections[1]; } else { } } else { if (intersections[0].Y < 0) { ptDraw = intersections[0]; } else { ptDraw = intersections[1]; } } result.Add(ptDraw); } return result; }
2 確定每個文字的坐標。
弧線總長度計算處理后,就可以算出每個文字占用的弧線長度,根據每個文字占用的弧線長度就可以計算出文字的坐標。
List<PointDouble> CalDrawPoint(float startDegree, int txtCount) { List<double> listLenPart = new List<double>(); List<PointDouble> listPoint = GetDrawPoint(startDegree, 10000); //計算弧線長度 double arcLen = ; //每個文字占用的弧線長度 double txtSpanPer = arcLen / (txtCount - 1); //計算文字對應的點 List<PointDouble> result = new List<PointDouble>(); result.Add(listPoint[0]); double lenSpanCal = 0; for (int i = 0; i < listLenPart.Count; i++) { double n = listLenPart[i]; lenSpanCal += n; if (lenSpanCal >= txtSpanPer) { result.Add(listPoint[i + 1]); lenSpanCal = 0; } } if (result.Count < txtCount) result.Add(listPoint.Last()); Debug.Assert(result.Count == txtCount); return result; }
3 計算文字的旋轉角度
確定了文字的坐標后,就可以計算出該點對應的切線,從而求出切線角度。切線公式如下:
計算切線坐標源碼如下:
/// <summary> /// 計算橢圓切線的角度 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> float CalTangentLineDegree(float x, float y) { if (y == 0) return 90; float a = EllipseWidth / 2; float b = EllipseHeight / 2; float k = -b * b * x / (a * a * y); float result = (float)Math.Atan(k); result = (float)ToDegree(result); return result; }
文字的坐標和旋轉角度確定后,后續處理就水到渠成:
程序界面截圖: