从点到圆角矩形或椭圆的最长距离
longest distance from point to rounded rectangle or ellipse
如何找到从形状内部的点到其边界的最长距离。
我特别想为这些情况寻找距离:
示例 3(没有圆角的右侧)将是右下角,但如何计算其他 2 个?
我正在寻找 JavaScript 解决方案,但我也对基本的逻辑解释感到满意。
这是我用来获得最远角的脚本:
// the bounding box
var bound = document.getElementById('bound')
var radius = parseInt(getComputedStyle(bound).borderRadius, 10);
// listen to events
bound.addEventListener('mousedown', getFarthest)
/**
* get the fartest point from click to border
**/
function getFarthest(event) {
// get event coordinates
var y = event.layerY;
var x = event.layerX;
// get event dimensions
var w = event.target.offsetWidth;
var h = event.target.offsetHeight;
// get offset
var offsetX = Math.abs(w / 2 - x);
var offsetY = Math.abs(h / 2 - y);
// get delta
var deltaX = w / 2 + offsetX;
var deltaY = h / 2 + offsetY;
// calculate size
var size = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2) - 2 * deltaX * deltaY * Math.cos(90 / 180 * Math.PI));
event.target.innerText = Math.round(size);
}
基本逻辑解释:
您正在寻找形状上的点 X,X 处的切线垂直于红点 P。
矩形是一种特殊情况,因为角没有明确定义的切线。但是你已经处理过那个案子了。
至于椭圆和圆角,我假设你知道如何计算切线(如果不会,Google它)。找到给定点 X=(x,y) 处的切线表达式,以及从 P 到 X 的直线的表达式。当它们垂直时(它们方向的点积为零),你就有了一个候选。计算所有这些候选点,然后找出哪个离P最远。
在 html 中,radius 在角上创建了 4 个圆。我很确定无论你点击哪里,最远的点总是在一个角上,因为到最远点的线与边缘成 90 度角。最远的点也总是在相反的象限中。请注意,在html中,半径不能大于width/2
和height/2
。因此不可能制作出真正的椭圆。
因为直线总是和边成90度角,我们知道直线应该穿过圆的中间。每隔一条线都不能与圆的边缘成 90 度角。要计算距离,我们只需要在我们点击的点和圆的中间之间做毕达哥拉斯。圆心到圆边的距离是已知的,因为那是半径。
密码
// listen to events
bound.addEventListener('mousedown', getFarthest)
/**
* get the fartest point from click to border
**/
function getFarthest(event) {
//In IE the computed border radius is an empty string, causing parseInt to make it NaN.
var radius = parseInt(window.getComputedStyle(event.target).borderRadius, 10);
if( radius === NaN ) {
event.target.innerText = "ERROR";
console.error( "Computed radius is not a number in this browser." );
return;
}
// get event coordinates
var x = event.offsetX;
var y = event.offsetY;
//get the width and height of the element
var rect = event.target.getBoundingClientRect();
//We know that the furthest point is in the opposite quarter, on the rounded bit
//The greatest distance is the point where the line to the edge has a 90 degrees corner
//with the edge. This only happens if the line goes through the center of the circle
//the distance between the center of a circle and it's edge is... the radius.
//the distance between the center of a circle and a point is simple pythagoras.
//Thus, we don't need to know where it intersects to find the distance.
var circleX;
var circleY;
//Find the middle point of the circle
if( x < (rect.width / 2) ) {
circleX = rect.width - radius;
} else {
circleX = radius;
}
if( y < (rect.height / 2) ) {
circleY = rect.height - radius;
} else {
circleY = radius;
}
var pythagoras = Math.sqrt( Math.pow( circleX - x, 2 ) + Math.pow( circleY - y, 2 ) );
var distance = pythagoras + radius;
//Put it in a suitable place
event.target.innerText = Math.round( distance );
}
body {
margin: 50px;
font-family: sans-serif;
background: #424242;
overflow: hidden;
}
.wire {
display: block;
width: 10em;
height: 20em;
box-shadow: 0 0 0 2px;
font-size: 20px;
line-height: 20em;
margin: -10em -5em;
position: absolute;
top: 50%;
left: 50%;
user-select: none;
text-align: center;
border: 0;
border-radius: 0em;
background: white;
}
.tracker {
background: red;
pointer-events:none;
}
<span id="bound" class="wire">Area</span>
有点证明
此图像显示角始终比形状的边更远。 r
是半径。 a
、b
和 c
是毕达哥拉斯中使用的术语。 c
将始终大于 a
或 b
,因此 c + r
将始终大于 a + r
或 b + r
。
此图显示了为什么割线总是更短。 A线是最长的线。 B线是割线。蓝色条纹圆圈的中间点是 A 线和 B 线的起点,并经过 B 线与我们的圆相交的点。蓝色条纹圆圈上的所有点与直线 A 和 B 的起点的距离相同。正如您可以清楚地看到,线 A 更长,因为它穿过蓝色圆圈。如果要创建一个圆,中间点为 A 和 B 的起点,半径为 A 与圆的相交处,则除了 A 与圆相交的地方外,它不会与我们的形状相交。
如何找到从形状内部的点到其边界的最长距离。
我特别想为这些情况寻找距离:
示例 3(没有圆角的右侧)将是右下角,但如何计算其他 2 个?
我正在寻找 JavaScript 解决方案,但我也对基本的逻辑解释感到满意。
这是我用来获得最远角的脚本:
// the bounding box
var bound = document.getElementById('bound')
var radius = parseInt(getComputedStyle(bound).borderRadius, 10);
// listen to events
bound.addEventListener('mousedown', getFarthest)
/**
* get the fartest point from click to border
**/
function getFarthest(event) {
// get event coordinates
var y = event.layerY;
var x = event.layerX;
// get event dimensions
var w = event.target.offsetWidth;
var h = event.target.offsetHeight;
// get offset
var offsetX = Math.abs(w / 2 - x);
var offsetY = Math.abs(h / 2 - y);
// get delta
var deltaX = w / 2 + offsetX;
var deltaY = h / 2 + offsetY;
// calculate size
var size = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2) - 2 * deltaX * deltaY * Math.cos(90 / 180 * Math.PI));
event.target.innerText = Math.round(size);
}
基本逻辑解释:
您正在寻找形状上的点 X,X 处的切线垂直于红点 P。
矩形是一种特殊情况,因为角没有明确定义的切线。但是你已经处理过那个案子了。
至于椭圆和圆角,我假设你知道如何计算切线(如果不会,Google它)。找到给定点 X=(x,y) 处的切线表达式,以及从 P 到 X 的直线的表达式。当它们垂直时(它们方向的点积为零),你就有了一个候选。计算所有这些候选点,然后找出哪个离P最远。
在 html 中,radius 在角上创建了 4 个圆。我很确定无论你点击哪里,最远的点总是在一个角上,因为到最远点的线与边缘成 90 度角。最远的点也总是在相反的象限中。请注意,在html中,半径不能大于width/2
和height/2
。因此不可能制作出真正的椭圆。
因为直线总是和边成90度角,我们知道直线应该穿过圆的中间。每隔一条线都不能与圆的边缘成 90 度角。要计算距离,我们只需要在我们点击的点和圆的中间之间做毕达哥拉斯。圆心到圆边的距离是已知的,因为那是半径。
密码
// listen to events
bound.addEventListener('mousedown', getFarthest)
/**
* get the fartest point from click to border
**/
function getFarthest(event) {
//In IE the computed border radius is an empty string, causing parseInt to make it NaN.
var radius = parseInt(window.getComputedStyle(event.target).borderRadius, 10);
if( radius === NaN ) {
event.target.innerText = "ERROR";
console.error( "Computed radius is not a number in this browser." );
return;
}
// get event coordinates
var x = event.offsetX;
var y = event.offsetY;
//get the width and height of the element
var rect = event.target.getBoundingClientRect();
//We know that the furthest point is in the opposite quarter, on the rounded bit
//The greatest distance is the point where the line to the edge has a 90 degrees corner
//with the edge. This only happens if the line goes through the center of the circle
//the distance between the center of a circle and it's edge is... the radius.
//the distance between the center of a circle and a point is simple pythagoras.
//Thus, we don't need to know where it intersects to find the distance.
var circleX;
var circleY;
//Find the middle point of the circle
if( x < (rect.width / 2) ) {
circleX = rect.width - radius;
} else {
circleX = radius;
}
if( y < (rect.height / 2) ) {
circleY = rect.height - radius;
} else {
circleY = radius;
}
var pythagoras = Math.sqrt( Math.pow( circleX - x, 2 ) + Math.pow( circleY - y, 2 ) );
var distance = pythagoras + radius;
//Put it in a suitable place
event.target.innerText = Math.round( distance );
}
body {
margin: 50px;
font-family: sans-serif;
background: #424242;
overflow: hidden;
}
.wire {
display: block;
width: 10em;
height: 20em;
box-shadow: 0 0 0 2px;
font-size: 20px;
line-height: 20em;
margin: -10em -5em;
position: absolute;
top: 50%;
left: 50%;
user-select: none;
text-align: center;
border: 0;
border-radius: 0em;
background: white;
}
.tracker {
background: red;
pointer-events:none;
}
<span id="bound" class="wire">Area</span>
有点证明
r
是半径。 a
、b
和 c
是毕达哥拉斯中使用的术语。 c
将始终大于 a
或 b
,因此 c + r
将始终大于 a + r
或 b + r
。