精华内容
下载资源
问答
  • 求圆外一点切线的切点坐标(算法) 求圆外一点切线的切点坐标(算法) 解此题的常规方法是的方程和切线方程联立解的两个点的坐标,这种方法过于繁琐,而且在代码中不易实现。由此想到用向量旋转来解此题...

    求圆外一点做圆切线的切点坐标(算法)

    求圆外一点做圆切线的切点坐标(算法)
    tim题目要求

    解此题的常规方法是圆的方程和切线方程联立解的两个点的坐标,这种方法过于繁琐,而且在代码中不易实现。由此想到用向量旋转来解此题,解法如下。

    知识点提要

    二维坐标下向量旋转后的向量坐标公式。如下图:
    在这里插入图片描述

    解题思路

    解题思路就是通过以点到圆心的向量旋转得到新的点到圆心的向量,然后乘以模长得到坐标。
    在这里插入图片描述

    C程序代码

    #include <stdio.h>
    #include<math.h>
    struct Point
    {  // 声明结构体类型
        double x;      // 该点的x坐标
        double y;      // 该点的y坐标
    }C,P,Q1,Q2,U;
    // C是圆心的坐标 P是点的坐标 Q1,Q2是切点坐标 U是点到圆心的单位向量坐标
    int main()
    {
        double r =0; // 圆的半径
        double distance=0; // 圆心r 到p 点的距离
        double length=0; // 点p 到切点的距离
        double angle =0; // 切线与点心连线的夹角
        
        printf("请输入C点坐标:\n");
        scanf("%lf %lf",&C.x,&C.y);
        printf("请输入P点坐标:\n");
        scanf("%lf %lf",&P.x,&P.y);
        printf("请输入圆的半径:\n");
        scanf("%lf",&r);
        // 求出点到圆心的距离
        distance =sqrt((P.x-C.x)*(P.x-C.x)+ (P.y-C.y)*(P.y-C.y));
        // 判断是否符合要求 distance<=r 不符合则返回 否则进行运算
        if(distance<=r){
         printf("您输入的数值不在范围内!\n");
         return 0;
        }
         
        // 点p 到切点的距离
        length = sqrt(distance*distance-r*r);
        
        // 点到圆心的单位向量
        U.x=(C.x-P.x)/distance;
        U.y=(C.y-P.y)/distance;
        
        // 计算切线与点心连线的夹角
        angle = asin(r/distance);
        
        // 向正反两个方向旋转单位向量
        Q1.x = U.x * cos(angle)  -  U.y * sin(angle);
        Q1.y = U.x * sin(angle)  +  U.y * cos(angle);
        Q2.x = U.x * cos(-angle) -  U.y * sin(-angle);
        Q2.y = U.x * sin(-angle) +  U.y * cos(-angle);
        // 得到新座标
        Q1.x = ( Q1.x + P.x) * length;
        Q1.y = ( Q1.y + P.y) * length;
        Q2.x = ( Q2.x + P.x) * length;
        Q2.y = ( Q2.y + P.y) * length;
        // 输出坐标
        printf("Q1的坐标为:(%.1f,%.1f),Q2的坐标为:(%.1f,%.1f) \n",Q1.x,Q1.y,Q2.x,Q2.y);
        
        return 0;
    }
    
    
    展开全文
  • 圆外一点P1(x1,y1)向(x - a)2 + (y - b)2 = R2作切线,切线与相切的切点是P0(x0,y0) 先直线P0P1直线方程 因为P0P1⊥OP0 向量OP0 = (x0 - a,y0 - b ) 向量P0P1 = (x1 - x0, y1 - y0) 所以 向量P0P1 ...

    由圆外一点P1(x1,y1)向圆(x - a)2 + (y - b)2 = R2作切线,切线与圆相切的切点是P0(x0,y0)
    image.png

    方法一: 公式法

    先求直线P0P1直线方程
    因为P0P1⊥OP0
    向量OP0 = (x0 - a,y0 - b )
    向量P0P1 = (x1 - x0, y1 - y0)
    所以 向量P0P1 点乘 向量OP0 = 0
    所以 (x0 - a)* (x1 - x0) + (y0 - b)(y1 - y0) = 0
    并且 因为点P0是圆上的点,=> (x0 - a)2 + (y0 - b)2 = R2

    解方程就可以求出P0(x0,y0)坐标,当然这样求法太复杂,我没有耐心解下去了,我们换个思维求我们把圆换成这样,相当于把整个系统做了一次相对位移,移动到0点
    x2 + y2 = R2
    image.png
    那么经过点P0(x0,y0)这个圆的的切线方程就是
    x0x1 + y0y1 = R2
    并且x20 + y20 = R2
    所以
    (x21 + y21)x20 -2R2x1x0 + R4 - y21R2 = 0
    这样就是求解一元二次方程
    m = (x21 + y21) / R2

    x0 = (-b±√(b2 - 4ac)) / (2a) = (x1 ± y1√(m-1)) / m
    y0 = (y1 ± x1√(m-1)) / m
    至此切点是找到了,
    然后再位移下就是真正的点了

    p

    let canvas =  document.getElementById("target");
      canvas.width = document.body.clientWidth;
      canvas.height = document.body.clientHeight;
      let ctx = canvas.getContext("2d");
      let isDrawing = false;
      canvas.addEventListener('mousedown', e => {
          let x = e.offsetX;
          let y = e.offsetY;
          isDrawing = true;
          pointP = {x:x,y:y};
          update();
      });
    
      canvas.addEventListener('mousemove', e => {
          if (isDrawing === true) {
              let x = e.offsetX;
              let y = e.offsetY;
              pointP = {x:x,y:y};
              update();
          }
      });
    
      canvas.addEventListener('mouseup', e => {
          if (isDrawing === true) {
              isDrawing = false;
          }
      });
    
      let pointP = {x: 300,y: 100};
      //圆心坐标
      let pointCenter ={x:250,y:250};
      //圆点半径
      let radius = 100;
    
      function update(){
          ctx.clearRect(0,0,canvas.width,canvas.height);
          //圆心
          drawPoint(pointCenter.x,pointCenter.y,"#986923");
    
          //圆
          ctx.beginPath();
          ctx.arc(pointCenter.x,pointCenter.y,radius,0,2*Math.PI,true);
          ctx.stroke();
          ctx.closePath();
    
          drawPoint(pointP.x,pointP.y,"#986923");
          let arrayQieDian = calcQieDian(pointCenter.x,pointCenter.y,radius,pointP);
          arrayQieDian.forEach((point)=>{
              drawPoint(point.x,point.y,"#f00");
              drawLine(pointP,point);
              drawLine(pointCenter,point);
          });
      }
      update();
    
      function drawPoint(x,y,color){
          ctx.beginPath();
          ctx.fillStyle=color;
          ctx.arc(x,y,5,0,2*Math.PI,true);
          ctx.fill();
      }
    
      function drawLine(pointStart,pointEnd) {
          ctx.beginPath();
          ctx.moveTo(pointStart.x,pointStart.y);
          ctx.lineTo(pointEnd.x,pointEnd.y);
          ctx.stroke();
      }
    
       function calcQieDian(cx,cy,radius,point) {
           //将实际的点做一次转换,因为下面的计算都是暗转圆心都是在圆点计算的
           let outsideX = point.x - cx;
           let outsideY = point.y - cy;
           
           let m = (Math.pow(outsideX,2)+Math.pow(outsideY,2))/Math.pow(radius,2);
           //求出的结果将会有4种排列
           let pointA = {
               x:((outsideX+outsideY*Math.sqrt(m-1))/m),
               y:((outsideY+outsideX*Math.sqrt(m-1))/m)
           };
    
           let pointB = {
               x:((outsideX-outsideY*Math.sqrt(m-1))/m),
               y:((outsideY-outsideX*Math.sqrt(m-1))/m)
           };
           let pointC = {
               x:((outsideX+outsideY*Math.sqrt(m-1))/m),
               y:((outsideY-outsideX*Math.sqrt(m-1))/m)
           };
           let pointD = {
               x:((outsideX-outsideY*Math.sqrt(m-1))/m),
               y:((outsideY+outsideX*Math.sqrt(m-1))/m)
           };
    
           let array = [];
           //实际上只会有2个切点,利用向量垂直,点乘结果是0来判断哪个是有效的
           //因为浮点数不能精确到0,所以这里用了1e-10
           if(Math.abs(pointA.x*(outsideX -pointA.x ) + pointA.y * (outsideY - pointA.y)) <= 1e-10){
              // 再将坐标转换回来
               pointA.x += cx;
               pointA.y += cy;
               array.push(pointA);
           }
    
           if(Math.abs(pointB.x*(outsideX -pointB.x ) + pointB.y * (outsideY - pointB.y)) <= 1e-10){
               pointB.x += cx;
               pointB.y += cy;
               array.push(pointB);
           }
           if(Math.abs(pointC.x*(outsideX -pointC.x ) + pointC.y * (outsideY - pointC.y)) <= 1e-10){
               pointC.x += cx;
               pointC.y += cy;
               array.push(pointC);
           }
           if(Math.abs(pointD.x*(outsideX -pointD.x ) + pointD.y * (outsideY - pointD.y)) <= 1e-10){
               pointD.x += cx;
               pointD.y += cy;
               array.push(pointD);
           }
           return array;
       }
    

    方法二:向量法

    image.png
    思路:只要知道P1点与水平线的角度就可以计算坐标,先计算OM与水平线的角度,角P1OM的余弦值就是P1O / OM
    P1O 的长度就是半径r

    let canvas =  document.getElementById("target");
       canvas.width = document.body.clientWidth;
       canvas.height = document.body.clientHeight;
       let ctx = canvas.getContext("2d");
       let isDrawing = false;
       let eventCircle = false;
       canvas.addEventListener('mousedown', e => {
           let x = e.offsetX;
           let y = e.offsetY;
           isDrawing = true;
           if(Math.pow(x - pointCenter.x,2) + Math.pow(y - pointCenter.y,2) <= radius*radius){
               eventCircle = true;
               pointCenter.x = x;
               pointCenter.y = y;
           }else{
               pointP.x = x;
               pointP.y = y;
           }
           update();
       });
    
       canvas.addEventListener('mousemove', e => {
           if (isDrawing === true) {
               let x = e.offsetX;
               let y = e.offsetY;
               if(eventCircle){
                   pointCenter.x = x;
                   pointCenter.y = y;
               }else{
                   pointP.x = x;
                   pointP.y = y;
               }
               update();
           }
       });
    
       canvas.addEventListener('mouseup', e => {
           if (isDrawing === true) {
               isDrawing = false;
               eventCircle = false;
           }
       });
    
       let pointP = {x: 300,y: 100};
       //圆心坐标
       let pointCenter ={x:250,y:250};
       //圆点半径
       let radius = 100;
    
       function update(){
           ctx.clearRect(0,0,canvas.width,canvas.height);
           //圆心
           drawPoint(pointCenter.x,pointCenter.y,"#986923");
    
           //圆
           ctx.beginPath();
           ctx.arc(pointCenter.x,pointCenter.y,radius,0,2*Math.PI,true);
           ctx.stroke();
           ctx.closePath();
    
           drawPoint(pointP.x,pointP.y,"#986923");
           let p = calcQieDian2(pointCenter.x,pointCenter.y,radius,pointP);
           drawText("P1",p.p1.x,p.p1.y);
           drawText("P2",p.p2.x,p.p2.y);
           drawText("M",pointP.x,pointP.y);
           drawText("O",pointCenter.x,pointCenter.y);
    
           drawPoint(p.p1.x,p.p1.y,"#f00");
           drawPoint(p.p2.x,p.p2.y,"#f00");
    
           drawLine(pointCenter,p.p1);
           drawLine(pointCenter,p.p2);
           drawLine(pointCenter,pointP);
    
           drawLine(pointP,p.p1);
           drawLine(pointP,p.p2);
           drawLine({x:0,y:pointCenter.y},{x:canvas.width,y:pointCenter.y});
    
    
       }
       update();
    
       function drawPoint(x,y,color){
           ctx.beginPath();
           ctx.fillStyle=color;
           ctx.arc(x,y,5,0,2*Math.PI,true);
           ctx.fill();
       }
    
       function drawLine(pointStart,pointEnd) {
           ctx.beginPath();
           ctx.moveTo(pointStart.x,pointStart.y);
           ctx.lineTo(pointEnd.x,pointEnd.y);
           ctx.stroke();
       }
    
       function calcQieDian2(cx,cy,radius,point) {
           //点到圆心的距离
           let d = Math.sqrt(Math.pow(cx - point.x,2) + Math.pow(cy - point.y,2));
           let vc1c2 = {x:point.x - cx,y:-point.y + cy}; //屏幕坐标系与笛卡尔坐标系是y轴是反着的
           let radC1C2 = Math.acos(vc1c2.x / Math.sqrt(Math.pow(vc1c2.x,2) + Math.pow(vc1c2.y,2)));
           let theta = Math.acos(radius/d);
           if(point.y < cy){
               let p1 = {x:cx + Math.cos(theta + radC1C2)*radius,y:cy - Math.sin(theta + radC1C2)*radius};
               let p2 = {x:cx + Math.cos(theta - radC1C2)*radius,y:cy + Math.sin(theta - radC1C2)*radius};
               return {p1:p1,p2:p2};
           }else{
               radC1C2 = Math.PI - radC1C2;
               let p1 = {x:cx + Math.cos(Math.PI - theta - radC1C2)*radius,y:cy + Math.sin(Math.PI - theta - radC1C2)*radius};
               let p2 = {x:cx + Math.cos(Math.PI - (theta - radC1C2))*radius,y:cy - Math.sin(Math.PI - (theta - radC1C2))*radius};
               return {p1:p1,p2:p2};
           }
       }
    
       function drawText(text,x,y) {
           ctx.beginPath();
           ctx.font="40px Arial";
           ctx.fillText(text,x,y);
           ctx.stroke();
       }
    

    p

    方法三 atan2

    利用atan2计算,返回(-pi,pi]之间的值,从x轴正方向逆时针旋转到点(x,y)时经过的角度 ​

    image.png

     function angle(p1,p2) {
           return Math.atan2(p1.y - p2.y, p1.x - p2.x);
       }
    
       function getVector(cx, cy, a, r) {
           return {x:cx + r * Math.cos(a), y:cy + r * Math.sin(a)};
       }
    
      function calcQieDian3(pointCircle,radius,point) {
           let d = Math.sqrt(Math.pow(pointCircle.x - point.x,2) + Math.pow(pointCircle.y - point.y,2));
           const angleBetweenCenters = angle(point,pointCircle);
           const spread = Math.acos(radius/ d);
           const angle1 = angleBetweenCenters + spread;
           const angle2 = angleBetweenCenters - spread;
           const p1 = getVector(pointCircle.x,pointCircle.y, angle1, radius);
           const p2 = getVector(pointCircle.x,pointCircle.y, angle2, radius);
           return {p1:p1,p2:p2};
       }
    

    完整代码

    let canvas =  document.getElementById("target");
       canvas.width = document.body.clientWidth;
       canvas.height = document.body.clientHeight;
       let ctx = canvas.getContext("2d");
       let isDrawing = false;
       let eventCircle = false;
       canvas.addEventListener('mousedown', e => {
           let x = e.offsetX;
           let y = e.offsetY;
           isDrawing = true;
           if(Math.pow(x - pointCenter.x,2) + Math.pow(y - pointCenter.y,2) <= radius*radius){
               eventCircle = true;
               pointCenter.x = x;
               pointCenter.y = y;
           }else{
               pointP.x = x;
               pointP.y = y;
           }
           update();
       });
    
       canvas.addEventListener('mousemove', e => {
           if (isDrawing === true) {
               let x = e.offsetX;
               let y = e.offsetY;
               if(eventCircle){
                   pointCenter.x = x;
                   pointCenter.y = y;
               }else{
                   pointP.x = x;
                   pointP.y = y;
               }
               update();
           }
       });
    
       canvas.addEventListener('mouseup', e => {
           if (isDrawing === true) {
               isDrawing = false;
               eventCircle = false;
           }
       });
    
       let pointP = {x: 300,y: 100};
       //圆心坐标
       let pointCenter ={x:250,y:250};
       //圆点半径
       let radius = 100;
    
       function angle(p1,p2) {
           return Math.atan2(p1.y - p2.y, p1.x - p2.x);
       }
    
       function getVector(cx, cy, a, r) {
           return {x:cx + r * Math.cos(a), y:cy + r * Math.sin(a)};
       }
    
    
       function update(){
           ctx.clearRect(0,0,canvas.width,canvas.height);
           //圆心
           drawPoint(pointCenter.x,pointCenter.y,"#986923");
    
           //圆
           ctx.beginPath();
           ctx.arc(pointCenter.x,pointCenter.y,radius,0,2*Math.PI,true);
           ctx.stroke();
           ctx.closePath();
    
           drawPoint(pointP.x,pointP.y,"#986923");
    
    
           let p = calcQieDian3(pointCenter,radius,pointP);
           drawText("P1",p.p1.x,p.p1.y);
           drawText("P2",p.p2.x,p.p2.y);
           drawText("M",pointP.x,pointP.y);
           drawText("O",pointCenter.x,pointCenter.y);
    
           drawPoint(p.p1.x,p.p1.y,"#f00");
           drawPoint(p.p2.x,p.p2.y,"#f00");
    
           drawLine(pointCenter,p.p1);
           drawLine(pointCenter,p.p2);
           drawLine(pointCenter,pointP);
    
           drawLine(pointP,p.p1);
           drawLine(pointP,p.p2);
           drawLine({x:0,y:pointCenter.y},{x:canvas.width,y:pointCenter.y});
    
    
       }
       update();
    
       function drawPoint(x,y,color){
           ctx.beginPath();
           ctx.fillStyle=color;
           ctx.arc(x,y,5,0,2*Math.PI,true);
           ctx.fill();
       }
    
       function drawLine(pointStart,pointEnd) {
           ctx.beginPath();
           ctx.moveTo(pointStart.x,pointStart.y);
           ctx.lineTo(pointEnd.x,pointEnd.y);
           ctx.stroke();
       }
    
       function calcQieDian3(pointCircle,radius,point) {
           let d = Math.sqrt(Math.pow(pointCircle.x - point.x,2) + Math.pow(pointCircle.y - point.y,2));
           const angleBetweenCenters = angle(point,pointCircle);
           const spread = Math.acos(radius/ d);
           const angle1 = angleBetweenCenters + spread;
           const angle2 = angleBetweenCenters - spread;
           const p1 = getVector(pointCircle.x,pointCircle.y, angle1, radius);
           const p2 = getVector(pointCircle.x,pointCircle.y, angle2, radius);
           return {p1:p1,p2:p2};
       }
       
    
       function drawText(text,x,y) {
           ctx.beginPath();
           ctx.font="30px Arial";
           ctx.fillText(text,x,y);
           ctx.stroke();
       }
    
    展开全文
  • // 原帖地址:http://www.cnblogs.com/zhaojz/p/4218026.html//获取切点坐标 point 圆外一点 dot 圆心 r 半径function getCircleTangent(point, dot, r) { var r_square = Math.pow(r, 2); // r的平方 var point_v...
    // 原帖地址:http://www.cnblogs.com/zhaojz/p/4218026.html
    //获取切点坐标 point 圆外的一点 dot 圆心 r 半径
    function getCircleTangent(point, dot, r) {
    var r_square = Math.pow(r, 2); // r的平方
    var point_v = point[1] - dot[1]; //point到x轴的距离的平方
    var point_h = point[0] - dot[0]; //point到y轴的距离的平方
    var c_square = Math.pow(point_v, 2) + Math.pow(point_h, 2); //point到圆心的距离的平方

    var c = Math.sqrt(c_square); //point到圆心的距离

    var sinA = Math.abs(point_v) / c; //sinA
    var cosA = Math.abs(point_h) / c; //cosA
    var b_square = c_square - r_square; //point到切点的距离的平方
    var b = Math.sqrt(b_square); //point到切点的距离

    var sinB = b / c; //sinB
    var cosB = r / c; //cosB
    //以圆心为坐标圆点,确定point所在的象限
    var quadrant = 1; //默认值
    var pm_h = point_h == 0 ? point_h : point_h / Math.abs(point_h); //水平方向
    var pm_v = point_v == 0 ? point_v : point_v / Math.abs(point_v); //垂直方向
    var hv = pm_h * pm_v; //相乘,-1时point在一三象限,+1时point在二四象限,0时point在轴上
    switch (hv) {
    case 1:
    if ((pm_h + pm_v) == -2) {
    quadrant = 2; //第二象限
    } else {
    quadrant = 4; //第四象限
    }
    break;
    case -1:
    if ((pm_h - pm_v) == -2) {
    quadrant = 3; //第三象限
    }
    break;
    case 0:
    if ((pm_h + pm_v) == -1) { //point在x轴的负半轴或者y轴的正半轴时,断定point在第二象限
    quadrant = 2;
    }
    if ((pm_h + pm_v) == 1) { //point在x轴的正半轴或者y轴的负半轴时,断定point在第四象限
    quadrant = 4;
    }
    break;
    default:
    }
    var sinC = 0;
    var conC = 0;
    var sinD = 0;
    var conD = 0;
    switch (quadrant) {
    case 1:
    sinC = cosB * cosA + sinB * sinA; //sinC = sin(90+(B-A)) = cos(B-A) = cosB*cosA+sinB*sinA
    conC = -(sinB * cosA - cosB * sinA); //cosC = cos(90+(B-A)) = -sin(B-A) = -(sinB*cosA-cosB*sinA)
    sinD = -(cosA * cosB - sinA * sinB); //sinD = sin(270-(A+B))
    conD = -(sinA * cosB + cosA * sinB); //conD = cos(270-(A+B))
    break;
    case 2:
    sinC = -(cosB * cosA - sinB * sinA); //sinC = sin(-90+(A+B))
    conC = sinA * cosB + cosA * sinB; //conC = cos(-90+(A+B))
    sinD = cosA * cosB + sinA * sinB; //sinD = sin(90+(A-B))
    conD = -(sinA * cosB - cosA * sinB); //conD = cos(90+(A-B))
    break;
    case 3:
    sinC = -(cosA * cosB + sinA * sinB); //sinC = sin(-90+(A-B))
    conC = -(sinA * cosB - cosA * sinB); //conC = cos(-90+(A-B))
    sinD = (cosA * cosB - sinA * sinB);
    conD = sinA * cosB + cosA * sinB;
    break;
    case 4:
    sinC = cosA * cosB - sinA * sinB;
    conC = -(sinA * cosB + cosA * sinB)
    sinD = -(cosA * cosB + sinA * sinB); //sinD = sin(270+(A-B))
    conD = (sinA * cosB - cosA * sinB); //conD = cos(270+(A-B))
    break;
    default:
    }
    return {
    point1: {x: point[0] + b * conC, y: point[1] + b * sinC},
    point2: {x: point[0] + b * conD, y: point[1] + b * sinD}
    }; //两个切点位置
    }

    转载于:https://www.cnblogs.com/Yishin/p/6845670.html

    展开全文
  • 已知C点坐标、圆心坐标O及其半径r,求切点坐标。 我只计算了其中一个坐标点。 float radius;//半径 Vector3 m_yuanxin;//圆心坐标 Vector3 m_qiedian;//切点坐标 ...C(圆外一点)</param> ...

    已知C点坐标、圆心坐标O及其半径r,求切点坐标。

    我只计算了其中一个坐标点。

            float radius;//半径
            Vector3 m_yuanxin;//圆心坐标
            Vector3 m_qiedian;//切点坐标
            /// <param name="m_pos[2]">C(圆外一点)</param>
            /// <param name="Odian">O圆心坐标</param>
            /// <param name="Ddian">D切点</param>
            /// <returns></returns>
            void CalculateD(List<Vector3> ve)
            {
                // 计算OA与OD之间的夹角
                float aod;
                float l_AO = Mathf.Sqrt((ve[2].x - m_yuanxin.x) * (ve[2].x - m_yuanxin.x) + (ve[2].y - m_yuanxin.y) * (ve[2].y - m_yuanxin.y));
                aod = Mathf.Acos(radius / l_AO) * 180 / Mathf.PI;
                // 计算X轴与OA之间的角度
                float angle = 0;
                float angleend = 0;
                float _x = ve[2].x - m_yuanxin.x;
                if (ve[2].x <= m_yuanxin.x && ve[2].y >= m_yuanxin.y)//180-270;C点相对于O点在第二象限,则D点在第三象限
                {
                    angle = Mathf.Acos(-_x / l_AO) * 180 / Mathf.PI;
                    angleend = -180 + aod - angle;
                }
                else if (ve[2].x >= m_yuanxin.x && ve[2].y >= m_yuanxin.y)//90-180;C点相对于O点在第一象限,则D点在第二象限
                {
                    angle = Mathf.Acos(_x / l_AO) * 180 / Mathf.PI;
                    angleend = angle + aod;
                }
                else if (ve[2].x >= m_yuanxin.x && ve[2].y <= m_yuanxin.y)//0-90;C点相对于O点在第四象限,则D点在第一象限
                {
                    angle = Mathf.Acos(_x / l_AO) * 180 / Mathf.PI;
                    angleend = aod - angle;
                }
                else if (ve[2].x <= m_yuanxin.x && ve[2].y <= m_yuanxin.y)//270-360;C点相对于O点在第三象限,则D点在第四象限
                {
                    angle = Mathf.Acos(-_x / l_AO) * 180 / Mathf.PI;
                    angleend = angle + aod - 180;
                }
                //计算切点坐标
                float x = m_yuanxin.x + radius * Mathf.Cos(angleend * Mathf.PI / 180);
                float y = m_yuanxin.y + radius * Mathf.Sin(angleend * Mathf.PI / 180);
                m_qiedian = new Vector3(x, y, 0);
            }

    以下方法是参考别个修改了点点

            /// <summary>
            /// 计算出切点坐标
            /// </summary>
            /// <param name="ptCenter">圆心坐标</param>
            /// <param name="ptOutside">第三点坐标</param>
            /// <param name="dbRadious">半径</param>
            /// <returns></returns>
            Vector3 CalcQieDian(Vector3 ptCenter, Vector3 ptOutside, float dbRadious)
            {
    
                Vector3 E, F, G, H;
                E = new Vector3();
                F = new Vector3();
                G = new Vector3();
                H = new Vector3();
                float r = dbRadious;
                //1. 坐标平移到圆心ptCenter处,求园外点的新坐标E
                E.x = ptOutside.x - ptCenter.x;
                E.y = ptOutside.y - ptCenter.y; //平移变换到E
    
                //2. 求圆与OE的交点坐标F, 相当于E的缩放变换
                float t = r / Mathf.Sqrt(E.x * E.x + E.y * E.y); //得到缩放比例
                F.x = E.x * t;
                F.y = E.y * t; //缩放变换到F
    
                //3. 将E旋转变换角度a到切点G,其中cos(a)=r/OF=t, 所以a=arccos(t);
                float a = Mathf.Acos(t); //得到旋转角度
                if ((E.x <= 0 && E.y >= 0) || (E.x <= 0 && E.y <= 0))//C点相对于圆心在第二、三象限
                {
                    a = -a;
                }
                G.x = F.x * Mathf.Cos(a) - F.y * Mathf.Sin(a);
                G.y = F.x * Mathf.Sin(a) + F.y * Mathf.Cos(a); //旋转变换到G
    
                //4. 将G平移到原来的坐标下得到新坐标H
                H.x = G.x + ptCenter.x;
                H.y = G.y + ptCenter.y; //平移变换到H
                return H;
            }

     

    展开全文
  • 圆心在坐标原点 圆心不在坐标原点
  • CPoint CalcQieDian(CPoint ptCenter, CPoint ptOutside, double dbRadious) { struct point {double x, y;}; point E,F,G,H;... 坐标平移到圆心ptCenter处,园外点的新坐标E E.x= ptOutside.x-ptC
  • 切线与内切线的切点算法

    千次阅读 2019-10-26 14:59:12
    最近想画两球水滴效果所有在...根据CircleUtils类的getCircleTangentPointOut方法返回外切点坐标[r1p1, r1p2, r2p1, r2p2],依次为左边的两个切点坐标和右边两个切点坐标。 根据CircleUtils类的getCircleTangent...
  • 题目: ... 给出两个的圆心坐标和半径,公切线数目(-1表示无穷)、两公切线的切点和这条公切线上切点的距离。 ac代码: 注意精度!!比较大小尽量用三态函数 #include <bit...
  • 求圆上点的坐标

    万次阅读 2016-09-17 00:16:21
    求圆上点的坐标需要已知的条件:圆心、半径、角度 假设圆心:o (x0,y0) 半径:r 角度:angle (角度是相对于图中红点位置而言,逆时针为负数,顺时针为正) 计算公式: p2 (x1,y1), 其中angle = 30 ...
  • 文中利用平面几何学"同弧上的弦切角等于所对圆心角的一半"定理,解决曲线上任意点坐标计算中方位角推算方法,此方法可直接得到曲线上任意点的坐标方位角和边长,省略了标准计算方法通过切点为中间过渡的计算办法,最...
  • 依赖:【点】、【直线】、【】 //画切线 ...//point 圆外一点 //dot 圆心 //r 半径 function drawCircleTangent(point, dot, r){ //画辅助线-start var color = 'DarkRed'; //切线的...
  • 题目地址:https://vjudge.net/problem/UVA-12304 题目: ... 解题思路: 紫书P267-P269将的很清楚了,新的知识点是直线平移的法: 直线,v是方向向量 1.出单位法向量normal Point Verunit(Point a) ...
  • 跑道是一个圆形,在本题中,我们认为跑道是一个半径为R的圆形,设圆心的坐标为原点(0,0)。 小明跑步的起点坐标为(R,0),他沿着圆形跑道跑步,而且一直沿着一个方向跑步。回到家后,他查看了自己的计步器,计步器...
  • 【数学】椭圆曲线中的半代入法 例题 张宇《高数18讲2021版》习题 17.3 锥面S 是由过点(4,0)且与椭圆 x24+y23=1\frac{x^{2}}{4}+\frac{y^{2}}{3}=...对于例题,设切点坐标为(a,b),则直接可设切线方程为 ...
  • 坐标其实很简单,但...目 录—、极坐标的基本概念二、极坐标和直角坐标的转换三、直角坐标系下的曲线方程转换为极坐标系下的曲线方程 (1)圆心在原点的: (2)圆心过原点的椭圆方程: (3)直线四、对称中心不在原...
  • 先回顾一下高中所学的切点弦的相关性质 对于某个圆心为原点的 1.若点在上,过该点作的切线,则切线的直线方程为 证明:可对左右关于x,y求导:2x*dx+2y*dy=0 得到 k=dy/dx=-x0/y0(隐函数求导) 带入...
  • 求圆外一点的交点P:利用向量转向,点向式来求解。 已知切点和P点和光源O点:我们可以利用两直线相交来(构造一个x轴的直线) 线段合并:先对我们出来的线段进行排序,然后如果前面一个线段的右端点大于当前...
  • 错题

    2018-05-02 14:10:00
    (2)从C外一点P(x1,y1)向该引一条切线,切点为M,O为坐标原点,且有|PM|=|PO|,使得|PM|取得最小值的点P的坐标. 解:(1)∵切线在两坐标轴上的截距相等,∴当截距不为零时,设切线方程为x+y=a,又∵C...
  • iOS 坐标变换

    千次阅读 2017-07-24 13:12:48
    iOS 坐标变换 在iOS中,Quartz 2D提供了坐标变换支持。   一、特殊的坐标变换(平移、缩放、旋转)   1. - void CGContextTranslateCTM ( CGContextRef c, CGFloat tx, CGFloat ty ):平移坐标系统。 该方法相当...
  • 假设这个圆外一点坐标是(a,b),那么可以设另一个点(a,b+1),然后以每个切点分别作第三个点形成夹角。要求这个夹角的角度可以先根据三点出三边,再套用cosx=(a2+b2-c2)/2ab出arccosx,这样即可出四个弧角。最后...
  • GIS算法--已知一点经纬度,方位角,距离一点

    万次阅读 热门讨论 2016-08-24 10:44:39
    已知一个点A的经纬度坐标,点B相对与A的方位角,B到A的距离,B的经纬度坐标,用Javascript语言来完成该算法,借用了一下openL CommonFunc.caculate={ VincentyConstants : { a: 6378137, b: 6356752.3142, ...
  • PostGIS坐标转换算法

    千次阅读 2019-06-14 14:01:53
    -- 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换 -- 即 百度 转 谷歌、高德 CREATE OR REPLACE FUNCTION FreeGIS_BD2GCJ( in bd_point geometry(Point,4326), out gcj_point geometry(Point,4326) ) RETURNS ...
  • 椭圆极点极线初探

    万次阅读 2015-08-10 20:32:35
    椭圆乃中学数学的一项重要内容,其形状之优雅大概迷倒了不少青春少年,然而除了欣赏其外观之美,作为学生还应该发掘其内在之美,即数学美。本文就椭圆的一些问题作一概要叙述。椭圆曲线将其所在平面分成了三个部分...
  • 给用户通常在平面上对地图进行处理,这些地图的要素代表地球表面空间要素的位置是用x轴和y轴表示的地理坐标系统。地球表面的空间要素是基于经纬度表示的地理坐标系统。所以项目一开始就需要确定统一的坐标系统。 ...
  • 其实就是一个椭圆与给定圆外切的切点坐标,这个椭圆不是标准椭圆(即主轴为 xx 轴)。 如果我们暴力列方程的话有如下几个方程: 切点在上; 切点在椭圆上; 该点处的切线与椭圆的切线相同。 按理说是可...
  • 两点到的最小距离

    2012-10-02 23:52:00
    0$上运动,圆外有两点$C(d,e),D(f,g)$,两点到动点的距离之和最小,此时动点的坐标. 如图. 解决方案如下:当线段CD与不相交时, 做以C,D为焦点,且与相切的椭圆.椭圆与切点即为满足条件的...
  • 15.从多边形外一点出发到该多边形的切线 18 16.判断多边形的核是否存在 19 ㈣ 的基本运算 1 .点是否在内 20 2 .不共线的三点所确定的 21 ㈤ 矩形的基本运算 1.已知矩形三点坐标第4点坐标 22 ㈥ ...
  • 椭圆曲线算法:入门(1)

    千次阅读 2019-05-16 10:49:04
    检查这些点是否在直线上是显而易见的,然而检查R是否属于椭圆曲线并不是,因为我们不得不解决一个一点都不有趣的三次方程问题。 考虑这么一个例子:根据我们给出的 visual tool ,给定的P=(1,2)和Q=(3,4)都...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 688
精华内容 275
关键字:

圆外一点求切点坐标