检查是否在 P5.js 中单击了圆弧
Check if an arc clicked in P5.js
在P5中检查圆是否被点击非常简单,但是我想不出用圆弧做同样的简单方法。
这就是我创建弧线的方式:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(255);
stroke(0);
strokeWeight(10);
noFill();
arc(200, 200, 200, 200, HALF_PI, PI*1.75);
}
这就是检查圆圈是否被点击的方法:
function mousePressed() {
var d = dist(mouseX, mouseY, 200,200);
var within_diam = (d<200+width/2 && d>200-width/2);
console.log('Circle clicked');
}
除了圆圈是否被点击之外,我还可以检查圆弧缺失的扇区是否被点击,但它看起来很麻烦,我很确定这应该是一种正确且简单的方法。
你可以做的是使用圆碰撞检测的公式,也许不是更好的方法,但可以完成工作。
假设您有一个圆 A(4, 5) 和一个圆 B(6, 8),因此您将应用公式:
sqrt(sqr(x) + sqr(y))
sqrt(sqr(4 − 3) + sqr(8 − 4)) = 8.062
因此在您的情况下,圆圈 A 将是您的鼠标,圆圈 B 将是固定圆圈,但您也可以将其反转。
检查下面的代码,这应该可以正常工作。
var mouseRadius = 10;
var _circle = {
x: 200,
y: 200,
r: 100
};
function setup() {
createCanvas(400, 400);
print(_circle);
}
function draw() {
background(255);
stroke(0);
strokeWeight(10);
noFill();
arc(_circle.x, _circle.y, _circle.r * 2, _circle.r * 2, HALF_PI, PI*1.75);
}
function mousePressed() {
if (isColliding(mouseX, mouseY, _circle.x, _circle.y, _circle.r + mouseRadius)) {
console.log('Circle pressed');
}
}
function isColliding(x1, y1, x2, y2, r) {
let part1 = (x1 - x2 ) * ( x1 - x2 );
let part2 = ( y1 - y2 ) * ( y1 - y2 );
if (Math.sqrt(part1 + part2) < r ) {
return true;
}
return false;
}
编辑
您可以将此功能替换为其他功能,将完成相同的工作,但此功能将使用较少的计算机进程,因为不再有 SQRT:
function isColliding(x1, y1, x2, y2, r) {
let dx = x2 - x1;
let dy = y2 - y1;
let radius = r * r;
if ((dx * dx) + (dy* dy) < radius ) {
return true;
}
return false;
}
您需要检查距离和角度。
下面的示例正确使用了距离,但角度计算不正确。
let withinAngle = angle > angleStart && angle < angleEnd;
角度值从起始角度开始增加,直到达到180度。然后角度值再次下降。我不确定为什么会这样。
var pos = { x: 200, y: 200 },
radius = 100,
size = { width: radius * 2, height: radius * 2 },
weight = 10,
angleStart = Math.PI / 2,
angleEnd = Math.PI * 1.75,
angleDiff = angleEnd - angleStart;
function setup() {
createCanvas(400, 400);
textFont('Arial', 16);
}
function draw() {
background(255);
stroke(0);
strokeWeight(weight);
//noFill();
arc(pos.x, pos.y, size.width, size.height, angleStart, angleEnd);
let origin = createVector(pos.x, pos.y);
drawArrow(origin, createVector(size.width / 2, 0), 'red');
drawArrow(origin, createVector(mouseX - pos.x, mouseY - pos.y), 'blue');
let target = createVector(mouseX - pos.x, (mouseY - pos.y) * -1);
let magnitude = dist(mouseX, mouseY, pos.x, pos.y);
let angle = origin.angleBetween(target);
strokeWeight(0);
text([
`Target: (${target.x}, ${target.y})`,
`Magnitude: ${magnitude.toFixed(3)}`,
`Radians: ${(angle / Math.PI).toFixed(3)}π`,
`Degrees: ${degrees(angle).toFixed(3)}°`
].join('\n'), 250, 20);
}
function mousePressed(e) {
let origin = createVector(pos.x, pos.y);
let target = createVector(mouseX - pos.x, (mouseY - pos.y) * -1);
if (checkBounds(origin, target)) {
console.log('Circle stroke clicked');
}
}
// Check to see if the click was within the stroke weight.
// There is no angle check in here...
function checkBounds(origin, target) {
let magnitude = dist(mouseX, mouseY, size.width, size.height);
let withinDist = magnitude > radius && magnitude < radius + weight;
let angle = origin.angleBetween(target);
let withinAngle = angle > angleStart && angle < angleEnd;
return withinDist && withinAngle;
}
/** https://p5js.org/reference/#/p5.Vector/angleBetween */
function drawArrow(base, vec, myColor) {
push();
stroke(myColor);
strokeWeight(3);
fill(myColor);
translate(base.x, base.y);
line(0, 0, vec.x, vec.y);
rotate(vec.heading());
let arrowSize = 7;
translate(vec.mag() - arrowSize, 0);
triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
pop();
}
.as-console-wrapper { height: 80px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
在P5中检查圆是否被点击非常简单,但是我想不出用圆弧做同样的简单方法。
这就是我创建弧线的方式:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(255);
stroke(0);
strokeWeight(10);
noFill();
arc(200, 200, 200, 200, HALF_PI, PI*1.75);
}
这就是检查圆圈是否被点击的方法:
function mousePressed() {
var d = dist(mouseX, mouseY, 200,200);
var within_diam = (d<200+width/2 && d>200-width/2);
console.log('Circle clicked');
}
除了圆圈是否被点击之外,我还可以检查圆弧缺失的扇区是否被点击,但它看起来很麻烦,我很确定这应该是一种正确且简单的方法。
你可以做的是使用圆碰撞检测的公式,也许不是更好的方法,但可以完成工作。
假设您有一个圆 A(4, 5) 和一个圆 B(6, 8),因此您将应用公式:
sqrt(sqr(x) + sqr(y))
sqrt(sqr(4 − 3) + sqr(8 − 4)) = 8.062
因此在您的情况下,圆圈 A 将是您的鼠标,圆圈 B 将是固定圆圈,但您也可以将其反转。 检查下面的代码,这应该可以正常工作。
var mouseRadius = 10;
var _circle = {
x: 200,
y: 200,
r: 100
};
function setup() {
createCanvas(400, 400);
print(_circle);
}
function draw() {
background(255);
stroke(0);
strokeWeight(10);
noFill();
arc(_circle.x, _circle.y, _circle.r * 2, _circle.r * 2, HALF_PI, PI*1.75);
}
function mousePressed() {
if (isColliding(mouseX, mouseY, _circle.x, _circle.y, _circle.r + mouseRadius)) {
console.log('Circle pressed');
}
}
function isColliding(x1, y1, x2, y2, r) {
let part1 = (x1 - x2 ) * ( x1 - x2 );
let part2 = ( y1 - y2 ) * ( y1 - y2 );
if (Math.sqrt(part1 + part2) < r ) {
return true;
}
return false;
}
编辑
您可以将此功能替换为其他功能,将完成相同的工作,但此功能将使用较少的计算机进程,因为不再有 SQRT:
function isColliding(x1, y1, x2, y2, r) {
let dx = x2 - x1;
let dy = y2 - y1;
let radius = r * r;
if ((dx * dx) + (dy* dy) < radius ) {
return true;
}
return false;
}
您需要检查距离和角度。
下面的示例正确使用了距离,但角度计算不正确。
let withinAngle = angle > angleStart && angle < angleEnd;
角度值从起始角度开始增加,直到达到180度。然后角度值再次下降。我不确定为什么会这样。
var pos = { x: 200, y: 200 },
radius = 100,
size = { width: radius * 2, height: radius * 2 },
weight = 10,
angleStart = Math.PI / 2,
angleEnd = Math.PI * 1.75,
angleDiff = angleEnd - angleStart;
function setup() {
createCanvas(400, 400);
textFont('Arial', 16);
}
function draw() {
background(255);
stroke(0);
strokeWeight(weight);
//noFill();
arc(pos.x, pos.y, size.width, size.height, angleStart, angleEnd);
let origin = createVector(pos.x, pos.y);
drawArrow(origin, createVector(size.width / 2, 0), 'red');
drawArrow(origin, createVector(mouseX - pos.x, mouseY - pos.y), 'blue');
let target = createVector(mouseX - pos.x, (mouseY - pos.y) * -1);
let magnitude = dist(mouseX, mouseY, pos.x, pos.y);
let angle = origin.angleBetween(target);
strokeWeight(0);
text([
`Target: (${target.x}, ${target.y})`,
`Magnitude: ${magnitude.toFixed(3)}`,
`Radians: ${(angle / Math.PI).toFixed(3)}π`,
`Degrees: ${degrees(angle).toFixed(3)}°`
].join('\n'), 250, 20);
}
function mousePressed(e) {
let origin = createVector(pos.x, pos.y);
let target = createVector(mouseX - pos.x, (mouseY - pos.y) * -1);
if (checkBounds(origin, target)) {
console.log('Circle stroke clicked');
}
}
// Check to see if the click was within the stroke weight.
// There is no angle check in here...
function checkBounds(origin, target) {
let magnitude = dist(mouseX, mouseY, size.width, size.height);
let withinDist = magnitude > radius && magnitude < radius + weight;
let angle = origin.angleBetween(target);
let withinAngle = angle > angleStart && angle < angleEnd;
return withinDist && withinAngle;
}
/** https://p5js.org/reference/#/p5.Vector/angleBetween */
function drawArrow(base, vec, myColor) {
push();
stroke(myColor);
strokeWeight(3);
fill(myColor);
translate(base.x, base.y);
line(0, 0, vec.x, vec.y);
rotate(vec.heading());
let arrowSize = 7;
translate(vec.mag() - arrowSize, 0);
triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
pop();
}
.as-console-wrapper { height: 80px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>