2016-06-09 2 views
2

Я после двух массивов:логика Петля для рисования линии Javascript

var element_1 = new Array([x1,y1],[x2,y2],[x3,y3],[x4,y4]); 
var element_2 = new Array([x1,y1],[x2,y2],[x3,y3],[x4,y4]); 

Логика: Я хочу, чтобы запустить цикл (гнездовой), где каждый элемент element_1 (для например [x1,y1]) сравнивается с каждым элементом element_2 и кратчайшее расстояние между ними должно быть рассчитано в пределах цикла (я знаю, как рассчитать кратчайший путь). Трудная часть здесь заключается в том, что мне нужна ссылка на то, какая пара сделала кратчайшее, а затем получить те комбинации [x1,y1] и [x2,y2], чтобы нарисовать линию.

Образец данных:

var element_1 = new Array([10,0],[20,10],[10,20],[0,10]); 
var element_2 = new Array([10,30],[20,40],[10,50],[0,40]); 

линия должна быть между [10,20] и [10,30]. Кроме того, мне как-то нужно будет хранить координаты где-то, чтобы передать его функции линии рисования

Как это сделать? Любые выводы будут высоко оценены.

+0

Можете ли вы предоставить набор фактических координат и результат, который вы ожидаете? – blex

+0

Что такое '[y4, y4]' – Redu

+0

@blex координаты хранятся в массиве динамически onclick при щелчке элемента. пара 4 [x, y] - это координаты опорных точек прямоугольника (средние точки по высоте и ширине). Таким образом, 2 массива имеют якоря или 2 элемента. Цель состоит в том, чтобы таким образом найти кратчайшие соединительные якоря и их значения x, y, чтобы нарисовать линию между ними – Arihant

ответ

3

Вот как я бы это сделать:

var element_1 = [[0,0],[1,2],[5,3],[6,8]]; 
 
var element_2 = [[0,1],[1,4],[5,9],[9,8]]; 
 

 
var closest = {a: false, b: false, distance: false}; 
 

 
for(var i=0; i<element_1.length; i++) { 
 
    for(var j=0; j<element_2.length; j++) { 
 
    var distance = calculate_distance(element_1[i], element_2[j]); 
 
    console.log('Distance between element_1['+i+'] and element_2['+j+']: ' + distance); 
 
    if(closest.distance === false || distance < closest.distance) { 
 
     closest = {a: element_1[i], b: element_2[j], distance: distance}; 
 
    } 
 
    } 
 
} 
 

 
console.log('The shortest path is between '+closest.a+' and '+closest.b+', which is '+closest.distance); 
 

 
function calculate_distance(a, b) { 
 
    var width = Math.abs(a[0] - b[0]), 
 
     height = Math.abs(a[1] - b[1]), 
 
     hypothenuse = Math.sqrt(width*width + height*height); 
 
    return hypothenuse; 
 
}

Как Roko C. Buljan сказал, в вашем случае вы можете просто заменить new Array() с []. Here's why.

+3

Вы пропустили отличную возможность использовать 'Math.hypot';) –

+1

Wow ... Почему JavaScript всегда хранит от меня секреты? Может быть, я должен прочитать документы;) Спасибо, я буду использовать это! – blex

+0

NO! Не используйте его, ждите год ... или три. Это функция ES5. : D (IE ... помните?) –

1

Ну, мне очень понравился этот вопрос. Это вдохновило меня изобрести общий метод Array для применения обратного вызова друг к другу с элементами из двух массивов. Поэтому я назвал его Array.prototype.withEachOther(). То, что он делает, это именно то, что @blex сделал в своем решении с вложенными циклами. Он применяет операцию (предоставляемую обратным вызовом) к каждому элементу массива с элементом другого массива. Давайте посмотрим, как это работает.

Array.prototype.withEachOther = function(a,cb,s=0){ 
 
    return this.reduce((p,et) => a.reduce((q,ea) => cb(et,ea,q),p),s); 
 
}; 
 
var element_1 = [[10,0],[20,10],[10,20],[0,10]], 
 
    element_2 = [[10,30],[20,40],[10,50],[0,40]], 
 
      cb = (p1,p2,q) => {var h = Math.hypot(p1[0]-p2[0],p1[1]-p2[1]); 
 
           return h < q.d ? {d:h,p1:p1,p2:p2} : q}, 
 
     minDist = element_1.withEachOther(element_2,cb,{d:Number.MAX_SAFE_INTEGER,p1:[],p2:[]}); 
 
console.log(minDist);

Итак, давайте объяснить, что происходит.

Array.prototype.withEachOther = function(a,cb,s=0){ 
    return this.reduce((p,et) => a.reduce((q,ea) => cb(et,ea,q),p),s); 
}; 

является многоразовой функцией. Он выполнит операцию, которая предоставляется в функции обратного вызова, с каждым другим элементом из двух массивов. Требуется 3 аргумента (a,cb,s=0).

  • a является вторым массивом, который мы будем применять наш обратный вызов к каждому элементу для каждого элемента массива, который ссылающийся .withEachOther.
  • cb - это обратный вызов. Ниже я объясню обратный вызов, примененный для этой проблемы.
  • s=0 - начальное (со значением по умолчанию 0), с которого мы начнем. Это может быть все, что зависит от функции обратного вызова.

return this.reduce((p,et) => a.reduce((q,ea) => cb(et,ea,q),p),s);

эта часть является основной функции. Как видите, у него есть два вложенных сокращения.Внешнее сокращение имеет начальное значение, обозначенное s, которое предоставляется, как объяснено выше. Первоначальное значение сначала присваивается аргументу p обратного вызова внешнего сокращения, а другой аргумент et присваивается один за другим с каждым из элементов вызывающего массива. (e lement of t его). Во внешнем сокращении мы вызываем другое сокращение (внутреннее сокращение). Внутреннее сокращение начинается с начального значения результата предыдущего цикла, который является внешним уменьшением p, и после каждого вычисления возвращается результат к его уменьшенной переменной значения q. q является нашей памятью и проверен в обратном вызове, чтобы убедиться, что мы сохраним его как есть или заменим его результатом нашего расчета. После того, как внутреннее сокращение закончит полный раунд, он вернет q в p, и тот же механизм снова запустится, пока мы не закончим все элементы массива, вызывающие .withEachOther.

cb = (p1,p2,q) => {var h = Math.hypot(p1[0]-p2[0],p1[1]-p2[1]); 
        return h < q.d ? {d:h,p1:p1,p2:p2} : q} 

Обратный вызов является особенным для этой проблемы. Он получит две точки (каждая с координатами x и y). Будет вычислять расстояние между ними и будет сравнивать ее с ранее выполненным расчетом. Если он меньше, он заменит q, вернув это новое значение; если нет, он вернет q как есть.

Смежные вопросы