If you're seeing this message, it means we're having trouble loading external resources on our website.

Jeżeli jesteś za filtrem sieci web, prosimy, upewnij się, że domeny *.kastatic.org i *.kasandbox.org są odblokowane.

Główna zawartość

Sprężystość

Na początku tej sekcji omówiliśmy modelowanie ruchu harmonicznego za pomocą fali sinusoidalnej w przedziale pikseli, a następnie w ramach ćwiczenia mieliście zamodelować kulkę na sprężynie przy użyciu tej fali. Chociaż używanie funkcji sin() to szybkie i prowizoryczne, zawarte w jednej linii rozwiązanie które może sprawić, że coś szybko zacznie działać, nie wystarczy jeżeli chcemy mieć kulkę zawieszoną na sprężynie w dwuwymiarowej przestrzeni, dodatkowo reagując na inne siły w otoczeni (wiatr, grawitacja itd.) Aby osiągnąć tego typu symulację (taką, która będzie identyczna do przykładu z wahadłem, tyle, że tym razem obiekt zawieszony będzie na sprężynie), potrzebujemy opisać siły sprężyny za pomocą PVector.
Siła sprężyny obliczana jest na podstawie prawa Hooke’a, nazwanego tak od Roberta Hooke’, brytyjskiego fizyka który opracował ten wzór w 1660. Hooke tak opisał to prawo po łacinie: "Ut tensio, sic vis," or “Jakie rozciągnięcie, taka siła.” Pomyślmy o tym w ten sposób:
Siła sprężyny jest wprost proporcjonalna do jej rozciągnięcia.
Innymi słowy, jeżeli pociągniemy mocno za kulkę, siła będzie duża; jeżeli lekko pociągniemy kulkę, siła będzie mała. Za pomocą matematyki można to opisać w taki sposób:
Fs=kx
  • k jest stałe i jego wartość będzie tą rzeczą, która ostatecznie skaluje siłę. Czy sprężyna jest elastyczna, czy raczej sztywna?
  • x odnosi się do przesunięcia sprężyny, czyli różnicy między bieżącą długością a długością spoczynkową. Długość spoczynkowa jest definiowana jako długość sprężyny w stanie równowagi.
Pamiętajcie, siłą to wektor, musimy więc policzyć zarówno moduł, jak i kierunek. Spójrzmy na jeszcze jeden wykres sprężyny i opiszmy wszystkie dane, które możemy mieć w programie.
Ustalmy następujące trzy początkowe zmienne, odpowiadające tym z powyższego wykresu i nadajmy im rozsądne wartości.
var anchor = new PVector(100, 10);
var bob = new PVector(110, 100);
var restLength = 20;
Wpierw użyjmy prawa Hooke'a do obliczenia wartości siły. Musimy wiedzieć ile wynosi k oraz x. k jest proste; to po prostu stała, więc wymyślmy coś.
var k = 0.1;
x jest trochę trudniejsze. Musimy znać “różnicę pomiędzy aktualną długością a długością spoczynkową.” Długość spoczynkowa jest opisana w zmiennej restLength. Ile wynosi aktualna długość? Jest ona równa odległości pomiędzy zmiennymi anchor i bob. A jak obliczamy odległość? A może użyjemy modułu wektora który jest poprowadzony od zmiennej anchor do bob? (Zauważcie, że to dokładny ten sam proces który użyliśmy do liczenia odległości w dziale poświęconym przyciąganiu ziemskiemu.)
var dir = PVector.sub(bob, anchor);
var currentLength = dir.mag();
var x = currentLength - restLength;
Teraz gdy wyróżniliśmy elementy niezbędne do obliczenia modułu mocy (-1 * k * x), musimy znaleźć kierunek w postaci wektora jednostkowego wskazującego kierunek siły. Dobra wiadomość jest taka, że już mamy ten wektor. Prawda? Przed chwilą zastanawialiśmy się: “Jak możemy obliczyć tą odległość? Może użyjemy modułu wektora który jest skierowany od zmiennej anchor do bob?” Cóż, ten sam wektor wskazuje również kierunek siły!
Na powyższym diagramie możemy zobaczyć, że jeżeli rozciągniemy sprężynę poza jej długość spoczynkową, powinna istnieć siła która będzie ciągnąć ją z powrotem w stronę punktu zaczepienia. A jeżeli zmniejszy się poniżej długości spoczynkowej, siła powinna odpychać ją od punktu przyłożenia. To odwrócenie kierunku jest wzięte pod uwagę we wzorze w postaci -1. Dzięki temu wszystko, co musimy zrobić to znormalizować PVector którego używamy do obliczenia odległości! Rzućmy okiem na kod i przemianujmy tą zmienną PVectora na “force.”
var k = 0.01;
var force = PVector.sub(bob, anchor);
var currentLength = force.mag();
var x = currentLength - restLength;
// Kierunek siły sprężyny, wektor jednostkowy
force.normalize();
// Po połączeniu: kierunek i moduł!
force.mult(-1 * k * x);
Teraz, gdy mamy opracowany algorytm który pozwala obliczyć wektor siły sprężyny, pozostaje pytanie: jakiej struktury programowania obiektowego powinniśmy użyć? To jest jedna z tych sytuacji, gdzie nie istnieje “poprawna” odpowiedź. Istnieje kilka możliwości; wybór zależy od tego, co ma robić program i od stylu programowania osoby piszącej kod. Skoro jednak pracowaliśmy cały czas na obiekcie Mover, kontynuujmy ten zwyczaj. Pomyślmy o tym w ten sposób: nasz obiekt Mover jest kulką zaczepioną do sprężyny. Kulka potrzebuje położenia, prędkości i wektora przyspieszenia w celu przemieszczania się po ekranie. Świetnie - to już mamy! Możemy nawet dodać do kulki siłę grawitacji poprzez metodę applyForce(). Pozostaje nam tylko jeden krok—dodanie siły sprężyny:
var bob = new Bob();

draw = function()  {
  // Nasza “wymyślona siła grawitacji”
  var gravity = new PVector(0, 1);
  bob.applyForce(gravity);
  // Musimy również obliczyć i zastosować siłę pochodzącą od sprężyny!
  var spring = ????
  bob.applyForce(spring);

  // Nasze standardowe metody update() i display()
  bob.update();
  bob.display();
};
Jedną z opcji byłoby napisanie całego kodu siły sprężyny w głównej pętli draw(). Ale wybiegając w przyszłość, gdybyśmy chcieli mieć wiele kulek i wiele sprężyn, dobrym pomysłem byłoby napisanie dodatkowego obiektu, Spring. Jak pokazano na powyższym wykresie, obiekt Bob przechowuje informacje o ruchach kulki; obiekt Spring przechowuje informacje o punkcie przyczepienia sprężyny i jej długości spoczynkowej, oraz oblicza siłę, z jaką sprężyna działa na kulkę.
Pozwala nam to napisać ten wspaniały kod, który powiąże je ze sobą:
var bob = new Bob();
var spring = new Spring();

draw = function()  {
  // Nasza “wymyślona siła grawitacji”
  var gravity = new PVector(0, 1);
  bob.applyForce(gravity);
  // Spring.connect() zajmie się wyliczeniem
  //  i zastosowaniem siły sprężystości
  spring.connect(bob);

  // Nasze standardowe metody update() i display()
  bob.update();
  bob.display();
};
Mogliście zauważyć, że jest to bardzo podobna sytuacja do tego, co miało miejsce w dziale Grawitacja w przypadku przyciągacza. Tam ustaliliśmy coś takiego:
var force = attractor.calculateAttraction(mover);
mover.applyForce(force);
Analogiczna sytuacja ze sprężyną wygląda tak:
var force = spring.calculateForce(bob);
bob.applyForce(force);
A w tym przykładzie jedyne, co zrobiliśmy, to:
spring.connect(bob);
Dlaczego? Czemu nie użyjemy metody applyForce() na kulce? Odpowiedź jest prosta - nie musimy używać applyForce() na kulce. Tyle, że zamiast robić to w metodzie draw(), przedstawiamy bardzo rozsądną (a czasami nawet preferowaną) alternatywę, która polega na tym, że to metoda connect() zajmuje się wywołaniem applyForce() na kulce.
Spring.prototype.connect(bob) {
  var force = /* jakieś magiczne obliczenia */;
  bob.applyForce(force);
};
Czemu robimy to jednym sposobem w przypadku obiektu Attractor, a w inny z obiektem Spring? Gdy uczyliśmy się na temat sił, było znacznie łatwiej zademonstrować dodawanie wszystkich sił w głównej pętli draw(), licząc na to, że pomoże to opanować Wam dodawanie sił. Teraz, gdy czujemy się bardziej komfortowo z tymi zagadnieniami, pora umieścić część tych detali wewnątrz samych obiektów.
Połączmy to wszystko w jedną całość, w programie zamieszczonym poniżej. Dodaliśmy parę rzeczy: (1) obiekt Bob zawiera funkcję odpowiedzialną za interakcję z myszką, dzięki czemu może być przeciągany po ekranie, oraz (2) obiekt Spring posiada funkcję ograniczającą długość połączenia pomiędzy minimum a maksimum.

Ten kurs "Symulacje Natury" jest pochodną z "Natury Kodu " stworzonej przez Daniela Shiffmana, użytej pod licencją Creative Commons Attribution-NonCommercial 3.0 Unported License.

Chcesz dołączyć do dyskusji?

Na razie brak głosów w dyskusji
Rozumiesz angielski? Kliknij tutaj, aby zobaczyć więcej dyskusji na angielskiej wersji strony Khan Academy.