Scala, расположение объектов по окружности - PullRequest
1 голос
/ 12 января 2012

Я пытаюсь заполнить окружность точками, расположенными через равные интервалы.Вот код (он использует некоторую обработку, но это не важно для понимания):

class Circle (x: Float, y: Float, subdivisions: Int, radius: Float) extends WorldObject(x, y) {

  def subs = subdivisions
  def r = radius
  val d = r + r

  def makePoints() : List[Glyph] = { 
    val step = PConstants.TWO_PI / subdivisions
    val points = List.make(subdivisions, new Glyph())

    for(i <- 0 to subdivisions - 1) {
      points(i) position (PApplet.cos(step * i) * r + xPos, PApplet.sin(step * i) * r + yPos)
    }

    points
  }

  val points: List[Glyph] = makePoints()

  override def draw() {
    applet fill 0
    applet stroke 255
    applet ellipse(x, y, d, d)
    applet fill 255

    points map(_.update())
  }

}

class Glyph(x: Float, y: Float) extends WorldObject(x, y){
    def this() = this(0, 0)

    override def draw() {
      applet ellipse(xPos, yPos, 10, 10)
    }
}

object WorldObject {

}

abstract class WorldObject(var xPos: Float, var yPos: Float) {
  def this() = this(0, 0)
  def x = xPos
  def y = yPos

  def update() {
    draw()
  }

  def draw()

  def position(x: Float, y: Float) {
    xPos = x
    yPos = y
  }

  def move(dx: Float, dy: Float) {
    xPos += dx
    yPos += dy
  }
}

Странный результат, который я получаю, заключается в том, что все точки расположены в одном месте.Я экспериментировал с проверками println ... проверки в методе makePoints() показывают все нормально, но проверки в Circle.draw() или даже сразу после makePoints() показывают результат, как я вижу его на экране - всеточки расположены в одном месте, именно там, где генерируется последняя из них, а именно x=430.9017 y=204.89435 для круга, расположенного в x=400 y=300 и подразделенного на 5 точек.Так что как-то все они собираются в том месте, где сидит последний из них.

Почему такое поведение?Что я делаю не так?


UPD: Нам удалось найти причину, см. Ниже:

Отвечая на вопрос, неизвестный пользователь изменил кодиспользовать метод fill вместо make.Основное существенное различие между ними заключается в том, что make предварительно вычисляет его аргументы, а fill - нет.Таким образом make заполняет список полностью идентичными элементами.Однако fill повторяет вычисления для каждого дополнения.Вот исходные коды этих методов из источников Scala:

  /** Create a list containing several copies of an element.
   *
   *  @param n    the length of the resulting list
   *  @param elem the element composing the resulting list
   *  @return     a list composed of n elements all equal to elem
   */
  @deprecated("use `fill' instead", "2.8.0")
  def make[A](n: Int, elem: A): List[A] = {
    val b = new ListBuffer[A]
    var i = 0
    while (i < n) {
      b += elem
      i += 1
    }
    b.toList
  }

И метод fill:

  /** Produces a $coll containing the results of some element computation a number of times.
   *  @param   n  the number of elements contained in the $coll.
   *  @param   elem the element computation
   *  @return  A $coll that contains the results of `n` evaluations of `elem`.
   */
  def fill[A](n: Int)(elem: => A): CC[A] = {
    val b = newBuilder[A]
    b.sizeHint(n)
    var i = 0
    while (i < n) {
      b += elem
      i += 1
    }
    b.result
  }

1 Ответ

1 голос
/ 12 января 2012

Я изменил много переменных вперед и назад (def x = ... => def x () =, x / this.x и x / xPos и ​​т. Д.), Добавил операторы println и удалил (P) applet- материал, который заставил компилятор жаловаться.

Было бы полезно предоставить скомпилируемую, запускаемую, автономную демонстрацию. Вот оно:

class Circle (x: Float, y: Float, subdivisions: Int, radius: Float) 
    extends WorldObject (x, y) {

  def subs = subdivisions
  def r = radius
  val d = r + r

  def makePoints() : List[Glyph] = { 
//    val step = PConstants.TWO_PI / subdivisions
    val step = 6.283F / subdivisions
    val points = List.fill (subdivisions) (new Glyph ())
    for (i <- 0 to subdivisions - 1) {
//      points (i) position (PApplet.cos (step * i) * r + xPos, 
//          PApplet.sin (step * i) * r + yPos)
                val xx = (math.cos (step * i) * r).toFloat + xPos
                val yy = (math.sin (step * i) * r).toFloat + yPos
                println (xx + ": " + yy)
      points (i) position (xx, yy)
    }
    points
  }

  val points: List [Glyph] = makePoints ()
  override def draw () {
  /*
    applet fill 0
    applet stroke 255
    applet ellipse(x, y, d, d)
    applet fill 255
  */
//    println ("Circle:draw () upd-> " + super.x () + "\t" + y () + "\t" + d); 
    points map (_.update ())
    println ("Circle:draw () <-upd " + x + "\t" + y + "\t" + d); 
  }
}

class Glyph (x: Float, y: Float) extends WorldObject (x, y) {
    def this () = this (0, 0)
    override def draw() {
      // applet ellipse (xPos, yPos, 10, 10)
      println ("Glyph:draw (): " + xPos + "\t" + yPos + "\t" + 10); 
    }
}

object Circle {
    def main (as: Array [String]) : Unit = {
        val c = new Circle (400, 300, 5, 100)
        c.draw ()       
    }
}

object WorldObject {

}

abstract class WorldObject (var xPos: Float, var yPos: Float) {

  def this () = this (0, 0)
  def x = xPos
  def y = yPos

  def update () {
    draw ()
  }

  def draw ()

  def position (x: Float, y: Float) {
    xPos = x
    yPos = y
    // println (x + " ?= " + xPos + " ?= " + (this.x ()))
  }

  def move (dx: Float, dy: Float) {
    xPos += dx
    yPos += dy
  }
}

Мой результат:

500.0: 300.0
430.9052: 395.1045
319.10266: 358.78452
319.09177: 241.23045
430.8876: 204.88977
Glyph:draw (): 500.0    300.0   10
Glyph:draw (): 430.9052 395.1045    10
Glyph:draw (): 319.10266    358.78452   10
Glyph:draw (): 319.09177    241.23045   10
Glyph:draw (): 430.8876 204.88977   10
Circle:draw () <-upd 400.0  300.0   200.0

Можете ли вы заметить разницу?

Вы должны создать копию своего кода и поэтапно удалить код, который не нужен для воспроизведения ошибки, проверяя, сохраняется ли ошибка по-прежнему. Тогда вы должны решить гораздо меньшую проблему или найти ошибку самостоятельно.

...