2015-08-20 27 views
6

Symuluję system cząsteczek w przetwarzaniu. Opierając się na książce Nature of Code Daniela Shiffmana, zrobiłem wiosnę, a następnie zacząłem eksperymentować z suwakami, aby wykonać utwór, który ma dłuższą lub krótszą długość w oparciu o suwak.Jak wykonać element ślizgowy w przetwarzaniu za pomocą systemów cząsteczek

Teraz próbuję zrobić taki, który przesuwa się za suwak, dwie cząstki poruszają się w tym samym kierunku dwóch cząstek. Zrobiłem to z dodaniem PVectora, znajdowaniem nowej pozycji i rysowaniem węzła, ale to nie działa, gdy mam wielu członków, a jeden jest pod wpływem innych. Potrzebuję zastosować siłę, aby to zrobić: zobacz function 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); 
} 

zobacz diagram poniżej:

diagram

(a) jest to, co chcę mieć, (b) jak to robi teraz.

W pierwszym przykładzie długość jest taka sama, a elementy przesuwają się (obie cząstki).

W drugim długość jest większa i nie ślizga

Proszę dać mi znać, jeśli wiesz, jak stosować siły, która przesuwa element.

Dziękuję

+0

Co dokładnie masz na myśli mówiąc to nie działa? Czy możesz opublikować [MCVE] (http://stackoverflow.com/help/mcve)? –

+0

@KevinWorkman Sprawdź diagram i daj mi znać, czy to pomaga. – Apollon1954

+0

Będziesz mieć dużo lepsze szczęście, jeśli opublikujesz MCVE zamiast rozłączonego fragmentu. –

Odpowiedz

3

Jeśli dobrze zrozumiałem, starasz się zrobić kilka rzeczy:

  1. zmiany sprężyny długość
  2. przekładają punkty końcowe sprężynę w kierunku sprężyny
  3. sterowania powyższe parametry przy użyciu suwaków

Pierwsza część jest banalna, ponieważ obiekt Spring ma właściwość len. Drugi polega nieco vector math:

  1. kierunek linii jest odejmujące na jego dwa punkty końcowe
  2. wektor może być skalowane łatwo dowolnej długości przez normalizację najpierw (zmniejszenie się więc na długości jest równa 1,0), a następnie pomnożenie przez wartość skalarną.
  3. Wektor może być tłumaczone przez proste dodanie innego wektora sobie

Oto skomentowany szkic wykonawczy powyższych punktów:

//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