**
** \legal
** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+** Copyright (c) 2007 Chris Moore
**
** This package is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License as
#endif
}
-inline float calculate_distance(const std::vector<synfig::BLinePoint>& bline)
+inline float calculate_distance(const std::vector<synfig::BLinePoint>& bline, bool bline_loop)
{
std::vector<synfig::BLinePoint>::const_iterator iter,next,ret;
std::vector<synfig::BLinePoint>::const_iterator end(bline.end());
next=bline.begin();
- //if(loop)
- // iter=--bline.end();
- //else
- iter=next++;
+ if(bline_loop)
+ iter=--bline.end();
+ else
+ iter=next++;
for(;next!=end;iter=next++)
{
inline void
CurveGradient::sync()
{
- curve_length_=calculate_distance(bline);
+ curve_length_=calculate_distance(bline, bline_loop);
}
Real dist;
float perp_dist;
+ bool edge_case = false;
if(bline.size()==0)
return Color::alpha();
next=find_closest(fast,bline,point,t,bline_loop,&perp_dist);
perp_dist/=curve_length_;
}
- else
+ else // not perpendicular
{
next=find_closest(fast,bline,point,t,bline_loop);
}
else if(quality<=2)search_iterations=10;
else if(quality<=4)search_iterations=8;
*/
- if(!perpendicular)
+ if(perpendicular)
+ {
+ if(quality>7)
+ search_iterations=4;
+ }
+ else // not perpendicular
{
if(quality<=6)search_iterations=7;
else if(quality<=7)search_iterations=6;
else if(quality<=8)search_iterations=5;
else search_iterations=4;
}
- else
- {
- if(quality>7)
- search_iterations=4;
- }
// Figure out the closest point on the curve
if (fast)
t = curve.find_closest(fast, point,search_iterations);
-
// Calculate our values
- p1=curve(t);
- tangent=deriv(t).norm();
+ p1=curve(t); // the closest point on the curve
+ tangent=deriv(t).norm(); // the unit tangent at that point
+
+ // if the point we're nearest to is at either end of the
+ // bline, our distance from the curve is the distance from the
+ // point on the curve. we need to know which side of the
+ // curve we're on, so find the average of the two tangents at
+ // this point
+ if (t<0.00001 || t>0.99999)
+ {
+ if (t<0.5)
+ {
+ if (iter->get_split_tangent_flag())
+ {
+ tangent=(iter->get_tangent1().norm()+tangent).norm();
+ edge_case=true;
+ }
+ }
+ else
+ {
+ if (next->get_split_tangent_flag())
+ {
+ tangent=(next->get_tangent2().norm()+tangent).norm();
+ edge_case=true;
+ }
+ }
+ }
if(perpendicular)
{
p1-=tangent*perp_dist;
tangent=-tangent.perp();
}
- else
- {
+ else // not perpendicular
+ // the width of the bline at the closest point on the curve
thickness=(next->get_width()-iter->get_width())*t+iter->get_width();
- }
- //}
}
- if(!perpendicular)
- {
- diff=tangent.perp()*thickness*width;
- p1-=diff*0.5;
- const Real mag(diff.inv_mag());
- supersample=supersample*mag;
- diff*=mag*mag;
- dist=((point_-offset)*diff-p1*diff);
- }
- else
+ if(perpendicular)
{
if(quality>7)
{
dist=((point_-offset)*diff-p1*diff);
}
}
+ else // not perpendicular
+ {
+ if (edge_case)
+ {
+ diff=(p1-(point_-offset));
+ if(diff*tangent.perp()<0) diff=-diff;
+ diff=diff.norm()*thickness*width;
+ }
+ else
+ diff=tangent.perp()*thickness*width;
+
+ p1-=diff*0.5;
+ const Real mag(diff.inv_mag());
+ supersample=supersample*mag;
+ diff*=mag*mag;
+ dist=((point_-offset)*diff-p1*diff);
+ }
if(loop)
dist-=floor(dist);
}
float
-CurveGradient::calc_supersample(const synfig::Point &x, float pw,float ph)const
+CurveGradient::calc_supersample(const synfig::Point &/*x*/, float pw,float /*ph*/)const
{
return pw;
}