इस पद के लिए, y = f (t) जहां t वह पैरामीटर है जिसे आप बदलते हैं (समय / प्रगति) और y लक्ष्य के लिए दूरी है। इसलिए मैं 2D प्लॉट पर उन बिंदुओं के संदर्भ में बात करूंगा जहां क्षैतिज अक्ष समय / प्रगति है और ऊर्ध्वाधर दूरी है।
मुझे लगता है कि आप पहले (0, 1) और चौथे (अंतिम) बिंदु पर (1, 0) के साथ एक क्यूबिक बेजियर वक्र बना सकते हैं। दो मध्य बिंदुओं को इस 1-बाय -1 आयत के भीतर यादृच्छिक रूप से रखा जा सकता है (x = रैंड, y = रैंड)। मैं इसे विश्लेषणात्मक रूप से सत्यापित करने में असमर्थ हूं, लेकिन सिर्फ एक एप्लेट (हाँ, आगे बढ़ो और हँसो) के साथ खेलने से ऐसा लगता है कि इस तरह की बाधा के साथ बेजियर वक्र कभी कम नहीं होगा।
यह आपका प्रारंभिक कार्य b (p1, P2) होगा जो बिंदु p1 से बिंदु P2 तक एक गैर-घटता हुआ पथ प्रदान करता है।
अब आप ab (p (1) = (0, 1), p (n) = (1, 0)) उत्पन्न कर सकते हैं और इस वक्र के साथ p (i) का एक नंबर चुनें जैसे कि 1
अनिवार्य रूप से, आप एक "सामान्य" पथ उत्पन्न कर रहे हैं, और फिर इसे खंडों में तोड़कर प्रत्येक खंड को पुन: उत्पन्न कर रहे हैं।
चूंकि आप एक गणितीय कार्य चाहते हैं: मान लीजिए कि उपरोक्त प्रक्रिया एक फ़ंक्शन y = f (t, s) में पैक की गई है, जो आपको बीज s के कार्य के लिए t पर दूरी प्रदान करती है। आपको चाहिये होगा:
- मुख्य बेज़ियर रेखा के 2 मध्य बिंदु (से (0, 1) से (1, 0) रखने के लिए 4 यादृच्छिक संख्याएँ
- यदि आपके पास n सेगमेंट (हमेशा पहला सेगमेंट (0, 1) यानी टी = 0 पर शुरू होता है और अंतिम छोर पर (1,0) यानी टी = 1 है तो प्रत्येक सेगमेंट की सीमा के लिए एन -1 नंबर
- 1 नंबर यदि आप सेगमेंट की संख्या को यादृच्छिक करना चाहते हैं
- सेगमेंट की तर्ज के मध्य बिंदुओं को रखने के लिए 4 और संख्याएँ, आपकी टी भूमि पर
इसलिए प्रत्येक बीज को निम्नलिखित में से एक की आपूर्ति करनी चाहिए:
- 0 और 1 के बीच 7 + एन वास्तविक संख्या (यदि आप सेगमेंट की संख्या को नियंत्रित करना चाहते हैं)
- 7 वास्तविक संख्या और 1 से अधिक पूर्णांक (यादृच्छिक संख्या में सेगमेंट के लिए)
मुझे लगता है कि आप इन दोनों में से किसी एक को केवल बीज s के रूप में संख्या की आपूर्ति करके पूरा कर सकते हैं। वैकल्पिक रूप से, आप बीज के रूप में एक नंबर की आपूर्ति की तरह कुछ कर सकते हैं, और फिर रैंड (ओं), रैंड (s + 1), रैंड (s + 2) और इतने पर (या साथ आरंभ) के साथ अंतर्निहित यादृच्छिक संख्या जनरेटर को कॉल कर सकते हैं s और उसके बाद rand.NextNumber) पर कॉल करते रहें।
ध्यान दें कि भले ही पूरा फ़ंक्शन f (t, s) कई खंडों से बना है, आप केवल प्रत्येक t के लिए एक खंड का मूल्यांकन कर रहे हैं। आपको इस पद्धति के साथ खंडों की सीमाओं की बार-बार गणना करने की आवश्यकता होगी , क्योंकि आपको यह सुनिश्चित करने के लिए उन्हें क्रमबद्ध करना होगा कि कोई दो खंड ओवरलैप न हों। आप संभवतः इस अतिरिक्त कार्य से अनुकूलन कर सकते हैं और छुटकारा पा सकते हैं और केवल प्रत्येक कॉल के लिए एक सेगमेंट के समापन बिंदु ढूंढ सकते हैं, लेकिन अभी मेरे लिए यह स्पष्ट नहीं है।
इसके अलावा, बेज़ियर कर्व्स आवश्यक नहीं हैं, किसी भी उपयुक्त व्यवहार करने वाली तख़्ती करेंगे।
मैंने एक नमूना मैटलैब कार्यान्वयन बनाया।
बेज़ियर फ़ंक्शन (वेक्टरकृत):
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
, इसलिए किसी भी शोर फ़ंक्शन के पूर्ण मूल्य का सामान्यीकृत एकीकरण आपकी सभी आवश्यकताओं को पूरा करेगा। दुर्भाग्य से मुझे इसकी गणना करने का कोई आसान तरीका नहीं पता है, लेकिन शायद कोई और करता है। :)