Constraining PShape scale

edited April 2017 in Questions about Code

Hi all

I'm working on a project which shows a map of Northern Ireland. Right now I'm trying to work on an opening sequence where only the lough shows, and when clicked the counties grow from nothing. The problem I'm having is that everything grows from the corner, and I'm not quite sure how to constrain the scales so that the PShapes don't become larger than I need them to be.

Anyone have any advice firstly on how to scale up and down from the centre point of each PShape, and secondly how to constrain the scales?

Thanks a million!

Tagged:

Answers

  • Please share your code -- it is hard to know what you mean by "constrain the scale."

    Re:

    firstly how to scale up and down from the centre point of each PShape

    Look at shapeMode() -- e.g. shapeMode(CENTER):

    Other options if your shape data is not encoded in a centered way include using shape(s, x, y), translate(), and/or PShape.translate(). For details see previous related discussions:

    Re:

    secondly how to constrain the scales

    You could use constrain() or max().

  • PShape lough;  
    
    color loughHighlight, loughColor;
    color baseColor;
    color currentColor;
    
    boolean loughOver = false;
    boolean loughScaler = false;
    
    void setup() {  
      size(1000, 600);
      frameRate(20);
      loughColor = color(255, 0, 0);
      loughHighlight = color(255, 121, 121);
      baseColor = color(255);
      currentColor = baseColor;
    
      lough = createShape();
      lough.beginShape();
      lough.fill(loughColor);
      lough.stroke(color(0));
      lough.strokeWeight(5);
      lough.vertex(665, 298);
      lough.vertex(658, 302);
      lough.vertex(655, 330);
      lough.vertex(660, 335);
      lough.vertex(655, 345);
      lough.vertex(660, 365);
      lough.vertex(660, 380);
      lough.vertex(645, 400);
      lough.vertex(640, 420);
      lough.vertex(647, 422);
      lough.vertex(657, 422);
      lough.vertex(680, 415);
      lough.vertex(687, 419);
      lough.vertex(688, 423);
      lough.vertex(700, 422);
      lough.vertex(704, 417);
      lough.vertex(710, 410);
      lough.vertex(720, 400);
      lough.vertex(720, 373);
      lough.vertex(740, 363);
      lough.vertex(738, 353);
      lough.vertex(720, 350);
      lough.vertex(730, 310);
      lough.vertex(730, 305);
      lough.vertex(720, 305);
      lough.vertex(695, 310);
      lough.vertex(688, 308);
      lough.vertex(678, 305);
      lough.vertex(682, 300);
      lough.endShape(CLOSE);
    }
    
    void draw() {
      update(mouseX, mouseY);
      background(currentColor);
    
      if (loughOver) {
        fill(loughHighlight);
      } else {
        fill(loughColor);
      }
      shape(lough);
      if (loughScaler){
        pushMatrix();
        lough.scale(0.9);
        popMatrix();
      } else if (!loughScaler){
        pushMatrix();
        lough.scale(1.0);
        popMatrix();
      }
    }
    
    void update(int x, int y) {
      if ( overLough(650, 280, 100, 140) ) {
        loughOver = true;
      } else {
        loughOver = false;
      }
    }
    
    void mousePressed() {
      if (loughOver) {
        loughScaler = true;
      } else if (!loughOver) {
        loughScaler = false;
      }
    }
    
    boolean overLough(int x, int y, int width, int height) {
      if (mouseX >= x && mouseX <= x+width && mouseY >= y && mouseY <= y+height){
        return true;
      } else {
        return false;
      }
    }
    

    This is a simplified version of it. Right now, only the red shape shrinks down when clicked, and it shrinks into the top left corner. I'm trying to make it shrink and grow from a central point, rather than into the corner, and once I get that working, I can apply it to more shapes.

    I also want some more shapes to grow from nothing (if that makes sense) but I can only figure out how to make them keep growing, rather than stop when they've reached a maximum size.

    I'm sure there's a really simple way to do this that I've maybe missed somewhere.

    Thanks

  • The links I shared above are perfect for this situation -- your lough.vertex() coordinates aren't centered around 0,0 -- you can fix this in any of the ways mentioned (translating, or shifting the coordinates). See this thread for a detailed example of how to fix:

  • Hi Jeremy. Thanks for getting back to me. I've tried applying the code in the above example, but I've somehow ended up with a tiny square in the centre of the screen. I thought it was maybe something to do with the scale for loop, but removing it or adjusting the parameters doesn't seem to have done anything. Is there something I've missed somewhere?

    PShape lough;  
    
    color loughColor = color(255, 0, 0);
    color baseColor;
    color currentColor;
    
    //boolean loughOver = false;
    //boolean loughScaler = false;
    
    void setup() {  
      size(1000, 600);
    }
    
    void draw() {
      //update(mouseX, mouseY);
      background(255);
      translate(width/2, height/2);
      for (float scale = 1; scale > 0.4; scale -=1) {
        scale(scale);
        drawLough();
      }
    }
    
    void drawLough() {
      //lough = createShape();
      //lough.beginShape();
      fill(loughColor);
      stroke(0);
      strokeWeight(5);
      pushMatrix();
      ellipse(0, 0, 2, 2);
      // x runs from 640 to 740, y runs from 298 to 423.
      // so center is offset (740 + 640)/2 = 690 ; y = (298 + 423)/2 = 360.5.
      translate(-690, - 360.5);
      vertex(665, 298);
      vertex(658, 302);
      vertex(655, 330);
      vertex(660, 335);
      vertex(655, 345);
      vertex(660, 365);
      vertex(660, 380);
      vertex(645, 400);
      vertex(640, 420);
      vertex(647, 422);
      vertex(657, 422);
      vertex(680, 415);
      vertex(687, 419);
      vertex(688, 423);
      vertex(700, 422);
      vertex(704, 417);
      vertex(710, 410);
      vertex(720, 400);
      vertex(720, 373);
      vertex(740, 363);
      vertex(738, 353);
      vertex(720, 350);
      vertex(730, 310);
      vertex(730, 305);
      vertex(720, 305);
      vertex(695, 310);
      vertex(688, 308);
      vertex(678, 305);
      vertex(682, 300);
      popMatrix();
      //lough.endShape(CLOSE);
    }
    
  • Notice you are calling translate twice.

    Also you need to call beginShape() and endShape() when using vertex.

    Kf

  • Hi there

    Thanks to everyone for all your help. I have eventually got it scaling to a point I have defined but I had to go down a rather different route to get it working lol, by scaling and translating. As always, one problem solved is another problem gained, as my code now won't delete previous iterations of the shape. Has anyone ever encountered this before?

      PShape lough, eire;
    
    void setup() {
      size(1300, 750, P2D);
    
      eire = createShape();
      eire.beginShape();
      eire.fill(150);
      eire.stroke(color(0));
      eire.strokeWeight(1);
      eire.vertex( 746, 617);
      eire.vertex( 790, 675);
      eire.vertex( 800, 710);
      eire.vertex( 820, 715);
      eire.vertex( 825, 725);
      eire.vertex( 825, 735);
      eire.vertex( 820, height +1);
      eire.vertex( 0, height +1);
      eire.vertex( -1, -1);
      eire.vertex( 440, -1);
      eire.vertex( 480, 10);
      eire.vertex( 485, 20);
      eire.vertex( 410, 60);
      eire.vertex( 390, 130);
      eire.vertex( 390, 160);
      eire.vertex( 350, 173);
      eire.vertex( 290, 283);
      eire.vertex( 225, 305);
      eire.vertex( 210, 295);
      eire.vertex( 170, 320);
      eire.vertex( 170, 350);
      eire.vertex( 225, 368);
      eire.vertex( 203, 399);
      eire.vertex( 190, 403);
      eire.vertex( 180, 398);
      eire.vertex( 169, 400);
      eire.vertex( 162, 405);
      eire.vertex( 156, 413);
      eire.vertex( 130, 419);
      eire.vertex( 115, 425);
      eire.vertex( 115, 440);
      eire.vertex( 125, 470);
      eire.vertex( 142, 482);
      eire.vertex( 158, 505);
      eire.vertex( 180, 520);
      eire.vertex( 185, 530);
      eire.vertex( 210, 545);
      eire.vertex( 220, 580);
      eire.vertex( 240, 590);
      eire.vertex( 258, 585);
      eire.vertex( 273, 595);
      eire.vertex( 298, 630);
      eire.vertex( 330, 637);
      eire.vertex( 365, 630);
      eire.vertex( 400, 640);
      eire.vertex( 427, 633);
      eire.vertex( 421, 600);
      eire.vertex( 432, 590);
      eire.vertex( 448, 586);
      eire.vertex( 455, 554);
      eire.vertex( 445, 535);
      eire.vertex( 481, 470);
      eire.vertex( 529, 545);
      eire.vertex( 579, 592);
      eire.vertex( 600, 580);
      eire.vertex( 635, 600);
      eire.vertex( 630, 640);
      eire.vertex( 645, 655);
      eire.vertex( 705, 640);
      eire.vertex( 708, 615);
      eire.vertex( 718, 620);
    
      eire.endShape(CLOSE);
    
    
      lough = createShape();
      lough.beginShape();
      lough.fill(255, 0, 0);
      lough.stroke(color(0));
      lough.strokeWeight(5);
      lough.vertex(665, 298);
      lough.vertex(658, 302);
      lough.vertex(655, 330);
      lough.vertex(660, 335);
      lough.vertex(655, 345);
      lough.vertex(660, 365);
      lough.vertex(660, 380);
      lough.vertex(645, 400);
      lough.vertex(640, 420);
      lough.vertex(647, 422);
      lough.vertex(657, 422);
      lough.vertex(680, 415);
      lough.vertex(687, 419);
      lough.vertex(688, 423);
      lough.vertex(700, 422);
      lough.vertex(704, 417);
      lough.vertex(710, 410);
      lough.vertex(720, 400);
      lough.vertex(720, 373);
      lough.vertex(740, 363);
      lough.vertex(738, 353);
      lough.vertex(720, 350);
      lough.vertex(730, 310);
      lough.vertex(730, 305);
      lough.vertex(720, 305);
      lough.vertex(695, 310);
      lough.vertex(688, 308);
      lough.vertex(678, 305);
      lough.vertex(682, 300);
      lough.endShape(CLOSE);
    }
    
    void draw() {
      shape(eire);
      shape(lough);
    }
    
    void mousePressed() {
    
      PVector origin = new PVector(718, 363);
      // origin(665, 298); width = 105, height = 130
      //so if I wan't to center the origin, x = 665 + (105/2), y = 298 + (130/2);
    
      float scale_factor= .9;
      float s_x = ((origin.x) * scale_factor);
      float s_y = ((origin.y) * scale_factor);
      float trans_x = (origin.x - s_x);
      float trans_y = (origin.y - s_y);
    
    
      lough.scale(.9);
      lough.translate(trans_x, trans_y);
    }
    
  • Answer ✓

    I believe if you ad background(150); as the first line in setup, your current problem should be solved.

    Kf

  • Awesome, thanks for all the help everyone! Seem to have it doing what I need it to now

Sign In or Register to comment.