첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

■ PathGeometry 클래스를 사용해 GraphicsPath 객체에서 패스 지오메트리 객체를 구하는 방법을 보여준다.

TestProject.zip
0.01MB

▶ 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="800"
    Height="600"
    Title="PathGeometry 클래스 : GraphicsPath 객체에서 패스 지오메트리 구하기"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Grid>
        <Path Name="path"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Stroke="Red"
            StrokeThickness="3">
        </Path>
    </Grid>
</Window>

 

▶ MainWindow.xaml.cs

using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows;
using System.Windows.Media;

namespace TestProject
{
    /// <summary>
    /// 메인 윈도우
    /// </summary>
    public partial class MainWindow : Window
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainWindow()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            GraphicsPath graphicsPath = GetRoundedRectanglePath(new RectangleF(0, 0, 300, 300), 10, 10, true, true, true, true);

            PathGeometry pathGeometry = GetPathGeometry(graphicsPath);

            this.path.Data = pathGeometry;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 라운드 사각형 패스 구하기 - GetRoundedRectanglePath(rectangle, radiusX, radiusY, roundUpperLeft, roundUpperRight, roundLowerRight, roundLowerLeft)

        /// <summary>
        /// 라운드 사각형 패스 구하기
        /// </summary>
        /// <param name="rectangle">사각형</param>
        /// <param name="radiusX">반경 X</param>
        /// <param name="radiusY">반경 Y</param>
        /// <param name="roundUpperLeft">좌상단 라운드 여부</param>
        /// <param name="roundUpperRight">우상단 라운드 여부</param>
        /// <param name="roundLowerRight">우하단 라운드 여부</param>
        /// <param name="roundLowerLeft">좌하단 라운드 여부</param>
        /// <returns>라운드 사각형 패스</returns>
        private GraphicsPath GetRoundedRectanglePath
        (
            RectangleF rectangle,
            float      radiusX,
            float      radiusY,
            bool       roundUpperLeft,
            bool       roundUpperRight,
            bool       roundLowerRight,
            bool       roundLowerLeft
        )
        {
            PointF point1;
            PointF point2;

            GraphicsPath path = new GraphicsPath();

            if(roundUpperLeft)
            {
                RectangleF cornerRectangle = new RectangleF
                (
                    rectangle.X,
                    rectangle.Y,
                    2 * radiusX,
                    2 * radiusY
                );

                path.AddArc(cornerRectangle, 180, 90);

                point1 = new PointF(rectangle.X + radiusX, rectangle.Y);
            }
            else
            {
                point1 = new PointF(rectangle.X, rectangle.Y);
            }

            if(roundUpperRight)
            {
                point2 = new PointF(rectangle.Right - radiusX, rectangle.Y);
            }
            else
            {
                point2 = new PointF(rectangle.Right, rectangle.Y);
            }

            path.AddLine(point1, point2);

            if(roundUpperRight)
            {
                RectangleF cornerRectangle = new RectangleF
                (
                    rectangle.Right - 2 * radiusX,
                    rectangle.Y,
                    2 * radiusX,
                    2 * radiusY
                );

                path.AddArc(cornerRectangle, 270, 90);

                point1 = new PointF(rectangle.Right, rectangle.Y + radiusY);
            }
            else
            {
                point1 = new PointF(rectangle.Right, rectangle.Y);
            }

            if(roundLowerRight)
            {
                point2 = new PointF(rectangle.Right, rectangle.Bottom - radiusY);
            }
            else
            {
                point2 = new PointF(rectangle.Right, rectangle.Bottom);
            }

            path.AddLine(point1, point2);

            if(roundLowerRight)
            {
                RectangleF cornerRectangle = new RectangleF
                (
                    rectangle.Right  - 2 * radiusX,
                    rectangle.Bottom - 2 * radiusY,
                    2 * radiusX,
                    2 * radiusY
                );

                path.AddArc(cornerRectangle, 0, 90);

                point1 = new PointF(rectangle.Right - radiusX, rectangle.Bottom);
            }
            else
            {
                point1 = new PointF(rectangle.Right, rectangle.Bottom);
            }

            if(roundLowerLeft)
            {
                point2 = new PointF(rectangle.X + radiusX, rectangle.Bottom);
            }
            else
            {
                point2 = new PointF(rectangle.X, rectangle.Bottom);
            }

            path.AddLine(point1, point2);

            if(roundLowerLeft)
            {
                RectangleF cornerRectangle = new RectangleF
                (
                    rectangle.X,
                    rectangle.Bottom - 2 * radiusY,
                    2 * radiusX,
                    2 * radiusY
                );

                path.AddArc(cornerRectangle, 90, 90);

                point1 = new PointF(rectangle.X, rectangle.Bottom - radiusY);
            }
            else
            {
                point1 = new PointF(rectangle.X, rectangle.Bottom);
            }

            if(roundUpperLeft)
            {
                point2 = new PointF(rectangle.X, rectangle.Y + radiusY);
            }
            else
            {
                point2 = new PointF(rectangle.X, rectangle.Y);
            }

            path.AddLine(point1, point2);

            path.CloseFigure();

            return path;
        }

        #endregion
        #region 패스 지오메트리 구하기 - GetPathGeometry(graphicsPath)

        /// <summary>
        /// 패스 지오메트리 구하기
        /// </summary>
        /// <param name="graphicsPath">그래픽스 패스</param>
        /// <returns>패스 지오메트리</returns>
        private PathGeometry GetPathGeometry(GraphicsPath graphicsPath)
        {
            List<PathFigure> pathFigureList = new List<PathFigure>();

            if(graphicsPath.PointCount != 0)
            {
                PointF[] pathPointArray = graphicsPath.PathPoints;

                byte[] pathTypeByteArray = graphicsPath.PathTypes;

                PathFigure pathFigure = new PathFigure();

                pathFigureList.Add(pathFigure);

                int index = 0;

                while(index < pathPointArray.Length)
                {
                    switch((int)pathTypeByteArray[index] & 7)
                    {
                        case 0 :

                            System.Windows.Point point1 = new System.Windows.Point
                            (
                                (double)pathPointArray[index].X,
                                (double)pathPointArray[index].Y
                            );

                            pathFigure.StartPoint = point1;

                            ++index;

                            break;

                        case 1 :

                            System.Windows.Point point2 = new System.Windows.Point
                            (
                                (double)pathPointArray[index].X,
                                (double)pathPointArray[index].Y
                            );

                            pathFigure.Segments.Add((PathSegment)new LineSegment(point2, true));

                            ++index;

                            break;

                        case 3 :

                            System.Windows.Point point3 = new System.Windows.Point
                            (
                                (double)pathPointArray[index].X,
                                (double)pathPointArray[index].Y
                            );

                            System.Windows.Point point4 = new System.Windows.Point
                            (
                                (double)pathPointArray[index + 1].X,
                                (double)pathPointArray[index + 1].Y
                            );

                            System.Windows.Point point5 = new System.Windows.Point
                            (
                                (double)pathPointArray[index + 2].X,
                                (double)pathPointArray[index + 2].Y
                            );

                            pathFigure.Segments.Add((PathSegment)new BezierSegment(point3, point4, point5, true));

                            index += 3;

                            break;
                    }

                    if(((int)pathTypeByteArray[index - 1] & 128) != 0)
                    {
                        pathFigure.IsClosed = true;

                        pathFigure = new PathFigure();

                        pathFigureList.Add(pathFigure);
                    }
                }
            }

            return new PathGeometry((IEnumerable<PathFigure>)pathFigureList)
            {
                FillRule = graphicsPath.FillMode == FillMode.Alternate ? FillRule.EvenOdd : FillRule.Nonzero
            };
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요