Динамическое вычисление местоположения точек после преобразования вращения - PullRequest
0 голосов
/ 25 мая 2020

Вопрос : Как следует реализовать 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>
...