Как изменить цвет отдельной строки при нажатии мыши ()

#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);
    }
}