简体   繁体   中英

Drawing arrows using mouse coordinates in Processing(java)

Im working on a program that draws arrows with the mouse, so for the tip of the arrow to be pointing in the right direction Im using PVector (one for the base and one for the tip of the arrow).

I made it work so you can draw one arrow and it stays in the screen, but the second arrow and third etc are drawn in a completely wrong place. looks like the coordinates are not being passed correctly to the drawArrow() function. Does anyone know what is wrong with my approach to this problem?

PVector arrowTip = new PVector(); //for drawing arrows
PVector lineBase = new PVector(); //for drawing arrows

//save drawn arrow value for drawing saved arrows
PVector [] base = new PVector[100];
PVector [] vec = new PVector[100];
PVector vector = new PVector();
boolean drawing;
float xx,yy;


int flag=0;


void settings() {
  float hg=displayHeight/1.1;
  int wd=(int)hg*10/8;
  size(wd, (int)hg);
  drawing=false;
}

void draw() {
  background(255);

  //draw arrows
   if (flag == 1) {
   
   arrowTip.x = mouseX;
   arrowTip.y = mouseY;
   drawArrow(lineBase, arrowTip.sub(lineBase));
   }
   
  
  if (flag==1) {
    arrowTip.x = mouseX;
    arrowTip.y = mouseY;
  }
  
  //new
  drawSavedArrows();
}

//new
void drawSavedArrows() {
  for (int i =0; i<base.length; i++) {
    if (vec[i]!=null && base[i]!=null) {
      //draw saved arrow
      xx=vec[i].x;
      yy=vec[i].y;
      vector.x=xx;
      vector.y=yy;
      drawArrow(base[i], vector.sub(base[i]));//this is not working, the relative o,o coor seem to be stuck on the first one saved
    }
  }
}


void drawArrow(PVector base, PVector vector) {

  strokeWeight(height / 50);
  fill(20, 85, 30, 180);
  stroke(20, 85, 30, 180);
  translate(base.x, base.y); //set relative 0,0 coor
  line(0, 0, vector.x, vector.y); //draw line from relative 0,0 to mouse
  rotate(vector.heading());
  int arrowSize = height / 20;
  translate(vector.mag() - arrowSize, 0); //length of vec minus arrowsize relative
  triangle(0, arrowSize / 1.5, 0, -arrowSize / 1.5, arrowSize, 0);
}


void mousePressed() {
  if (mouseButton == RIGHT) //right click for drawing arrows
  {
    lineBase.x = pmouseX; //get the coor for the staring point of the arrow
    lineBase.y = pmouseY;


    //save base vector to first null
    for (int i =0; i<base.length; i++) {
      if (base[i]==null && vec[i]==null) {

        base[i] = new PVector();
        base[i].x=pmouseX;
        base[i].y=pmouseY;
        break;
      }
    }
    drawing=true;
  } else if(mouseButton == LEFT){
    for (int i=0; i<base.length; i++) {     //delete all vectors
      if (base[i]==null) {
        break;
      }
      base[i]=null; 
      vec[i]=null;
    }
  }
} 


void mouseDragged() {
  if (mouseButton == RIGHT) {
    flag = 1;
  }
}
void mouseReleased() {
  flag = 0;
  if (drawing) {
    for (int i =0; i<vec.length; i++) {
      if (vec[i]==null) {

        vec[i] = new PVector();//save coor for arrow tip
        vec[i].x=arrowTip.x;
        vec[i].y=arrowTip.y;
        break;
      }
    }
  }
  drawing=false;
}


I found out that translate is cumulative. So this:

translate(100, 300);

is the same as this:

translate(50, 150);
translate(50, 150):

What I had to do was isolate the effect of the transformation using push() and pop(). All you have to do is update your drawArrow() function like so:

 void drawArrow(PVector base, PVector vector) {
  push();
  strokeWeight(height / 50);
  fill(20, 85, 30, 180);
  stroke(20, 85, 30, 180);
  translate(base.x, base.y); //set relative 0,0 coor
  line(0, 0, vector.x, vector.y); //draw line from relative 0,0 to mouse
  rotate(vector.heading());
  int arrowSize = height / 20;
  translate(vector.mag() - arrowSize, 0); //length of vec minus arrowsize relative
  triangle(0, arrowSize / 1.5, 0, -arrowSize / 1.5, arrowSize, 0);
  pop();
}

I'd suggest making use of pushMatrix() and popMatrix() . What's happening right now is you're doing a translation and rotation for the first vector, and then you're doing another one for the second vector on top of it. pushMatrix() and popMatrix() will reset the transformation for every vector:

void drawArrow(PVector base, PVector vector) {
  strokeWeight(height / 50);
  fill(20, 85, 30, 180);
  stroke(20, 85, 30, 180);
  pushMatrix();
  translate(base.x, base.y); //set relative 0,0 coor
  line(0, 0, vector.x, vector.y); //draw line from relative 0,0 to mouse
  rotate(vector.heading());
  int arrowSize = height / 20;
  translate(vector.mag() - arrowSize, 0); //length of vec minus arrowsize relative
  triangle(0, arrowSize / 1.5, 0, -arrowSize / 1.5, arrowSize, 0);
  popMatrix();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM