Code

Applying fixes for gcc 4.3 build issues (closes LP: #169115)
[inkscape.git] / src / livarot / PathCutting.cpp
1 /*
2  *  PathCutting.cpp
3  *  nlivarot
4  *
5  *  Created by fred on someday in 2004.
6  *  public domain
7  *
8  *  Additional Code by Authors:
9  *   Richard Hughes <cyreve@users.sf.net>
10  *
11  *  Copyright (C) 2005 Richard Hughes
12  *
13  *  Released under GNU GPL, read the file 'COPYING' for more information
14  */
16 #include <cstring>
17 #include <string>
18 #include <cstdio>
20 #include "Path.h"
21 #include "style.h"
22 #include "livarot/path-description.h"
23 #include "libnr/n-art-bpath.h"
24 #include "libnr/nr-point-matrix-ops.h"
26 void  Path::DashPolyline(float head,float tail,float body,int nbD,float *dashs,bool stPlain,float stOffset)
27 {
28   if ( nbD <= 0 || body <= 0.0001 ) return; // pas de tirets, en fait
30   std::vector<path_lineto> orig_pts = pts;
31   pts.clear();
33   int       lastMI=-1;
34   int curP = 0;
35   int lastMP = -1;
37   for (int i = 0; i < int(orig_pts.size()); i++) {
38     if ( orig_pts[curP].isMoveTo == polyline_moveto ) {
39       if ( lastMI >= 0 && lastMI < i-1 ) { // au moins 2 points
40         DashSubPath(i-lastMI,lastMP, orig_pts, head,tail,body,nbD,dashs,stPlain,stOffset);
41       }
42       lastMI=i;
43       lastMP=curP;
44     }
45     curP++;
46   }
47   if ( lastMI >= 0 && lastMI < int(orig_pts.size()) - 1 ) {
48     DashSubPath(orig_pts.size() - lastMI, lastMP, orig_pts, head, tail, body, nbD, dashs, stPlain, stOffset);
49   }
50 }
52 void  Path::DashPolylineFromStyle(SPStyle *style, float scale, float min_len)
53 {
54     if (style->stroke_dash.n_dash) {
56         double dlen = 0.0;
57         for (int i = 0; i < style->stroke_dash.n_dash; i++) {
58             dlen += style->stroke_dash.dash[i] * scale;
59         }
60         if (dlen >= min_len) {
61             NRVpathDash dash;
62             dash.offset = style->stroke_dash.offset * scale;
63             dash.n_dash = style->stroke_dash.n_dash;
64             dash.dash = g_new(double, dash.n_dash);
65             for (int i = 0; i < dash.n_dash; i++) {
66                 dash.dash[i] = style->stroke_dash.dash[i] * scale;
67             }
68             int    nbD=dash.n_dash;
69             float  *dashs=(float*)malloc((nbD+1)*sizeof(float));
70             while ( dash.offset >= dlen ) dash.offset-=dlen;
71             dashs[0]=dash.dash[0];
72             for (int i=1; i<nbD; i++) {
73                 dashs[i]=dashs[i-1]+dash.dash[i];
74             }
75             // modulo dlen
76             this->DashPolyline(0.0, 0.0, dlen, nbD, dashs, true, dash.offset);
77             free(dashs);
78             g_free(dash.dash);
79         }
80     }
81 }
84 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)
85 {
86   if ( spL <= 0 || spP == -1 ) return;
87   
88   double      totLength=0;
89   NR::Point   lastP;
90   lastP = orig_pts[spP].p;
91   for (int i=1;i<spL;i++) {
92     NR::Point const n = orig_pts[spP + i].p;
93     NR::Point d=n-lastP;
94     double    nl=NR::L2(d);
95     if ( nl > 0.0001 ) {
96       totLength+=nl;
97       lastP=n;
98     }
99   }
100   
101   if ( totLength <= head+tail ) return; // tout mange par la tete et la queue
102   
103   double    curLength=0;
104   double    dashPos=0;
105   int       dashInd=0;
106   bool      dashPlain=false;
107   double    lastT=0;
108   int       lastPiece=-1;
109   lastP = orig_pts[spP].p;
110   for (int i=1;i<spL;i++) {
111     NR::Point   n;
112     int         nPiece=-1;
113     double      nT=0;
114     if ( back ) {
115       n = orig_pts[spP + i].p;
116       nPiece = orig_pts[spP + i].piece;
117       nT = orig_pts[spP + i].t;
118     } else {
119       n = orig_pts[spP + i].p;
120     }
121     NR::Point d=n-lastP;
122     double    nl=NR::L2(d);
123     if ( nl > 0.0001 ) {
124       double   stLength=curLength;
125       double   enLength=curLength+nl;
126       // couper les bouts en trop
127       if ( curLength <= head && curLength+nl > head ) {
128         nl-=head-curLength;
129         curLength=head;
130         dashInd=0;
131         dashPos=stOffset;
132         bool nPlain=stPlain;
133         while ( dashs[dashInd] < stOffset ) {
134           dashInd++;
135           nPlain=!(nPlain);
136           if ( dashInd >= nbD ) {
137             dashPos=0;
138             dashInd=0;
139             break;
140           }
141         }
142         if ( nPlain == true && dashPlain == false ) {
143           NR::Point  p=(enLength-curLength)*lastP+(curLength-stLength)*n;
144           p/=(enLength-stLength);
145           if ( back ) {
146             double pT=0;
147             if ( nPiece == lastPiece ) {
148               pT=(lastT*(enLength-curLength)+nT*(curLength-stLength))/(enLength-stLength);
149             } else {
150               pT=(nPiece*(curLength-stLength))/(enLength-stLength);
151             }
152             AddPoint(p,nPiece,pT,true);
153           } else {
154             AddPoint(p,true);
155           }
156         } else if ( nPlain == false && dashPlain == true ) {
157         }
158         dashPlain=nPlain;
159       }
160       // faire les tirets
161       if ( curLength >= head /*&& curLength+nl <= totLength-tail*/ ) {
162         while ( curLength <= totLength-tail && nl > 0 ) {
163           if ( enLength <= totLength-tail ) nl=enLength-curLength; else nl=totLength-tail-curLength;
164           double  leftInDash=body-dashPos;
165           if ( dashInd < nbD ) {
166             leftInDash=dashs[dashInd]-dashPos;
167           }
168           if ( leftInDash <= nl ) {
169             bool nPlain=false;
170             if ( dashInd < nbD ) {
171               dashPos=dashs[dashInd];
172               dashInd++;
173               if ( dashPlain ) nPlain=false; else nPlain=true;
174             } else {
175               dashInd=0;
176               dashPos=0;
177               //nPlain=stPlain;
178               nPlain=dashPlain;
179             }
180             if ( nPlain == true && dashPlain == false ) {
181               NR::Point  p=(enLength-curLength-leftInDash)*lastP+(curLength+leftInDash-stLength)*n;
182               p/=(enLength-stLength);
183               if ( back ) {
184                 double pT=0;
185                 if ( nPiece == lastPiece ) {
186                   pT=(lastT*(enLength-curLength-leftInDash)+nT*(curLength+leftInDash-stLength))/(enLength-stLength);
187                 } else {
188                   pT=(nPiece*(curLength+leftInDash-stLength))/(enLength-stLength);
189                 }
190                 AddPoint(p,nPiece,pT,true);
191               } else {
192                 AddPoint(p,true);
193               }
194             } else if ( nPlain == false && dashPlain == true ) {
195               NR::Point  p=(enLength-curLength-leftInDash)*lastP+(curLength+leftInDash-stLength)*n;
196               p/=(enLength-stLength);
197               if ( back ) {
198                 double pT=0;
199                 if ( nPiece == lastPiece ) {
200                   pT=(lastT*(enLength-curLength-leftInDash)+nT*(curLength+leftInDash-stLength))/(enLength-stLength);
201                 } else {
202                   pT=(nPiece*(curLength+leftInDash-stLength))/(enLength-stLength);
203                 }
204                 AddPoint(p,nPiece,pT,false);
205               } else {
206                 AddPoint(p,false);
207               }
208             }
209             dashPlain=nPlain;
210             
211             curLength+=leftInDash;
212             nl-=leftInDash;
213           } else {
214             dashPos+=nl;
215             curLength+=nl;
216             nl=0;
217           }
218         }
219         if ( dashPlain ) {
220           if ( back ) {
221             AddPoint(n,nPiece,nT,false);
222           } else {
223             AddPoint(n,false);
224           }
225         }
226         nl=enLength-curLength;
227       }
228       if ( curLength <= totLength-tail && curLength+nl > totLength-tail ) {
229         nl=totLength-tail-curLength;
230         dashInd=0;
231         dashPos=0;
232         bool nPlain=false;
233         if ( nPlain == true && dashPlain == false ) {
234         } else if ( nPlain == false && dashPlain == true ) {
235           NR::Point  p=(enLength-curLength)*lastP+(curLength-stLength)*n;
236           p/=(enLength-stLength);
237           if ( back ) {
238             double pT=0;
239             if ( nPiece == lastPiece ) {
240               pT=(lastT*(enLength-curLength)+nT*(curLength-stLength))/(enLength-stLength);
241             } else {
242               pT=(nPiece*(curLength-stLength))/(enLength-stLength);
243             }
244             AddPoint(p,nPiece,pT,false);
245           } else {
246             AddPoint(p,false);
247           }
248         }
249         dashPlain=nPlain;
250       }
251       // continuer
252       curLength=enLength;
253       lastP=n;
254       lastPiece=nPiece;
255       lastT=nT;
256     }
257   }
259 #include "../display/canvas-bpath.h"
261 void* Path::MakeArtBPath(void)
263         int                              nb_cmd=0,max_cmd=0;
264         NArtBpath* bpath=(NArtBpath*)g_malloc((max_cmd+1)*sizeof(NArtBpath));
265         
266         NR::Point   lastP,bezSt,bezEn,lastMP;
267         int         lastM=-1,bezNb=0;
268   for (int i=0;i<int(descr_cmd.size());i++) {
269     int const typ = descr_cmd[i]->getType();
270     switch ( typ ) {
271       case descr_close:
272       {
273                                 if ( lastM >= 0 ) {
274                                         bpath[lastM].code=NR_MOVETO;
275                                         if ( nb_cmd >= max_cmd ) {
276                                                 max_cmd=2*nb_cmd+1;
277                                                 bpath=(NArtBpath*)g_realloc(bpath,(max_cmd+1)*sizeof(NArtBpath));
278                                         }
279                                         bpath[nb_cmd].code=NR_LINETO;
280                                         bpath[nb_cmd].x3=lastMP[0];
281                                         bpath[nb_cmd].y3=lastMP[1];
282                                         nb_cmd++;
283                                 }
284                                 lastM=-1;
285                         } 
286                                 break;
287                         case descr_lineto:
288                                 {
289         PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
290                                 if ( nb_cmd >= max_cmd ) {
291                                         max_cmd=2*nb_cmd+1;
292                                         bpath=(NArtBpath*)g_realloc(bpath,(max_cmd+1)*sizeof(NArtBpath));
293                                 }
294                                 bpath[nb_cmd].code=NR_LINETO;
295                                 bpath[nb_cmd].x3=nData->p[0];
296                                 bpath[nb_cmd].y3=nData->p[1];
297                                 nb_cmd++;
298                                 lastP=nData->p;
299       }
300         break;
301       case descr_moveto:
302       {
303         PathDescrMoveTo *nData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
304                                 if ( nb_cmd >= max_cmd ) {
305                                         max_cmd=2*nb_cmd+1;
306                                         bpath=(NArtBpath*)g_realloc(bpath,(max_cmd+1)*sizeof(NArtBpath));
307                                 }
308                                 bpath[nb_cmd].code=NR_MOVETO_OPEN;
309                                 bpath[nb_cmd].x3=nData->p[0];
310                                 bpath[nb_cmd].y3=nData->p[1];
311                                 lastM=nb_cmd;
312                                 nb_cmd++;
313                                 lastP=lastMP=nData->p;
314       }
315         break;
316       case descr_arcto:
317       {
318         PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
319                                 lastP=nData->p;
320       }
321         break;
322       case descr_cubicto:
323       {
324         PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
325                                 if ( nb_cmd >= max_cmd ) {
326                                         max_cmd=2*nb_cmd+1;
327                                         bpath=(NArtBpath*)g_realloc(bpath,(max_cmd+1)*sizeof(NArtBpath));
328                                 }
329                                 bpath[nb_cmd].code=NR_CURVETO;
330                                 bpath[nb_cmd].x1=lastP[0]+0.333333*nData->start[0];
331                                 bpath[nb_cmd].y1=lastP[1]+0.333333*nData->start[1];
332                                 bpath[nb_cmd].x2=nData->p[0]-0.333333*nData->end[0];
333                                 bpath[nb_cmd].y2=nData->p[1]-0.333333*nData->end[1];
334                                 bpath[nb_cmd].x3=nData->p[0];
335                                 bpath[nb_cmd].y3=nData->p[1];
336                                 nb_cmd++;
337                                 lastP=nData->p;
338       }
339         break;
340       case descr_bezierto:
341       {
342         PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
343                                 if ( nb_cmd >= max_cmd ) {
344                                         max_cmd=2*nb_cmd+1;
345                                         bpath=(NArtBpath*)g_realloc(bpath,(max_cmd+1)*sizeof(NArtBpath));
346                                 }
347                                 if ( nData->nb <= 0 ) {
348                                         bpath[nb_cmd].code=NR_LINETO;
349                                         bpath[nb_cmd].x3=nData->p[0];
350                                         bpath[nb_cmd].y3=nData->p[1];
351                                         nb_cmd++;
352                                         bezNb=0;
353                                 } else if ( nData->nb == 1 ){
354                                         PathDescrIntermBezierTo *iData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i+1]);
355                                         bpath[nb_cmd].code=NR_CURVETO;
356                                         bpath[nb_cmd].x1=0.333333*(lastP[0]+2*iData->p[0]);
357                                         bpath[nb_cmd].y1=0.333333*(lastP[1]+2*iData->p[1]);
358                                         bpath[nb_cmd].x2=0.333333*(nData->p[0]+2*iData->p[0]);
359                                         bpath[nb_cmd].y2=0.333333*(nData->p[1]+2*iData->p[1]);
360                                         bpath[nb_cmd].x3=nData->p[0];
361                                         bpath[nb_cmd].y3=nData->p[1];
362                                         nb_cmd++;
363                                         bezNb=0;
364                                 } else {
365                                         bezSt=2*lastP-nData->p;
366                                         bezEn=nData->p;
367                                         bezNb=nData->nb;
368                                 }
369                                 lastP=nData->p;
370       }
371         break;
372       case descr_interm_bezier:
373       {
374                                 if ( bezNb > 0 ) {
375                                         PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
376                                         NR::Point p_m=nData->p,p_s=0.5*(bezSt+p_m),p_e;
377                                         if ( bezNb > 1 ) {
378                                                 PathDescrIntermBezierTo *iData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i+1]);
379                                                 p_e=0.5*(p_m+iData->p);
380                                         } else {
381                                                 p_e=bezEn;
382                                         }
383                                         
384                                         if ( nb_cmd >= max_cmd ) {
385                                                 max_cmd=2*nb_cmd+1;
386                                                 bpath=(NArtBpath*)g_realloc(bpath,(max_cmd+1)*sizeof(NArtBpath));
387                                         }
388                                         bpath[nb_cmd].code=NR_CURVETO;
389                                         NR::Point  cp1=0.333333*(p_s+2*p_m),cp2=0.333333*(2*p_m+p_e);
390                                         bpath[nb_cmd].x1=cp1[0];
391                                         bpath[nb_cmd].y1=cp1[1];
392                                         bpath[nb_cmd].x2=cp2[0];
393                                         bpath[nb_cmd].y2=cp2[1];
394                                         bpath[nb_cmd].x3=p_e[0];
395                                         bpath[nb_cmd].y3=p_e[1];
396                                         nb_cmd++;
397                                         
398                                         bezNb--;
399                                 }
400                         }
401         break;
402     }
403   }
404         bpath[nb_cmd].code=NR_END;
405         return bpath;
408 void  Path::LoadArtBPath(void *iV,NR::Matrix const &trans,bool doTransformation)
410   if ( iV == NULL ) return;
411   NArtBpath *bpath = (NArtBpath*)iV;
412   
413   SetBackData (false);
414   Reset();
415   {
416     int   i;
417     bool  closed = false;
418     NR::Point lastX(0,0);
419     
420     for (i = 0; bpath[i].code != NR_END; i++)
421     {
422       switch (bpath[i].code)
423       {
424         case NR_LINETO:
425           lastX[0] = bpath[i].x3;
426           lastX[1] = bpath[i].y3;
427           if ( doTransformation ) {
428             lastX*=trans;
429           }
430             LineTo (lastX);
431             break;
432           
433         case NR_CURVETO:
434         {
435           NR::Point  tmp,tms(0,0),tme(0,0),tm1,tm2;
436           tmp[0]=bpath[i].x3;
437           tmp[1]=bpath[i].y3;
438           tm1[0]=bpath[i].x1;
439           tm1[1]=bpath[i].y1;
440           tm2[0]=bpath[i].x2;
441           tm2[1]=bpath[i].y2;
442           if ( doTransformation ) {
443             tmp*=trans;
444             tm1*=trans;
445             tm2*=trans;
446           }
447           tms=3 * (tm1 - lastX);
448           tme=3 * (tmp - tm2);
449           CubicTo (tmp,tms,tme);
450         }
451           lastX[0] = bpath[i].x3;
452           lastX[1] = bpath[i].y3;
453           if ( doTransformation ) {
454             lastX*=trans;
455           }
456           break;
457           
458         case NR_MOVETO_OPEN:
459         case NR_MOVETO:
460           if (closed) Close ();
461           closed = (bpath[i].code == NR_MOVETO);
462           lastX[0] = bpath[i].x3;
463           lastX[1] = bpath[i].y3;
464           if ( doTransformation ) {
465             lastX*=trans;
466           }
467             MoveTo (lastX);
468             break;
469         default:
470           break;
471       }
472     }
473     if (closed) Close ();
474   }
478 /**
479  *    \return Length of the lines in the pts vector.
480  */
482 double Path::Length()
484     if ( pts.empty() ) {
485         return 0;
486     }
488     NR::Point lastP = pts[0].p;
490     double len = 0;
491     for (std::vector<path_lineto>::const_iterator i = pts.begin(); i != pts.end(); i++) {
493         if ( i->isMoveTo != polyline_moveto ) {
494             len += NR::L2(i->p - lastP);
495         }
497         lastP = i->p;
498     }
499     
500     return len;
504 double Path::Surface()
506     if ( pts.empty() ) {
507         return 0;
508     }
509     
510     NR::Point lastM = pts[0].p;
511     NR::Point lastP = lastM;
513     double surf = 0;
514     for (std::vector<path_lineto>::const_iterator i = pts.begin(); i != pts.end(); i++) {
516         if ( i->isMoveTo == polyline_moveto ) {
517             surf += NR::cross(lastM - lastP, lastM);
518             lastP = lastM = i->p;
519         } else {
520             surf += NR::cross(i->p - lastP, i->p);
521             lastP = i->p;
522         }
523         
524     }
525     
526   return surf;
530 Path**      Path::SubPaths(int &outNb,bool killNoSurf)
532   int      nbRes=0;
533   Path**   res=NULL;
534   Path*    curAdd=NULL;
535   
536   for (int i=0;i<int(descr_cmd.size());i++) {
537     int const typ = descr_cmd[i]->getType();
538     switch ( typ ) {
539       case descr_moveto:
540         if ( curAdd ) {
541           if ( curAdd->descr_cmd.size() > 1 ) {
542             curAdd->Convert(1.0);
543             double addSurf=curAdd->Surface();
544             if ( fabs(addSurf) > 0.0001 || killNoSurf == false ) {
545               res=(Path**)g_realloc(res,(nbRes+1)*sizeof(Path*));
546               res[nbRes++]=curAdd;
547             } else { 
548               delete curAdd;
549             }
550           } else {
551             delete curAdd;
552           }
553           curAdd=NULL;
554         }
555         curAdd=new Path;
556         curAdd->SetBackData(false);
557         {
558           PathDescrMoveTo *nData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
559           curAdd->MoveTo(nData->p);
560         }
561           break;
562       case descr_close:
563       {
564         curAdd->Close();
565       }
566         break;        
567       case descr_lineto:
568       {
569         PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
570         curAdd->LineTo(nData->p);
571       }
572         break;
573       case descr_cubicto:
574       {
575         PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
576         curAdd->CubicTo(nData->p,nData->start,nData->end);
577       }
578         break;
579       case descr_arcto:
580       {
581         PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
582         curAdd->ArcTo(nData->p,nData->rx,nData->ry,nData->angle,nData->large,nData->clockwise);
583       }
584         break;
585       case descr_bezierto:
586       {
587         PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
588         curAdd->BezierTo(nData->p);
589       }
590         break;
591       case descr_interm_bezier:
592       {
593         PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
594         curAdd->IntermBezierTo(nData->p);
595       }
596         break;
597       default:
598         break;
599     }
600   }
601   if ( curAdd ) {
602     if ( curAdd->descr_cmd.size() > 1 ) {
603       curAdd->Convert(1.0);
604       double addSurf=curAdd->Surface();
605       if ( fabs(addSurf) > 0.0001 || killNoSurf == false  ) {
606         res=(Path**)g_realloc(res,(nbRes+1)*sizeof(Path*));
607         res[nbRes++]=curAdd;
608       } else {
609         delete curAdd;
610       }
611     } else {
612       delete curAdd;
613     }
614   }
615   curAdd=NULL;
616   
617   outNb=nbRes;
618   return res;
620 Path**      Path::SubPathsWithNesting(int &outNb,bool killNoSurf,int nbNest,int* nesting,int* conts)
622   int      nbRes=0;
623   Path**   res=NULL;
624   Path*    curAdd=NULL;
625   bool     increment=false;
626   
627   for (int i=0;i<int(descr_cmd.size());i++) {
628     int const typ = descr_cmd[i]->getType();
629     switch ( typ ) {
630       case descr_moveto:
631       {
632         if ( curAdd && increment == false ) {
633           if ( curAdd->descr_cmd.size() > 1 ) {
634             // sauvegarder descr_cmd[0]->associated
635             int savA=curAdd->descr_cmd[0]->associated;
636             curAdd->Convert(1.0);
637             curAdd->descr_cmd[0]->associated=savA; // associated n'est pas utilise apres
638             double addSurf=curAdd->Surface();
639             if ( fabs(addSurf) > 0.0001 || killNoSurf == false ) {
640               res=(Path**)g_realloc(res,(nbRes+1)*sizeof(Path*));
641               res[nbRes++]=curAdd;
642             } else { 
643               delete curAdd;
644             }
645           } else {
646             delete curAdd;
647           }
648           curAdd=NULL;
649         }
650         Path*  hasDad=NULL;
651         for (int j=0;j<nbNest;j++) {
652           if ( conts[j] == i && nesting[j] >= 0 ) {
653             int  dadMvt=conts[nesting[j]];
654             for (int k=0;k<nbRes;k++) {
655               if ( res[k] && res[k]->descr_cmd.empty() == false && res[k]->descr_cmd[0]->associated == dadMvt ) {
656                 hasDad=res[k];
657                 break;
658               }
659             }
660           }
661           if ( conts[j] > i  ) break;
662         }
663         if ( hasDad ) {
664           curAdd=hasDad;
665           increment=true;
666         } else {
667           curAdd=new Path;
668           curAdd->SetBackData(false);
669           increment=false;
670         }
671         PathDescrMoveTo *nData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
672         int mNo=curAdd->MoveTo(nData->p);
673         curAdd->descr_cmd[mNo]->associated=i;
674         }
675         break;
676       case descr_close:
677       {
678         curAdd->Close();
679       }
680         break;        
681       case descr_lineto:
682       {
683         PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
684         curAdd->LineTo(nData->p);
685       }
686         break;
687       case descr_cubicto:
688       {
689         PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
690         curAdd->CubicTo(nData->p,nData->start,nData->end);
691       }
692         break;
693       case descr_arcto:
694       {
695         PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
696         curAdd->ArcTo(nData->p,nData->rx,nData->ry,nData->angle,nData->large,nData->clockwise);
697       }
698         break;
699       case descr_bezierto:
700       {
701         PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
702         curAdd->BezierTo(nData->p);
703       }
704         break;
705       case descr_interm_bezier:
706       {
707         PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
708         curAdd->IntermBezierTo(nData->p);
709       }
710         break;
711       default:
712         break;
713     }
714   }
715   if ( curAdd && increment == false ) {
716     if ( curAdd->descr_cmd.size() > 1 ) {
717       curAdd->Convert(1.0);
718       double addSurf=curAdd->Surface();
719       if ( fabs(addSurf) > 0.0001 || killNoSurf == false  ) {
720         res=(Path**)g_realloc(res,(nbRes+1)*sizeof(Path*));
721         res[nbRes++]=curAdd;
722       } else {
723         delete curAdd;
724       }
725     } else {
726       delete curAdd;
727     }
728   }
729   curAdd=NULL;
730   
731   outNb=nbRes;
732   return res;
736 void Path::ConvertForcedToVoid()
737 {  
738     for (int i=0; i < int(descr_cmd.size()); i++) {
739         if ( descr_cmd[i]->getType() == descr_forced) {
740             delete descr_cmd[i];
741             descr_cmd.erase(descr_cmd.begin() + i);
742         }
743     }
747 void Path::ConvertForcedToMoveTo()
748 {  
749     NR::Point lastSeen(0, 0);
750     NR::Point lastMove(0, 0);
751     
752     {
753         NR::Point lastPos(0, 0);
754         for (int i = int(descr_cmd.size()) - 1; i >= 0; i--) {
755             int const typ = descr_cmd[i]->getType();
756             switch ( typ ) {
757             case descr_forced:
758             {
759                 PathDescrForced *d = dynamic_cast<PathDescrForced *>(descr_cmd[i]);
760                 d->p = lastPos;
761                 break;
762             }
763             case descr_close:
764             {
765                 PathDescrClose *d = dynamic_cast<PathDescrClose *>(descr_cmd[i]);
766                 d->p = lastPos;
767                 break;
768             }
769             case descr_moveto:
770             {
771                 PathDescrMoveTo *d = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
772                 lastPos = d->p;
773                 break;
774             }
775             case descr_lineto:
776             {
777                 PathDescrLineTo *d = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
778                 lastPos = d->p;
779                 break;
780             }
781             case descr_arcto:
782             {
783                 PathDescrArcTo *d = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
784                 lastPos = d->p;
785                 break;
786             }
787             case descr_cubicto:
788             {
789                 PathDescrCubicTo *d = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
790                 lastPos = d->p;
791                 break;
792             }
793             case descr_bezierto:
794             {
795                 PathDescrBezierTo *d = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
796                 lastPos = d->p;
797                 break;
798             }
799             case descr_interm_bezier:
800             {
801                 PathDescrIntermBezierTo *d = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
802                 lastPos = d->p;
803                 break;
804             }
805             default:
806                 break;
807             }
808         }
809     }
811     bool hasMoved = false;
812     for (int i = 0; i < int(descr_cmd.size()); i++) {
813         int const typ = descr_cmd[i]->getType();
814         switch ( typ ) {
815         case descr_forced:
816             if ( i < int(descr_cmd.size()) - 1 && hasMoved ) { // sinon il termine le chemin
818                 delete descr_cmd[i];
819                 descr_cmd[i] = new PathDescrMoveTo(lastSeen);
820                 lastMove = lastSeen;
821                 hasMoved = true;
822             }
823             break;
824             
825         case descr_moveto:
826         {
827           PathDescrMoveTo *nData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
828           lastMove = lastSeen = nData->p;
829           hasMoved = true;
830         }
831         break;
832       case descr_close:
833       {
834         lastSeen=lastMove;
835       }
836         break;        
837       case descr_lineto:
838       {
839         PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
840         lastSeen=nData->p;
841       }
842         break;
843       case descr_cubicto:
844       {
845         PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
846         lastSeen=nData->p;
847      }
848         break;
849       case descr_arcto:
850       {
851         PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
852         lastSeen=nData->p;
853       }
854         break;
855       case descr_bezierto:
856       {
857         PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
858         lastSeen=nData->p;
859      }
860         break;
861       case descr_interm_bezier:
862       {
863         PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
864         lastSeen=nData->p;
865       }
866         break;
867       default:
868         break;
869     }
870   }
872 static int       CmpPosition(const void * p1, const void * p2) {
873   Path::cut_position *cp1=(Path::cut_position*)p1;
874   Path::cut_position *cp2=(Path::cut_position*)p2;
875   if ( cp1->piece < cp2->piece ) return -1;
876   if ( cp1->piece > cp2->piece ) return 1;
877   if ( cp1->t < cp2->t ) return -1;
878   if ( cp1->t > cp2->t ) return 1;
879   return 0;
881 static int       CmpCurv(const void * p1, const void * p2) {
882   double *cp1=(double*)p1;
883   double *cp2=(double*)p2;
884   if ( *cp1 < *cp2 ) return -1;
885   if ( *cp1 > *cp2 ) return 1;
886   return 0;
890 Path::cut_position* Path::CurvilignToPosition(int nbCv, double *cvAbs, int &nbCut)
892     if ( nbCv <= 0 || pts.empty() || back == false ) {
893         return NULL;
894     }
895   
896     qsort(cvAbs, nbCv, sizeof(double), CmpCurv);
897   
898     cut_position *res = NULL;
899     nbCut = 0;
900     int curCv = 0;
901   
902     double len = 0;
903     double lastT = 0;
904     int lastPiece = -1;
906     NR::Point lastM = pts[0].p;
907     NR::Point lastP = lastM;
909     for (std::vector<path_lineto>::const_iterator i = pts.begin(); i != pts.end(); i++) {
911         if ( i->isMoveTo == polyline_moveto ) {
913             lastP = lastM = i->p;
914             lastT = i->t;
915             lastPiece = i->piece;
917         } else {
918             
919             double const add = NR::L2(i->p - lastP);
920             double curPos = len;
921             double curAdd = add;
922             
923             while ( curAdd > 0.0001 && curCv < nbCv && curPos + curAdd >= cvAbs[curCv] ) {
924                 double const theta = (cvAbs[curCv] - len) / add;
925                 res = (cut_position*) g_realloc(res, (nbCut + 1) * sizeof(cut_position));
926                 res[nbCut].piece = i->piece;
927                 res[nbCut].t = theta * i->t + (1 - theta) * ( (lastPiece != i->piece) ? 0 : lastT);
928                 nbCut++;
929                 curAdd -= cvAbs[curCv] - curPos;
930                 curPos = cvAbs[curCv];
931                 curCv++;
932             }
933             
934             len += add;
935             lastPiece = i->piece;
936             lastP = i->p;
937             lastT = i->t;
938         }
939     }
940     
941     return res;
944 /* 
945 Moved from Layout-TNG-OutIter.cpp
946 TODO: clean up uses of the original function and remove
948 Original Comment:
949 "this function really belongs to Path. I'll probably move it there eventually,
950 hence the Path-esque coding style"
952 */
953 template<typename T> inline static T square(T x) {return x*x;}
954 Path::cut_position Path::PointToCurvilignPosition(NR::Point const &pos) const
956     unsigned bestSeg = 0;
957     double bestRangeSquared = DBL_MAX;
958     double bestT = 0.0; // you need a sentinel, or make sure that you prime with correct values.
960     for (unsigned i = 1 ; i < pts.size() ; i++) {
961         if (pts[i].isMoveTo == polyline_moveto) continue;
962         NR::Point p1, p2, localPos;
963         double thisRangeSquared;
964         double t;
966         if (pts[i - 1].p == pts[i].p) {
967             thisRangeSquared = square(pts[i].p[NR::X] - pos[NR::X]) + square(pts[i].p[NR::Y] - pos[NR::Y]);
968             t = 0.0;
969         } else {
970             // we rotate all our coordinates so we're always looking at a mostly vertical line.
971             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])) {
972                 p1 = pts[i - 1].p;
973                 p2 = pts[i].p;
974                 localPos = pos;
975             } else {
976                 p1 = pts[i - 1].p.cw();
977                 p2 = pts[i].p.cw();
978                 localPos = pos.cw();
979             }
980             double gradient = (p2[NR::X] - p1[NR::X]) / (p2[NR::Y] - p1[NR::Y]);
981             double intersection = p1[NR::X] - gradient * p1[NR::Y];
982             /*
983               orthogonalGradient = -1.0 / gradient; // you are going to have numerical problems here.
984               orthogonalIntersection = localPos[NR::X] - orthogonalGradient * localPos[NR::Y];
985               nearestY = (orthogonalIntersection - intersection) / (gradient - orthogonalGradient);
987               expand out nearestY fully :
988               nearestY = (localPos[NR::X] - (-1.0 / gradient) * localPos[NR::Y] - intersection) / (gradient - (-1.0 / gradient));
990               multiply top and bottom by gradient:
991               nearestY = (localPos[NR::X] * gradient - (-1.0) * localPos[NR::Y] - intersection * gradient) / (gradient * gradient - (-1.0));
993               and simplify to get:
994             */
995             double nearestY =  (localPos[NR::X] * gradient + localPos[NR::Y] - intersection * gradient)
996                              / (gradient * gradient + 1.0);
997             t = (nearestY - p1[NR::Y]) / (p2[NR::Y] - p1[NR::Y]);
998             if (t <= 0.0) {
999                 thisRangeSquared = square(p1[NR::X] - localPos[NR::X]) + square(p1[NR::Y] - localPos[NR::Y]);
1000                 t = 0.0;
1001             } else if (t >= 1.0) {
1002                 thisRangeSquared = square(p2[NR::X] - localPos[NR::X]) + square(p2[NR::Y] - localPos[NR::Y]);
1003                 t = 1.0;
1004             } else {
1005                 thisRangeSquared = square(nearestY * gradient + intersection - localPos[NR::X]) + square(nearestY - localPos[NR::Y]);
1006             }
1007         }
1009         if (thisRangeSquared < bestRangeSquared) {
1010             bestSeg = i;
1011             bestRangeSquared = thisRangeSquared;
1012             bestT = t;
1013         }
1014     }
1015     Path::cut_position result;
1016     if (bestSeg == 0) {
1017         result.piece = 0;
1018         result.t = 0.0;
1019     } else {
1020         result.piece = pts[bestSeg].piece;
1021         if (result.piece == pts[bestSeg - 1].piece) {
1022             result.t = pts[bestSeg - 1].t * (1.0 - bestT) + pts[bestSeg].t * bestT;
1023         } else {
1024             result.t = pts[bestSeg].t * bestT;
1025         }
1026     }
1027     return result;
1029 /*
1030     this one also belongs to Path
1031     returns the length of the path up to the position indicated by t (0..1)
1033     TODO: clean up uses of the original function and remove
1035     should this take a cut_position as a parameter?
1036 */
1037 double Path::PositionToLength(int piece, double t)
1039     double length = 0.0;
1040     for (unsigned i = 1 ; i < pts.size() ; i++) {
1041         if (pts[i].isMoveTo == polyline_moveto) continue;
1042         if (pts[i].piece == piece && t < pts[i].t) {
1043             length += NR::L2((t - pts[i - 1].t) / (pts[i].t - pts[i - 1].t) * (pts[i].p - pts[i - 1].p));
1044             break;
1045         }
1046         length += NR::L2(pts[i].p - pts[i - 1].p);
1047     }
1048     return length;
1051 void Path::ConvertPositionsToForced(int nbPos, cut_position *poss)
1053     if ( nbPos <= 0 ) {
1054         return;
1055     }
1056     
1057     {
1058         NR::Point lastPos(0, 0);
1059         for (int i = int(descr_cmd.size()) - 1; i >= 0; i--) {
1060             int const typ = descr_cmd[i]->getType();
1061             switch ( typ ) {
1062                 
1063             case descr_forced:
1064             {
1065                 PathDescrForced *d = dynamic_cast<PathDescrForced *>(descr_cmd[i]);
1066                 d->p = lastPos;
1067                 break;
1068             }
1069                 
1070             case descr_close:
1071             {
1072                 delete descr_cmd[i];
1073                 descr_cmd[i] = new PathDescrLineTo(NR::Point(0, 0));
1075                 int fp = i - 1;
1076                 while ( fp >= 0 && (descr_cmd[fp]->getType()) != descr_moveto ) {
1077                     fp--;
1078                 }
1079                 
1080                 if ( fp >= 0 ) {
1081                     PathDescrMoveTo *oData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[fp]);
1082                     dynamic_cast<PathDescrLineTo*>(descr_cmd[i])->p = oData->p;
1083                 }
1084             }
1085             break;
1086             
1087             case descr_bezierto:
1088             {
1089                 PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
1090                 NR::Point theP = nData->p;
1091                 if ( nData->nb == 0 ) {
1092                     lastPos = theP;
1093                 }
1094             }
1095             break;
1096             
1097         case descr_moveto:
1098         {
1099             PathDescrMoveTo *d = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
1100             lastPos = d->p;
1101             break;
1102         }
1103         case descr_lineto:
1104         {
1105             PathDescrLineTo *d = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
1106             lastPos = d->p;
1107             break;
1108         }
1109         case descr_arcto:
1110         {
1111             PathDescrArcTo *d = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
1112             lastPos = d->p;
1113             break;
1114         }
1115         case descr_cubicto:
1116         {
1117             PathDescrCubicTo *d = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
1118             lastPos = d->p;
1119             break;
1120         }
1121         case descr_interm_bezier:
1122         {
1123             PathDescrIntermBezierTo *d = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
1124             lastPos = d->p;
1125             break;
1126         }
1127         default:
1128           break;
1129       }
1130     }
1131   }
1133   qsort(poss, nbPos, sizeof(cut_position), CmpPosition);
1135   for (int curP=0;curP<nbPos;curP++) {
1136     int   cp=poss[curP].piece;
1137     if ( cp < 0 || cp >= int(descr_cmd.size()) ) break;
1138     float ct=poss[curP].t;
1139     if ( ct < 0 ) continue;
1140     if ( ct > 1 ) continue;
1141         
1142     int const typ = descr_cmd[cp]->getType();
1143     if ( typ == descr_moveto || typ == descr_forced || typ == descr_close ) {
1144       // ponctuel= rien a faire
1145     } else if ( typ == descr_lineto || typ == descr_arcto || typ == descr_cubicto ) {
1146       // facile: creation d'un morceau et d'un forced -> 2 commandes
1147       NR::Point        theP;
1148       NR::Point        theT;
1149       NR::Point        startP;
1150       startP=PrevPoint(cp-1);
1151       if ( typ == descr_cubicto ) {
1152         double           len,rad;
1153         NR::Point        stD,enD,endP;
1154         {
1155           PathDescrCubicTo *oData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[cp]);
1156           stD=oData->start;
1157           enD=oData->end;
1158           endP=oData->p;
1159           TangentOnCubAt (ct, startP, *oData,true, theP,theT,len,rad);
1160         }
1161         
1162         theT*=len;
1163         
1164         InsertCubicTo(endP,(1-ct)*theT,(1-ct)*enD,cp+1);
1165         InsertForcePoint(cp+1);
1166         {
1167           PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[cp]);
1168           nData->start=ct*stD;
1169           nData->end=ct*theT;
1170           nData->p=theP;
1171         }
1172         // decalages dans le tableau des positions de coupe
1173         for (int j=curP+1;j<nbPos;j++) {
1174           if ( poss[j].piece == cp ) {
1175             poss[j].piece+=2;
1176             poss[j].t=(poss[j].t-ct)/(1-ct);
1177           } else {
1178             poss[j].piece+=2;
1179           }
1180         }
1181       } else if ( typ == descr_lineto ) {
1182         NR::Point        endP;
1183         {
1184           PathDescrLineTo *oData = dynamic_cast<PathDescrLineTo *>(descr_cmd[cp]);
1185           endP=oData->p;
1186         }
1188         theP=ct*endP+(1-ct)*startP;
1189         
1190         InsertLineTo(endP,cp+1);
1191         InsertForcePoint(cp+1);
1192         {
1193           PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[cp]);
1194           nData->p=theP;
1195         }
1196         // decalages dans le tableau des positions de coupe
1197        for (int j=curP+1;j<nbPos;j++) {
1198           if ( poss[j].piece == cp ) {
1199             poss[j].piece+=2;
1200             poss[j].t=(poss[j].t-ct)/(1-ct);
1201           } else {
1202             poss[j].piece+=2;
1203           }
1204         }
1205       } else if ( typ == descr_arcto ) {
1206         NR::Point        endP;
1207         double           rx,ry,angle;
1208         bool             clockw,large;
1209         double   delta=0;
1210         {
1211           PathDescrArcTo *oData = dynamic_cast<PathDescrArcTo *>(descr_cmd[cp]);
1212           endP=oData->p;
1213           rx=oData->rx;
1214           ry=oData->ry;
1215           angle=oData->angle;
1216           clockw=oData->clockwise;
1217           large=oData->large;
1218         }
1219         {
1220           double      sang,eang;
1221           ArcAngles(startP,endP,rx,ry,angle,large,clockw,sang,eang);
1222           
1223           if (clockw) {
1224             if ( sang < eang ) sang += 2*M_PI;
1225             delta=eang-sang;
1226           } else {
1227             if ( sang > eang ) sang -= 2*M_PI;
1228             delta=eang-sang;
1229           }
1230           if ( delta < 0 ) delta=-delta;
1231         }
1232         
1233         PointAt (cp,ct, theP);
1234         
1235         if ( delta*(1-ct) > M_PI ) {
1236           InsertArcTo(endP,rx,ry,angle,true,clockw,cp+1);
1237         } else {
1238           InsertArcTo(endP,rx,ry,angle,false,clockw,cp+1);
1239         }
1240         InsertForcePoint(cp+1);
1241         {
1242           PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[cp]);
1243           nData->p=theP;
1244           if ( delta*ct > M_PI ) {
1245             nData->clockwise=true;
1246           } else {
1247             nData->clockwise=false;
1248           }
1249         }
1250         // decalages dans le tableau des positions de coupe
1251         for (int j=curP+1;j<nbPos;j++) {
1252           if ( poss[j].piece == cp ) {
1253             poss[j].piece+=2;
1254             poss[j].t=(poss[j].t-ct)/(1-ct);
1255           } else {
1256             poss[j].piece+=2;
1257           }
1258         }
1259       }
1260     } else if ( typ == descr_bezierto || typ == descr_interm_bezier ) {
1261       // dur
1262       int theBDI=cp;
1263       while ( theBDI >= 0 && (descr_cmd[theBDI]->getType()) != descr_bezierto ) theBDI--;
1264       if ( (descr_cmd[theBDI]->getType()) == descr_bezierto ) {
1265         PathDescrBezierTo theBD=*(dynamic_cast<PathDescrBezierTo *>(descr_cmd[theBDI]));
1266         if ( cp >= theBDI && cp < theBDI+theBD.nb ) {
1267           if ( theBD.nb == 1 ) {
1268             NR::Point        endP=theBD.p;
1269             NR::Point        midP;
1270             NR::Point        startP;
1271             startP=PrevPoint(theBDI-1);
1272             {
1273               PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[theBDI+1]);
1274               midP=nData->p;
1275             }
1276             NR::Point       aP=ct*midP+(1-ct)*startP;
1277             NR::Point       bP=ct*endP+(1-ct)*midP;
1278             NR::Point       knotP=ct*bP+(1-ct)*aP;
1279                         
1280             InsertIntermBezierTo(bP,theBDI+2);
1281             InsertBezierTo(knotP,1,theBDI+2);
1282             InsertForcePoint(theBDI+2);
1283             {
1284               PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[theBDI+1]);
1285               nData->p=aP;
1286             }
1287             {
1288               PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[theBDI]);
1289               nData->p=knotP;
1290             }
1291             // decalages dans le tableau des positions de coupe
1292             for (int j=curP+1;j<nbPos;j++) {
1293               if ( poss[j].piece == cp ) {
1294                 poss[j].piece+=3;
1295                 poss[j].t=(poss[j].t-ct)/(1-ct);
1296               } else {
1297                 poss[j].piece+=3;
1298               }
1299             }
1300             
1301           } else {
1302             // decouper puis repasser
1303             if ( cp > theBDI ) {
1304               NR::Point   pcP,ncP;
1305               {
1306                 PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[cp]);
1307                 pcP=nData->p;
1308               }
1309               {
1310                 PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[cp+1]);
1311                 ncP=nData->p;
1312               }
1313               NR::Point knotP=0.5*(pcP+ncP);
1314               
1315               InsertBezierTo(knotP,theBD.nb-(cp-theBDI),cp+1);
1316               {
1317                 PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[theBDI]);
1318                 nData->nb=cp-theBDI;
1319               }
1320               
1321               // decalages dans le tableau des positions de coupe
1322               for (int j=curP;j<nbPos;j++) {
1323                 if ( poss[j].piece == cp ) {
1324                   poss[j].piece+=1;
1325                 } else {
1326                   poss[j].piece+=1;
1327                 }
1328               }
1329               curP--;
1330             } else {
1331               NR::Point   pcP,ncP;
1332               {
1333                 PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[cp+1]);
1334                 pcP=nData->p;
1335               }
1336               {
1337                 PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[cp+2]);
1338                 ncP=nData->p;
1339               }
1340               NR::Point knotP=0.5*(pcP+ncP);
1341               
1342               InsertBezierTo(knotP,theBD.nb-1,cp+2);
1343               {
1344                 PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[theBDI]);
1345                 nData->nb=1;
1346               }
1347               
1348               // decalages dans le tableau des positions de coupe
1349               for (int j=curP;j<nbPos;j++) {
1350                 if ( poss[j].piece == cp ) {
1351 //                  poss[j].piece+=1;
1352                 } else {
1353                   poss[j].piece+=1;
1354                 }
1355               }
1356               curP--;
1357             }
1358           }
1359         } else {
1360           // on laisse aussi tomber
1361         }
1362       } else {
1363         // on laisse tomber
1364       }
1365     }
1366   }
1369 void        Path::ConvertPositionsToMoveTo(int nbPos,cut_position* poss)
1371   ConvertPositionsToForced(nbPos,poss);
1372 //  ConvertForcedToMoveTo();
1373   // on fait une version customizee a la place
1375   Path*  res=new Path;
1376   
1377   NR::Point    lastP(0,0);
1378   for (int i=0;i<int(descr_cmd.size());i++) {
1379     int const typ = descr_cmd[i]->getType();
1380     if ( typ == descr_moveto ) {
1381       NR::Point  np;
1382       {
1383         PathDescrMoveTo *nData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[i]);
1384         np=nData->p;
1385       }
1386       NR::Point  endP;
1387       bool       hasClose=false;
1388       int        hasForced=-1;
1389       bool       doesClose=false;
1390       int        j=i+1;
1391       for (;j<int(descr_cmd.size());j++) {
1392         int const ntyp = descr_cmd[j]->getType();
1393         if ( ntyp == descr_moveto ) {
1394           j--;
1395           break;
1396         } else if ( ntyp == descr_forced ) {
1397           if ( hasForced < 0 ) hasForced=j;
1398         } else if ( ntyp == descr_close ) {
1399           hasClose=true;
1400           break;
1401         } else if ( ntyp == descr_lineto ) {
1402           PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[j]);
1403           endP=nData->p;
1404         } else if ( ntyp == descr_arcto ) {
1405           PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[j]);
1406           endP=nData->p;
1407         } else if ( ntyp == descr_cubicto ) {
1408           PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[j]);
1409           endP=nData->p;
1410         } else if ( ntyp == descr_bezierto ) {
1411           PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[j]);
1412           endP=nData->p;
1413         } else {
1414         }
1415       }
1416       if ( NR::LInfty(endP-np) < 0.00001 ) {
1417         doesClose=true;
1418       }
1419       if ( ( doesClose || hasClose ) && hasForced >= 0 ) {
1420  //       printf("nasty i=%i j=%i frc=%i\n",i,j,hasForced);
1421         // aghhh.
1422         NR::Point   nMvtP=PrevPoint(hasForced);
1423         res->MoveTo(nMvtP);
1424         NR::Point   nLastP=nMvtP;
1425         for (int k = hasForced + 1; k < j; k++) {
1426           int ntyp=descr_cmd[k]->getType();
1427           if ( ntyp == descr_moveto ) {
1428             // ne doit pas arriver
1429           } else if ( ntyp == descr_forced ) {
1430             res->MoveTo(nLastP);
1431           } else if ( ntyp == descr_close ) {
1432             // rien a faire ici; de plus il ne peut y en avoir qu'un
1433           } else if ( ntyp == descr_lineto ) {
1434             PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[k]);
1435             res->LineTo(nData->p);
1436             nLastP=nData->p;
1437           } else if ( ntyp == descr_arcto ) {
1438             PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[k]);
1439             res->ArcTo(nData->p,nData->rx,nData->ry,nData->angle,nData->large,nData->clockwise);
1440             nLastP=nData->p;
1441           } else if ( ntyp == descr_cubicto ) {
1442             PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[k]);
1443             res->CubicTo(nData->p,nData->start,nData->end);
1444             nLastP=nData->p;
1445           } else if ( ntyp == descr_bezierto ) {
1446             PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[k]);
1447             res->BezierTo(nData->p);
1448             nLastP=nData->p;
1449           } else if ( ntyp == descr_interm_bezier ) {
1450             PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[k]);
1451             res->IntermBezierTo(nData->p);
1452           } else {
1453           }
1454         }
1455         if ( doesClose == false ) res->LineTo(np);
1456         nLastP=np;
1457         for (int k=i+1;k<hasForced;k++) {
1458           int ntyp=descr_cmd[k]->getType();
1459           if ( ntyp == descr_moveto ) {
1460             // ne doit pas arriver
1461           } else if ( ntyp == descr_forced ) {
1462             res->MoveTo(nLastP);
1463           } else if ( ntyp == descr_close ) {
1464             // rien a faire ici; de plus il ne peut y en avoir qu'un
1465           } else if ( ntyp == descr_lineto ) {
1466             PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[k]);
1467             res->LineTo(nData->p);
1468             nLastP=nData->p;
1469           } else if ( ntyp == descr_arcto ) {
1470             PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[k]);
1471             res->ArcTo(nData->p,nData->rx,nData->ry,nData->angle,nData->large,nData->clockwise);
1472             nLastP=nData->p;
1473           } else if ( ntyp == descr_cubicto ) {
1474             PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[k]);
1475             res->CubicTo(nData->p,nData->start,nData->end);
1476             nLastP=nData->p;
1477           } else if ( ntyp == descr_bezierto ) {
1478             PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[k]);
1479             res->BezierTo(nData->p);
1480             nLastP=nData->p;
1481           } else if ( ntyp == descr_interm_bezier ) {
1482             PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[k]);
1483             res->IntermBezierTo(nData->p);
1484           } else {
1485           }
1486         }
1487         lastP=nMvtP;
1488         i=j;
1489       } else {
1490         // regular, just move on
1491         res->MoveTo(np);
1492         lastP=np;
1493       }
1494     } else if ( typ == descr_close ) {
1495       res->Close();
1496     } else if ( typ == descr_forced ) {
1497       res->MoveTo(lastP);
1498     } else if ( typ == descr_lineto ) {
1499       PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[i]);
1500       res->LineTo(nData->p);
1501       lastP=nData->p;
1502     } else if ( typ == descr_arcto ) {
1503       PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[i]);
1504       res->ArcTo(nData->p,nData->rx,nData->ry,nData->angle,nData->large,nData->clockwise);
1505       lastP=nData->p;
1506     } else if ( typ == descr_cubicto ) {
1507       PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[i]);
1508       res->CubicTo(nData->p,nData->start,nData->end);
1509       lastP=nData->p;
1510     } else if ( typ == descr_bezierto ) {
1511       PathDescrBezierTo *nData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[i]);
1512       res->BezierTo(nData->p);
1513       lastP=nData->p;
1514     } else if ( typ == descr_interm_bezier ) {
1515       PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[i]);
1516       res->IntermBezierTo(nData->p);
1517     } else {
1518     }
1519   }
1521   Copy(res);
1522   delete res;
1523   return;
1526 /*
1527   Local Variables:
1528   mode:c++
1529   c-file-style:"stroustrup"
1530   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1531   indent-tabs-mode:nil
1532   fill-column:99
1533   End:
1534 */
1535 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :