2016-01-19 13 views
5

पर कुशलता से बहुत से अंक के साथ ड्राइंग चार्ट IOS पर कुशलतापूर्वक बहुत सारे बिंदुओं (10 000 तक) के साथ एक लाइन चार्ट खींचने का एक तरीका ढूंढ रहा हूं। ग्राफ को रीयल-टाइम डेटा मिलता है और उसे एक बार कई बार अपडेट करने की आवश्यकता होती है। मैं ग्राफ को कुशलता से आकर्षित करने का एक तरीका समझने की कोशिश कर रहा हूं, इसलिए यह CPU को अधिकतम नहीं करता है और ड्राइंग करते समय मुख्य थ्रेड को अवरुद्ध करता है।आईओएस

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

मुझे आईओएस पर बड़े डेटा सेटों को कुशल बनाने पर कुछ भी नहीं मिला है, लेकिन मुझे आशा है कि प्रदर्शन बढ़ाने के लिए जीपीयू का उपयोग करने के तरीके हैं।

+0

क्या आपको सभी 10k अंक आकर्षित करना है? यहां तक ​​कि एक आईपैड स्क्रीन पर, जो अत्यधिक अत्यधिक लगता है ... (क्षैतिज पिक्सल से अधिक अंक)। क्या आपने डेटा को छोटे सेट में औसत मान लिया है? – Hamish

+0

@ originaluser2 मैं पूरी तरह से सहमत हूं। मैं कुछ क्लाइंट काम कर रहा हूं और अभी तक इन कई बिंदुओं को चित्रित करने के विचार से बात करने में सक्षम नहीं हूं। – JonasG

+0

अच्छी तरह से यदि आप उन्हें मनाने में सक्षम हैं, औसत आपकी सबसे अच्छी शर्त है! मुझे संदेह है कि आप मेटल/ओपन जीएल में पूर्ण किए बिना जीपीयू का अधिक लाभ उठाने में सक्षम होंगे। मुझे पूरा यकीन है कि 'UIBezierPath' मुख्य रूप से कोर ग्राफिक्स का उपयोग हुड के नीचे करता है, और यह सब सीपीयू पर चलता है। – Hamish

उत्तर

0

मैं अंत में ओपन के साथ एक ग्राफ खींचने के लिए एक कार्यान्वयन पाया: https://github.com/syedhali/EZAudio/blob/master/EZAudio/EZAudioPlotGL.m

यह वास्तव में बहुत आसान है और प्रदर्शन में सुधार विशाल कर रहे हैं।

ए 7 चिप (या नए) वाले उपकरणों के लिए यह धातु के साथ ग्राफ को आकर्षित करने के लिए शायद तेज़ होगा, जो कि बहुत आसान होना चाहिए। ऐसा करने के तरीके पर कुछ मार्गदर्शिकाएं हैं: https://www.raywenderlich.com/77488/ios-8-metal-tutorial-swift-getting-started

1

मुझे कुछ साल पहले इस तरह की स्थिति थी (आईफोन 4 दिनों में वापस)।

मैं एक CGMutablePathRef जो मैं बाद में अंक के लिए पहला बिंदु के लिए CGPathMoveToPoint, और CGPathAddLineToPoint का उपयोग कर अंक जोड़ा हुआ करता था।

स्वीकार्य प्रदर्शन प्राप्त करने के लिए, मैंने डेटा बिंदुओं को एक सी सरणी में संग्रहीत किया (NSArray नहीं)। साथ ही, जब कोई बिंदु साजिश करते हैं, तो यदि उसके प्रदर्शन निर्देशांक अंतिम प्लॉट किए गए बिंदु के समान थे, तो मैंने कॉल को CGPathAddLineToPoint पर छोड़ दिया। (यह अक्सर तब होगा जब आपके पास पिक्सल की तुलना में अधिक डेटा पॉइंट हों)।

मुझे सटीक ड्राइंग समय याद नहीं है, लेकिन यह आश्चर्यजनक रूप से तेज़ था।

+0

यदि आप डेटा सेट को औसत करने में असमर्थ हैं, तो यह निश्चित रूप से अगला सबसे अच्छा विकल्प है। (पूर्ण धातु जा रहा है) – Hamish

0

UIBezierPath का उपयोग करके अंक प्लॉट करने की बजाय, आप CGBitmapContext सेट कर सकते हैं और फिर "हाथ से" बिंदुओं को प्लॉट कर सकते हैं, उदा।

color = (0xFF << 24) | (blue << 16) | (green << 8) | (red); // AABBGGRR 
for (loop = 0; loop < count; loop++) 
{ 
    index = indices[loop]; 
    self.pixels[index] = color; 
} 

जहां self.pixels वह बफर है जिसका उपयोग आप CGBitmapContext बनाने के लिए करते थे। फिर, drawRect में:

CGContextRef c = UIGraphicsGetCurrentContext(); 

CGImageRef image = CGBitmapContextCreateImage(self.imageContext); 
CGContextDrawImage(c, self.bounds, image); 
CGImageRelease(image); 

मुझे लगता है कि आप इस काफी तेजी (और छोटे) CGPath या UIBezierPath का उपयोग करने से होने के लिए मिल जाएगा।