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

Вернуться   Форум Flasher.ru > Блоги > Идеи и творения

Буду делиться тем что делаю.
Оценить эту запись

Небольшой совет по оптимизации

Запись от Герыч размещена 30.07.2009 в 20:03
Обновил(-а) Герыч 09.08.2009 в 00:07

Иногда бывает нужно разложить вектор на 2 составляющие по заданному направлению.
То есть есть нормализованный вектор (nx,ny) и надо разложить вектор (vx,vy) в сумму вектора (x1,y1) с тем же направлением, что и (nx,ny), т.е. коллинеарный вектор и перпендикулярного ему вектора (x2,y2).



Вот меня на днях осенило, что раньше я это делал глупо и есть способ чуток быстрее. Вот код, поймёте сами:
Код AS3:
var vx:Number=Math.random()*20-10;		//Исходный вектор
var vy:Number=Math.random()*20-10;
var nx:Number=Math.random()*20-10;		//Вектор направления
var ny:Number=Math.random()*20-10;
var d:Number=Math.sqrt(nx*nx+ny*ny);
if(d>0)
{
	d=1/d;
	nx*=d;
	ny*=d;
 
	var i:int;
	var x1:Number;
	var y1:Number;
	var x2:Number;
	var y2:Number;
	var x3:Number;
	var y3:Number;
 
	var p1:Number;
	var p2:Number;
 
	var t1:uint;
	var t2:uint;
	t1=getTimer();
	p1=nx*vx+ny*vy;
	x1=p1*nx;
	y1=p1*ny;
	for(i=0;i<100000;i++)
	{
		p2=vx*ny-vy*nx;		//так я делал раньше(через 2-ую проекцию)
		x2=p2*ny;
		y2=-p2*nx;
	}
	t1=getTimer()-t1;
	t2=getTimer();
	for(i=0;i<100000;i++)
	{
		x3=vx-x1;		//так я буду делать отныне!
		y3=vy-y1;
	}
	t2=getTimer()-t2;
	//Кстати trace'ы надо именно тут располагать
	//Если ставить перед промежутком кода t2=getTimer(); ...  t2=getTimer()-t2;
	//то t1 будет меньше t2!
	trace("Исходный вектор:",vx,vy)
	trace("Направление:",nx,ny);
	trace("Время работы:",t1,t2);
	trace("Первая проекция:",x1,y1);
	trace("Проверка данных:")
	trace(" первым способом:",x2,y2);
	trace(" вторым способом:",x3,y3);
}
else
	trace("Impossible thing =)");
Что мне вывелось(в дебаг режиме):
Код:
Исходный вектор: 7.630283823236823 -9.665163177996874
Направление: 0.977460412497158 0.21111878647075802
Время работы: 31 20
Первая проекция: 5.2956878106917 1.14379996348391
Проверка данных:
 первым способом: 2.334596012545122 -10.808963141480783
 вторым способом: 2.3345960125451235 -10.808963141480785
Делюсь всем этим бредом потому что это просто, но для меня почему-то не было очевидным.. вот такая оч небольшая оптимизулечка)
Всего комментариев 2

Комментарии

Старый 01.08.2009 14:17 Волгоградец вне форума
Волгоградец
 
Аватар для Волгоградец
Все правильно, вектор (х2, у2) - это разница векторов (vx,vy) и (x1,y1)...
И мне кажется, в самом начале необязательно нормализовать вектор (nx,ny), т.к. ты берешь для этого корень суммы произведений. А как известно, это очень дорогостоящая операция. Можно так:
Код AS1/AS2:
x1 = (p1 / (nx * nx + ny * ny)) * nx;
y1 = (p1 / (nx * nx + ny * ny)) * ny;
А вообще, молодец, пиши еще. Лично я с удовольствием читаю.
Старый 01.08.2009 15:06 Герыч вне форума
Герыч
 
Аватар для Герыч
корень не относился к оптимизации. Это просто такая задачка была поставлена:
Дан вектор длины 1. Разложить другой вектор на 2 части по его направлению.
Ну и акцент был сделан на том что 2-ая проекция не нужна, если известна первая.

Ну а вообще да, в случае произвольного по длине вектора n мой код будет таким:
Код AS3:
var vx:Number=Math.random()*20-10;		//Исходный вектор
var vy:Number=Math.random()*20-10;
var nx:Number=Math.random()*20-10;		//Вектор направления
var ny:Number=Math.random()*20-10;
var d2:Number=nx*nx+ny*ny;
if(d2>0)
{
	d2=1/d2;
	var i:int;
	var x1:Number;
	var y1:Number;
	var x2:Number;
	var y2:Number;
	var x3:Number;
	var y3:Number;
 
	var p1:Number;
	var p2:Number;
 
	var t1:uint;
	var t2:uint;
	t1=getTimer();
	p1=(nx*vx+ny*vy)*d2;
	x1=p1*nx;
	y1=p1*ny;
	for(i=0;i<100000;i++)
	{
		p2=(vx*ny-vy*nx)*d2;
		x2=p2*ny;
		y2=-p2*nx;
	}
	t1=getTimer()-t1;
	t2=getTimer();
	for(i=0;i<100000;i++)
	{
		x3=vx-x1;
		y3=vy-y1;
	}
	t2=getTimer()-t2;
	trace("Исходный вектор:",vx,vy)
	trace("Направление:",nx,ny);
	trace("Время работы:",t1,t2);
	trace("Первая проекция:",x1,y1);
	trace("Проверка данных:")
	trace(" первым способом:",x2,y2);
	trace(" вторым способом:",x3,y3);
}
else
	trace("Impossible thing =)");
Результаты опять правильные:
Код:
Исходный вектор: -4.513090290129185 -0.7671708147972822
Направление: -0.05007965490221977 -9.953597588464618
Время работы: 28 22
Первая проекция: -0.00397401994153772 -0.7898575855571011
Проверка данных:
 первым способом: -4.509116270187647 0.022686770759818772
 вторым способом: -4.509116270187647 0.02268677075981884
Объяснение(для тех кто не понимает), почему это работает:
Пусть v-вектор, n-вектор
тогда наш вектор-проеция вектора v на вектор n можно записать так:
Код:
vp=(v,n/|n|)*n/|n|
вынося |n| получим:
Код:
vp=(v,n)*n / (|n|*|n|)
где |n|*|n| = nx*nx+ny*ny
 

 


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


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