При рисовании текстовых полей на карте отображаются все поля одновременно, а не одно поле - PullRequest
0 голосов
/ 10 июля 2020

Обычно у меня есть карта с городами на ней, у каждого города своя долгота и широта. У меня есть файл excell, который содержит население каждого города, которое необходимо отображать в текстовом поле при нажатии на поле. У меня проблема с отображением всех данных сразу, и только одно поле на карте доступно для щелчка, хотя у меня есть код для нескольких городов.

PImage img;
// variables for moving image around
int updown = 0;
int leftright = 0;
int radius = 10, direction, directionX=1, directionY=0;

PVector pos2D = new PVector();

// variables for using the mouse to navigate around the sphere
float rotx = PI/4;
float roty = PI/4;
float xcoord, ycoord;
float rotateX, rotateY, camX, camY, camZ;
float x=20, y=20;
float speed=0.5;

String[][] data;

// variables to enable zooming with mouse wheel
float wheelCount = 0;
float mwX = 0;
float mwY = 0;
float zoom = 1;

int screen = 0; // variable for different screens

boolean drawText = false;

void setup() {
  size(800, 600, P3D);
  img = loadImage("uk-admin.jpg");
  textSize(12);
  smooth();
  noStroke();
  String[] lines = loadStrings("Data.csv"); // reads contents of files
  println("There are " + lines.length + " lines");   
  String[] header = split(lines[0], ','); // seperates data
  println(String.join("   ", header)); // joins all headers
  data = new String[lines.length-1][header.length-1]; // checks the columns and rows
  for (int i = 1 ; i < lines.length; i++) {
        String[] dataStr = split(lines[i], ',');
        data[i-1] = dataStr;
        println(String.join("  ", dataStr));
    }
}

void draw() {
background(0);
noStroke();

beginCamera();
camera(width/2.0, height/2.0, (height/2.0) / tan(PI*30.0 / 180.0), width/2.0, height/2.0, 0, 0, 1, 0);
translate(leftright,updown);
endCamera();

//changes position
  x=x+speed*directionX;
  y=y+speed*directionY;
  
  //checks boundaries
  if ((x>width-radius) || x<radius)
  {
    directionX=-directionX;
  }
  if ((y>height-radius) || (y<radius))
  {
    directionY=-directionY;
  }
  
  if(direction==1)
  rect(x, y, 20, 20);
  
  imageMode(CENTER);
  
  translate(camX, camY, camZ);
  translate(width/2.0-camX, height/2.0-camY);
  rotateY(rotateY);
  rotateX(rotateX);
  translate(-(width/2.0-camX), -(height/2.0-camY));


// sets zooming level for mousewheel
if (wheelCount != 0) {
    mwX=mouseX;
    mwY=mouseY;
    zoom-=wheelCount/50;
    wheelCount = 0; 
}
translate(mwX, mwY);
scale(zoom);
translate(-(mwX), -(mwY));
translate(width / 2, height / 2, 340);

// 1991 map
if(screen == 0) {
    fill(255);
    textSize(12); 
    text("1891", 100, -80, 0);

beginShape();
texture(img);
vertex(-100, -100, 0, 0, 0);
vertex(100, -100, 0, img.width, 0);
vertex(100, 100, 0, img.width, img.height);
vertex(-100, 100, 0, 0, img.height);
endShape();

//frankfurt
pushMatrix();
fill(0); 
translate(55, 75);
box (2, 2, 2);
pos2D.set(screenX(0, 0), screenY(0, 0));
popMatrix(); 

if ( dist(mouseX, mouseY, pos2D.x, pos2D.y)<60 ) {
    cursor(HAND);
 }else {
    cursor(ARROW);
 }
    if (drawText) {
      fill(#000000);
      textSize(12);
      text("6.715.769", 55, 75);
    }
  
//berlin
pushMatrix();
fill(0);
translate(32, 51);
box (2, 2, 2);
pos2D.set(screenX(0, 0, 0), screenY(0, 0, 0));
popMatrix(); 

if ( dist(mouseX, mouseY, pos2D.x, pos2D.y)<60 ) {
    cursor(HAND);
 }else {
    cursor(ARROW);
 }
    if (drawText) {
      fill(#000000);
      textSize(12);
      text("965.928", 27, 59);
    }

// dortmund
pushMatrix();
fill(0);
textSize(12); 
translate(12, -29);
box (2, 2, 2);
pos2D.set(screenX(0, 0, 0), screenY(0, 0, 0));
popMatrix();

if ( dist(mouseX, mouseY, pos2D.x, pos2D.y)<60 ) {
    cursor(HAND);
 }else {
    cursor(ARROW);
 }
    if (drawText) {
      fill(#000000);
      textSize(12);
      text("NO DATA", 12, -29);
      textSize(12);
    }

}
// 1901 map
if(screen == 1) {
    //shows 2001 data
     fill(248, 255, 6);
    text("2001", 100, -80, 0);

beginShape();
texture(img);
vertex(-100, -100, 0, 0, 0);
vertex(100, -100, 0, img.width, 0);
vertex(100, 100, 0, img.width, img.height);
vertex(-100, 100, 0, 0, img.height);
endShape();

//reading
pushMatrix();
fill(204, 0, 0, 151);
translate(42, 75, 0);
box (5, 5, 10);
popMatrix();

//Manchester
pushMatrix();
fill(204, 0, 0, 151);
translate(34, 86, 0);
box (5, 5, 10);
popMatrix();

// London
pushMatrix();
fill(204, 0, 0, 151);
translate(28, 65, 0);
box (5, 5, 10);
popMatrix();

}

//2001 map
if(screen == 2) {
    //shows 2011 data
    fill(248, 255, 6);
    text("2011", 100, -80, 0);
    
beginShape();
texture(img);
vertex(-100, -100, 0, 0, 0);
vertex(100, -100, 0, img.width, 0);
vertex(100, 100, 0, img.width, img.height);
vertex(-100, 100, 0, 0, img.height);
endShape();

// Las Vegas
pushMatrix();
fill(204, 0, 0, 151);
translate(55, 75, 0);
box (5, 5, 10);
popMatrix();

//LA
pushMatrix();
fill(204, 0, 0, 151);
translate(32, 51, 0);
box (5, 5, 10);
popMatrix();

//new york
pushMatrix();
fill(204, 0, 0, 151);
translate(30, 29, 0);
box (5, 5, 10);
popMatrix();
}

}


void keyPressed() {
  if (key == CODED) {
    if (keyCode == UP) { // moves camera up
      updown = updown+30;
    } else if (keyCode == DOWN) { // moves camera down
      updown = updown-30;
    } else if (keyCode == RIGHT) { // moves camera right
      leftright = leftright-30;
    } else if (keyCode == LEFT) { // moves camera left
      leftright = leftright+30;
    }
    
  }
}

void mouseWheel(MouseEvent event) {
  wheelCount = event.getCount();
}

  //allows button click to switch between scenes.
void mousePressed(MouseEvent event) {
  if (mouseButton == RIGHT) {
    screen = (screen + 1) % 3;
    }
    if (event.getCount() == 1) {  // detect double click
    if (mouseButton == LEFT && dist(mouseX,mouseY, pos2D.x, pos2D.y)<60) {
    drawText = ! drawText;
  }
}
}
void mouseDragged() {
  if (mouseButton == RIGHT) {
    rotateY += (pmouseX - mouseX)*0.01;
    rotateX += (pmouseY - mouseY)*0.01;
  } if (mouseButton == LEFT) {
    camX -= (pmouseX - mouseX);
    camY -= (pmouseY - mouseY);
  } 
}

По какой-то причине только поле для Берлина кликабельна, остальное - нет. Когда я нажимаю на Берлин на карте, отображаются данные для всех городов, в которые добавлен указанный выше фрагмент кода. Мне нужно иметь возможность фильтровать по городам, например, я нажимаю Берлин, поэтому появляются только данные по Берлину. Что я делаю не так?

1 Ответ

2 голосов
/ 10 июля 2020

Причина, по которой все текстовые поля появляются при нажатии, заключается в том, что у вас есть только одна переменная drawText, которая определяет для каждого города, показывать ли текст или нет. В очень упрощенном виде у вас есть следующее:

boolean drawText = false;

void draw() {

    // code for city 1...
    if (drawText) {
        // show text box for city 1
    }
    
    // code for city 2...
    if (drawText) {
        // show text box for city 2
    }
    
    // and so on
    
}

void mousePressed(MouseEvent event) {
    
    // if left click...
    drawText = !drawText;
    
}

Либо drawText истинно или ложно, и если это правда, то для каждого города текст будет показан. У вас нет отдельного логического значения для каждого города.

Тогда причина, по которой работает только один из ваших блоков, и, вероятно, также причина, по которой вы неправильно поняли, какой из них будет показан, заключается в этой части:

if (mouseButton == LEFT && dist(mouseX,mouseY, pos2D.x, pos2D.y)<60) {
    drawText = ! drawText;
}

Этот if проверяет, меньше ли расстояние мыши до координат pos2D 60. Но поскольку вы обновляете pos2D с каждым городом, все города просто создаются в одном большой блок кода, это проверяет только расстояние до последнего добавляемого города, где обновляется pos2D (Дортмунд). Упрощенно то, что вы делаете, можно сравнить со следующим:

int test = 0;
int input = 10;

void draw() {
    
    // first
    test = 1;
    if (input == test)
        // do something
    
    // second
    test = 2;
    if (input == test)
        // do something
    
    // and so on until...
    
    // tenth
    test = 10;
    if (input == test)
        //do something

}

void mouseClicked(MouseEvent event) {
    
    // set input based on something from mouse...
    input = getMouseInput(event);
    
    if (input == test)
        drawText = !drawText;
    
}

Вышеупомянутое приведено только для иллюстрации. Внимательно проверьте его и подумайте, что будет, если вы позвоните по номеру draw(), а затем mouseClicked(). Какое значение будет иметь test? Если test представляет какой-то город, для какого из них переменная drawText когда-либо будет изменена? Может ли он работать для других значений?

Основная проблема с вашим кодом заключается в том, что вы используете глобальные переменные, такие как drawText и pos2D, которые затем меняются разными методами. У вас есть несколько городов, но каждый город зависит от одной переменной, отображающей ли его текстовое поле, и каждый город зависит от одной переменной для позиции.

Java - это объектно-ориентированный язык. Для решения подобных проблем такой язык использует классы для моделирования данных и поведения, а затем создает объекты как экземпляры таких классов. В вашем случае было бы полезно, если бы у вас был класс «Город», который имеет свои собственные данные и может реагировать на щелчки мыши. Вот краткий набросок, который поможет вам начать:

public class City {

    private final int xCoordinate;
    private final int yCoordinate;
    private final String text;
    private boolean drawText;
    
    public City(int xCoord, int yCoord, String boxText) {
        this.xCoordinate = xCoord;
        this.yCoordinate = yCoord;
        this.text = boxText;
        drawText = false;
    }
    
    public void draw() {
        pushMatrix();
        fill(0);
        translate(xCoordinate, yCoordinate);
        
        // and further methods needed for rendering
        // ...
        
        if (drawText) {
            fill(#000000);
            textSize(12);
            text(text, xCoordinate, yCoordinate);
        }
    }
    
    public boolean isMouseOnCity(int mouseX, int mouseY) {
        return dist(mouseX, mouseY, xCoordinate, yCoordinate) < 60;
    }   
    
}

Затем вы должны создать объект City, например City dortmund = new City(12, -29, "NO DATA");. Методы могут быть вызваны в городе для выполнения logi c, внесения изменений в данные или получения результата. Например, dortmund.isMouseOnCity(mouseX, mouseY) может проверить, находится ли для данных координат мыши курсор над Дортмундом или нет. Метод dortmund.draw() позаботится только о рисовании данных для этого города на основе значений его собственных переменных. Ключевым моментом является то, что координаты города, отображаемый текст и показывать ли текст теперь local для экземпляра города.

Проведите небольшое исследование, как спроектировать правильный объект- ориентированный код в Java, а затем примените его к своему коду. Я подозреваю, что вы либо пришли из опыта императивного программирования (например, C), либо совсем новичок в программировании, поэтому может потребоваться время, чтобы изучить лучшие способы делать что-то в другой парадигме.

...