Example #1
0
Real
synfig::bline_length(const ValueBase &bline, bool bline_loop, std::vector<Real> *lengths)
{
	BLinePoint blinepoint0, blinepoint1;
	const std::vector<BLinePoint> list(bline.get_list().begin(),bline.get_list().end());
	int size(list.size());
	if(!bline_loop) size--;
	if(size < 1) return Real();
	// Calculate the lengths and the total length
	Real tl(0), l;
	vector<BLinePoint>::const_iterator iter, next(list.begin());
	iter = bline_loop ? --list.end() : next++;
	for(;next!=list.end(); next++)
	{
		blinepoint0 = *iter;
		blinepoint1 = *next;
		etl::hermite<Vector> curve(blinepoint0.get_vertex(),   blinepoint1.get_vertex(),
							blinepoint0.get_tangent2(), blinepoint1.get_tangent1());
		l=curve.length();
		if(lengths) lengths->push_back(l);
		tl+=l;
		iter=next;
	}
	return tl;
}
Example #2
0
Real
synfig::std_to_hom(const ValueBase &bline, Real pos, bool index_loop, bool bline_loop)
{
	BLinePoint blinepoint0, blinepoint1;
	const std::vector<BLinePoint> list(bline.get_list().begin(),bline.get_list().end());
	int size = list.size(), from_vertex;
	// trivial cases
	if(pos == 0.0 || pos == 1.0)
		return pos;
	if(!bline_loop) size--;
	if(size < 1) return Real();
	Real int_pos((int)pos);
	Real one(0.0);
	if (index_loop)
	{
		pos = pos - int_pos;
		if (pos < 0)
		{
			pos++;
			one=1.0;
		}
	}
	else
	{
		if (pos < 0) pos = 0;
		if (pos > 1) pos = 1;
	}
	// Calculate the lengths and the total length
	Real tl=0, pl=0;
	std::vector<Real> lengths;
	vector<BLinePoint>::const_iterator iter, next;
	tl=bline_length(bline, bline_loop, &lengths);
	// If the total length of the bline is zero return pos
	if(tl==0.0) return pos;
	from_vertex = int(pos*size);
	// Calculate the partial length until the bezier that holds the current
	std::vector<Real>::const_iterator liter(lengths.begin());
	for(int i=0;i<from_vertex; i++, liter++)
		pl+=*liter;
	// Calculate the remaining length of the position over current bezier
	// Setup the curve of the current bezier.
	next=list.begin();
	iter = bline_loop ? --list.end() : next++;
	if (from_vertex > size-1) from_vertex = size-1; // if we are at the end of the last bezier
	blinepoint0 = from_vertex ? *(next+from_vertex-1) : *iter;
	blinepoint1 = *(next+from_vertex);
	etl::hermite<Vector> curve(blinepoint0.get_vertex(),   blinepoint1.get_vertex(),
							blinepoint0.get_tangent2(), blinepoint1.get_tangent1());
	// add the distance on the bezier we are on.
	pl+=curve.find_distance(0.0, pos*size - from_vertex);
	// and return the homogenous position
	return int_pos+pl/tl-one;
}
void ValueAverage::set_average_value_weighted(ValueBase &weighted_list, const ValueBase &value)
{
	if (weighted_list.get_type() != type_list) return;

	ValueBase::List list = weighted_list.get_list();
	if (list.empty()) return;
	types_namespace::TypeWeightedValueBase *t =
		dynamic_cast<types_namespace::TypeWeightedValueBase *>(&(list.front().get_type()));
	if (t == NULL) return;
	if (!check_weighted_type(*t)) return;

	ValueBase::List values_list;
	values_list.reserve(list.size());
	std::vector<Real> weights_list;
	weights_list.reserve(list.size());
	for(ValueBase::List::const_iterator i = list.begin(); i != list.end(); ++i) {
		if (i->get_type() != *t) return;
		weights_list.push_back( t->extract_weight(*i) );
		values_list.push_back( t->extract_value(*i) );
	}
	set_average_value_generic(
		values_list.begin(), values_list.end(),
		weights_list.begin(), weights_list.end(),
		value );

	std::vector<Real>::const_iterator j = weights_list.begin();
	for(ValueBase::List::const_iterator i = values_list.begin(); i != values_list.end(); ++i, ++j)
		list[i - values_list.begin()] = t->create_weighted_value(*j, *i);
	weighted_list = list;
}
Example #4
0
bool
ValueBase::operator==(const ValueBase& rhs)const
{
	if(get_type()!=rhs.get_type())
		return false;
	if(data==rhs.data)
		return true;

	switch(get_type())
	{
	case TYPE_TIME:                   return get(Time()).is_equal(rhs.get(Time()));
	case TYPE_REAL:                   return abs(get(Real())-rhs.get(Real()))<=0.00000000000001;
	case TYPE_INTEGER:                return get(int())==rhs.get(int());
	case TYPE_BOOL:                   return get(bool())==rhs.get(bool());
	case TYPE_ANGLE:                  return get(Angle())==rhs.get(Angle());
	case TYPE_VECTOR:                 return get(Vector()).is_equal_to(rhs.get(Vector()));
	case TYPE_COLOR:                  return get(Color())==rhs.get(Color());
	case TYPE_STRING:                 return get(String())==rhs.get(String());
	case TYPE_CANVAS:                 return get(Canvas::LooseHandle())==rhs.get(Canvas::LooseHandle());
	case TYPE_LIST:                   return get_list()==rhs.get_list();
	case TYPE_VALUENODE_BONE:         return get(ValueNode_Bone::Handle())==rhs.get(ValueNode_Bone::Handle());
	case TYPE_DASHITEM:               return get(DashItem())==rhs.get(DashItem());
	case TYPE_SEGMENT:             // return get(Segment())==rhs.get(Segment());
	case TYPE_GRADIENT:            // return get(Gradient())==rhs.get(Gradient());
	case TYPE_BONE:                // return get(Bone())==rhs.get(Bone());
	case TYPE_BLINEPOINT:          // return get(BLinePoint())==rhs.get(BLinePoint());
	case TYPE_MATRIX:              // return get(Matrix())==rhs.get(Matrix());
	case TYPE_BONE_WEIGHT_PAIR:    // return get(BoneWeightPair())==rhs.get(BoneWeightPair());
	case TYPE_WIDTHPOINT:
	case TYPE_NIL:
	default:                          return false;
	}
	return false;
}
Example #5
0
ValueBase
synfig::convert_bline_to_segment_list(const ValueBase& bline)
{
	std::vector<Segment> ret;

//	std::vector<BLinePoint> list(bline.operator std::vector<BLinePoint>());
	//std::vector<BLinePoint> list(bline);
	std::vector<BLinePoint> list(bline.get_list().begin(),bline.get_list().end());
	std::vector<BLinePoint>::const_iterator	iter;

	BLinePoint prev,first;

	//start with prev = first and iter on the second...

	if(list.empty()) return ValueBase(ret,bline.get_loop());
	first = prev = list.front();

	for(iter=++list.begin();iter!=list.end();++iter)
	{
		ret.push_back(
			Segment(
				prev.get_vertex(),
				prev.get_tangent2(),
				iter->get_vertex(),
				iter->get_tangent1()
			)
		);
		prev=*iter;
	}
	if(bline.get_loop())
	{
		ret.push_back(
			Segment(
				prev.get_vertex(),
				prev.get_tangent2(),
				first.get_vertex(),
				first.get_tangent1()
			)
		);
	}
	return ValueBase(ret,bline.get_loop());
}
Example #6
0
ValueBase
synfig::convert_bline_to_width_list(const ValueBase& bline)
{
	std::vector<Real> ret;
//	std::vector<BLinePoint> list(bline.operator std::vector<BLinePoint>());
	//std::vector<BLinePoint> list(bline);
	std::vector<BLinePoint> list(bline.get_list().begin(),bline.get_list().end());
	std::vector<BLinePoint>::const_iterator	iter;

	if(bline.empty())
		return ValueBase(ValueBase::TYPE_LIST);

	for(iter=list.begin();iter!=list.end();++iter)
		ret.push_back(iter->get_width());

	if(bline.get_loop())
		ret.push_back(list.front().get_width());

	return ValueBase(ret,bline.get_loop());
}
ValueBase ValueAverage::average_weighted(const ValueBase &weighted_list, const ValueBase &default_value)
{
	if (weighted_list.get_type() != type_list) return default_value;

	const ValueBase::List &list = weighted_list.get_list();
	ValueBase::List values_list;
	values_list.reserve(list.size());
	std::vector<Real> weights_list;
	weights_list.reserve(list.size());
	for(ValueBase::List::const_iterator i = list.begin(); i != list.end(); ++i) {
		types_namespace::TypeWeightedValueBase *t =
			dynamic_cast<types_namespace::TypeWeightedValueBase *>(&(i->get_type()));
		if (t == NULL) continue;
		if (!check_weighted_type(*t)) continue;
		weights_list.push_back( t->extract_weight(*i) );
		values_list.push_back( t->extract_value(*i) );
	}
	return average_generic(
		values_list.begin(), values_list.end(),
		weights_list.begin(), weights_list.end(),
		default_value );
}
Example #8
0
Real
synfig::hom_to_std(const ValueBase &bline, Real pos, bool index_loop, bool bline_loop)
{
	BLinePoint blinepoint0, blinepoint1;
	const std::vector<BLinePoint> list(bline.get_list().begin(),bline.get_list().end());
	int size = list.size(), from_vertex(0);
	// trivial cases
	if(pos == 0.0 || pos == 1.0)
		return pos;
	if(!bline_loop) size--;
	if(size < 1) return Real();
	Real int_pos=int(pos);
	Real one(0.0);
	if (index_loop)
	{
		pos = pos - int_pos;
		if (pos < 0)
		{
			pos++;
			one=1.0;
		}
	}
	else
	{
		if (pos < 0) pos = 0;
		if (pos > 1) pos = 1;
	}
	// Calculate the lengths and the total length
	Real tl(0), pl(0), mpl, bl;
	std::vector<Real> lengths;
	vector<BLinePoint>::const_iterator iter, next;
	tl=bline_length(bline, bline_loop,&lengths);
	// Calculate the my partial length (the length where pos is)
	mpl=pos*tl;
	next=list.begin();
	iter = bline_loop ? --list.end() : next++;
	std::vector<Real>::const_iterator liter(lengths.begin());
	// Find the previous bezier where we pos is placed and the sum
	// of lengths to it (pl)
	// also remember the bezier's length where we stop
	while(mpl > pl && next!=list.end())
	{
		pl+=*liter;
		bl=*liter;
		iter=next;
		next++;
		liter++;
		from_vertex++;
	}
	// correct the iters and partial length in case we passed over
	if(pl > mpl)
	{
		liter--;
		next--;
		if(next==list.begin())
			iter=--list.end();
		else
			iter--;
		pl-=*liter;
		from_vertex--;
	}
	// set up the cureve
	blinepoint0 = *iter;
	blinepoint1 = *next;
	etl::hermite<Vector> curve(blinepoint0.get_vertex(),   blinepoint1.get_vertex(),
							blinepoint0.get_tangent2(), blinepoint1.get_tangent1());
	// Find the solution to which is the standard postion which matches the current
	// homogenous position
	// Secant method: http://en.wikipedia.org/wiki/Secant_method
	Real sn(0.0); // the standard position on current bezier
	Real sn1(0.0), sn2(1.0);
	Real t0((mpl-pl)/bl); // the homogenous position on the current bezier
	int iterations=0;
	int max_iterations=100;
	Real max_error(0.00001);
	Real error;
	Real fsn1(t0-curve.find_distance(0.0,sn1)/bl);
	Real fsn2(t0-curve.find_distance(0.0,sn2)/bl);
	Real fsn;
	do
	{
		sn=sn1-fsn1*((sn1-sn2)/(fsn1-fsn2));
		fsn=t0-curve.find_distance(0.0, sn)/bl;
		sn2=sn1;
		sn1=sn;
		fsn2=fsn1;
		fsn1=fsn;
		error=fabs(fsn2-fsn1);
		iterations++;
	}while (error>max_error && max_iterations > iterations);
	// convert the current standard index (s) to the bline's standard index
	// and return it
	return int_pos+Real(from_vertex + sn)/size-one;
}
Example #9
0
Real
synfig::find_closest_point(const ValueBase &bline, const Point &pos, Real &radius, bool loop, Point *out_point)
{
	Real d,step;
	float time = 0;
	float best_time = 0;
	int best_index = -1;
	synfig::Point best_point;

	if(radius==0)radius=10000000;
	Real closest(10000000);

	int i=0;
	std::vector<BLinePoint> list(bline.get_list().begin(),bline.get_list().end());
	typedef std::vector<BLinePoint>::const_iterator iterT;
	iterT iter, prev, first;
	for(iter=list.begin(); iter!=list.end(); ++i, ++iter)
	{
		if( first == iterT() )
			first = iter;

		if( prev != iterT() )
		{
			bezier<Point>	curve;

			curve[0] = (*prev).get_vertex();
			curve[1] = curve[0] + (*prev).get_tangent2()/3;
			curve[3] = (*iter).get_vertex();
			curve[2] = curve[3] - (*iter).get_tangent1()/3;
			curve.sync();

			#if 0
			// I don't know why this doesn't work
			time=curve.find_closest(pos,6);
			d=((curve(time)-pos).mag_squared());

			#else
			//set the step size based on the size of the picture
			d = (curve[1] - curve[0]).mag() + (curve[2]-curve[1]).mag()	+ (curve[3]-curve[2]).mag();

			step = d/(2*radius); //want to make the distance between lines happy

			step = max(step,0.01); //100 samples should be plenty
			step = min(step,0.1); //10 is minimum

			d = find_closest(curve,pos,step,&closest,&time);
			#endif

			if(d < closest)
			{
				closest = d;
				best_time = time;
				best_index = i;
				best_point = curve(best_time);
			}

		}

		prev = iter;
	}

	// Loop if necessary
	if( loop && ( first != iterT() ) && ( prev != iterT() ) )
	{
		bezier<Point>	curve;

		curve[0] = (*prev).get_vertex();
		curve[1] = curve[0] + (*prev).get_tangent2()/3;
		curve[3] = (*first).get_vertex();
		curve[2] = curve[3] - (*first).get_tangent1()/3;
		curve.sync();

		#if 0
		// I don't know why this doesn't work
		time=curve.find_closest(pos,6);
		d=((curve(time)-pos).mag_squared());

		#else
		//set the step size based on the size of the picture
		d = (curve[1] - curve[0]).mag() + (curve[2]-curve[1]).mag()	+ (curve[3]-curve[2]).mag();

		step = d/(2*radius); //want to make the distance between lines happy

		step = max(step,0.01); //100 samples should be plenty
		step = min(step,0.1); //10 is minimum

			d = find_closest(curve,pos,step,&closest,&time);
		#endif

		if(d < closest)
		{
			closest = d;
			best_time = time;
			best_index = 0;
			best_point = curve(best_time);
		}
	}

	if(best_index != -1)
	{
		if(out_point)
			*out_point = best_point;

		int loop_adjust(loop ? 0 : -1);
		int size = list.size();
		Real amount = (best_index + best_time + loop_adjust) / (size + loop_adjust);
		return amount;
	}

	return 0.0;

}