#java #processing
#java #обработка
Вопрос:
У меня есть этот небольшой фрагмент кода для прототипа.
Я пытаюсь сделать так, чтобы при нажатии мыши () или при нажатии мыши () цвет строки, на которую нажата кнопка, менялся.
Я не могу ни за что в этом разобраться!
Любая помощь будет высоко оценена!
Код, который мне пока удалось написать, приведен ниже, он должен работать нормально.
int value = 0;
ArrayList<Line> l = new ArrayList<Line>();
void setup() {
size(500,500);
background(57, 76, 222);
//noLoop();
stroke(255);
strokeWeight(3);
}
void draw() {
for (int i = 1; i< 20; i ) {
l.add(new Line());
for (int a=0; a< l.size(); a ){
l.get(a).display();
noLoop();
}
}
int total = l.size();
println("The total number of lines is: " total);
}
class Line {
int ranX1, ranX2, ranY1, ranY2;
Line() {
ranX1 = int(random(50,450));
ranX2 = int(random(50,450));
ranY1 = int(random(50,450));
ranY2 = int(random(50,450));
}
void update() {
//
}
void display() {
line(ranX1,ranX2,ranY1,ranY2);
}
}
Комментарии:
1. На вашем месте я бы начал с поиска в Google «обнаружение столкновения сегментов точечной линии» или «определить, находится ли точка рядом с сегментом линии» или что-то подобное.
Ответ №1:
Если у вас есть линия, заданная точкой ( O
) и направлением ( D
), то ближайшая точка на линии к точке p может быть вычислена следующим образом
X = O D * dot(P-O, D);
Скалярное произведение 2 векторов равно косинусу угла между 2 векторами, умноженному на величину (длину) обоих векторов.
dot( A, B ) == | A | * | B | * cos( alpha )
Скалярное произведение V
и D
равно косинусу угла между линией ( O
, D
) и вектором V = P - O
, умноженному на величину (длину) V
, потому D
что является единичным вектором (длина D
равна 1.0).
Используется PVector
для получения направления от ( ranX1
, ranY1
) до ( ranX2
, ranY2
) и преобразования вектора направления в единичный вектор by .normalize()
. Длина вектора проверяется с помощью .mag()
:
PVector D = new PVector(ranX2 - ranX1, ranY2 - ranY1);
if ( D.mag() > 0.0 )
D.normalize();
Используйте приведенный выше алгоритм для вычисления нормального расстояния до бесконечной строки, где 0 точки ( ranX1
, ranY1
) и ( ranX2
, ranY2
) находятся на. Для этого используются методы .mult()
, .add()
, .dist()
и .dot()
:
PVector X = new PVector(ranX1, ranY1);
X.add( D.mult( D.dot( vP1 ) ) );
boolean hit = X.dist(new PVector(x, y)) < hit_dist;
Используйте скалярное произведение, чтобы проверить, находится ли точка пересечения ( X
) линии и нормальной линии через точку an ( x
, y
) между ( ranX1
, ranY1
) и ( ranX2
, ranY2
) . Скалярное произведение меньше 0,0, если угол между двумя полотнищами больше 90 градусов или меньше -90 градусов:
PVector vP1 = new PVector(x - ranX1, y - ranY1);
if ( D.dot( vP1 ) < 0.0 )
hit = false;
PVector vP2 = new PVector(x - ranX2, y - ranY2);
if ( D.dot( vP2 ) > 0.0 )
hit = false;
Добавьте в класс метод isHit
Line
, который проверяет, находится ли в строке позиция ввода ( x
, y
). Приемлемая точность для определения щелчка по строке может быть установлена hit_dist
. Уменьшите это значение, если строка должна быть точно задана. Увеличьте его, чтобы разрешить попадание рядом, но и рядом со строкой. Добавьте атрибут color col
и метод, который может изменять цвет:
class Line {
// [...]
color col;
// [...]
void setColor(color c) {
col = c;
}
boolean isHit(int x, int y) {
final int hit_dist = 5;
// [...]
return hit;
}
}
Используйте событие нажатия мыши mousePressed()
для обхода всех строк в цикле. Изменение цвета каждой строки — это 2hit» с помощью мыши при нажатии мыши:
void mousePressed() {
for (int i = 0; i < l.size(); i) {
if (l.get(i).isHit(mouseX, mouseY)) {
l.get(i).setColor(color(255, 0, 0) );
}
}
}
Смотрите пример, в котором реализован алгоритм и внесены некоторые дополнительные улучшения и исправления ошибок в ваш код:
int value = 0;
ArrayList<Line> l = new ArrayList<Line>();
void setup() {
size(500,500);
for (int i = 0; i < 20; i) {
l.add(new Line());
}
}
void draw() {
background(57, 76, 222);
strokeWeight(3);
for (int i = 0; i < l.size(); i) {
l.get(i).display();
}
}
void mousePressed() {
for (int i = 0; i < l.size(); i) {
if (l.get(i).isHit(mouseX, mouseY)) {
l.get(i).setColor(color(255, 0, 0) );
}
}
}
class Line {
int ranX1, ranX2, ranY1, ranY2;
color col;
Line() {
col = color(255);
ranX1 = int(random(50,450));
ranX2 = int(random(50,450));
ranY1 = int(random(50,450));
ranY2 = int(random(50,450));
}
void setColor(color c) {
col = c;
}
boolean isHit(int x, int y) {
final int hit_dist = 5;
PVector D = new PVector(ranX2 - ranX1, ranY2 - ranY1);
if ( D.mag() > 0.0 )
D.normalize();
PVector vP1 = new PVector(x - ranX1, y - ranY1);
if ( D.dot( vP1 ) < 0.0 )
return false;
PVector vP2 = new PVector(x - ranX2, y - ranY2);
if ( D.dot( vP2 ) > 0.0 )
return false;
PVector X = new PVector(ranX1, ranY1);
X.add( D.mult( D.dot( vP1 ) ) );
boolean hit = X.dist(new PVector(x, y)) < hit_dist;
return hit;
}
void display() {
stroke(col);
line(ranX1, ranY1, ranX2, ranY2);
}
}