我正在为Android创建一个像素艺术编辑器,最近我使用中点椭圆算法实现了一个椭圆工具。
我只想强调这个工具工作 * 完美!*
唯一的问题是,如果我在一个更大的位图(大约1000 x1000或更大)上绘制一个大椭圆,椭圆的边会被剪切,并且会出现一些奇怪的行为:
为什么会这样呢?
中点椭圆算法的代码:
package com.therealbluepandabear.pixapencil.algorithms
import com.therealbluepandabear.pixapencil.activities.canvas.canvascommands.overrideSetPixel
import com.therealbluepandabear.pixapencil.models.Coordinates
class MidpointEllipseAlgorithm(private val algorithmInfo: AlgorithmInfoParameter, private val xDEC: Boolean = false, private val yDEC: Boolean = false, private val filledMode: Boolean = false) {
private val shouldLineIgnoreBrush = true
private fun putPixel(p1: Coordinates, p2: Coordinates) {
val xc = p1.x
val yc = p1.y
val x = p2.x
val y = p2.y
if (!xDEC && !yDEC) {
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates(xc + x, yc + y),
algorithmInfo.color
)
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates(xc + x, yc - y),
algorithmInfo.color
)
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates(xc - x, yc - y),
algorithmInfo.color
)
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates(xc - x, yc + y),
algorithmInfo.color
)
if (filledMode) {
val lineAlgorithmInstance = LineAlgorithm(algorithmInfo, shouldLineIgnoreBrush)
lineAlgorithmInstance.compute(
Coordinates(xc + x, yc + y),
Coordinates(xc + x, yc - y),
)
lineAlgorithmInstance.compute(
Coordinates(xc - x, yc - y),
Coordinates(xc - x, yc + y),
)
}
} else if (xDEC && !yDEC) {
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates((xc + x) + 1, yc + y),
algorithmInfo.color
)
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates((xc + x) + 1, yc - y),
algorithmInfo.color
)
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates(xc - x, yc - y),
algorithmInfo.color
)
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates(xc - x, yc + y),
algorithmInfo.color
)
if (filledMode) {
val lineAlgorithmInstance = LineAlgorithm(algorithmInfo, shouldLineIgnoreBrush)
lineAlgorithmInstance.compute(
Coordinates((xc + x) + 1, yc + y),
Coordinates((xc + x) + 1, yc - y),
)
lineAlgorithmInstance.compute(
Coordinates(xc - x, yc - y),
Coordinates(xc - x, yc + y),
)
}
} else if (!xDEC && yDEC) {
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates(xc + x, (yc + y) + 1),
algorithmInfo.color
)
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates(xc + x, yc - y),
algorithmInfo.color
)
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates(xc - x, yc - y),
algorithmInfo.color
)
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates(xc - x, (yc + y) + 1),
algorithmInfo.color
)
if (filledMode) {
val lineAlgorithmInstance = LineAlgorithm(algorithmInfo, shouldLineIgnoreBrush)
lineAlgorithmInstance.compute(
Coordinates(xc + x, (yc + y) + 1),
Coordinates(xc + x, yc - y),
)
lineAlgorithmInstance.compute(
Coordinates(xc - x, yc - y),
Coordinates(xc - x, (yc + y) + 1),
)
}
} else {
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates((xc + x) + 1, (yc + y) + 1),
algorithmInfo.color
)
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates((xc + x) + 1, yc - y),
algorithmInfo.color
)
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates(xc - x, yc - y),
algorithmInfo.color
)
algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
Coordinates(xc - x, (yc + y) + 1),
algorithmInfo.color
)
if (filledMode) {
val lineAlgorithmInstance = LineAlgorithm(algorithmInfo, shouldLineIgnoreBrush)
lineAlgorithmInstance.compute(
Coordinates((xc + x) + 1, (yc + y) + 1),
Coordinates((xc + x) + 1, yc - y),
)
lineAlgorithmInstance.compute(
Coordinates(xc - x, yc - y),
Coordinates(xc - x, (yc + y) + 1),
)
}
}
}
fun compute(p1: Coordinates, rx: Int, ry: Int) {
val idp = Coordinates(0, ry)
var xkp1 = idp.x
var ykp1 = idp.y
var lxkp1: Int
var lykp1: Int
var p1k = (ry * ry) + ((rx * rx) / 4) - (ry * (rx * rx))
val incy = p1.y
val incx = p1.x
putPixel(Coordinates(incx, incy), Coordinates(xkp1, ykp1))
while (
(2 * (xkp1 + 1) * (ry * ry))
<
(2 * ykp1 * (rx * rx))
) {
p1k += if (p1k >= 0) {
xkp1++
ykp1--
lxkp1 = xkp1 - 1
lykp1 = ykp1 + 1
(ry * ry) + (2 * (lxkp1 + 1)) * (ry * ry) + (rx * rx) * ((ykp1 * ykp1) - (lykp1 * lykp1)) - (rx * rx) * (ykp1 - lykp1)
} else {
xkp1++
lxkp1 = xkp1 - 1
lykp1 = ykp1
(ry * ry) + (2 * (lxkp1 + 1)) * (ry * ry) + (rx * rx) * ((ykp1 * ykp1) - (lykp1 * lykp1))
}
putPixel(Coordinates(incx, incy), Coordinates(xkp1, ykp1))
}
var p2k = (ry * ry) * ((xkp1 + 0.5) * (xkp1 + 0.5)) + (rx * rx) * ((ykp1 - 1) * (ykp1 - 1)) - ((rx * rx) * (ry * ry))
while (
ykp1 > 0
) {
if (p2k >= 0) {
ykp1--
lykp1 = ykp1 + 1
lxkp1 = xkp1
p2k += (rx * rx) - 2 * (rx * rx) * (lykp1 - 1) + (ry * ry) * ((xkp1 * xkp1) - (lxkp1 * lxkp1))
} else {
xkp1++
lxkp1 = xkp1 - 1
ykp1--
lykp1 = ykp1 + 1
p2k += (rx * rx) - 2 * (rx * rx) * (lykp1 - 1) + (ry * ry) * ((xkp1 * xkp1) - (lxkp1 * lxkp1)) + (ry * ry) * (xkp1 - lxkp1)
}
putPixel(Coordinates(incx, incy), Coordinates(xkp1, ykp1))
}
}
}
这个问题只存在于MidpointEllipseAlgorithm
中,所以它已经被隔离了。overrideSetPixel
函数没有导致这个行为,因为当我用一个简单的Bitmap.setPixel
替换它时,问题仍然存在。但是,尽管它已经被隔离了,我还是不明白为什么会发生这种情况。
如果你在较小的画布上画椭圆,这个行为就不会被演示,它可以完美地工作。只有当你在一个大的位图上画一个足够大的椭圆时,这个行为才会被演示。
为什么在大的位图上它会被这样“剪切”?这完全是无稽之谈,因为算法本身已经被我的同行审查过了,而且它是高标准的。我试图通过调整变量和不等式来修复它,但我不知道它是从哪里来的,我甚至把我的算法代码与网上的算法代码进行了比较,即使我替换了它,我仍然会遇到这个问题。
1条答案
按热度按时间j7dteeu81#
通过将以下内容转换为
double
进行修复: