PathCutting.cpp revision 77eda576f455eeb23c7b92510f38bc60738473ab
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Created by fred on someday in 2004.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * public domain
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Additional Code by Authors:
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Richard Hughes <cyreve@users.sf.net>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Copyright (C) 2005 Richard Hughes
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Released under GNU GPL, read the file 'COPYING' for more information
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshvoid Path::DashPolyline(float head,float tail,float body,int nbD,float *dashs,bool stPlain,float stOffset)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( nbD <= 0 || body <= 0.0001 ) return; // pas de tirets, en fait
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( lastMI >= 0 && lastMI < i-1 ) { // au moins 2 points
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh DashSubPath(i-lastMI,lastMP, orig_pts, head,tail,body,nbD,dashs,stPlain,stOffset);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( lastMI >= 0 && lastMI < int(orig_pts.size()) - 1 ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh DashSubPath(orig_pts.size() - lastMI, lastMP, orig_pts, head, tail, body, nbD, dashs, stPlain, stOffset);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emikloshvoid Path::DashPolylineFromStyle(SPStyle *style, float scale, float min_len)
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh for (int i = 0; i < style->stroke_dash.n_dash; i++) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // modulo dlen
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh this->DashPolyline(0.0, 0.0, dlen, nbD, dashs, true, dash.offset);
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshvoid 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)
1667116521643e2475184b048e0abb77a2aa9735miklosh if ( totLength <= head+tail ) return; // tout mange par la tete et la queue
68664e00e2372534b4df2fdc5f54f836bafece18miklosh // couper les bouts en trop
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh NR::Point p=(enLength-curLength)*lastP+(curLength-stLength)*n;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh pT=(lastT*(enLength-curLength)+nT*(curLength-stLength))/(enLength-stLength);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh pT=(nPiece*(curLength-stLength))/(enLength-stLength);
1667116521643e2475184b048e0abb77a2aa9735miklosh } else if ( nPlain == false && dashPlain == true ) {
1667116521643e2475184b048e0abb77a2aa9735miklosh // faire les tirets
1667116521643e2475184b048e0abb77a2aa9735miklosh if ( curLength >= head /*&& curLength+nl <= totLength-tail*/ ) {
1667116521643e2475184b048e0abb77a2aa9735miklosh if ( enLength <= totLength-tail ) nl=enLength-curLength; else nl=totLength-tail-curLength;
1667116521643e2475184b048e0abb77a2aa9735miklosh //nPlain=stPlain;
68664e00e2372534b4df2fdc5f54f836bafece18miklosh NR::Point p=(enLength-curLength-leftInDash)*lastP+(curLength+leftInDash-stLength)*n;
68664e00e2372534b4df2fdc5f54f836bafece18miklosh pT=(lastT*(enLength-curLength-leftInDash)+nT*(curLength+leftInDash-stLength))/(enLength-stLength);
68664e00e2372534b4df2fdc5f54f836bafece18miklosh pT=(nPiece*(curLength+leftInDash-stLength))/(enLength-stLength);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh } else if ( nPlain == false && dashPlain == true ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh NR::Point p=(enLength-curLength-leftInDash)*lastP+(curLength+leftInDash-stLength)*n;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh pT=(lastT*(enLength-curLength-leftInDash)+nT*(curLength+leftInDash-stLength))/(enLength-stLength);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh pT=(nPiece*(curLength+leftInDash-stLength))/(enLength-stLength);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( curLength <= totLength-tail && curLength+nl > totLength-tail ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh } else if ( nPlain == false && dashPlain == true ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh NR::Point p=(enLength-curLength)*lastP+(curLength-stLength)*n;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh pT=(lastT*(enLength-curLength)+nT*(curLength-stLength))/(enLength-stLength);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh pT=(nPiece*(curLength-stLength))/(enLength-stLength);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // continuer
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh switch ( typ ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh currentpath->appendNew<Geom::LineSegment>(Geom::Point(nData->p[0], nData->p[1]));
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh PathDescrMoveTo *nData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh currentpath->start(Geom::Point(nData->p[0], nData->p[1]));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh /* TODO: add testcase for this descr_arcto case */
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh currentpath->appendNew<Geom::SVGEllipticalArc>( nData->rx, nData->ry, nData->angle, nData->large, !nData->clockwise, to_2geom(nData->p) );
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh currentpath->appendNew<Geom::CubicBezier>( Geom::Point(x1,y1) , Geom::Point(x2,y2) , Geom::Point(x3,y3) );
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh currentpath->appendNew<Geom::LineSegment>( Geom::Point(nData->p[0], nData->p[1]) );
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrIntermBezierTo *iData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i+1]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh currentpath->appendNew<Geom::CubicBezier>( Geom::Point(x1,y1) , Geom::Point(x2,y2) , Geom::Point(x3,y3) );
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( bezNb > 0 ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrIntermBezierTo *iData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i+1]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh NR::Point cp1=0.333333*(p_s+2*p_m),cp2=0.333333*(2*p_m+p_e);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh currentpath->appendNew<Geom::CubicBezier>( Geom::Point(x1,y1) , Geom::Point(x2,y2) , Geom::Point(x3,y3) );
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const *>(c)) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const *>(&c)) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Point tms = 3 * ((*cubic_bezier)[1] - (*cubic_bezier)[0]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Point tme = 3 * ((*cubic_bezier)[3] - (*cubic_bezier)[2]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh CubicTo (from_2geom(tmp), from_2geom(tms), from_2geom(tme));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::SVGEllipticalArc const *>(&c)) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh ArcTo( from_2geom(svg_elliptical_arc->finalPoint()),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh svg_elliptical_arc->ray(0), svg_elliptical_arc->ray(1),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh svg_elliptical_arc->large_arc_flag(), !svg_elliptical_arc->sweep_flag() );
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //this case handles sbasis as well as all other curve types
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //recurse to convert the new path resulting from the sbasis to svgd
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh/** 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
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshvoid Path::LoadPath(Geom::Path const &path, Geom::Matrix const &tr, bool doTransformation, bool append)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // TODO: this can be optimized by not generating a new path here, but doing the transform in AddCurve
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // directly on the curve parameters
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Path const pathtr = doTransformation ? path * tr : path;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for(Geom::Path::const_iterator cit = pathtr.begin(); cit != pathtr.end_open(); ++cit) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // check if closing segment is empty before adding it
3686c32a570c3df738a09b34e85fc5d6bd50d020mikloshvoid Path::LoadPathVector(Geom::PathVector const &pv)
3686c32a570c3df738a09b34e85fc5d6bd50d020mikloshvoid Path::LoadPathVector(Geom::PathVector const &pv, Geom::Matrix const &tr, bool doTransformation)
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh for(Geom::PathVector::const_iterator it = pv.begin(); it != pv.end(); ++it) {
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh * \return Length of the lines in the pts vector.
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh double len = 0;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh for (std::vector<path_lineto>::const_iterator i = pts.begin(); i != pts.end(); i++) {
1db439af43130c9695dbbb661e893d56006bb072miklosh double surf = 0;
1db439af43130c9695dbbb661e893d56006bb072miklosh for (std::vector<path_lineto>::const_iterator i = pts.begin(); i != pts.end(); i++) {
920fbbf5386a5d3b1d0a1304cb71eb48112abe0dmiklosh switch ( typ ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( fabs(addSurf) > 0.0001 || killNoSurf == false ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrMoveTo *nData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh curAdd->ArcTo(nData->p,nData->rx,nData->ry,nData->angle,nData->large,nData->clockwise);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( fabs(addSurf) > 0.0001 || killNoSurf == false ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshPath** Path::SubPathsWithNesting(int &outNb,bool killNoSurf,int nbNest,int* nesting,int* conts)
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh switch ( typ ) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // sauvegarder descr_cmd[0]->associated
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh curAdd->descr_cmd[0]->associated=savA; // associated n'est pas utilise apres
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if ( fabs(addSurf) > 0.0001 || killNoSurf == false ) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh for (int j=0;j<nbNest;j++) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh for (int k=0;k<nbRes;k++) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if ( res[k] && res[k]->descr_cmd.empty() == false && res[k]->descr_cmd[0]->associated == dadMvt ) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if ( conts[j] > i ) break;
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh PathDescrMoveTo *nData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh curAdd->ArcTo(nData->p,nData->rx,nData->ry,nData->angle,nData->large,nData->clockwise);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if ( fabs(addSurf) > 0.0001 || killNoSurf == false ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for (int i = int(descr_cmd.size()) - 1; i >= 0; i--) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh switch ( typ ) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrForced *d = dynamic_cast<PathDescrForced *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrClose *d = dynamic_cast<PathDescrClose *>(descr_cmd[i]);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh PathDescrMoveTo *d = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh PathDescrLineTo *d = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh PathDescrArcTo *d = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh PathDescrCubicTo *d = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrBezierTo *d = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh PathDescrIntermBezierTo *d = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh bool hasMoved = false;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh switch ( typ ) {
8ec52d39f409ecf67125cd4d878b844e9391e7e8miklosh if ( i < int(descr_cmd.size()) - 1 && hasMoved ) { // sinon il termine le chemin
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrMoveTo *nData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmikloshstatic int CmpPosition(const void * p1, const void * p2) {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmikloshstatic int CmpCurv(const void * p1, const void * p2) {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmikloshPath::cut_position* Path::CurvilignToPosition(int nbCv, double *cvAbs, int &nbCut)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh double len = 0;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh double lastT = 0;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for (std::vector<path_lineto>::const_iterator i = pts.begin(); i != pts.end(); i++) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh while ( curAdd > 0.0001 && curCv < nbCv && curPos + curAdd >= cvAbs[curCv] ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh res = (cut_position*) g_realloc(res, (nbCut + 1) * sizeof(cut_position));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh res[nbCut].t = theta * i->t + (1 - theta) * ( (lastPiece != i->piece) ? 0 : lastT);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmikloshTODO: clean up uses of the original function and remove
c4723fe0caa2096d00cb31a7d1506351ba8102dbmikloshOriginal Comment:
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh"this function really belongs to Path. I'll probably move it there eventually,
c4723fe0caa2096d00cb31a7d1506351ba8102dbmikloshhence the Path-esque coding style"
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshtemplate<typename T> inline static T square(T x) {return x*x;}
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshPath::cut_position Path::PointToCurvilignPosition(NR::Point const &pos, unsigned seg) const
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // if the parameter "seg" == 0, then all segments will be considered
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // In however e.g. "seg" == 6 , then only the 6th segment will be considered
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh unsigned bestSeg = 0;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh double bestT = 0.0; // you need a sentinel, or make sure that you prime with correct values.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (pts[i].isMoveTo == polyline_moveto || (seg > 0 && i != seg)) continue;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh thisRangeSquared = square(pts[i].p[NR::X] - pos[NR::X]) + square(pts[i].p[NR::Y] - pos[NR::Y]);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh // we rotate all our coordinates so we're always looking at a mostly vertical line.
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh if (fabs(pts[i - 1].p[NR::X] - pts[i].p[NR::X]) < fabs(pts[i - 1].p[NR::Y] - pts[i].p[NR::Y])) {
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh double gradient = (p2[NR::X] - p1[NR::X]) / (p2[NR::Y] - p1[NR::Y]);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh double intersection = p1[NR::X] - gradient * p1[NR::Y];
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh orthogonalGradient = -1.0 / gradient; // you are going to have numerical problems here.
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh orthogonalIntersection = localPos[NR::X] - orthogonalGradient * localPos[NR::Y];
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh nearestY = (orthogonalIntersection - intersection) / (gradient - orthogonalGradient);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh expand out nearestY fully :
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh nearestY = (localPos[NR::X] - (-1.0 / gradient) * localPos[NR::Y] - intersection) / (gradient - (-1.0 / gradient));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh multiply top and bottom by gradient:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh nearestY = (localPos[NR::X] * gradient - (-1.0) * localPos[NR::Y] - intersection * gradient) / (gradient * gradient - (-1.0));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh and simplify to get:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh double nearestY = (localPos[NR::X] * gradient + localPos[NR::Y] - intersection * gradient)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh t = (nearestY - p1[NR::Y]) / (p2[NR::Y] - p1[NR::Y]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (t <= 0.0) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh thisRangeSquared = square(p1[NR::X] - localPos[NR::X]) + square(p1[NR::Y] - localPos[NR::Y]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh } else if (t >= 1.0) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh thisRangeSquared = square(p2[NR::X] - localPos[NR::X]) + square(p2[NR::Y] - localPos[NR::Y]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh thisRangeSquared = square(nearestY * gradient + intersection - localPos[NR::X]) + square(nearestY - localPos[NR::Y]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh result.t = pts[bestSeg - 1].t * (1.0 - bestT) + pts[bestSeg].t * bestT;
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh this one also belongs to Path
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh returns the length of the path up to the position indicated by t (0..1)
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh TODO: clean up uses of the original function and remove
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh should this take a cut_position as a parameter?
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh length += NR::L2((t - pts[i - 1].t) / (pts[i].t - pts[i - 1].t) * (pts[i].p - pts[i - 1].p));
e45563a3c46261d8c32014f8e516857ba01bd7b7mikloshvoid Path::ConvertPositionsToForced(int nbPos, cut_position *poss)
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh if ( nbPos <= 0 ) {
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh for (int i = int(descr_cmd.size()) - 1; i >= 0; i--) {
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh switch ( typ ) {
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh PathDescrForced *d = dynamic_cast<PathDescrForced *>(descr_cmd[i]);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh descr_cmd[i] = new PathDescrLineTo(NR::Point(0, 0));
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh while ( fp >= 0 && (descr_cmd[fp]->getType()) != descr_moveto ) {
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh if ( fp >= 0 ) {
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh PathDescrMoveTo *oData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[fp]);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh dynamic_cast<PathDescrLineTo*>(descr_cmd[i])->p = oData->p;
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrMoveTo *d = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrLineTo *d = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrArcTo *d = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrCubicTo *d = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrIntermBezierTo *d = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh qsort(poss, nbPos, sizeof(cut_position), CmpPosition);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( ct < 0 ) continue;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( typ == descr_moveto || typ == descr_forced || typ == descr_close ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // ponctuel= rien a faire
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh } else if ( typ == descr_lineto || typ == descr_arcto || typ == descr_cubicto ) {
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh // facile: creation d'un morceau et d'un forced -> 2 commandes
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrCubicTo *oData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[cp]);
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh TangentOnCubAt (ct, startP, *oData,true, theP,theT,len,rad);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[cp]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // decalages dans le tableau des positions de coupe
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrLineTo *oData = dynamic_cast<PathDescrLineTo *>(descr_cmd[cp]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[cp]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // decalages dans le tableau des positions de coupe
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh PathDescrArcTo *oData = dynamic_cast<PathDescrArcTo *>(descr_cmd[cp]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh ArcAngles(startP,endP,rx,ry,angle,large,clockw,sang,eang);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[cp]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // decalages dans le tableau des positions de coupe
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh } else if ( typ == descr_bezierto || typ == descr_interm_bezier ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh while ( theBDI >= 0 && (descr_cmd[theBDI]->getType()) != descr_bezierto ) theBDI--;
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh if ( (descr_cmd[theBDI]->getType()) == descr_bezierto ) {
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh PathDescrBezierTo theBD=*(dynamic_cast<PathDescrBezierTo *>(descr_cmd[theBDI]));
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[theBDI+1]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[theBDI+1]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[theBDI]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // decalages dans le tableau des positions de coupe
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // decouper puis repasser
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[cp]);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[cp+1]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[theBDI]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // decalages dans le tableau des positions de coupe
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[cp+1]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[cp+2]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[theBDI]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // decalages dans le tableau des positions de coupe
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh// poss[j].piece+=1;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // on laisse aussi tomber
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // on laisse tomber
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid Path::ConvertPositionsToMoveTo(int nbPos,cut_position* poss)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh// ConvertForcedToMoveTo();
cb814cb0df20053ca3ef16ce55da474435daf045miklosh // on fait une version customizee a la place
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrMoveTo *nData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[j]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[j]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[j]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[j]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if ( ( doesClose || hasClose ) && hasForced >= 0 ) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // printf("nasty i=%i j=%i frc=%i\n",i,j,hasForced);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // ne doit pas arriver
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // rien a faire ici; de plus il ne peut y en avoir qu'un
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[k]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[k]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh res->ArcTo(nData->p,nData->rx,nData->ry,nData->angle,nData->large,nData->clockwise);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[k]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[k]);
5afaaeaa19bbb236d2556135e75afd28007b6c9fmiklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[k]);
1dd83d492fcbfaebb3603846cc163296d1256c97miklosh // ne doit pas arriver
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // rien a faire ici; de plus il ne peut y en avoir qu'un
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[k]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[k]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh res->ArcTo(nData->p,nData->rx,nData->ry,nData->angle,nData->large,nData->clockwise);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[k]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[k]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[k]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // regular, just move on
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh res->ArcTo(nData->p,nData->rx,nData->ry,nData->angle,nData->large,nData->clockwise);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
ed09b99cb3592f9afb57d2ae3fb88e7f1aca0eb4miklosh Local Variables:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh c-file-style:"stroustrup"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh indent-tabs-mode:nil
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh fill-column:99
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :