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

Եթե գտնվում ես վեբ զտիչի հետևում, խնդրում ենք համոզվել, որ *.kastatic.org և *.kasandbox.org տիրույթները հանված են արգելափակումից։

Հիմնական նյութ

Զսպանակի ուժեր

Այս բաժնի սկզբում քննարկեցինք սինուս ֆունկցիայի արժեքները պիքսելների ինչ-որ միջակայքում արտապատկերելու միջոցով պարզ հարմոնիկ շարժման մոդելավորումը, և քեզ հնարավորություն տվեցինք, սինուսի ալիքը կիրառելով, զսպանակին ամրացված ծանրակ նմանակելու։ Չնայած նրան, որ sin() ֆունկցիայի միջոցով որևէ առարկա տատանելը միտողանի, հեշտ ու պարզ լուծում է, այն այդքան էլ օգտակար չէ, երբ մեր նպատակը երկչափ տարածությունում զսպանակից կախված ծանրակ ունենալն է, որը գտնվում է նաև միջավայրի այլ ուժերի ազդեցության տակ, օրինակ՝ ծանրության կամ քամու ուժերի։ Ճոճանակի օրինակին նման և դրանից միայն զսպանակ բազուկով տարբերվող նմանակիչ ստանալու համար պետք է զսպանակի ուժերը PVector-ով մոդելավորել։
Զսպանակի ուժը հաշվում են Հուկի օրենքով, որը կոչվում է 1660 թվականին բանաձևը դուրս բերած բրիտանացի գիտնական Ռոբերտ Հուկի անունով։ Հուկը օրենքն ի սկզբանե լատիներեն էր ձևակերպել՝ Ut tensio, sic vis, թարգմանաբար նշանակում է՝ որքան ձգում, այնքան ուժ։ Պատկերացնենք այսպես՝
Զսպանակի ուժն ուղիղ համեմատական է զսպանակի ձգվածությանը։
Այլ կերպ ասած, եթե ծանրակը շատ քաշես, ուժը մեծ կլինի, եթե քիչ քաշես, ուժը փոքր կլինի։ Մաթեմատիկական տեսանկյունից օրենքը կարելի է ձևակերպել այսպես՝
Fspring=kx
  • k-ն հաստատուն է, և դրա արժեքը կփոխի ուժի մեծությունը։ Զսպանակը ճկո՞ւն է, թե՞ շատ կոշտ։
  • x-ը զսպանակի տեղափոխության չափն է, այսինքն՝ ընթացիկ երկարության ու հանգստի երկարության տարբերությունը։ Հանգստի երկարություն ասելով հասկանում ենք հավասարակշռված վիճակում զսպանակի երկարությունը։
Վերհիշիր, որ ուժը վեկտոր է, հետևաբար պետք է հաշվենք և՛ երկարությունը, և՛ ուղղությունը։ Դիագրամը դիտարկենք ևս մեկ անգամ և անվանենք բոլոր այն տվյալները, որոնք կարող ենք ունենալ ծրագրում։
Գրենք դիագրամում ցուցադրված հետևյալ երեք սկզբնական փոփոխականները և դրանց տանք տրամաբանական արժեքներ։
var anchor = new PVector(100, 10);
var bob = new PVector(110, 100);
var restLength = 20;
Ուժի երկարությունը հաշվելու համար կիրառենք Հուկի օրենքը։ Դրա համար պետք է իմանալ k-ի և x-ի արժեքները։ k-ն հեշտ է, քանի որ հաստատուն է. կարող ենք որևէ արժեք գրել։
var k = 0{,}1;
x-ն ավելի բարդ է։ Մեզ պետք է իմանալ «ընթացիկ երկարության և հանգստի երկարության տարբերությունը»։ Հանգստի երկարությունը սահմանել ենք restLength-ում։ Իսկ որքա՞ն է ընթացիկ երկարությունը. հենակետի և ծանրակի հեռավորությունը։ Ինչպե՞ս հաշվենք այդ հեռավորությունը։ Կարող ենք հաշվել հենակետից ծանրակ ուղղված վեկտորի երկարությունը։ Ուշադրություն դարձրու, որ ձգողականության բաժնում էլ ենք հեռավորությունն այսպես հաշվել։
var dir = PVector.sub(bob, anchor);
var currentLength = dir.mag();
var x = currentLength - restLength;
Քանի որ ուժի երկարությունը հաշվելու համար ամեն ինչ արդեն պատրաստ է՝ (-1 * k * x), պետք է գտնենք վեկտորի ուղղությունը՝ ուժի ուղղությամբ միավոր վեկտոր։ Իրականում այդ վեկտորը մենք արդեն ունենք. չէ՞ որ մի քիչ առաջ հեռավորությունը հաշվելու համար հաշվեցինք հենակետից ծանրակ ուղղությամբ վեկտորի երկարությունը։ Հենց այդ վեկտորն էլ ուժի ուղղությունն է։
Վերը ներկայացված դիագրամում տեսնում ենք, որ եթե զսպանակը ձգում ենք ավելի, քան իր հանգստի երկարությունն է, ծանրակը դեպի հենակետ հետ քաշող ուժ պետք է առաջանա, իսկ եթե զսպանակի երկարությունը հանգստի երկարությունից փոքր է, ուժը ծանրակը հրում է հենակետից հեռու։ Ուղղության փոփոխությունն այս բանաձևում կատարվում է -1 թվի միջոցով։ Հետևաբար, ուղղության վեկտորը ստանալու ու կիրառելու համար ընդամենը պետք է PVector-ը նորմավորենք։ Վերանայենք կոդը և PVector փոփոխականը վերանվանենք force։
var k = 0,01;
var force = PVector.sub(bob, anchor);
var currentLength = force.mag();
var x = currentLength - restLength;
// Զսպանակի ուժի ուղղությունը՝ միավոր վեկտոր
force.normalize();
// Երկարության և ուղղության միացում 
force.mult(-1 * k * x);
Քանի որ զսպանակի ուժը հաշվելու ալգորիթմը պատրաստ է, մնում է հասկանալ, թե օբյեկտային կողմնորոշվածությամբ ծրագրավորման որ կառուցվածքն է պետք կիրառել։ Սա այն դեպքերից է, երբ միանշանակ «ճիշտ» պատասխան չկա։ Հնարավոր բազմաթիվ տարբերակներ կան, և մեր ընտրությունը կախված է ծրագրի նպատակներից և ծրագրավորման մեր նախընտրած ոճից։ Այնուամենայնիվ, քանի որ երկար աշխատել ենք Mover օբյեկտի վրա, ճիշտ կլինի շարունակել դրանով աշխատել։ Պատկերացնենք, որ Mover օբյեկտը զսպանակի ծանրակն է։ Շարժվելու համար այն պետք է ունենա դիրք, արագություն և արագացում։ Շատ լավ է, այդքանն արդեն կա։ Միգուցե նաև applyForce() մեթոդի միջոցով ծանրության ուժ է գործադրվում։ Մնում է զսպանակի ուժ կիրառել.
var bob = new Bob();

draw = function()  {
  // Մեր ստեղծած ծանրության ուժը
  var gravity = new PVector(0, 1);
  bob.applyForce(gravity);
  // Պետք է նաև զսպանակի ուժը հաշվելու և կիրառել
  var spring = ????
  bob.applyForce(spring);

  // Մեր միշտ կիրառած update() և display() մեթոդները
  bob.update();
  bob.display();
};
Տարբերակներից մեկը զսպանակի ուժը հաշվող ու կիրառող կոդը draw() ցիկլում գրելն է, սակայն հնարավոր ապագա ծրագրերը դիտարկելուց հետո, երբ կունենաս բազմաթիվ զսպանակներ ու ծանրակը, ավելի տրամաբանական է թվում Spring օբյեկտ գրելը։ Ինչպես գրված է վերը բերված դիագրամում, Bob օբյեկտը ծանրակի շարժմանն է հետևում, իսկ Spring օբյեկտը պահում է զսպանակի հենակետն ու հանգստի երկարությունը և հաշվում է զսպանակի ուժը ծանրակի վրա։
Այդ երկուսն իրար միացնելու համար կարող ենք գրել հետևյալ կոդը.
var bob = new Bob();
var spring = new Spring();

draw = function()  {
  // Մեր ստեղծած ծանրության ուժը
  var gravity = new PVector(0, 1);
  bob.applyForce(gravity);
  // Spring.connect()-ը զսպանակի ուժը 
  // կհաշվի և կկիրառի
  spring.connect(bob);

  // Մեր միշտ կիրառած update() և display() մեթոդները
  bob.update();
  bob.display();
};
Գուցե կնկատես, որ սա շատ նման է ձգողականության բաժնում մեր կատարած քայլերին, երբ ստեղծեցինք attractor օբյեկտը։ Այնտեղ այսպիսի բան էինք գրել՝
var force = attractor.calculateAttraction(mover);
mover.applyForce(force);
Զսպանակի դեպքում կստացվի այսպես՝
var force = spring.calculateForce(bob);
bob.applyForce(force);
Այնուամենայնիվ, մենք ընդամենը հետևյալն ենք գրել.
spring.connect(bob);
Ինչո՞ւ։ Ինչո՞ւ ծանրակի դեպքում applyForce()-ը կանչելու կարիք չկա։ Պատասխանն այն է, որ applyForce()-ը կանչելու կարիքը կա, սակայն ընդամենը ցուցադրում ենք, որ այն draw()-ում կանչելու փոխարեն կարող ես կատարել համարժեք և հաճախ ավելի նախընտրելի քայլ՝ connect() մեթոդում կանչել applyForce() մեթոդը։
Spring.prototype.connect(bob) {
  var force = /* բարդ հաշվարկներ */;
  bob.applyForce(force);
};
Ինչո՞ւ ենք Attractor օբյեկտի դեպքում մի բան անում, իսկ Spring օբյեկտի դեպքում՝ ուրիշ։ Երբ ուժերի մասին նոր էինք սովորում, դրանք draw() ցիկլում կիրառելն օգնում էր քեզ ավելի լավ հասկանալ՝ ինչ ենք անում, և ինչպես են ուժերը կուտակվում։ Քանի որ արդեն ամեն ինչ ավելի լավ ենք պատկերացնում, ավելի հեշտ է օբյեկտի մեջ գրել։
Փորձենք ամեն ինչը իրար միացնել։ Մի քանի բան ավելացրել ենք. (1) Bob օբյեկտն արդեն հնարավոր է մկնիկով կառավարել, և (2) Spring օբյեկտը սահմանափակում է միացման երկարությունը վերևից և ներքևից։

«Բնական նմանակիչներ» դասընթացը ստեղծվել է Դանիել Շիֆմանի «Կոդի բնույթը» գրքի հիման վրա և կիրառվում է ըստ Creative Commons Attribution-NonCommercial 3,0 Unported License-ի։

Ուզո՞ւմ ես միանալ խոսակցությանը։

Առայժմ հրապարակումներ չկան։
Անգլերեն հասկանո՞ւմ ես: Սեղմիր այստեղ և ավելի շատ քննարկումներ կգտնես «Քան» ակադեմիայի անգլերեն կայքում: