2008-10-13 23 views
17

इंटरनेट एक्सप्लोरर के लिए अपने स्वयं के वीएमएल प्रारूप पर आधारित एसवीजी कार्यान्वयन पर काम करते हुए मुझे एक वीएमएल अंडाकार चाप के लिए एक एसवीजी अंडाकार चाप के अनुवाद की समस्या आई। अंडाकार पर दो अंक और अंडाकार सीमा बॉक्सदो बिंदुओं और त्रिज्या के आकार से एक अंडाकार के केंद्र की गणना कैसे करें

के आकार के लिए निर्देशांक के दो जोड़े: अंडाकार पर दो अंक और दायरों की लंबाई, एसवीजी में एक चाप द्वारा दिया जाता है के लिए दो कोण:

VML में एक चाप द्वारा दिया जाता है

तो, सवाल यह है कि: उनके निर्देशांक के दो जोड़े को अंडाकार पर दो बिंदुओं के कोण कैसे व्यक्त करें। एक मध्यवर्ती प्रश्न हो सकता है: अपने वक्र पर बिंदुओं की एक जोड़ी के निर्देशांक द्वारा एक अंडाकार का केंद्र कैसे खोजें।

अद्यतन: चलो एक पूर्व शर्त है कि एक अंडाकार सामान्य रूप से रखा जाता है (इसके त्रिज्या रैखिक समन्वय प्रणाली धुरी के समानांतर होते हैं), इस प्रकार कोई रोटेशन लागू नहीं होता है।

अद्यतन: यह सवाल svg से संबंधित नहीं है: अंडाकार तत्व, बल्कि करने के लिए "एक" अंडाकार चाप svg में आदेश: पथ तत्व (SVG Paths: The elliptical arc curve commands)

उत्तर

21

तो यहाँ समाधान है:

एक अंडाकार की parametrized सूत्र:

 
x = x0 + a * cos(t) 
y = y0 + b * sin(t) 

आइए पुट में जाना जाता है यह करने के लिए दो अंक के निर्देशांक:

 
x1 = x0 + a * cos(t1) 
x2 = x0 + a * cos(t2) 
y1 = y0 + b * sin(t1) 
y2 = y0 + b * sin(t2) 

अब हम एक प्रणाली है 4 चर के साथ समीकरणों का केंद्र: अंडाकार केंद्र (x0/y0) और दो कोण टी 1, टी 2

आइए क्रम में घटाना समीकरणों केंद्र से छुटकारा पाने के निर्देशांक:

 
x1 - x2 = a * (cos(t1) - cos(t2)) 
y1 - y2 = b * (sin(t1) - sin(t2)) 

यह फिर से लिखा जा सकता है (उत्पाद करने वाली राशि पहचान सूत्रों के साथ) के रूप में:

 
(x1 - x2)/(2 * a) = sin((t1 + t2)/2) * sin((t1 - t2)/2) 
(y2 - y1)/(2 * b) = cos((t1 + t2)/2) * sin((t1 - t2)/2) 

के समीकरण में से कुछ की जगह दो:

 
r1 = sin(a1) * sin(a2) 
r2 = cos(a1) * sin(a2) 
:

 
r1: (x1 - x2)/(2 * a) 
r2: (y2 - y1)/(2 * b) 
a1: (t1 + t2)/2 
a2: (t1 - t2)/2 

फिर हम सरल समीकरण प्रणाली मिल

दूसरे से पहले समीकरण डिवाइडिंग पैदा करता है:

 
a1 = arctan(r1/r2) 

पहले समीकरण को यह परिणाम जोड़ना देता है:

 
a2 = arcsin(r2/cos(arctan(r1/r2))) 

या, सरल (ट्रिग की रचनाओं और उलटा ट्रिग कार्यों का उपयोग कर):

 
a2 = arcsin(r2/(1/sqrt(1 + (r1/r2)^2))) 

या इससे भी अधिक सरल:

 
a2 = arcsin(sqrt(r1^2 + r2^2)) 

अब आरंभिक चार-समीकरण प्रणाली को आसानी से हल किया जा सकता है और सभी कोणों के साथ-साथ ग्रहण केंद्र समन्वय भी मिल सकते हैं।

+2

स्पष्ट होने के लिए: t1 = a1 + a2, t2 = a1-a2, x0 = x1 - a * cos (t1), y0 = वाई 1 - बी * पाप (टी 1) – AndrewS

+1

क्या आप एक एसवीजी आर्क से एक वीएमएल आर्क में कनवर्ट करने का उदाहरण पोस्ट कर सकते हैं? जैसे "ए 80 80 0 1 0 200 200" त्रिज्या 80 से 200,200 की घड़ी की बड़ी चाप पैदा करता है। यह वीएमएल में कैसे दोहराया जा सकता है? धन्यवाद! – DeadPassive

+0

इसके अलावा, y0 = y1 - b * sin (t1) सही है, या वह पाप होना चाहिए (टी 2)? – DeadPassive

1

एक अंडाकार केवल दो अंक द्वारा परिभाषित नहीं किया जा सकता। यहां तक ​​कि एक सर्कल (एक विशेष cased अंडाकार) भी तीन बिंदुओं द्वारा परिभाषित किया गया है।

यहां तक ​​कि तीन बिंदुओं के साथ, आप इन तीन बिंदुओं (सोच: रोटेशन) के माध्यम से अनंत अंडाकारों से गुज़रेंगे।

ध्यान दें कि एक बाउंडिंग बॉक्स अंडाकार के लिए एक केंद्र का सुझाव देता है, और शायद यह मानता है कि इसकी प्रमुख और मामूली अक्ष एक्स, वाई (या वाई, एक्स) अक्षों के समानांतर हैं।

+0

वास्तव में, मैं उस पर एक नोट जोड़ना भूल गया। अब करूँगा –

1

मध्यवर्ती प्रश्न काफी आसान है ... आप नहीं करते हैं। आप बाध्यकारी बॉक्स से एक अंडाकार के केंद्र का काम करते हैं (अर्थात्, बॉक्स का केंद्र अंडाकार का केंद्र है, जब तक कि अंडाकार बॉक्स में केंद्रित हो)।

आपके पहले प्रश्न के लिए, मैं अंडाकार समीकरण के ध्रुवीय रूप को देखता हूं, जो Wikipedia पर उपलब्ध है। आपको अंडाकार की सनकीता को भी काम करने की आवश्यकता होगी।

या आप बाध्यकारी बॉक्स से मूल्यों को बलपूर्वक बल दे सकते हैं ... यदि कोई बिंदु अंडाकार पर स्थित है और कोण से मेल खाता है, और बाउंडिंग बॉक्स में प्रत्येक बिंदु के माध्यम से फिर से काम करें।

+0

मैं svg में पथकीय arcs के बारे में बात कर रहा हूँ: पथ, एक अंडाकार नहीं। गणित के लिए, मैंने ध्रुवीय और रैखिक समन्वय प्रणालियों दोनों में समीकरणों को हल करने के कुछ तीन कागजात किए हैं, अभी भी कोई भाग्य नहीं है। –

+0

यह अभी भी एक ही प्रक्रिया होनी चाहिए। एक अंडाकार चाप अंडाकार के 2 'बाध्य बिंदु' के साथ एक अंडाकार का सिर्फ एक वर्ग है। बाध्य आयताकार आपको पूर्ण अंडाकार बनाने के लिए सारी जानकारी देने के लिए पर्याप्त होना चाहिए। फिर आपको समीकरण में कोणों को खिलाने की आवश्यकता है। – workmad3

+0

फिर से, मैंने प्रश्न ठीक से तैयार नहीं किया। यह आयताकार नहीं है जो दिया जाता है, लेकिन त्रिज्या के आकार। –

4

आपके द्वारा पोस्ट किए गए अंडाकार वक्र आर्क लिंक में link to elliptical arc implementation notes शामिल है।

वहां, आपको conversion from endpoint to centre parameterisation के लिए समीकरण मिलेगा।

मैट्रिक्स और वेक्टर गणना करने के लिए Sylvester.js का उपयोग करके an interactive demo of elliptical arc paths से लिया गया समीकरणों का मेरा जावास्क्रिप्ट कार्यान्वयन यहां दिया गया है।

// Calculate the centre of the ellipse 
// Based on http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter 
var x1 = 150; // Starting x-point of the arc 
var y1 = 150; // Starting y-point of the arc 
var x2 = 400; // End x-point of the arc 
var y2 = 300; // End y-point of the arc 
var fA = 1; // Large arc flag 
var fS = 1; // Sweep flag 
var rx = 100; // Horizontal radius of ellipse 
var ry = 50; // Vertical radius of ellipse 
var phi = 0; // Angle between co-ord system and ellipse x-axes 

var Cx, Cy; 

// Step 1: Compute (x1′, y1′) 
var M = $M([ 
       [ Math.cos(phi), Math.sin(phi)], 
       [-Math.sin(phi), Math.cos(phi)] 
      ]); 
var V = $V([ (x1-x2)/2, (y1-y2)/2 ]); 
var P = M.multiply(V); 

var x1p = P.e(1); // x1 prime 
var y1p = P.e(2); // y1 prime 


// Ensure radii are large enough 
// Based on http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters 
// Step (a): Ensure radii are non-zero 
// Step (b): Ensure radii are positive 
rx = Math.abs(rx); 
ry = Math.abs(ry); 
// Step (c): Ensure radii are large enough 
var lambda = ((x1p * x1p)/(rx * rx)) + ((y1p * y1p)/(ry * ry)); 
if(lambda > 1) 
{ 
    rx = Math.sqrt(lambda) * rx; 
    ry = Math.sqrt(lambda) * ry; 
} 


// Step 2: Compute (cx′, cy′) 
var sign = (fA == fS)? -1 : 1; 
// Bit of a hack, as presumably rounding errors were making his negative inside the square root! 
if((((rx*rx*ry*ry) - (rx*rx*y1p*y1p) - (ry*ry*x1p*x1p))/((rx*rx*y1p*y1p) + (ry*ry*x1p*x1p))) < 1e-7) 
    var co = 0; 
else 
    var co = sign * Math.sqrt(((rx*rx*ry*ry) - (rx*rx*y1p*y1p) - (ry*ry*x1p*x1p))/((rx*rx*y1p*y1p) + (ry*ry*x1p*x1p))); 
var V = $V([rx*y1p/ry, -ry*x1p/rx]); 
var Cp = V.multiply(co); 

// Step 3: Compute (cx, cy) from (cx′, cy′) 
var M = $M([ 
       [ Math.cos(phi), -Math.sin(phi)], 
       [ Math.sin(phi), Math.cos(phi)] 
      ]); 
var V = $V([ (x1+x2)/2, (y1+y2)/2 ]); 
var C = M.multiply(Cp).add(V); 

Cx = C.e(1); 
Cy = C.e(2); 
संबंधित मुद्दे