在任何给定的 space 处,如何使最短的线接触两个圆圈?
How can you make shortest line touching two circles at any given space?
这是我想要实现的目标。
参数均为圆半径、x - 圆心和 y - 圆心。做线的函数是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);
但是看起来像这样。
你几乎是正确的。正如@welbog 指出的那样,您想使用 Math.atan2。此外,您将 cos 和 sin 换成了 x/y。最后,你只需要计算一次角度。
这是一个演示:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@4.0.0" 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>
三角函数不需要。
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
这是我想要实现的目标。
参数均为圆半径、x - 圆心和 y - 圆心。做线的函数是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);
但是看起来像这样。
你几乎是正确的。正如@welbog 指出的那样,您想使用 Math.atan2。此外,您将 cos 和 sin 换成了 x/y。最后,你只需要计算一次角度。
这是一个演示:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@4.0.0" 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>
三角函数不需要。
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