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

728x90
반응형

■ Canvas 클래스 : 호(Arc) 도형 추가하기 예제

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

using System.Windows;

using System.Windows.Controls;

using System.Windows.Media;

 

Canvas canvas = new Canvas();

 

Rect   rectangle  = new Rect(100, 100, 200, 200); // 타원 사각형

double startAngle =  0 * (Math.PI / 180d);        // 시작 각도

double endAngle   = 90 * (Math.PI / 180d);        // 종료 각도

 

Point point1;

Point point2;

 

AddArc

(

    canvas,

    Brushes.Transparent,

    Brushes.Red,

    3,

    rectangle,

    startAngle,

    endAngle,

    false,

    SweepDirection.Clockwise,

    out point1,

    out point2

);

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

 

■ Canvas 클래스 : 호(Arc) 도형 추가하기

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

using System;

using System.Collections.Generic;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Media;

using System.Windows.Shapes;

 

#region 호 도형 추가하기 - AddArc(canvas, fillBrush, strokeBrush, strokeThickness, startPoint, endPoint, size, rotationAngle, isLargeArc, sweepDirection, isStroked)

 

/// <summary>

/// 호 도형 추가하기

/// </summary>

/// <param name="canvas">캔버스</param>

/// <param name="fillBrush">채우기 브러시</param>

/// <param name="strokeBrush">스트로크 브러시</param>

/// <param name="strokeThickness">스트로크 두께</param>

/// <param name="startPoint">시작 포인트</param>

/// <param name="endPoint">종료 포인트</param>

/// <param name="size">크기</param>

/// <param name="rotationAngle">회전 각도</param>

/// <param name="isLargeArc">큰 호 여부</param>

/// <param name="sweepDirection">스위프 방향</param>

/// <param name="isStroked">스트로크 여부</param>

/// <returns>호 패스 도형</returns>

public Path AddArc

(

    Canvas         canvas,

    Brush          fillBrush,

    Brush          strokeBrush,

    double         strokeThickness,

    Point          startPoint,

    Point          endPoint,

    Size           size,

    double         rotationAngle,

    bool           isLargeArc,

    SweepDirection sweepDirection,

    bool           isStroked

)

{

    ArcSegment arcSegment = new ArcSegment

    (

        endPoint,

        size,

        rotationAngle,

        isLargeArc,

        sweepDirection,

        isStroked

    );

 

    PathSegmentCollection pathSegmentCollection = new PathSegmentCollection();

 

    pathSegmentCollection.Add(arcSegment);

 

    PathFigure pathFigure = new PathFigure();

 

    pathFigure.StartPoint = startPoint;

    pathFigure.Segments   = pathSegmentCollection;

 

    PathGeometry pathGeometry = new PathGeometry();

 

    pathGeometry.Figures.Add(pathFigure);

 

    Path path = new Path();

 

    path.Fill            = fillBrush;

    path.Stroke          = strokeBrush;

    path.StrokeThickness = strokeThickness;

    path.Data            = pathGeometry;

 

    canvas.Children.Add(path);

 

    return path;

}

 

#endregion

#region 호 도형 추가하기 - AddArc(canvas, fillBrush, strokeBrush, strokeThickness, rectangle, angle1, angle2, isLargeArc, sweepDirection, point1, point2)

 

/// <summary>

/// 호 도형 추가하기

/// </summary>

/// <param name="canvas">캔버스</param>

/// <param name="fillBrush">채우기 브러시</param>

/// <param name="strokeBrush">스트로크 브러시</param>

/// <param name="strokeThickness">스트로크 두께</param>

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

/// <param name="angle1">각도 1</param>

/// <param name="angle2">각도 2</param>

/// <param name="isLargeArc">큰 호 여부</param>

/// <param name="sweepDirection">스위프 방향</param>

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

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

/// <returns>호 패스 도형</returns>

public Path AddArc

(

    Canvas         canvas,

    Brush          fillBrush,

    Brush          strokeBrush,

    double         strokeThickness,

    Rect           rectangle,

    double         angle1,

    double         angle2,

    bool           isLargeArc,

    SweepDirection sweepDirection,

    out Point      point1,

    out Point      point2

)

{

    Point[] pointArray = GetEllipsePointArray(rectangle, angle1, angle2);

 

    point1 = pointArray[0];

    point2 = pointArray[1];

 

    Size size = new Size(rectangle.Width / 2, rectangle.Height / 2);

 

    return AddArc

    (

        canvas,

        fillBrush,

        strokeBrush,

        strokeThickness,

        pointArray[0],

        pointArray[1],

        size,

        0,

        isLargeArc,

        sweepDirection,

        true

    );

}

 

#endregion

 

#region 타원 포인트 배열 구하기 - GetEllipsePointArray(rectangle, startAngle, endAngle)

 

/// <summary>

/// 타원 포인트 배열 구하기

/// </summary>

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

/// <param name="startAngle">시작 각도</param>

/// <param name="endAngle">종료 각도</param>

/// <returns>타원 포인트 배열</returns>

private Point[] GetEllipsePointArray(Rect rectangle, double startAngle, double endAngle)

{

    Point centerPoint = new Point

    (

        rectangle.X + rectangle.Width  / 2.0,

        rectangle.Y + rectangle.Height / 2.0

    );

 

    double distance = rectangle.Width + rectangle.Height;

 

    Point point1 = new Point

    (

        centerPoint.X + distance * Math.Cos(startAngle),

        centerPoint.Y + distance * Math.Sin(startAngle)

    );

 

    Point point2 = new Point

    (

        centerPoint.X + distance * Math.Cos(endAngle),

        centerPoint.Y + distance * Math.Sin(endAngle)

    );

 

    Point[] intersectionPointArray1 = FindEllipseLineIntersectionPointArray

    (

        rectangle,

        centerPoint,

        point1,

        true

    );

 

    Point[] intersectionPointArray2 = FindEllipseLineIntersectionPointArray

    (

        rectangle,

        centerPoint,

        point2,

        true

    );

 

    return new Point[]

    {

        intersectionPointArray1[0],

        intersectionPointArray2[0]

    };

}

 

#endregion

#region 타원과 직선 교차점 배열 찾기 - FindEllipseLineIntersectionPointArray(rectangle, lineStartPoint, lineEndPoint, segmentOnly)

 

/// <summary>

/// 타원과 직선 교차점 배열 찾기

/// </summary>

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

/// <param name="lineStartPoint">직선 시작점</param>

/// <param name="lineEndPoint">직선 종료점</param>

/// <param name="segmentOnly">세그먼트만 여부</param>

/// <returns>타원과 직선 교차점 배열</returns>

private Point[] FindEllipseLineIntersectionPointArray

(

    Rect  rectangle,

    Point lineStartPoint,

    Point lineEndPoint,

    bool  segmentOnly

)

{

    if((rectangle.Width == 0) || (rectangle.Height == 0) || ((lineStartPoint.X == lineEndPoint.X) && (lineStartPoint.Y == lineEndPoint.Y)))

    {

        return new Point[] { };

    }

 

    if(rectangle.Width < 0)

    {

        rectangle.X     =  rectangle.Right;

        rectangle.Width = -rectangle.Width;

    }

            

    if(rectangle.Height < 0)

    {

        rectangle.Y      =  rectangle.Bottom;

        rectangle.Height = -rectangle.Height;

    }

 

    double centerX = rectangle.Left + rectangle.Width  / 2f;

    double centerY = rectangle.Top  + rectangle.Height / 2f;

 

    rectangle.X -= centerX;

    rectangle.Y -= centerY;

 

    lineStartPoint.X -= centerX;

    lineStartPoint.Y -= centerY;

 

    lineEndPoint.X -= centerX;

    lineEndPoint.Y -= centerY;

 

    double a = rectangle.Width  / 2;

    double b = rectangle.Height / 2;

 

    double c1 = (lineEndPoint.X - lineStartPoint.X) * (lineEndPoint.X - lineStartPoint.X) / a / a +

                (lineEndPoint.Y - lineStartPoint.Y) * (lineEndPoint.Y - lineStartPoint.Y) / b / b;

    double c2 = 2 * lineStartPoint.X * (lineEndPoint.X - lineStartPoint.X) / a / a +

                2 * lineStartPoint.Y * (lineEndPoint.Y - lineStartPoint.Y) / b / b;

    double c3 = lineStartPoint.X * lineStartPoint.X / a / a + lineStartPoint.Y * lineStartPoint.Y / b / b - 1;

 

    List<double> valueList = new List<double>();

 

    double discriminant = c2 * c2 - 4 * c1 * c3;

 

    if(discriminant == 0)

    {

        valueList.Add(-c2 / 2 / c1);

    }

    else if(discriminant > 0)

    {

        valueList.Add((double)((-c2 + Math.Sqrt(discriminant)) / 2 / c1));

        valueList.Add((double)((-c2 - Math.Sqrt(discriminant)) / 2 / c1));

    }

 

    List<Point> pointList = new List<Point>();

 

    foreach(double value in valueList)

    {

        if(!segmentOnly || ((value >= 0f) && (value <= 1f)))

        {

            double x = lineStartPoint.X + (lineEndPoint.X - lineStartPoint.X) * value + centerX;

            double y = lineStartPoint.Y + (lineEndPoint.Y - lineStartPoint.Y) * value + centerY;

 

            pointList.Add(new Point(x, y));

        }

    }

 

    return pointList.ToArray();

}

 

#endregion

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

728x90
반응형
Posted by 사용자 icodebroker
TAG , ,

댓글을 달아 주세요