Algorithm 在两个矩形之间绘制不重叠的圆弧

Algorithm 在两个矩形之间绘制不重叠的圆弧,algorithm,math,svg,Algorithm,Math,Svg,我试图画一条连接两个矩形的(svg)弧。问题是,圆弧应该从矩形的边界开始,而不是从中心开始 举例说明: 我有矩形的中心点、宽度和高度C1 w1 h1 C2 w2 h2以及圆弧的中心和x、y半径D rx ry。所以基本上,对于绘制紫色弧,我缺少了P1和P2 所有值都是动态的,并且可以更改,因此算法需要不知道rx和ry、矩形的宽度和高度、矩形之间的相对位置等 考虑到圆角,顶部的樱桃将是最好的。但这并不是必须的。让椭圆的中心成为坐标原点(若不是,只需将矩形坐标移动-D.X和-D.Y) 在这个系统中,

我试图画一条连接两个矩形的(svg)弧。问题是,圆弧应该从矩形的边界开始,而不是从中心开始

举例说明:

我有矩形的中心点、宽度和高度
C1 w1 h1 C2 w2 h2
以及圆弧的中心和x、y半径
D rx ry
。所以基本上,对于绘制紫色弧,我缺少了
P1
P2

所有值都是动态的,并且可以更改,因此算法需要不知道
rx
ry
、矩形的宽度和高度、矩形之间的相对位置等


考虑到圆角,顶部的樱桃将是最好的。但这并不是必须的。

让椭圆的中心成为坐标原点(若不是,只需将矩形坐标移动-D.X和-D.Y)

在这个系统中,椭圆方程是

 x^2/rx^2 + y^2/ry^2 = 1
在这个等式中替换矩形边坐标,并检查结果是否真的属于矩形。
例如,顶部矩形的右边缘是
X=C1'.X+w1
。从椭圆方程中找出Y,并检查它是否在范围
C1'Y-h1。。C1'Y+h1
。如果是的话,
P1=(C1'.X+w1,CalculatedY)

好的,只为将来可能会偶然发现这一点的人准备

下面是我在javascript(ES6)中提出的内容。但将其移植到其他语言应该很容易

/**
 * Calculate the intersection of the border of the given rectangle
 * and a circular arc.
 * @param  {Object} rectangle    Rectangle object with dimensions and position properties.
 * @param  {Object} arc          Arc object with center and radius properties.
 * @return {Object}              Resulting intersection point, with x- and y-coordinates.
 */
calculateBorderPoint(rectangle, arc) {
  // Clone the rectangle, because we don't want to mutate the original.
  const a = Object.assign({}, rectangle.position);

  // Treat center of circle as coordinate origin.
  a.x -= arc.center.x;
  a.y -= arc.center.y;

  let points = [];

  // Check east & west with possible x values
  const possibleX = [
    a.x - rectangle.dimensions.width / 2,
    a.x + rectangle.dimensions.width / 2,
  ];
  possibleX.forEach((x) => {
    const ySquared = [
      Math.sqrt(Math.pow(arc.radius, 2) - Math.pow(x, 2)),
      -Math.sqrt(Math.pow(arc.radius, 2) - Math.pow(x, 2)),
    ];
    // Check if the derived y value is in range of rectangle
    ySquared.forEach((y) => {
      if (y >= a.y - rectangle.dimensions.height / 2 &&
          y <= a.y + rectangle.dimensions.height / 2) {
        points.push({x, y});
      }
    });
  });

  // Check north & south with possible y values
  const possibleY = [
    a.y - rectangle.dimensions.height / 2,
    a.y + rectangle.dimensions.height / 2,
  ];
  possibleY.forEach((y) => {
    const xSquared = [
      Math.sqrt(Math.pow(arc.radius, 2) - Math.pow(y, 2)),
      -Math.sqrt(Math.pow(arc.radius, 2) - Math.pow(y, 2)),
    ];
    // Check if the derived x value is in range of rectangle
    xSquared.forEach((x) => {
      if (x >= a.x - rectangle.dimensions.width / 2 &&
          x <= a.x + rectangle.dimensions.width / 2) {
        points.push({x, y});
      }
    });
  });

  // At this point you will propably have multiple possible solutions,
  // because the circle might intersect the rectangle at multiple points.
  // You need to select the point, that makes most sense in your case.
  // One solution would be to select the one closest to the other rectangle.

  // Translate it back.
  points[0].x += arc.center.x;
  points[0].y += arc.center.y;

  return points[0];
}
/**
*计算给定矩形边界的交点
*和一个圆弧。
*@param{Object}具有维度和位置属性的矩形对象。
*@param{Object}具有中心和半径属性的圆弧对象。
*@return{Object}结果交点,x坐标和y坐标。
*/
calculateBorderPoint(矩形、圆弧){
//克隆矩形,因为我们不想改变原始矩形。
const a=Object.assign({},rectangle.position);
//将圆心视为坐标原点。
a、 x-=弧心x;
a、 y-=弧中心y;
设点=[];
//使用可能的x值检查东和西
可能常数=[
a、 x-矩形。尺寸。宽度/2,
a、 x+矩形。尺寸。宽度/2,
];
可能的forEach((x)=>{
常数Y平方=[
sqrt(Math.pow(弧半径,2)-Math.pow(x,2)),
-sqrt(Math.pow(弧半径,2)-Math.pow(x,2)),
];
//检查导出的y值是否在矩形范围内
ySquared.forEach((y)=>{
如果(y>=a.y-矩形.尺寸.高度/2&&
y{
常数x平方=[
sqrt(Math.pow(弧半径,2)-Math.pow(y,2)),
-sqrt(Math.pow(弧半径,2)-Math.pow(y,2)),
];
//检查导出的x值是否在矩形范围内
xSquared.forEach((x)=>{
如果(x>=a.x-矩形.dimensions.width/2&&

x你总是想画较短的弧吗?你如何决定你画的两个弧中的哪一个?此外,C1和C2总是位于弧上,还是这只是巧合?@WillemVanOnsem我从第三个点
P3
,而不是在图片中绘制的点导出弧。
P3
用于编辑弧。是的,弧总是会继续通过圆心点
C1
C2
。你为什么不采取简单的方法,在从C1到C2的弧顶上绘制不透明的矩形?@PaulLeBeau是的,我正在附加箭头(和其他附加信息)在arc的开始/结束。谢谢!这个想法实际上比我预期的要简单得多。我会检查一下,看看我想出了什么。如果效果好,我会把你的答案标记为接受。