Показать сообщение отдельно
Старый 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)
 
Ответить с цитированием