home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / animutil / kfast / src / animate.c next >
Encoding:
C/C++ Source or Header  |  1992-07-03  |  18.2 KB  |  802 lines

  1. #include <math.h>
  2. #include "skeleton.h"
  3.  
  4. /* animate primitives */
  5.  
  6. int strokes(line_ptr line)
  7. {
  8.     int n;
  9.  
  10.     n = 1;
  11.     while(line->next!=NULL)
  12.     {
  13.         n++;
  14.         line = line->next;
  15.     }
  16.  
  17.     return(n);
  18. }
  19.  
  20. void addsegs(line_ptr seg,int n,int req)
  21. {
  22.     int rs,rt,i,j,k=0,l;
  23.     int x1,y1,dx,dy;
  24.  
  25.     if(n/POINTS != req/POINTS)    
  26.         seg->pts=(struct pts *)realloc((void *)seg->pts,
  27.          sizeof(struct pts)*POINTS*(req/POINTS+1),
  28.      sizeof(struct pts)*POINTS*(n/POINTS+1));
  29.     seg->number = req+1;
  30.  
  31.     if(n==0)
  32.     {
  33.         x1 = seg->pts->p[0][0];
  34.         y1 = seg->pts->p[0][1];
  35.  
  36.     
  37.     for(i=1;i<=req;i++)
  38.     {
  39.         seg->pts->p[i][0]=x1;
  40.         seg->pts->p[i][1]=y1;
  41.     }
  42.     return;
  43.     }
  44.  
  45.     rt = req/n;
  46.     rs = req%n;
  47.  
  48.     for(i=n;i>=0;i--)
  49.     {
  50.     if(i>rs)
  51.         j = rs + rt*i;
  52.     else
  53.         j = (rt+1)*i;
  54.         
  55.     seg->pts->p[j][0] = seg->pts->p[i][0];
  56.     seg->pts->p[j][1] = seg->pts->p[i][1];
  57.     
  58.         
  59.     if(i!=n)
  60.     {
  61.             x1 = seg->pts->p[j][0];
  62.                y1 = seg->pts->p[j][1];
  63.                dx = seg->pts->p[k][0] - seg->pts->p[j][0];
  64.                dy = seg->pts->p[k][1] - seg->pts->p[j][1];
  65.  
  66.         for(l=1;l<k-j;l++)
  67.         {
  68.             seg->pts->p[j+l][0] = (dx*l)/(k-j)+x1;
  69.             seg->pts->p[j+l][1] = (dy*l)/(k-j)+y1;
  70.  
  71.         }
  72.     }
  73.     k = j;
  74.     }
  75. }
  76.  
  77. void breakstroke(line_ptr seg,int n)
  78. {
  79.     int step;
  80.     line_ptr newseg;
  81.  
  82.  
  83.     if(n<=1) return;
  84.  
  85.     if(seg->number-1<n)
  86.         addsegs(seg,seg->number-1,n);
  87.  
  88.     step = (seg->number-1)/n;
  89.  
  90.     for(;n>1;n--)
  91.     {
  92.         newseg = cutseg(seg,step);
  93.  
  94.     newseg->next = seg->next;
  95.     seg->next = newseg;
  96.  
  97.         seg = newseg;
  98.     }
  99. }
  100.  
  101. void addstrokes(line_ptr line,int n,int req)
  102. {
  103.     int rs,rt,i;
  104.     line_ptr nextline;
  105.  
  106.     rt = req/n;
  107.     rs = req%n;
  108.  
  109.     for(i=1;i<=rs;i++)
  110.     {
  111.     nextline = line->next;
  112.         breakstroke(line,rt+1);
  113.         line = nextline;
  114.     }
  115.     while(line!=NULL)
  116.     {
  117.     nextline = line->next;
  118.         breakstroke(line,rt);
  119.         line = nextline;
  120.     }
  121. }
  122.  
  123.  
  124. void preprocess(line_ptr l1,line_ptr l2)
  125. {
  126.     int n1,n2;
  127.  
  128.     if((l1==NULL)||(l2==NULL)) return;
  129.  
  130.  
  131.     n1 = strokes(l1);
  132.     n2 = strokes(l2);
  133.  
  134.     if(n1>n2) addstrokes(l2,n2,n1);
  135.     else if(n2>n1) addstrokes(l1,n1,n2);
  136.  
  137.     while(l1!=NULL)
  138.     {
  139.         n1 = l1->number-1;
  140.         n2 = l2->number-1;
  141.  
  142.         if(n1>n2) addsegs(l2,n2,n1);
  143.         else if(n2>n1) addsegs(l1,n1,n2);
  144.  
  145.         l1 = l1->next;
  146.         l2 = l2->next;
  147.     }
  148. }
  149.  
  150. int relative(int x ,int y ,int x1,int y1,int x2,int y2,
  151.              int x3,int y3,int x4,int y4,int *l,int *w)
  152. {
  153.     double L,W,dist2,tdist2;
  154.     int a,b,c,d,e,f,g,h;
  155.     int A,B,C;
  156.     int temp,cross1,cross2;
  157.  
  158.     a = x-x1; b = x2-x1; c = y-y1; d = y2-y1;
  159.     e = x-x3; f = x4-x3; g = y-y3; h = y4-y3;
  160.  
  161.     cross1 = a*d - c*b;    /* psuedo cross products */
  162.     cross2 = e*h - g*f;
  163.     
  164.     if((cross1>0 && cross2>0)||(cross1<0 && cross2<0))
  165.         return(FALSE);
  166.     
  167.     cross1 = (a-e)*c - (c-g)*a;    /* another cross product */
  168.     cross2 = (x4-x2)*(y-y2) - (y4-y2)*(x-x2);
  169.  
  170.     if((cross1>0 && cross2>0)||(cross1<0 && cross2<0))
  171.         return(FALSE);
  172.  
  173.     A = b*h - d*f;
  174.     B = c*f + d*e - a*h - b*g;    /* I won't soon forget this one */
  175.     C = a*g - c*e;
  176.  
  177.     if(A==0)
  178.     {
  179.     if(B!=0)
  180.         L = -(double)C/B;
  181.     else
  182.     {
  183.         return(FALSE);
  184.     }
  185.     }
  186.     else
  187.     {
  188.     temp = B*B - 4*A*C;
  189.     
  190.     if(temp<0)
  191.     {
  192.         return(FALSE);
  193.     }
  194.     
  195.     L = ((double)(-B) - sqrt((double)temp))/(2*A);
  196.         if(L>1.0 || L<0.0)
  197.         L = ((double)(-B) + sqrt((double)temp))/(2*A);
  198.        if(L>1.0 || L<0.0)
  199.     {
  200.         return(FALSE);
  201.     }
  202.     }
  203.  
  204.     tdist2 = (a-e-(b-f)*L)*(a-e-(b-f)*L) + (c-g-(d-h)*L)*(c-g-(d-h)*L);
  205.     if(tdist2==0.0)
  206.     {
  207.         return(FALSE);
  208.     }    
  209.     dist2 = (a-b*L)*(a-b*L) + (c-d*L)*(c-d*L);
  210.  
  211.     W = sqrt(dist2/tdist2);
  212.     if(W>1.0 || W<0.0)
  213.     {
  214.      return(FALSE);
  215.     }
  216.  
  217.     *l = (int)(L*256);
  218.     *w = (int)(W*256);
  219.  
  220.     return(TRUE);
  221. }
  222.  
  223. line_ptr makerelative(obj_ptr object)
  224. {
  225.     int i,j,k,p;
  226.     int l,w;
  227.     line_ptr seg,rel,head;
  228.  
  229.     seg = object->image;
  230.     rel = head = NULL;
  231.  
  232.     while(seg!=NULL)
  233.     {
  234.     p = 0;
  235.         for(i=0;i<seg->number;i++)
  236.         {
  237.             for(j=0;j<object->skeleton->number;j++)
  238.             {
  239.                 for(k=0;k<=1;k++)
  240.                 {
  241.             if((j*2+k+2<object->outline->number) &&
  242.              (j+1<object->skeleton->number))
  243.             {
  244.                         if(relative(seg->pts->p[i][0],seg->pts->p[i][1],
  245.                          object->skeleton->pts->p[j][0],
  246.                          object->skeleton->pts->p[j][1],
  247.                          object->skeleton->pts->p[j+1][0],
  248.                          object->skeleton->pts->p[j+1][1],
  249.                          object->outline->pts->p[j*2+k][0],
  250.                          object->outline->pts->p[j*2+k][1],
  251.                          object->outline->pts->p[j*2+k+2][0],
  252.                          object->outline->pts->p[j*2+k+2][1],
  253.                          &l,&w)==TRUE)
  254.                         {
  255.                              if(rel==NULL)
  256.                             {
  257.                     rel=(line_ptr)malloc(sizeof(struct line));
  258.                         rel->pts=(struct pts *)
  259.                      malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
  260.  
  261.                     head = rel;
  262.                     rel->next = NULL;
  263.                     rel->linec = seg->linec;
  264.                     rel->fillc = seg->fillc;
  265.                             }
  266.                             else if(p==0)
  267.                             {
  268.                     rel->next=(line_ptr)malloc(sizeof(struct line));
  269.                         rel = rel->next;
  270.                     rel->pts=(struct pts *)
  271.                      malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
  272.  
  273.                     rel->next = NULL;
  274.                                     rel->linec = seg->linec;
  275.                     rel->fillc = seg->fillc;
  276.                             }
  277.  
  278.                                rel->pts->p[p][0] = l+(j<<8);
  279.                 rel->pts->p[p][1] = ((k)?(-1):(1))*w;
  280.                 p++;
  281.  
  282.                 k = 1;
  283.                 j = object->skeleton->number;
  284.             }
  285.                     }
  286.                 }
  287.             }
  288.         }
  289.     if(p!=0)
  290.     {
  291.             rel->number=p;
  292.         if((p-1)/POINTS!=(seg->number-1)/POINTS)
  293.             rel->pts=(struct pts *)
  294.              realloc((void *)rel->pts,
  295.                   sizeof(struct pts)*POINTS*((p-1)/POINTS+1),
  296.              sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
  297.         if(p==1)
  298.         {
  299.                        rel->pts->p[1][0] = rel->pts->p[0][0];
  300.             rel->pts->p[1][1] = rel->pts->p[0][1];
  301.         }
  302.     }
  303.         seg = seg->next;
  304.     }
  305.     return(head);
  306. }
  307.  
  308. void makeimage(obj_ptr object,line_ptr relative)
  309. {
  310.     int i,j,k,p;
  311.     int l,w,x1,y1,x2,y2;
  312.     line_ptr seg,derel;
  313.  
  314.     seg = relative;
  315.     derel = NULL;
  316.     deleteline(object->image);
  317.  
  318.     while(seg!=NULL)
  319.     {
  320.     p = 0;
  321.         for(i=0;i<seg->number;i++)
  322.         {
  323.             l = seg->pts->p[i][0];
  324.             w = seg->pts->p[i][1];
  325.  
  326.             j = l>>8;
  327.             k = ((w<0)?(1):(0));
  328.  
  329.             l = l - (j<<8);
  330.             w = abs(w);
  331.  
  332.             if((j+1<object->skeleton->number) &&
  333.          (k+j*2+2<object->outline->number))
  334.         {
  335.         x1 = ((object->skeleton->pts->p[j+1][0] -
  336.                  object->skeleton->pts->p[j][0]) * l)/256 +
  337.                  object->skeleton->pts->p[j][0];
  338.                 y1 = ((object->skeleton->pts->p[j+1][1] -
  339.                  object->skeleton->pts->p[j][1]) * l)/256 +
  340.                  object->skeleton->pts->p[j][1];
  341.                 x2 = ((object->outline->pts->p[j*2+k+2][0] -
  342.                  object->outline->pts->p[j*2+k][0]) * l)/256 +
  343.                  object->outline->pts->p[j*2+k][0];
  344.                 y2 = ((object->outline->pts->p[j*2+k+2][1] -
  345.                   object->outline->pts->p[j*2+k][1]) * l)/256 +
  346.                   object->outline->pts->p[j*2+k][1];
  347.  
  348.                 x1 = ((x2-x1) * w)/256 + x1;
  349.                 y1 = ((y2-y1) * w)/256 + y1;
  350.  
  351.             if(derel==NULL)
  352.             {
  353.             derel=(line_ptr)malloc(sizeof(struct line));
  354.                 derel->pts=(struct pts *)
  355.              malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
  356.  
  357.             derel->next = NULL;
  358.  
  359.             derel->linec = seg->linec;
  360.             derel->fillc = seg->fillc;
  361.             object->image = derel;
  362.                 }
  363.                 else if(p==0)
  364.                 {
  365.             derel->next=(line_ptr)malloc(sizeof(struct line));
  366.                 derel = derel->next;
  367.             derel->pts=(struct pts *)
  368.              malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
  369.  
  370.             derel->next = NULL;
  371.  
  372.             derel->linec = seg->linec;
  373.             derel->linec = seg->linec;
  374.             derel->fillc = seg->fillc;
  375.                 }
  376.  
  377.                derel->pts->p[p][0] = x1;
  378.         derel->pts->p[p][1] = y1;
  379.  
  380.         p++;
  381.         }
  382.         }
  383.     if(p!=0)
  384.     {
  385.             derel->number=p;
  386.         if((p-1)/POINTS!=(seg->number-1)/POINTS)
  387.             derel->pts=(struct pts *)
  388.              realloc((void *)derel->pts,
  389.                   sizeof(struct pts)*POINTS*((p-1)/POINTS+1),
  390.              sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
  391.         setbox(derel);
  392.         if(p==1)
  393.         {
  394.                        derel->pts->p[1][0] = derel->pts->p[0][0];
  395.             derel->pts->p[1][1] = derel->pts->p[0][1];
  396.         }
  397.     }
  398.         seg = seg->next;
  399.     }
  400. }
  401.  
  402. void inbetween(int xi,int yi,int xo,int yo,int frame,int frames,
  403.                int law,int *x,int *y)
  404. {
  405.     if((law & XACCEL) && (law & XDECEL))
  406.         *x = (int)((xo-xi)*(1.0-cos((double)PI*frame/frames))/2)+xi;
  407.     else if(law & XACCEL)
  408.         *x = (int)((xo-xi)*(1.0-cos((double)PI*frame/frames/2)))+xi;
  409.     else if(law & XDECEL)
  410.         *x = (int)((xo-xi)*sin((double)PI*frame/frames/2))+xi;
  411.     else
  412.         *x = (int)((xo-xi)*(double)frame/frames)+xi;
  413.  
  414.     if((law & YACCEL) && (law & YDECEL))
  415.         *y = (int)((yo-yi)*(1.0-cos((double)PI*frame/frames))/2)+yi;
  416.     else if(law & YACCEL)
  417.         *y = (int)((yo-yi)*(1.0-cos((double)PI*frame/frames/2)))+yi;
  418.     else if(law & YDECEL)
  419.         *y = (int)((yo-yi)*sin((double)PI*frame/frames/2))+yi;
  420.     else
  421.         *y = (int)((yo-yi)*(double)frame/frames)+yi;
  422. }
  423.  
  424. line_ptr imagebetween(line_ptr linein,line_ptr lineout,
  425.                       int frame,int frames,int law)
  426. {
  427.     line_ptr start, line;
  428.     int i;
  429.     int x,y,n;
  430.  
  431.     start = NULL;
  432.     
  433.     while(linein!=NULL && lineout!=NULL)
  434.     {
  435.     if(linein->number>lineout->number)
  436.         n = lineout->number;
  437.     else
  438.         n = linein->number;
  439.     
  440.         for(i=0;i<n;i++)
  441.         {
  442.             inbetween(linein->pts->p[i][0],linein->pts->p[i][1],
  443.              lineout->pts->p[i][0],lineout->pts->p[i][1],
  444.              frame,frames,law,&x,&y);
  445.             if(start==NULL)
  446.             {
  447.                 line = (line_ptr)malloc(sizeof(struct line));
  448.         line->pts = malloc(sizeof(struct pts)*POINTS*((n-1)/POINTS+1));
  449.         
  450.         line->linec = linein->linec;
  451.         line->fillc = linein->fillc;
  452.         line->next = NULL;
  453.         
  454.         start = line;
  455.             }
  456.             else if(i==0)
  457.             {
  458.                 line->next = (line_ptr)malloc(sizeof(struct line));
  459.         line = line->next;
  460.         line->pts = malloc(sizeof(struct pts)*POINTS*((n-1)/POINTS+1));
  461.         
  462.                 line->linec = linein->linec;
  463.         line->fillc = linein->fillc;
  464.         line->next = NULL;
  465.             }
  466.         
  467.             line->pts->p[i][0] = x;
  468.         line->pts->p[i][1] = y;
  469.         }
  470.     
  471.     line->number = n;
  472.     setbox(line);
  473.  
  474.     if(n==1)
  475.     {
  476.         line->pts->p[1][0] = line->pts->p[0][0];
  477.         line->pts->p[1][1] = line->pts->p[0][1];
  478.     }
  479.  
  480.         linein = linein->next;
  481.         lineout = lineout->next;
  482.     }
  483.     return(start);
  484. }
  485.  
  486. obj_ptr findtype(obj_ptr object,int flags,int *n)
  487. {
  488.     *n = 0;
  489.     if(flags!=0)
  490.     {
  491.         while((object!=NULL)&&((object->entry&flags)!=flags))
  492.         {
  493.             object=object->next;
  494.             (*n)++;
  495.         }
  496.     }
  497.     else
  498.     {
  499.         while((object!=NULL)&&(object->entry==0))
  500.         {
  501.             object=object->next;
  502.             (*n)++;
  503.         }
  504.     }
  505.     return(object);
  506. }
  507.  
  508. obj_ptr findtypeback(obj_ptr object,int flags,int *n)
  509. {
  510.     *n = 0;
  511.     if(flags!=0)
  512.     {
  513.         while((object!=NULL)&&((object->entry&flags)!=flags))
  514.         {
  515.             object=object->prev;
  516.             (*n)++;
  517.         }
  518.     }
  519.     else
  520.     {
  521.         while((object!=NULL)&&(object->entry==0))
  522.         {
  523.             object=object->prev;
  524.             (*n)++;
  525.         }
  526.     }
  527.  
  528.     return(object);
  529. }
  530.  
  531. /*
  532. void makeoutline(obj_ptr with,obj_ptr without)
  533. {
  534.     double length,a1i,a1f,a2i,a2f,aoi,aof;
  535.     int x10,y10,x11,y11,x12,y12,x1o,y1o,x20,y20,x21,y21,x22,y22,x2o,y2o;
  536.     int i;
  537.  
  538.     deleteline(without->outline);
  539.     without->outline = NULL;
  540.  
  541.     for(i=0;i<with->outline->number;i++)
  542.     {
  543.         x10 = with->skeleton->pts->p[i/2][0];
  544.         y10 = with->skeleton->pts->p[i/2][1];
  545.         x1o = with->outline->pts->p[i][0];
  546.         y1o = with->outline->pts->p[i][1];
  547.         if(i>1)
  548.         {
  549.             x11 = with->skeleton->pts->p[i/2-1][0];
  550.             y11 = with->skeleton->pts->p[i/2-1][1];
  551.         }
  552.         if(i<with->outline->number-2)
  553.         {
  554.             x12 = with->skeleton->pts->p[i/2+1][0];
  555.             y12 = with->skeleton->pts->p[i/2+1][1];
  556.         }
  557.  
  558.         x20 = without->skeleton->pts->p[i/2][0];
  559.         y20 = without->skeleton->pts->p[i/2][1];
  560.         if(i!=0)
  561.         {
  562.             x21 = without->skeleton->pts->p[i/2-1][0];
  563.             y21 = without->skeleton->pts->p[i/2-1][1];
  564.         }
  565.         if(i!=with->outline->number-1)
  566.         {
  567.             x22 = without->skeleton->pts->p[i/2+1][0];
  568.             y22 = without->skeleton->pts->p[i/2+1][1];
  569.         }
  570.  
  571.         length = sqrt((double)(x10-x11)*(x10-x11) +
  572.          (double)(y10-y11)*(y10-y11));
  573.  
  574.         a1i = atan2((double)(x11-x10),(double)(y11-y10));
  575.         a2i = atan2((double)(x12-x10),(double)(y12-y10));
  576.         aoi = atan2((double)(x1o-x10),(double)(y1o-y10));
  577.         a1f = atan2((double)(x21-x20),(double)(y21-y20));
  578.         a2f = atan2((double)(x22-x20),(double)(y22-y20));
  579.  
  580.         if(i==0)
  581.             aof = aoi + (a2f-a2i);
  582.         else if(i==with->outline->number-1)
  583.             aof = aoi + (a1f-a1i);
  584.         else
  585.             aof = aoi + ((a1f-a1i) + (a2f-a2i))/2;
  586.  
  587.         x2o = x21 + (int)(length*cos(aof));
  588.         y2o = y21 + (int)(length*sin(aof));
  589.  
  590.         without->outline = addpoint(without->outline,x2o,y2o);
  591.     }
  592. }
  593.  
  594.  
  595. void derelative(obj_ptr firstimage,int n)
  596. {
  597.     obj_ptr nextskel,image;
  598.     int f,acc,i;
  599.  
  600.     nextskel = findtype(firstimage->next,SKELETON,&f);
  601.     f = f + 1;
  602.     acc = f;
  603.     while(nextskel!=NULL && acc < n)
  604.     {
  605.         if(nextskel->entry & XOUTLINE != XOUTLINE)
  606.             makeoutline(firstimage,nextskel);
  607.         image = firstimage->next;
  608.         for(i=1;i<=f;i++)
  609.         {
  610.             image->skeleton = imagebetween(firstimage->skeleton,
  611.              nextskel->skeleton,i,f,firstimage->ilaw);
  612.             image->outline = imagebetween(firstimage->outline,
  613.              nextskel->outline,i,f,firstimage->ilaw);
  614.             makeimage(image);
  615.             image = image->next;
  616.         }
  617.         firstimage = nextskel;
  618.         nextskel = findtype(firstimage->next,SKELETON,&f);
  619.         acc = acc + f;
  620.     }
  621. }
  622.  */
  623.  
  624. void animate(obj_ptr object)
  625. {
  626.     obj_ptr firstimage, nextimage, firstskel, nextskel, image;
  627.     line_ptr firstrel,nextrel, rel, firstcopy, nextcopy;
  628.     int f,n,i,j;
  629.     int skelable;
  630.  
  631.     if(object==NULL) return;
  632.     firstrel = nextrel = NULL;
  633.  
  634.     firstimage = findtype(object,IMAGE,&f);
  635.     
  636.     if(firstimage==NULL) return;
  637.     
  638.     if((firstimage->entry&(SKELETON|XOUTLINE))==(SKELETON|XOUTLINE))
  639.     {
  640.         skelable=TRUE;
  641.     firstrel = makerelative(firstimage);
  642.     }
  643.     else
  644.     {
  645.          skelable = FALSE;
  646.     }
  647.     
  648.     nextimage = findtype(firstimage->next,IMAGE,&n);
  649.  
  650.     while(nextimage!=NULL)
  651.     {
  652.         if(skelable==TRUE)
  653.     {
  654.         if((nextimage->entry&(SKELETON|XOUTLINE))==(SKELETON|XOUTLINE))
  655.         {
  656.             nextrel = makerelative(nextimage);
  657.             nextcopy = copyline(nextrel);
  658.             firstcopy = copyline(firstrel);
  659.             preprocess(firstcopy,nextcopy);
  660.         }
  661.         else
  662.         {
  663.             skelable = FALSE;
  664.         }
  665.         
  666.         j = 0;
  667.         firstskel = firstimage;
  668.         nextskel = findtype(firstskel->next,SKELETON|XOUTLINE,&f);
  669.         while((j+f<=n) && (nextskel!=NULL))
  670.         {
  671.             if((skelable==TRUE) && (nextskel!=nextimage))
  672.             {
  673.                         rel = imagebetween(firstcopy,
  674.                              nextcopy,j+f+1,n+1,firstskel->ilaw);
  675.                 makeimage(nextskel,rel);    
  676.                 deleteline(rel);
  677.             }
  678.             else if(nextskel!=nextimage)
  679.             {
  680.                 makeimage(nextskel,firstrel);
  681.             }
  682.  
  683.             image = firstskel->next;
  684.             for(i=1;i<=f;i++)
  685.             {
  686.                 deleteline(image->skeleton);
  687.                            image->skeleton = imagebetween(firstskel->skeleton,
  688.                             nextskel->skeleton,i,f+1,firstskel->ilaw);
  689.                 deleteline(image->outline);
  690.                            image->outline = imagebetween(firstskel->outline,
  691.                             nextskel->outline,i,f+1,firstskel->ilaw);
  692.  
  693.                 if(skelable==TRUE)
  694.                 {
  695.                             rel = imagebetween(firstcopy,
  696.                               nextcopy,j+i,n+1,firstskel->ilaw);
  697.                     makeimage(image,rel);    
  698.                     deleteline(rel);
  699.                 }
  700.                 else
  701.                 {
  702.                     makeimage(image,firstrel);
  703.                 }
  704.                            image = image->next;
  705.             }
  706.             
  707.             j = j+f+1;
  708.             firstskel = nextskel;
  709.  
  710.             nextskel = findtype(firstskel->next,SKELETON|XOUTLINE,&f);
  711.         }
  712.  
  713.         if(skelable==TRUE)
  714.         {
  715.             deleteline(firstcopy);
  716.             deleteline(nextcopy);
  717.         }
  718.         else
  719.             nextrel=NULL;
  720.             
  721.         deleteline(firstrel);
  722.         firstrel = nextrel;
  723.         
  724.         if(j<n)
  725.         {
  726.             n = n - j;
  727.             firstcopy = copyline(firstskel->image);
  728.             nextcopy = copyline(nextimage->image);
  729.             preprocess(firstcopy,nextcopy);
  730.                     image = firstskel->next;
  731.                     for(i=1;i<=n;i++)
  732.                     {
  733.                 deleteline(image->image);
  734.                         image->image = imagebetween(firstcopy,
  735.                          nextcopy,i,n+1,firstskel->ilaw);
  736.                         image = image->next;
  737.                     }
  738.             deleteline(firstcopy);
  739.             deleteline(nextcopy);
  740.         }
  741.     }
  742.     else
  743.     {
  744.         /* inbetweening of images */
  745.         firstcopy = copyline(firstimage->image);
  746.         nextcopy = copyline(nextimage->image);
  747.         
  748.         preprocess(firstcopy,nextcopy);
  749.                 image = firstimage->next;
  750.                 for(i=1;i<=n;i++)
  751.                 {
  752.             deleteline(image->image);
  753.                     image->image = imagebetween(firstcopy,
  754.                      nextcopy,i,n+1,firstimage->ilaw);
  755.                     image = image->next;
  756.                 }
  757.         deleteline(firstcopy);
  758.         deleteline(nextcopy);
  759.         
  760.         if((nextimage->entry&(SKELETON|XOUTLINE))==(SKELETON|XOUTLINE))
  761.         {
  762.             skelable = TRUE;
  763.             deleteline(firstrel);
  764.             firstrel = makerelative(nextimage);
  765.         }
  766.         }
  767.  
  768.         firstimage = nextimage;
  769.     
  770.         nextimage = findtype(firstimage->next,IMAGE,&n);
  771.      }
  772.  
  773.      if((firstimage->next!=NULL) && (skelable==TRUE))
  774.      {
  775.     firstskel = firstimage;
  776.     nextskel = findtype(firstimage->next,SKELETON|XOUTLINE,&f);
  777.     while(nextskel!=NULL)
  778.     {
  779.  
  780.         makeimage(nextskel,firstrel);
  781.         
  782.         image = firstskel->next;
  783.         for(i=1;i<=f;i++)
  784.         {
  785.             deleteline(image->skeleton);
  786.                        image->skeleton = imagebetween(firstskel->skeleton,
  787.                         nextskel->skeleton,i,f+1,firstskel->ilaw);
  788.             deleteline(image->outline);
  789.                        image->outline = imagebetween(firstskel->outline,
  790.                         nextskel->outline,i,f+1,firstskel->ilaw);
  791.             makeimage(image,firstrel);
  792.                        image = image->next;
  793.         }
  794.  
  795.         firstskel = nextskel;
  796.         nextskel = findtype(firstskel->next,SKELETON|XOUTLINE,&f);
  797.     }
  798.      }
  799.      deleteline(firstrel);
  800. }
  801.  
  802.