आपके स्केच में बादल प्रत्येक पॉलीगॉन एज के साथ एक निश्चित ओवरलैप के साथ खींची गई मंडलियों की एक श्रृंखला हैं।
भरे मूल क्लाउड आकृति को आकर्षित करने का एक आसान तरीका पहले बहुभुज को भरना होगा और फिर भरे बहुभुज के शीर्ष पर मंडलियों को आकर्षित करना होगा।
जब आप क्लाउड को आंशिक रूप से पारदर्शी रंग से भरना चाहते हैं तो वह दृष्टिकोण फ्लैट गिरता है, क्योंकि एक दूसरे के साथ और बेस पॉलीगॉन के साथ मंडलियों का ओवरलैप दो बार चित्रित किया जाएगा। यह क्लाउड वक्र पर छोटे कार्टून-स्टाइल ओवरहूट को भी याद करेगा।
क्लाउड खींचने का एक बेहतर तरीका पहले सभी मंडलियां बनाना है और उसके बाद अपने अगले पड़ोसी के साथ प्रत्येक सर्कल के अंतरंग कोण निर्धारित करना है। फिर आप सर्कल सेगमेंट के साथ पथ बना सकते हैं, जिसे आप भर सकते हैं। रूपरेखा में अंत कोण के लिए एक छोटे से ऑफसेट के साथ स्वतंत्र चाप शामिल होते हैं।
आपके उदाहरण में, क्लाउड आर्क के बीच की दूरी स्थिर है। पॉलीगॉन शिखर पर आर्क को बनाना आसान है जिससे दूरी दूरी को बनाकर और बहुभुज किनारे को उस दूरी से समान रूप से विभाजित किया जा सके।
जावास्क्रिप्ट में एक उदाहरण कार्यान्वयन (बहुभुज ड्रैगिंग के बिना) नीचे है। मैं सी # से परिचित नहीं हूं, लेकिन मुझे लगता है कि मूल एल्गोरिदम स्पष्ट है। कोड एक पूर्ण वेब पेज है, जिसे आप कैनवास का समर्थन करने वाले ब्राउज़र में सहेज सकते हैं और प्रदर्शित कर सकते हैं; मैंने फ़ायरफ़ॉक्स में इसका परीक्षण किया है।
क्लाउड खींचने के लिए फ़ंक्शन त्रिज्या, आर्क दूरी और डिग्री में ओवरशूट जैसे विकल्पों का एक ऑब्जेक्ट लेता है।मैंने छोटे बहुभुजों जैसे अपमानजनक मामलों का परीक्षण नहीं किया है, लेकिन चरम मामले में एल्गोरिदम को प्रत्येक पॉलीगॉन वर्टेक्स के लिए केवल एक चाप खींचना चाहिए।
बहुभुज को दक्षिणावर्त परिभाषित किया जाना चाहिए। अन्यथा, बादल क्लाउड कवर में एक छेद की तरह होगा। अगर यह कोने आर्क के चारों ओर कोई कलाकृतियों नहीं थे, तो यह एक अच्छी सुविधा होगी।
संपादित करें: मैंने नीचे क्लाउड एल्गोरिदम के लिए simple online test page प्रदान किया है। पृष्ठ आपको विभिन्न मानकों के साथ खेलने की अनुमति देता है। यह अच्छी तरह से एल्गोरिदम की कमियों को भी दिखाता है। (एफएफ और क्रोम में परीक्षण किया गया।)
कलाकृतियों तब होते हैं जब प्रारंभ और अंत कोण ठीक से निर्धारित नहीं होते हैं। बहुत उलझन वाले कोणों के साथ, कोने के बगल में चाप के बीच भी चौराहे हो सकती है। मैं तय कर दी है नहीं है, लेकिन मैं यह भी है कि बहुत muczh सोचा नहीं दिया जाता है।)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Cumulunimbus</title>
<script type="text/javascript">
function Point(x, y) {
this.x = x;
this.y = y;
}
function get(obj, prop, fallback) {
if (obj.hasOwnProperty(prop)) return obj[prop];
return fallback;
}
/*
* Global intersection angles of two circles of the same radius
*/
function intersect(p, q, r) {
var dx = q.x - p.x;
var dy = q.y - p.y;
var len = Math.sqrt(dx*dx + dy*dy);
var a = 0.5 * len/r;
if (a < -1) a = -1;
if (a > 1) a = 1;
var phi = Math.atan2(dy, dx);
var gamma = Math.acos(a);
return [phi - gamma, Math.PI + phi + gamma];
}
/*
* Draw a cloud with the given options to the given context
*/
function cloud(cx, poly, opt) {
var radius = get(opt, "radius", 20);
var overlap = get(opt, "overlap", 5/6);
var stretch = get(opt, "stretch", true);
// Create a list of circles
var circle = [];
var delta = 2 * radius * overlap;
var prev = poly[poly.length - 1];
for (var i = 0; i < poly.length; i++) {
var curr = poly[i];
var dx = curr.x - prev.x;
var dy = curr.y - prev.y;
var len = Math.sqrt(dx*dx + dy*dy);
dx = dx/len;
dy = dy/len;
var d = delta;
if (stretch) {
var n = (len/delta + 0.5) | 0;
if (n < 1) n = 1;
d = len/n;
}
for (var a = 0; a + 0.1 * d < len; a += d) {
circle.push({
x: prev.x + a * dx,
y: prev.y + a * dy,
});
}
prev = curr;
}
// Determine intersection angles of circles
var prev = circle[circle.length - 1];
for (var i = 0; i < circle.length; i++) {
var curr = circle[i];
var angle = intersect(prev, curr, radius);
prev.end = angle[0];
curr.begin = angle[1];
prev = curr;
}
// Draw the cloud
cx.save();
if (get(opt, "fill", false)) {
cx.fillStyle = opt.fill;
cx.beginPath();
for (var i = 0; i < circle.length; i++) {
var curr = circle[i];
cx.arc(curr.x, curr.y, radius, curr.begin, curr.end);
}
cx.fill();
}
if (get(opt, "outline", false)) {
cx.strokeStyle = opt.outline;
cx.lineWidth = get(opt, "width", 1.0);
var incise = Math.PI * get(opt, "incise", 15)/180;
for (var i = 0; i < circle.length; i++) {
var curr = circle[i];
cx.beginPath();
cx.arc(curr.x, curr.y, radius,
curr.begin, curr.end + incise);
cx.stroke();
}
}
cx.restore();
}
var poly = [
new Point(250, 50),
new Point(450, 150),
new Point(350, 450),
new Point(50, 300),
];
window.onload = function() {
cv = document.getElementById("cv");
cx = cv.getContext("2d");
cloud(cx, poly, {
fill: "lightblue", // fill colour
outline: "black", // outline colour
incise: 15, // overshoot in degrees
radius: 20, // arc radius
overlap: 0.8333, // arc distance relative to radius
stretch: false, // should corner arcs coincide?
});
}
</script>
</head>
<body>
<canvas width="500" height="500" id="cv"></canvas>
</body>
</html>
यह अब तक की सबसे अच्छी प्रतिक्रिया मैंने कभी StackOverflow पर प्राप्त हो गया है। काश मैं इस अविश्वसनीय प्रयास के लिए आपको और अधिक अंक दे सकता हूं। आपका कोड अच्छी तरह से संरचित, समझने में आसान है, और निर्विवाद रूप से प्रभावशाली है! धन्यवाद, एम ओहेम। – Laith
हालांकि एक छोटी सी समस्या है। यदि अंक (वर्ग बनाते हैं) निचले दाएं से शुरू होते हैं, ऊपर दाएं, ऊपरी बाएं और निचले बाएं, खींचे गए बादल विपरीत होते हैं। – chitgoks
@chitgoks: त्रुटि पोस्ट में है, कोड में नहीं। बहुभुज का अभिविन्यास परिभाषित किया जाना चाहिए, क्योंकि इसका उपयोग यह पता लगाने के लिए किया जाता है कि क्लाउड के "बाहरी" क्या है। पोस्ट घड़ी की दिशा में कहता है, लेकिन वाईएम के साथ एचटीएमएल कैनवास में ऊपर से नीचे तक, यह anticlockwise है। तो अपनी दूसरी और चौथी verices स्वैप करें, और आपको मिलना चाहिए। –