Вопрос : Как следует реализовать Dynami c Тригонометрию для древовидного графа c генератор генератора в Javascript, чтобы «ветви» отображались в правильном положении с учетом их вращения?
Цель этого кода - процедурно сгенерировать что-то похожее на дерево.
Он использует рекурсивную функцию под названием addTreeBranch. Каждая итерация проверяет ширину предыдущей ветки, затем вызывает еще две функции для еще двух ветвей с шириной, разделенной между ними в диапазоне 60-40 или около того. Каждая ветвь вращается в небольшом диапазоне, что отрицательно, если ветвь является левой. Рекурсии продолжаются до тех пор, пока доступная ширина не станет 1.
Проблема :
Basi c тригонометрия для того, кто не лучший в пространственной математике. Кроме того, система координат для java сбивает меня с толку.
Проблема состоит в том, чтобы правильно выстраивать каждую новую ветку с каждой старой веткой. Каждая новая ветвь смещается неправильно.
Javascript / CSS вращается вокруг начала координат. Значения «left» и «top», соответствующие X и Y, не меняются при повороте ветви. Для новой ветки мне нужно посмотреть на верхнюю, левую и поворотную часть старой ветки и вычислить, где должна располагаться новая ветка, чтобы ее нижняя часть совпадала с верхом предыдущей ветки.
это, я думаю, мне нужно сделать немного тригонометрии. Я считаю, что формула поворота точки выглядит примерно так: x1 = x cos (угол) - y sin (угол) y2 = x sin (угол) + y cos (угол )
Однако я просто не могу понять, как применить эту формулу к системе координат javascript. Если бы я мог вычислить, каковы реальные угловые точки для повернутого div, я мог бы использовать их для позиционирования следующего div. Я знаю точку начала вращения (центр div), и я включил ее в систему точек отладки здесь.
Моя основная проблема в том, что я не могу понять, как работать из системы координат начала координат в верхнем левом углу javascripts.
Рассматриваемый код :
//x and y are values extrapolated from the last branch i.e oldX oldY
if(rightOrLeft == 'left') {
var newx = x - 0.5 * oldWidth;
branch.style.left = newx + "px";
}
else {
var newx = (x+ 0.5 * oldWidth);
branch.style.left = newx + "px";
}
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tree</title>
<style>
body {
font-family: Courier, monospace;
text-align: center;
}
</style>
<script>
var woodcolor = "#966F33";
var treeParts = [];
var coords = [];
function build() {
console.time('Clear timer');
//remove old tree, if extant
for (i = 0; i < treeParts.length; i++) {
treeParts[i].parentNode.removeChild(treeParts[i]);
}
treeParts = [];
clearCoords();
console.timeEnd('Clear timer');
console.time('Tree creation timer');
//create a starting branch with these values
let branch = document.createElement('div');
var x = 100;
var y = 516;
var h = 284;
var w = 75;
branch.style.top = y + "px";
branch.style.left = x + "px";
branch.style.height = h + "px";
branch.style.width = w + "px";
branch.setAttribute('class', 'tree-branch');
branch.style.backgroundColor = woodcolor;
branch.style.position = "absolute";
branch.style.display = "block";
//these random vals will determine how each side is divided
var rwidth = getRndInteger(40, 60) / 100;
var rheight = getRndInteger(50, 70) / 100;
//add to the tree parts container
document.getElementById('tree-container').appendChild(branch);
//add to treeparts array for deletion later as needed
treeParts.push(branch);
//create a new branch recursively
//left first
addTreeBranch(branch, rwidth, rheight, 'left');
//right next
addTreeBranch(branch, 1 - rwidth, getRndInteger(50, 70) / 100, 'right');
console.timeEnd('Tree creation timer');
//debug branch print
//printBranch(branch);
}
function getRndInteger(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function addTreeBranch(oldBranch, widthPercent, heightPercent, rightOrLeft) {
var x = parseInt(oldBranch.style.left, 10);
var y = parseInt(oldBranch.style.top, 10);
var oldHeight = parseInt(oldBranch.style.height);
var h = parseInt(oldHeight, 10) * heightPercent;
//get the width of the passing branch - if it is less than 1, time to return and end the recursive call
var oldWidth = parseInt(oldBranch.style.width, 10);
if (oldWidth <= 1) {
return;
}
var w = parseInt(oldWidth, 10) * widthPercent;
var rwidth = getRndInteger(40, 60) / 100;
var rheight = getRndInteger(40, 60) / 100;
var branch = document.createElement('div');
branch.style.top = (y - h) + 10 + "px";
branch.style.height = h + "px";
branch.style.width = w + "px";
branch.setAttribute('class', 'tree-branch');
branch.style.backgroundColor = woodcolor;
branch.style.position = "absolute";
branch.style.display = "block";
//rotate left or right
var rot = getRndInteger(15, 27);
if (rightOrLeft == 'left') {
rot *= -1;
}
var oldRot = getRotation(oldBranch.style.transform);
rot += oldRot;
var transtring = "rotate(" + rot + "deg)";
branch.style.transform += transtring;
//console.log("angle is " + rot + ", oldheight is " + oldHeight);
//change X to line up appropriately with branch
if (rightOrLeft == 'left') {
var newx = x - 0.5 * oldWidth;
branch.style.left = newx + "px";
} else {
var newx = (x + 0.5 * oldWidth);
branch.style.left = newx + "px";
}
//left first
addTreeBranch(branch, rwidth, rheight, 'left');
//right next
addTreeBranch(branch, 1 - rwidth, getRndInteger(50, 70) / 100, 'right');
document.getElementById('tree-container').appendChild(branch);
treeParts.push(branch);
//debug
if (document.getElementById("debug1").checked != false) {
printBranchCoords(branch);
}
}
function getRotation(transfrm) {
var start = transfrm.indexOf("rotate(");
var end = transfrm.indexOf("deg");
var newString = transfrm.substring(start + 1, end + 1);
if (newString == null || !parseInt(newString)) {
return 0;
} else {
return parseInt(newString);
}
}
function printBranch(branch) {
var y = branch.style.y;
var x = branch.style.x;
var h = branch.style.height;
var w = branch.style.width;
console.table(x, y, h, w);
}
function printBranchCoords(branch) {
var originColor = "#239bad";
var mpColor = "#e8dbda";
var centColor = "#f00c0c";
var rotPointColor = "#dbd0af";
var width = parseInt(branch.style.width);
var height = parseInt(branch.style.height);
var x = [4];
var y = [4];
var rot = getRotation(branch.style.transform);
x[0] = parseInt(branch.style.left);
y[0] = parseInt(branch.style.top);
printCoord(x[0], y[0], "t-lft", originColor);
x[1] = x[0] + width;
y[1] = y[0];
printCoord(x[1], y[1], "t-rt", originColor);
x[2] = x[1];
y[2] = y[1] + height;
printCoord(x[2], y[2], "b-rt", originColor);
x[3] = x[2] - width;
y[3] = y[2];
printCoord(x[3], y[3], "b-lft", originColor);
cx = x[0] + width * .5;
cy = y[0] + height * .5;
var hypo = Math.sqrt(Math.pow((cx - x[0]), 2) + Math.pow((y[0] - cy), 2));
printCoord(cx, cy, "hypot" + Math.round(hypo, 2), centColor);
}
function printCoord(x = [], y = [], text, color) {
//console.log('coord:',x,y);
var coord = document.createElement('div');
coord.style.top = y + "px";
coord.style.left = x + "px";
coord.style.width = "10px";
coord.style.height = "10px";
coord.style.backgroundColor = color;
coord.setAttribute('class', 'tree-branch');
coord.style.position = "absolute";
coord.style.opacity = "0.6";
coord.style.x = x + "px";
coord.style.y = y + "px";
coord.style.borderStyle = "dashed";
coord.style.borderRight = "0px";
coord.style.borderBottom = "0px";
coord.style.fontSize = "4px";
coord.innerHTML = "({" + Math.round(x, 2) + "," + Math.round(y, 2) + ") " + text;
document.getElementById('tree-container').appendChild(coord);
coords.push(coord);
}
function clearCoords() {
for (i = 0; i < coords.length; i++) {
coords[i].parentNode.removeChild(coords[i]);
}
coords = [];
}
</script>
</head>
<body>
<button type="button" onclick="build()">Build</button>
<button type="button" onclick="clearCoords()">Clear Debug Coords</button>
<input type="checkbox" id="debug1" value="debugCheck">
<label for="debug1" class="debug-label">Build Coord markers</label>
<div id="tree-container"></div>
</body>
</html>