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

▶ 타원 상에서 호(Arc) 시작점/종료점 구하기 예제

using System;
using System.Windows;

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

Point[] pointArray = GetEllipsePointArray(rectangle, startAngle, endAngle);

 

728x90

 

▶ 타원 상에서 호(Arc) 시작점/종료점 구하기

using System;
using System.Collections.Generic;
using System.Windows;

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

/// <summary>
/// 타원 포인트 배열 구하기
/// </summary>
/// <param name="rectangle">사각형</param>
/// <param name="startAngle">시작 각도</param>
/// <param name="endAngle">종료 각도</param>
/// <returns>타원 포인트 배열</returns>
public 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

댓글을 달아 주세요