10 |
10 |
|
11 |
11 |
namespace MarkupToPDF.Controls_PDF
|
12 |
12 |
{
|
13 |
|
public class HoneyPDFLib_DrawSet_Cloud : BaseMethod
|
|
13 |
public class DrawSet_Cloud : BaseMethod
|
14 |
14 |
{
|
15 |
15 |
public static Point nextPoint = new Point(0, 0);
|
16 |
16 |
|
17 |
|
public static double returnAngle(Point start, ref Point end)
|
|
17 |
public static double returnAngle(Point start, Point end)
|
18 |
18 |
{
|
19 |
19 |
double angle = MathSet.getAngle(start.X, start.Y, end.X, end.Y);
|
20 |
|
//angle *= -1;
|
21 |
|
|
22 |
20 |
angle += 90;
|
23 |
|
//if (angle < 0)
|
24 |
|
//{
|
25 |
|
// angle = angle + 360;
|
26 |
|
//}
|
|
21 |
|
27 |
22 |
return angle;
|
28 |
23 |
}
|
29 |
24 |
|
30 |
|
public static void GenerateLineWithCloud(Point p1, Point p2, double arcLengthOrigin, PdfContentByte contentByte, double boundAngle, double fixAngle)
|
31 |
|
{
|
32 |
|
var arcLength = arcLengthOrigin / 3.0; // 임의값. 실제로는 ZoomSize와 결합해서 전달할 것
|
33 |
|
|
|
25 |
/// <summary>
|
|
26 |
/// generate cloud between given p1 and p2
|
|
27 |
/// </summary>
|
|
28 |
/// <param name="p1"></param>
|
|
29 |
/// <param name="p2"></param>
|
|
30 |
/// <param name="arcLengthOrigin"></param>
|
|
31 |
/// <param name="contentByte"></param>
|
|
32 |
/// <param name="boundAngle"></param>
|
|
33 |
/// <param name="fixAngle"></param>
|
|
34 |
public static void GenerateLineWithCloud(Point p1, Point p2, double arcLength , PdfContentByte contentByte, double boundAngle, double fixAngle)
|
|
35 |
{
|
|
36 |
arcLength = 10;
|
34 |
37 |
double l = MathSet.DistanceTo(p1, p2); /// p1와 p2의 길이
|
35 |
|
double dx = p2.X - p1.X;
|
36 |
|
double dy = p1.Y - p2.Y;
|
37 |
|
dx /= l;
|
38 |
|
dy /= l;
|
|
38 |
arcLength = (l < arcLength) ? l : arcLength;
|
|
39 |
double dx = (p2.X - p1.X) / l;
|
|
40 |
double dy = (p2.Y - p1.Y) / l;
|
|
41 |
Point norm = MathSet.RotateAbout(new Point(0, 0), new Point(dx, dy), 90);
|
|
42 |
|
39 |
43 |
double count = l / arcLength; // 두 선의 길이에서 normalize 된 사이즈만큼을 나눠 진행 수치의 갯수 파악
|
40 |
44 |
|
41 |
45 |
Point lastPt = new Point(p1.X, p1.Y);
|
42 |
|
Double j = 1;
|
43 |
46 |
Point uses = new Point(0, 0); //사용된 값 누적치
|
44 |
47 |
uses = lastPt; //Point 첫번째꺼 대입
|
45 |
48 |
contentByte.MoveTo((float)lastPt.X, (float)lastPt.Y);
|
46 |
49 |
|
47 |
|
|
48 |
|
for (j = 1; j < (count - 1); j++) //dx , dy의 횟수차로 증감치를 결정
|
|
50 |
for (int j = 0; j < count; j++) //dx , dy의 횟수차로 증감치를 결정
|
49 |
51 |
{
|
50 |
|
var moveUsesX = j * dx * arcLength + lastPt.X;
|
51 |
|
//var moveUsesY = j * dy * arcLength + lastPt.Y;
|
52 |
|
var moveUsesY = lastPt.Y - (j * dy * arcLength); //Y축 반전
|
53 |
|
|
54 |
|
l = MathSet.DistanceTo(uses, new Point(moveUsesX, moveUsesY)); /// 시작점과 진행점의 길이 구하기
|
55 |
|
///
|
56 |
|
var midP = MathSet.getMiddlePoint(uses, new Point(moveUsesX, moveUsesY)); //시작점과 끝점의 중간점
|
57 |
|
var endP = MathSet.RotateAbout(midP, new Point(midP.X + (l / 2), midP.Y), boundAngle); //중간점을 계산된 각도로 돌림(반시계)
|
58 |
|
contentByte.CurveTo((float)uses.X, (float)uses.Y, (float)endP.X, (float)endP.Y, (float)moveUsesX, (float)moveUsesY);
|
59 |
|
uses = new Point(moveUsesX, moveUsesY); //진행값을 누적시켜 계속 진행할 수 있게 변경해줌
|
|
52 |
/// update last point
|
|
53 |
if (j == count - 1)
|
|
54 |
{
|
|
55 |
lastPt.X = p2.X;
|
|
56 |
lastPt.Y = p2.Y;
|
|
57 |
}
|
|
58 |
else
|
|
59 |
{
|
|
60 |
lastPt.X = lastPt.X + dx * arcLength;
|
|
61 |
lastPt.Y = lastPt.Y + dy * arcLength; /// Y축 반전
|
|
62 |
}
|
|
63 |
|
|
64 |
var midP = MathSet.getMiddlePoint(uses, lastPt); //시작점과 끝점의 중간점
|
|
65 |
contentByte.CurveTo((float)uses.X, (float)uses.Y, (float)midP.X - norm.X * arcLength*0.3, (float)midP.Y - norm.Y*arcLength*0.3, (float)lastPt.X, (float)lastPt.Y);
|
|
66 |
uses.X = lastPt.X;
|
|
67 |
uses.Y = lastPt.Y;
|
60 |
68 |
}
|
61 |
69 |
|
62 |
|
if ((count > j) || (count > 0))
|
|
70 |
l = MathSet.DistanceTo(uses, p2); /// 남은 거리 계산
|
|
71 |
if (l > 0)
|
63 |
72 |
{
|
64 |
|
double angle = 0;
|
65 |
|
//angle = MathSet.AngleMethod(uses, p2);
|
66 |
|
var ppp = p2;
|
67 |
|
angle = returnAngle(uses, ref ppp) + fixAngle;
|
68 |
|
GenerateLineWithCloud_Closing(uses, p2, arcLength, contentByte, angle);
|
|
73 |
var midP = MathSet.getMiddlePoint(uses, p2); //시작점과 끝점의 중간점
|
|
74 |
contentByte.CurveTo((float)uses.X, (float)uses.Y, (float)midP.X - norm.X * l*0.3, (float)midP.Y - norm.Y*l*0.3, (float)p2.X, (float)p2.Y);
|
69 |
75 |
}
|
70 |
|
|
71 |
|
//contentByte.Stroke();
|
72 |
76 |
}
|
73 |
77 |
|
74 |
78 |
public static void GenerateLineWithCloud_Closing(Point p1, Point p2, double arcLengthOrigin, PdfContentByte contentByte, double boundAngle)
|
75 |
79 |
{
|
76 |
|
//Point instP = MathSet.GetNormVectorBetween(p1,p2);
|
77 |
|
|
78 |
|
//Point nextP = MathSet.GetNormVectorBetween(p2, nextPoint);
|
79 |
|
|
80 |
|
////contentByte.MoveTo((float)p1.X, (float)p1.Y);
|
81 |
|
////p1.X += instP.X;
|
82 |
|
////p1.Y += instP.Y;
|
83 |
|
|
84 |
|
|
85 |
|
//double l = MathSet.DistanceTo(p1, p2); /// p1와 p2의 길이
|
86 |
|
//var midP = MathSet.getMiddlePoint(p1, p2); //시작점과 끝점의 중간점
|
87 |
|
//var endP = MathSet.RotateAbout(midP, new Point(midP.X + (l / 2), midP.Y), boundAngle); //중간점을 계산된 각도로 돌림(반시계)
|
88 |
|
|
89 |
|
//contentByte.CurveTo((float)(p1.X - instP.X - instP.X), (float)(p1.Y - instP.Y - instP.Y),
|
90 |
|
// (float)endP.X, (float)endP.Y,
|
91 |
|
// //(float)(p2.X + instP.X), (float)(p2.Y + instP.Y));
|
92 |
|
// //(float)(p2.X + instP.X /4), (float)(p2.Y + instP.Y / 4));
|
93 |
|
// (float)(p2.X + instP.X + nextP.X/2), (float)(p2.Y + instP.X + nextP.Y/2));
|
94 |
|
// //nextP
|
95 |
|
|
96 |
80 |
contentByte.MoveTo((float)p1.X, (float)p1.Y);
|
97 |
81 |
double l = MathSet.DistanceTo(p1, p2); /// p1와 p2의 길이
|
98 |
82 |
var midP = MathSet.getMiddlePoint(p1, p2); //시작점과 끝점의 중간점
|
... | ... | |
101 |
85 |
}
|
102 |
86 |
|
103 |
87 |
public static void DrawCloud(List<Point> points, double lineSize, double arcLength, PdfContentByte contentByte, System.Windows.Media.DoubleCollection DashSize,
|
104 |
|
SolidColorBrush color, PaintSet PaintStyle, bool NotEofFill, bool reverseAngle, double opac)
|
|
88 |
SolidColorBrush color, PaintSet PaintStyle, bool NotEofFill, bool reverseAngle, bool isHighlight, double opac)
|
105 |
89 |
{
|
106 |
90 |
double fixAngle = 0;
|
107 |
91 |
if (reverseAngle)
|
... | ... | |
116 |
100 |
gs1.FillOpacity = (float)opac;
|
117 |
101 |
contentByte.SetGState(gs1);
|
118 |
102 |
var rect = contentByte.PdfDocument.PageSize;
|
119 |
|
contentByte.SetColorStroke(bs);
|
120 |
|
List<float> DashSet = new List<float>();
|
121 |
|
/// WPF defines a device-independent pixel as 1 / 96 per inch
|
122 |
|
/// iTextSharp : "the default for the size of the unit in default user space (1/72 inch)
|
123 |
|
lineSize = lineSize * 72 / 96;
|
124 |
|
|
125 |
|
/*if (lineSize < 3)
|
|
103 |
if (isHighlight)
|
126 |
104 |
{
|
127 |
|
lineSize = 2.5;
|
|
105 |
contentByte.SetColorFill(BaseColor.YELLOW);
|
128 |
106 |
}
|
|
107 |
else
|
|
108 |
{
|
|
109 |
contentByte.SetColorStroke(bs);
|
|
110 |
}
|
|
111 |
List<float> DashSet = new List<float>();
|
129 |
112 |
|
130 |
|
contentByte.SetLineWidth((float)lineSize - 2);
|
131 |
|
*/
|
|
113 |
/// WPF defines a device-independent pixel as 1 / 96 per inch
|
|
114 |
/// iTextSharp : "the default for the size of the unit in default user space (1/72 inch)
|
|
115 |
lineSize = lineSize * 72 / 96*0.5;
|
132 |
116 |
|
133 |
117 |
DashSize.ToList().ForEach(data => DashSet.Add((float)data * 2));
|
134 |
118 |
contentByte.SetLineDash(DashSet.ToArray(), DashSet.Count - 2);
|
135 |
|
//contentByte.SetLineWidth((float)lineSize - 2);
|
136 |
119 |
contentByte.SetLineWidth((float)lineSize);
|
137 |
120 |
|
138 |
121 |
var getMidSet = MathSet.FindCentroid(points);
|
139 |
122 |
contentByte.NewPath();
|
140 |
123 |
double area = MathSet.AreaOf(points);
|
141 |
|
bool reverse = (area < 0);
|
|
124 |
if(area < 0) points.Reverse();
|
142 |
125 |
int count = points.Count;
|
143 |
126 |
double angle = 0;
|
144 |
127 |
for (int i = 0; i < count - 1; i++) //테스트로 하나만
|
145 |
|
//for (int i = 0; i < 2; i++) //테스트로 하나만
|
146 |
128 |
{
|
147 |
|
//angle = MathSet.AngleMethod(points[i], points[i + 1]);
|
148 |
|
var ppp = points[i + 1];
|
149 |
|
angle = returnAngle(points[i], ref ppp) + fixAngle;
|
|
129 |
angle = returnAngle(points[i], points[i + 1]) + fixAngle;
|
150 |
130 |
GenerateLineWithCloud(points[i], points[i + 1], arcLength, contentByte, angle, fixAngle);
|
151 |
|
|
152 |
|
if (i + 1 < count)
|
153 |
|
{
|
154 |
|
nextPoint = points[i];
|
155 |
|
}
|
156 |
131 |
}
|
157 |
|
//angle = MathSet.AngleMethod(points[points.Count-1], points[0]);
|
158 |
|
var rrrrr = points[0];
|
159 |
|
angle = returnAngle(points[points.Count - 1], ref rrrrr) + fixAngle;
|
160 |
|
GenerateLineWithCloud(points[points.Count - 1], points[0], arcLength, contentByte, angle, fixAngle);
|
161 |
|
//contentByte.ClosePath();
|
162 |
|
//PaintFill(contentByte, PaintSet.None, bs);
|
163 |
|
//contentByte.NewPath();
|
164 |
|
#region 부족한 부분 접합
|
165 |
|
if (!NotEofFill)
|
166 |
|
{
|
167 |
|
foreach (var item in points)
|
168 |
|
{
|
169 |
|
if (item == points.First())
|
170 |
|
{
|
171 |
|
contentByte.MoveTo((float)item.X, (float)item.Y);
|
172 |
|
}
|
173 |
|
else
|
174 |
|
{
|
175 |
|
contentByte.LineTo((float)item.X, (float)item.Y);
|
176 |
|
}
|
177 |
|
}
|
178 |
|
//contentByte.ClosePath();
|
179 |
132 |
|
180 |
|
}
|
|
133 |
angle = returnAngle(points[points.Count - 1], points[0]) + fixAngle;
|
|
134 |
GenerateLineWithCloud(points[points.Count - 1], points[0], arcLength, contentByte, angle, fixAngle);
|
181 |
135 |
|
182 |
|
#endregion
|
183 |
|
//PaintFill(contentByte, PaintStyle, bs);
|
184 |
136 |
switch (PaintStyle)
|
185 |
137 |
{
|
186 |
138 |
case PaintSet.Fill:
|
... | ... | |
197 |
149 |
contentByte.SetColorFill(colors);
|
198 |
150 |
contentByte.ClosePath();
|
199 |
151 |
contentByte.Fill();
|
200 |
|
DrawCloud(points, lineSize, arcLength, contentByte, DashSize, color, PaintSet.None, true, reverseAngle, opac);
|
|
152 |
DrawCloud(points, lineSize, arcLength, contentByte, DashSize, color, PaintSet.None, true, reverseAngle, false, opac);
|
201 |
153 |
}
|
202 |
154 |
break;
|
203 |
155 |
case PaintSet.None:
|