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

তোমার যদি কোন ওয়েব ফিল্টার দেওয়া থাকে, তাহলে দয়া করে নিশ্চিত কর যে *.kastatic.org এবং *.kasandbox.org ডোমেইনগুলো উন্মুক্ত।

মূল বিষয়বস্তু

মহাকর্ষীয় আকর্ষণ

সম্ভবত সবচেয়ে জনপ্রিয় বল (force) হল মহাকর্ষ (gravity)। স্যার আইজ্যাক নিউটনের মাথায় একটি আপেল পতিত হবার ঘটনাকে কেন্দ্র করেই পৃথিবীতে মহাকর্ষের উপস্থিতির প্রকাশ পায়। মহাকর্ষের কারণে সকল বস্তু ভূমিতে পতিত হয়। কিন্তু মহাকর্ষ সম্পর্কে এই ধারণা আমাদের অভিজ্ঞতালব্ধ। সত্যিকার অর্থে, পৃথিবী যেমন মহাকর্ষ বলের কারণে আপেলকে নিজের দিকে আকর্ষণ করে, তেমনিভাবে আপেলও পৃথিবীকে নিজের দিকে আকর্ষণ করে। আসল বিষয়টি হল, পৃথিবী এতো বিশাল আকৃতির যে, অন্যান্য বস্তুর চেয়ে পৃথিবীর আকর্ষণ বল অনেক বেশি। ভরবিশিষ্ট প্রত্যেকটি বস্তুই অন্য সকল বস্তুর উপর মহাকর্ষ বল প্রয়োগ করে। মহাকর্ষ বলের মান বের করার সূত্র নিচের চিত্রে দেওয়া হল:
দুটি গোলকের মধ্যবর্তী মহাকর্ষ বলের চিত্র
এই সূত্রটি সম্পর্কে জানা যাক।
  • F হল মহাকর্ষ বল, আমরা এই ভেক্টরটি বের করে applyForce() ফাংশনে পাঠাতে চাই।
  • G হল সার্বজনীন মহাকর্ষীয় ধ্রুবক, যার মান হল প্রতি বর্গ সেকেন্ডে প্রতি কিলোগ্রামে 6.67428 x 10^-11 ঘন মিঃ। যদি নিজের নাম আইজ্যাক নিউটন অথবা অ্যালবার্ট আইনস্টাইন হয় তাহলে এই সংখ্যাটি খুবই গুরুত্বপূর্ণ। কিন্তু যেহেতু আমরা ProcessingJS প্রোগ্রামার, একারণে সংখ্যাটি এতটা গুরুত্বপূর্ণ নয়। আবারও বলি, এটি হল একটি ধ্রুবক যা ব্যবহার করে আমরা বলকে শক্তিশালী অথবা দুর্বল করতে পারি। মহাকর্ষীয় ধ্রুবককে এক (1) এর সমতুল্য করে এটিকে বাদ দিলেও ভুল হবে না।
  • m, start subscript, 1, end subscript এবং m, start subscript, 2, end subscript হল 1 এবং 2 নং বস্তুর ভর (mass)। আমরা নিউটনের দ্বিতীয় সূত্রে দেখেছিলাম (F, with, vector, on top, equals, M, A, with, vector, on top), ভরকেও আমরা বাদ দিতে পারি। আসলে, পর্দায় আঁকা আকৃতিগুলির কোন বাহ্যিক ভর নেই। তবুও, যদি আমরা এই মানগুলি রাখি, তাহলে আমরা আরও মজাদার সিমুলেশন তৈরি করতে পারবো যেখানে “বড়” বস্তু (অবজেক্ট) ছোট বস্তুর উপুর বেশি মহাকর্ষ বল প্রয়োগ করবে।
  • r, with, hat, on top হল একক ভেক্টর যা 1 থেকে 2 নং বস্তুর দিকে নির্দেশ করে। কিছুক্ষণ পরে, আমরা একটি বস্তুর অবস্থানকে অপর বস্তু থেকে বিয়োগ করে ভেক্টরের মান বের করবো।
  • r, squared হল দুইটি বস্তুর মধ্যবর্তী দূরত্বের বর্গ। এটা নিয়ে একটু ভেবে দেখা যাক। সূত্র থেকে আমরা বুঝতে পারি যে—G, m_1, m, start subscript, 2, end subscript—এগুলির মান যত বড় হবে, আকর্ষণ বলও তত বেশি হবে। বড় ভর, বড় আকর্ষণ বল। বড় G, বড় আকর্ষণ বল। আমরা জানি, কোন কিছু দিয়ে কোন কিছুকে ভাগ করলে সেটার বিপরীত মান পাওয়া যায়। আকর্ষণ বল হল মধ্যবর্তী দূরত্বের বর্গের ব্যস্তানুপাতিক। বস্তু যত দূরে থাকবে, এটির আকর্ষণ বল তত দুর্বল হবে; বস্তু যত নিকটে থাকবে, এটির আকর্ষণ বল তত শক্তিশালী হবে।
আশা করি এখন সূত্রটি বোঝা যাচ্ছে। আমরা উল্লেখিত চিত্র দেখে সূত্রের প্রত্যেকটি মান সম্পর্কে জেনেছি। এখন সূত্রটিকে ProcessingJS এর কোডে পরিণত করার পদ্ধতি বের করতে হবে। সূত্র থেকে অনুধাবিত কিছু ধারণা নিচে দেওয়া হল।
আমাদের দুইটি বস্তু আছে:
  1. প্রতিটি বস্তুর একটি PVector অবস্থান: location1 এবং location2 আছে।
  2. প্রতিটি বস্তুর একটি সাংখ্যিক ভর: mass1 এবং mass2 আছে।
  3. একটি সাংখ্যিক চলক G হল সার্বজনীন মহাকর্ষীয় ধ্রুবক।
এগুলো অনুমানের ভিত্তিতে, আমরা একটি মহাকর্ষ বল PVector force হিসাব করতে চাই। আমরা এই কাজ দুইটি ধাপে করবো। প্রথমত, আমরা উপরে উল্লেখিত সূত্র থেকে বলের দিক হিসাব করব r, with, hat, on top . দ্বিতীয়ত, আমরা ভর এবং দূরত্ব সাপেক্ষে আকর্ষণ বলের শক্তি হিসাব করবো।
মনে আছে, যখন আমরা মাউসের দিকে একটি বস্তুর ত্বরণ বের করেছিলাম? আমরা সেই একই লজিক ব্যবহার করবো।
একটি ভেক্টর হল দুইটি বিন্দুর মধ্যবর্তী পার্থক্য। বৃত্ত থেকে মাউসের দিকে একটি ভেক্টর তৈরি করার জন্য, আমরা শুধু একবিন্দুকে অপর বিন্দু থেকে বিয়োগ করবো:
var dir = PVector.sub(mouse, location);
আমাদের ক্ষেত্রে, 1 নং বস্তু থেকে 2 নং বস্তুর উপর আকর্ষণ বলের দিক সমান হল:
var dir = PVector.sub(location1, location2);
খেয়াল রাখতে হবে যে, আমরা একটি একক ভেক্টর চাই, একটি ভেক্টর যা শুধুমাত্র দিক নির্দেশ করবে। বিয়োগের পর ভেক্টরটিকে নরমালাইজ (normalize) করতে হবে:
dir.normalize();
ঠিক আছে, আমরা আকর্ষণ বলের দিক পেয়ে গেছি। এখন শুধু আমাদের মান বের করে ভেক্টরটিকে সেই অনুসারে পরিমাপ করতে হবে।
var m = (G * mass1 * mass2) / (distance * distance);
dir.mult(m);
এখন একটি সমস্যা হল আমরা দূরত্বটি জানি না। G, mass1 এবং mass2 সব কিছুই দেওয়া আছে, কিন্তু উপরের কোডটিকে কাজ করানোর জন্য আমাদের আগে দূরত্ব (distance) হিসাব করতে হবে। আমরা এক বিন্দু থেকে অপর বিন্দুতে ভেক্টর তৈরি করেছি, মনে আছে? সেই ভেক্টরটির দৈর্ঘ্যই কি দুইটি বস্তুর মধ্যবর্তী দূরত্ব হবে না?
আসলে, নরমালাইজ করার আগেই আমরা যদি শুধুমাত্র আরেকটি লাইন কোডে যোগ করে ভেক্টরটির মান নেই, তাহলে দূরত্ব পাবো।
// এক বিন্দু থেকে অপর বিন্দুতে ভেক্টর
var force = PVector.sub(location1, location2);

// ভেক্টরের দৈর্ঘ্য (মান) যা দুইটি বস্তুর মধ্যবর্তী দূরত্ব
var distance = force.mag();

// আকর্ষণ বলের শক্তি নির্ণয়ের জন্য এই সূত্রটি মহাকর্ষের ক্ষেত্রে ব্যবহার করা হয়
var strength = (G * mass1 * mass2) / (distance * distance);

// বলের ভেক্টরটিকে উপযুক্ত মানে নরমালাইজ এবং পরিমাপ করে
force.normalize();
force.mult(strength);
লক্ষ্য করি, PVector ভেক্টরের নাম বদলিয়ে “dir” কে “force” লেখা হয়েছে। সবশেষে, সব হিসাব করা শেষ হলে, যেই PVector নিয়ে আমরা প্রথমে শুরু করেছিলাম, সেটি থেকেই বলের ভেক্টর পাবো।
যেহেতু হিসাব এবং কোড করে (মহাকর্ষ ইমুলেট করে) আকর্ষণ বল বের করা শেষ, সেজন্য এখন আমাদের ProcessingJS প্রোগ্রামে এই পদ্ধতি প্রয়োগ করতে হবে। এই অংশে আমরা, একটি সাধারণ Mover অবজেক্ট (বস্তু) তৈরি করেছি—PVector অবস্থান, বেগ, ত্বরণ এবং তার সাথে applyForce() বিশিষ্ট একটি অবজেক্ট। এখন এই class এবং নিচের অবজেক্টগুলো নিয়ে একটি প্রোগ্রাম তৈরি করি:
  • একটি Mover অবজেক্ট।
  • একটি Attractor অবজেক্ট (একটি নতুন অবজেক্ট যার অবস্থান নির্দিষ্ট থাকবে)।
Mover অবজেক্টটি Attractor অবজেক্টের দিয়ে মহাকর্ষীয় আকর্ষণ বল অনুভব করবে, নিচে এটার চিত্র দেওয়া হল।
আমরা খুবই সাধারণভাবে নতুন Attractor অবজেক্ট তৈরি করা শুরু করতে পারি—এটিকে একটি ভর এবং অবস্থান দেই, তারপর নিজেকে দৃশ্যমান করার জন্য একটি মেথড (ভরকে পরিমাপের সাথে যুক্ত করে) তৈরি করি।
var Attractor = function() {
    this.position = new PVector(width/2, height/2);
    this.mass = 20;
    this.G = 1;
    this.dragOffset = new PVector(0, 0);
    this.dragging = false;
    this.rollover = false;
};

// অবজেক্ট দৃশ্যমান করার মেথড
Attractor.prototype.display = function() {
    ellipseMode(CENTER);
    strokeWeight(4);
    stroke(0);
    fill(175, 175, 175, 200);
    ellipse(this.position.x, this.position.y, this.mass*2, this.mass*2);
};
এটাকে সংজ্ঞায়িত করার পর, আমরা Attractor বস্তুর অস্তিত্ব তৈরি করতে পারি।
var mover = new Mover();
var attractor = new Attractor();

draw = function() {
    background(50, 50, 50);

    attractor.display();
    mover.update();
    mover.display();
};
এটি একটি ভালো কাঠামো: একটি Mover এবং একটি Attractor অবজেক্ট নিয়ে একটি প্রোগ্রাম। ধাঁধাঁর শেষ অংশটুকু হল একটি অবজেক্টের উপর অপর অবজেক্টের আকর্ষণ পদ্ধতি বের করা। আমরা কীভাবে এই দুইটি অবজেক্টের মধ্যে সমন্বয় ঘটাবো?
কাঠামোগতভাবে, আমরা কয়েকটি পদ্ধতিতে এটা করতে পারি। নিচে কিছু উল্লেখ করা হল।
কাজফাংশন
1. একটু ফাংশন যা উভয় Attractor এবং Mover অবজেক্ট পায়:attraction(a, m);
2. Attractor অবজেক্টে একটি মেথড যা Mover অবজেক্ট পায়:a.attract(m);
3. Mover অবজেক্টে একটি মেথড যা Attractor অবজেক্ট পায়:mover.attractedTo(a);
4. Attractor অবজেক্টে একটি মেথড যা একটি Mover অবজেক্ট পায় এবং আকর্ষণ বল হিসেবে একটি PVector রিটার্ন করে। তারপর আকর্ষণ বলকে Mover অবজেক্টের applyForce() মেথডে পাঠানো হয়।`var f = a.calculateAttraction(m);
mover.applyForce(f);` |
দুটি অবজেক্টের মধ্যে সমন্বয় ঘটানোর আগে বিভিন্ন উপায়গুলি যাচাই করে নেওয়া ভালো এবং প্রতিটি পদ্ধতির জন্যেই আর্গুমেন্ট তৈরি করা যায়। শুরুতেই প্রথম পদ্ধতিটি বাদ দেই, কারণ Mover অথবা Attractor অবজেক্টের ক্ষেত্রে একটি সাধারণ ফাংশনের চাইতে একটি অবজেক্ট অরিয়েন্টেড ফাংশন অনেক ভালো। এখানে 2 অথবা 3 নং পদ্ধতির মধ্যে একমাত্র পার্থক্য হল যথাক্রমে বলা যে “attractor আকর্ষণ করে mover কে” অথবা “mover আকর্ষিত হয় attractor এর দিকে।” এখন আমরা যে কোর্সে আছি তার জন্য 4 নং পদ্ধতিটিই সবচেয়ে উপযুক্ত। অনেক সময় নিয়ে আমরা applyForce() মেথড তৈরি করেছি এবং আমার মনে হয় মনোযোগ দিয়ে অনুসরণ করলে উদাহরণগুলো আরও পরিষ্কার হবে।
পক্ষান্তরে, আমাদের আগে ছিল:
var f = new PVector(0.1, 0); // বানানো বল
mover.applyForce(f);
এখন আমাদের আছে:
var f = a.calculateAttraction(m); // দুইটি  বস্তুর মধ্যবর্তী আকর্ষণ বল
mover.applyForce(f);
এবং আমরা draw() ফাংশনকে এভাবে লিখতে পারি:
draw = function() {
    background(50, 50, 50);

    // আকর্ষণ বল প্রয়োগের হিসাব
    var f = a.calculateAttraction(m);
    mover.applyForce(f);

    attractor.display();
    mover.update();
    mover.display();
};
আমাদের প্রায় শেষ হয়ে গেছে। যেহেতু আমরা Attractor অবজেক্টের মধ্যে calculateAttraction() মেথডকে রাখতে চেয়েছি, এজন্য আমাদের আসলেই ফাংশনটি লিখতে হবে। ফাংশনটির একটি Mover অবজেক্ট নিয়ে একটি PVector রিটার্ন করবে। এই ফাংশনটির ভেতরে কি থাকবে? এতক্ষণ আমরা মহাকর্ষের যে সকল গাণিতিক হিসাব করলাম সেগুলো থাকবে!
Attractor.prototype.calculateAttraction = function(mover) {

    // বলের দিক কি?
    var force = PVector.sub(this.position, mover.position);    
    var distance = force.mag();
    force.normalize();

    // বলের মান কত?
    var strength = (this.G * this.mass * mover.mass) / (distance * distance);
    force.mult(strength);

    // বল রিটার্ন করে যাতে ব্যবহার করা যায়!
    return force;
};
শেষ হয়ে গেছে। আসলে, প্রায় শেষ। আমাদের ছোট আরেকটি কাজ করতে হবে। উপরের কোডটি আরেকবার দেখি। ভাগের চিহ্নটি দেখা যায় কি? যখনই এমন থাকবে তখনই আমাদের একটি বিষয় চিন্তা করতে হবে: যদি দূরত্ব অনেক অনেক ছোট কোন সংখ্যা হয় অথবা শূন্য হয় তাহলে কি হবে??! বাস্তবে, আমরা জানি 0 কে কোন সংখ্যা দিয়ে ভাগ করা যায় না এবং যদি কোন সংখ্যাকে যেমন 0.0001 এরকম সংখ্যা দিয়ে ভাগ করতেই হয়, তাহলে তা ওই সংখ্যাকে 10,000 দিয়ে গুণ করার সমতুল্য! সঠিক, এটিই হল বাস্তব-জগতে মহাকর্ষের শক্তির আসল সূত্র, কিন্তু আমরা তো বাস্তব জগতে নেই। আমরা ProcessingJS এর জগতে আছি। আর ProcessingJS এর জগতে, mover অনেক, অনেক বড় হতে পারে, প্রায় attractor এর সমান এবং বল এতই শক্তিশালী হতে পারে যে mover পর্দার বাহিরে ঊড়ে যেতে পারে। এজন্য এই সূত্র দিয়ে আমাদের বাস্তবধর্মী চিন্তা নিয়ে দূরত্বের মাপ নির্দিষ্ট করে দেওয়া উচিত। Mover আসলে যেখানেই থাকুক না কেন, attractor থেকে আমরা একে কখনই 5 পিক্সেল থেকে কাছে অথবা 25 পিক্সেল দূরে যেতে দেবো না।
distance = constrain(distance, 5, 25);
এই কারণেই আমাদের ন্যূনত্বম এবং সর্বোচ্চ দূরত্ব নির্দিষ্ট করে দিতে হবে। যদি mover, ধরি, attractor থেকে 500 পিক্সেল দূরে থাকে (অসম্ভব নয়), তাহলে আমরা বলকে 250,000 দিয়ে ভাগ করবো। এক্ষেত্রে বলটি এতই ক্ষুদ্র হতে পারে যে আমাদের মনে হতে পারে যে আমরা কোন বলই প্রয়োগ করছি না।
এখন, কেমন বৈশিষ্ট্য চাই তা সম্পূর্ণ নিজ ইচ্ছার উপর নির্ভর করবে। কিন্তু যদি চাই যে স্বাভাবিক একটি আকর্ষণ বল যেন বিরাজ করে যা বেশি ছোটও নয় আবার খুব শক্তিশালীও নয়, সেক্ষেত্রে দূরত্বকে সীমাবদ্ধ রাখা সবচাইতে উপযুক্ত পদ্ধতি।
এখন এটাকে একটি প্রোগ্রামে পরিণত করি। Mover অবজেক্টটি একদম অপরিবর্তিত আছে, কিন্তু আমাদের প্রোগ্রামে নতুন একটি Attractor অবজেক্ট আছে এবং তাদের মধ্যে সমন্বয়কারী কোড আছে। মাউস দিয়ে attractor কে নিয়ন্ত্রণ করার কোড প্রোগ্রামে দিয়ে দেওয়া আছে, যাতে সহজেই ক্রিয়া-প্রতিক্রিয়া দেখা যায়।
অবশ্য, আমরা এই উদাহরণটিতে অ্যারে ব্যবহার করে অনেকগুলি Mover অবজেক্ট নিতে পারি, যেমন আগের উদাহরণে করা হয়েছিল। আমাদের প্রোগ্রামে আমরা প্রধান যে পরিবর্তনটি করেছি তা হল Mover অবজেক্ট এখন ভর (mass), x এবং y (যেরুপ আমরা আগে করেছি) নেয়, Mover সম্বলিত অ্যারে সংজ্ঞায়িত করেছি এবং সেই অ্যারেতে লুপ করে পৃথক পৃথক সময়ে প্রতিটি অবজেক্টের উপর আকর্ষণ বলের হিসাব বের করেছি:
var movers = [];
var attractor = new Attractor();

for (var i = 0; i < 10; i++) {
    movers[i] = new Mover(random(0.1, 2), random(width), random(height));
}

draw = function() {
    background(50, 50, 50);

    attractor.display();
    for (var i = 0; i < movers.length; i++) {
        var force = attractor.calculateAttraction(movers[i]);
        movers[i].applyForce(force);

        movers[i].update();
        movers[i].display();
    }
};

এই "প্রাকৃতিক সিমুলেশন" কোর্সটি নেওয়া হয়েছে Daniel Shiffman (ড্যানিয়েল শিফম্যান) এর লেখা "The Nature of Code" (কোডের প্রকৃতি) থেকে এবং এটি ক্রিয়েটিভ কমন্সের এট্রিবিউশন-নন কমার্শিয়াল 3.0 আনপোরটেড লাইসেন্সের অধিনস্ত।

আলোচনায় অংশ নিতে চাও?

কোন আলাপচারিতা নেই।
ইংরেজি জানো? খান একাডেমির ইংরেজি সাইটে আরো আলোচনা দেখতে এখানে ক্লিক কর।