- 출처 : https://stackoverflow.com/questions/22791951/algorithm-to-find-an-arc-its-center-radius-and-angles-given-3-points
- 출처 : http://heilow.egloos.com/418569## 요구사항
3개의 점을 알고 있을 때 해당 점을 지나는 원호를 그리고 싶다.
우리는 A,B,C 3개의 점 위치를 알고 있다
A에서 시작하여 B를 통과하여 C로 끝나는 호를 어떻게 그릴 수 있을까. 중심좌표와 반지름 r을 어떻게 구할 수 있을까?
## 풀이 아이디어
A와 B 사이의 직각선을 구할 수 있고,
B와 C 사이의 직각선을 구할 수 있다.
이 2개의 선이 교차하는 부분이 원의 중심이다.
자세한 설명은 아래와 같다.
이에 대한 자바스크립트 소스는 아래와 같다.
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<style>canvas { border:2px solid magenta; }</style>
</head>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script>
window.onload = function() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// 3점의좌표
let p1 = {x:0, y:200}
let p2 = {x:300, y:320}
let p3 = {x:400, y:200}
// 두 수직 이등분선의 기울기
let d1 = (p2.x - p1.x) / (p2.y - p1.y)
let d2 = (p3.x - p2.x) / (p3.y - p2.y)
// 원의중심
let c = {x:0, y:0}
c.x = ((p3.y - p1.y) + (p2.x + p3.x) * d2 - (p1.x + p2.x) * d1) / (2 * (d2 - d1))
c.y = -d1 * (c.x - (p1.x + p2.x) / 2) + (p1.y + p2.y) / 2
// 원의 반지름
// let r = sqrt(( p1.x - c.x) ^ 2 + ( p1.y - c.y) ^ 2);
let radius = Math.sqrt( Math.pow(( p1.x - c.x) , 2) + Math.pow(( p1.y - c.y) , 2));
console.log(c, radius)
// p1~p3 각도 구하기
let startAngle = Math.atan2(p1.y - c.y, p1.x - c.x)
let endAngle = Math.atan2(p3.y - c.y, p3.x - c.x)
if(startAngle > endAngle){
let tmp = endAngle
endAngle = startAngle
startAngle = tmp
}
console.log(startAngle, endAngle)
// 세점 그리기
ctx.beginPath();
ctx.moveTo(p1.x, p1.y)
ctx.arc(p1.x, p1.y, 5, 0, 2*Math.PI);
ctx.moveTo(p2.x, p2.y)
ctx.arc(p2.x, p2.y, 5, 0, 2*Math.PI);
ctx.moveTo(p3.x, p3.y)
ctx.arc(p3.x, p3.y, 5, 0, 2*Math.PI);
ctx.strokeStyle = 'red';
ctx.fill();
ctx.stroke();
// 원호 arc로 그리기
// ctx.beginPath();
// ctx.arc(c.x, c.y, radius, startAngle, endAngle);
// ctx.moveTo(p3.x, p3.y);
// ctx.lineTo(c.x, c.y);
// ctx.lineTo(p1.x, p1.y);
// ctx.strokeStyle = "blue";
// ctx.stroke();
// 원호를 점으로 그리기
var obj = {};
// startAngle ~ endAngle 까지 n개의 라디언 으로 표시
let gab = (endAngle - startAngle) / 20
for (var i = startAngle; i <= endAngle; i += gab) {
obj.x = Math.floor(radius * Math.cos( i ));
obj.y = Math.floor(radius * Math.sin( i ));
ctx.strokeRect( c.x+obj.x , c.y+obj.y, 2,2);
}
}
function toRadians(degrees) {
return degrees * (Math.PI / 180);
}
</script>
</body>
</html>
'프론트엔드 개발 놀이터 > etc' 카테고리의 다른 글
두 점을 지나는 직선 그리기(dda, bresenham) - js (0) | 2022.08.01 |
---|---|
[VSCode] ESLint + Prettier : Expected indentation of 2 spaces but found 4 (0) | 2021.11.03 |
특정 프로그램이 죽었을 때 자동으로 재시작하게 하는 배치파일 (0) | 2020.10.19 |
[casperjs] 윈도우 환경 실행시 did you install phantomj (0) | 2020.10.13 |
[크롬인텐트] 모바일 웹에서 앱 실행하기 (앱 미설치 시 마켓으로 이동) (0) | 2020.09.24 |