Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Рисование большого количества линий (http://www.flasher.ru/forum/showthread.php?t=152350)

RaVeN-Nikma 16.03.2011 13:55

Рисование большого количества линий
 
Руководство поставила в принципе тривиальную задачу, необходимо рисовать простой линейный график. Но есть одно "но", об которое я споткнулся. Необходимо рисовать огромное количество линий (100к и более), плюс при определенных событиях нужно перерисовывать все нарисованные линии (если изменилась ценовая шкала например).

Обычный метод lineTo, без всяких перерисовак, почему-то начинает через время все медленнее работать, загружает процессор сильнее с каждай новой линией, хотя выполняется команда lineTo с таким же интервалом как и ранее. Делать bitmap тоже не подходит т.к. это не решает проблемы перерисовки, при изменении шкалы.

Вообщем я пришел к выводу что нужна какая-то хитрость, чтобы не рисовать огромное количество линий, но визуально картинка бы не менялась. Рисовать каждую 10 или 20 точку не подходит, т.к. можно пропустить скачек на графике и просто не отобразить его.

Может у кого есть соображения по данной проблеме? (Перепробовал уже множество методов)

in4core 16.03.2011 14:03

Цитата:

Обычный метод lineTo, без всяких перерисовак, почему-то начинает через время все медленнее работать, загружает процессор сильнее с каждай новой линией, хотя выполняется команда lineTo с таким же интервалом как и ранее. Делать bitmap тоже не подходит т.к. это не решает проблемы перерисовки, при изменении шкалы.
Это как так битмап не решит? Пускай у вас там в коде - не визуально идут операции, потом перерисовка в битмап и добавление на сцену. Тормазов сильный не ьудет замечано. Я например тестировал на слабых компах - брал битмап 1200 * 1200 и прогонял его через таймер каждые 20 мск изменяя его графику - делал Noise как на телевизоре.

RaVeN-Nikma 16.03.2011 14:13

Проблему с рисованием решит, но не решит, когда потребуется перерисовать под новую Y шкалу. Дабы внести ясность: идут данные (цена Y, время X), когда цена достигает потолка, то шкала расширяется до нового лимита, и сталобыть предыдущие данные нужно отображать уже исходя что шкала Y уже не от 0 до 100$, а от 0 до 500$. Раздвигаться шкала Y может в зависимости от поступаемых данных. Да и при сильном resize, bitmap линии делает чуть ли не прозрачными

in4core 16.03.2011 14:16

Цитата:

Да и при сильном resize, bitmap линии делает чуть ли не прозрачными
Битмап создается из вектора. никаких ресайзов для битмапа у вас не будет...

RaVeN-Nikma 16.03.2011 14:27

Тоесть Вы предлагаете, при resize прорисовать 100к линий в Sprite из которого потом сделать bitmap и только bitmap отобразить? (если не делать ресайз bitmapa)

in4core 16.03.2011 14:30

Да именно так. потому что не добавляя на сцену рантаймом - память так не жрется, тем более на сцене нет векторной перерисовки

cleptoman 16.03.2011 14:36

рисуйте линии себе спокойно порционно. нарисовали , допустим 100 линий, загнали в битмапу, стерли и т.д.

RaVeN-Nikma 16.03.2011 14:54

Написал на быструю руку класс, исходя из ваших слов. Либо, я что-то не так делаю, либо это не подходит, ибо с каждой новой линией скорость падает.

Устанавливаем fps 100 и смотрим
Код AS3:

package 
{
 
        import flash.display.Graphics;
        import flash.display.MovieClip;
        import flash.events.Event;
        import flash.display.Sprite;
        import flash.display.Bitmap;
        import flash.display.BitmapData;
 
        public class test extends MovieClip
        {
 
                private var bitMAP:Bitmap = new Bitmap();
                private var bitMapDATA:BitmapData;
                private var graf:Sprite = new Sprite();
                private var count:uint = 0;
                private var step:Number = 0;
                private var equityArr:Vector.<Object> = new Vector.<Object>();
 
                public function test():void {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(e:Event = null):void {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
 
                        loadGrafik();
                }
 
                public function loadGrafik():void
                {
 
                        for (var i:int = 0; i < 10000; i++ ) {
                                equityArr.push( { day:"2011.03.23", time:"13:26", money:randomRange(40, 60) } );
                        }
 
                        step = (300 / 10000);
 
                        graf.graphics.lineStyle(2, 0x008cd2);
                        bitMapDATA = new BitmapData( 300, 200 );
                        addChild(bitMAP);
                        this.addEventListener(Event.ENTER_FRAME, createPoint);
                }
 
                private function randomRange(max:Number, min:Number = 0):Number
                {
                        return Math.random() * (max - min) + min;
                }
 
                private function createPoint(e:Event):void
                {
                        var vectorStartTime:Number = getTime();
 
                        graf.graphics.lineTo( (step*count) , equityArr[count].money);
                        bitMapDATA.draw( graf );
                        bitMAP.bitmapData = bitMapDATA;
                        count++;
 
                        var vectorTime:Number = (getTime() - vectorStartTime);
                        trace(vectorTime);
                }
 
                private function getTime():Number
                {
                        return (new Date()).getTime();
                }
 
        }
}

Добавлено через 19 минут
Кажется понял в чем проблема. Надо изменить функцию createPoint на

Код AS3:

private function createPoint(e:Event):void
                {
                        var vectorStartTime:Number = getTime();
 
                        var gr:Graphics = graf.graphics;
 
                        var st:Number = (step * count);
                        gr.lineTo( st , equityArr[count].money);
                        var rect:Rectangle = new Rectangle(st, 0, (300 - st), 200);
                        bitMapDATA.draw( graf, null, null, null, rect, false );
                        bitMAP.bitmapData = bitMapDATA;
 
                        gr.clear();
                        gr.lineStyle(2, 0x008cd2);
                        gr.moveTo( st , equityArr[count].money);
 
                        count++;
 
                        var vectorTime:Number = (getTime() - vectorStartTime);
                        trace(vectorTime);
                }


incoob 16.03.2011 15:54

Возможно, что, рисуя линию напрямую в bitmap, вы получите больший выигрыш в производительности. Тут рассказано о библиотеке, которая умеет такое делать.

GBee 16.03.2011 18:20

100К линий в графике, для просмотра человеком? Можно посмотреть, что за график в результате получается?

Добавлено через 13 минут
Не знаю, у меня моментом, правда я малек переписал.

Код AS3:

package 
{
 
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.display.Graphics;
        import flash.display.MovieClip;
        import flash.display.Sprite;
        import flash.events.Event;
 
        public class GRTest extends MovieClip
        {
 
                private var count:uint = 0;
                private var step:Number = 0;
                private var equityArr:Array;//Vector.<Object> = new Vector.<Object>();
 
                public function GRTest():void {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(e:Event = null):void {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
 
                        loadGrafik();
                }
 
                public function loadGrafik():void
                {
                        equityArr = [];
                        for (var i:int = 0; i < 10000; i++ ) {
                                equityArr.push( { day:"2011.03.23", time:"13:26", money:randomRange(40, 60) } );
                        }
 
                        step = (300 / 10000);
                        drawGraph(equityArr);
                }
 
                private function drawGraph(arr:Array):void
                {
                        var g:Graphics = graphics;
                        g.clear();
                        g.lineStyle(2, 0x008cd2);
                        var len:int = arr.length;
                        for(var i:int = 0; i<len; i++)
                        {
                                g.lineTo(step*i, equityArr[i].money);
                        }
                }
 
                private function randomRange(max:Number, min:Number = 0):Number
                {
                        return Math.random() * (max - min) + min;
                }
        }
}



Часовой пояс GMT +4, время: 08:54.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.