从点到圆角矩形或椭圆的最长距离

时间:2015-08-21 16:28:16

标签: javascript trigonometry

如何找到从形状内的点到其边界的最长距离。

我特别想找到这些案件的距离:

示例3(右边没有圆角)将是右下角但是如何计算其他2?

enter image description here

我正在寻找一个JavaScript解决方案,但我也对基本的逻辑解释感到满意。

这是我用来获得最远角落的脚本:

Codepen example

// 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);
}

2 个答案:

答案 0 :(得分:4)

基本逻辑解释:

你正在寻找X上的切线垂直于红点P的形状上的点X.

矩形是一种特殊情况,因为角落没有明确定义的切线。但你已经处理了这个案子。

至于椭圆和圆角,我假设您知道如何计算切线(如果没有,谷歌它)。找到给定点X =(x,y)处的切线的表达式,以及从P到X的线的表达式。当这些是垂直的(它们的方向的点积为零)时,您有一个候选者。计算所有这些候选点,然后找出哪一个距离P最远。

答案 1 :(得分:3)

在html中,radius在角落中创建4个圆圈。我很确定无论你在哪里点击,最远点总是位于其中一个角落,因为最远点的线与边缘有90度角。最远点也总是在相反的象限。请注意,在html中,半径不能大于width/2height/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>

有点证明

Corners are always further away 此图像显示角落总是比形状的侧面更远。 r是半径。 abc是毕达哥拉斯中使用的术语。 c将始终大于ab,因此c + r将始终大于a + rb + r

Tangent and secants 此图显示了为什么割线总是更短。 A线是最长的线。 B行是割线。蓝色条纹圆具有中间点,其中线A和B开始,并且穿过线B与我们的圆相交的点。蓝色条纹圆上的所有点与A线和B线开始的距离相同。你可以清楚地看到,A线更长,因为它穿过蓝色圆圈。如果要创建一个中间点,其中A和B开始的圆,以及A与圆相交的半径,除了A与圆相交的地方之外,它将不会与我们的形状相交。