lpe-powerstroke.cpp revision 507b5114b6c7eb03fbe6d4480eb88e331fc65f6c
#define INKSCAPE_LPE_POWERSTROKE_CPP
/** \file
* @brief PowerStroke LPE implementation. Creates curves with modifiable stroke width.
*/
/* Authors:
* Johan Engelen <j.b.c.engelen@alumnus.utwente.nl>
*
* Copyright (C) 2010-2011 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include "live_effects/lpe-powerstroke.h"
#include "sp-shape.h"
// for the spiro interpolator:
#include "live_effects/bezctx.h"
#include "live_effects/bezctx_intf.h"
#include "live_effects/spiro.h"
/// @TODO Move this to 2geom
namespace Geom {
namespace Interpolate {
enum InterpolatorType {
};
class Interpolator {
public:
Interpolator() {};
virtual ~Interpolator() {};
// virtual Piecewise<D2<SBasis> > interpolateToPwD2Sb(std::vector<Point> points) = 0;
private:
Interpolator(const Interpolator&);
Interpolator& operator=(const Interpolator&);
};
class Linear : public Interpolator {
public:
Linear() {};
virtual ~Linear() {};
}
return path;
};
private:
};
// this class is terrible
class CubicBezierFit : public Interpolator {
public:
CubicBezierFit() {};
virtual ~CubicBezierFit() {};
// worst case gives us 2 segment per point
for (unsigned i = 0; i < n_points; ++i) {
}
double tolerance_sq = 0; // this value is just a random guess
if ( n_segs > 0)
{
for (int c = 0; c < n_segs; c++) {
}
}
g_free(b);
return fit;
};
private:
CubicBezierFit(const CubicBezierFit&);
CubicBezierFit& operator=(const CubicBezierFit&);
};
/// @todo invent name for this class
class CubicBezierJohan : public Interpolator {
public:
CubicBezierJohan() {};
virtual ~CubicBezierJohan() {};
}
return fit;
};
private:
CubicBezierJohan(const CubicBezierJohan&);
CubicBezierJohan& operator=(const CubicBezierJohan&);
};
class SpiroInterpolator : public Interpolator {
public:
SpiroInterpolator() {};
virtual ~SpiroInterpolator() {};
for (unsigned int i = 0; i < len; ++i) {
controlpoints[i].x = points[i][X];
}
free(s);
return fit;
};
private:
typedef struct {
int is_open;
} bezctx_ink;
{
}
else {
g_message("spiro moveto not finite");
}
#endif
}
{
}
else {
g_message("spiro lineto not finite");
}
#endif
}
{
}
else {
g_message("spiro quadto not finite");
}
#endif
}
{
}
else {
g_message("spiro curveto not finite");
}
#endif
}
bezctx *
}
SpiroInterpolator(const SpiroInterpolator&);
SpiroInterpolator& operator=(const SpiroInterpolator&);
};
switch (type) {
case INTERP_LINEAR:
case INTERP_CUBICBEZIER:
case INTERP_CUBICBEZIER_JOHAN:
case INTERP_SPIRO:
default:
}
}
} //namespace Interpolate
} //namespace Geom
namespace Inkscape {
namespace LivePathEffect {
};
static const Util::EnumDataConverter<unsigned> InterpolatorTypeConverter(InterpolatorTypeData, sizeof(InterpolatorTypeData)/sizeof(*InterpolatorTypeData));
enum LineCapType {
};
};
static const Util::EnumDataConverter<unsigned> LineCapTypeConverter(LineCapTypeData, sizeof(LineCapTypeData)/sizeof(*LineCapTypeData));
enum LineCuspType {
};
};
static const Util::EnumDataConverter<unsigned> LineCuspTypeConverter(LineCuspTypeData, sizeof(LineCuspTypeData)/sizeof(*LineCuspTypeData));
sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve."), "sort_points", &wr, this, true),
interpolator_type(_("Interpolator type"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path."), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN),
start_linecap_type(_("Start line cap type"), _("Determines the shape of the path's start."), "start_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_ROUND),
cusp_linecap_type(_("Cusp line cap type"), _("Determines the shape of the cusps along the path."), "cusp_linecap_type", LineCuspTypeConverter, &wr, this, LINECUSP_ROUND),
end_linecap_type(_("End line cap type"), _("Determines the shape of the path's end."), "end_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_ROUND)
{
show_orig_path = true;
/// @todo offset_points are initialized with empty path, is that bug-save?
}
{
}
void
{
}
{
}
// find discontinuities in piecewise
std::vector<unsigned> find_discontinuities(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in, double eps=Geom::EPSILON)
{
}
}
return indices;
}
{
using namespace Geom;
// perhaps use std::list instead of std::vector?
}
if (sort_points) {
}
// first and last point have same distance from path as second and second to last points, respectively.
// create stroke path where points (x,y) := (t, offset)
Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(static_cast<Geom::Interpolate::InterpolatorType>(interpolator_type.get_value()));
delete interpolator;
// find time values for which x lies outside path domain
// and only take portion of x and y that lies within those time values
}
x = reverse(x);
y = reverse(y);
switch (end_linecap) {
case LINECAP_PEAK:
{
break;
}
case LINECAP_SQUARE:
{
Geom::LineSegment cap12(output.lastValue() + radius*end_deriv, mirrorpath.firstValue() + radius*end_deriv);
break;
}
case LINECAP_BUTT:
{
break;
}
case LINECAP_ROUND:
default:
{
Geom::SVGEllipticalArc cap1(output.lastValue(), radius1, radius1, M_PI/2., false, y.firstValue() < 0, mirrorpath.firstValue()); // note that y is reversed above!
break;
}
}
switch (start_linecap) {
case LINECAP_PEAK:
{
break;
}
case LINECAP_SQUARE:
{
Geom::LineSegment cap22(output.lastValue() - radius*start_deriv, output.firstValue() - radius*start_deriv);
break;
}
case LINECAP_BUTT:
{
break;
}
case LINECAP_ROUND:
default:
{
Geom::SVGEllipticalArc cap2(output.lastValue(), radius2, radius2, M_PI/2., false, y.lastValue() < 0, output.firstValue()); // note that y is reversed above!
break;
}
}
return output;
}
{
using namespace Geom;
// path is closed
// linecap parameter can be ignored
// perhaps use std::list instead of std::vector?
if (sort_points) {
}
// add extra points for interpolation between first and last point
// create stroke path where points (x,y) := (t, offset)
Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(static_cast<Geom::Interpolate::InterpolatorType>(interpolator_type.get_value()));
delete interpolator;
// output 2 separate paths
// find time values for which x lies outside path domain
// and only take portion of x and y that lies within those time values
}
x = reverse(x);
y = reverse(y);
return output;
}
{
using namespace Geom;
} else {
}
// add the output path vector to the already accumulated vector:
}
}
return path_out;
}
LPEPowerStroke::path_from_piecewise_fix_cusps(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &B, double tol) {
/* per definition, the input piecewise should be closed. each discontinuity should be fixed with a cusp-ending,
as defined by cusp_linecap_type
*/
for (unsigned i=1; i < B.size(); i++) {
{ // discontinuity found, so fix it :-)
switch (cusp_linecap) {
default:
break;
}
}
}
}
/* ######################## */
} //namespace LivePathEffect
} /* namespace Inkscape */
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :