有一個矩形和一個圓,我想要一個函式,它可以回傳它們碰撞點的坐標,如下所示
let myrect = { x: 100, y: 100, w: 100, h: 50 };
let mycircle = { x: 156, y: 156, r: 100 };
function detectCoords(rect, circle) {
//do something
return [{ x: 5, y: 2}, { x: 3, y: 7}] //example
}

uj5u.com熱心網友回復:
基于Wyck 的評論。唯一需要的代碼是intersections函式(這是你的detectCoords函式)。如果您有任何問題,請發表評論:-)
function intersections (rect, circle) {
var y_top = rect.y - rect.h / 2;
var x_right = rect.x rect.w / 2;
var y_bottom = rect.y rect.h / 2;
var x_left = rect.x - rect.w / 2;
return [
// absolute coordinates
// of all the `rect` edges
/* 0 even */ y_top,
/* 1 odd */ x_right,
/* 2 even */ y_bottom,
/* 3 odd */ x_left
].map(function (x_or_y, i) {
// relative coordinate
// of one `rect` edge
return x_or_y - (
// `i & 1` is 0 or 1
circle["yx"[i & 1]]
);
}).map(function (x_or_y, i) {
// edge out of circle
if (Math.abs(x_or_y) > circle.r) {
return [];
}
// edge and circle intersect
else {
let y_or_x, x1, y1, x2, y2;
y_or_x = Math.sqrt(
circle.r ** 2 - x_or_y ** 2
);
i = i & 1; // 0 or 1
x1 = [y_or_x, x_or_y][i];
y1 = [x_or_y, y_or_x][i];
x2 = x1 * (i ? 1 : -1);
y2 = y1 * (i ? -1 : 1);
// two elligible points
// with absolute coordinates
return [{
x : circle.x x1,
y : circle.y y1
}, {
x : circle.x x2,
y : circle.y y2
}];
}
}).reduce(function (acc, xys, i) {
var k, min, max;
i = i & 1; // 0 or 1
k = "xy"[i];
min = [x_left, y_top][i];
max = [x_right, y_bottom][i];
return acc.concat(xys.filter(function (xy) {
// `xy` is on the edge ? yes : no
return xy[k] >= min && xy[k] <= max;
}));
}, []);
}
// optional code
onload = function () {
var canvasEl = getEl("canvas");
var ctx = canvasEl.getContext("2d");
canvasEl.width = 400;
canvasEl.height = 300;
draw(
ctx,
readRect(),
readCircle()
);
onSubmit("form", function (ev) {
ev.preventDefault();
ctx.clearRect(
0, 0,
canvasEl.width,
canvasEl.height
);
draw(
ctx,
readRect(),
readCircle()
);
});
}
function readRect () {
var x, y, w, h;
var rectXyEl = getEl("rect-xy");
var rectWhEl = getEl("rect-wh");
[x, y] = readPair(rectXyEl);
[w, h] = readPair(rectWhEl);
return { x : x, y : y, w : w, h : h };
}
function readCircle () {
var x, y, r;
var circleXyEl = getEl("circle-xy");
var circleREl = getEl("circle-r");
[x, y] = readPair(circleXyEl);
r = parseInt(circleREl.value, 10);
return { x : x, y : y, r : r };
}
function readPair (el) {
return el.value.split(" ").map(
(x) => parseInt(x, 10)
);
}
function draw (ctx, rect, circle) {
drawRect(ctx, rect);
drawCircle(ctx, circle);
drawIntersections(ctx, rect, circle);
}
function drawRect (ctx, rect) {
ctx.beginPath();
ctx.rect(
rect.x - rect.w / 2,
rect.y - rect.h / 2,
rect.w, rect.h
);
ctx.stroke();
}
function drawCircle (ctx, circle) {
ctx.beginPath();
ctx.arc(
circle.x, circle.y,
circle.r,
0, 2 * Math.PI
);
ctx.stroke();
}
function drawIntersections (ctx, rect, circle) {
for (let xy of intersections(rect, circle)) {
ctx.beginPath();
ctx.arc(xy.x, xy.y, 3, 0, 2 * Math.PI, true);
ctx.stroke();
}
}
function onSubmit (id, f) {
getEl(id).addEventListener("submit", f);
}
function getEl (id) {
return document.getElementById(id);
}
body {
margin: .5em;
background: #ddd;
}
input[type=text] {
width: 60px;
}
input[type=submit] {
margin-top: .5em;
}
.column {
float: left;
}
.column:first-child {
background: white;
margin-right: .5em;
padding: .5em;
width: 90px;
}
<div class="column">
<form id="form">
rect x y <input
type="text"
id="rect-xy"
value="100 100"
>
rect w h <input
type="text"
id="rect-wh"
value="130 130"
>
circle x y <input
type="text"
id="circle-xy"
value="100 100"
>
circle r <input
type="text"
id="circle-r"
value="75"
>
<input type="submit">
</form>
</div>
<div class="column">
<canvas id="canvas" style="background:white"></canvas>
</div>
運算式n & 1是按位和。n它選擇基數 2 中的“最右邊”位。
> | 0 & 1 // 0b00
< | 0
> | 1 & 1 // 0b01
< | 1
> | 2 & 1 // 0b10
< | 0
> | 3 & 1 // 0b11
< | 1
你可以用它n & 1來檢查一個數字是否是奇數。
> | 4 & 1 ? "odd" : "even"
< | "even"
uj5u.com熱心網友回復:
這是一個檢查矩形坐標是否存在于圓內的簡單方法。只需使用簡單回圈增加值即可。
let rect = { x: 40, y: 100, w: 100, h: 50 }
let mycircle = { x: 156, y: 156, r: 100 }
function isInside(circle_x, circle_y, rad, x, y) {
//formula x^2 y^2=r^2
if (
(x - circle_x) * (x - circle_x) (y - circle_y) * (y - circle_y) <=
rad * rad
)
return true
else return false
}
function getIntersectionPoint(circle, rect) {
let coor = []
let notFullyInside = false
//for top
for (let index = rect.x; index < rect.x rect.w; index ) {
if (isInside(circle.x, circle.y, circle.r, index, rect.y)) {
if (notFullyInside) {
coor.push({ x: index, y: rect.y })
break
}
} else {
notFullyInside = true
}
}
notFullyInside = false
//for left
for (let index = rect.y; index < rect.y rect.h; index ) {
if (isInside(circle.x, circle.y, circle.r, rect.x, index)) {
if (notFullyInside) {
coor.push({ x: rect.x, y: index })
break
}
} else {
notFullyInside = true
}
}
notFullyInside = false
//for right
for (let index = rect.y; index < rect.y rect.h; index ) {
if (isInside(circle.x, circle.y, circle.r, rect.x rect.w, index)) {
if (notFullyInside) {
coor.push({ x: rect.x rect.w, y: index })
break
}
} else {
notFullyInside = true
}
}
notFullyInside = false
//for bottom
for (let index = rect.x; index < rect.x rect.w; index ) {
if (isInside(circle.x, circle.y, circle.r, index, rect.y rect.h)) {
if (notFullyInside) {
coor.push({ x: index, y: rect.y rect.h })
break
}
} else {
notFullyInside = true
}
}
return coor
}
console.log(getIntersectionPoint(mycircle, rect))
uj5u.com熱心網友回復:
有效實施指南:
WLOG 圓的中心是原點(如果不是你可以平移所有點)。然后假設在縱坐標 Y 和橫坐標 X0 < X1 的水平邊。
如果 Y < -R 或 Y > R,則沒有交集。
否則,檢查 X02 > R2 - Y2 和 X12 > R2 - Y2。如果兩者都為假,則該段完全在內部。如果一假一真,則有一個交集。如果兩個為真,則有兩個交集。
交叉點的縱坐標為 Y,因此橫坐標為 ±√(R2 - Y2)。根據上述內部/外部條件取負號和/或正號。(真/假是-,假/真是 ,真/真是兩者。)
重復四個側面。(您可以將水平邊的條件重用于垂直邊的條件。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/412188.html
標籤:
上一篇:獲取數字的所有整數磁區
