Круги обнаружения столкновений с использованием рекурсии в JavaScript

Я хочу создавать круги в случайных местах на определенном расстоянии от основного круга. Круги не должны пересекаться друг с другом. Я создал метод, который проверяет каждый круг, не пересекает ли он все другие круги. Обнаружение столкновений делает свое дело, но часть рекурсии в моем коде не работает:

if (collision > 0) {
    console.log("GENERATE NEW RANDOM COORDINATE")
    generateRandomCoordinate(d, r)
}

Результат

Как вы можете видеть в выходных данных, мое приложение генерирует новые координаты (158 290) при обнаружении столкновения (138 272). Тем не менее, он по-прежнему рисует круг в точке (138 272).

Есть идеи, почему это происходит? Пожалуйста, дайте мне знать, если вы знаете более эффективный способ ...

Функция generateRandomCoordinate

function generateRandomCoordinate(d, r) {
    var phi = Math.random() * 2 * Math.PI
    var x = topicCoordinates[0].x + Math.round(d * Math.cos(phi))
    var y = topicCoordinates[0].y + Math.round(d * Math.sin(phi))
    var collision = 0
    for (var j = 0; j < topicCoordinates.length; j++) {
        var dx = x - topicCoordinates[j].x
        var dy = y - topicCoordinates[j].y
        var distance = Math.sqrt(dx * dx + dy * dy)

        if (distance < r + topicCoordinates[j].r) {
            collision++
            console.log("COLLISION DETECTED BETWEEN POINT(" + "x: " + x + ", y: " + y + ") AND  POINT(x1: " + topicCoordinates[j].x + ", y1: " + topicCoordinates[j].y + ")")
        }
    }
    if (collision > 0) {
        console.log("GENERATE NEW RANDOM COORDINATE")
        generateRandomCoordinate(d, r)
    }

    var topicCoordinate = {
        "x": x,
        "y": y,
        "r": r
    }
    return topicCoordinate
}

Вызов функции generateRandomCoordinate

var randomCoordinate = generateRandomCoordinate(d, r)
x = randomCoordinate.x
y = randomCoordinate.y
r = randomCoordinate.r
}

console.log("ADDED POINT(x: " + x + ", y: " + y + ", r: " + r + ")")
var topicCoordinate = {
    "x": x,
    "y": y,
    "r": r
}
topicCoordinates.push(topicCoordinate)
drawCircle(x, y, r)

Вывод

введите описание изображения здесь

ОБНОВЛЕНИЕ Рабочий код

function generateRandomCoordinate(d, r) {
    var collision = true
    while (collision) {
        collision = false
        var phi = Math.random() * 2 * Math.PI
        var x = topicCoordinates[0].x + Math.round(d * Math.cos(phi))
        var y = topicCoordinates[0].y + Math.round(d * Math.sin(phi))
        for (var j = 0; j < topicCoordinates.length; j++) {
            var dx = x - topicCoordinates[j].x
            var dy = y - topicCoordinates[j].y
            var distance = Math.sqrt(dx * dx + dy * dy)

            if (distance < r + topicCoordinates[j].r) {
                collision = true
                console.log("COLLISION DETECTED BETWEEN POINT(" + "x: " + x + ", y: " + y + ") AND  POINT(x1: " + topicCoordinates[j].x + ", y1: " + topicCoordinates[j].y + ")")
            }
        }
    }

    var topicCoordinate = { "x" : x, "y" : y, "r" : r }
    return topicCoordinate
}

person Engo    schedule 29.10.2016    source источник


Ответы (1)


Нет необходимости в рекурсивном вызове функции. Просто организуйте цикл (псевдокод)

 repeat
     iscollision = false 
     generate x,y
     for other circles check
         if collision occurs
             iscollision = true
             break  //no need to check later circles    
 until iscollision = false

Что касается вашей рекурсивной путаницы - для каждого экземпляра функции уровня рекурсивного вызова есть собственные внутренние копии переменных, поэтому внешняя функция не знает о внутренних x, y - вы не возвращаете их в этом фрагменте кода:

  if (collision > 0) {
    vvvvvvvvvvvvvvvvvv
    generateRandomCoordinate(d, r)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
person MBo    schedule 29.10.2016
comment
Где мне восстановить мои новые координаты в случае столкновения? Моя цель - продолжать поиск новых бесконфликтных координат, пока не найду их ... - person Engo; 30.10.2016
comment
Как я уже писал - в началеrepeat цикла. Жизненная аналогия - бросить мяч в корзину. Если пропустили, попробуйте еще раз. - person MBo; 30.10.2016