CP5 controls: Slider where for each increment, do something

edited July 2016 in Library Questions

Lets say I'm stretching a line from point a to point b based on a slider value. At the moment, all pixels between point a and b are stretched equally (where the new width is squared and divided by 100):

         sliderValue= (int)(theEvent.controller().value());
            a = (int) (pow( sliderValue, 2) /100);

But, I want to stretch points along the line at an increasing rate from a to b. I want to do a statement where for each tick, the stretch on the pixels is increased. so say the first point on my slider is 100: a = pow(a, 2) /100 which equals 100. The second increment on the slider is 10, so now the slider value is at 110, but a should be 121 (a = pow(110,2)/100). The next point on the slider is 120, so a should be 144, and so on. So the distanc between the points along the line increases, even though the slider tick mark value stays at increments of 10.

How do I do that in Processing? Thanks

Tagged:

Answers

  • (bump) anyone?

  • You didn't get a response, because your problem description doesn't make sense and you propose a convulated quasi-solution. Instead, if you want to increase the likeliness of a response, you should either break down the problem into separate subproblems or provide a runnable example to fix. Doing this may even help you in solving the problem yourself.

  • edited July 2014

    Ok, let me put it like this: I just want something to happen every time the slider increments or decrements. And it has to happen for each increment/decrement (whatever unit it increments by).

    So I need something that says, "For each (increment on slider) do this." Is there a way to use slider values in that way?

  • This description is even more vague.

  • edited July 2014 Answer ✓

    How many pixels do you want to display over the distance b-a? Assume n. If equally spaced the distance between pixels would be (b-a)/(n-1). So each pixel's offset would be i*(b-a)/(n-1).

    You just need the formula i*what to calculate the position of each pixel. Where the sum of [(i+1)*what - i*(what)] for i=1 to n equals (b-a), and (n-1)*what = (b-a) and 1*what = 0;

    If the formula was i^2+i -.5 Then for i = 650 pixels the value would be 423,129.5. So scaling this over a distance to 3250 pixels the formula would be something like

      for(int i = 0;i <650;i++)
      {
          offset = i * ((pow(i,2)+i-0.5)/((pow(650,2)+650-.5)/3250)
      }
    

    Untested, with possible edge issues. Note: computing the denominator outside the loop would be more efficient.

  • Thank you, jas. That's exactly what I was looking for!

  • Answer ✓

    I'd replace pow(x, 2) w/ sq(x) for performance reasons! >-)

  • Note: the formula was arbitrary and I expect yours will change with each slider increment.

  • GoToLoop pow(x,2) is as efficient as sq(x). It would be a sad compiler that would not optimize it.

  • edited July 2014

    Unfortunately, Java has a very poor compiler! It prefers to rely most optimization job on its runtime VM instead!

    While sq() function merely multiplies the passed argument to itself:

    static public final float sq(float n) {
      return n*n;
    }
    

    Function pow() is rerouted to various tortuous paths:

    processing.core.PApplet:


    public static final float pow(float n, float e) {
      return (float) Math.pow(n, e);
    }
    

    java.lang.Math:


    public static double pow(double a, double b) {
      return StrictMath.pow(a, b);
    }
    

    java.lang.StrictMath:


    public static native double pow(double a, double b);
    


    After all those indirects, it ends up invoking an external native code. Probably in C!
    I personally doubt Java's runtime would be able to turn all of those as fast as a simple sq() would! ;;)
    But who knows, JVM can later conclude that pow(x, 2) will always return the same result from the same x!

    And seriously, the expression (pow(650,2) + 650 - .5)/3250 would become a single constant value
    130.19984 at compile time if you had just wrote it as (650*650 + 650 - .5)/3250! :P

  • edited July 2014

    My choice of format was to permit easy adjustment and experimentation. I wasn't trying to obfuscate my explanation via optimization, but show the thought process of deriving an answer.

    An answer without explanation is not much of an answer. Should one want to change the power from 2 to 2.723, or experiment with different power settings, presto a variable substitution vs a formula change.


    Make it work, make it right, make it fast.

    I was answering the how to "make it work" portion of the question only. The rest was left as an exercise to the questioner.


    As to pow() versus sq():

    I ran 2 tests. Test 1 pow() loop timed followed by sq() loop timed each draw cycle, totaling the durations, for 1,040,000 millis(). Test 2 reversed the order and ran for 3,122,000 millis();

    Test 1 pow() was 0.202% faster, Test 2 sq() was 0.229% faster for a whopping 0.027% advantage for sq(). or 27/100,000ths.

  • edited July 2014

    I've just replied b/c you gratuitously said that pow(x,2) was as efficient as sq(x)!
    It's nice that you based your argument on a speed test now! O:-)

    As I had pointed out, pow() in the end is a native compiled function, most probably in C.
    It is meant for both floating-point base and exponent parameters. A very heavy complicated calculation!

    But of course it should have some shortcuts for some basic cases as simple as a 2 exponent passed argument!
    Much probably, it merely returns base*base, like sq() does after all! 8-X

  • edited July 2014

    Well, i did my own performance comparison tests and sq(random(x)) ended up about 5.5x faster than pow(random(x), 2) in my 64-bit Lubuntu @ Q6600 CPU! :-t

    // forum.processing.org/two/discussion/6152/
    // cp5-controls-slider-where-for-each-increment-do-something
    
    void sqTest(final int ii) {
      for (int i = 0; i++ != ii; sq(random(MIN_INT, MAX_INT)));
    }
    
    void pow2Test(final int ii) {
      for (int i = 0; i++ != ii; pow(random(MIN_INT, MAX_INT), 2));
    }
    
    void setup() {
      // Warm-up:
      sqTest(500000);
      pow2Test(500000);
    
      // Time Measure for sq():
      int m = millis();
      sqTest(50000000);
      m = millis() - m;
      println("sq(): \t" + m/1e3);
    
      // Time Measure for pow2():
      m = millis();
      pow2Test(50000000);
      m = millis() - m;
      println("pow2(): \t" + m/1e3);
    
      exit();
    }
    
  • Mileage may vary! Next to no difference on my system, pow2/sw=99.720645%:

    system

    Ten tests flip/flopping order:


    pow2(): 1.193 sq(): 1.196

    sq(): 1.135 pow2(): 1.117


    pow2(): 1.125 sq(): 1.132

    sq(): 1.127 pow2(): 1.122


    pow2(): 1.119 sq(): 1.124

    sq(): 1.115 pow2(): 1.142


    pow2(): 1.128 sq(): 1.138

    sq(): 1.135 pow2(): 1.11


    pow2(): 1.123 sq(): 1.11

    sq(): 1.117 pow2(): 1.108


    pow2(): 1.118 sq(): 1.117

    sq(): 1.125 pow2(): 1.128


    pow2(): 1.117 sq(): 1.135

    sq(): 1.119 pow2(): 1.118


    pow2(): 1.11 sq(): 1.123

    sq(): 1.115 pow2(): 1.127


    pow2(): 1.131 sq(): 1.117

    sq(): 1.137 pow2(): 1.121


    pow2(): 1.12 sq(): 1.112

    sq(): 1.121 pow2(): 1.11
    ===============
    pow2/sw=0.99720645

    // forum.processing.org/two/discussion/6152/
    // cp5-controls-slider-where-for-each-increment-do-something
    
    void sqTest(final int ii) {
      for (int i = 0; i++ != ii; sq (random (MIN_INT, MAX_INT)));
    }
    
    void pow2Test(final int ii) {
      for (int i = 0; i++ != ii; pow (random (MIN_INT, MAX_INT), 2));
    }
    float pow2Total = 0;
    float sqTotal = 0;
    void setup() {
      int m = millis();
      // Warm-up:
      for (int i=0; i<10; i++)
      {
        pow2Test(500000);
        sqTest(500000);
        println(" ---");
    
        // Time Measure for pow2():
        m = millis();
        pow2Test(50000000);
        m = millis() - m;
        println("pow2(): \t" + m/1e3);
        pow2Total += m/1e3;
    
        // Time Measure for sq():
        m = millis();
        sqTest(50000000);
        m = millis() - m;
        println("  sq(): \t" + m/1e3);
        sqTotal += m/1e3;
        println(" ");
        // Warm-up:
        sqTest(500000);
        pow2Test(500000);
    
        // Time Measure for sq():
        m = millis();
        sqTest(50000000);
        m = millis() - m;
        println("  sq(): \t" + m/1e3);
        sqTotal += m/1e3;
    
        // Time Measure for pow2():
        m = millis();
        pow2Test(50000000);
        m = millis() - m;
        println("pow2(): \t" + m/1e3);
        pow2Total += m/1e3;
      }
      println("===============");
      println("pow2/sw="+pow2Total/sqTotal);
      exit();
    }
    
  • Dunno why, perhaps due to OpenJDK rather than Oracle's, pow() is more than 6x slower than sq() here: ~O)
    pow2/sw=6.052789

Sign In or Register to comment.