프로젝트

일반

사용자정보

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

markus / MarkupToPDF / Controls / Common / MathSet.cs @ b643fcca

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

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