Closed7
多角形の内外判定
数学やり直し
外積と内積について
内外判定のプログラム例
Paizaのこのスキルアップ問題集にトライ中
単純に標準入力された値が四角形の範囲内かを見ればいいとは思うが,せっかくだから他の方法で解いてみたい
外積はなんとか出た
最初全然正負が合わず,なんでかと思ったら,四角形の頂点を反時計回りに並べていなかったからだった
気を付けないといけない......
下記サイトの記事を参考にさせてもらいました.
const n = Number(lines[0]);
const points = lines
.slice(1, n + 3)
.map((line) => line.split(" ").map(Number))
.map((points) => ({ x: points[0], y: points[1] }));
console.log(points);
const [xs, xt] = [points[n].x, points[n].y];
const [ys, yt] = [points[n + 1].x, points[n + 1].y];
const A = { x: xs, y: ys };
const B = { x: xt, y: ys };
const C = { x: xt, y: yt };
const D = { x: xs, y: yt };
const vector_AB = createVector(A, B);
const vector_BC = createVector(B, C);
const vector_CD = createVector(C, D);
const vector_DA = createVector(D, A);
let count = 0;
function cross(v1, v2) {
return v1.x * v2.y - v1.y * v2.x;
}
function createVector(a, b) {
return { x: b.x - a.x, y: b.y - a.y };
}
for (let index = 0; index < n; index++) {
let vector_AE = createVector(A, points[index]);
let vector_BE = createVector(B, points[index]);
let vector_CE = createVector(C, points[index]);
let vector_DE = createVector(D, points[index]);
let vector_cross_AB_AE = cross(vector_AB, vector_AE);
let vector_cross_BC_BE = cross(vector_BC, vector_BE);
let vector_cross_CD_CE = cross(vector_CD, vector_CE);
let vector_cross_DA_DE = cross(vector_DA, vector_DE);
console.log(
vector_cross_AB_AE,
vector_cross_BC_BE,
vector_cross_CD_CE,
vector_cross_DA_DE
);
}
符号が一つでも違うと,点は外にある,と判定できるけど,これ辺の上に点がある場合は弾かれてしまうっぽい
辺上にあっても内部判定するように修正しないといけない
そう考えると,外積より多角形の内部にある点と頂点が成す角の和が360°になるほうを採用したほうが楽なのかな 要検証ではある
外積は並行だと0になる
要は一直線上だと0なので,任意の点が辺上にあるのを確認するには,外積が0かつ,長方形の辺上内にあるかどうかを見ればよい
とりあえずPaizaでは次のコードで合格.もっとキレイに書けるとは思うけどとりあえずコレで良しとする.
rectangle.js
const n = Number(lines[0]);
const points = lines
.slice(1, n + 3)
.map((line) => line.split(" ").map(Number))
.map((points) => ({ x: points[0], y: points[1] }));
//const pointsObject = points.map((point) => ({ x: point[0], y: point[1] }));
console.log(points);
//console.log(pointsObject);
const [xs, xt] = [points[n].x, points[n].y];
const [ys, yt] = [points[n + 1].x, points[n + 1].y];
const A = { x: xs, y: ys };
const B = { x: xt, y: ys };
const C = { x: xt, y: yt };
const D = { x: xs, y: yt };
const vector_AB = createVector(A, B);
const vector_BC = createVector(B, C);
const vector_CD = createVector(C, D);
const vector_DA = createVector(D, A);
let count = 0;
function cross(v1, v2) {
return v1.x * v2.y - v1.y * v2.x;
}
function createVector(a, b) {
return { x: b.x - a.x, y: b.y - a.y };
}
function judgeOnPointsOrLines(point, min, max) {
return (
min.x <= point.x &&
point.x <= max.x &&
min.y <= point.y &&
point.y <= max.y
);
}
for (let index = 0; index < n; index++) {
let vector_AE = createVector(A, points[index]);
let vector_BE = createVector(B, points[index]);
let vector_CE = createVector(C, points[index]);
let vector_DE = createVector(D, points[index]);
let vector_cross_AB_AE = cross(vector_AB, vector_AE);
let vector_cross_BC_BE = cross(vector_BC, vector_BE);
let vector_cross_CD_CE = cross(vector_CD, vector_CE);
let vector_cross_DA_DE = cross(vector_DA, vector_DE);
// console.log(
// vector_cross_AB_AE,
// vector_cross_BC_BE,
// vector_cross_CD_CE,
// vector_cross_DA_DE
// );
if (
vector_cross_AB_AE >= 0 &&
judgeOnPointsOrLines(A, { x: xs, y: ys }, { x: xt, y: yt }) &&
vector_cross_BC_BE >= 0 &&
judgeOnPointsOrLines(B, { x: xs, y: ys }, { x: xt, y: yt }) &&
vector_cross_CD_CE >= 0 &&
judgeOnPointsOrLines(C, { x: xs, y: ys }, { x: xt, y: yt }) &&
vector_cross_DA_DE >= 0 &&
judgeOnPointsOrLines(D, { x: xs, y: ys }, { x: xt, y: yt })
) {
count++;
}
}
console.log(count);
このスクラップは2024/07/23にクローズされました