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

studentsimf 08.05.2013 23:40

Как стереть часть линии
 
Делаю простейший редактор для рисования. В котором можно рисовать только линиями. Возникла проблема в реализации стерки. Так и не смог сам побороть (
Подскажите как можно стереть/удалить часть нарисованной линии?
Маски и растр использовать нельзя, нужно именно в векторе удалять.

Первое что приходит на ум рисовать поверх спрайт и удалять его, поидее он должен затирать то что под ним, но он как отдельный обьект просто с верху ложиться (что не удивительно) и ничего не происходит/ (Во Flash IDE, похоже, что сделано именно так, спрайтом поверх)

Второе это юзать Vector.<IGraphicsData> считывать обьект и удалять точки по которым строятся линии, но это как то слишклм сложно... может есть попроще решение?

Idon'tKnow 09.05.2013 03:38

Вот есть идея. Просто перерисовывать линию белую, если нужно стереть. Не подходит такой вариант?

Код AS3:

package 
{
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.display.Graphics;
        import flash.events.MouseEvent;
 
        /**
        * ...
        */

        public class Main extends Sprite
        {
        private var container:Sprite;       
        private var simpleRect:Shape;
                public function Main():void
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                        container = new Sprite();
                        simpleRect = new Shape();
                        simpleRect.graphics.beginFill(0xFAAAFA);
                        simpleRect.graphics.lineStyle(1);
                        simpleRect.graphics.drawRect(100, 100, 300, 500);
                        container.addChild(simpleRect);
                        container.addEventListener(MouseEvent.MOUSE_OUT,  containerMouseLeftListener);
                        container.addEventListener(MouseEvent.MOUSE_OVER, containerAddListenerCleaner);
                        addChild(container);
                        simpleRect.graphics.lineStyle(20, 0xFFFFFF);
                }
 
                private function init(e:Event = null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
                        // entry point
                }
 
                private function containerCleanerListener(e:MouseEvent):void {
                        simpleRect.graphics.lineTo(e.target.mouseX, e.target.mouseY);
                        simpleRect.graphics.moveTo(e.target.mouseX, e.target.mouseY);
                }
 
                private function containerAddListenerCleaner(e:MouseEvent):void {
                        simpleRect.graphics.moveTo(e.target.mouseX, e.target.mouseY);
                        e.currentTarget.addEventListener(MouseEvent.MOUSE_MOVE, containerCleanerListener);
                }
 
                private function containerMouseLeftListener(e:MouseEvent):void {
                e.currentTarget.removeEventListener(MouseEvent.MOUSE_MOVE, containerCleanerListener);               
                }
 
        }
 
}


studentsimf 09.05.2013 03:51

Цитата:

Сообщение от Idon'tKnow (Сообщение 1132563)
Вот есть идея. Просто перерисовывать линию белую, если нужно стереть. Не подходит такой вариант?

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

Сейчас пробую пробегаться по векторному массиву... и удалять точки которые попадаются под руку)) но такое это кривое решение)))

Код AS1/AS2:

var v:Vector.<IGraphicsData>;
v = conrainerPaint.graphics.readGraphicsData(true);
 
for (var i : int = 0; i < v.length; i++)
{
        if (String(v[i]) ==  "[object GraphicsPath]")
        {
                if (GraphicsPath(v[i]).data.indexOf(int(conrainerPaint.mouseX)) != -1 && GraphicsPath(v[i]).data.indexOf(int(conrainerPaint.mouseY)) != -1)
                {
                        v.splice(i, 1);
                        conrainerPaint.graphics.clear();
                        conrainerPaint.graphics.drawGraphicsData(v);
                        return;
                }       
        }       
}


expl 09.05.2013 11:51

Вспомните, как происходит стирание в векторных редакторах - в том же Flash IDE. Там изменяется вектор, по которому проходят стиралкой.
И убрать точки здесь не достаточно - здесь надо искать точки пересечения области стиралки с линиями, дробить линию на куски, удалять куски, попавшие в область стирания.
А если у Вас не просто линии, а ещё и области заливки - задача становится ещё интереснее - придётся использовать хитрые алгоритмы по работе с контурами.

Но такого редактора я на flash не видел. Переходите на растр и не выпендривайтесь :)
... или рисуйте поверх закрашенные цветом фона контуры.

mikhailk 09.05.2013 12:58

Цитата:

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

Однако.
Есть известный факт - все, что можно сделать во FlashIDE, можно сделать напрямую на AS. Если посмотреть, как реализована стерка во FlashIDE, то мне кажется она сделана так:

1. Векторный объект представляется как растровый
2. Стерка работает с растровым
3. После завершения стирания векторный объект корректируется с учетом того, что осталось от растрового.

Последняя операция хорошо видна, потому что после того, как заканчиваешь стирать, фигуры и линии немного изменяются (результат не идеально соответствует тому, что осталось от растрового объекта).

expl 09.05.2013 13:17

Если посмотреть, насколько криво работает векторизатор растра в том же флеше, то с трудом в это верится.
Тем более - сложение/вычитание векторных контуров выглядит более оптимальным (и в boost-е реализовано). Оно и в poligonal(as3/haXe) реализовано, но щас эту либу нагуглить не могу.

Цитата:

Последняя операция хорошо видна, потому что после того, как заканчиваешь стирать, фигуры и линии немного изменяются (результат не идеально соответствует тому, что осталось от растрового объекта).
Да просто оптимизатором проходятся - избыток точек убирают, ИМХО.

Simplifier 09.05.2013 15:46

Можно ж просто режим смешивания ERASE пользовать для стерки

studentsimf 09.05.2013 16:26

Цитата:

Сообщение от expl (Сообщение 1132574)
А если у Вас не просто линии, а ещё и области заливки - задача становится ещё интереснее

Нет ТОЛЬКО линии!

Цитата:

Сообщение от expl (Сообщение 1132574)
Но такого редактора я на flash не видел. Переходите на растр и не выпендривайтесь :)
... или рисуйте поверх закрашенные цветом фона контуры.

Нет растр не подходит, так как итоговая картинка может быть любого размера хоть 50000 пикселей по ширине, пустой файл 5000Х5000 px в растре весит 45Mb, а в векторе ничего не весит, поэтому мне нужен именно вектор.

Кстати во флеше стирание линии происходит, видимо, наложением другого шейпа (белого) поверх линии, и последующего его удаления! Как бы сделать так же!
Проблема в том что я "програмист" с натяжкой, поэтому прошу помощи!

expl 09.05.2013 19:38

Нормальное решение:
1 При проведении стиралкой при каждом смещении мыши запоминаем положение курсора - получаем список точек.
2 При каждом смещении мыши в процессе ведения перерисовываем по этим точкам (зная размеры и форму стиралки) область цветом фона
3 После отпускания мыши строим по этому списку точек (зная размеры и форму стиралки) контур (просто список точек этого контура по/против часовой стрелке скорее всего)
4 Усиленно и люто гуглим алгоритмы обрезания прямых контуром
5 Берём список всех нарисованных прямых и режем каждую этим контуром, удаляя попавшие в контур и добавляя обрезки, не попавшие в контур.
6 перерисовываем все прямые по новым данным.

Примечание:
Ещё можно не искать контур, а сделать N разрезов - сколько было перемещений мыши простым квадратом (если стиралка квадратная). Может даже сразу при перемещении резать. Но это не так гладко будет смотреться. (Чтобы разрезать линию квадратом школьной математики то должно хватить, хотя попотеть придётся, там в условиях главное не запутаться)

Решение попроще:
1, 2 То же, что и в нормальном решении
3 Оставляем этот закрашенный контур как есть, не удаляя его с экрана (или перерисовываем на тот же слой, где линии)

Решение попроще с возможностью менять цвет фона потом:
Похоже на решение попроще, но теперь надо
Цитата:

смешивания ERASE пользовать для стерки
А это значит, что придётся организовать хитрую вложенность спрайтов, чтобы через стёртую область просвечивал фон.

studentsimf 10.05.2013 04:15

Цитата:

Сообщение от expl (Сообщение 1132630)
Нормальное решение:

Спасибо, это очевидное решение, мне бы реализацию геденить подсмотреть... самому велосипед нехочется придумывать, да и не осилю скорее всего.

Реально НИКТО в мире не заморачивался стиранием линий? я весь интернет перерыл уже...

Если уж не линии то хотя бы удаление отдельно взятого пути, при наведении на него стеркой, к примеру.
Это как оказалось тоже не простая задача, хиттест не повесиш. Сделал вариант смотрю точки из GraphicsPath.data и если совпадают с мышиной координатой то удаляю весь путь. Но все очень плохо с этим методом(

Монстры кода! Помогите! Мозг кипит уже!

нашел что то отдаленно напоминающее http://wonderfl.net/c/1NKA


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

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