首页 > 其他分享 >包含点集所有点的最小圆

包含点集所有点的最小圆

时间:2023-05-05 18:56:15浏览次数:35  
标签:canvas center 包含 ctx 最小 点集 points let circle

理论来自论文:https://www.doc88.com/p-7189543163840.html 如果看不了就搜一下我的这篇博客的标题吧,至少写博客的时候是能看的

用js实现了这篇论文,命名也是用ABCD比较容易对应上。红色是点,蓝色是包含所有点的最小圆

初始有5个点,和对应的圆,包含这5个点。

鼠标点击一个空位置可以生成一个新点,点击已有的点会删除这个点,每次点击都会重新渲染

 

 下面是完整代码,复制到一个html文件里双击打开就可以用

<!DOCTYPE html>
<html>
    <head>
        <style>
            canvas{
                background-color: lightgrey;
            }
        </style>
    </head>
    <body>
        <canvas width="1600" height="1000"></canvas>
    </body>
    <script>
        var points=[
            {x: 500, y: 500},
            {x: 530, y: 500},
            {x: 570, y: 530},
            {x: 530, y: 560},
            {x: 500, y: 560}
        ];
        //两点距离
        function getD(A,B){
            return Math.sqrt((A.x-B.x)**2 + (A.y-B.y)**2);
        }
        //三角形外接圆
        function circleCenter(A, B, C) {
            let yDelta_a = B.y - A.y;
            let xDelta_a = B.x - A.x;
            let yDelta_b = C.y - B.y;
            let xDelta_b = C.x - B.x;
            if(xDelta_a==0||xDelta_b==0||yDelta_a==0)//边界情况,把点换个位置
                return circleCenter(B,C,A);
            let center = {};
            let aSlope = yDelta_a/xDelta_a;
            let bSlope = yDelta_b/xDelta_b;
            center.x = (aSlope*bSlope*(A.y - C.y) + bSlope*(A.x + B.x)
                - aSlope*(B.x+C.x) )/(2* (bSlope-aSlope) );
            center.y = -1*(center.x - (A.x+B.x)/2)/aSlope +  (A.y+B.y)/2;
            center.r=getD(center,A);//求出圆心之后随便跟一个点算距离就是半径
            return center;
        }
        //包含三点的最小圆
        function minCircleOf3(A,B,C){
            let edges=new Array(3);
            let points=[A,B,C];
            for(let i=0;i<3;i++){
                let cur=points[i],next=points[(i+1)%3];
                edges[i]=(cur.x-next.x)**2 + (cur.y-next.y)**2;
            }
            let sum=edges.reduce((a,b)=>a+b);
            let max=Math.max(...edges);
            if(max<sum/2)
                return circleCenter(A,B,C);
            let index=edges.indexOf(max);
            let p1=points[index],p2=points[(index+1)%3];
            let x=(p1.x+p2.x)/2;
            let y=(p1.y+p2.y)/2;
            let r=Math.sqrt(max)/2;
            return {x,y,r};
        }
        //距离target的最远点
        function getfarthest(target){
            let d=points.map(p=>getD(p,target));
            let res=0;
            for(let i=1;i<d.length;i++){
                if(d[i]>d[res])
                    res=i;
            }
            return {index:res, d:d[res]};
        }
        function minCircle(){
            let ABC=[points[0],points[parseInt(points.length/3)],points[parseInt(points.length*2/3)]];
            let circle=minCircleOf3(...ABC);
            let D=getfarthest(circle);
            let t=0;
            while(D.d-circle.r>0.1&&t++<10){//兼容误差
                let next=new Array(3);
                for(let i=0;i<3;i++){
                    let cp=ABC.slice();
                    cp[i]=points[D.index];
                    next[i]=minCircleOf3(...cp);
                }
                let max=0;
                for(let i=1;i<3;i++)
                    if(next[i].r>next[max].r)
                        max=i;
                circle=next[max];
                ABC[max]=points[D.index];
                D=getfarthest(circle);
            }
            return circle;
        }
        function render(){
            let canvas=document.getElementsByTagName('canvas')[0];
            let ctx=canvas.getContext('2d');
            canvas.width=canvas.width;//to clear
            ctx.fillStyle = 'red';
            for(let point of points){
                ctx.beginPath();
                ctx.arc(point.x, point.y, 3, 0, 2*Math.PI);
                ctx.closePath();
                ctx.fill();
            }
            if(points.length<3)
                return;
            let circle=minCircle();
            ctx.strokeStyle='#0000ff50';
            ctx.lineWidth=6;
            ctx.beginPath();
            ctx.arc(circle.x,circle.y,circle.r,0,2*Math.PI);
            ctx.stroke();
        }
        render();
        document.getElementsByTagName('canvas')[0].addEventListener('click',e=>{
            let x=e.offsetX,y=e.offsetY;
            let newPoints=points.filter(u=>getD(u,{x,y})>6);
            if(newPoints.length==points.length){
                points.push({x,y});
            }
            else{
                points=newPoints;
            }
            render();
        });
    </script>
</html>

 

标签:canvas,center,包含,ctx,最小,点集,points,let,circle
From: https://www.cnblogs.com/nsyglpc/p/17375095.html

相关文章

  • 209. 长度最小的子数组
     分析:这题是找满足和大于等于target的最短数组有点小问题,想用双指针做,但是写得有点糅杂了最后一组案例时间超了最后借鉴了一下题解写出来代码:1classSolution(object):2defminSubArrayLen(self,target,nums):3"""4:typetarget:int......
  • LeetCode 209. 长度最小的子数组
    题目链接:LeetCode209.长度最小的子数组本题是一个滑动窗口的题,所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。在本题中实现滑动窗口,主要确定如下三点:窗口内是什么?窗口就是满足其和≥target的长度最小的连续子数组。如何移动窗口的起......
  • .net 中使用OpenCvSharp 判断一张图片中是否包含指定图标
    1.添加包引用<ItemGroup><PackageReferenceInclude="OpenCvSharp4"Version="4.7.0.20230115"/><PackageReferenceInclude="OpenCvSharp4.Extensions"Version="4.7.0.20230115"/><PackageRef......
  • 实例 042 获取一维数组最小值
      你可以使用以下代码来获取一维数组中的最小值:int[]arr={5,3,9,1,7};intmin=arr[0];for(inti=1;i<arr.length;i++){if(arr[i]<min){min=arr[i];}}System.out.println("最小值为:"+min);  在上面的代码中,我们首先初始......
  • 双指针|长度最小的子数组
    给定一个含有n个正整数的数组和一个正整数target。找出该数组中满足其和≥target的长度最小的连续子数组[numsl,numsl+1,...,numsr-1,numsr],并返回其长度。如果不存在符合条件的子数组,返回0。输入:target=7,nums=[2,3,1,2,4,3]输出:2解释:子数组[4,3]是该条......
  • CarSim or TruckSim与Simulink联合仿真,使用键盘控制车辆加速,减速,转向,包含前进与后退档
    CarSimorTruckSim与Simulink联合仿真,使用键盘控制车辆加速,减速,转向,包含前进与后退档位切换,支持自定义按键功能,支持拓展提供carsim参数配置文件,导入即可运行提供simulink模型文件提供模型搭建过程详细说明文档ID:45100675708233261......
  • 自动驾驶图像全景分隔,基于HRnetSegmentation从训练工程到tensorRT工程部署Demo闭环一
    自动驾驶图像全景分隔,基于HRnetSegmentation从训练工程到tensorRT工程部署Demo闭环一套,包含训练工程及部署工程,和环境的配置说明,已在实际项目中使用。大厂自动驾驶工程师沉淀实实在在的工作经验总结资料是一线自动驾驶工程师辛苦工作的结果。ID:3150671806789047......
  • 自动驾驶车道线检测,基于LaneLine Detect从训练工程到tensorRT工程部署Demo闭环一套,包
    自动驾驶车道线检测,基于LaneLineDetect从训练工程到tensorRT工程部署Demo闭环一套,包含训练工程及部署工程,和环境的配置说明,已在实际项目中使用。大厂自动驾驶工程师沉淀实实在在的工作经验总结资料是一线自动驾驶工程师辛苦工作的结果ID:7950671420904511......
  • 百度飞桨工程部署,一手教你快速部署百度飞桨C++工程落地,包含飞桨OCR文字检测识别、飞桨
    百度飞桨工程部署,一手教你快速部署百度飞桨C++工程落地,包含飞桨OCR文字检测识别、飞桨图片分类、飞桨图片检测,直接调用飞桨模型库,配合tensorRT模型加速库进行前向运算,可以直接按照我的cmake内容将代码移植到实际落地项目中。经验证在x86工控机和边缘端nano、Xavier等ARM设备......
  • 自动驾驶图像分类,基于HRnet从训练工程到tensorRT工程部署Demo闭环一套,包含训练工程及
    自动驾驶图像分类,基于HRnet从训练工程到tensorRT工程部署Demo闭环一套,包含训练工程及部署工程,和环境的配置说明,已在实际项目中使用。大厂自动驾驶工程师沉淀资料是一线自动驾驶工程师辛苦工作的结果ID:5150672485127196......