첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

■ 대칭 복합 선 그리기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


MainWindow.xaml

 

 

<Window x:Class="TestProject.MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Width="600"

    Height="450"

    Title="대칭 복합 선 그리기"

    Loaded="Window_Loaded">

    <Grid Name="mainGrid">

    </Grid>

</Window>

 

 

MainWindow.xaml.cs

 

 

using System;

using System.Windows;

using System.Windows.Media;

using System.Windows.Shapes;

 

namespace TestProject

{

    /// <summary>

    /// 메인 윈도우

    /// </summary>

    public partial class MainWindow : Window

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainWindow()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainWindow()

        {

            InitializeComponent();

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 윈도우 로드시 처리하기 - Window_Loaded(sender, e)

 

        /// <summary>

        /// 윈도우 로드시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Window_Loaded(object sender, RoutedEventArgs e)

        {

            double width = Math.Min

            (

                this.mainGrid.ActualWidth  - 60,

                this.mainGrid.ActualHeight - 40

            );

 

            Rect rectangle = new Rect(30, 40, width, width);

 

            Point[] pointArray = GetStarPointArray(-Math.PI / 2, 5, 2, rectangle);

 

            double[] thicknessesArray = { 15, 10, 6 };

 

            Brush[] brusheArray = { Brushes.Blue, Brushes.White, Brushes.Blue };

 

            for(int i = 0; i < thicknessesArray.Length; i++)

            {

                Polygon polygon = new Polygon();

 

                polygon.Points          = new PointCollection(pointArray);

                polygon.StrokeThickness = thicknessesArray[i];

                polygon.Stroke          = brusheArray[i];

 

                this.mainGrid.Children.Add(polygon);

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 교차 포인트 찾기 - FindIntersectionPoint(point1, point2, point3, point4,

            lineIntersect, segmentIntersect, intersectionPoint, closePoint1, closePoint2)

 

        /// <summary>

        /// 교차 포인트 찾기

        /// </summary>

        /// <param name="point1">포인트 1</param>

        /// <param name="point2">포인트 2</param>

        /// <param name="point3">포인트 3</param>

        /// <param name="point4">포인트 41</param>

        /// <param name="lineIntersect">직선 교차 여부</param>

        /// <param name="segmentIntersect">세그먼트 교차 여부</param>

        /// <param name="intersectionPoint">교차 포인트</param>

        /// <param name="closePoint1">근접 포인트 1</param>

        /// <param name="closePoint2">근접 포인트 2</param>

        private void FindIntersectionPoint(Point point1, Point point2, Point point3, Point point4,

            out bool lineIntersect, out bool segmentIntersect, out Point intersectionPoint, out Point closePoint1, out Point closePoint2)

        {

            double dx12 = point2.X - point1.X;

            double dy12 = point2.Y - point1.Y;

            double dx34 = point4.X - point3.X;

            double dy34 = point4.Y - point3.Y;

 

            double denominator = (dy12 * dx34 - dx12 * dy34);

 

            double t1 = ((point1.X - point3.X) * dy34 + (point3.Y - point1.Y) * dx34) / denominator;

 

            if(double.IsInfinity(t1))

            {

                lineIntersect    = false;

                segmentIntersect = false;

 

                intersectionPoint = new Point(double.NaN, double.NaN);

 

                closePoint1 = new Point(double.NaN, double.NaN);

                closePoint2 = new Point(double.NaN, double.NaN);

 

                return;

            }

 

            lineIntersect = true;

 

            double t2 = ((point3.X - point1.X) * dy12 + (point1.Y - point3.Y) * dx12) / -denominator;

 

            intersectionPoint = new Point(point1.X + dx12 * t1, point1.Y + dy12 * t1);

 

            segmentIntersect = ((t1 >= 0) && (t1 <= 1) && (t2 >= 0) && (t2 <= 1));

 

            if(t1 < 0)

            {

                t1 = 0;

            }

            else if(t1 > 1)

            {

                t1 = 1;

            }

 

            if(t2 < 0)

            {

                t2 = 0;

            }

            else if(t2 > 1)

            {

                t2 = 1;

            }

 

            closePoint1 = new Point(point1.X + dx12 * t1, point1.Y + dy12 * t1);

            closePoint2 = new Point(point3.X + dx34 * t2, point3.Y + dy34 * t2);

        }

 

        #endregion

        #region 오목 반지름 구하기 - GetConcaveRadius(pointCount, skip)

 

        /// <summary>

        /// 오목 반지름 구하기

        /// </summary>

        /// <param name="pointCount">포인트 카운트</param>

        /// <param name="skip">건너띄기</param>

        /// <returns>오목 반지름</returns>

        private double GetConcaveRadius(int pointCount, int skip)

        {

            if(pointCount < 5)

            {

                return 0.33f;

            }

 

            double deltaTheta = 2 * Math.PI / pointCount;

            double theta00    = -Math.PI / 2;

            double theta01    = theta00 + deltaTheta * skip;

            double theta10    = theta00 + deltaTheta;

            double theta11    = theta10 - deltaTheta * skip;

 

            Point pt00 = new Point

            (

                (double)Math.Cos(theta00),

                (double)Math.Sin(theta00)

            );

 

            Point pt01 = new Point

            (

                (double)Math.Cos(theta01),

                (double)Math.Sin(theta01)

            );

 

            Point pt10 = new Point

            (

                (double)Math.Cos(theta10),

                (double)Math.Sin(theta10)

            );

 

            Point pt11 = new Point

            (

                (double)Math.Cos(theta11),

                (double)Math.Sin(theta11)

            );

 

            bool lineIntersect;

            bool segmentIntersect;

 

            Point intersectionPoint;

            Point closePoint1;

            Point closePoint2;

 

            FindIntersectionPoint

            (

                pt00,

                pt01,

                pt10,

                pt11,

                out lineIntersect,

                out segmentIntersect,

                out intersectionPoint,

                out closePoint1,

                out closePoint2

            );

 

            return Math.Sqrt(intersectionPoint.X * intersectionPoint.X + intersectionPoint.Y * intersectionPoint.Y);

        }

 

        #endregion

        #region 별 포인트 배열 구하기 - GetStarPointArray(startTheta, pointCount, skip, rectangle)

 

        /// <summary>

        /// 별 포인트 배열 구하기

        /// </summary>

        /// <param name="startTheta">시작 세타</param>

        /// <param name="pointCount">포인트 카운트</param>

        /// <param name="skip">건너띄기</param>

        /// <param name="rectangle">사각형</param>

        /// <returns>별 포인트 배열</returns>

        private Point[] GetStarPointArray(double startTheta, int pointCount, int skip, Rect rectangle)

        {

            double  theta;

            double  deltaTheta;

            Point[] pointArray;

 

            double  halfWidth  = rectangle.Width  / 2f;

            double  halfHeight = rectangle.Height / 2f;

            double  centerX    = rectangle.X + halfWidth;

            double  centerY    = rectangle.Y + halfHeight;

 

            if(skip == 1)

            {

                pointArray = new Point[pointCount];

 

                theta = startTheta;

 

                deltaTheta = 2 * Math.PI / pointCount;

 

                for(int i = 0; i < pointCount; i++)

                {

                    pointArray[i] = new Point

                    (

                        (double)(centerX + halfWidth * Math.Cos(theta)),

                        (double)(centerY + halfHeight * Math.Sin(theta))

                    );

 

                    theta += deltaTheta;

                }

 

                return pointArray;

            }

 

            double concaveRadius = GetConcaveRadius(pointCount, skip);

 

            pointArray = new Point[2 * pointCount];

            theta      = startTheta;

            deltaTheta = Math.PI / pointCount;

 

            for(int i = 0; i < pointCount; i++)

            {

                pointArray[2 * i] = new Point

                (

                    (double)(centerX + halfWidth  * Math.Cos(theta)),

                    (double)(centerY + halfHeight * Math.Sin(theta))

                );

 

                theta += deltaTheta;

 

                pointArray[2 * i + 1] = new Point

                (

                    (double)(centerX + halfWidth  * Math.Cos(theta) * concaveRadius),

                    (double)(centerY + halfHeight * Math.Sin(theta) * concaveRadius)

                );

 

                theta += deltaTheta;

            }

 

            return pointArray;

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker

댓글을 달아 주세요