2017-01-16 8 views
0

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

enter image description here

Параметры оба радиуса окружности, х - центры, а у - центры. Функция создания строки - line(x1, y1, x2, y2).

Вот что я теперь использую JavaScript.

var lineX1 = circleX1 + (circleRadius1 * Math.sin(Math.atan2(circleY2 - circleY1, circleX2 - circleX1))); 
var lineY1 = circleY1 + (circleRadius1 * Math.cos(Math.atan2(circleY2 - circleY1, circleX2 - circleX1))); 
var lineX2 = circleX2 - (circleRadius2 * Math.sin(Math.atan2(circleY1 - circleY2, circleX1 - circleX2))); 
var lineY2 = circleY2 - (circleRadius2 * Math.cos(Math.atan2(circleY1 - circleY2, circleX1 - circleX2))); 

line(lineX1, lineY1, lineX2, lineY2); 

Но это выглядит так.

enter image description here

+1

Вы звоните 'Math.atan()' (то есть, один-параметр метода), но собираясь вызвать 'Math.atan2()' (т.е. два-параметра метода)? – Welbog

+0

Это была опечатка, я тоже использовал 'Math.atan2()'. Сожалею! – notalentgeek

ответ

2

Вы почти правильно. Как отметил @welbog, вы хотите использовать Math.atan2. Кроме того, вы заменили свой cos и sin для x/y. Наконец, вам нужно только вычислить угол один раз.

Вот демонстрация:

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script> 
 
</head> 
 

 
<body> 
 
    <script> 
 
    var svg = d3.select('body') 
 
     .append('svg') 
 
     .attr('width', 500) 
 
     .attr('height', 500); 
 
     
 
    draw(); 
 

 
    function draw() { 
 
     
 
     svg.selectAll("*").remove(); 
 

 
     var circleRadius1 = Math.random() * 100, 
 
     circleRadius2 = Math.random() * 100, 
 
     circleX1 = Math.random() * 500, 
 
     circleY1 = Math.random() * 500, 
 
     circleX2 = Math.random() * 500, 
 
     circleY2 = Math.random() * 500; 
 
     
 
     svg.append('circle') 
 
     .attr('r', circleRadius1) 
 
     .attr('cx', circleX1) 
 
     .attr('cy', circleY1) 
 
     .style('fill', 'none') 
 
     .style('stroke', 'steelblue'); 
 
     
 
     svg.append('circle') 
 
     .attr('r', circleRadius2) 
 
     .attr('cx', circleX2) 
 
     .attr('cy', circleY2) 
 
     .style('fill', 'none') 
 
     .style('stroke', 'orange'); 
 
     
 
     var angle = Math.atan2(circleY2 - circleY1, circleX2 - circleX1), 
 
      lineX1 = circleX1 + (circleRadius1 * Math.cos(angle)), 
 
      lineY1 = circleY1 + (circleRadius1 * Math.sin(angle)), 
 
      lineX2 = circleX2 - (circleRadius2 * Math.cos(angle)), 
 
      lineY2 = circleY2 - (circleRadius2 * Math.sin(angle)); 
 
      
 
     svg.append('line') 
 
     .attr('x1', lineX1) 
 
     .attr('y1', lineY1) 
 
     .attr('x2', lineX2) 
 
     .attr('y2', lineY2) 
 
     .style('stroke','black') 
 
     
 
     setTimeout(draw, 1000); 
 

 
    } 
 
    </script> 
 
</body> 
 

 
</html>

+0

Oooh. Хорошо, проблема была на самом деле потому, что я перевернул соз и грех. 'Math.atan()' был типом, так как я использовал 'Math.atan2()' также. В общем, спасибо за ваш ответ! – notalentgeek

3

Там нет необходимости в тригонометрические функции.

center difference vector 
dx = cx2 - cx1 
dy = cy2 - cy1 
len = Math.Sqrt(dx*dx + dy*dy) 
normalized 
udx = dx/len 
udy = dy/len 

line ends 
lx1 = cx1 + udx * r1 
ly1 = cy1 + udy * r1 
lx2 = cx2 - udx * r2 
ly2 = cy2 - udy * r2 
+0

Упрощенный, но в JavaScript нет 'Math.Sqrt()'. Это 'math.sqrt()'. –

+0

Я не знаю таких особенностей JavaScript, поэтому дал своего рода псевдокод. – MBo