Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование в широком смысле слова > Алгоритмика

Алгоритмика Об алгоритмах вообще; методы, обсуждения способов решения

Ответ
 
Опции темы
Старый 20.05.2013, 16:54   #1
is.SarCasm
Бывалый
 
Аватар для is.SarCasm
 
Регистрация: 17.05.2009
Адрес: Днепропетровск
Сообщений: 672
Написано 180 полезных сообщений
(для 428 пользователей)
Заливка контура (2д)

Делаю игру-рисовалку. Нужно реализовать нормальную заливку фигур.
Я использую что-то типа рекурсии и зарисовываю части не точками, а линиями.

В коде ниже я использую Unity3d, но там в принципе всё должно быть интуитивно понятно:

void Fill(IntVector2 pos, Texture2D canvas, Color newColor)
{
// For speed control
float time = Time.realtimeSinceStartup;
int  points=0;
// DEBUGGG


IntVector2 point;
Stack pixelStack = new Stack(); // point from where start filling
bool spanTop = false; // Does line above need to be filled?
bool spanBot = false; // below
Color oldColor = canvas.GetPixel(pos.x,pos.y); // Set color that will be replaced


pixelStack.Push(pos); // Start
while(pixelStack.Count>0) // Рекурсия
{
	point =  pixelStack.Pop() as IntVector2; // Get new point
	spanBot = false; spanTop = false;
	while(point.x>=0 && canvas.GetPixel(point.x,point.y)==oldColor) // FInd most left pixel
	{
		point.x--;
	}
	point.x++;
	
	// Start fill line from left to right
	while(point.x<canvas.width && canvas.GetPixel(point.x,point.y)==oldColor) // until we meet another pixel
	{
		canvas.SetPixel(point.x,point.y,newColor);
		
		// Is there line above needs filling?
		if(spanTop==false && point.y>0 && canvas.GetPixel(point.x,point.y-1)==oldColor)
		{
			IntVector2 newpoint = new IntVector2(point.x,point.y-1);
			pixelStack.Push(newpoint); // add new point from where we will start fill line
			spanTop = true;
			points++; // for debug
		} else if(spanTop==true && point.y>0 && canvas.GetPixel(point.x,point.y-1)!=oldColor) {
			spanTop = false;
		}
		
		// Below?
		if(spanBot==false && point.y<canvas.height && canvas.GetPixel(point.x,point.y+1)==oldColor)
		{
			IntVector2 newpoint = new IntVector2(point.x,point.y+1);
			pixelStack.Push(newpoint);
			spanBot = true;
			points++; // for debug
		} else if(spanBot==true && point.y<canvas.height && canvas.GetPixel(point.x,point.y+1)!=oldColor) {
			spanBot = false;
		}
		point.x++; // next pixet left->right
	}
	
}
time = time - Time.realtimeSinceStartup; // for debug
canvas.Apply(); // Change material (takes rly little time)


print("CalculateTime:"+(-time)+", points detected:"+points);
}
Разрешение полотна: 900х675
Первый тест:
Простое белое полотно

CalculateTime:0.7691972, points detected:674

Второй тест:
Очень сложная фигура, небольшая по площади

CalculateTime:0.3095117, points detected: 19011

(линии оказались быстрее чем точки, может прямоугольники быстрее линий? ;D)
(Offline)
 
Ответить с цитированием
Старый 20.05.2013, 17:58   #2
den
Дэвелопер
 
Аватар для den
 
Регистрация: 13.02.2010
Сообщений: 1,645
Написано 620 полезных сообщений
(для 2,419 пользователей)
Ответ: Заливка контура (2д)

Первый тест:
Простое белое полотно
(Offline)
 
Ответить с цитированием
Старый 20.05.2013, 18:20   #3
is.SarCasm
Бывалый
 
Аватар для is.SarCasm
 
Регистрация: 17.05.2009
Адрес: Днепропетровск
Сообщений: 672
Написано 180 полезных сообщений
(для 428 пользователей)
Ответ: Заливка контура (2д)

Texture2D.SetPixels
Using SetPixels can be faster than calling SetPixel repeatedly, especially for large textures. In addition, SetPixels can access individual mipmap levels.

Пытался использовать, но для неё нужен массив WxH, который создается очень долго и результат с 0.7 увеличивается до 0.85... Печаль.
(Offline)
 
Ответить с цитированием
Старый 20.05.2013, 18:51   #4
is.SarCasm
Бывалый
 
Аватар для is.SarCasm
 
Регистрация: 17.05.2009
Адрес: Днепропетровск
Сообщений: 672
Написано 180 полезных сообщений
(для 428 пользователей)
Ответ: Заливка контура (2д)

Хм, не могу придумать как уменьшить кол-во вызовов SetPixel\GetPixel, если это вообще возможно тут.
Думаю сделать второй способ, в котором вместо SetPixel\GetPixel я буду работать с массивом цветов, который скопирую в начале, а потом зарисую это SetPixels'ом, может и будет профит.
На какую скорость вообще стоит расчитывать? У меня даже в Paint.NET'е заливка некоторое время занимает (быстрее конечно чем у меня тут)
(Offline)
 
Ответить с цитированием
Старый 21.05.2013, 11:31   #5
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Ответ: Заливка контура (2д)

Читай пиксели в массив перед работой, обновляй массив, потом записывай весь буфер сразу в текстуру.
http://docs.unity3d.com/Documentatio...tPixels32.html
http://docs.unity3d.com/Documentatio...tPixels32.html
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Старый 21.05.2013, 13:15   #6
impersonalis
Зануда с интернетом
 
Аватар для impersonalis
 
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений
(для 20,935 пользователей)
Ответ: Заливка контура (2д)

В чём вопрос темы с позиции алгоритма? В рекурсии при заливке? Тогда:
вот тут рекурсия заменена на работу со списком.
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


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


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com