ArtRage 5 Product PageArtRage Lite Product PageArtRage for iOS Product PageArtRage for Android Product PageArtRage  Android Oil Painter Free Product PageArtRage  Free Demos Page

Results 1 to 10 of 10

Thread: Spirograph

  1. #1
    Join Date
    Feb 2010
    Location
    Nevada
    Posts
    139

    Spirograph

    My fellow ArtRagers, what key feature were you crushed to realize was left out of version 3.5?

    Is it vectors?

    Perspective options?

    A "Bob Ross" slider for the Oil Brush?

    Wrong!

    It's a spirograph generator! But now you can fill the void. Simply copy and paste the below code into a UTF-16 text file per Andy's instructions. (edit: or, click on the file and save to your Scripts directory)

    The generator works on the current painting with your selected drawing tool (try it with eraser on a colored background). It should work with both 3.5 and 3.5 Pro.

    If you run into any problems, please let me know!

    edit on 8/3/11: made minor change to multicolor code, hopefully without breaking anything
    Code:
    //===========================================================================
    //===========================================================================
    //                            ArtRage Script File.
    //===========================================================================
    //===========================================================================
    
    
    //===========================================================================
    // Version Block - Script version and ArtRage version:
    //===========================================================================
    
    <Version>
        ArtRage Version: ArtRage 3 Studio Pro
        ArtRage Build: 3.5.1
        Professional Edition: No
        Script Version: 1
    </Version>
    
    
    //===========================================================================
    // Header block - Info about the painting/person who generated this script:
    //===========================================================================
    
    <Header>
        // === Project data
        Painting Name: "untitled"
        Painting Width: 1280
        Painting Height: 1024
        Painting DPI: 72
        // === Author data
        Author Name: "Ti-Chen Feng"
        Script Name: "Epicycloid"
        Comment: "a 'spirograph' generator"
        Script Type: ""
        Script Feature Flags: 0
    </Header>
    
    
    //===========================================================================
    // Script data follows:
    //===========================================================================
    
    //function: changes the foreground color (this method of color variation does not work for some tools)
    void SetColor( real rAmount )  {
      real rHue = ColourH()
    
      rHue+=rAmount
      if (rHue>1) rHue--
      SetColourHLS( rHue, ColourL(), ColourS() )
    
      return
    }
    
    
    //function: draws the epicycloid
    void DrawEpicycloid(int nRes, real R, real r, real d, real rCenterX, real rCenterY, real rReps, flag fColorChange)  {
    
    //set up initial values (at theta = 0 rad)
    flag fContinue = YES
    int i = 0
    int nTool = CurrentToolID()            //Done in main, but I couldn't take the idea of passing yet another parameter
    int nColType = 0                    //0=none, 1=normal, 2=paint, 3=ink
    real rColAmount = 0.004                //default
    real x = rCenterX + R + r + d
    real y = rCenterY
    real delta = 2*3.14159265/(nRes+1)
    real theta = 0
    real rPressure = 0.235
    
    //fudging to mimic the additional pressure exerted by user
    rPressure += CurrentToolSetting(0x0B2D05E34)
    if (rPressure>1) rPressure=1
    
    //Depending on drawing tool, set up multicolor type
    if( fColorChange )  {
      //default: pencil (precise off), crayon, chalk, tube, glitter (mc off), sticker spray
      nColType = 1
      //oil, felt pen, knife (flat or edge), roller, wc
      if( nTool==4900 || nTool==4904 || (nTool==4905 && CurrentToolSetting(0x0B2D05E60)<2) || nTool==4915 || nTool==4916 )  {
        nColType = 2
        rColAmount = 0.4
      }
      //pencil (precise), airbrush, ink, gloop
      if( nTool==4901 || nTool==4914 || nTool==4917 || nTool==4918 )  {
        nColType = 3
        rColAmount = 0.09
      }
      //knife (other), eraser, glitter (multicolor)
      if( (nTool==4905 && CurrentToolSetting(0x0B2D05E60)>1) || nTool==4906 || (nTool==4913 && CurrentToolSetting(0x0B2D05E3E)>0) )  {
        nColType = 0
      }
    }
    //MessageBox("color type = %%nColType")
    
    //The while loop lets user continue if the results are interesting
    //The stroke event is broken up to allow Undo
    while (rReps>0)  {
      <StrokeEvent>
        <StrokeHeader>
          <EventPt> Wait: 0.000s Loc: (x, y) Pr: rPressure Ti: 1 Ro: 0 Rv: NO Iv: NO </EventPt>
          <Recorded> No </Recorded>
        </StrokeHeader>
    
      // MouseDown point
      Loc: (x, y) Pr: rPressure Ti: 1 Ro: 0 Rv: NO Iv: NO
    
      //Draw the requested number of iterations
      for (i=0; i<=rReps*nRes; i++)  {
        Loc: (x, y) Pr: rPressure Ti: 1 Ro: 0 Rv: NO Iv: NO
        x = rCenterX + (R+r)*cos(theta) + d*cos(((R+r)/r)*theta)
        y = rCenterY + (R+r)*sin(theta) + d*sin(((R+r)/r)*theta)
        theta+=delta
        if( nColType==1 )  SetColor(rColAmount)
        }
    
      // MouseUp point.  
      Loc: (x, y) Pr: rPressure Ti: 1 Ro: 0 Rv: NO Iv: NO
      </StrokeEvent>
    
      //Continue or stop?
      InputBox("Stationary circle: %%R\nMoving circle: %%r\nDrawing arm: %%d\nResolution: %%nRes\nNumber of cycles to draw (0-100)$$rReps")
      if( rReps>100 )  rReps=100
      if( nColType>1 )  SetColor(rColAmount)
    }
    return
    }
    
    
    
    <Events>
    
    flag fGradient = NO                    //whether or not to change hue during stroke event
    flag fNewLayer = YES                //put epicycloid on a new layer or use the current layer?
    int nTool = CurrentToolID()            //user's selected tool
    int nResolution = 180                //how often to calculate (x,y) per cycle
    real rCycle = 9.01                    //how many cycles to draw per iteration (one cycle being 360 degrees around stator)
    real rMaxRadX = PaintingWidth()/2
    real rMaxRadY = PaintingHeight()/2
    real rMaxRad = rMaxRadX
    real rStaRad = 100                    //radius of stator
    real rRotRad = -45                    //radius of rotor; rotor is outside of stator if positive, inside if negative
    real rArmLen = -55                    //length of a drawing arm fixed at center of rotor; starts pointing out (pos) or in (neg)
    
    //Check to make sure selected tool is not: sampler, xform, text, fill, or select
    if( nTool==4909 || nTool==4910 || nTool==4919 || nTool==4921 || nTool==4922 )  {
      MessageBox("Please select an appropriate tool!")
      exit
    }
    
    //Maxiumum allowed radius is half the height or width (whichever is greater) of the canvas
    if (rMaxRadY>rMaxRadX) rMaxRad=rMaxRadY
    
    InputBox("Radius of stationary circle$$rStaRad\nRadius of moving circle$$rRotRad\nDrawing arm length$$rArmLen\nResolution (2-360)$$nResolution\nNumber of cycles (1-100)$$rCycle\nMulticolor?$$fGradient\nDraw on new layer?$$fNewLayer")
    //Verify input values:
    //    Radius of stator must be positive. Clamp maximum radius so the epicycloid is visible
    if (rStaRad<0) rStaRad=-rStaRad
    if (rStaRad>rMaxRad) rStaRad=rMaxRad
    //    Clamp maximum radius of rotor. For hypotrochoid, clamp radius to rStaRad. 0 is disallowed.
    if (rRotRad>rMaxRad) rRotRad=rMaxRad
    if (rRotRad<-rStaRad) rRotRad=-rStaRad
    if (rRotRad==0) rRotRad=rStaRad/100
    //    Clamp drawing arm length.
    if (rArmLen>rMaxRad) rArmLen=rMaxRad
    if (rArmLen<-rMaxRad) rArmLen=-rMaxRad
    //    nResolution is from 2 (draws 2 points per cycle) to 360 (draws 360 points)
    if (nResolution<2) nResolution=2
    if (nResolution>360) nResolution=360
    //    Number of cycles per iteration can be from 0 to, say, 100
    if (rCycle<0) rCycle=0
    if (rCycle>100) rCycle=100
    
    //Make a new layer, if requested
    if (fNewLayer) Wait: 0   EvType: Command   CommandID: Add New Layer
    
    //Draw!
    DrawEpicycloid(nResolution, rStaRad, rRotRad, rArmLen, rMaxRadX, rMaxRadY, rCycle, fGradient)
    
    //110803
    P.S. Here are some spirograph apps on the Internet:
    http://www.mathplayground.com/SpirographMath.html
    http://www.math.psu.edu/dlittle/java...1.0/index.html
    http://perl.guru.org/lynn/apps/
    Attached Files Attached Files
    Last edited by terrygillooly; 08-04-2011 at 02:37 PM. Reason: update code
    Cat Boxes, a web comic

  2. #2
    Join Date
    Mar 2006
    Location
    Ambient Design
    Posts
    3,839
    That's seriously very cool! Nicely done.

    Can I suggest one tiny change though - change the
    Professional Edition: Yes
    flag to 'NO' instead. Your script doesn't use any features that cant be used in ArtRage Studio (not the Pro edition) so it would save a message box popping up with users who dont have Studio Pro.
    AndyRage's mantra for graphics engine code:
    "Sure - how hard can it be?"

  3. #3
    Join Date
    Feb 2010
    Location
    Nevada
    Posts
    139
    Oh, yes, thanks for the tip! So that's what that flag does.


    Quote Originally Posted by AndyRage View Post
    That's seriously very cool! Nicely done.
    Also, basking.
    Cat Boxes, a web comic

  4. #4
    Join Date
    Mar 2006
    Location
    Ambient Design
    Posts
    3,839
    If you want me to complicate your life a bit more...
    Some of the tools have a problem with changing colour during a stroke - I see by the comments in your script that you'd noticed. Here's why:

    The InkPen, AirBrush, Gloop and Precise Pencil dont paint directly into the paint layer. They paint into a temporary 16-bit greyscale mask (to get better compositing resolution) which is mixed with the current paint colour into the paint map at mouse up. What you're seeing with those tools in your script is each tiny change in the screen area during the stroke taking the greyscale map and mixing it with the current colour at the time, and displaying that on the screen. That's not what actually gets put into the paint map. Then at the end of the stroke the entire temporary map is mixed with the new current colour and composited into your layer paint map. So it seems to suddenly revert to one colour.

    If you wanted to make the script deal with that, test if the current tool is inkpen, airbrush, gloop, or pencil with the precise flag set. If it is then instead of doing a continuous stroke to a closely spaced sequence of individual single dabs. Each dab has a mouse up, and every mouse up composits the change into the map in the current colour at the time. It will appear as though you are doing a multicoloured stroke, and it will be correct in the layer map.
    AndyRage's mantra for graphics engine code:
    "Sure - how hard can it be?"

  5. #5
    Join Date
    Mar 2006
    Location
    Ambient Design
    Posts
    3,839
    Alternatively, switch off the 'multi-colour' option for those tools.
    AndyRage's mantra for graphics engine code:
    "Sure - how hard can it be?"

  6. #6
    Join Date
    Feb 2010
    Location
    Nevada
    Posts
    139
    Andy, thank you for explaining about the color issue! I'd been really scratching my head over that.

    I notice, also, that changing the color did not work at all for the Oil Brush, Paint Roller, and Palette Knife. Do these tools only read the color value at the beginning of a stroke?

    Quote Originally Posted by AndyRage View Post
    If you wanted to make the script deal with that, test if the current tool is inkpen, airbrush, gloop, or pencil with the precise flag set. If it is then instead of doing a continuous stroke to a closely spaced sequence of individual single dabs. Each dab has a mouse up, and every mouse up composits the change into the map in the current colour at the time. It will appear as though you are doing a multicoloured stroke, and it will be correct in the layer map.
    Hm. Does that mean a separate stroke event for each color change?

    Or can a single stroke event have multiple mouse ups/downs? What would that code look like?
    Cat Boxes, a web comic

  7. #7
    Join Date
    Mar 2006
    Location
    Ambient Design
    Posts
    3,839
    Quote Originally Posted by terrygillooly View Post
    Andy, thank you for explaining about the color issue! I'd been really scratching my head over that.

    I notice, also, that changing the color did not work at all for the Oil Brush, Paint Roller, and Palette Knife. Do these tools only read the color value at the beginning of a stroke?
    The Oil Brush and the like work kinda like the real thing, I'm afraid. At the start of a stroke the brush head is loaded with a volume of paint of the current colour and that volume of paint 'runs out' as the stroke progresses. If the stroke intersects paint already on the canvas it picks up that paint. So during the stroke the current colour is (almost) completely ignored.


    Hm. Does that mean a separate stroke event for each color change?

    Or can a single stroke event have multiple mouse ups/downs? What would that code look like?
    You'd so something like:
    Code:
     <StrokeEvent>
      <StrokeHeader>
      <EventPt> Loc: (rX,rY) Pr: 1 Ti: 1 Ro: 0 Rv: NO Iv: NO </EventPt>
      <Recorded> No </Recorded>
     </StrokeHeader>
       Loc: (rX,rY) Pr: 1.0 Ti: 1 Ro: 0 Rv: NO Iv: NO
      </StrokeEvent>
    That should give you a single splat of paint at the rX, rY coordinate.
    AndyRage's mantra for graphics engine code:
    "Sure - how hard can it be?"

  8. #8
    Join Date
    Feb 2010
    Location
    Nevada
    Posts
    139
    Hm. Unfortunately, dabbing instead of a making continuous stroke left me with dots instead of curves at the lower resolutions. I think I'll leave it the way it is for now.
    Cat Boxes, a web comic

  9. #9
    Join Date
    May 2009
    Location
    3438 ft above sea level
    Posts
    2,951
    Haha Terry, loved your script 'plug' intro... was almost expecting 'But wait... there's more' in there

    This sounds like an interesting one, can't wait to try it out... thanks for your efforts
    "I paint because I love to cut mats" (Arthur Alexander)

  10. #10
    Join Date
    Oct 2010
    Location
    Boston, USA
    Posts
    17

    Smile Thanks, Nice fun script

    Thanks,

    Fun Script

    Carlos

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •