PathCutting.cpp revision 64644ef078a66789690938eccf204c7e81fc8fd4
/*
* nlivarot
*
* Created by fred on someday in 2004.
* public domain
*
* Additional Code by Authors:
* Richard Hughes <cyreve@users.sf.net>
*
* Copyright (C) 2005 Richard Hughes
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include <cstring>
#include <string>
#include <cstdio>
#include <typeinfo>
#include "Path.h"
#include "style.h"
#include "livarot/path-description.h"
#include "helper/geom-curves.h"
void Path::DashPolyline(float head,float tail,float body,int nbD,float *dashs,bool stPlain,float stOffset)
{
int lastMI=-1;
int curP = 0;
int lastMP = -1;
}
lastMI=i;
}
curP++;
}
DashSubPath(orig_pts.size() - lastMI, lastMP, orig_pts, head, tail, body, nbD, dashs, stPlain, stOffset);
}
}
{
double dlen = 0.0;
}
}
for (int i=1; i<nbD; i++) {
}
// modulo dlen
}
}
}
void Path::DashSubPath(int spL, int spP, std::vector<path_lineto> const &orig_pts, float head,float tail,float body,int nbD,float *dashs,bool stPlain,float stOffset)
{
double totLength=0;
for (int i=1;i<spL;i++) {
if ( nl > 0.0001 ) {
lastP=n;
}
}
double curLength=0;
double dashPos=0;
int dashInd=0;
bool dashPlain=false;
double lastT=0;
int lastPiece=-1;
for (int i=1;i<spL;i++) {
int nPiece=-1;
double nT=0;
if ( back ) {
} else {
}
if ( nl > 0.0001 ) {
// couper les bouts en trop
dashInd=0;
dashInd++;
dashPos=0;
dashInd=0;
break;
}
}
if ( back ) {
double pT=0;
} else {
}
} else {
AddPoint(p,true);
}
}
}
// faire les tirets
}
if ( leftInDash <= nl ) {
bool nPlain=false;
dashInd++;
} else {
dashInd=0;
dashPos=0;
//nPlain=stPlain;
}
if ( back ) {
double pT=0;
} else {
}
} else {
AddPoint(p,true);
}
if ( back ) {
double pT=0;
} else {
}
} else {
AddPoint(p,false);
}
}
nl-=leftInDash;
} else {
nl=0;
}
}
if ( dashPlain ) {
if ( back ) {
} else {
AddPoint(n,false);
}
}
}
dashInd=0;
dashPos=0;
bool nPlain=false;
if ( back ) {
double pT=0;
} else {
}
} else {
AddPoint(p,false);
}
}
}
// continuer
lastP=n;
}
}
}
Geom::PathVector *
{
int bezNb=0;
switch ( typ ) {
case descr_close:
{
currentpath->close(true);
}
break;
case descr_lineto:
{
}
break;
case descr_moveto:
{
}
break;
case descr_arcto:
{
/* TODO: add testcase for this descr_arcto case */
currentpath->appendNew<Geom::SVGEllipticalArc>( nData->rx, nData->ry, nData->angle, nData->large, !nData->clockwise, nData->p );
}
break;
case descr_cubicto:
{
currentpath->appendNew<Geom::CubicBezier>( Geom::Point(x1,y1) , Geom::Point(x2,y2) , Geom::Point(x3,y3) );
}
break;
case descr_bezierto:
{
bezNb=0;
currentpath->appendNew<Geom::CubicBezier>( Geom::Point(x1,y1) , Geom::Point(x2,y2) , Geom::Point(x3,y3) );
bezNb=0;
} else {
}
}
break;
case descr_interm_bezier:
{
if ( bezNb > 0 ) {
if ( bezNb > 1 ) {
} else {
}
currentpath->appendNew<Geom::CubicBezier>( Geom::Point(x1,y1) , Geom::Point(x2,y2) , Geom::Point(x3,y3) );
bezNb--;
}
}
break;
}
}
return pv;
}
{
if( is_straight_curve(c) )
{
LineTo( c.finalPoint() );
}
/*
else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const *>(c)) {
...
}
*/
}
else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::SVGEllipticalArc const *>(&c)) {
svg_elliptical_arc->rotationAngle(), /// \todo check that this parameter is in radians (rotation_angle returns the angle in radians!)
} else {
//this case handles sbasis as well as all other curve types
//recurse to convert the new path resulting from the sbasis to svgd
}
}
}
/** append is false by default: it means that the path should be resetted. If it is true, the path is not resetted and Geom::Path will be appended as a new path
*/
void Path::LoadPath(Geom::Path const &path, Geom::Affine const &tr, bool doTransformation, bool append)
{
if (!append) {
SetBackData (false);
Reset();
}
return;
// TODO: this can be optimized by not generating a new path here, but doing the transform in AddCurve
// directly on the curve parameters
}
// check if closing segment is empty before adding it
if ( !crv.isDegenerate() ) {
}
Close();
}
}
{
}
void Path::LoadPathVector(Geom::PathVector const &pv, Geom::Affine const &tr, bool doTransformation)
{
SetBackData (false);
Reset();
// FIXME: 2geom is currently unable to maintain SVGElliptical arcs through transformation, and
// sometimes it crashes on a continuity error during conversions, therefore convert to beziers here.
// (the fix is of course to fix 2geom and then remove this if-statement, and just execute the 'else'-clause)
if (doTransformation) {
}
} else {
}
}
}
/**
* \return Length of the lines in the pts vector.
*/
{
return 0;
}
double len = 0;
if ( i->isMoveTo != polyline_moveto ) {
}
lastP = i->p;
}
return len;
}
{
return 0;
}
double surf = 0;
if ( i->isMoveTo == polyline_moveto ) {
} else {
lastP = i->p;
}
}
return surf;
}
{
int nbRes=0;
switch ( typ ) {
case descr_moveto:
if ( curAdd ) {
} else {
delete curAdd;
}
} else {
delete curAdd;
}
}
curAdd->SetBackData(false);
{
}
break;
case descr_close:
{
}
break;
case descr_lineto:
{
}
break;
case descr_cubicto:
{
}
break;
case descr_arcto:
{
}
break;
case descr_bezierto:
{
}
break;
case descr_interm_bezier:
{
}
break;
default:
break;
}
}
if ( curAdd ) {
} else {
delete curAdd;
}
} else {
delete curAdd;
}
}
return res;
}
{
int nbRes=0;
bool increment=false;
switch ( typ ) {
case descr_moveto:
{
// sauvegarder descr_cmd[0]->associated
} else {
delete curAdd;
}
} else {
delete curAdd;
}
}
for (int j=0;j<nbNest;j++) {
for (int k=0;k<nbRes;k++) {
break;
}
}
}
if ( conts[j] > i ) break;
}
if ( hasDad ) {
increment=true;
} else {
curAdd->SetBackData(false);
increment=false;
}
}
break;
case descr_close:
{
}
break;
case descr_lineto:
{
}
break;
case descr_cubicto:
{
}
break;
case descr_arcto:
{
}
break;
case descr_bezierto:
{
}
break;
case descr_interm_bezier:
{
}
break;
default:
break;
}
}
} else {
delete curAdd;
}
} else {
delete curAdd;
}
}
return res;
}
void Path::ConvertForcedToVoid()
{
delete descr_cmd[i];
}
}
}
void Path::ConvertForcedToMoveTo()
{
{
switch ( typ ) {
case descr_forced:
{
d->p = lastPos;
break;
}
case descr_close:
{
d->p = lastPos;
break;
}
case descr_moveto:
{
lastPos = d->p;
break;
}
case descr_lineto:
{
lastPos = d->p;
break;
}
case descr_arcto:
{
lastPos = d->p;
break;
}
case descr_cubicto:
{
lastPos = d->p;
break;
}
case descr_bezierto:
{
lastPos = d->p;
break;
}
case descr_interm_bezier:
{
lastPos = d->p;
break;
}
default:
break;
}
}
}
bool hasMoved = false;
switch ( typ ) {
case descr_forced:
delete descr_cmd[i];
hasMoved = true;
}
break;
case descr_moveto:
{
hasMoved = true;
}
break;
case descr_close:
{
}
break;
case descr_lineto:
{
}
break;
case descr_cubicto:
{
}
break;
case descr_arcto:
{
}
break;
case descr_bezierto:
{
}
break;
case descr_interm_bezier:
{
}
break;
default:
break;
}
}
}
return 0;
}
return 0;
}
{
return NULL;
}
nbCut = 0;
int curCv = 0;
double len = 0;
double lastT = 0;
int lastPiece = -1;
if ( i->isMoveTo == polyline_moveto ) {
lastT = i->t;
} else {
nbCut++;
curCv++;
}
lastP = i->p;
lastT = i->t;
}
}
return res;
}
/*
Moved from Layout-TNG-OutIter.cpp
TODO: clean up uses of the original function and remove
Original Comment:
"this function really belongs to Path. I'll probably move it there eventually,
hence the Path-esque coding style"
*/
template<typename T> inline static T square(T x) {return x*x;}
{
// if the parameter "seg" == 0, then all segments will be considered
// In however e.g. "seg" == 6 , then only the 6th segment will be considered
unsigned bestSeg = 0;
double bestRangeSquared = DBL_MAX;
double thisRangeSquared;
double t;
thisRangeSquared = square(pts[i].p[Geom::X] - pos[Geom::X]) + square(pts[i].p[Geom::Y] - pos[Geom::Y]);
t = 0.0;
} else {
// we rotate all our coordinates so we're always looking at a mostly vertical line.
if (fabs(pts[i - 1].p[Geom::X] - pts[i].p[Geom::X]) < fabs(pts[i - 1].p[Geom::Y] - pts[i].p[Geom::Y])) {
} else {
}
/*
orthogonalGradient = -1.0 / gradient; // you are going to have numerical problems here.
orthogonalIntersection = localPos[Geom::X] - orthogonalGradient * localPos[Geom::Y];
nearestY = (orthogonalIntersection - intersection) / (gradient - orthogonalGradient);
expand out nearestY fully :
nearestY = (localPos[Geom::X] - (-1.0 / gradient) * localPos[Geom::Y] - intersection) / (gradient - (-1.0 / gradient));
multiply top and bottom by gradient:
nearestY = (localPos[Geom::X] * gradient - (-1.0) * localPos[Geom::Y] - intersection * gradient) / (gradient * gradient - (-1.0));
and simplify to get:
*/
if (t <= 0.0) {
thisRangeSquared = square(p1[Geom::X] - localPos[Geom::X]) + square(p1[Geom::Y] - localPos[Geom::Y]);
t = 0.0;
} else if (t >= 1.0) {
thisRangeSquared = square(p2[Geom::X] - localPos[Geom::X]) + square(p2[Geom::Y] - localPos[Geom::Y]);
t = 1.0;
} else {
thisRangeSquared = square(nearestY * gradient + intersection - localPos[Geom::X]) + square(nearestY - localPos[Geom::Y]);
}
}
if (thisRangeSquared < bestRangeSquared) {
bestSeg = i;
bestT = t;
}
}
if (bestSeg == 0) {
result.t = 0.0;
} else {
} else {
}
}
return result;
}
/*
this one also belongs to Path
returns the length of the path up to the position indicated by t (0..1)
TODO: clean up uses of the original function and remove
should this take a cut_position as a parameter?
*/
{
double length = 0.0;
break;
}
}
return length;
}
{
if ( nbPos <= 0 ) {
return;
}
{
switch ( typ ) {
case descr_forced:
{
d->p = lastPos;
break;
}
case descr_close:
{
delete descr_cmd[i];
int fp = i - 1;
fp--;
}
if ( fp >= 0 ) {
}
}
break;
case descr_bezierto:
{
}
}
break;
case descr_moveto:
{
lastPos = d->p;
break;
}
case descr_lineto:
{
lastPos = d->p;
break;
}
case descr_arcto:
{
lastPos = d->p;
break;
}
case descr_cubicto:
{
lastPos = d->p;
break;
}
case descr_interm_bezier:
{
lastPos = d->p;
break;
}
default:
break;
}
}
}
if ( ct < 0 ) continue;
if ( ct > 1 ) continue;
// ponctuel= rien a faire
// facile: creation d'un morceau et d'un forced -> 2 commandes
if ( typ == descr_cubicto ) {
{
}
{
}
// decalages dans le tableau des positions de coupe
} else {
}
}
} else if ( typ == descr_lineto ) {
{
}
{
}
// decalages dans le tableau des positions de coupe
} else {
}
}
} else if ( typ == descr_arcto ) {
double delta=0;
{
}
{
if (clockw) {
} else {
}
}
} else {
}
{
} else {
}
}
// decalages dans le tableau des positions de coupe
} else {
}
}
}
// dur
{
}
{
}
{
}
// decalages dans le tableau des positions de coupe
} else {
}
}
} else {
// decouper puis repasser
{
}
{
}
{
}
// decalages dans le tableau des positions de coupe
} else {
}
}
curP--;
} else {
{
}
{
}
{
}
// decalages dans le tableau des positions de coupe
// poss[j].piece+=1;
} else {
}
}
curP--;
}
}
} else {
// on laisse aussi tomber
}
} else {
// on laisse tomber
}
}
}
}
{
// ConvertForcedToMoveTo();
// on fait une version customizee a la place
if ( typ == descr_moveto ) {
{
}
bool hasClose=false;
int hasForced=-1;
bool doesClose=false;
int j=i+1;
if ( ntyp == descr_moveto ) {
j--;
break;
} else if ( ntyp == descr_forced ) {
} else if ( ntyp == descr_close ) {
hasClose=true;
break;
} else if ( ntyp == descr_lineto ) {
} else if ( ntyp == descr_arcto ) {
} else if ( ntyp == descr_cubicto ) {
} else if ( ntyp == descr_bezierto ) {
} else {
}
}
doesClose=true;
}
// printf("nasty i=%i j=%i frc=%i\n",i,j,hasForced);
// aghhh.
for (int k = hasForced + 1; k < j; k++) {
if ( ntyp == descr_moveto ) {
// ne doit pas arriver
} else if ( ntyp == descr_forced ) {
} else if ( ntyp == descr_close ) {
// rien a faire ici; de plus il ne peut y en avoir qu'un
} else if ( ntyp == descr_lineto ) {
} else if ( ntyp == descr_arcto ) {
} else if ( ntyp == descr_cubicto ) {
} else if ( ntyp == descr_bezierto ) {
} else if ( ntyp == descr_interm_bezier ) {
} else {
}
}
for (int k=i+1;k<hasForced;k++) {
if ( ntyp == descr_moveto ) {
// ne doit pas arriver
} else if ( ntyp == descr_forced ) {
} else if ( ntyp == descr_close ) {
// rien a faire ici; de plus il ne peut y en avoir qu'un
} else if ( ntyp == descr_lineto ) {
} else if ( ntyp == descr_arcto ) {
} else if ( ntyp == descr_cubicto ) {
} else if ( ntyp == descr_bezierto ) {
} else if ( ntyp == descr_interm_bezier ) {
} else {
}
}
i=j;
} else {
// regular, just move on
}
} else if ( typ == descr_close ) {
} else if ( typ == descr_forced ) {
} else if ( typ == descr_lineto ) {
} else if ( typ == descr_arcto ) {
} else if ( typ == descr_cubicto ) {
} else if ( typ == descr_bezierto ) {
} else if ( typ == descr_interm_bezier ) {
} else {
}
}
delete res;
return;
}
/*
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 :