2014-01-03 2 views
1

Учитывая ограниченный квадрат и общее количество меньших квадратов. Меньшие квадраты должны быть нарисованы внутри большего квадрата, равномерно распределенного круговым способом, только касаясь, но не перекрываясь. Как вы вычисляете ширину внутреннего квадрата?Круговая макет меньших квадратов в большом квадрате

(обновлено ссылка скрипки) http://jsfiddle.net/mdluffy/6bUVz/3/

///////// INPUTS /////////////////////////////////////////// 
var BoundingBoxSide = 100; 
var NofInnerBoxes = 14; 
    //////////////////////////////////////////////////////////// 
drawBoxes(); 

function drawBoxes() 
{ 
var c=document.getElementById("myCanvas"); 
var ctx=c.getContext("2d"); 
ctx.rect(0,0,BoundingBoxSide,BoundingBoxSide); 
ctx.stroke(); 

for(var i=0; i < NofInnerBoxes; i++) 
{ 
    // ************************************************************************************ // 
    // This needs to be computed so that the boxes touch each other, but not overlap 
    var innerBoxSide = 20; 
    // ************************************************************************************ // 
    var angle = degToRad(i * 360/NofInnerBoxes); 
    var innerX = ((BoundingBoxSide - innerBoxSide)/2) * Math.cos(angle); 
    var innerY = ((BoundingBoxSide - innerBoxSide)/2) * Math.sin(angle); 
    ctx.rect(BoundingBoxSide/2 + innerX - innerBoxSide/2, BoundingBoxSide/2 - innerY - innerBoxSide/2, innerBoxSide, innerBoxSide); 

    ctx.stroke(); 

} 
} 

function degToRad(d) 
{ 
    return d * Math.PI/180; 
} 

Update:

Я работаю на 3D визуализации с использованием three.js. Это древовидная структура с узлами, представленными в виде кубов. Кубы дочерних узлов выложены круговыми вершинами кубов родительского узла. Рекурсивно применяется.

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

+1

Ваша ссылка на скрипку пуста. Это для оптимизации упаковки? – K3N

+0

Вы показали, какой код вы пробовали; что он делает и как это отличается от того, что вы хотите? – LarsH

+0

Уточняющий вопрос: должны ли внутренние квадраты касаться внешнего квадрата на всех четырех сторонах? Я так не думаю ... потому что такой плотный прямоугольник часто не был бы квадратным. – LarsH

ответ

1

Вот моя попытка:

var alpha = Math.PI * (NofInnerBoxes - 2)/(2 * NofInnerBoxes) 
var t = Math.tan(alpha) 
var innerBoxSide = BoundingBoxSide/Math.sqrt(t*t + 4*t + 5) 

(Кредит: до WolframAlpha решения для innerBoxSide, и конверт я doodled на спине.)

Update: выше была под что две стороны каждого внутреннего квадрата параллельны прямой, проходящей через центры этого внутреннего квадрата и внешнего квадрата. Теперь я вижу, что это предположение было не тем, что вы имели в виду.

Вот еще один подход. В этом, круги, описывающим внутренние квадраты будут все касаются друг друга, хотя сами по себе внутренние квадраты не совсем соприкасаются друг с другом:

var alpha = Math.PI/NofInnerBoxes 
var t = Math.sin(alpha) 
var innerBoxSide = BoundingBoxSide * t/((t + 1) * Math.sqrt(2)) 

Результат:

enter image description here

Выведение

В ответ на запрос о том, как была получена формула ...

Да r_s (r sub s) - «малый радиус», то есть радиус окружностей, которые описывают внутренние квадраты. Эти внутренние круги касаются большого круга, который в книжники на внешней площади. Назовите радиус большого круга r_b (b для «большого»).

Обратите внимание, что сторона внешнего квадрата, a.k.a. BoundingBoxSide, is = 2 * r_b. Отметим также, что диаметр каждой внутренней окружности 2 * r_s также является диагональю каждого внутреннего квадрата. Поэтому сторона каждого внутреннего квадрата, a.k.a. innerBoxSide, равна = (2 * r_s)/sqrt (2).

Теперь позвольте углу alpha = половина угла, который каждый внутренний круг подставляет (если это правильный глагол) вокруг центра большого круга. То есть alpha = (2 * pi/NofInnerBoxes)/2 = pi/NofInnerBoxes.

Ключ состоит в том, чтобы нарисовать правый треугольник, где один из углов - альфа; это скажет нам соотношения между всеми сторонами этого треугольника, используя триггерные функции, такие как sin(). И мы можем сделать такой треугольник, вершинами которого являются:

A. The center of the big circle 
B. The center of a small circle 
C. The point where that small circle touches its neighbor 

Правый угол при вершине С, а угол альфа в вершине A. Длина стороне BC = R_s, а длина гипотенузы (AB) = r_b - r_s.

Таким образом, по определению sin() можно сказать, что sin (альфа) = противоположная сторона/гипотенуза = BC/AB = r_s/(r_b - r_s). Решите это уравнение для r_s, и получим r_s = r_b * sin (alpha)/(1 + sin (alpha)).

Наконец, включите факт (выше), что BoundingBoxSide = 2 * r_b и innerBoxSide = (2 * r_s)/sqrt (2); и вы получите приведенную выше формулу, innerBoxSide = BoundingBoxSide * t/((t + 1) * Math.sqrt(2)).

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

+0

@OP: Хм ... теперь, когда вы обновили свою ссылку на скрипку, я вижу, что вы хотите, чтобы все внутренние ящики были ориентированы одинаково. Я представлял, что внутренние коробки вращаются вокруг краев круга. Поэтому, если вышеуказанный ответ неприемлем для вашей цели, дайте мне знать. Это кажется сложнее, чем вопрос, который вы задавали. – LarsH

+0

@OP: Я только что опубликовал обновление. Меня устраивает. Посмотрите, что вы думаете. – LarsH

+0

благодарит LarsH. Я бы очень признателен, если бы вы объяснили, как вы пришли к уравнению. –

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