এই পোস্টের জন্য, y = f (t) যেখানে টি হল প্যারামিটার যেখানে আপনি পরিবর্তিত হন (সময় / অগ্রগতি) এবং y লক্ষ্যমাত্রার দূরত্ব। সুতরাং আমি 2D প্লটের পয়েন্টগুলির সাথে কথা বলব যেখানে অনুভূমিক অক্ষ সময় / অগ্রগতি এবং উল্লম্ব দূরত্ব।
আমি মনে করি আপনি প্রথম পয়েন্ট (0, 1) এবং চতুর্থ (শেষ) পয়েন্ট (1, 0) এর সাথে একটি ঘনক বেজিয়ার বক্র তৈরি করতে পারেন। দুটি মাঝারি পয়েন্টগুলি এই 1-বাই -1 আয়তক্ষেত্রের মধ্যে এলোমেলোভাবে (x = র্যান্ড, y = র্যান্ড) স্থাপন করা যেতে পারে। আমি এটি বিশ্লেষণযোগ্যভাবে যাচাই করতে পারছি না, তবে কেবল একটি অ্যাপলেট দিয়ে ঘুরে বেড়ানোর মাধ্যমে (হ্যাঁ, এগিয়ে যান এবং হাসবেন) মনে হয় বেজিয়ার বক্ররেখা কখনই এ জাতীয় বাধা দিয়ে কমবে না।
এটি আপনার প্রাথমিক ফাংশন বি (পি 1, পি 2) হবে যা পয়েন্ট পি 1 থেকে পয়েন্ট পি 2 এ অ-হ্রাস পাথ সরবরাহ করে।
এখন আপনি আব (পি (1) = (0, 1), পি (এন) = (1, 0)) উত্পন্ন করতে পারবেন এবং এই বক্ররেখার সাথে অনেকগুলি পি (আই) বেছে নিতে পারেন যে 1
মূলত, আপনি একটি "সাধারণ" পাথ তৈরি করছেন এবং তারপরে এটি ভাগে বিভক্ত হয়ে প্রতিটি বিভাগকে নতুন করে তৈরি করছেন।
যেহেতু আপনি একটি গাণিতিক ফাংশন চান: ধরুন উপরের পদ্ধতিটি একটি ফাংশন y = f (t, s) এ প্যাকেজ করা আছে যা আপনাকে বীজের s এর ক্রিয়াকলাপের জন্য দূরত্ব দেয়। আপনার প্রয়োজন হবে:
- প্রধান বেজিয়ার স্প্লাইনের 2 টি মাঝারি পয়েন্ট স্থাপনের জন্য 4 টি এলোমেলো সংখ্যা ((0, 1) থেকে (1, 0))
- প্রতিটি বিভাগের সীমানার জন্য এন -1 নম্বরগুলি যদি আপনার n অংশ থাকে (প্রথম বিভাগটি সর্বদা শুরু হয় (0, 1) অর্থাৎ t = 0 এবং শেষ প্রান্তটি (1,0) অর্থাৎ t = 1)
- বিভাগগুলির সংখ্যাটি এলোমেলো করতে চাইলে 1 নম্বর number
- বিভাগটির স্প্লাইনের মাঝের পয়েন্টগুলি রাখার জন্য আরও 4 টি সংখ্যা আপনার টিতে অবতরণ করছে
সুতরাং প্রতিটি বীজ নীচের একটি সরবরাহ করতে হবে:
- 0 এবং 1 এর মধ্যে 7 + n আসল সংখ্যা (আপনি যদি বিভাগগুলির সংখ্যা নিয়ন্ত্রণ করতে চান)
- 7 টি আসল সংখ্যা এবং 1 এর চেয়ে বড় একটি পূর্ণসংখ্যা (এলোমেলো সংখ্যার বিভাগগুলির জন্য)
আমি ধারণা করি আপনি কেবল বীজের হিসাবে সংখ্যার একটি অ্যারের সরবরাহ করে এর মধ্যে দুটিও অর্জন করতে পারেন। বিকল্পভাবে, আপনি বীজ হিসাবে এক নম্বর গুলি সরবরাহ করার মতো কিছু করতে পারেন এবং তারপরে বিল্ট-ইন র্যান্ডম নম্বর জেনারেটরটিকে র্যান্ড (গুলি), র্যান্ড (এস +1), র্যান্ড (এস + 2) এবং আরও কিছু দিয়ে কল করতে পারেন (বা এর সাথে আরম্ভ করুন) গুলি এবং তারপরে র্যান্ডেল কল করুন e নেক্সট নাম্বার)।
মনে রাখবেন যে পুরো ফাংশন এফ (টি, গুলি) অনেকগুলি অংশ নিয়ে গঠিত হলেও আপনি প্রতিটি টিয়ের জন্য একটি বিভাগকেই মূল্যায়ন করছেন। আপনি হবে , কারণ আপনি সেগুলির সাজাতে নিশ্চিত দুই অংশ ওভারল্যাপ করতে থাকবে, বারবার এই পদ্ধতিতে অংশ সীমানা নিরূপণ করা প্রয়োজন। আপনি সম্ভবত এই অতিরিক্ত কাজটি অপ্টিমাইজ করতে পারেন এবং মুক্তি পেতে পারেন এবং প্রতিটি কলের জন্য কেবলমাত্র একটি বিভাগের শেষ পয়েন্টগুলি খুঁজে পেতে পারেন তবে এখনই এটি আমার কাছে স্পষ্ট নয়।
এছাড়াও, বেজিয়ার কার্ভগুলি প্রয়োজনীয় নয়, উপযুক্তভাবে আচরণ করা স্প্লাইনটি করবে।
আমি একটি নমুনা মতলব বাস্তবায়ন তৈরি করেছি।
বেজিয়ার ফাংশন (ভেক্টরাইজড):
function p = bezier(t, points)
% p = bezier(t, points) takes 4 2-dimensional points defined by 2-by-4 matrix
% points and gives the value of the Bezier curve between these points at t.
%
% t can be a number or 1-by-n vector. p will be an n-by-2 matrix.
coeffs = [
(1-t').^3, ...
3*(1-t').^2.*t', ...
3*(1-t').*t'.^2, ...
t'.^3
];
p = coeffs * points;
end
উপরে বর্ণিত যৌগিক বেজিয়ার ফাংশন (প্রতিটি কলের জন্য কতটা মূল্যায়ন প্রয়োজন তা পরিষ্কার করার জন্য ইচ্ছাকৃতভাবে আবদ্ধ রেখে দেওয়া হয়েছে):
function p = bezier_compound(t, ends, s)
% p = bezier(t, points) takes 2 2-dimensional endpoints defined by a 2-by-2
% matrix ends and gives the value of a "compound" Bezier curve between
% these points at t.
%
% t can be a number or 1-by-n vector. s must be a 1-by-7+m vector of random
% numbers from 0 to 1. p will be an n-by-2 matrix.
%% Generate a list of segment boundaries
seg_bounds = [0, sort(s(9:end)), 1];
%% Find which segment t falls on
seg = find(seg_bounds(1:end-1)<=t, 1, 'last');
%% Find the points that segment boundaries evaluate to
points(1, :) = ends(1, :);
points(2, :) = [s(1), s(2)];
points(3, :) = [s(3), s(4)];
points(4, :) = ends(2, :);
p1 = bezier(seg_bounds(seg), points);
p4 = bezier(seg_bounds(seg+1), points);
%% Random middle points
p2 = [s(5), s(6)] .* (p4-p1) + p1;
p3 = [s(7), s(8)] .* (p4-p1) + p1;
%% Gather together these points
p_seg = [p1; p2; p3; p4];
%% Find what part of this segment t falls on
t_seg = (t-seg_bounds(seg))/(seg_bounds(seg+1)-seg_bounds(seg));
%% Evaluate
p = bezier(t_seg, p_seg);
end
যে স্ক্রিপ্টটি এলোমেলো বীজের জন্য ফাংশনটি প্লট করে (দ্রষ্টব্য যে এটিই একমাত্র জায়গা যেখানে র্যান্ডম ফাংশন বলা হয়, অন্যান্য সমস্ত কোডের এলোমেলো ভেরিয়েবলগুলি এই একটি এলোমেলো অ্যারে থেকে প্রচারিত হয়):
clear
clc
% How many samples of the function to plot (higher = higher resolution)
points = 1000;
ends = [
0, 0;
1, 1;
];
% a row vector of 12 random points
r = rand(1, 12);
p = zeros(points, 2);
for i=0:points-1
t = i/points;
p(i+1, :) = bezier_compound(t, ends, r);
end
% We take a 1-p to invert along y-axis here because it was easier to
% implement a function for slowly moving away from a point towards another.
scatter(p(:, 1), 1-p(:, 2), '.');
xlabel('Time');
ylabel('Distance to target');
এখানে একটি নমুনা আউটপুট:
এটি আপনার বেশিরভাগ মানদণ্ডকে মেটায় বলে মনে হচ্ছে। যাহোক:
- "কোণে" আছে। এটি আরও উপযুক্তভাবে বেজিয়ার কার্ভগুলি ব্যবহার করে উপযুক্ত হতে পারে।
- এটি "স্পষ্টতই" স্প্লাইচের মতো দেখায়, যদিও আপনি বীজকে না জেনে অবাস্তব সময়ের পরে এটি কী করবে তা আপনি সত্যিই অনুমান করতে পারবেন না।
- এটি খুব কমই কোণার দিকে খুব বেশি বিচ্যুত হয় (বীজ জেনারেটর বিতরণের সাথে খেলে এটি স্থির করা যেতে পারে)।
- কিউবিক বেজিয়ার ফাংশনটি এই সীমাবদ্ধতার দিক দিয়ে কোণার কাছাকাছি কোনও অঞ্চলে পৌঁছতে পারে না।
f'(x)>0
, তাই কোনও শব্দ কর্মের নিরঙ্কুশ মানটির স্বাভাবিকীকরণ সংহতকরণ আপনার সমস্ত প্রয়োজনীয়তা পূরণ করবে। দুর্ভাগ্যক্রমে আমি এটি গণনা করার কোনও সহজ উপায় জানি না, তবে সম্ভবত অন্য কেউ করেছে। :)