[Android] 모서리가 둥근 사다리꼴 그리기

uuranus·2024년 7월 18일
0
post-thumbnail

사다리꼴 그리기

직선으로만 그리는 사다리꼴은 이 포스팅에서 다뤘다.

center 위치 구하기

사다리꼴의 꼭짓점을 둥글게 만드는 원의 중심좌표부터 각도를 이용하여 구해준다.

val startSkewedWidth = width * startSkewed
val endSkewedWidth = width * endSkewed

val bottomStartHalfAngle = atan(height / startSkewedWidth) / 2
val bottomEndHalfAngle = atan(height / endSkewedWidth) / 2
val bottomStartHalfAngleDegree = bottomStartHalfAngle.toDegree()
val bottomEndHalfAngleDegree = bottomEndHalfAngle.toDegree()

val topStartCircleCenter = Point(
    startSkewedWidth + topStart / tan(PI / 2 - bottomStartHalfAngle).toFloat(),
    topStart
)
val topEndCircleCenter = Point(
    width - endSkewedWidth - topEnd / tan(PI / 2 - bottomEndHalfAngle).toFloat(),
    topEnd
)
val bottomStartCircleCenter = Point(
    bottomStart / tan(bottomStartHalfAngle),
    height - bottomStart
)
val bottomEndCircleCenter = Point(
    width - bottomEnd / tan(bottomEndHalfAngle),
    height - bottomEnd
)

모서리만 그리기

각 원의 중심좌표와 각도를 이용하여서 모서리를 arcTo를 이용해 그린다.

arcTo(
    rect = Rect(
        offset = Offset(
            topStartCircleCenter.x - topStart,
            topStartCircleCenter.y - topStart
        ),
        size = Size(topStart * 2, topStart * 2)
    ),
    startAngleDegrees = -90f - 2 * bottomStartHalfAngleDegree,
    sweepAngleDegrees = 2 * bottomStartHalfAngleDegree,
    forceMoveTo = false
)

최종 결과물

전체 코드

val path = Path()

val width = size.width
val height = size.height

val startSkewedWidth = width * startSkewed
val endSkewedWidth = width * endSkewed

val bottomStartHalfAngle = atan(height / startSkewedWidth) / 2
val bottomEndHalfAngle = atan(height / endSkewedWidth) / 2
val bottomStartHalfAngleDegree = bottomStartHalfAngle.toDegree()
val bottomEndHalfAngleDegree = bottomEndHalfAngle.toDegree()

val topStartCircleCenter = Point(
    startSkewedWidth + topStart / tan(PI / 2 - bottomStartHalfAngle).toFloat(),
    topStart
)
val topEndCircleCenter = Point(
    width - endSkewedWidth - topEnd / tan(PI / 2 - bottomEndHalfAngle).toFloat(),
    topEnd
)
val bottomStartCircleCenter = Point(
    bottomStart / tan(bottomStartHalfAngle),
    height - bottomStart
)
val bottomEndCircleCenter = Point(
    width - bottomEnd / tan(bottomEndHalfAngle),
    height - bottomEnd
)

path.apply {
    arcTo(
        rect = Rect(
            offset = Offset(
                topStartCircleCenter.x - topStart,
                topStartCircleCenter.y - topStart
            ),
            size = Size(topStart * 2, topStart * 2)
        ),
        startAngleDegrees = -90f - 2 * bottomStartHalfAngleDegree,
        sweepAngleDegrees = 2 * bottomStartHalfAngleDegree,
        forceMoveTo = false
    )

    arcTo(
        rect = Rect(
            offset = Offset(
                topEndCircleCenter.x - topEnd,
                topEndCircleCenter.y - topEnd
            ),
            size = Size(topEnd * 2, topEnd * 2)
        ),
        startAngleDegrees = -90f,
        sweepAngleDegrees = 2 * bottomEndHalfAngleDegree,
        forceMoveTo = false
    )

    arcTo(
        rect = Rect(
            offset = Offset(
                bottomEndCircleCenter.x - bottomEnd,
                bottomEndCircleCenter.y - bottomEnd
            ),
            size = Size(bottomEnd * 2, bottomEnd * 2)
        ),
        startAngleDegrees = 2 * bottomEndHalfAngleDegree - 90f,
        sweepAngleDegrees = 180f - 2 * bottomEndHalfAngleDegree,
        forceMoveTo = false
    )

    arcTo(
        rect = Rect(
            offset = Offset(
                bottomStartCircleCenter.x - bottomStart,
                bottomStartCircleCenter.y - bottomStart
            ),
            size = Size(bottomStart * 2, bottomStart * 2)
        ),
        startAngleDegrees = 90f,
        sweepAngleDegrees = 180f - 2 * bottomStartHalfAngleDegree,
        forceMoveTo = false
    )

    close()
}

깃헙 링크

https://github.com/uuranus/compose-shapes

profile
Frontend Developer

0개의 댓글