|
Carlos Lopez |
a09598 |
/* === S Y N F I G ========================================================= */
|
|
Carlos Lopez |
a09598 |
/*! \file outline.cpp
|
|
Carlos Lopez |
a09598 |
** \brief Implementation of the "Outline" layer
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** $Id$
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** \legal
|
|
Carlos Lopez |
a09598 |
** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
|
|
Carlos Lopez |
a09598 |
** Copyright (c) 2007, 2008 Chris Moore
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** This package is free software; you can redistribute it and/or
|
|
Carlos Lopez |
a09598 |
** modify it under the terms of the GNU General Public License as
|
|
Carlos Lopez |
a09598 |
** published by the Free Software Foundation; either version 2 of
|
|
Carlos Lopez |
a09598 |
** the License, or (at your option) any later version.
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** This package is distributed in the hope that it will be useful,
|
|
Carlos Lopez |
a09598 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Carlos Lopez |
a09598 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Carlos Lopez |
a09598 |
** General Public License for more details.
|
|
Carlos Lopez |
a09598 |
** \endlegal
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
/* ========================================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
//! \note This whole file should be rewritten at some point (darco)
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === H E A D E R S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#ifdef USING_PCH
|
|
Carlos Lopez |
a09598 |
# include "pch.h"
|
|
Carlos Lopez |
a09598 |
#else
|
|
Carlos Lopez |
a09598 |
#ifdef HAVE_CONFIG_H
|
|
Carlos Lopez |
a09598 |
# include <config.h></config.h>
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#include "outline.h"
|
|
Carlos Lopez |
a09598 |
#include <synfig string.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig time.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig context.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig paramdesc.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig renddesc.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig surface.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig value.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig valuenode.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#include <etl calculus=""></etl>
|
|
Carlos Lopez |
a09598 |
#include <etl bezier=""></etl>
|
|
Carlos Lopez |
a09598 |
#include <etl hermite=""></etl>
|
|
Carlos Lopez |
a09598 |
#include <vector></vector>
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#include <synfig valuenode_bline.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
using namespace etl;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === M A C R O S ========================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#define SAMPLES 50
|
|
Carlos Lopez |
a09598 |
#define ROUND_END_FACTOR (4)
|
|
Carlos Lopez |
a09598 |
#define CUSP_THRESHOLD (0.40)
|
|
Carlos Lopez |
a09598 |
#define SPIKE_AMOUNT (4)
|
|
Carlos Lopez |
a09598 |
#define NO_LOOP_COOKIE synfig::Vector(84951305,7836658)
|
|
Carlos Lopez |
a09598 |
#define EPSILON (0.000000001)
|
|
Carlos Lopez |
a09598 |
#define CUSP_TANGENT_ADJUST (0.025)
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === G L O B A L S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
SYNFIG_LAYER_INIT(Outline);
|
|
Carlos Lopez |
a09598 |
SYNFIG_LAYER_SET_NAME(Outline,"outline");
|
|
Carlos Lopez |
a09598 |
SYNFIG_LAYER_SET_LOCAL_NAME(Outline,N_("Outline"));
|
|
Carlos Lopez |
a09598 |
SYNFIG_LAYER_SET_CATEGORY(Outline,N_("Geometry"));
|
|
Carlos Lopez |
a09598 |
SYNFIG_LAYER_SET_VERSION(Outline,"0.2");
|
|
Carlos Lopez |
a09598 |
SYNFIG_LAYER_SET_CVS_ID(Outline,"$Id$");
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === P R O C E D U R E S ================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// This function was adapted from what was
|
|
Carlos Lopez |
a09598 |
// described on http://www.whisqu.se/per/docs/math28.htm
|
|
Carlos Lopez |
a09598 |
Point line_intersection(
|
|
Carlos Lopez |
a09598 |
const Point& p1,
|
|
Carlos Lopez |
a09598 |
const Vector& t1,
|
|
Carlos Lopez |
a09598 |
const Point& p2,
|
|
Carlos Lopez |
a09598 |
const Vector& t2
|
|
Carlos Lopez |
a09598 |
)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
const float& x0(p1[0]);
|
|
Carlos Lopez |
a09598 |
const float& y0(p1[1]);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const float x1(p1[0]+t1[0]);
|
|
Carlos Lopez |
a09598 |
const float y1(p1[1]+t1[1]);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const float& x2(p2[0]);
|
|
Carlos Lopez |
a09598 |
const float& y2(p2[1]);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const float x3(p2[0]+t2[0]);
|
|
Carlos Lopez |
a09598 |
const float y3(p2[1]+t2[1]);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const float near_infinity((float)1e+10);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
float m1,m2; // the slopes of each line
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// compute slopes, note the kluge for infinity, however, this will
|
|
Carlos Lopez |
a09598 |
// be close enough
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if ((x1-x0)!=0)
|
|
Carlos Lopez |
a09598 |
m1 = (y1-y0)/(x1-x0);
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
m1 = near_infinity;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if ((x3-x2)!=0)
|
|
Carlos Lopez |
a09598 |
m2 = (y3-y2)/(x3-x2);
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
m2 = near_infinity;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// compute constants
|
|
Carlos Lopez |
a09598 |
const float& a1(m1);
|
|
Carlos Lopez |
a09598 |
const float& a2(m2);
|
|
Carlos Lopez |
a09598 |
const float b1(-1.0f);
|
|
Carlos Lopez |
a09598 |
const float b2(-1.0f);
|
|
Carlos Lopez |
a09598 |
const float c1(y0-m1*x0);
|
|
Carlos Lopez |
a09598 |
const float c2(y2-m2*x2);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// compute the inverse of the determinate
|
|
Carlos Lopez |
a09598 |
const float det_inv(1.0f/(a1*b2 - a2*b1));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// use Kramers rule to compute the intersection
|
|
Carlos Lopez |
a09598 |
return Point(
|
|
Carlos Lopez |
a09598 |
((b1*c2 - b2*c1)*det_inv),
|
|
Carlos Lopez |
a09598 |
((a2*c1 - a1*c2)*det_inv)
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
} // end Intersect_Lines
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === M E T H O D S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Outline::Outline()
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
old_version=false;
|
|
Carlos Lopez |
a09598 |
round_tip[0]=true;
|
|
Carlos Lopez |
a09598 |
round_tip[1]=true;
|
|
Carlos Lopez |
a09598 |
sharp_cusps=true;
|
|
Carlos Lopez |
a09598 |
width=1.0f;
|
|
Carlos Lopez |
a09598 |
loopyness=1.0f;
|
|
Carlos Lopez |
a09598 |
expand=0;
|
|
Carlos Lopez |
a09598 |
homogeneous_width=true;
|
|
Carlos Lopez |
a09598 |
clear();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
vector<blinepoint> bline_point_list;</blinepoint>
|
|
Carlos Lopez |
a09598 |
bline_point_list.push_back(BLinePoint());
|
|
Carlos Lopez |
a09598 |
bline_point_list.push_back(BLinePoint());
|
|
Carlos Lopez |
a09598 |
bline_point_list.push_back(BLinePoint());
|
|
Carlos Lopez |
a09598 |
bline_point_list[0].set_vertex(Point(0,1));
|
|
Carlos Lopez |
a09598 |
bline_point_list[1].set_vertex(Point(0,-1));
|
|
Carlos Lopez |
a09598 |
bline_point_list[2].set_vertex(Point(1,0));
|
|
Carlos Lopez |
a09598 |
bline_point_list[0].set_tangent(bline_point_list[1].get_vertex()-bline_point_list[2].get_vertex()*0.5f);
|
|
Carlos Lopez |
a09598 |
bline_point_list[1].set_tangent(bline_point_list[2].get_vertex()-bline_point_list[0].get_vertex()*0.5f);
|
|
Carlos Lopez |
a09598 |
bline_point_list[2].set_tangent(bline_point_list[0].get_vertex()-bline_point_list[1].get_vertex()*0.5f);
|
|
Carlos Lopez |
a09598 |
bline_point_list[0].set_width(1.0f);
|
|
Carlos Lopez |
a09598 |
bline_point_list[1].set_width(1.0f);
|
|
Carlos Lopez |
a09598 |
bline_point_list[2].set_width(1.0f);
|
|
Carlos Lopez |
a09598 |
bline=bline_point_list;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
needs_sync=true;
|
|
Carlos Lopez |
5b3df3 |
|
|
Carlos Lopez |
5b3df3 |
Layer::Vocab voc(get_param_vocab());
|
|
Carlos Lopez |
5b3df3 |
Layer::fill_static(voc);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/*! The Sync() function takes the values
|
|
Carlos Lopez |
a09598 |
** and creates a polygon to be rendered
|
|
Carlos Lopez |
a09598 |
** with the polygon layer.
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
void
|
|
Carlos Lopez |
a09598 |
Outline::sync()
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
clear();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if (!bline.get_list().size())
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
synfig::warning(string("Outline::sync():")+N_("No vertices in outline " + string("\"") + get_description() + string("\"")));
|
|
Carlos Lopez |
a09598 |
return;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
try {
|
|
Carlos Lopez |
a09598 |
#if 1
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const bool loop(bline.get_loop());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ValueNode_BLine::Handle bline_valuenode;
|
|
Carlos Lopez |
a09598 |
if (bline.get_contained_type() == ValueBase::TYPE_SEGMENT)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
bline_valuenode = ValueNode_BLine::create(bline);
|
|
Carlos Lopez |
a09598 |
bline = (*bline_valuenode)(0);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const vector<synfig::blinepoint> bline_(bline.get_list().begin(),bline.get_list().end());</synfig::blinepoint>
|
|
Carlos Lopez |
a09598 |
#define bline bline_
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
vector<blinepoint>::const_iterator</blinepoint>
|
|
Carlos Lopez |
a09598 |
iter,
|
|
Carlos Lopez |
a09598 |
next(bline.begin());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const vector<blinepoint>::const_iterator</blinepoint>
|
|
Carlos Lopez |
a09598 |
end(bline.end());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
vector<point></point>
|
|
Carlos Lopez |
a09598 |
side_a,
|
|
Carlos Lopez |
a09598 |
side_b;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(loop)
|
|
Carlos Lopez |
a09598 |
iter=--bline.end();
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
iter=next++;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// iter next
|
|
Carlos Lopez |
a09598 |
// ---- ----
|
|
Carlos Lopez |
a09598 |
// looped nth 1st
|
|
Carlos Lopez |
a09598 |
// !looped 1st 2nd
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Vector first_tangent=bline.front().get_tangent2();
|
|
Carlos Lopez |
a09598 |
Vector last_tangent=iter->get_tangent1();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// if we are looped and drawing sharp cusps, we'll need a value for the incoming tangent
|
|
Carlos Lopez |
a09598 |
if (loop && sharp_cusps && last_tangent.is_equal_to(Vector::zero()))
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
hermite<vector> curve((iter-1)->get_vertex(), iter->get_vertex(), (iter-1)->get_tangent2(), iter->get_tangent1());</vector>
|
|
Carlos Lopez |
a09598 |
const derivative< hermite<vector> > deriv(curve);</vector>
|
|
Carlos Lopez |
a09598 |
last_tangent=deriv(1.0-CUSP_TANGENT_ADJUST);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// `first' is for making the cusps; don't do that for the first point if we're not looped
|
|
Carlos Lopez |
a09598 |
for(bool first=!loop; next!=end; iter=next++)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Vector prev_t(iter->get_tangent1());
|
|
Carlos Lopez |
a09598 |
Vector iter_t(iter->get_tangent2());
|
|
Carlos Lopez |
a09598 |
Vector next_t(next->get_tangent1());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool split_flag(iter->get_split_tangent_flag());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// if iter.t2 == 0 and next.t1 == 0, this is a straight line
|
|
Carlos Lopez |
a09598 |
if(iter_t.is_equal_to(Vector::zero()) && next_t.is_equal_to(Vector::zero()))
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
iter_t=next_t=next->get_vertex()-iter->get_vertex();
|
|
Carlos Lopez |
a09598 |
// split_flag=true;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// if the two points are on top of each other, ignore this segment
|
|
Carlos Lopez |
a09598 |
// leave `first' true if was before
|
|
Carlos Lopez |
a09598 |
if (iter_t.is_equal_to(Vector::zero()))
|
|
Carlos Lopez |
a09598 |
continue;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Setup the curve
|
|
Carlos Lopez |
a09598 |
hermite<vector> curve(</vector>
|
|
Carlos Lopez |
a09598 |
iter->get_vertex(),
|
|
Carlos Lopez |
a09598 |
next->get_vertex(),
|
|
Carlos Lopez |
a09598 |
iter_t,
|
|
Carlos Lopez |
a09598 |
next_t
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const float
|
|
Carlos Lopez |
a09598 |
iter_w((iter->get_width()*width)*0.5f+expand),
|
|
Carlos Lopez |
a09598 |
next_w((next->get_width()*width)*0.5f+expand);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const derivative< hermite<vector> > deriv(curve);</vector>
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if (first)
|
|
Carlos Lopez |
a09598 |
first_tangent = deriv(CUSP_TANGENT_ADJUST);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Make cusps as necessary
|
|
Carlos Lopez |
a09598 |
if(!first && sharp_cusps && split_flag && (!prev_t.is_equal_to(iter_t) || iter_t.is_equal_to(Vector::zero())) && !last_tangent.is_equal_to(Vector::zero()))
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Vector curr_tangent(deriv(CUSP_TANGENT_ADJUST));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const Vector t1(last_tangent.perp().norm());
|
|
Carlos Lopez |
a09598 |
const Vector t2(curr_tangent.perp().norm());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Real cross(t1*t2.perp());
|
|
Carlos Lopez |
a09598 |
Real perp((t1-t2).mag());
|
|
Carlos Lopez |
a09598 |
if(cross>CUSP_THRESHOLD)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
const Point p1(iter->get_vertex()+t1*iter_w);
|
|
Carlos Lopez |
a09598 |
const Point p2(iter->get_vertex()+t2*iter_w);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
side_a.push_back(line_intersection(p1,last_tangent,p2,curr_tangent));
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else if(cross<-CUSP_THRESHOLD)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
const Point p1(iter->get_vertex()-t1*iter_w);
|
|
Carlos Lopez |
a09598 |
const Point p2(iter->get_vertex()-t2*iter_w);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
side_b.push_back(line_intersection(p1,last_tangent,p2,curr_tangent));
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else if(cross>0 && perp>1)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
float amount(max(0.0f,(float)(cross/CUSP_THRESHOLD))*(SPIKE_AMOUNT-1)+1);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
side_a.push_back(iter->get_vertex()+(t1+t2).norm()*iter_w*amount);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else if(cross<0 && perp>1)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
float amount(max(0.0f,(float)(-cross/CUSP_THRESHOLD))*(SPIKE_AMOUNT-1)+1);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
side_b.push_back(iter->get_vertex()-(t1+t2).norm()*iter_w*amount);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Make the outline
|
|
Carlos Lopez |
a09598 |
if(homogeneous_width)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
const float length(curve.length());
|
|
Carlos Lopez |
a09598 |
float dist(0);
|
|
Carlos Lopez |
a09598 |
Point lastpoint;
|
|
Carlos Lopez |
a09598 |
for(float n=0.0f;n<0.999999f;n+=1.0f/SAMPLES)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
const Vector d(deriv(n>CUSP_TANGENT_ADJUST?n:CUSP_TANGENT_ADJUST).perp().norm());
|
|
Carlos Lopez |
a09598 |
const Vector p(curve(n));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(n)
|
|
Carlos Lopez |
a09598 |
dist+=(p-lastpoint).mag();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const float w(((next_w-iter_w)*(dist/length)+iter_w));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
side_a.push_back(p+d*w);
|
|
Carlos Lopez |
a09598 |
side_b.push_back(p-d*w);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
lastpoint=p;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
for(float n=0.0f;n<0.999999f;n+=1.0f/SAMPLES)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
const Vector d(deriv(n>CUSP_TANGENT_ADJUST?n:CUSP_TANGENT_ADJUST).perp().norm());
|
|
Carlos Lopez |
a09598 |
const Vector p(curve(n));
|
|
Carlos Lopez |
a09598 |
const float w(((next_w-iter_w)*n+iter_w));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
side_a.push_back(p+d*w);
|
|
Carlos Lopez |
a09598 |
side_b.push_back(p-d*w);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
last_tangent=deriv(1.0-CUSP_TANGENT_ADJUST);
|
|
Carlos Lopez |
a09598 |
side_a.push_back(curve(1.0)+last_tangent.perp().norm()*next_w);
|
|
Carlos Lopez |
a09598 |
side_b.push_back(curve(1.0)-last_tangent.perp().norm()*next_w);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
first=false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(loop)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
reverse(side_b.begin(),side_b.end());
|
|
Carlos Lopez |
a09598 |
add_polygon(side_a);
|
|
Carlos Lopez |
a09598 |
add_polygon(side_b);
|
|
Carlos Lopez |
a09598 |
return;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Insert code for adding end tip
|
|
Carlos Lopez |
a09598 |
if(round_tip[1] && !loop && side_a.size())
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
// remove the last point
|
|
Carlos Lopez |
a09598 |
side_a.pop_back();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const Point vertex(bline.back().get_vertex());
|
|
Carlos Lopez |
a09598 |
const Vector tangent(last_tangent.norm());
|
|
Carlos Lopez |
a09598 |
const float w((bline.back().get_width()*width)*0.5f+expand);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
hermite<vector> curve(</vector>
|
|
Carlos Lopez |
a09598 |
vertex+tangent.perp()*w,
|
|
Carlos Lopez |
a09598 |
vertex-tangent.perp()*w,
|
|
Carlos Lopez |
a09598 |
tangent*w*ROUND_END_FACTOR,
|
|
Carlos Lopez |
a09598 |
-tangent*w*ROUND_END_FACTOR
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
for(float n=0.0f;n<0.999999f;n+=1.0f/SAMPLES)
|
|
Carlos Lopez |
a09598 |
side_a.push_back(curve(n));
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
for(;!side_b.empty();side_b.pop_back())
|
|
Carlos Lopez |
a09598 |
side_a.push_back(side_b.back());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Insert code for adding begin tip
|
|
Carlos Lopez |
a09598 |
if(round_tip[0] && !loop && side_a.size())
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
// remove the last point
|
|
Carlos Lopez |
a09598 |
side_a.pop_back();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const Point vertex(bline.front().get_vertex());
|
|
Carlos Lopez |
a09598 |
const Vector tangent(first_tangent.norm());
|
|
Carlos Lopez |
a09598 |
const float w((bline.front().get_width()*width)*0.5f+expand);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
hermite<vector> curve(</vector>
|
|
Carlos Lopez |
a09598 |
vertex-tangent.perp()*w,
|
|
Carlos Lopez |
a09598 |
vertex+tangent.perp()*w,
|
|
Carlos Lopez |
a09598 |
-tangent*w*ROUND_END_FACTOR,
|
|
Carlos Lopez |
a09598 |
tangent*w*ROUND_END_FACTOR
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
for(float n=0.0f;n<0.999999f;n+=1.0f/SAMPLES)
|
|
Carlos Lopez |
a09598 |
side_a.push_back(curve(n));
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
add_polygon(side_a);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#else /* 1 */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool loop_;
|
|
Carlos Lopez |
a09598 |
if(bline.get_contained_type()==ValueBase::TYPE_BLINEPOINT)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
ValueBase value(bline);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(loopyness<0.5f)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
value.set_loop(false);
|
|
Carlos Lopez |
a09598 |
loop_=false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
loop_=value.get_loop();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
segment_list=convert_bline_to_segment_list(value);
|
|
Carlos Lopez |
a09598 |
width_list=convert_bline_to_width_list(value);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
clear();
|
|
Carlos Lopez |
a09598 |
return;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(segment_list.empty())
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
synfig::warning("Outline: segment_list is empty, layer disabled");
|
|
Carlos Lopez |
a09598 |
clear();
|
|
Carlos Lopez |
a09598 |
return;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Repair the width list if we need to
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Real default_width;
|
|
Carlos Lopez |
a09598 |
if(width_list.empty())
|
|
Carlos Lopez |
a09598 |
default_width=0.01;
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
default_width=width_list.back();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
while(width_list.size()
|
|
Carlos Lopez |
a09598 |
width_list.push_back(default_width);
|
|
Carlos Lopez |
a09598 |
while(width_list.size()>segment_list.size()+1)
|
|
Carlos Lopez |
a09598 |
width_list.pop_back();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Repair the zero tangents (if any)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
vector<segment>::iterator iter;</segment>
|
|
Carlos Lopez |
a09598 |
for(iter=segment_list.begin();iter!=segment_list.end();++iter)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(iter->t1.mag_squared()<=EPSILON && iter->t2.mag_squared()<=EPSILON)
|
|
Carlos Lopez |
a09598 |
iter->t1=iter->t2=iter->p2-iter->p1;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
vector<real>::iterator iter;</real>
|
|
Carlos Lopez |
a09598 |
vector<real> scaled_width_list;</real>
|
|
Carlos Lopez |
a09598 |
for(iter=width_list.begin();iter!=width_list.end();++iter)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
scaled_width_list.push_back((*iter*width+expand)*0.5f);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Vector::value_type n;
|
|
Carlos Lopez |
a09598 |
etl::hermite<vector> curve;</vector>
|
|
Carlos Lopez |
a09598 |
vector<point> vector_list;</point>
|
|
Carlos Lopez |
a09598 |
Vector last_tangent(segment_list.back().t2);
|
|
Carlos Lopez |
a09598 |
clear();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(!loop_)
|
|
Carlos Lopez |
a09598 |
last_tangent=NO_LOOP_COOKIE;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
vector<segment>::iterator iter;</segment>
|
|
Carlos Lopez |
a09598 |
vector<real>::iterator witer;</real>
|
|
Carlos Lopez |
a09598 |
for(
|
|
Carlos Lopez |
a09598 |
iter=segment_list.begin(),
|
|
Carlos Lopez |
a09598 |
witer=scaled_width_list.begin();
|
|
Carlos Lopez |
a09598 |
iter!=segment_list.end();
|
|
Carlos Lopez |
a09598 |
++iter,++witer)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(iter->t1.mag_squared()<=EPSILON && iter->t2.mag_squared()<=EPSILON)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(iter->p1-(iter->p2-iter->p1).perp().norm()*witer[0]);
|
|
Carlos Lopez |
a09598 |
vector_list.push_back((iter->p2-iter->p1)*0.05+iter->p1-(iter->p2-iter->p1).perp().norm()*((witer[1]-witer[0])*0.05+witer[0]));
|
|
Carlos Lopez |
a09598 |
vector_list.push_back((iter->p2-iter->p1)*0.95+iter->p1-(iter->p2-iter->p1).perp().norm()*((witer[1]-witer[0])*0.95+witer[0]));
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(iter->p2-(iter->p2-iter->p1).perp().norm()*witer[1]);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
curve.p1()=iter->p1;
|
|
Carlos Lopez |
a09598 |
curve.t1()=iter->t1;
|
|
Carlos Lopez |
a09598 |
curve.p2()=iter->p2;
|
|
Carlos Lopez |
a09598 |
curve.t2()=iter->t2;
|
|
Carlos Lopez |
a09598 |
curve.sync();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
etl::derivative<etl::hermite<vector> > deriv(curve);</etl::hermite<vector>
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// without this if statement, the broken tangents would
|
|
Carlos Lopez |
a09598 |
// have boxed edges
|
|
Carlos Lopez |
a09598 |
if(sharp_cusps && last_tangent!=NO_LOOP_COOKIE && !last_tangent.is_equal_to(iter->t1))
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
//Vector curr_tangent(iter->t1);
|
|
Carlos Lopez |
a09598 |
Vector curr_tangent(deriv(CUSP_TANGENT_ADJUST));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const Vector t1(last_tangent.perp().norm());
|
|
Carlos Lopez |
a09598 |
const Vector t2(curr_tangent.perp().norm());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Point p1(iter->p1+t1*witer[0]);
|
|
Carlos Lopez |
a09598 |
Point p2(iter->p1+t2*witer[0]);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Real cross(t1*t2.perp());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(cross>CUSP_THRESHOLD)
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(line_intersection(p1,last_tangent,p2,curr_tangent));
|
|
Carlos Lopez |
a09598 |
else if(cross>0)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
float amount(max(0.0f,(float)(cross/CUSP_THRESHOLD))*(SPIKE_AMOUNT-1)+1);
|
|
Carlos Lopez |
a09598 |
// Push back something to make it look vaguely round;
|
|
Carlos Lopez |
a09598 |
//vector_list.push_back(iter->p1+(t1*1.25+t2).norm()*witer[0]*amount);
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(iter->p1+(t1+t2).norm()*witer[0]*amount);
|
|
Carlos Lopez |
a09598 |
//vector_list.push_back(iter->p1+(t1+t2*1.25).norm()*witer[0]*amount);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
//last_tangent=iter->t2;
|
|
Carlos Lopez |
a09598 |
last_tangent=deriv(1.0f-CUSP_TANGENT_ADJUST);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
for(n=0.0f;n<1.0f;n+=1.0f/SAMPLES)
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(curve(n)+deriv(n>CUSP_TANGENT_ADJUST?n:CUSP_TANGENT_ADJUST).perp().norm()*((witer[1]-witer[0])*n+witer[0]) );
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(curve(1.0)+deriv(1.0-CUSP_TANGENT_ADJUST).perp().norm()*witer[1]);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
if(round_tip[1] && !loop_/* && (!sharp_cusps || segment_list.front().p1!=segment_list.back().p2)*/)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
// remove the last point
|
|
Carlos Lopez |
a09598 |
vector_list.pop_back();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
iter--;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
curve.p1()=iter->p2+Vector(last_tangent[1],-last_tangent[0]).norm()*(*witer);
|
|
Carlos Lopez |
a09598 |
curve.p2()=iter->p2-(Vector(last_tangent[1],-last_tangent[0]).norm()*(*witer));
|
|
Carlos Lopez |
a09598 |
curve.t2()=-(curve.t1()=last_tangent/last_tangent.mag()*(*witer)*ROUND_END_FACTOR);
|
|
Carlos Lopez |
a09598 |
curve.sync();
|
|
Carlos Lopez |
a09598 |
for(n=0.0f;n<1.0f;n+=1.0f/SAMPLES)
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(curve(n));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// remove the last point
|
|
Carlos Lopez |
a09598 |
vector_list.pop_back();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(!loop_)
|
|
Carlos Lopez |
a09598 |
last_tangent=NO_LOOP_COOKIE;
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
add_polygon(vector_list);
|
|
Carlos Lopez |
a09598 |
vector_list.clear();
|
|
Carlos Lopez |
a09598 |
last_tangent=segment_list.front().t1;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
//else
|
|
Carlos Lopez |
a09598 |
// last_tangent=segment_list.back().t2;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
vector<segment>::reverse_iterator iter;</segment>
|
|
Carlos Lopez |
a09598 |
vector<real>::reverse_iterator witer;</real>
|
|
Carlos Lopez |
a09598 |
for(
|
|
Carlos Lopez |
a09598 |
iter=segment_list.rbegin(),
|
|
Carlos Lopez |
a09598 |
witer=scaled_width_list.rbegin(),++witer;
|
|
Carlos Lopez |
a09598 |
!(iter==segment_list.rend());
|
|
Carlos Lopez |
a09598 |
++iter,++witer)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(iter->t1.mag_squared()<=EPSILON && iter->t2.mag_squared()<=EPSILON)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(iter->p2+(iter->p2-iter->p1).perp().norm()*witer[0]);
|
|
Carlos Lopez |
a09598 |
vector_list.push_back((iter->p2-iter->p1)*0.95+iter->p1+(iter->p2-iter->p1).perp().norm()*((witer[-1]-witer[0])*0.95+witer[0]));
|
|
Carlos Lopez |
a09598 |
vector_list.push_back((iter->p2-iter->p1)*0.05+iter->p1+(iter->p2-iter->p1).perp().norm()*((witer[-1]-witer[0])*0.05+witer[0]));
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(iter->p1+(iter->p2-iter->p1).perp().norm()*witer[-1]);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
curve.p1()=iter->p1;
|
|
Carlos Lopez |
a09598 |
curve.t1()=iter->t1;
|
|
Carlos Lopez |
a09598 |
curve.p2()=iter->p2;
|
|
Carlos Lopez |
a09598 |
curve.t2()=iter->t2;
|
|
Carlos Lopez |
a09598 |
curve.sync();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
etl::derivative<etl::hermite<vector> > deriv(curve);</etl::hermite<vector>
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// without this if statement, the broken tangents would
|
|
Carlos Lopez |
a09598 |
// have boxed edges
|
|
Carlos Lopez |
a09598 |
if(sharp_cusps && last_tangent!=NO_LOOP_COOKIE && !last_tangent.is_equal_to(iter->t2))
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
//Vector curr_tangent(iter->t2);
|
|
Carlos Lopez |
a09598 |
Vector curr_tangent(deriv(1.0f-CUSP_TANGENT_ADJUST));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
const Vector t1(last_tangent.perp().norm());
|
|
Carlos Lopez |
a09598 |
const Vector t2(curr_tangent.perp().norm());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Point p1(iter->p2-t1*witer[-1]);
|
|
Carlos Lopez |
a09598 |
Point p2(iter->p2-t2*witer[-1]);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Real cross(t1*t2.perp());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
//if(last_tangent.perp().norm()*curr_tangent.norm()<-CUSP_THRESHOLD)
|
|
Carlos Lopez |
a09598 |
if(cross>CUSP_THRESHOLD)
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(line_intersection(p1,last_tangent,p2,curr_tangent));
|
|
Carlos Lopez |
a09598 |
else if(cross>0)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
float amount(max(0.0f,(float)(cross/CUSP_THRESHOLD))*(SPIKE_AMOUNT-1)+1);
|
|
Carlos Lopez |
a09598 |
// Push back something to make it look vaguely round;
|
|
Carlos Lopez |
a09598 |
//vector_list.push_back(iter->p2-(t1*1.25+t2).norm()*witer[-1]*amount);
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(iter->p2-(t1+t2).norm()*witer[-1]*amount);
|
|
Carlos Lopez |
a09598 |
//vector_list.push_back(iter->p2-(t1+t2*1.25).norm()*witer[-1]*amount);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
//last_tangent=iter->t1;
|
|
Carlos Lopez |
a09598 |
last_tangent=deriv(CUSP_TANGENT_ADJUST);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
for(n=1.0f;n>CUSP_TANGENT_ADJUST;n-=1.0f/SAMPLES)
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(curve(n)-deriv(1-n>CUSP_TANGENT_ADJUST?n:1-CUSP_TANGENT_ADJUST).perp().norm()*((witer[-1]-witer[0])*n+witer[0]) );
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(curve(0.0f)-deriv(CUSP_TANGENT_ADJUST).perp().norm()*witer[0]);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
if(round_tip[0] && !loop_/* && (!sharp_cusps || segment_list.front().p1!=segment_list.back().p2)*/)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
// remove the last point
|
|
Carlos Lopez |
a09598 |
vector_list.pop_back();
|
|
Carlos Lopez |
a09598 |
iter--;
|
|
Carlos Lopez |
a09598 |
witer--;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
curve.p1()=iter->p1+Vector(last_tangent[1],-last_tangent[0]).norm()*(*witer);
|
|
Carlos Lopez |
a09598 |
curve.p2()=iter->p1-(Vector(last_tangent[1],-last_tangent[0]).norm()*(*witer));
|
|
Carlos Lopez |
a09598 |
curve.t1()=-(curve.t2()=last_tangent/last_tangent.mag()*(*witer)*ROUND_END_FACTOR);
|
|
Carlos Lopez |
a09598 |
curve.sync();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
for(n=1.0;n>0.0;n-=1.0/SAMPLES)
|
|
Carlos Lopez |
a09598 |
vector_list.push_back(curve(n));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// remove the last point
|
|
Carlos Lopez |
a09598 |
vector_list.pop_back();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
//if(loop_)
|
|
Carlos Lopez |
a09598 |
// reverse(vector_list.begin(),vector_list.end());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#ifdef _DEBUG
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
vector<point>::iterator iter;</point>
|
|
Carlos Lopez |
a09598 |
for(iter=vector_list.begin();iter!=vector_list.end();++iter)
|
|
Carlos Lopez |
a09598 |
if(!iter->is_valid())
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
synfig::error("Outline::sync(): Bad point in vector_list!");
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
//synfig::info("BLEHH__________--- x:%f, y:%f",vector_list.front()[0],vector_list.front()[1]);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
#endif /* _DEBUG */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
add_polygon(vector_list);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#endif /* 1 */
|
|
Carlos Lopez |
a09598 |
} catch (...) { synfig::error("Outline::sync(): Exception thrown"); throw; }
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#undef bline
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool
|
|
Carlos Lopez |
a09598 |
Outline::set_param(const String & param, const ValueBase &value)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(param=="segment_list")
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(dynamic_param_list().count("segment_list"))
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
connect_dynamic_param("bline",dynamic_param_list().find("segment_list")->second);
|
|
Carlos Lopez |
a09598 |
disconnect_dynamic_param("segment_list");
|
|
Carlos Lopez |
a09598 |
synfig::warning("Outline::set_param(): Updated valuenode connection to use the new \"bline\" parameter.");
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
synfig::warning("Outline::set_param(): The parameter \"segment_list\" is deprecated. Use \"bline\" instead.");
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if( (param=="segment_list" || param=="bline") && value.get_type()==ValueBase::TYPE_LIST)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
//if(value.get_contained_type()!=ValueBase::TYPE_BLINEPOINT)
|
|
Carlos Lopez |
a09598 |
// return false;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bline=value;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
/*
|
|
Carlos Lopez |
a09598 |
if( param=="seg" && value.get_type()==ValueBase::TYPE_SEGMENT)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(!segment_list.empty())
|
|
Carlos Lopez |
a09598 |
segment_list.clear();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
segment_list.push_back(value.get(Segment()));
|
|
Carlos Lopez |
a09598 |
loop_=false;
|
|
Carlos Lopez |
a09598 |
//sync();
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
if( param=="w[0]" && value.get_type()==ValueBase::TYPE_REAL)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(width_list.size()<2)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
width_list.push_back(value.get(Real()));
|
|
Carlos Lopez |
a09598 |
width_list.push_back(value.get(Real()));
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
width_list[0]=value.get(Real());
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
width=1;
|
|
Carlos Lopez |
a09598 |
//sync();
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if( param=="w[1]" && value.get_type()==ValueBase::TYPE_REAL)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(width_list.size()<2)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
width_list.push_back(value.get(Real()));
|
|
Carlos Lopez |
a09598 |
width_list.push_back(value.get(Real()));
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
width_list[1]=value.get(Real());
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
width=1;
|
|
Carlos Lopez |
a09598 |
//sync();
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if( param=="width_list" && value.same_type_as(width_list))
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
width_list=value;
|
|
Carlos Lopez |
a09598 |
//sync();
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
IMPORT(round_tip[0]);
|
|
Carlos Lopez |
a09598 |
IMPORT(round_tip[1]);
|
|
Carlos Lopez |
a09598 |
IMPORT(sharp_cusps);
|
|
Carlos Lopez |
a09598 |
IMPORT_PLUS(width,if(old_version){width*=2.0;});
|
|
Carlos Lopez |
a09598 |
IMPORT(loopyness);
|
|
Carlos Lopez |
a09598 |
IMPORT(expand);
|
|
Carlos Lopez |
a09598 |
IMPORT(homogeneous_width);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(param!="vector_list")
|
|
Carlos Lopez |
a09598 |
return Layer_Polygon::set_param(param,value);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
void
|
|
Carlos Lopez |
a09598 |
Outline::set_time(Context context, Time time)const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
const_cast<outline*>(this)->sync();</outline*>
|
|
Carlos Lopez |
a09598 |
context.set_time(time);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
void
|
|
Carlos Lopez |
a09598 |
Outline::set_time(Context context, Time time, Vector pos)const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
const_cast<outline*>(this)->sync();</outline*>
|
|
Carlos Lopez |
a09598 |
context.set_time(time,pos);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ValueBase
|
|
Carlos Lopez |
a09598 |
Outline::get_param(const String& param)const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
EXPORT(bline);
|
|
Carlos Lopez |
a09598 |
EXPORT(expand);
|
|
Carlos Lopez |
a09598 |
//EXPORT(width_list);
|
|
Carlos Lopez |
a09598 |
//EXPORT(segment_list);
|
|
Carlos Lopez |
a09598 |
EXPORT(homogeneous_width);
|
|
Carlos Lopez |
a09598 |
EXPORT(round_tip[0]);
|
|
Carlos Lopez |
a09598 |
EXPORT(round_tip[1]);
|
|
Carlos Lopez |
a09598 |
EXPORT(sharp_cusps);
|
|
Carlos Lopez |
a09598 |
EXPORT(width);
|
|
Carlos Lopez |
a09598 |
EXPORT(loopyness);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
EXPORT_NAME();
|
|
Carlos Lopez |
a09598 |
EXPORT_VERSION();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(param!="vector_list")
|
|
Carlos Lopez |
a09598 |
return Layer_Polygon::get_param(param);
|
|
Carlos Lopez |
a09598 |
return ValueBase();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Layer::Vocab
|
|
Carlos Lopez |
a09598 |
Outline::get_param_vocab()const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Layer::Vocab ret(Layer_Polygon::get_param_vocab());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Pop off the polygon parameter from the polygon vocab
|
|
Carlos Lopez |
a09598 |
ret.pop_back();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ret.push_back(ParamDesc("bline")
|
|
Carlos Lopez |
a09598 |
.set_local_name(_("Vertices"))
|
|
Carlos Lopez |
a09598 |
.set_origin("origin")
|
|
Carlos Lopez |
a09598 |
.set_hint("width")
|
|
Carlos Lopez |
a09598 |
.set_description(_("A list of BLine Points"))
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/*
|
|
Carlos Lopez |
a09598 |
ret.push_back(ParamDesc("width_list")
|
|
Carlos Lopez |
a09598 |
.set_local_name(_("Point Widths"))
|
|
Carlos Lopez |
a09598 |
.set_origin("segment_list")
|
|
Carlos Lopez |
a09598 |
.hidden()
|
|
Carlos Lopez |
a09598 |
.not_critical()
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ret.push_back(ParamDesc("width")
|
|
Carlos Lopez |
a09598 |
.set_is_distance()
|
|
Carlos Lopez |
a09598 |
.set_local_name(_("Outline Width"))
|
|
Carlos Lopez |
d243d7 |
.set_description(_("Global width of the outline"))
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ret.push_back(ParamDesc("expand")
|
|
Carlos Lopez |
a09598 |
.set_is_distance()
|
|
Carlos Lopez |
a09598 |
.set_local_name(_("Expand"))
|
|
Carlos Lopez |
d243d7 |
.set_description(_("Value to add to the global width"))
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ret.push_back(ParamDesc("sharp_cusps")
|
|
Carlos Lopez |
a09598 |
.set_local_name(_("Sharp Cusps"))
|
|
Carlos Lopez |
a09598 |
.set_description(_("Determines cusp type"))
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ret.push_back(ParamDesc("round_tip[0]")
|
|
Carlos Lopez |
a09598 |
.set_local_name(_("Rounded Begin"))
|
|
Carlos Lopez |
a09598 |
.set_description(_("Round off the tip"))
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ret.push_back(ParamDesc("round_tip[1]")
|
|
Carlos Lopez |
a09598 |
.set_local_name(_("Rounded End"))
|
|
Carlos Lopez |
a09598 |
.set_description(_("Round off the tip"))
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
ret.push_back(ParamDesc("loopyness")
|
|
Carlos Lopez |
a09598 |
.set_local_name(_("Loopyness"))
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
ret.push_back(ParamDesc("homogeneous_width")
|
|
Carlos Lopez |
a09598 |
.set_local_name(_("Homogeneous"))
|
|
Carlos Lopez |
d243d7 |
.set_description(_("When checked the width takes the length of the spline to interpolate"))
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return ret;
|
|
Carlos Lopez |
a09598 |
}
|