倒圆半径计算

时间:2015-05-23 18:45:34

标签: javascript geometry

我想计算倒圆的半径。

我设法实现了一切,但经过几个小时的挣扎后,我找不到计算正确反转半径的公式。

有关圆形反转的详细信息:

到目前为止我的代码:http://codepen.io/rafaelcastrocouto/pen/Mwjdga

它似乎有效,但你可以很容易地说它是完全错误的。

var c = $('#c'),
    b = $('body'),
    canvas = c[0],
    ctx = canvas.getContext('2d'),
    pi = Math.PI,
    r = 100,
    mr = 30,
    width, height, hw, hh;
var setup = function() {
  width = b.width();
  height = b.height();
  hw = width/2;
  hh = height/2;
  canvas.width = width;
  canvas.height = height;
  mid();
};
var mid = function() {
  circle(hw,hh,0.25);
  circle(hw,hh,r);
}
var circle = function(x,y,r) {
  ctx.beginPath();
  ctx.arc(x,y,r,0,pi*2);
  ctx.stroke();
  ctx.closePath();
};
var move = function(evt) {
  var x = evt.clientX,
      y = evt.clientY;
  ctx.clearRect(0,0,width,height);
  mid();
  circle(x,y,mr);
  var dx = x-hw,
      dy = y-hh,
      d = dist(dx,dy),
      nd = r*r/d,
      nx = dx*nd/d,
      ny = dy*nd/d,
      nr = mr*mr*pi/d; // whats the correct formula?
  console.log(nr);
  circle(nx+hw, ny+hh, nr);
};
var dist = function(x,y) {
  return Math.pow(x*x + y*y, 1/2);
};
$(setup);
$(window).resize(setup);
$(window).mousemove(move);

需要数学专家的帮助!

2 个答案:

答案 0 :(得分:1)

正如您所说,倒转一个圆的中心不会给您另一个圆的中心。同样,如果我们反转一个圆的两个相反的点,这并不意味着它们将成为反转圆上的相对点。 由于三个点描述了一个唯一的圆,我们可以使用它们找到反圆的方程。这给了我们倒圆的中心。然后,我们可以找到从中心到倒立点之一的距离,即半径。

以下c ++代码给出了中心。 (我不懂javascript)。函数v.norm2()给出向量v的平方范数。

Vector2D getcircle(Vector2D p1, Vector2D p2, Vector2D p3){
    Vector2D result;
    long double div = 2*(p1.x*(p2.y-p3.y)-p1.y*(p2.x-p3.x)+p2.x*p3.y-p3.x*p2.y);
    result.x = (p1.norm2()*(p2.y-p3.y)+p2.norm2()*(p3.y-p1.y)+p3.norm2()*(p1.y-p2.y))/div;
    result.y = (p1.norm2()*(p3.x-p2.x)+p2.norm2()*(p1.x-p3.x)+p3.norm2()*(p2.x-p1.x))/div;
    return result;
}

因此,如果您有一个半径为r的圆c,并且正对另一个半径为R的圆C求逆,则可以执行类似的操作

float getRadius(Vector2D C, float R, Vector2D c, float r){
    Vector2D p1 = Vector2D(c.x + r, c.y).invert(C, R);
    Vector2D p2 = Vector2D(c.x - r, c.y).invert(C, R);
    Vector2D p3 = Vector2D(c.x, c.y + r).invert(C, R);
    return (getcircle(p1, p2, p3) - p1).norm();
}

这是一个以中心(130,-130)和半径为128的圆的图像,并且相对于另一个以中心(0,0)和半径为40的圆(未显示)反转。 大圆圈上的红点是相反的极性。然后将它们反转,并显示在小圆圈上,在其中您可以看到它们不是相反的对立面。

a circle and it's inversion

答案 1 :(得分:0)

我的错误是我假设倒圆的中心也尊重OP x OP'= r 2 ,但如下图所示,它显然没有。解决方案是计算圆上的两个点并反映每个点,然后使用这些点之间的距离的一半来找到半径。

enter image description here

所以这是正确的代码:

var c = $('#c'),
  b = $('body'),
  canvas = c[0],
  ctx = canvas.getContext('2d'),
  fixedRadius = 100,
  saved = [], 
  width, height,
  half = {
    w: 0,
    h: 0
  },
  mouse = {
    r: 31,
    x: 0,
    y: 0
  },
  reflect = {
    x: 0,
    y: 0,
    r: 0
};

var setup = function() {
  width = b.width();
  height = b.height();
  half.w = width/2;
  half.h = height/2;
  canvas.width = width;
  canvas.height = height;
  move();
};

var mid = function() {
  circle(half.w,half.h,1.5);
  circle(half.w,half.h,fixedRadius);
};

var circle = function(x,y,r,c) {
  ctx.strokeStyle = c || 'black';
  ctx.beginPath();
  ctx.arc(x,y,r,0,Math.PI*2);
  ctx.stroke();
  ctx.closePath();
};

var line = function(x1,y1,x2,y2,c) {
  ctx.strokeStyle = c || 'black';
  ctx.beginPath();
  ctx.moveTo(x1,y1);
  ctx.lineTo(x2,y2);
  ctx.stroke();
  ctx.closePath();
};

var axis = function () {
  line(half.w,0,half.w,height,'#ccc');
  line(0,half.h,width,half.h,'#ccc');
};

var move = function(evt) {
  mouse.x = evt ? evt.clientX : half.w;
  mouse.y = evt ? evt.clientY : half.h + 11;
  ctx.clearRect(0,0,width,height);
  axis();
  mid();
  circle(mouse.x,mouse.y,mouse.r);
  circle(mouse.x,mouse.y,1,'grey');
  var di = {
    x: mouse.x - half.w, // orange
    y: mouse.y - half.h  // green
  }
  di.v = dist(di.x,di.y);
  var a = Math.atan2(di.y,di.x); // angle
  line(mouse.x - di.x,mouse.y,mouse.x,mouse.y,'orange');
  line(mouse.x,mouse.y - di.y,mouse.x,mouse.y,'green');
  var p1 = {
    v: di.v + mouse.r // cyan
  }; 
  p1.x = half.w + (Math.cos(a) * p1.v);
  p1.y = half.h + (Math.sin(a) * p1.v);
  circle(p1.x,p1.y,1.5,'cyan');
  var p2 = {
    v: di.v - mouse.r // red
  };
  p2.x = half.w+Math.cos(a)*p2.v;
  p2.y = half.h+Math.sin(a)*p2.v;
  circle(p2.x,p2.y,1.5,'red');
  var rp1 = {
    v: Math.pow(fixedRadius,2) / p1.v // cyan
  };
  rp1.x = Math.cos(a) * rp1.v,
  rp1.y = Math.sin(a) * rp1.v;
  circle(rp1.x+half.w,rp1.y+half.h,1.5,'cyan');
  var rp2 = {
    v: Math.pow(fixedRadius,2) / p2.v // red
  };
  rp2.x = Math.cos(a) * rp2.v,
  rp2.y = Math.sin(a) * rp2.v;
  circle(rp2.x+half.w,rp2.y+half.h,1.5,'red');
  var newDi = {
    v: dist(rp1.x - rp2.x, rp1.y - rp2.y)
  };   
  newDi.r = newDi.v/2,
  newDi.x = rp1.x + (Math.cos(a) * newDi.r), // yellow
  newDi.y = rp1.y + (Math.sin(a) * newDi.r); // purple
  if (p2.v < 0) {
    newDi.x = rp1.x - (Math.cos(a) * newDi.r),
    newDi.y = rp1.y - (Math.sin(a) * newDi.r);
  }
  reflect.x = half.w+newDi.x;
  reflect.y = half.h+newDi.y
  // reflected lines
  if (di.v<fixedRadius) line(rp1.x+half.w,rp1.y+half.h,p1.x,p1.y,'cyan');
  else line(rp2.x+half.w,rp2.y+half.h,p2.x,p2.y,'red');
  line(p1.x,p1.y,half.w,half.h,'#ccc');
  line(rp2.x+half.w,rp2.y+half.h,half.w,half.h,'#ccc');
  line(reflect.x-newDi.x,reflect.y,reflect.x,reflect.y,'yellow');
  line(reflect.x,reflect.y-newDi.y,reflect.x,reflect.y,'purple');
  // reflected circle
  circle(reflect.x, reflect.y, newDi.r);
  circle(reflect.x,reflect.y,1,'grey');
  circles(); // saved circles
  reflect.r = newDi.r;
};

var dist = function(x,y) {
  return Math.pow(x*x + y*y, 1/2);
};

var scroll = function(evt) {
  if(evt.originalEvent.wheelDelta > 0) {
    mouse.r++;
  } else {
    mouse.r--;
  }
  move(evt);
};

var click = function(evt) {
  saved.push(['c',mouse.x,mouse.y,mouse.r]);
  saved.push(['c',reflect.x,reflect.y,reflect.r]);
  saved.push(['l',mouse.x,mouse.y,reflect.x,reflect.y]);
};

var circles = function() {
  for(var i = 0; i < saved.length; i++) {
    var s = saved[i];
    if (s[0]=='c') circle(s[1],s[2],s[3],'grey');
    if (s[0]=='l') line(s[1],s[2],s[3],s[4],'grey');
  }
};

$(setup);
$(window)
  .on('resize', setup)
  .on('mousemove', move)
  .on('mousewheel', scroll)
  .on('click', click);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="c"></canvas>