⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 time_calc.cpp

📁 彩信浏览器
💻 CPP
字号:
// This file is part of Ambulant Player, www.ambulantplayer.org.//// Copyright (C) 2003-2007 Stichting CWI, // Kruislaan 413, 1098 SJ Amsterdam, The Netherlands.//// Ambulant Player is free software; you can redistribute it and/or modify// it under the terms of the GNU Lesser General Public License as published by// the Free Software Foundation; either version 2.1 of the License, or// (at your option) any later version.//// Ambulant Player is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public License// along with Ambulant Player; if not, write to the Free Software// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA/*  * @$Id: time_calc.cpp,v 1.9 2007/02/12 14:15:22 jackjansen Exp $  */#include "ambulant/smil2/time_calc.h"#include <cmath>#define AM_DBG if(0)//#define AM_DBG if(1)using namespace ambulant;using namespace smil2;// staticlib::logger* time_calc::clogger = 0;time_calc::time_calc(schedulable *tn):	m_tn(tn), 	m_attrs(*tn->get_time_attrs()),	m_paused(false), m_uses_dur(false) {	if(!clogger) clogger = lib::logger::get_logger();}// This function calculates the simple duration of this node.// See spec: "Defining the simple duration" // The last calculated simple duration is stored in the variable m_last_cdur.// This function will call the function "get_implicit_dur()" if and only if // the implicit duration of a node is required by the timing model.time_calc::time_type time_calc::calc_dur() {	if(!m_attrs.has_dur_specifier() && m_attrs.specified_end()) {		AM_DBG clogger->debug("%s[%s].calc_dur(): %s", m_attrs.get_tag().c_str(), 			m_attrs.get_id().c_str(), "indefinite");		return time_type::indefinite;	}	dur_type dt = m_attrs.get_dur_type();	time_type cdur = time_type::unresolved;	if(m_paused) dt = dt_indefinite; // do the calcs as if indefinite	if(dt == dt_definite) {		m_uses_dur = true;		cdur = time_manipulated(m_attrs.get_dur());	} else if(dt == dt_indefinite) {		cdur = time_type::indefinite;	} else if(dt == dt_unspecified) {		m_uses_dur = true;		cdur = m_tn->get_implicit_dur();	} else if(dt == dt_media) {		m_uses_dur = true;		cdur = m_tn->get_implicit_dur();	} 	AM_DBG clogger->debug("%s[%s].calc_dur(): %s", m_attrs.get_tag().c_str(), 		m_attrs.get_id().c_str(), ::repr(cdur).c_str());	return cdur;}time_calc::time_type time_calc::time_manipulated(time_type d) const {	if(!d.is_definite()) return d;	double speed = fabs(m_attrs.get_speed());	u_value_type speed100 = (u_value_type)(::floor(0.5 + speed * 100));	if(speed100 == 0) speed100 = 1;	unsigned long ud = (speed100 * d() ) / 100;	d = time_type(ud);	if(m_attrs.auto_reverse()) d += d;	return d;}// See spec: "Intermediate Active Duration Computation" // This function calculates the "intermediate active duration" of this node.// This quantity is used by the active duration calculation.time_calc::time_type time_calc::calc_intermediate_ad() {	time_type cdur = calc_dur();	time_type adrad = m_attrs.specified_rcount()?calc_active_rad():time_type::indefinite;	time_type rdur = m_attrs.specified_rdur()?m_attrs.get_rdur():time_type::indefinite;	time_type iad;	if(cdur() == 0) iad = time_type(0);	else if(!m_attrs.specified_rcount() && !m_attrs.specified_rdur())		iad = cdur;	else		iad = std::min(std::min(adrad, rdur), time_type::indefinite);	return iad;}// See spec: "Intermediate Active Duration Computation" // This function calculates the accumulated sum of the specified // number of simple durations of the iterations of this element.time_calc::time_type time_calc::calc_active_rad() {	assert(m_attrs.specified_rcount());	double rcount = m_attrs.get_rcount();		// Calculate based on the specified dur if definite	dur_type dt = m_attrs.get_dur_type();	if(dt == dt_definite) {		if(m_attrs.is_rcount_indefinite())			return time_type::indefinite;		else {			time_type dur = time_manipulated(m_attrs.get_dur());			return (value_type) ::floor(rcount*dur() + 0.5);		}	}			// Calculate based on the the implicit dur if definite	time_type idur = m_tn->get_implicit_dur();	if(idur.is_definite()) {		if(m_attrs.is_rcount_indefinite())			return time_type::indefinite;		else 			return (value_type) ::floor(rcount*idur() + 0.5);	}		// Best estimate based on the previous iteration.	time_type last_cdur = m_tn->get_last_dur();	if(last_cdur.is_definite()) {		if(m_attrs.is_rcount_indefinite())			return time_type::indefinite;		else 			return (value_type) ::floor(rcount*last_cdur() + 0.5);	}			// Cann't be resolved yet.	return time_type::unresolved;}// See spec: "Active duration algorithm"// This function calculates the preliminary active duration of an element, // before accounting for min and max  semanticstime_calc::time_type time_calc::calc_preliminary_ad(time_type b, time_type e) {	if(!m_attrs.has_dur_specifier() && m_attrs.specified_end()) {		assert(calc_dur() == time_type::indefinite);		if(e.is_definite())			return e - b;		else if(e.is_indefinite())			return time_type::indefinite;		else if(e.is_unresolved())			return time_type::unresolved;	} else if(!m_attrs.specified_end() || (m_attrs.specified_end() && m_attrs.end_is_indefinite())) {		return calc_intermediate_ad();	} 	// else	assert( (m_attrs.specified_end() && !m_attrs.end_is_indefinite()) && m_attrs.has_dur_specifier());	return std::min(calc_intermediate_ad(), e - b);}// See spec: "Active duration algorithm"// This function calculates the preliminary active duration of this node, // before accounting for min and max  semantics.// Simplified version of the above applicable when "end" is not specified.time_calc::time_type time_calc::calc_preliminary_ad(time_type b) {	assert(!m_attrs.specified_end());	return calc_intermediate_ad();}// See spec: "Active duration algorithm"// This function calculates the active duration of this node.time_calc::time_type time_calc::calc_ad(time_type b, time_type e) {	time_type minval = m_attrs.specified_min()?m_attrs.get_min():0;	time_type maxval = m_attrs.specified_max()?m_attrs.get_max():time_type::indefinite;	time_type pad = calc_preliminary_ad(b, e);	time_type cad = std::min(maxval, std::max(minval, pad));	AM_DBG clogger->debug("%s[%s].calc_ad(): %s", m_attrs.get_tag().c_str(), 		m_attrs.get_id().c_str(), ::repr(cad).c_str());		return cad;}// See spec: "Active duration algorithm"// This function calculates the active duration of this node.// Simplified version of the above applicable when "end" is not specified.time_calc::time_type time_calc::calc_ad(time_type b) {	assert(!m_attrs.specified_end());	time_type minval = m_attrs.specified_min()?m_attrs.get_min():0;	time_type maxval = m_attrs.specified_max()?m_attrs.get_max():time_type::indefinite;	time_type pad = calc_preliminary_ad(b);	time_type cad = std::min(maxval, std::max(minval, pad));	AM_DBG clogger->debug("%s[%s].calc_ad(): %s", m_attrs.get_tag().c_str(), 		m_attrs.get_id().c_str(), ::repr(cad).c_str());		return cad;}// Calculates and returns the active end of this node.// This uses calc_ad() function.time_calc::time_type time_calc::calc_end(time_type b, time_type e) {	return b + calc_ad(b, e);}// Calculates and returns the active end of this node when "end" is not specified.// This uses calc_ad() function.time_calc::time_type time_calc::calc_end(time_type b) {	assert(!m_attrs.specified_end());	return b + calc_ad(b);}// Calculates and returns the current inteval end.// This uses calc_ad() function.time_calc::time_type time_calc::calc_interval_end(interval_type& i, time_mset& end_list)  {	time_type begin = i.begin;	time_type end;	if(!m_attrs.specified_end()) {		end = calc_end(begin);	} else {		time_mset::iterator eit = end_list.lower_bound(begin);		if(eit != end_list.end()) end = *eit;		else end = time_type::unresolved;		end = calc_end(begin, end);	}	AM_DBG clogger->debug("%s[%s].calc_interval_end(): %s", m_attrs.get_tag().c_str(), 		m_attrs.get_id().c_str(), ::repr(end).c_str());		return end;}// See spec: "Getting the first interval"// Calculates the first valid interval for this node. // An interval is valid if:// a) has a definite begin // b) it is a valid child of its parent (e.g. begin < begin_before && end >= parent.begin)// When no such interval exists this function returns unresolved (e.g. failure).// When more than one intervals are valid the one that begins earlier is returned.// The returned interval has been modulated by any max/min attributes or any time manipulations.//// Please note that the interval calculated by this algorithm // does not embed all the available info provided by the model.// For example the fact that the parent simple duration // or the cut short last parent simple dur will// cut short the interval calculated by this algorithm. // The interval calculated may have an unresolved or indefinite end // whereas the parent may have a definite simple dur. // The scheduler should take into account this extra info.  //// The calculation uses active and simple duration algorithms// and requires this node's begin and end lists and the parent // simple dur.//time_calc::interval_type time_calc::calc_first_interval(time_mset& begin_list, time_mset& end_list, 	time_type begin_before) {	// define failure as an alias for the invalid unresolved interval.	interval_type failure = interval_type::unresolved;				// The begin of the first interval can be in [-infinity, parent.simple_end)	time_type begin_after = time_type::minus_infinity;		// Check the begin instance list	if(begin_list.empty()) {		AM_DBG clogger->debug("%s[%s].calc_first_interval(): begin list is empty", 			m_attrs.get_tag().c_str(), 			m_attrs.get_id().c_str());			return failure;	} 	AM_DBG clogger->debug("%s[%s].calc_first_interval(): begin list(%s, ...)", 		m_attrs.get_tag().c_str(), 		m_attrs.get_id().c_str(), 		::repr(*begin_list.lower_bound(begin_after)).c_str());			while(true) {		time_mset::iterator bit = begin_list.lower_bound(begin_after);		if(bit == begin_list.end()) return failure;		time_type temp_begin = *bit;		time_type temp_end;		if(temp_begin > begin_before) return failure;		if(!m_attrs.specified_end()) {			temp_end = calc_end(temp_begin);		} else {			time_mset::iterator eit = end_list.lower_bound(temp_begin);			if(eit != end_list.end()) {				temp_end = *eit;				end_list.erase(eit); // don't use it again e.g. next for equal values			}  else {				// either the list is empty or no time >= temp_begin				if(m_attrs.end_has_event_conditions() || end_list.empty())					temp_end = time_type::unresolved;				else {					AM_DBG clogger->debug("%s[%s].calc_first_interval(): %s", 						m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), ::repr(failure).c_str());					return failure;				}			}			temp_end = calc_end(temp_begin, temp_end);		}		// Handle the zero duration intervals at the parent begin time as a special case		// see: http://www.w3.org/2001/07/REC-SMIL20-20010731-errata		if(temp_end()>0 || (temp_begin()== 0 && temp_end()==0)) {			interval_type ret(temp_begin, temp_end);			AM_DBG clogger->debug("%s[%s].calc_first_interval(): %s", 				m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), ::repr(ret).c_str());			return ret;		} 		// else		begin_after = temp_end;	}}// See spec: "End of interval - Getting the next interval"// Calculates the next acceptable interval for this node.// The variable this->m_interval holds the just ended interval.//// This calculation uses active and simple duration algorithms// and requires this node's begin and end lists, this node's// just ended interval, and the parent simple dur.time_calc::interval_type time_calc::calc_next_interval(time_mset& begin_list, time_mset& end_list, 	time_type begin_before, time_type begin_after, bool prev_was_zero_dur) {	// define failure as an alias for the invalid unresolved interval.	interval_type failure = interval_type::unresolved;		if(begin_list.empty())		return failure;		time_mset::iterator bit;	if(!prev_was_zero_dur)		// the first value in the begin list that is >= begin_after		bit = begin_list.lower_bound(begin_after);	else		// the first value in the begin list that is > begin_after		// see: http://www.w3.org/2001/07/REC-SMIL20-20010731-errata		bit = begin_list.upper_bound(begin_after);		// If no such value or begins after parent end abort	if(bit == begin_list.end() || *bit >= begin_before) 		return failure;		// OK, we have a begin value - get an end	time_type temp_begin = *bit;	time_type temp_end;		if(!m_attrs.specified_end()) {		// this calculates the active end with no end constraint		temp_end = calc_end(temp_begin);	} else {		// the first value in the end list that is >= temp_begin		time_mset::iterator eit = end_list.lower_bound(temp_begin);				// Allow for non-0-duration interval that begins immediately		// after a 0-duration interval.		if(eit != end_list.end()) {			while(*eit == begin_after && eit != end_list.end()) ++eit;			if(eit != end_list.end()) temp_end = *eit;		}		if(eit == end_list.end()) { // no such value			if(m_attrs.end_has_event_conditions() || end_list.empty())				temp_end = time_type::unresolved;			else				return failure;		} 		temp_end = calc_end(temp_begin, temp_end);	}	return interval_type(temp_begin, temp_end);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -