Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 26.03.2015, 14:32
fresh.flash вне форума Посмотреть профиль Отправить личное сообщение для fresh.flash Посетить домашнюю страницу fresh.flash Найти все сообщения от fresh.flash
  № 1  
Ответить с цитированием
fresh.flash

Регистрация: Sep 2009
Адрес: Николаев
Сообщений: 26
Записей в блоге: 1
По умолчанию Направление обхода точек многоугольника, перспектива помещения(вид сверху)

Добрый день! Есть массив точек, который образует непересекающийся многоугольник. Точки даны по порядку(добавляет пользователь), т.е. первая и вторая точки образуют сторону многоугольника. Это пол помещения. Нужно нарисовать вид сверху с перспективами стен:


Это пример для прямоугольника.
Рабочий код, который определяет точки со сдвигом в зависимости от высоты помещения:
Код AS3:
for (var j:uint = 0; j < length; j++) {
	//находим текущую, прошлую и следующую точку
	_currPoint = points[j];
	if (j < points.length - 1)
		_nextPoint = points[j + 1];
	else
		_nextPoint = points[0];
	if (j == 0)
		_prevPoint = points[points.length - 1];
	else
		_prevPoint = points[j - 1];
	//находим отрезки, биссектрису
	norm1 = _currPoint.subtract(_prevPoint);
	norm1.normalize(1);
	norm2 = _currPoint.subtract(_nextPoint);
	norm2.normalize(1);
	bisectrix = norm1.add(norm2);
	//направление обхода
	cw = (_currPoint.x - _prevPoint.x) * (_nextPoint.y - _currPoint.y) - (_currPoint.y - _prevPoint.y) * (_nextPoint.x - _currPoint.x) > 0;
	if (!cw)
		bisectrix.normalize(h);
	else
		bisectrix.normalize( -h);
	//умножаем вектор биссектрисы на высоту стен
	normRatio = h / Math.abs(bisectrix.x * norm1.y - bisectrix.y * norm1.x);
	bisectrix.x *= normRatio;
	bisectrix.y *= normRatio;
	_pointsOffset.push(_currPoint.add(bisectrix));
}
Работает исправно и для сложных многоугольников (хотя такие вряд ли встретятся):


НО! Проблема 1: точки должны добавляться против часовой стрелки, если по часовой добавляешь - стены рисуются внутрь помещения и получается каламбур:


Проблема 2: если точки лежат на одной прямой - неправильно определяется биссектриса(на картинке ниже верхний отрезок многоугольника состоит из двух):


Буду благодарен за любую помощь как решить эти проблемы.

Код родился из этой темы.


Последний раз редактировалось fresh.flash; 26.03.2015 в 14:35. Причина: изменил название
Старый 26.03.2015, 15:24
nubideus вне форума Посмотреть профиль Отправить личное сообщение для nubideus Найти все сообщения от nubideus
  № 2  
Ответить с цитированием
nubideus

Регистрация: Jan 2013
Сообщений: 322
1. посчитать площадь полигона. если площадь положительное число - перевернуть полигон.

http://www.mathopenref.com/coordpolygonarea2.html
https://github.com/deltaluca/nape/bl...omPoly.cx#L261

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

Старый 26.03.2015, 16:23
silin вне форума Посмотреть профиль Посетить домашнюю страницу silin Найти все сообщения от silin
  № 3  
Ответить с цитированием
silin
 
Аватар для silin

блогер
Регистрация: Mar 2003
Адрес: Моск. обл.
Сообщений: 5,269
Записей в блоге: 6
1. можно соориентироваться по сумме всех внешних и внутренних углов
2. для соосных отрезков (не считается биссектриса в такой схеме)) просто брать перпендикуляр
Код AS3:
package
{
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.geom.Point;
 
	public class Main extends Sprite
	{
 
		public function Main():void
		{
 
			var a:Point = new Point(100, 200);
			var b:Point = new Point(200, 100);
			var c:Point = new Point(400, 200);
			var d:Point = new Point(250, 310);
			var e:Point = new Point(200, 300);
			var f:Point = new Point(150, 290);
 
 
			var points:Array = [a, b, c, d, e, f];
			// другое направление обхода
			//var points:Array = [f, e, d, c, b, a];
 
			graphics.lineStyle(0);
			drawPoly(graphics, points);
 
			graphics.lineStyle(0, 0xFF0000);
			var offsetPoints:Array = calcOffsetPoints(points, 20);
			drawPoly(graphics, offsetPoints);
 
		}
 
		public static function calcOffsetPoints(points:Array, distance:Number = 0):Array
		{
 
			var res:Array = [];
			var len:int = points.length;
 
			// нправление обхода
			var angle1:Number = 0;
			var angle2:Number = 0;
			for (var j:int = 0; j < len; j++)
			{
				var dp1:Point = points[(j + 1) % len].subtract(points[(j + 0) % len]);
				var dp2:Point = points[(j + 1) % len].subtract(points[(j + 2) % len]);
 
				var a1:Number = Math.atan2(dp1.y, dp1.x);
				var a2:Number = Math.atan2(dp2.y, dp2.x);
 
				var da1:Number = a1 - a2;
				var da2:Number = a2 - a1;
 
				if (da1 < 0)
					da1 += Math.PI * 2;
				if (da2 < 0)
					da2 += Math.PI * 2;
 
				angle1 += da1;
				angle2 += da2;
 
			}
			var winding:Boolean = angle2 - angle1 > 0;
 
			// расчет точек
			for (var i:int = 0; i < len; i++)
			{
 
				var p0:Point = points[i];
				var p1:Point = points[(i + 1) % len];
				var p2:Point = points[(i + 2) % len];
 
				var norm1:Point = p0.subtract(p1);
				var norm2:Point = p2.subtract(p1);
 
				norm1.normalize(1);
				norm2.normalize(1);
 
				var bisectrix:Point = norm1.add(norm2);
 
				// соосность отрезков
				if (bisectrix.length == 0)
				{
					bisectrix.y = norm1.x;
					bisectrix.x = norm1.y;
 
				}
 
				var normRatio:Number = distance / (bisectrix.x * norm1.y - bisectrix.y * norm1.x);
 
				bisectrix.x *= normRatio;
				bisectrix.y *= normRatio;
 
				// учитываем направление обхода
				var offsetPoint:Point = winding ? p1.subtract(bisectrix) : p1.add(bisectrix);
 
				res.push(offsetPoint);
			}
			return (res);
 
		}
 
		public static function drawPoly(graphics:Graphics, points:Array):void
		{
 
			graphics.moveTo(points[points.length - 1].x, points[points.length - 1].y);
			for (var i:int = 0; i < points.length; i++)
			{
				graphics.lineTo(points[i].x, points[i].y);
			}
		}
	}
 
}

Старый 26.03.2015, 16:23
fresh.flash вне форума Посмотреть профиль Отправить личное сообщение для fresh.flash Посетить домашнюю страницу fresh.flash Найти все сообщения от fresh.flash
  № 4  
Ответить с цитированием
fresh.flash

Регистрация: Sep 2009
Адрес: Николаев
Сообщений: 26
Записей в блоге: 1
nubideus, спасибо огромное)) Как просто оказалось. С первым пунктом проблема разрешилась.
Не добавлять вершины не вариант, т.к. заказчику нужна такая возможность(1 стену разбивать на две, чтобы раскладывать разные плитки)

silin, благодарю, у Вас, как обычно, код-эталон Всё работает и всё логически понятно. Будет возможность - закину деньгу, а то по Вашим примерам учил as3 и забыл поблагодарить))


Последний раз редактировалось fresh.flash; 26.03.2015 в 17:13.
Создать новую тему Ответ Часовой пояс GMT +4, время: 13:06.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Теги
AS3 , вектор , многоугольник , точка
Опции темы
Опции просмотра

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

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


 


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


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