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

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

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 01.08.2008, 16:02
alrusdi вне форума Посмотреть профиль Отправить личное сообщение для alrusdi Найти все сообщения от alrusdi
  № 1  
Ответить с цитированием
alrusdi

Регистрация: Nov 2005
Сообщений: 75
По умолчанию Равнозамедленное движение по ломаной

В общем задача такая: Необходимо визуализировать равнозамедленное движение точки по ломаной линии (динамичеки задаваемой массивом точек). Составляющие отрезки по длине различны. Может быть кто-то видел готовое решение или близкое (например равномерное движение по ломаной)?
Поиск я использовать умею...

Старый 01.08.2008, 16:47
Волгоградец вне форума Посмотреть профиль Отправить личное сообщение для Волгоградец Найти все сообщения от Волгоградец
  № 2  
Ответить с цитированием
Волгоградец
 
Аватар для Волгоградец

блогер
Регистрация: Sep 2007
Адрес: Гамбург
Сообщений: 1,648
Записей в блоге: 12
Используй Tween.

Старый 01.08.2008, 17:12
alrusdi вне форума Посмотреть профиль Отправить личное сообщение для alrusdi Найти все сообщения от alrusdi
  № 3  
Ответить с цитированием
alrusdi

Регистрация: Nov 2005
Сообщений: 75
Tween, к сожалению, не годиться. Ищу портируемое на другие языки решение. Я представляю как это нужно сделать, но алгоритм нетривиальный достаточно. Вот думаю может готовое найдется.

Старый 01.08.2008, 17:44
chingachgoog вне форума Посмотреть профиль Найти все сообщения от chingachgoog
  № 4  
Ответить с цитированием
chingachgoog
Banned
 
Аватар для chingachgoog

блогер
Регистрация: Nov 2006
Адрес: Moscow
Сообщений: 2,145
Записей в блоге: 7
Я бы задумался над классом Point и его методами (например, normalize)

Старый 01.08.2008, 19:05
Division вне форума Посмотреть профиль Отправить личное сообщение для Division Найти все сообщения от Division
  № 5  
Ответить с цитированием
Division
 
Аватар для Division

Регистрация: Jul 2008
Адрес: Украина, Херсон
Сообщений: 635
Отправить сообщение для Division с помощью ICQ
Первое что пришло в голову. Значит, есть массив координат.
Есть объект который движется по ломанной, заданной этими координатами.
У объекта есть скорость и текущее положение (просто вещественное число).
Для начала найдем длину ломанной. То есть сумму длин всех отрезков. Причем длину каждого отрезка нам также нужно хранить в массиве. Надеюсь школьные формулы все помнят (: Далее нам потребуется ещё один массив. Он по размеру будет такой же как массив координат. Только содержать будет не координаты, а длину ломанной от начала до данной точки. То есть с помощью него мы сможем зная пройденный путь(наше текущее положение) определить на каком из отрезков мы находимся. Надеюсь с этим всё понятно. Главное подготовить эти данные, остальное всё просто. Потом происходит анимация. К нашей координате всё время прибавляется скорость, и скорость уменьшается на какой-то коэфициент(равнозамедленное, ага). После того как расчитали новое значение нашей координаты, определим на каком отрезке мы находимся. Это просто, мы же знаем на каком участке пути какое расстояние будет пройдено. Далее нам нужен нормализованный вектор текущего отрезка. Назовем его V. Потом найдем разность между пройденным нами расстоянием и расстоянием до начала текущего отрезка. Фактически это будет расстояние, которое мы прошли по текущему отрезку. Если мы это расстояние поделим на длину текущего отрезка, получим некий коэфициент. Он всегда будет от 0 до 1. Назовем его k.
Так вот, наша текущая координата будет определяться формулой
pos = x0 + V * L * k
где pos - это координата начала отрезка, x0 - начальная координата отрезка, V - нормальзованный вектор, полученный из этого отрезка(находить по типу normalize(x1-x0)) L - длина отрезка, K - коэфициент от 0 до 1. Векторную алгебру все помнят? (:
Описал как всегда смутно. ИМХО реализуется всё очень просто, нужно только немного подумать.
__________________
while(1) {}


Последний раз редактировалось Division; 01.08.2008 в 19:14.
Старый 03.08.2008, 13:05
Alex_beginner вне форума Посмотреть профиль Отправить личное сообщение для Alex_beginner Найти все сообщения от Alex_beginner
  № 6  
Ответить с цитированием
Alex_beginner
 
Аватар для Alex_beginner

Регистрация: May 2008
Сообщений: 476
У меня два варианта:

1. Если Вы хорошо разбираетесь в математике, то по данным узловых точек можно "состряпать" линейный сплайн и потом и пользоваться для указания направления движения точки;
2. Tween для равнозамедленного движения - роскошь, которую могут позволить себе не многие, поэтому проще локально опысывать траекторию движения точки линейными уравнениями, получаемыми из значений координат двух ближайших узловых точек ломаной линии. В реализации данный вариант еще проще, чем на словах, поэтому не привожу здесь код. Думаю, Вы без труда его реализуете.
__________________
Случайность, господа, это знаете ли непознанная необходимость.

Старый 04.08.2008, 14:34
alrusdi вне форума Посмотреть профиль Отправить личное сообщение для alrusdi Найти все сообщения от alrusdi
  № 7  
Ответить с цитированием
alrusdi

Регистрация: Nov 2005
Сообщений: 75
Спасибо за внимание))
Может кому-нибудь в будущем понадобится этот код
Натуральным языком алгоритм описан Division, только что там про коэффициент K значит я так и не понял.
Alex_beginer, Что в данном случае подразумеваете под термином линейный сплайн? Опишите Ваш алгоритм натуральным языком?
Код:
//создадим объект, который будет двигаться равнозамедленно по ломаной
_root.createEmptyMovieClip("myobj", 1);
myobj.lineStyle(0, 0xFF0000, 100);
myobj.moveTo(-3, -3);
myobj.lineTo(3, -3);
myobj.lineTo(3, 3);
myobj.lineTo(-3, 3);
myobj.lineTo(-3, -3);

//массив точек ломаной
var mypath:Array = Array(
		Array(13,355),
		Array(50,305),
		Array(145,305),
		Array(229,267),
		Array(190,184),
		Array(268,127),
		Array(307,154),
		Array(294,241),
		Array(348,273),
		Array(408,225),
		Array(414,69)
);

var mypathlenght=0;
var myobjdistance=0;

//это для рисования ломаной
_root.lineStyle(0, 0x0000FF, 100);
_root.moveTo(mypath[0][0], mypath[0][1]);

for (var i=1; i<mypath.length; i++){
	//для каждого отрезка ломаной посчитаем его длину
	//хранить будем сумму длин отрезков до данного участка
	mypathlenght+=calcLength(mypath[i-1], mypath[i]);
	mypath[i][2]=mypathlenght;
	
	//также для каждого отрезка сохраним его нормализованный вектор
	//он даст нам направление движения
	mypath[i][3]=getNormalVector(mypath[i-1], mypath[i]);
	//нарисуем отрезок ломаной
	_root.lineTo(mypath[i][0], mypath[i][1]);
}

//высчитаем необходимую скорость движения
//скорость визуализации движения также будет зависеть от fps ролика
var mypathspeed=mypathlenght/33;
var curspeed=mypathspeed;

_root.onEnterFrame= function(){
	//посчитаем дистанцию которую на данный момент должен пройти объект
	myobjdistance+=curspeed;
	//определим отрезок на котором будет находится объект в данный момент
	var i = getIndexOfCurrentLine(myobjdistance);
	var locallength=0;
	if (i){
		if (i==-1){
			//объект дошел до конца пути
			//переместим его для точности в конечную точку траектории
			_root.onEnterFrame=null;
			i=mypath.length-1;
			_root.myobj._x=mypath[i][0];
			_root.myobj._y=mypath[i][1];
			return;
		}
		//объект находится на втором или последующих отрезках
		//посчитаем сколько он должен пройти от начала текущего отрезка
		var locallength=myobjdistance-mypath[i][2];
	}else{
		//объект на первом отрезке, значит общая дистанция которую он прошел
		//равна расстоянию пройденому им от начала отреска
		var locallength=myobjdistance;
	}
	//уменьшим скорость (движение равнозамедленное)
	curspeed*=0.97;
	//переместим объект от начала текущего отрезка
	//на посчитаное выше расстояние вдоль нормализованного вектора данного отрезка
	ix=mypath[i][0]+mypath[i+1][3][0]*locallength;
	iy=mypath[i][1]+mypath[i+1][3][1]*locallength;
	_root.myobj._x=ix;
	_root.myobj._y=iy;
}


function getIndexOfCurrentLine(ilength){
	for (var i=0; i<mypath.length; i++){
		if (ilength<mypath[i+1][2]){ return i;}
	}	
	return -1;
}

//расстояние между двумя точками равно корню из суммы квадратов
//разности соответствующих координат sqrt( (x2-x1)^2 + (y2-y1)^2 )
function calcLength(ar1, ar2){
	return Math.sqrt((ar2[0]-ar1[0])*(ar2[0]-ar1[0]) + (ar2[1]-ar1[1])*(ar2[1]-ar1[1]));
}

//чтобы нормализовать вектор нужно его составляющие поделить на длину
function getNormalVector(ar1, ar2){
        var ku = calcLength(ar1, ar2);
        nx = (ar2[0]-ar1[0]) / ku;
        ny = (ar2[1]-ar1[1]) / ku;
		return Array(nx, ny);
}


Последний раз редактировалось alrusdi; 04.08.2008 в 15:38.
Старый 04.08.2008, 15:51
Alex_beginner вне форума Посмотреть профиль Отправить личное сообщение для Alex_beginner Найти все сообщения от Alex_beginner
  № 8  
Ответить с цитированием
Alex_beginner
 
Аватар для Alex_beginner

Регистрация: May 2008
Сообщений: 476
Цитата:
Alex_beginer, Что в данном случае подразумеваете под термином линейный сплайн? Опишите Ваш алгоритм натуральным языком?
Описываю натуральным языком.

Линейный сплайн (кусочно-линейное интерполирование) представляет собой, некое уравнение, которое позволяет описывать ломаную линию. Как известно из основных постулатов Теории численных методов, полином стпени N может иметь N-1 локальный максимум и минимум и график может раскачиваться, чтобы пройти через точки ломаной линии. Поэтому, N-полиномиальное описание такой ломаной негодится, в принципе. Для описания такой линии лучше использовать линейный сплайн - уравнение, построенное по значениям узловых точек. Как правило, для описания такой кусочно-линейной кривой используют полином Лагранжа. Более детально, об этом можно прочитать в специализированной литературе по математике, имеющейся на пыльных полках многих букинистичеких магазинов.
__________________
Случайность, господа, это знаете ли непознанная необходимость.

Старый 04.08.2008, 16:39
Division вне форума Посмотреть профиль Отправить личное сообщение для Division Найти все сообщения от Division
  № 9  
Ответить с цитированием
Division
 
Аватар для Division

Регистрация: Jul 2008
Адрес: Украина, Херсон
Сообщений: 635
Отправить сообщение для Division с помощью ICQ
K - коэфициент от 0 до единицы. То есть мы знаем длину текущего отрезка(по которому движемся в данный момент). Знаем, какое расстояние мы по нему уже прошли. Делим это расстояние на длину отрезка, получаем коэфициент K (: Если прошли половину отрезка, K будет равен 0.5. Если находимся в начале отрезка - 0. В конце - ближе к единице. Короче если умножить нормализованный вектор полученный из текущего отрезка, на K, потом к начальной точке отрезка прибавить полученный вектор, то получим наши текущие координаты.

UPD: Чет я втыкаю (: А ведь действительно, можно просто умножить нормализованный вектор на пройденное по отрезку расстояние. И не нужно никаких коэфициентов...

Да, и ещё...
Если curspeed*=0.97, то такое движение не равнозамедленное (:
__________________
while(1) {}


Последний раз редактировалось Division; 04.08.2008 в 16:47.
Старый 04.08.2008, 16:55
Alex_beginner вне форума Посмотреть профиль Отправить личное сообщение для Alex_beginner Найти все сообщения от Alex_beginner
  № 10  
Ответить с цитированием
Alex_beginner
 
Аватар для Alex_beginner

Регистрация: May 2008
Сообщений: 476
Теперь поговорим более подробно о методе со сплайнами.

Порядок такой:

1. Рассчитываете все коэффициенты сплайна по данным узловых точек;
2. Известно, что расстояние между двумя ближайшими точками рассчитывается как:

R = корень_квадратный((x2-x1)^2+(y2-y1)^2);
где

x1,y1 - координаты предыдущей рассчитаной точки на предыдущей итерации.
R - расстояние между двумя ближайшими точками;
Таким образом, на текущей итерации для данного уравнения неизвестны только x2,y2;
3. Предполагается, что если расстояние проходимое точкой на всех отрезках ломаной для каждой итерации будет одинаковым, то движение точки можно назвать равномерным, т.е. точка движется с постоянной скоростью. Теперь, если расстояние проходимое точкой в каждой итерции будет изменяться по линейному закону, то такое движение можно назвать равнозамедленным, либо равноускоренным, в соответсвующих случаях
4. Уравнение сплайна представляет собой функцию y=f(x), а приведенное выше уравнение, также может быть представлено в виде y=f(x) (здесь y=y2; x=x2). В результате мы имеем систему уравнений из двух уравнений и двух неизвестных, найдти корни которой в общем ввиде несоставит труда, если пользоваться методом подстановки.
5. Теперь используя коэффициент R как постоянную в каждой итерации мы получаем равномерное движение. Изменяем его по линейному закону получаем равнозамедленное или равноускоренное движение.
6. Вот, собственно, и вся теория.
__________________
Случайность, господа, это знаете ли непознанная необходимость.


Последний раз редактировалось Alex_beginner; 04.08.2008 в 17:37.
Создать новую тему Ответ Часовой пояс GMT +4, время: 10:48.
Быстрый переход
  « Предыдущая тема | Следующая тема »  
Опции темы
Опции просмотра
Комбинированный вид Комбинированный вид

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

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


 


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


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