Форум 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=198158)

in4core 21.04.2013 02:10

диаграмма секторов
 
Решил сделать такую штучку ради интереса, с математикой не силен, поэтому рассуждал логически.
ВОобщем задача такая - на вход подается кол-во элементов ( секторов ) и их процентная ставка, от чего собственно зависит высота сектора ( это потом, не важно ) , - на выходе получаем диаграмму этих секторов, распределенных по кругу.
http://stackoverflow.com/questions/1...-like-this-one
По ссылке выше пример того, что хочу получить, только без черной сетки и всегда с дугой.
Вот собственно так начал решать эту задачку :

Код AS3:

public function drawDiagram(sectors:int , radius:Number , values:Array, triangulate:Boolean = false):void
                {
                        var diameter:Number = radius * 2;
                        var sectorMaxWidth:Number = 360 / sectors;
                        var angleRotation:Number = 360 / sectors;
                        var currentAngle:Number = angleRotation;
                        var arcHeight:Number = radius - Math.sqrt(Math.abs(((Math.pow(radius,2) - Math.pow(sectorMaxWidth / 2, 2)))));
 
                        var circle:Shape = new Shape();
                        circle.graphics.beginFill(0);
                        circle.graphics.drawCircle(0, 0, radius);
                        addChild(circle)
 
                        for (var i:int = 0; i < sectors; i++)
                        {
                                var firstSector:Shape = new Shape();
                                firstSector.graphics.beginFill(randomColor);
                                firstSector.graphics.lineStyle(1,0xFFFFFF)
                                firstSector.graphics.lineTo( -sectorMaxWidth  , -radius + arcHeight);
                                firstSector.graphics.curveTo( 0, -radius - arcHeight, sectorMaxWidth, -radius + arcHeight);
                                firstSector.graphics.lineTo(0, 0);
 
                                firstSector.rotation = currentAngle;
                                addChild(firstSector);
 
                                currentAngle += angleRotation;
 
                        }
 
                }
 
                private function get randomColor():int
                {
                        return Math.random()*0xFFFFFF;
                }

Собственно получается лажа, не могу понять именно в чем косяк, arcHeight ( взял формулу с нета ). Остальное собственно своими невеликими силами.
То есть по итогу, сектора должны занимать весь круг...

Wolsh 21.04.2013 03:14

1. С каких это пор curveTo стала рисовать дугу окружности?
2. Вы предлагаете нам самим писать тестовый проект, чтобы узнать, в чем именно у Вас "получается лажа"?

Simplifier 21.04.2013 03:47

Формулы - полный бред на вид. Где ты их выкопал?
Вот, например, это:
Код AS3:

var sectorMaxWidth:Number = 360 / sectors;

Ширину считают, поделив градусы на количество 0_о

Wolsh 21.04.2013 11:19

Вложений: 1
Циферки можно менять/удалять/добавлять новые:
SectorDiagram.swf   (2.2 Кб)

drawDiagram.as
Код AS3:

package  
{
        import flash.display.DisplayObjectContainer;
        import flash.display.Graphics;
        import flash.display.Sprite;
        /**
        * ...
        * @author wolsh
        */

        public function drawDiagram (container:DisplayObjectContainer, radius:Number, values:Array):void
        {
                var k:Number = radius / Math.max.apply(null, values);
                var sectors:uint = values.length;
                var sectorAngle:Number = 2 * Math.PI / sectors;
 
                for (var i:uint = 0; i < sectors; i++)
                {
                        var color:uint = 0x808080 + Math.random() * 0x404040;
                        var startAngle:Number = i * sectorAngle;
                        var sectorRadius:Number = values[i] * k;
                        var sector:Sprite = new Sprite();
                        container.addChild(sector);
 
                        // calculate fragments (18 gradians max at one step for cute round curve)
                        var frags:Number = Math.abs( Math.ceil(sectorAngle * 10 / Math.PI) );
                        if (sectorAngle < 0) frags += 1;
                        var fragAngle:Number = sectorAngle / frags;
                        // control points radius
                        var controlOutRadius:Number = sectorRadius / Math.cos( -fragAngle / 2);
                        // start drawings
                        var g:Graphics = sector.graphics;
                        g.lineStyle(1, 0xFFFFFF)
                        g.beginFill(color);
                        g.moveTo(0, 0);
                        var startX:Number = sectorRadius * Math.cos(startAngle);
                        var startY:Number = sectorRadius * Math.sin(startAngle);
                        g.lineTo(startX, startY);
                        // arc
                        for (var j:uint = 1; j < frags + 1; j++)
                        {
                                var aA:Number = startAngle + fragAngle * j;
                                var aX:Number = sectorRadius * Math.cos(aA);
                                var aY:Number = sectorRadius * Math.sin(aA);
                                var cA:Number = aA - fragAngle / 2;
                                var cX:Number = controlOutRadius * Math.cos(cA);
                                var cY:Number = controlOutRadius * Math.sin(cA);
                                g.curveTo(cX, cY, aX, aY);
                        }
                        g.lineTo(0, 0);
                }
        }
}

Main.as
Код AS3:

package 
{
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.text.TextField;
        import flash.text.TextFormat;
 
        /**
        * ...
        * @author wolsh
        */

        public class Main extends Sprite
        {
                private var _txt:TextField;
                private var _diagram:Sprite;
 
                public function Main():void
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(e:Event = null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
                        // entry point
                        _diagram = new Sprite();
                        addChild(_diagram);
                        _diagram.x = _diagram.y = 220;
                        var data:Array = [300, 250, 320, 115, 234, 52, 186, 256, 370];
                        drawDiagram(_diagram, 200, data);
                        _txt = new TextField();
                        _txt.defaultTextFormat = new TextFormat("Arial", 18, 0x808080);
                        _txt.wordWrap = true;
                        _txt.type = "input";
                        _txt.background = true;
                        _txt.backgroundColor = 0x505050;
                        addChild(_txt);
                        _txt.x = 440;
                        _txt.y = 180;
                        _txt.width = 310;
                        _txt.height = 100;
                        _txt.text = data.toString();
                        _txt.addEventListener(Event.CHANGE, handlerChange);
                }
 
                private function handlerChange(event:Event):void
                {
                        var data:Array = _txt.text.split(',');
                        _diagram.removeChildren();
                        drawDiagram(_diagram, 200, data);
                }
 
        }
 
}


Babylon 21.04.2013 14:02

in4core, если у вас много свободного времени могу подкинуть задачку на тему Трансформ менеджеров.
На сцене есть три спрайта, вложенных друг в друга и так же на сцене есть трансформ менеджер. Требуется корректно драгать им каждый из трех спрайтов.

shaman4d 21.04.2013 14:11

На что надеялся ТС ? Наверное на то что дадут ссылку на готовове решение....

in4core 21.04.2013 15:54

Wolsh - круто, спасибо, все таки заинтересовала тебя задача. Но тебе видишь все понятно и просто, а я почитав код половину не понимаю. Если тебе не лень давай порассуждаем : какие реально данные нам нужны?
1. Ширина сектора ( расстояние между 2мя конечными точками )
2. Высота дуги сектора.
3. Угол поворота

Что имеем изначально : только радиус и кол-во секторов. Будем рассуждать в контексте , что все значения 1,1,1,1,1 , то есть получим круг.
И так если у нас есть радиус и кол-во, угол поворота каждого сектора 360 / numSectors . Думаю тут ошибок нет.
Ширина сектора ? - вот тут нам нужна формула , какая ?
http://www.mathopenref.com/arclength.html - вот что я вижу. Где C = 360 / numSectors. Но как я понимаю, здесь нужно переводить в другую систему измерения или нет?
Далее высота дуги http://www.mathopenref.com/arcradius.html так же формула, и видимо так же перевод в другую систему.
Что получается в итоге - 1 цикл, все данные инициализируются 1 раз до цикла. Я так вижу решение этой задачи, у тебя же получается в 10 раз больше данных , формул и т.п. Вообщем понятно, что любую задачу можно решить разными способами, мне хочется именно моим попробовать, вопрос лишь в том, что я не понимаю, и где не так рассуждаю, прошу пояснить, если не сложно!

Добавлено через 2 минуты
Babylon
Твоя задача давно решена, есть готовая библиотека TransformTool найдешь в нете, другой вопрос , что она очень косячная , и мне было оч тяжело переписывать ее под себя в одном из проектов, ну ниче справился

Babylon 21.04.2013 16:36

А то я про эти библиотеки ничего не знаю...

Wolsh 21.04.2013 16:50

Что такое "ширина сектора"?
У сектора есть угол (в нашем случае тот же 360 / numSectors).
Есть две прямые линии — радиус сектора, и дуга этого радиуса.
Дуга это не любая кривая, и уж точно не кривая второго порядка, а часть окружности. Ее не нарисовать за один проход curveTo(). Будет.. кривая Кривая. Для 200-360 секторов это не будет заметно, но два будут выглядеть яйцами. Чтобы кривая была похожа на часть окружности, надо рисовать ее фрагментиками градусов по 15-30 (зависит от длины дуги конечно, но в среднем так). Поэтому угол сектора делится на фрагменты и во внутреннем цикле рисуются эти короткие кривые не более 18 градусов.
Нельзя посчитать "высоту дуги" один раз для всех секторов — она у всех разная, потому что радиус дуги разный (из values). Однако поскольку все фрагменты одного сектора имеют один радиус и одинаковый угол дуги, длина луча к контрольным точкам кривых тоже одинаковая и считается один раз для сектора.
Я не рисую все сектора "от ноля" с последующим поворотом спрайта. Мне так не нравится. Я рисую сектор там где он должен быть, поэтому первая точка дуги тоже ищется тригонометрически (можно через Point.polar()).
Для меня фраза "понятно, что любую задачу можно решить разными способами" приемлема только в том контексте, в котором задача действительно решается. Рисование окружности одним проходом curveTo извините, не решается никак. Какую бы "высоту дуги" Вы не посчитали.

Можно еще треугольные маски накладывать на красивые окружности от drawCircle(). Маску можно без дуги рисовать, обычный прямоугольный треугольник — посчитать проще, тем более если от нулевой оси.

in4core 21.04.2013 17:02

Цитата:

не решается никак. Какую бы "высоту дуги" Вы не посчитали.
Вот это видимо ключевая фраза, того, почему у меня не получалось все время. Однако не могу понять почему так, да если values разные - получается, как мы видим на рисунке разные дуги, но если все values одинаковые и образуют в итоге круг, то почему нельзя решить одним проходом? или можно? То есть когда я начинал решать задачу, мне стало непонятно именно это, ведь я сразу не стал лезть на values , а хотел получить круг из секторов


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

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