Why my class doesn't work?!

Hello,

I’d like to deform a text according to an attractor encapsulated into a class, but it doesn’t work! Why?
What is wrong with my constructor?
Thanks a lot in advance for your help.
Best,
L

import processing.pdf.*;
import geomerative.*;

int x, y;
String [] message={"music is like a mountain path,", "once at the top", "you come down", "then go up again"};
color textColor=0;
RFont f;
RShape gShape; 

float fontSize=110;
int splitGlyph = 120;
String fontName="FreeSans.ttf";

RPoint[][] pointsP;
float r = random(5, 20);
WordAttractor attractorW;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  size(1920, 1080);
  RG.init(this);


  for (int i =0; i<message.length; i++) {
    f = new RFont("FreeSans.ttf", int( fontSize), LEFT); 
    pointsP= new RPoint [message[i].length()][splitGlyph];
    RGroup myGroup = f.toGroup(message[i]);
    myGroup = myGroup.toPolygonGroup();
    pointsP[i]=myGroup.getPoints();
  }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void draw() {

  background(0);
  // fill(0,100);
  //rect(0,0,width,height);
  smooth();
  pushMatrix();
  translate(100, 50);


  for (int l=0; l<message.length; l++) {
    if (l==0) {   
      rotate(PI/20);
    } else if (l==1) {
      rotate(-PI/10);
      translate(0, 250);
    } else if (l==2) {
      rotate(PI/15);
    } else if (l==3) {
      translate(700, 50);
      rotate(PI/-15);
    }
    pointsP=new RPoint [message.length][splitGlyph];
    translate(0, l+1*150);
    pointsP= new RPoint [message[l].length()][splitGlyph];

    RShape [] gShape = new RShape [message.length];
    //get grouped lettershapes from RFont    
    gShape [l] = f.toShape(message[l]); 
    //get the PShape[] containing all the single letters as RShapes. Each letter = children
    RShape[]letterShapes = gShape[l].children;

    //Number of childrens --> number of letters
    int tChildCount = gShape[l].children.length;
    //int tChildrenCount = gShape[1].children.length;
    //println(l);
    for (int k = 0; k < tChildCount; k++) { 
      RShape tShape = letterShapes[k];

      // Calculate distance between mouseX position and the center of each character
      float dx= dist(mouseX, 0, gShape[l].children[k].getCenter().x, 0);
      //Scale each character according to its distance with mouseX
      if (l==0) {
        gShape[l].children[k].scale(1.2, gShape[l].children[k].getCenter());
        gShape[l].children[k].translate(gShape[l].children[k].getCenter().x*0.3, gShape[l].children[k].getCenter().y);
      } else if (l==1) {
        gShape[l].children[k].scale(0.9, gShape[l].children[k].getCenter());
      } else if (l==2) {
        gShape[l].children[k].scale(1.4, gShape[l].children[k].getCenter());
        gShape[l].children[k].translate(gShape[l].children[k].getCenter().x*0.5, gShape[l].children[k].getCenter().y);
      } else if (l==3 && k>5) {

        gShape[l].children[k].scale(1.9, gShape[l].children[k].getCenter());
        gShape[l].children[k].translate(-230+gShape[l].children[k].getCenter().x*0.6, gShape[l].children[k].getCenter().y);
      }
      float sx= map(dx, 0, 100, 3, 1);
      float r= map(dx, 0, 100, 0, -TWO_PI);
      if (dx<100 && mouseY<350 && l==0 ) {
        gShape[l].children[k].scale(sx, gShape[l].children[k].getCenter());
        gShape[l].children[k].rotate(r, gShape[l].children[k].getCenter());
      } else if (dx<100 && mouseY>350 && mouseY<550 && l==1 ) {
        gShape[l].children[k].scale(sx, gShape[l].children[k].getCenter());
        gShape[l].children[k].rotate(r, gShape[l].children[k].getCenter());
      } else if (dx<100 && mouseY>550 && mouseY<750 && l==2 ) {
        gShape[l].children[k].scale(sx, gShape[l].children[k].getCenter());
        gShape[l].children[k].rotate(r, gShape[l].children[k].getCenter());
      } else if (dx<100 && mouseY>750 && l==3 ) {
        // gShape[l].children[k].scale(sx, gShape[l].children[k].getCenter());
        // gShape[l].children[k].rotate(r, gShape[l].children[k].getCenter());
      }

      for (int j=0; j<splitGlyph; j++) {
        float frac=(1.0/splitGlyph);  
        pointsP[k][j]=gShape[l].children[k].getPoint(j*frac);
        RPoint topLeft = tShape.getTopLeft();
        RPoint bottomRight = tShape.getBottomRight();
        bottomRight.x +=30;

        if (l==0) { 
          //attractorW= new WordAttractor(mouseX, -20, pointsP);
          //attractorW.attract();
        }
        /*RPoint position = new RPoint(mouseX, -20);
         float d=pointsP[k][j].dist(position);
         RPoint desired = new RPoint (pointsP[k][j]);
         desired.sub(position);
         desired.normalize();
         desired.scale(map(d, 0, 150, 50, 0));
         pointsP[k][j].add(desired);*/


        stroke(255);
        pushMatrix(); 
        translate( pointsP[k][j].x, pointsP[k][j].y);
        beginShape();
        noFill();
        strokeWeight(1);
        float angle = TWO_PI/18;
        rotate(j/angle+mouseX/500*noise(pointsP[k][j].x));
        bezier(-5*(noise(5)), 5, -10*(noise(2)), 5, -5*noise(10), -5, 5, -5);
        endShape();
        popMatrix();
      }
    }
  }
  popMatrix();
}

class WordAttractor {

  float force_radious = 100;
  float maxForce = 12;
  RPoint position;
  RPoint [][] pointsP;

  WordAttractor(float x, float y,RPoint [][]p ) {
    pointsP = p;
    position = new RPoint(x, y);
  }

  void attract() {
    for (int i =0; i<pointsP.length; i++) {
      for (int j =0; j<pointsP[i].length; j++) { 
        float d= pointsP[i][j].dist(position);
        if (d < force_radious) {   
          RPoint desired = new RPoint(pointsP[i][j]);
          desired.sub(position);
          desired.normalize();
          desired.scale(map(d, 0, force_radious, maxForce, 0));
          pointsP[i][j].add(desired);
        }
      }
    }
  }
}

Have you tried debugging your code? Which line of code is behaving differently from what you expected? Can you try to narrow the problem down to a smaller example program? (For example if your problem is not related to loading font files, please don’t include the code that loads a font file.)

1 Like

Dear @Kevin,

Thanks for your reply.
Here is below a smaller example program. I tried to debugg and to narrow down the mistake. Lines 61-62 don’t work like expect. I’d like the WordAttractor to repell the bezier curves of each letterThe error is inside the class :“the constructor is undefined”. Where am I wrong ?
Thank you for your help!
Best,
L

import geomerative.*;

int x, y;
String [] message={"music is like a mountain path"};
color textColor=0;
RFont f;
RShape gShape; 
float fontSize=110;
int splitGlyph = 120;
RPoint[][] pointsP;
float r = random(5, 20);
WordAttractor attractorW;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  size(1920, 1080);
  RG.init(this);
    f = new RFont("FreeSans.ttf", int( fontSize), LEFT); 
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void draw() {

  background(0);
  smooth();
  pushMatrix();
  for (int l=0; l<message.length; l++) {
    translate(200, height/2);
    pointsP= new RPoint [message[l].length()][splitGlyph];

    RShape [] gShape = new RShape [message.length];
    //get grouped lettershapes from RFont    
    gShape [l] = f.toShape(message[l]); 
    //get the PShape[] containing all the single letters as RShapes. Each letter = children
    RShape[]letterShapes = gShape[l].children;
    //Number of childrens --> number of letters
    int tChildCount = gShape[l].children.length;
    //int tChildrenCount = gShape[1].children.length;
    for (int k = 0; k < tChildCount; k++) { 
      RShape tShape = letterShapes[k];

      // Calculate distance between mouseX position and the center of each character
      float dx= dist(mouseX, 0, gShape[l].children[k].getCenter().x, 0);
      //Scale each character according to its distance with mouseX
      float sx= map(dx, 0, 100, 3, 1);
      float r= map(dx, 0, 100, 0, -TWO_PI);
      if (dx<100 && mouseY > height/2-100 && mouseY<height/2+100 && l==0 ) {
        gShape[l].children[k].scale(sx, gShape[l].children[k].getCenter());
        gShape[l].children[k].rotate(r, gShape[l].children[k].getCenter());
      }
      for (int j=0; j<splitGlyph; j++) {
        float frac=(1.0/splitGlyph);  
        pointsP[k][j]=gShape[l].children[k].getPoint(j*frac);
        RPoint topLeft = tShape.getTopLeft();
        RPoint bottomRight = tShape.getBottomRight();
        bottomRight.x +=30;
       
        attractorW= new WordAttractor(mouseX, mouseY,pointsP[k][j]);
        attractorW.attract();

        /*RPoint position = new RPoint(mouseX, -20);
         float d=pointsP[k][j].dist(position);
         RPoint desired = new RPoint (pointsP[k][j]);
         desired.sub(position);
         desired.normalize();
         desired.scale(map(d, 0, 150, 50, 0));
         pointsP[k][j].add(desired);*/

        stroke(255);
        pushMatrix(); 
        translate( pointsP[k][j].x, pointsP[k][j].y);
        beginShape();
        noFill();
        strokeWeight(1);
        float angle = TWO_PI/18;
        rotate(j/angle+mouseX/500*noise(pointsP[k][j].x));
        bezier(-5*(noise(5)), 5, -10*(noise(2)), 5, -5*noise(10), -5, 5, -5);
        endShape();
        popMatrix();
      }
    }
  }
  popMatrix();
}

class WordAttractor {

  float force_radious = 100;
  float maxForce = 12;
  RPoint position;
  RPoint [][] points;

  WordAttractor(float x, float y, RPoint [][]p ) {
    points = p;
    position = new RPoint(x, y);
  }

  void attract() {
    for (int i =0; i<pointsP.length; i++) {
      for (int j =0; j<pointsP[i].length; j++) {
        float d= points[i][j].dist(position);
        if (d < force_radious) {   
          RPoint desired = new RPoint(points[i][j]);
          desired.sub(position);
          desired.normalize();
          desired.scale(map(d, 0, force_radious, maxForce, 0));
          points[i][j].add(desired);
        }
      }
    }
  }
}

Look at your constructor here:

WordAttractor(float x, float y, RPoint [][]p ) {

This constructor expects a float argument, another float argument, and a 2D RPoint array argument.

But this is how you’re calling it:

attractorW= new WordAttractor(mouseX, mouseY,pointsP[k][j]);

The third parameter is supposed to be a 2D array, but you’re passing it a single element from a 2D array.

Taking a step back, I strongly encourage you to work in smaller steps. This is a lot of code to debug. Instead of writing your entire program and then trying to run it, try to write one small part at a time. Then it’s much easier to catch bugs like this. Good luck.

3 Likes

Stupid answer, but its worth a try: did you sav the file where you wrote your class?
I always forget to save :crazy_face:

1 Like

Thanks for reply @Kevin,
so if I understand I must put :

attractorW= new WordAttractor(mouseX, mouseY,pointsP[k][j]);

inside a loop for a 2D array?!

Yep!! I did it thanks for thinking about this option :stuck_out_tongue_winking_eye:

1 Like

Yes u r true @Kevin, I went too fast and was too tired

WordAttractor(float x, float y, RPoint p ) {
attractorW= new WordAttractor(mouseX, -20,pointsP[k][j]);

That way it works perfectly! Thanks a lot for your help and pedagogical approach, I really appreciate. !:grin: Best wishes, L

Dear Kevin,
I have a more complex question: how should I proceed to keep the deformation produced by the attractor on the text ?! Now once the attractor is more than a 100px away from the letter the letter get back ist original shape. Should I create a function outside draw()?!
Thanks in advance.
Best,
L