2015-08-20 1 views
6

Je simule un système de particules en cours de traitement. Basé sur le livre Nature of Code de Daniel Shiffman, j'ai fait un printemps et ensuite j'ai commencé à expérimenter avec des curseurs pour en faire un plus long ou plus court basé sur un curseur.Comment faire un membre coulissant dans Traitement avec des systèmes de particules

Maintenant, j'essaie de faire un qui glisse par le curseur, les deux particules se déplacent dans la même direction des deux particules. Je l'ai fait avec le PVector add, trouvant la nouvelle position et dessinant le nœud, mais cela ne fonctionne pas quand j'ai plusieurs membres et que l'un est affecté par les autres. Je dois appliquer une force pour cela: voir la fonction applyForce().

void update(float distance) { 
    PVector force = PVector.sub(b.location, a.location); 
    float d = force.mag(); 
    float x = d - distance; 
//direction of the force 
    force.normalize(); 
    force.mult(-1 * k* x/mass); 
//apply to one node 
    b.applyForce(force); 
    force.mult(-1); 
//apply opposite to the other node 
    a.applyForce(force); 
} 

//Newton's law: F = M * A 
void applyForce(PVector force) { 
    PVector f = force.get(); 
    f.div(mass); 
    acceleration.add(f); 
} 

Vérifiez le schéma ci-dessous:

diagram

(a) est ce que je veux avoir, (b) est ainsi qu'il fait maintenant.

Dans le premier exemple, la longueur est la même et les membres glissent (les deux particules).

Dans la seconde la longueur est plus grande et ne glisse pas

S'il vous plaît laissez-moi savoir si vous savez comment appliquer une force qui glisse le membre.

Merci

+0

Que voulez-vous dire exactement quand vous dites ça ne marche pas? Pouvez-vous poster un [MCVE] (http://stackoverflow.com/help/mcve)? –

+0

@KevinWorkman S'il vous plaît vérifier le diagramme et laissez-moi savoir si cela aide. – Apollon1954

+0

Vous aurez beaucoup plus de chance si vous postez un MCVE au lieu d'un extrait déconnecté. –

Répondre

3

Si je comprends bien, vous essayez de faire quelques petites choses:

  1. changer la longueur du ressort
  2. traduire les points d'extrémité du ressort dans la direction du ressort
  3. de commande les paramètres ci-dessus en utilisant les curseurs

La première partie est triviale depuis l'objet Spring a une propriété len. La seconde implique un peu de vector math:

  1. la direction d'une ligne est la soustraction de ses deux points d'extrémité
  2. un vecteur peut être adapté facilement à toute longueur en normalisant le premier (réduisant donc sa longueur est égal à 1,0), puis en multipliant par une valeur scalaire.
  3. Un vecteur peut être traduit en ajoutant simplement un autre vecteur se

Voici un croquis commenté la mise en œuvre des points ci-dessus:

//sliders to control spring rest length and translation 
Slider rlength = new Slider("rest length", 5, 5, 200, 20, 50, 250, 100, false); 
Slider translate = new Slider("translate", 5, 30, 200, 20, -10, 10, 0, false); 

Spring spring = new Spring(new Bob(75,350),new Bob(350,75),(int)rlength.value); 

void setup(){ 
    size(400,400); 
    spring.k = 0.01;//tweak elasticity 
} 
void draw(){ 
    // update 
    //update sliders 
    rlength.update(mouseX,mouseY,mousePressed); 
    translate.update(mouseX,mouseY,mousePressed); 
    //update spring 
    spring.a.update(); 
    spring.b.update(); 
    spring.update(); 
    //make both points draggable 
    spring.a.drag(mouseX, mouseY); 
    spring.b.drag(mouseX, mouseY); 
    //draw 
    background(255); 
    rlength.draw(); 
    translate.draw(); 
    spring.display(); 
} 
//handle mouse events for spring points dragging 
void mousePressed() { 
    spring.a.clicked(mouseX, mouseY); 
    spring.b.clicked(mouseX, mouseY); 
} 
void mouseReleased() { 
    spring.a.stopDragging(); 
    spring.b.stopDragging(); 
} 
//handle slider events 
void onSliderUpdate(Slider s){ 
    if(s == rlength) spring.len = rlength.value; 
    if(s == translate){ 
    //compute the direction of the spring by subtracting the two points 
    PVector direction = PVector.sub(spring.a.location,spring.b.location); 
    //normalize the vector -> it will not have a length/magnitude of 1.0, but will still point in the line direction 
    direction.normalize(); 
    //scale or multiply the normalized vector to the translation amount 
    direction.mult(translate.value); 
    //finally, add the result to each spring point, essentially offsetting/translating 
    spring.a.location.add(direction); 
    spring.b.location.add(direction); 
    } 
} 
//Slider 
class GUIElement{ 
    float w,h,x,y;//width, height and position 
    color bg = color(200);//background colour 
    color fg = color(0);//foreground colour 
    String label; 
    GUIElement(String label,float x,float y,float w,float h){ 
    this.x = x; 
    this.y = y; 
    this.w = w; 
    this.h = h; 
    this.label = label; 
    } 
    void update(int mx,int my,boolean md){} 
    void draw(){} 
} 
class Slider extends GUIElement{ 
    float min,max,value,pvalue;//slider values: minimum, maximum and current 
    float cx,pw = 20;//current slider picker position, picker width 

    boolean updating,liveDrag = true,isInt = false; 
    //label to display on slider, it's position(x,y), size(w,h) and values(min, max and default/current) 
    Slider(String label,float x,float y,float w,float h,float min,float max,float value,boolean isInt){ 
    super(label,x,y,w,h); 
    this.min = min; 
    this.max = max; 
    this.value = value; 
    this.isInt = isInt; 
    cx = map(value,min,max,x,x+w); 
    } 
    void update(int mx,int my,boolean md){ 
    if(md){ 
     if((mx >= x && mx <= (x+w)) && 
     (my >= y && my <= (y+h))){ 
     cx = mx; 
     value = map(cx,x,x+w,min,max); 
     updating = true; 
     if(liveDrag){ 
      boolean updated = (isInt ? ((int)value != (int)pvalue) : (value != pvalue)); 
      if(updated){ 
      pvalue = value; 
      onSliderUpdate(this); 
      } 
     } 
     }else updating = false; 
    }else{ 
     if(updating){ 
     updating = false; 
     onSliderUpdate(this); 
     } 
    } 
    } 
    void draw(){ 
    pushStyle(); 
    noStroke(); 
    fill(bg); 
    rect(x,y,w,h); 
    fill(fg,64); 
    rect(x,y,cx-x,h);//this displays a rect that stretches based on the value 
    fill(0); 
    text(label+": "+(isInt ? (int)value : value),x+pw,y+h*.75); 
    popStyle(); 
    } 
    String toString(){ 
    return label + ":" + value; 
    } 
} 

// The Nature of Code 
// Daniel Shiffman 
// http://natureofcode.com 

// Bob class, just like our regular Mover (location, velocity, acceleration, mass) 

class Bob { 
    PVector location; 
    PVector velocity; 
    PVector acceleration; 
    float mass = 12; 

    // Arbitrary damping to simulate friction/drag 
    float damping = 0.95; 

    // For mouse interaction 
    PVector dragOffset; 
    boolean dragging = false; 

    // Constructor 
    Bob(float x, float y) { 
    location = new PVector(x,y); 
    velocity = new PVector(); 
    acceleration = new PVector(); 
    dragOffset = new PVector(); 
    } 

    // Standard Euler integration 
    void update() { 
    velocity.add(acceleration); 
    velocity.mult(damping); 
    location.add(velocity); 
    acceleration.mult(0); 
    } 

    // Newton's law: F = M * A 
    void applyForce(PVector force) { 
    PVector f = force.get(); 
    f.div(mass); 
    acceleration.add(f); 
    } 


    // Draw the bob 
    void display() { 
    stroke(0); 
    strokeWeight(2); 
    fill(175); 
    if (dragging) { 
     fill(50); 
    } 
    ellipse(location.x,location.y,mass*2,mass*2); 
    } 

    // The methods below are for mouse interaction 

    // This checks to see if we clicked on the mover 
    void clicked(int mx, int my) { 
    float d = dist(mx,my,location.x,location.y); 
    if (d < mass) { 
     dragging = true; 
     dragOffset.x = location.x-mx; 
     dragOffset.y = location.y-my; 
    } 
    } 

    void stopDragging() { 
    dragging = false; 
    } 

    void drag(int mx, int my) { 
    if (dragging) { 
     location.x = mx + dragOffset.x; 
     location.y = my + dragOffset.y; 
    } 
    } 
} 

// Nature of Code 2011 
// Daniel Shiffman 
// Chapter 3: Oscillation 

// Class to describe an anchor point that can connect to "Bob" objects via a spring 
// Thank you: http://www.myphysicslab.com/spring2d.html 

class Spring { 

    // Location 
    PVector anchor; 

    // Rest length and spring constant 
    float len; 
    float k = 0.2; 

    Bob a; 
    Bob b; 

    // Constructor 
    Spring(Bob a_, Bob b_, int l) { 
    a = a_; 
    b = b_; 
    len = l; 
    } 

    // Calculate spring force 
    void update() { 
    // Vector pointing from anchor to bob location 
    PVector force = PVector.sub(a.location, b.location); 
    // What is distance 
    float d = force.mag(); 
    // Stretch is difference between current distance and rest length 
    float stretch = d - len; 

    // Calculate force according to Hooke's Law 
    // F = k * stretch 
    force.normalize(); 
    force.mult(-1 * k * stretch); 
    a.applyForce(force); 
    force.mult(-1); 
    b.applyForce(force); 
    } 


    void display() { 
    strokeWeight(3); 
    stroke(0); 
    line(a.location.x, a.location.y, b.location.x, b.location.y); 
    ellipse(a.location.x, a.location.y,10,10); 
    ellipse(b.location.x, b.location.y,10,10); 
    } 
} 

Slider controlled Spring