sketchucation logo sketchucation
    • Login
    πŸ€‘ SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

    [REQ] Curvespace for bezierspline.rb

    Scheduled Pinned Locked Moved Plugins
    7 Posts 3 Posters 1.2k Views 3 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • PixeroP Offline
      Pixero
      last edited by

      While struggling with animation paths i discovered a way to use the Polyline Divider tool combined with the flightpath script to bake every frame of an animation.
      The Polyline Divider however only draws straight lines that make a bit jumpy animations at bends. After a little Googling I found some code for something called Curvespace. Could this be implemented as a addon to beziercurve.rb?

      If this could be done and perhaps add the possibility to use different interpolations like smoothstep for the distance between point one might just be able to do some smooooooth animation. πŸ€“

      Here's the code:

      function q = curvspace(p,N)
      
      % CURVSPACE Evenly spaced points along an existing curve in 2D or 3D.
      %   CURVSPACE(P,N) generates N points that interpolates a curve
      %   (represented by a set of points) with an equal spacing. Each
      %   row of P defines a point, which means that P should be a n x 2
      %   (2D) or a n x 3 (3D) matrix.
      %
      %   (Example)
      %   x = -2*pi;0.5;2*pi;
      %   y = 10*sin(x);
      %   z = linspace(0,10,length(x));
      %   N = 50;
      %   p = [x',y',z'];
      %   q = curvspace(p,N);
      %   figure;
      %   plot3(p(;,1),p(;,2),p(;,3),'*b',q(;,1),q(;,2),q(;,3),'.r');
      %   axis equal;
      %   legend('Original Points','Interpolated Points');
      %
      %   See also LINSPACE.
      %
      
      %   22 Mar 2005, Yo Fukushima
      
      
      %% initial settings %%
      currentpt = p(1,;); % current point
      indfirst = 2; % index of the most closest point in p from curpt
      len = size(p,1); % length of p
      q = currentpt; % output point
      k = 0;
      
      %% distance between points in p %%
      for k0 = 1;len-1
         dist_bet_pts(k0) = distance(p(k0,;),p(k0+1,;));
      end
      totaldist = sum(dist_bet_pts);
      
      %% interval %%
      intv = totaldist./(N-1);
      
      %% iteration %%
      for k = 1;N-1
         
         newpt = []; distsum = 0;
         ptnow = currentpt;
         kk = 0;
         pttarget = p(indfirst,;);
         remainder = intv; % remainder of distance that should be accumulated
         while isempty(newpt)
            % calculate the distance from active point to the most
            % closest point in p
            disttmp = distance(ptnow,pttarget);
            distsum = distsum + disttmp;
            % if distance is enough, generate newpt. else, accumulate
            % distance
            if distsum >= intv
               newpt = interpintv(ptnow,pttarget,remainder);
            else
               remainder = remainder - disttmp;
               ptnow = pttarget;
               kk = kk + 1;
               if indfirst+kk > len
                  newpt = p(len,;);
               else
                  pttarget = p(indfirst+kk,;);
               end
            end
         end
         
         % add to the output points
         q = [q; newpt];
         
         % update currentpt and indfirst
         currentpt = newpt;
         indfirst = indfirst + kk;
         
      end
      
      
      
      %%%%%%%%%%%%%%%%%%%%%%%%%
      %%    SUBFUNCTIONS     %%
      %%%%%%%%%%%%%%%%%%%%%%%%%
      
      function l = distance(x,y)
      
      % DISTANCE Calculate the distance.
      %   DISTANCE(X,Y) calculates the distance between two
      %   points X and Y. X should be a 1 x 2 (2D) or a 1 x 3 (3D)
      %   vector. Y should be n x 2 matrix (for 2D), or n x 3 matrix
      %   (for 3D), where n is the number of points. When n > 1,
      %   distance between X and all the points in Y are returned.
      %
      %   (Example)
      %   x = [1 1 1];
      %   y = [1+sqrt(3) 2 1];
      %   l = distance(x,y)
      %
      
      % 11 Mar 2005, Yo Fukushima
      
      %% calculate distance %%
      if size(x,2) == 2
         l = sqrt((x(1)-y(;,1)).^2+(x(2)-y(;,2)).^2);
      elseif size(x,2) == 3
         l = sqrt((x(1)-y(;,1)).^2+(x(2)-y(;,2)).^2+(x(3)-y(;,3)).^2);
      else
         error('Number of dimensions should be 2 or 3.');
      end
      
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      
      function newpt = interpintv(pt1,pt2,intv)
      
      % Generate a point between pt1 and pt2 in such a way that
      % the distance between pt1 and new point is intv.
      % pt1 and pt2 should be 1x3 or 1x2 vector.
      
      dirvec = pt2 - pt1;
      dirvec = dirvec./norm(dirvec);
      l = dirvec(1); m = dirvec(2);
      newpt = [intv*l+pt1(1),intv*m+pt1(2)];
      if length(pt1) == 3
         n = dirvec(3);
         newpt = [newpt,intv*n+pt1(3)];
      end
      
      
      1 Reply Last reply Reply Quote 0
      • Chris FullmerC Offline
        Chris Fullmer
        last edited by

        Who wrote beziercurve.rb? IS that the one that @Last released? Or is it by Fredo or Didier or something?

        Since most of the bezier curve scripts keep splines that are editable after they are created, I am guessing that the beziercurve script is writing it definition parameters to an Attribute Dictionary. You might check the attributes of the bezier and see if it doesn't have some [x,y,z] infos associated with it. A simple bezier should have 4 sets of x,y,z info with it. If the curve does have it, then you can use it to reproduce the bezier with as many segments as you would like.

        But that is only if the bezier has stored its start point, endpoint, start_handle, and end_handle (I've been calling them handles because of Illustrator, but I don't if they have a real name).

        Thats just a thought, maybe it doesn't work like that.

        Chris

        Lately you've been tan, suspicious for the winter.
        All my Plugins I've written

        1 Reply Last reply Reply Quote 0
        • PixeroP Offline
          Pixero
          last edited by

          I mean Fredos BezierSpline tools that is made for extending with other curves.

          1 Reply Last reply Reply Quote 0
          • fredo6F Offline
            fredo6
            last edited by

            @pixero said:

            While struggling with animation paths i discovered a way to use the Polyline Divider tool combined with the flightpath script to bake every frame of an animation.
            The Polyline Divider however only draws straight lines that make a bit jumpy animations at bends. After a little Googling I found some code for something called Curvespace. Could this be implemented as a addon to beziercurve.rb?

            If this could be done and perhaps add the possibility to use different interpolations like smoothstep for the distance between point one might just be able to do some smooooooth animation. πŸ€“

            Pixero,

            It would be easy to integrate, but I am afraid that this code does not do anything different from the Divider.
            What I would suggest is that you design your path with a F Spline (or a Polyline converetd to a F-Spline), and then convert it via Polyline Divider, so that all segments have the same length. If you take a small enough length dimension, it will preserve the smooth shape of the curve.

            Attached is a file showing the 3 steps:
            Polyline - FSpline - Divider.jpg

            Indeed, this could be automated in one type of curve (say Divider-F-Spline) if you really need this frequently.

            Fredo

            PS: I remember there is also a script called BezierFlightPath or so that creates Bezier curves with equal segments.


            Polyline - FSpline - Divider.skp

            1 Reply Last reply Reply Quote 0
            • PixeroP Offline
              Pixero
              last edited by

              Wow, didnt know it was possible with the current tools.

              Another question.
              Would it be possible to have the choice of other than linear distance distribution of the points?
              And set a min distance and a max distance.
              That would make it possible to smooth the animation by accelerating or decelerating.

              I'm getting exited here...

              Like this:

              
              ### INTERPOLATIONS ###
              t is the current time, between 0 and duration inclusive. 
              b is the initial value of the animation property. 
              c is the total change in the animation property. 
              d is the duration of the motion. 
              
              # Linear interpolation (even spacing)
              def lerp(t, b, c)  
              	return ((b.to_f) * (1.0 - t.to_f) + c.to_f * t.to_f)
              end
              
              # EaseIn equation function for a quadratic (t^2) easing in; accelerating from zero velocity.
              def easeInQuad(t, b, c, d)
              	return c*(t/=d)*t + b;
              end#def
              
              # EaseOut equation function for a quadratic (t^2) easing out; decelerating to zero velocity.
              def easeOutQuad(t, b, c, d)
              	return -c *(t/=d)*(t-2) + b;
              end#def
              
              # Smoothstep interpolation
              def smooth(t, b, c) 
              	r=(t.to_f-b.to_f)/(c.to_f-b.to_f)
              	return r*r*(3.0-2.0*r)
              end
              
              1 Reply Last reply Reply Quote 0
              • fredo6F Offline
                fredo6
                last edited by

                @pixero said:

                Another question.
                Would it be possible to have the choice of other than linear distance distribution of the points?
                And set a min distance and a max distance.
                That would make it possible to smooth the animation by accelerating or decelerating.

                Evrything is possible. The question is to specify it.

                I can easily make the Divider with an increasing or decreasing step following any mathematical equation. Alternatively, this could be based on angles so that it speeds up in the straight sections and slows down in the curves.

                Fredo

                1 Reply Last reply Reply Quote 0
                • PixeroP Offline
                  Pixero
                  last edited by

                  The thing is that I have found a way to control animation in SU and if I could specify a min length, a max length and one of the interpolations in my post above (when linear only one length of cause)when converting to polyline divider everything would work. Of cause a curve based alternative could also be handy. This would mean a huge step forwards for animation in SU.
                  I'll try to make a tutorial if/when I have this last piece of the puzzle.

                  Here's a link to some more interpolations:
                  http://library.sfug.ch/trac/browser/trunk/branches/1.x/doc/as3/benchmarks/tweener/caurina/transitions/Equations.as?rev=219

                  1 Reply Last reply Reply Quote 0
                  • 1 / 1
                  • First post
                    Last post
                  Buy SketchPlus
                  Buy SUbD
                  Buy WrapR
                  Buy eBook
                  Buy Modelur
                  Buy Vertex Tools
                  Buy SketchCuisine
                  Buy FormFonts

                  Advertisement