Показать сообщение отдельно
Старый 20.12.2012, 20:46
Hauts вне форума Посмотреть профиль Отправить личное сообщение для Hauts Посетить домашнюю страницу Hauts Найти все сообщения от Hauts
  № 10  
Ответить с цитированием
Hauts
 
Аватар для Hauts

блогер
Регистрация: Feb 2008
Адрес: Россия, Новосибирск, Академгородок
Сообщений: 2,113
Записей в блоге: 1
Отправить сообщение для Hauts с помощью ICQ Отправить сообщение для Hauts с помощью Skype™
Попробовал. Получается так себе. Очевидно, что смещение точек зачастую нерациональное, не такое, как хотелось бы.

Код AS3:
package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
 
	/**
	 * ...
	 * @author Hauts
	 */
	public class Main extends Sprite
	{
		[Embed(source="../lib/image.png")]
		private var _imageClass:Class;
		private var _image:Bitmap;
		private var _bimapData:BitmapData;
		private var _debugDrawClip:Sprite;
		private var _imageContainer:Sprite;
		private var _results:Array;
 
		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
 
			stage.scaleMode = StageScaleMode.NO_SCALE
 
			_results = [];
 
			_image = new _imageClass() as Bitmap
			_image.smoothing = true;
			_imageContainer = new Sprite();
			addChild(_imageContainer)
			_imageContainer.addChild(_image);
 
			_debugDrawClip = new Sprite();
			addChild(_debugDrawClip)
 
			stage.addEventListener(MouseEvent.CLICK, clickHandler);
 
			nextTest()
		}
 
		private function clickHandler(e:MouseEvent):void
		{
			nextTest()
		}
 
		private function nextTest():void
		{
			_image.rotation = (Math.random() - 0.5) * 3
			_image.scaleX = 0.9 + Math.random() * 0.1
			_bimapData = new BitmapData(_imageContainer.width, _imageContainer.height, false, 0xFFFFFFFF);
			_bimapData.draw(_imageContainer)
 
			var points:Array = generateCoords(_bimapData, 25);
			_results.push(points);
 
			drawPoints(_debugDrawClip.graphics, points);
 
			if (_results.length > 1)
			{
				drawWays(_debugDrawClip.graphics)
			}
		}
 
		private function drawWays(gr:Graphics):void
		{
			if (_results.length > 1)
			{
				var curPoints:Array = _results[_results.length - 1]
				var prevPoints:Array = _results[_results.length - 2]
				var totalPoints:int = curPoints.length;
				for (var k:int = 0; k < totalPoints; k++)
				{
					gr.moveTo(prevPoints[k].x, prevPoints[k].y)
					gr.lineStyle(1, 0x00FF00);
					gr.lineTo(curPoints[k].x, curPoints[k].y)
				}
			}
		}
 
		private function drawPoints(gr:Graphics, points:Array):void
		{
			var totalPoints:int = points.length;
			gr.clear();
			gr.beginFill(0xFF0000);
			var k:int
			for (k = 0; k < totalPoints; k++)
			{
				gr.drawCircle(points[k].x, points[k].y, 3);
			}
			gr.endFill();
		}
 
		private function generateCoords(bitmapData:BitmapData, totalPoints:int = 100):Array
		{
			var activeRect:Rectangle = bitmapData.getColorBoundsRect(0xFFFFFFFF, 0xFF000000, true);
			var points:Array = [];
			var rectSize:Number = activeRect.width * activeRect.height
			var spacePerPoint:Number = rectSize / totalPoints;
			var pointRadius:Number = Math.sqrt(spacePerPoint) / 2;
			var k:int
			var j:int
			var p1:Point
			var p2:Point
			var newPoint:Point
			for (k = 0; k < totalPoints; k++)
			{
				newPoint = new Point();
				newPoint.x = activeRect.left + activeRect.width / 2 + Math.cos(k / totalPoints * Math.PI * 2);
				newPoint.y = activeRect.top + activeRect.height / 2 + Math.sin(k / totalPoints * Math.PI * 2);
				points.push(newPoint)
			}
			for (var i:Number = pointRadius; i >= 0; i -= 0.01)
			{
				for (k = 0; k < totalPoints; k++)
				{
					p1 = points[k];
					for (j = 0; j < totalPoints; j++)
					{
						if (k != j)
						{
							p2 = points[j] as Point;
 
							var dx:Number = p1.x - p2.x;
							var dy:Number = p1.y - p2.y;
 
							var distance:Number = Math.sqrt(dx * dx + dy * dy);
							var depth:Number = i * 2 - distance
							if (depth > 0)
							{
								solveIntersection(bitmapData, p1, p2, (depth * dx / distance), (depth * dy / distance))
							}
						}
					}
				}
			}
			points.sortOn(["x", "y"], Array.NUMERIC);
			return points;
		}
 
		private function solveIntersection(bitmapData:BitmapData, p1:Point, p2:Point, offsetX:Number, offsetY:Number):void
		{
			p1.x += offsetX / 2;
			p1.y += offsetY / 2;
			p2.x -= offsetX / 2;
			p2.y -= offsetY / 2;
			if (bitmapData.getPixel(p1.x, p1.y) == 0xFFFFFF)
			{
				p1.x -= offsetX
				p1.y -= offsetY
			}
			if (bitmapData.getPixel(p2.x, p2.y) == 0xFFFFFF)
			{
				p2.x += offsetX
				p2.y += offsetY
			}
		}
	}
}
Клик по флэшке — отрисует новые точки.
fill_image_with_points_3.swf   (12.3 Кб)


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

И да, возможно я просто криво написал код.

Есть еще идеи? Подскажите
Вложения
Тип файла: swf fill_image_with_points_3.swf (12.3 Кб, 91 просмотров)
__________________
hauts.ru