2011-12-09 22 views
5

मैं ब्रेसेनहम के लाइन एल्गोरिदम के साथ चाप बनाने के लिए रास्ता खोज रहा हूं। यह एल्गोरिदम सही सर्कल खींचता है, लेकिन अगर मुझे ड्रॉ आर्क (0 से पीआई तक) की आवश्यकता होती है और इसे 30 डिग्री (उदाहरण के लिए) के लिए घुमाएं?सी ++ ब्रेसनहेम की लाइन एल्गोरिदम ड्रॉ खींचें और घुमाएं

void DrawCircle(HDC hdc,int x0, int y0, int radius) 
{ 
     int x = 0; 
     int y = radius; 
     int delta = 2 - 2 * radius; 
     int error = 0; 

     while(y >= 0) { 
       //SetPixel(hdc,x0 + x, y0 + y,pencol); 
       SetPixel(hdc,x0 + x, y0 - y,pencol); 
       //SetPixel(hdc,x0 - x, y0 + y,pencol); 
       SetPixel(hdc,x0 - x, y0 - y,pencol); 
       error = 2 * (delta + y) - 1; 
       if(delta < 0 && error <= 0) { 
         ++x; 
         delta += 2 * x + 1; 
         continue; 
       } 
       error = 2 * (delta - x) - 1; 
       if(delta > 0 && error > 0) { 
         --y; 
         delta += 1 - 2 * y; 
         continue; 
       } 
       ++x; 
       delta += 2 * (x - y); 
       --y; 
     } 
} 

उत्तर

3

1/2 सर्कल (पीआई) प्राप्त करने के लिए, केवल अपने सेट पिक्सेल रूटीन में से एक को कॉल करें। 30 डिग्री घूर्णन करने के लिए अपने चाप को कुछ ट्रिगर की आवश्यकता होती है। जब तक आपका एक्स/वाई अनुपात तन (30 डिग्री) के बराबर न हो, तब तक आप उपरोक्त लूप को चला सकते हैं, फिर वास्तव में तब तक ड्राइंग शुरू करें जब तक कि आपका अनुपात उस मूल्य को हिट न करे जब आप रोकना चाहते हैं। सबसे कुशल तरीका नहीं है, लेकिन यह काम करेगा। इसे बेहतर बनाने के लिए, आपको अपने शुरुआती 4 var मानों की पूर्व-गणना करने की आवश्यकता होगी। आप उपरोक्त रन से मूल्य ले सकते हैं और उन्हें प्रारंभिक मानों के रूप में प्लग कर सकते हैं और यह बहुत ही कुशल होगा।

क्या आपको उपरोक्त एल्गोरिदम Michael Abrash's Black Book सामान से मिला है? यदि नहीं, तो मैं इसके लिए तेजी से सर्कल/आर्क ड्राइंग पर संदर्भ के दूसरे बिंदु के रूप में Google के लिए Google होगा।

ठीक है, हां, चिपकने वाले लंबवत को वहां शामिल नहीं किया गया था। यहाँ कुछ मैं वेब Abrash से होने का दावा है कि पर पाया गया है:


/* One of Abrash's ellipse algorithms */ 

void draw_ellipse(int x, int y, int a, int b, int color) 
{ 
    int wx, wy; 
    int thresh; 
    int asq = a * a; 
    int bsq = b * b; 
    int xa, ya; 

    draw_pixel(x, y+b, color); 
    draw_pixel(x, y-b, color); 

    wx = 0; 
    wy = b; 
    xa = 0; 
    ya = asq * 2 * b; 
    thresh = asq/4 - asq * b; 

    for (;;) { 
     thresh += xa + bsq; 

     if (thresh >= 0) { 
      ya -= asq * 2; 
      thresh -= ya; 
      wy--; 
     } 

     xa += bsq * 2; 
     wx++; 

     if (xa >= ya) 
      break; 


     draw_pixel(x+wx, y-wy, color); 
     draw_pixel(x-wx, y-wy, color); 
     draw_pixel(x+wx, y+wy, color); 
     draw_pixel(x-wx, y+wy, color); 
    } 

    draw_pixel(x+a, y, color); 
    draw_pixel(x-a, y, color); 

    wx = a; 
    wy = 0; 
    xa = bsq * 2 * a; 

    ya = 0; 
    thresh = bsq/4 - bsq * a; 

    for (;;) { 
     thresh += ya + asq; 

     if (thresh >= 0) { 
      xa -= bsq * 2; 
      thresh = thresh - xa; 
      wx--; 
     } 

     ya += asq * 2; 
     wy++; 

     if (ya > xa) 
      break; 

     draw_pixel(x+wx, y-wy, color); 
     draw_pixel(x-wx, y-wy, color); 
     draw_pixel(x+wx, y+wy, color); 
     draw_pixel(x-wx, y+wy, color); 
    } 
} 

विचार किया जा रहा आप एक समय x4 पर वृत्त के एक 8 वीं आकर्षित और फिर तैयार की अन्य 8ths पाने के लिए फ्लिप। फिर भी आपके प्रश्न का सीधे उत्तर नहीं देते हैं। उस पर काम कर रहे हैं ...

फिर से, ऊपर दिए गए आपके कोड को काम करना चाहिए, आपको केवल शुरुआती और समापन स्थितियों को ध्यान से नियंत्रित करने की आवश्यकता है। Y> = 0 को आपकी 'आर्क' लंबाई को समाप्त करने के बाद जो भी हो, वह बनने की आवश्यकता है और शुरुआती मानों को आपके चाप की शुरुआत के रूप में गणना करने की आवश्यकता है।

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

+0

धन्यवाद, मैंने सोचा कि हमें समीकरण बदलना चाहिए, लेकिन मेरा संस्करण काम नहीं करता है। क्या आप उदाहरण दे सकते हैं? और यह माइकल एब्राश की ब्लैक बुक से नहीं है। – PePe

+0

हां, यह ग्राफिक्स प्रोग्रामिंग पुस्तक से ब्लैक बुक में शामिल अध्याय में नहीं था। मुझे पढ़ना याद आया और माना कि यह संकलन संस्करण में होगा। इसके लिए नेट पर चारों ओर खुदाई ... –

+0

धन्यवाद, लेकिन मैं ब्रेसनहेम के एल्गोरिदम का उपयोग करना पसंद करता हूं। – PePe

1

यकीन Bresenham के लिए आप की जरूरत नहीं है, वहाँ एक तेजी से कदम विधि शुरू की in this SO post, जहां केंद्र बिंदु, बिंदु और चाप कोण शुरू करने के लिए सेट कर सकते हैं। इसे मानदंड को रोकने की आवश्यकता नहीं है, क्योंकि यह पहले से ही एल्गोरिदम (आर्क कोण द्वारा) में शामिल है। यह तेजी से क्या बनाता है टेंगेंशियल और रेडियल आंदोलन कारकों का सटीकता है और वास्तविक पाश में कोई ट्रिगर फ़ंक्शन कॉल नहीं है, केवल गुणा करें, जोड़ें और घटाएं।

AFAIK वहाँ तरीकों के तीन प्रकार है:
ए) Bresenham तरह इंक्रीमेंटल
बी) पर उप-विभाजन विधि की तरह this
सी) चरण (या खंड) विधि

मैं कदम की एक धीमी गति से उदाहरण ले लेंगे विधि (इस का उपयोग नहीं करता है, तो गति महत्वपूर्ण है):

// I know the question is tagged c++, but the idea comes clear in javascript 
var start_angle = 0.5, end_angle = 1.1, r = 30; 
for(var i = start_angle; i < end_angle; i = i + 0.05) 
{ 
    drawpixel(50 + Math.cos(i) * r, y: 100 + Math.sin(i) * r); // center point is (50,100) 
} 

सुस्ती क्योंकि और पाप जो दोहराया जाता है (अनावश्यक) पाश में से आता है। उपर्युक्त एसओ पोस्ट में वर्णित अनुसार यह कोस और पाप को पूर्ववत करके हल किया जा सकता है। इसका मतलब है विशाल गति (शीर्ष 5 जावास्क्रिप्ट इंजन में औसत 12x)।

मैंने विभिन्न सर्कल और आर्क ड्राइंग एल्गोरिदम के गैर-पूर्ण-तुलनीय speedtest बनाए। ब्रेसनहेम तेज़ है, लेकिन शुरुआती और रोक लगाने वाले मानदंड तर्क को जोड़ने की जरूरत है, जो थोड़ी देर तक आलू को धीमा कर देता है। यदि आपको वास्तव में ब्रेसनहेम और आर्क की आवश्यकता है, तो मेरे पास इसके लिए कोई तैयार समाधान नहीं है और अभी तक ऐसा नहीं मिला है। यह निश्चित रूप से संभव है।वैसे, ब्रेकनहम (कम से कम जावास्क्रिप्ट में) की तुलना में सटीक ट्रिग का उपयोग करने की चरण विधि प्रदर्शन में इतनी खराब नहीं है। कृपया सी ++ और रिपोर्ट में परीक्षण करें।