lpe-knot.cpp revision b45c97a239397bed144bc7922ee8cc5664d2dcc7
/** @file
* @brief LPE knot effect implementation
*/
/* Authors:
* Jean-Francois Barraud <jf.barraud@gmail.com>
*
* Copyright (C) 2007 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include "sp-shape.h"
#include "live_effects/lpe-knot.h"
#include "style.h"
#include <exception>
namespace Inkscape {
namespace LivePathEffect {
class KnotHolderEntityCrossingSwitcher : public LPEKnotHolderEntity
{
public:
virtual ~KnotHolderEntityCrossingSwitcher() {}
};
//---------------------------------------------------------------------------
//LPEKnot specific Interval manipulation.
//---------------------------------------------------------------------------
//remove an interval from an union of intervals.
//TODO: is it worth moving it to 2Geom?
static
}
return ret;
}
//find the time interval during which patha is hidden by pathb near a given crossing.
// Warning: not accurate!
static
using namespace Geom;
cutterPath.close();
//cutterPath.appendNew<LineSegment> (A-width*N);
}
}
// TODO: Fix all this in 2geom!!!!
//---------------------------------------------------------------------------
// some 2Geom work around.
//---------------------------------------------------------------------------
//Cubic Bezier curves might self intersect; the 2geom code used to miss them.
//This is a quick work around; maybe not needed anymore? -- TODO: check!
//TODO/TOCHECK/TOFIX: I think the BUG is in path-intersection.cpp -> curve_mono_split(...):
//the derivative of the curve should be used instead of the curve itself.
using namespace Geom;
return ret;
}
//TODO: Fix this in 2Geom; I think CrossingSets should not contain duplicates.
//Yeah, I know, there is a "unique" algorithm for that...
//Note: I'm not sure the duplicates are always consecutive!! (can be first and last, I think)
//Note: I also found crossings c with c.ta or c.tb not in path[a] or path[b] domain. This is definitely not normal.
bool dup = false;
dup = true;
g_warning("Duplicate found in a Geom::CrossingSet!");
break;
}
}
if (!dup) {
}
}
}
return result;
}
//---------------------------------------------------------------------------
//LPEKnot specific Crossing Data manipulation.
//---------------------------------------------------------------------------
namespace LPEKnotNS {
//Yet another crossing data representation. Not sure at all it is usefull!
// +: >Given a point, you immediately know which strings are meeting there,
// and the index of the crossing along each string. This makes it easy to check
// topology change. In a CrossingSet, you have to do some search to know the index
// of the crossing along "the second" string (i.e. find the symetric crossing)...
// >Each point is stored only once.
// However, we don't have so many crossing points in general, so none of these points might be relevant.
//
// -: one more clumsy data representation, and "parallelism" failures to expect...
// (in particular, duplicates are hateful with this respect...)
CrossingPoints::CrossingPoints(Geom::CrossingSet const &input, std::vector<Geom::Path> const &path) : std::vector<CrossingPoint>()
{
using namespace Geom;
//g_print("DBG>\nCrossing set content:\n");
for( unsigned n=0; n<i_crossings.size(); n++ ){
Crossing c = i_crossings[n];
unsigned j = c.getOther(i);
//FIXME: times in crossing are sometimes out of range!!
//if (0<ti || ti > 1)g_print("oops! -->");
cp.i = i;
cp.j = j;
if (i==j){
c_bar.a = c.b;
c_bar.b = c.a;
}
//g_print("i=%u, ni=%u, j=%u, nj=%u\n",cp.i,cp.ni,cp.j,cp.nj);
}/*
else{
//debug purpose only:
//This crossing is already registered in output. Just make sure it has a "mirror".
g_print("deja trouve?");
get(i,n);
bool found = false;
for( unsigned ii=0; ii<input.size(); ii++){
Crossings ii_crossings = input[ii];
for( unsigned nn=0; nn<ii_crossings.size(); nn++ ){
Crossing cc = ii_crossings[nn];
if ( (ii!=i || nn!=n) &&
) ) found = true;
}
}
assert( found );
g_print(" oui!\n");
}
*/
}
}
//g_print("CrossingPoints reslut:\n");
//for (unsigned k=0; k<size(); k++){
// g_print("cpts[%u]: i=%u, ni=%u, j=%u, nj=%u\n",k,(*this)[k].i,(*this)[k].ni,(*this)[k].j,(*this)[k].nj);
//}
}
{
using namespace Geom;
}
}
}
{
using namespace Geom;
for( unsigned n=0; n<size(); n++){
CrossingPoint cp = (*this)[n];
}
return result;
}
//FIXME: rewrite to check success: return bool, put result in arg.
{
for (unsigned k=0; k<size(); k++){
if (
) return (*this)[k];
}
assert(false);//debug purpose...
return CrossingPoint();
}
unsigned
{
double dist=-1;
result = k;
}
}
return result;
}
//TODO: Find a way to warn the user when the topology changes.
//TODO: be smarter at guessing the signs when the topology changed?
void
{
bool topo_changed = false;
for (unsigned n=0; n<size(); n++){
other[n].i == (*this)[n].i &&
other[n].j == (*this)[n].j &&
{
}else{
topo_changed = true;
break;
}
}
if (topo_changed){
//TODO: Find a way to warn the user!!
for (unsigned n=0; n<size(); n++){
}else{
(*this)[n].sign = default_value;
}
}
}
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//LPEKnot effect.
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// initialise your parameters here:
interruption_width(_("Interruption width"), _("Size of hidden region of lower string"), "interruption_width", &wr, this, 3),
prop_to_stroke_width(_("unit of stroke width"), _("Consider 'Gap width' as a ratio of stroke width."), "prop_to_stroke_width", &wr, this, true),
switcher_size(_("Switcher size"), _("Orientation indicator/switcher size"), "switcher_size", &wr, this, 15),
crossing_points_vector(_("Crossing Signs"), _("Crossings signs"), "crossing_points_vector", &wr, this)
{
// register all your parameters here, so Inkscape knows which parameters this effect has:
registerKnotHolderHandle(new KnotHolderEntityCrossingSwitcher(), _("Drag to select a crossing, click to flip it"));
selectedCrossing = 0;
}
{
}
void
{
//SPCurve *curve = SP_SHAPE(lpeitem)->curve;
// //TODO: where should the switcher be initialized? (it shows up here if there is no crossing at all)
// //The best would be able to hide it when there is no crossing!
//Geom::Point A = *(curve->first_point());
//Geom::Point B = *(curve->last_point());
//switcher = (A+B)*.5;
}
void
}else if (crossing_points.size()>0){
selectedCrossing = 0;
}else{
//TODO: is there a way to properly hide the helper.
//switcher = Geom::Point(Geom::infinity(),Geom::infinity());
}
}
{
using namespace Geom;
//double width = interruption_width;
double width = interruption_width;
if ( prop_to_stroke_width.get_value() ) {
width *= stroke_width;
}
if (crossingTable.size()==0){
return input_path;
}
for (unsigned i = 0; i < crossingTable.size(); i++){
dom.push_back(Interval(0.,path_in.at(i).size()));//-0.00001));FIX ME: this should not be needed anymore.
//FIXME: check success...
if (sign_code!=0){
}
}
}
}
}
}
return path_out;
}
void
{
using namespace Geom;
//FIXME: do we have to be more carefull to access stroke width?
}
static LPEKnot *
{
g_print ("Warning: Effect is not of type LPEKnot!\n");
return NULL;
}
}
void
{
using namespace Geom;
double r = switcher_size*.1;
char const * svgd;
//TODO: use a nice path!
//svgd = "M -10,0 A 10 10 0 1 0 0,-10 l 5,-1 -1,2";
svgd = "m -7.07,7.07 c 3.9,3.91 10.24,3.91 14.14,0 3.91,-3.9 3.91,-10.24 0,-14.14 -3.9,-3.91 -10.24,-3.91 -14.14,0 l 2.83,-4.24 0.7,2.12";
//svgd = "M 10,0 A 10 10 0 1 1 0,-10 l -5,-1 1,2";
svgd = "m 7.07,7.07 c -3.9,3.91 -10.24,3.91 -14.14,0 -3.91,-3.9 -3.91,-10.24 0,-14.14 3.9,-3.91 10.24,-3.91 14.14,0 l -2.83,-4.24 -0.7,2.12";
}else{
//svgd = "M 10,0 A 10 10 0 1 0 -10,0 A 10 10 0 1 0 10,0 ";
svgd = "M 10,0 C 10,5.52 5.52,10 0,10 -5.52,10 -10,5.52 -10,0 c 0,-5.52 4.48,-10 10,-10 5.52,0 10,4.48 10,10 z";
}
}
void
KnotHolderEntityCrossingSwitcher::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
{
lpe->updateSwitcher();
// if(lpe->selectedCrossing < lpe->crossing_points.size())
// lpe->switcher = lpe->crossing_points[lpe->selectedCrossing].pt;
// else
// lpe->switcher = p;
// FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
}
{
}
void
{
unsigned s = lpe->selectedCrossing;
if (state & GDK_SHIFT_MASK){
}else{
}
// FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
}
}
/* ######################## */
} // 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:encoding=utf-8:textwidth=99 :