最近遇到一个需求,画一个轮廓,然后外面画一个圆,圆外面再画个箭头表示方向,不能互相遮挡,所以轮廓要完全在圆内。

涉及一个子问题,先调研了一下:计算包含三角形的最小圆。后续根据这个一直迭代计算包含任意多边形的最小圆。

锐角三角形就是外接圆;钝角三角形要取最长边中点作为圆心,最长边长度作为直径;直角三角形可以并入其中任意一种情况。

参照了博客:https://blog.csdn.net/qq_17148595/article/details/122067966

效果如图

 

 

附上完整网页代码:

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <style>
  5             #main{
  6                 height: 100%;
  7                 display: flex;
  8                 flex-direction: column;
  9             }
 10             #top{
 11                 display: grid;
 12                 grid-template-rows: 50% 50%;
 13                 grid-template-columns: 33% 33% 33%;
 14             }
 15             input{
 16                 width: 100px;
 17             }
 18             canvas{
 19                 flex-grow: 1;
 20             }
 21         </style>
 22     </head>
 23     <body>
 24         <div id="main">
 25             <div id="top">
 26                 <div>
 27                     <span>A.x</span>
 28                     <input type="number" value="333" oninput="update()" />
 29                 </div>
 30                 <div>
 31                     <span>B.x</span>
 32                     <input type="number" value="400" oninput="update()" />
 33                 </div>
 34                 <div>
 35                     <span>C.x</span>
 36                     <input type="number" value="315" oninput="update()" />
 37                 </div>
 38                 <div>
 39                     <span>A.y</span>
 40                     <input type="number" value="100" oninput="update()" />
 41                 </div>
 42                 <div>
 43                     <span>B.y</span>
 44                     <input type="number" value="200" oninput="update()" />
 45                 </div>
 46                 <div>
 47                     <span>C.y</span>
 48                     <input type="number" value="370" oninput="update()" />
 49                 </div>
 50             </div>
 51             <canvas width="1000" height="800"></canvas>
 52         </div>
 53     </body>
 54     <script>
 55         function circleCenter(A, B, C) {
 56             let yDelta_a = B.y - A.y;
 57             let xDelta_a = B.x - A.x;
 58             let yDelta_b = C.y - B.y;
 59             let xDelta_b = C.x - B.x;
 60             if(xDelta_a==0||xDelta_b==0||yDelta_a==0)//边界情况,把点换个位置
 61                 return circleCenter(B,C,A);
 62             let center = {};
 63             let aSlope = yDelta_a/xDelta_a;
 64             let bSlope = yDelta_b/xDelta_b;
 65             center.x = (aSlope*bSlope*(A.y - C.y) + bSlope*(A.x + B.x)
 66                 - aSlope*(B.x+C.x) )/(2* (bSlope-aSlope) );
 67             center.y = -1*(center.x - (A.x+B.x)/2)/aSlope +  (A.y+B.y)/2;
 68             center.r=Math.sqrt((center.x-A.x)**2+(center.y-A.y)**2);//求出圆心之后随便跟一个点算距离就是半径
 69             return center;
 70         }
 71         function update(){
 72             let c=document.getElementsByTagName('canvas')[0];
 73             let ctx=c.getContext('2d');
 74             c.width=c.width;//to clear
 75             let a=Array.from(document.getElementsByTagName('input')).map(u=>parseInt(u.value));
 76             let l=[];
 77             for(let i=0;i<3;i++){
 78                 l.push(Math.sqrt((a[(i+1)%3]-a[i])**2+(a[(i+1)%3+3]-a[i+3])**2));
 79             }
 80             let max=0;
 81             for(let i=1;i<3;i++)
 82                 if(l[i]>l[max])
 83                     max=i;//找到最长边
 84             if(l.reduce((a,b)=>a+b)-l[max]*2<0.01)//共线
 85                 return;
 86             let sum=0;
 87             for(let i=0;i<3;i++){
 88                 if(i!=max)
 89                     sum+=l[i]**2;
 90             }
 91             let circle=circleCenter({x:a[0],y:a[3]}, {x:a[1],y:a[4]}, {x:a[2],y:a[5]});
 92             ctx.moveTo(a[0],a[3]);
 93             ctx.lineTo(a[1],a[4]);
 94             ctx.lineTo(a[2],a[5]);
 95             ctx.closePath();
 96             ctx.stroke();
 97             ctx.strokeStyle='blue';
 98             ctx.beginPath();
 99             ctx.arc(circle.x,circle.y,circle.r,0,2*Math.PI);
100             ctx.stroke();
101             if(l[max]**2>=sum){//不是锐角三角形
102                 ctx.strokeStyle='red';
103                 ctx.beginPath();
104                 ctx.arc((a[max]+a[(max+1)%3])/2,(a[max+3]+a[(max+1)%3+3])/2,l[max]/2,0,2*Math.PI);
105                 ctx.stroke();
106             }
107         }
108         update();
109     </script>
110 </html>