프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

markus / MarkupToPDF / Controls / Common / MathSet.cs @ 4a54bb3a

이력 | 보기 | 이력해설 | 다운로드 (14.7 KB)

1 787a4489 KangIngu
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Windows;
5 f5407d37 swate0609
using System.Windows.Media;
6 787a4489 KangIngu
7
namespace MarkupToPDF.Controls.Common
8
{
9
    public class MathSet
10
    {
11 b643fcca taeseongkim
        private const double Rad2Deg = 180.0 / Math.PI;
12
        private const double Deg2Rad = Math.PI / 180.0;
13
        private const double UnitAngle = 15;
14 787a4489 KangIngu
15
        public static List<double> angleSet = new List<double>();
16
17
        public static double getMultipleAngle(double increase, double YourAngle)
18
        {
19
            angleSet.Clear();
20
21
            for (double i = 0; i <= 360; i += increase)
22
            {
23
                angleSet.Add(i);
24
            }
25
26
            if (YourAngle < 0)
27
            {
28
                YourAngle += 360;
29
            }
30
            double TargetData = YourAngle;
31
            double NearAngle = 0;
32
            double k = 0;
33
34
            foreach (var item in angleSet)
35
            {
36
                double j = 0;
37
                j = TargetData - item;
38
                j = j < 0 ? -j : j;
39
                if (j < k)
40
                {
41
                    NearAngle = item;
42
                }
43
                k = j;
44
            }
45
            return NearAngle;
46
        }
47
48
        public static Point getNearPoint(List<Point> pointList, Point setPoint)
49
        {
50
            Point nearPoint = pointList.Select
51
            (n => new
52 992a98b4 KangIngu
            {
53
                n,
54
                distance = Math.Sqrt
55 787a4489 KangIngu
                    (
56 4a54bb3a humkyung
                        Math.Pow((n.X - setPoint.X), 2)
57
                        + System.Math.Pow((n.Y - setPoint.Y), 2)
58 787a4489 KangIngu
                    )
59 992a98b4 KangIngu
            }
60 787a4489 KangIngu
            ).OrderBy(p => p.distance).First().n;
61
62
            return nearPoint;
63
        }
64
65
        public class ClipLine
66
        {
67
            public static int DONT_INTERSECT = -0x01;
68
            public static int COLLINEAR = 0x00;
69
            public static int INTERSECT = 0x01;
70
            public static double TOLER = 0.0;
71
72
            public Point _start;
73
            public Point _end;
74
75
            public ClipLine(Point start, Point end)
76
            {
77
                _start = start;
78
                _end = end;
79
            }
80
81
            public bool IsLeftSide(Point pt)
82
            {
83
                double dx1 = _end.X - _start.X;
84
                double dy1 = _end.Y - _start.Y;
85
                double dx2 = pt.X - _start.X;
86
                double dy2 = pt.Y - _start.Y;
87
88
                return ((dx1 * dy2 - dy1 * dx2) > 0.0);
89
            }
90
91
            public bool IsRightSide(Point pt)
92
            {
93
                double dx1 = _end.X - _start.X;
94
                double dy1 = _end.Y - _start.Y;
95
                double dx2 = pt.X - _start.X;
96
                double dy2 = pt.Y - _start.Y;
97
98
                return ((dx1 * dy2 - dy1 * dx2) < 0.0);
99
            }
100
101
            /// <summary>
102 e65e8c5c humkyung
            /// get intersection point between this and line2d
103 787a4489 KangIngu
            /// </summary>
104
            /// <author>humkyung</author>
105
            /// <date>2012.08.30</date>
106
            /// <param name="intsec"></param>
107
            /// <param name="line2d"></param>
108
            /// <returns></returns>
109
            public int IntersectWith(ref Point intsec, ClipLine line2d)
110
            {
111
                double Ax = 0.0, Bx = 0.0, Cx = 0.0, Ay = 0.0, By = 0.0, Cy = 0.0, d = 0.0, e = 0.0, f = 0.0;
112
                double x1lo = 0.0, x1hi = 0.0, y1lo = 0.0, y1hi = 0.0;
113
114
                Ax = _end.X - _start.X;
115
                Bx = line2d._start.X - line2d._end.X;
116
                // X bound box test
117
                if (Ax < 0.0)
118
                {
119
                    x1lo = _end.X;
120
                    x1hi = _start.X;
121
                }
122
                else
123
                {
124
                    x1hi = _end.X;
125
                    x1lo = _start.X;
126
                }
127
128
                if (Bx > 0.0)
129
                {
130
                    if ((x1hi < line2d._end.X) || (line2d._start.X < x1lo)) return ClipLine.DONT_INTERSECT;
131
                }
132
                else
133
                {
134
                    if ((x1hi < line2d._start.X) || (line2d._end.X < x1lo)) return ClipLine.DONT_INTERSECT;
135
                }
136
137
                Ay = _end.Y - _start.Y;
138
                By = line2d._start.Y - line2d._end.Y;
139
                /* Y bound box test*/
140
                if (Ay < 0)
141
                {
142
                    y1lo = _end.Y;
143
                    y1hi = _start.Y;
144
                }
145
                else
146
                {
147
                    y1hi = _end.Y;
148
                    y1lo = _start.Y;
149
                }
150
151
                if (By > 0)
152
                {
153
                    if ((y1hi < line2d._end.Y) || (line2d._start.Y < y1lo)) return ClipLine.DONT_INTERSECT;
154
                }
155
                else
156
                {
157
                    if ((y1hi < line2d._start.Y) || (line2d._end.Y < y1lo)) return ClipLine.DONT_INTERSECT;
158
                }
159
160
                Cx = _start.X - line2d._start.X;
161
                Cy = _start.Y - line2d._start.Y;
162
                f = Ay * Bx - Ax * By;	/* both denominator*/
163
                /// lines are collinear.
164
                if (0.0 == f) return ClipLine.COLLINEAR;
165
166
                d = By * Cx - Bx * Cy;	/* alpha numerator*/
167
                if (f > 0.0)
168
                {		/* alpha tests*/
169
                    if ((d < (0 + ClipLine.TOLER)) || (d > (f - ClipLine.TOLER))) return ClipLine.DONT_INTERSECT;
170
                }
171
                else
172
                {
173
                    if ((d > (0 - ClipLine.TOLER)) || (d < (f + ClipLine.TOLER))) return ClipLine.DONT_INTERSECT;
174
                }
175
176
                e = Ax * Cy - Ay * Cx;	/* beta numerator*/
177
                if (f > 0.0)
178
                {		/* beta tests*/
179
                    if ((e < (0 + ClipLine.TOLER)) || (e > (f - ClipLine.TOLER))) return ClipLine.DONT_INTERSECT;
180
                }
181
                else
182
                {
183
                    if ((e > (0 - ClipLine.TOLER)) || (e < (f + ClipLine.TOLER))) return ClipLine.DONT_INTERSECT;
184
                }
185
186
                /*compute intersection coordinates*/
187
                double alpha = d / f;
188
189
                if (_start.X == _end.X)
190
                    intsec.X = _start.X;
191
                else intsec.X = _start.X + alpha * Ax;
192
                if (_start.Y == _end.Y)
193
                    intsec.Y = _start.Y;
194
                else intsec.Y = _start.Y + alpha * Ay;
195
196
                return ClipLine.INTERSECT;
197
            }
198
        }
199
200
        public class ClipRect
201
        {
202
            public Point center;
203
            public double width, height, angle;	/// angle is degree
204
205
            public int IntersectWith(ref Point intsec, ClipLine line2d)
206
            {
207
                double radians = Math.PI * angle / 180.0;
208
                double cs = Math.Cos(radians), sn = Math.Sin(radians);
209
                Point[] corner = new Point[4];
210
                corner[0].X = center.X - width * 0.5;
211
                corner[0].Y = center.Y - height * 0.5;
212
                corner[1] = corner[0];
213
                corner[1].X += width;
214
                corner[2] = corner[1];
215
                corner[2].Y += height;
216
                corner[3] = corner[2];
217
                corner[3].X -= width;
218
                /// rotate 4 corners about angle
219
                for (int i = 0; i < corner.Length; ++i)
220
                {
221
                    double ptx = corner[i].X - center.X;
222
                    double pty = corner[i].Y - center.Y;
223
                    corner[i].X = center.X + ((cs * ptx) - (sn * pty));
224
                    corner[i].Y = center.Y + ((sn * ptx) + (cs * pty));
225
                }
226
227
                for (int i = 0; i < corner.Length; ++i)
228
                {
229
                    int si = i % corner.Length, ei = (i + 1) % corner.Length;
230
                    if (ClipLine.INTERSECT == line2d.IntersectWith(ref intsec, new ClipLine(corner[si], corner[ei])))
231
                    {
232
                        return ClipLine.INTERSECT;
233
                    }
234
                }
235
236
                return ClipLine.DONT_INTERSECT;
237
            }
238
        }
239
240
        public static double AngleMethod(Point StartPoint, Point EndPoint)
241
        {
242
            return Math.Abs(Math.Atan2(EndPoint.X - StartPoint.X, StartPoint.Y - EndPoint.Y) * Rad2Deg);
243
        }
244 b643fcca taeseongkim
245 787a4489 KangIngu
        public static double DegreesToRadians(double angle)
246
        {
247
            return ((angle * Math.PI) / 180f);
248
        }
249 b643fcca taeseongkim
250 787a4489 KangIngu
        public static double DistanceTo(Point p1, Point p2)
251
        {
252
            double dx = p2.X - p1.X;
253
            double dy = p2.Y - p1.Y;
254
            return Math.Sqrt(dx * dx + dy * dy);
255
        }
256
257
        public static Point getMiddlePoint(Point p1, Point p2)
258
        {
259 3b797b23 humkyung
            return new Point { X = (p1.X + p2.X) * 0.5, Y = (p1.Y + p2.Y) * 0.5 };
260 787a4489 KangIngu
        }
261
262
        /// <summary>
263
        /// return area of polygon
264
        /// </summary>
265
        /// <author>humkyung</author>
266
        /// <date>2012.07.04</date>
267
        /// <param name="points"></param>
268
        /// <returns></returns>
269
        public static double AreaOf(List<Point> points)
270
        {
271
            double res = 0;
272
            int p = 0, q = 0;
273
274
            for (p = points.Count - 1, q = 0; q < points.Count; p = q++)
275
            {
276
                res += points[p].X * points[q].Y - points[p].Y * points[q].X;
277
            }
278
279
            return res;
280
        }
281 b643fcca taeseongkim
282 787a4489 KangIngu
        /// <summary>
283
        /// return normal vector from p1 to p2
284
        /// </summary>
285
        /// <author>humkyung</author>
286
        /// <date>2012.07.19</date>
287
        /// <param name="p1"></param>
288
        /// <param name="p2"></param>
289
        /// <returns></returns>
290
        public static Point GetNormVectorBetween(Point p1, Point p2)
291
        {
292
            Point res = new Point();
293
294
            double d = MathSet.DistanceTo(p1, p2);
295
            if (d > 0)
296
            {
297
                res.X = (p2.X - p1.X) / d;
298
                res.Y = (p2.Y - p1.Y) / d;
299
            }
300
301
            return res;
302
        }
303 b643fcca taeseongkim
304 787a4489 KangIngu
        public static Point FindCentroid(List<Point> pntSet)
305
        {
306
            Double getThePointX = new Double();
307
            Double getThePointY = new Double();
308
309
            for (int i = 0; i < pntSet.Count; i++)
310
            {
311
                int ReIndex = (i + pntSet.Count / 2) % pntSet.Count;
312
                Point p = (MathSet.getMiddlePoint(pntSet[i], pntSet[ReIndex]));
313
                getThePointX += p.X;
314
                getThePointY += p.Y;
315
            }
316
            double count = Convert.ToDouble(pntSet.Count);
317
            //return new Point(getThePointX/Convert.ToDouble(pntSet.Count(),getThePointY/Convert.ToDouble(pntSet.Count());
318
            return new Point(getThePointX / count, getThePointY / count);
319
        }
320
321 3b797b23 humkyung
        /// <summary>
322
        /// org 기준으로 dest를 dAngle(in degree)만큼 회전 시킨다.
323
        /// </summary>
324
        /// <param name="org"></param>
325
        /// <param name="dest"></param>
326
        /// <param name="dAngle"></param>
327
        /// <returns></returns>
328 787a4489 KangIngu
        public static Point RotateAbout(Point org, Point dest, double dAngle)
329
        {
330 e65e8c5c humkyung
            var transform = new RotateTransform() { Angle = dAngle, CenterX = org.X, CenterY = org.Y };
331
            return transform.Transform(dest);
332 787a4489 KangIngu
        }
333
334
        public static double getAngle(double x1, double y1, double x2, double y2)
335
        {
336
            double alpha = 0;
337
            double dx = x2 - x1;
338
            double dy = y2 - y1;
339
            double l = Math.Sqrt(dx * dx + dy * dy);
340
341
            if (l > 0)
342
            {
343
                alpha = Math.Acos(dx / l);
344
                double cross = MathSet.CrossProduct(1, 0, dx, dy);
345
                if (cross < 0) alpha = -alpha;
346
347
                alpha *= MathSet.Rad2Deg;
348
            }
349
            else
350
            {
351
                alpha = 0;
352
            }
353
354
            return alpha;
355
        }
356
357
        public static double DotProduct(double x1, double y1, double x2, double y2)
358
        {
359
            return (x1 * x2 + y1 * y2);
360
        }
361
362
        public static double CrossProduct(double x1, double y1, double x2, double y2)
363
        {
364
            return (x1 * y2 - y1 * x2);
365
        }
366
367 992a98b4 KangIngu
        /// <summary>
368
        /// return angle in degree between given two vectors
369
        /// </summary>
370
        /// <author>humkyung</author>
371
        /// <date>2018.05.09</date>
372
        /// <param name="vec1"></param>
373
        /// <param name="vec2"></param>
374
        /// <returns></returns>
375
        public static double getAngleBetweenVectors(Point vec1, Point vec2)
376
        {
377
            double dot = MathSet.DotProduct(vec1.X, vec1.Y, vec2.X, vec2.Y);
378
            double length1 = Math.Sqrt(vec1.X * vec1.X + vec1.Y * vec1.Y);
379
            double length2 = Math.Sqrt(vec2.X * vec2.X + vec2.Y * vec2.Y);
380
            double cross = MathSet.CrossProduct(vec1.X, vec1.Y, vec2.X, vec2.Y);
381
            double radian = Math.Acos(dot / (length1 * length2));
382
383
            return (cross > 0) ? radian * MathSet.Rad2Deg : -(radian * MathSet.Rad2Deg);
384
        }
385
386 168f8027 taeseongkim
        // 사용용도가 불분명함.
387 787a4489 KangIngu
        public static string returnAngleString(Point start, ref Point end, bool PressShift)
388
        {
389
            double angle = MathSet.getAngle(start.X, start.Y, end.X, end.Y);
390
            double approxAngle = MathSet.getMultipleAngle(UnitAngle, angle);
391
392
            if (PressShift)
393
            {
394
                double distance = MathSet.DistanceTo(start, end);
395
                end = MathSet.RotateAbout(start, new Point(start.X + distance, start.Y), approxAngle);
396
                return String.Format("{1}({0})", approxAngle.ToString("0.#") + "°", Math.Abs(approxAngle - 360).ToString("0.#") + "°");
397
            }
398
            else
399
            {
400
                angle *= -1;
401
402
                if (angle < 0)
403
                {
404
                    angle = angle + 360;
405
                }
406
                return String.Format("{0}", angle.ToString("0.#") + "°");
407
            }
408
        }
409
410 168f8027 taeseongkim
        /// <summary>
411
        /// returnAngleString을 변경하여 수정
412
        /// 상단 컨트롤에 Angle값을 보여주기 위해 수정함.
413
        /// </summary>
414
        /// <param name="start"></param>
415
        /// <param name="end"></param>
416
        /// <param name="PressShift"></param>
417
        /// <returns></returns>
418
        public static double returnAngle(Point start, ref Point end, bool PressShift)
419
        {
420
            double angle = MathSet.getAngle(start.X, start.Y, end.X, end.Y);
421
            double approxAngle = MathSet.getMultipleAngle(UnitAngle, angle);
422
423
            if (PressShift)
424
            {
425
                double distance = MathSet.DistanceTo(start, end);
426
                end = MathSet.RotateAbout(start, new Point(start.X + distance, start.Y), approxAngle);
427
428
                angle = approxAngle;
429
            }
430
431 b643fcca taeseongkim
            if (angle < 0)
432
            {
433
                angle = 360 + angle;
434
            }
435
436 168f8027 taeseongkim
            return angle;
437
        }
438
439 787a4489 KangIngu
        public static Point getRectMiddlePoint(Rect data)
440
        {
441
            Point startP = new Point(data.X, data.Y);
442
            Point endP = new Point(data.Right, data.Bottom);
443
            return MathSet.getMiddlePoint(startP, endP);
444
        }
445
    }
446 b643fcca taeseongkim
}
클립보드 이미지 추가 (최대 크기: 500 MB)