椭圆形的侧面是在很大的位图上切割的吗?
我正在为Android创建一个像素艺术编辑器,最近我使用了Midpoint椭圆算法实施了椭圆工具。
我只想强调,该工具完美地工作!
唯一的问题是,如果我在较大的位图上绘制一个大椭圆形(约为1000x1000或更多),则椭圆的侧面被切割,而且有一些奇怪的行为正在发生:
为什么会发生这种情况?
中点椭圆算法的代码:
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))
}
}
}
问题仅在MidpointElpeLipSealGorithm
中存在,因此已被隔离。 OverridesetPixel
函数不会引起此行为,因为当我用简单的bitmap.setpixel
替换时,问题仍然存在。但是,尽管它是孤立的,但我感到困惑为什么会发生这种情况。
如果您在较小的画布上绘制椭圆,则无法证明这种行为,它可以很好地工作。只有当您在证明此行为的大比特图上绘制足够大小的椭圆形。
为什么在大的位图上像这样“剪裁”?这是完全荒谬的,因为我的同龄人对算法本身进行了审查,这是一个很高的标准。我试图通过调整变量和不等式来解决它,但是我不知道它来自哪里,甚至将我的算法代码与在线算法代码进行了比较,即使我更换了它,我也会得到问题。
I am creating a pixel art editor for Android, and recently I implemented an ellipse tool using the midpoint ellipse algorithm.
I would just like to emphasize that this tool works perfectly!
The only problem is, if I draw a large ellipse on a larger bitmap (of around 1000x1000 or more), the sides of the ellipse get cut, and there is some strange behaviour going on:
Why is this happening?
Code for the midpoint ellipse algorithm:
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))
}
}
}
The problem only exists in the MidpointEllipseAlgorithm
, so it's been isolated. The overrideSetPixel
function is not causing this behaviour because when I replace it with a simple Bitmap.setPixel
the problem still exists. But, although it's been isolated, I am confused why this is happening.
If you draw the ellipse on smaller canvases this behaviour isn't getting demonstrated, it works perfectly. It's only if you draw an ellipse of a sufficient size on a large bitmap where this behaviour is demonstrated.
Why is it being 'cut' like this on large bitmaps? It's completely nonsensical as the algorithm itself has been reviewed by my peers, and it is to a high standard. I have tried to fix it by adjusting variables and inequalities but I have no clue where it's coming from, I even compared my algorithm code to the ones online and still, even if I replace it I get the issue.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
通过将以下内容转换为
double
来修复:Fixed by converting the following to
double
: