android 椭圆的边在大位图上被剪切?

vatpfxk5  于 2023-02-02  发布在  Android
关注(0)|答案(1)|浏览(123)

我正在为Android创建一个像素艺术编辑器,最近我使用中点椭圆算法实现了一个椭圆工具。
我只想强调这个工具工作 * 完美!*
唯一的问题是,如果我在一个更大的位图(大约1000 x1000或更大)上绘制一个大椭圆,椭圆的边会被剪切,并且会出现一些奇怪的行为:

为什么会这样呢?
中点椭圆算法的代码:

  1. package com.therealbluepandabear.pixapencil.algorithms
  2. import com.therealbluepandabear.pixapencil.activities.canvas.canvascommands.overrideSetPixel
  3. import com.therealbluepandabear.pixapencil.models.Coordinates
  4. class MidpointEllipseAlgorithm(private val algorithmInfo: AlgorithmInfoParameter, private val xDEC: Boolean = false, private val yDEC: Boolean = false, private val filledMode: Boolean = false) {
  5. private val shouldLineIgnoreBrush = true
  6. private fun putPixel(p1: Coordinates, p2: Coordinates) {
  7. val xc = p1.x
  8. val yc = p1.y
  9. val x = p2.x
  10. val y = p2.y
  11. if (!xDEC && !yDEC) {
  12. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  13. Coordinates(xc + x, yc + y),
  14. algorithmInfo.color
  15. )
  16. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  17. Coordinates(xc + x, yc - y),
  18. algorithmInfo.color
  19. )
  20. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  21. Coordinates(xc - x, yc - y),
  22. algorithmInfo.color
  23. )
  24. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  25. Coordinates(xc - x, yc + y),
  26. algorithmInfo.color
  27. )
  28. if (filledMode) {
  29. val lineAlgorithmInstance = LineAlgorithm(algorithmInfo, shouldLineIgnoreBrush)
  30. lineAlgorithmInstance.compute(
  31. Coordinates(xc + x, yc + y),
  32. Coordinates(xc + x, yc - y),
  33. )
  34. lineAlgorithmInstance.compute(
  35. Coordinates(xc - x, yc - y),
  36. Coordinates(xc - x, yc + y),
  37. )
  38. }
  39. } else if (xDEC && !yDEC) {
  40. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  41. Coordinates((xc + x) + 1, yc + y),
  42. algorithmInfo.color
  43. )
  44. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  45. Coordinates((xc + x) + 1, yc - y),
  46. algorithmInfo.color
  47. )
  48. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  49. Coordinates(xc - x, yc - y),
  50. algorithmInfo.color
  51. )
  52. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  53. Coordinates(xc - x, yc + y),
  54. algorithmInfo.color
  55. )
  56. if (filledMode) {
  57. val lineAlgorithmInstance = LineAlgorithm(algorithmInfo, shouldLineIgnoreBrush)
  58. lineAlgorithmInstance.compute(
  59. Coordinates((xc + x) + 1, yc + y),
  60. Coordinates((xc + x) + 1, yc - y),
  61. )
  62. lineAlgorithmInstance.compute(
  63. Coordinates(xc - x, yc - y),
  64. Coordinates(xc - x, yc + y),
  65. )
  66. }
  67. } else if (!xDEC && yDEC) {
  68. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  69. Coordinates(xc + x, (yc + y) + 1),
  70. algorithmInfo.color
  71. )
  72. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  73. Coordinates(xc + x, yc - y),
  74. algorithmInfo.color
  75. )
  76. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  77. Coordinates(xc - x, yc - y),
  78. algorithmInfo.color
  79. )
  80. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  81. Coordinates(xc - x, (yc + y) + 1),
  82. algorithmInfo.color
  83. )
  84. if (filledMode) {
  85. val lineAlgorithmInstance = LineAlgorithm(algorithmInfo, shouldLineIgnoreBrush)
  86. lineAlgorithmInstance.compute(
  87. Coordinates(xc + x, (yc + y) + 1),
  88. Coordinates(xc + x, yc - y),
  89. )
  90. lineAlgorithmInstance.compute(
  91. Coordinates(xc - x, yc - y),
  92. Coordinates(xc - x, (yc + y) + 1),
  93. )
  94. }
  95. } else {
  96. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  97. Coordinates((xc + x) + 1, (yc + y) + 1),
  98. algorithmInfo.color
  99. )
  100. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  101. Coordinates((xc + x) + 1, yc - y),
  102. algorithmInfo.color
  103. )
  104. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  105. Coordinates(xc - x, yc - y),
  106. algorithmInfo.color
  107. )
  108. algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
  109. Coordinates(xc - x, (yc + y) + 1),
  110. algorithmInfo.color
  111. )
  112. if (filledMode) {
  113. val lineAlgorithmInstance = LineAlgorithm(algorithmInfo, shouldLineIgnoreBrush)
  114. lineAlgorithmInstance.compute(
  115. Coordinates((xc + x) + 1, (yc + y) + 1),
  116. Coordinates((xc + x) + 1, yc - y),
  117. )
  118. lineAlgorithmInstance.compute(
  119. Coordinates(xc - x, yc - y),
  120. Coordinates(xc - x, (yc + y) + 1),
  121. )
  122. }
  123. }
  124. }
  125. fun compute(p1: Coordinates, rx: Int, ry: Int) {
  126. val idp = Coordinates(0, ry)
  127. var xkp1 = idp.x
  128. var ykp1 = idp.y
  129. var lxkp1: Int
  130. var lykp1: Int
  131. var p1k = (ry * ry) + ((rx * rx) / 4) - (ry * (rx * rx))
  132. val incy = p1.y
  133. val incx = p1.x
  134. putPixel(Coordinates(incx, incy), Coordinates(xkp1, ykp1))
  135. while (
  136. (2 * (xkp1 + 1) * (ry * ry))
  137. <
  138. (2 * ykp1 * (rx * rx))
  139. ) {
  140. p1k += if (p1k >= 0) {
  141. xkp1++
  142. ykp1--
  143. lxkp1 = xkp1 - 1
  144. lykp1 = ykp1 + 1
  145. (ry * ry) + (2 * (lxkp1 + 1)) * (ry * ry) + (rx * rx) * ((ykp1 * ykp1) - (lykp1 * lykp1)) - (rx * rx) * (ykp1 - lykp1)
  146. } else {
  147. xkp1++
  148. lxkp1 = xkp1 - 1
  149. lykp1 = ykp1
  150. (ry * ry) + (2 * (lxkp1 + 1)) * (ry * ry) + (rx * rx) * ((ykp1 * ykp1) - (lykp1 * lykp1))
  151. }
  152. putPixel(Coordinates(incx, incy), Coordinates(xkp1, ykp1))
  153. }
  154. var p2k = (ry * ry) * ((xkp1 + 0.5) * (xkp1 + 0.5)) + (rx * rx) * ((ykp1 - 1) * (ykp1 - 1)) - ((rx * rx) * (ry * ry))
  155. while (
  156. ykp1 > 0
  157. ) {
  158. if (p2k >= 0) {
  159. ykp1--
  160. lykp1 = ykp1 + 1
  161. lxkp1 = xkp1
  162. p2k += (rx * rx) - 2 * (rx * rx) * (lykp1 - 1) + (ry * ry) * ((xkp1 * xkp1) - (lxkp1 * lxkp1))
  163. } else {
  164. xkp1++
  165. lxkp1 = xkp1 - 1
  166. ykp1--
  167. lykp1 = ykp1 + 1
  168. p2k += (rx * rx) - 2 * (rx * rx) * (lykp1 - 1) + (ry * ry) * ((xkp1 * xkp1) - (lxkp1 * lxkp1)) + (ry * ry) * (xkp1 - lxkp1)
  169. }
  170. putPixel(Coordinates(incx, incy), Coordinates(xkp1, ykp1))
  171. }
  172. }
  173. }

这个问题只存在于MidpointEllipseAlgorithm中,所以它已经被隔离了。overrideSetPixel函数没有导致这个行为,因为当我用一个简单的Bitmap.setPixel替换它时,问题仍然存在。但是,尽管它已经被隔离了,我还是不明白为什么会发生这种情况。
如果你在较小的画布上画椭圆,这个行为就不会被演示,它可以完美地工作。只有当你在一个大的位图上画一个足够大的椭圆时,这个行为才会被演示。
为什么在大的位图上它会被这样“剪切”?这完全是无稽之谈,因为算法本身已经被我的同行审查过了,而且它是高标准的。我试图通过调整变量和不等式来修复它,但我不知道它是从哪里来的,我甚至把我的算法代码与网上的算法代码进行了比较,即使我替换了它,我仍然会遇到这个问题。

j7dteeu8

j7dteeu81#

通过将以下内容转换为double进行修复:

  1. var p2k = (ry.toDouble() * ry.toDouble()) * ((xkp1.toDouble() + 0.5) * (xkp1.toDouble() + 0.5)) + (rx.toDouble() * rx.toDouble()) * ((ykp1.toDouble() - 1) * (ykp1.toDouble() - 1)) - ((rx.toDouble() * rx.toDouble()) * (ry.toDouble() * ry.toDouble()))

相关问题