Circular spiral in illustrator?

i'm trying to make a circular design with small circles in the center that spiral out and get bigger
i've tried a few different ways: i made a blend with a big and small circle and applied it to a spiral path that i then transformed in a circle, and i tried saving it as a pattern brush and applying it to the path, but i didn't like how that looked. i also tried a circular path with circles on it and duplicated and scaled it larger
the problem i keep having is that the circles are spaced further apart when they're smaller in the center, and get larger and spaced close together. i know you can distribute the spacing in the align palette, but the problem is that the circles are on a spiral
i'm attaching a picture of the inspiration -- i'm trying to recreate that design. notice the way the circles are spaced very precisely.. can anyone help me out here? (i'm pretty sure there's a way to make the rotations exactly in the transform palette, but i'm very unfamiliar with how to do that)
thanks for any help!!

Majxkristina, I played with this some more and got pretty close to your 'inspiration' image with these settings.
Large  anchor circle 500 points diameter.
32 small circles, 20 pt. diameter each. (Angle of each circle's rotation from center is 11.25 degrees.)
Transform Effect settings:
Scale 90%, rotate 5 degrees, centered, 13 copies.
Harron, Terri's file is full of good info. I see she uses a small unpainted circle to move center of transformation.
For a transformation like the dot pinwheel in this thread, which requires precise geometry, I think using a large unpainted circle outside the objects offers more precision than a small anchor object.
I hope Adobe steals FreeHand's Transform Effect anchor. It's visible, snaps to guides, and marks the center of transformation quite precisely.

Similar Messages

  • I have an ipod 4gen and i reset the whole thing because i bought it from a friend and didnt want his stuff on it,no its been hours and there is just a circular spiral going on my screen and i cand do anything about it,please help

    i have an ipod 4gen and i reset the whole thing because i bought it from a friend and didnt want his stuff on it,no its been hours and there is just a circular spiral going on my screen and i cand do anything about it,please help

    Try:
    - iOS: Not responding or does not turn on
    - Also try DFU mode after try recovery mode
    How to put iPod touch / iPhone into DFU mode « Karthik's scribblings
    - If not successful and you can't fully turn the iOS device fully off, let the battery fully drain. After charging for an least an hour try the above again.
    - Try on another computer
    - If still not successful that usually indicates a hardware problem and an appointment at the Genius Bar of an Apple store is in order.
    Apple Retail Store - Genius Bar       

  • Gradient interlocking circular arrows in Illustrator

    hi there- I was wondering how you make interlocking circular arrows similar to this in Illustrator:
    I can do the circular arrows one of two ways:
    create a circular outline, split into 3, put arrow heads on, make them a fill and add gradient OR
    create a circle and split into 3 and add triangles for arrow heads.
    The issue I have is that one arrow head needs to be separated from the line and brought to the front so it's interlocked and still has the gradient intact - if that makes sense...? The 2nd and 3rd image shows where I am at the moment.
    How do you do this?!
    Any help would be greatly appreciated!

    This may be cheating, but I'd create a symbol and duplicate around the center point. Then duplicate the problem arrow and mask the front copy:
    This method lets you add as many arrows as you like to the circle.

  • Circular Curve Distortion Illustrator 3D/Filter Help?

    Hello I am trying to create a circular graphic that is similar to a race track turn with banking.  Is there a type of distortion filter or 3d that I can use that can help me create the feeling of a vanishing point that bends around a turn?
    Below is sort of the feeling
    Thank you

    You can do it wwith a simple path with a stroke or two and using the 3D Rotate effect with the option to use a perspective on it. You use no fill on th e path just strookes you get this
    This is without the previw on
    This is with the preview turned on

  • Can We Create Motion Paths From Lines Drawn In Illustrator?

    Is there any way to convert lines drawn in Adobe Illustrator into Motion Paths within Adobe Edge Animate? In other words, if I were to create something like a spiral in Illustrator to use as a path to animate an object on in Edge. Or perhaps if I wanted an object to move around the shape of another object as though it were on a path.

    An easier way would be to change the origin of a circle and it would move around it.
    Sample: https://app.box.com/s/k1lxscpit527vm0vguna

  • Spiral shape in Adobe Illustrator CC 2014

    I am having difficulties creating a spiral shape in Adobe Illustrator CC. I have looked online for tutorials; however, I don't believe that CC has this spiral tool. I've tried making my own, but it's difficult to do without having imperfections. Is there an easier way to do it?

    Thank you Monika! However, I'm not seeing the spiral tool that is mentioned in the tool gallery. When I click on the tool to draw a shape, there is no spiral.

  • Making a sunflower center with Fibonacci spiral of dots:  I'm a very new beginner to Illustrator

    I read a previous thread about creating a sunflower center with a Fibonacci spiral of dots or squares.  I could sort of follow what was being suggested, but not quite.  I am a very very new Illustrator user, learning it now in a graphic design course.  Could someone please explain, in terms this raw beginner could follow, how to get that so-beautiful spiral of dots that looks just like a sunflower center?  I have been a sunflower lover for years (it's the theme in my kitchen), and it was just so natural for the Fibonacci spiral of its seeds to pop into my head when we've been asked to design a logo. Part of my logo design will be based on a stylized sunflower, and it will look so cool to get the seeds arrangement right.
    Thanks in advance for any help in this endeavor.

    The first problem I see with the Florales Mustermit dem Transformationseffekt erstellen is my apprehensions that I can accurately carry out the instructions.  We  are presently working with the pen function, to get better control of that wild thing.  We haven't gotten to transform, although I have doodled with it on my own.  The second is anatomical accuracy.  The middle of the swirl created above is empty.    I see the Fibonacci spirals of stylized sunflower seeds on certain websites, so  I know Illustrator can make them.  Now, how to make ME make them, LOL!  As I told Monika (who I thank again, profusely), I will try this tonight when I get home from work (I am presently a high school teacher in a school system that is self-destructing, making teaching less of a career and more a journey through Dante's Inferno.).  I am sure it is I who will end up spiraling after a night of trying this, but I will persist!  We have learned to copy, the two types of selection arrows, and very recently image tracing, after a long stint of introducing us to InDesign.  I hope that somewhere in my new little bag of tricks there will be the means to do this.

  • Help me about Illustrator CS3

    anyone can help me to put the definition of this :
    http://farm1.static.flickr.com/196/519573598_11f4a6397f_o.jpg
    for example;
    Zoom Tools- The Zoom tool allows us to enlarge or reduce the view of artwork we are viewing or when we want to edit everything in detail.
    i hope you help me all of the content on that images that i gave*
    sorry for my English..

    Oh this puzzled me as well until I started to ask them precisely what they meant and realize they want use to help the give a verbal definition of each of the tool sets as in their example.
    For instance:
    Pen Tool:
    The Pen Tool is used to create paths of both straight or curved geometry by creating anchor points which the paths connect as segments, either opened or closed paths which can be stroked or filled. The Pen tools also include a pen to add anchor points to the path and one to remove anchor points and a tool to convert anchor points which redirects the nature of the anchor points from a corner anchor point to a curved anchor point.
    Line tool:
    is a tool to create a straight path by dragging the tool, it creates two end points and can only be used to create straight open paths.
    Arc Tool
    does the same thing as the line tool but only creates arcs that are open paths with two end points
    Spiral Tool
    The spiral is used to create spiral paths that are opened paths that is one continuous path
    The Grid Tools
    The Rectangle Grid Tool is used to create a grid of open straight paths of various number of divisions as the user defines the number through a dialog and then drags or enters the dimensions to make it the desired overall size.
    The Polar Grid does the same as the Rectangle Grid tool but it is a Circular Polar geometry.The concentric circular paths are closed and the divisions are open paths.
    This is what they are looking for they must be instructing a course in Illustrator or writing a book.
    I think that Erikku Yuki can obtain this information from the help files.

  • Convert old cs4 script to illustrator cc

    This is a big ask, but I found this script to remove redundant points at github.com/mekkablue/Glyphs-Scripts
    Each time I run, it seems to work, it shows how many points it has removed, but then illustrator crashes, with no kind of error notice.
    If I run it via extendscript toolkit it jumps to the following bit of code
    var docRef=app.activeDocument;
    I would really love to get this to work, if anyone is willing to help me.
      RemovetRedundantPoints.jsx
      A Javascript for Adobe Illustrator
      Author:
      Jim Heck
      [email protected]
      Purpose:
      Remove anchorpoints on selected path that are coincident in location.
      Finds and optionally removes redundant points from each selected PathItem.
      Useful for cleaning up after Offset Path and Outline Stroke commands in CS3.
      To Use:
      Select the paths, including compound paths to be affected. If no path is
      selected, the script will run for all paths in the document that are not
      locked. Run the script.
      Rights:
      This work is licensed under the Creative Commons Attribution 3.0 United States
      License. To view a copy of this license, visit
      http://creativecommons.org/licenses/by/3.0/us/
      or send a letter to Creative Commons, 171 Second Street, Suite 300,
      San Francisco, California, 94105, USA.
      Version History:
      1.8 120108 More fixes to the logic for keeping only a single point.
      The direction handles for the remaining point are now correctly calculated
      based on relative angle and distance to the original anchor to which a
      handle related. Also if a SMOOTH point is remaining, the angle of the
      two direction handles has been tweaked to be exactly 180 degrees for
      consistency with the definition of a SMOOTH point.
      1.7 120106 Change the way direction handles and PointType are handled
      when keeping only one point. Retract handles less than 0.5 points to keep
      consistent angles for SMOOTH point types. If keepLeadingPoint or
      keepTrailingPoint is specified, try to keep the PointType of that point.
      In the absence of other indicators, base PointType on the point (leading
      or trailing) that has an extended handle.
      1.6.1 090914 Tweak defaults to make sense for my work style
      1.6 090411 Fix a bug in creating a temporary path. Fix a bug in
      findRedundantPoints(), when searching backwards, the tolerance was always
      applied against the first point on the path instead of the adjacent point
      along the path. Change selection options so that there is more control over
      which points are processed on a given path. The new options allow for ignoring
      selection of points, restricting processing to only selected points, or
      processing redundant points if at least one of them is selected. Correct count
      of redundant points removed when both leading and trailing points retained.
      1.5 090404 Change default action to remove. Fix a major performance issue
      in the docGetSelectedPaths() routine. Searching through all the paths in very
      complex files takes a LONG time. Instead, search the document groups array.
      BETA: Lots of hacking on the removeRedundantPoints() routine to improve the
      look of the resulting curve when applied to the oxbow problem.
      1.4.1 090331 Fix a bug in removeRedundantPoints(), needed to compare absolute
      error to a tolerance. Also, loosen up the error criteria so less smooth
      points are mischaracterized as corners. Tolerance is now 0.02 radians,
      which is about 1.15 degrees. For some reason, the redundant points on
      arbitrary (non-geometric) outlined paths have lots of slop in the
      direction handles.
      1.4 090331 Add options to control which points are left on removal, leading,
      trailing or both. If neither is retained, the redundant point positions
      are averaged. If both are retained, intermediate points are removed, and
      inward facing control handles are synthesized (see comments below).
      Switched to using the atan2 function instead of atan for calculating theta.
      Fixed bugs in docGetSelectedPaths(). CompoundPathItem objects don't seem
      to have properly formed pathItems arrays when they contain what appear to
      be groups of paths. Also, layer objects can contain layers.
      1.3.1 090327 Limit user entered tolerance value to something sane.
      1.3 090327 Add user controls to specify a tolerance in points for identifying
      redundant points.
      1.2.3 090327 Improve results dialog verbiage.
      1.2.2 090326 Bug fix. Observe proper unlocking and locking order for
      handling of locked objects.
      1.2.1 090326 Minor bug fixes including, restricting selection only option
      to not be allowed with selection function.
      1.2 090326 Add option to remove only redundant points sets with at least one
      selected point. Fix broken option to remove locked redundant points.
      Add results dialog OK button.
      1.1 090325 Improve select action to work across selection or entire document.
      Handle nested layers in docGetSelectedPaths(). Clean whitespace.
      1.0.1 090325 Minor bug fix.
      1.0 090311 Initial release.
    * Function: getPairTheta
    * Description:
    * Return the angle relative to the X axis from the line formed between
    * two points, which are passed in as arguments. The angle is measured
    * relative to point A (as if A were relocated to the origin, and the angle
    * is measured to the X axis itself). The arguments are expected to be
    * arrays of two numbers (X, Y) defining the point. The return value is in
    * radians (PI to -PI)
    function getPairTheta(pairA,pairB){
      var deltaX=pairB[0]-pairA[0];
      var deltaY=pairB[1]-pairA[1];
      /*alert("deltaX="+deltaX+" deltaY="+deltaY);*/
      return(Math.atan2(deltaY, deltaX));
    * Function: getPairDistance
    * Description:
    * Return the distance between two points. The arguments are expected to be
    * arrays of two numbers (X, Y) defining the point. The return value is the
    * distance in units relative to the inputs.
    function getPairDistance(pairA,pairB){
      var deltaX=pairB[0]-pairA[0];
      var deltaY=pairB[1]-pairA[1];
      return(Math.sqrt((deltaX*deltaX)+(deltaY*deltaY)));
    * Function: findRedundantPoints
    * Description:
    * Find all sets of redundant points for the input path. A redundant point
    * is defined as one that has the same anchor location as a neighboring point.
    * The arguments are a path to work on, the tolerance in points to apply to
    * determine a point is redundant, and a boolean to indicate that only
    * groups of redundant points where at least one point is selected should
    * be considered. The return value is an Array of Arrays containing the
    * indicies of the redundant pathPoint objects found in the path.
    function findRedundantPoints(path, tolerance, anySelected, allSelected){
      var anchorDistance = 0;
      var redundantPointSets = new Array();
      var redundantPoint = new Array();
      var selectedRedundantPointSets = new Array();
      var selectedRedundantPoint = new Array();
      var i = 0;
      var j = 0;
      var k = 0;
      var index;
      var selected = false;
      if(path.pathPoints.length > 1) {
      * The first path point may be coincident with some at the end of the path
      * so we check going backwards first. Redundant points pushed on the
      * front of the array so they stay in order leftmost to rightmost.
      redundantPoint.push(0);
      index = 0;
      for (i=path.pathPoints.length-1; i>0; i--) {
      * Get distance and round to nearest hundredth of a point.
      * If points are closer than the tolerance, consider them
      * coincident.
      anchorDistance = getPairDistance(path.pathPoints[index].anchor, path.pathPoints[i].anchor);
      anchorDistance = roundToPrecision(anchorDistance, 0.01);
      if (anchorDistance < tolerance) {
      redundantPoint.unshift(i);
      else {
      break;
      index = i;
      * If we haven't used up all the points, start searching forwards
      * up to the point we stopped searching backwards. Test the
      * current point against the next point. If the next point matches push
      * its index onto the redundantPoint array. When the first one doesn't match,
      * check if the redundantPoint array has more than one index. If so add it
      * to the redundantPointSets array. Then clean the redundantPoint array
      * and push on the next point index.
      if(i > 0) {
      for (j=0; j<i; j++) {
      anchorDistance = getPairDistance(path.pathPoints[j].anchor, path.pathPoints[j+1].anchor);
      anchorDistance = roundToPrecision(anchorDistance, 0.01);
      if (anchorDistance < tolerance) {
      redundantPoint.push(j+1);
      else {
      if (redundantPoint.length > 1) {
      redundantPointSets.push(redundantPoint);
      redundantPoint = [];
      redundantPoint.push(j+1);
      * Push the last redundantPoint array onto the redundantPointSets array if
      * its length is greater than one.
      if (redundantPoint.length > 1) {
      redundantPointSets.push(redundantPoint);
      if (anySelected) {
      for (i=0; i<redundantPointSets.length; i++) {
      var currentPointSet = redundantPointSets[i];
      selected = false;
      for (j=0; j<currentPointSet.length; j++) {
      if (path.pathPoints[currentPointSet[j]].selected ==
      PathPointSelection.ANCHORPOINT) {
      selected = true;
      if (selected) {
      selectedRedundantPointSets.push(currentPointSet);
      else if (allSelected) {
      for (i=0; i<redundantPointSets.length; i++) {
      var currentPointSet = redundantPointSets[i];
      for (j=currentPointSet.length-1; j>=0; j--) {
      var currentPoint = path.pathPoints[currentPointSet[j]];
      if (currentPoint.selected == PathPointSelection.ANCHORPOINT) {
      selectedRedundantPoint.unshift(currentPointSet[j]);
      else {
      break;
      if (j > 0) {
      for (k=0; k<j; k++) {
      var currentPoint = path.pathPoints[currentPointSet[k]];
      if (currentPoint.selected == PathPointSelection.ANCHORPOINT) {
      selectedRedundantPoint.push(currentPointSet[k]);
      else {
      if (selectedRedundantPoint.length > 1) {
      selectedRedundantPointSets.push(selectedRedundantPoint);
      selectedRedundantPoint = [];
      if (selectedRedundantPoint.length > 1) {
      selectedRedundantPointSets.push(selectedRedundantPoint);
      selectedRedundantPoint = [];
      else {
      selectedRedundantPointSets = redundantPointSets;
      return(selectedRedundantPointSets);
    * Function: countRedundantPoints
    * Description:
    * Count the number of redundant points given a redundantPointSets array as
    * the first parameter.
    function countRedundantPoints(redundantPointSets, doKeepLeadingPoint, doKeepTrailingPoint) {
      var i = 0;
      var redundantPoints = 0;
      var pointsKept = 1;
      if (doKeepLeadingPoint && doKeepTrailingPoint) {
      pointsKept = 2;
      for (i=0; i<redundantPointSets.length; i++) {
      redundantPoints += redundantPointSets[i].length - pointsKept;
      return (redundantPoints);
    * Function: countSelectedPoints
    * Description:
    * Count the number of selected anchor points given a path as the first parameter.
    function countSelectedPoints(path) {
      var i = 0;
      var selectedPoints = 0;
      for (i=0; i<path.pathPoints.length; i++) {
      if (path.pathPoints[i].selected == PathPointSelection.ANCHORPOINT) {
      selectedPoints++;
      return (selectedPoints);
    * Function: removeRedundantPoints
    * Description:
    * Remove redundant points from a path input as the first parameter. The
    * second input parameter should be an array of arrays containing the
    * indicies of redundant points, as returned from function
    * findRedundantPoints(). From each set of indicies, the first point is
    * retained, and the subsequent points are removed from the path. Care is
    * taken to preserve the proper leftDirection and rightDirection handles,
    * as well as the proper PointType for the remaining point. Returns
    * the number of points removed.
    function removeRedundantPoints(path, redundantPointSets, keepLeadingPoint, keepTrailingPoint, keepAveragedPoint){
      var i = 0;
      var j = 0;
      var pointsToRemove = new Array();
      var tempLayer;
      var tempPath;
      * For each array of redundant point indicies in array redundantPointSets,
      * modify the leadingPoint to have all the properties needed to properly
      * describe the set of coincident points.
      for (i=0; i<redundantPointSets.length; i++) {
      var x = 0;
      var y = 0;
      var currentPointSet = redundantPointSets[i];
      var leadingPoint = path.pathPoints[currentPointSet[0]];
      var trailingPoint = path.pathPoints[currentPointSet[currentPointSet.length-1]];
      if (keepLeadingPoint && keepTrailingPoint) {
      * JAH 090401 REVISIT COMMENT WHEN DONE
      * If we are keeping two points, the leftDirection of the leading point
      * and rightDirection of the trailing point are already fixed. We have to
      * synthesize the inward facing handles, and choose pointType of the two points.
      * To allow easy manipultion of the inner handles without disturbing the fixed
      * handles, make the points PointType.CORNER. For the direction handles, make
      * them parallel to their respective paired handle, and extend them half the
      * distance between the two remaining points.
      var averagedPoint;
      var theta;
      var deltaX;
      var deltaY;
      var pairDistance;
      var leftDistance;
      var rightDistance;
      var firstRemovedIndex = 1;
      if (currentPointSet.length > 2) {
      averagedPoint = path.pathPoints[currentPointSet[1]];
      else {
      tempLayer = app.activeDocument.layers.add();
      tempLayer.name = "Temp";
      tempPath = tempLayer.pathItems.add();
      averagedPoint = tempPath.pathPoints.add();
      if( currentPointSet.length <= 2 || !keepAveragedPoint ) {
      * Use just the leading and trailing points. Create inward facing
      * direction handles for the two endpoints based on the relationship
      * of the angles between each endpoint and the average point.
      * For each endpoint, calcualte the angle of the endpoint to the
      * average point, and the endpoint to the other endpoint. Combine
      * the angles. The base angle for the inward facing direction handle
      * is the angle that points it towards the average point. Add to this
      * angle, a multiple of the difference between the angle just mentioned,
      * and the angle to the other endpoint. Adding this difference angle
      * will bias the curve towards the average point. Finally, set the
      * length of the direction handle as the distance from the endpoint
      * to the average point multiplied by a factor.
      var thetaAverage;
      var thetaPair;
      var tweakThetaToOppositeEndpoint = 1.0;
      var tweakPairDistance = 0.5;
      * Since the leading and trailing points will have direction handles pointing
      * in different directions, these points must be corner points by necessity.
      leadingPoint.pointType = PointType.CORNER;
      trailingPoint.pointType = PointType.CORNER;
      * Create new average point.
      for (j=0; j<currentPointSet.length; j++) {
      x += path.pathPoints[currentPointSet[j]].anchor[0];
      y += path.pathPoints[currentPointSet[j]].anchor[1];
      x /= currentPointSet.length;
      y /= currentPointSet.length;
      averagedPoint.anchor = Array(x, y);
      averagedPoint.leftDirection = Array( averagedPoint.anchor[0], averagedPoint.anchor[1]);
      averagedPoint.rightDirection = Array( averagedPoint.anchor[0], averagedPoint.anchor[1]);
      averagedPoint.pointType = PointType.CORNER;
      /* Calcualte new leading point rightDirection */
      pairDistance = getPairDistance(leadingPoint.anchor, averagedPoint.anchor);
      thetaAverage = getPairTheta(leadingPoint.anchor, averagedPoint.anchor);
      thetaPair = getPairTheta(leadingPoint.anchor, trailingPoint.anchor);
      theta = thetaAverage + tweakThetaToOppositeEndpoint * (thetaAverage - thetaPair);
      /*alert("thetaAverage="+thetaAverage+" thetaPair="+thetaPair" theta="+theta);*/
      deltaX = Math.cos(theta) * tweakPairDistance * pairDistance;
      deltaY = Math.sin(theta) * tweakPairDistance * pairDistance;
      leadingPoint.rightDirection = Array(leadingPoint.anchor[0]+deltaX, leadingPoint.anchor[1]+deltaY);
      /* Calcualte new trailing point leftDirection */
      pairDistance = getPairDistance(trailingPoint.anchor, averagedPoint.anchor);
      thetaAverage = getPairTheta(trailingPoint.anchor, averagedPoint.anchor);
      thetaPair = getPairTheta(trailingPoint.anchor, leadingPoint.anchor);
      theta = thetaAverage + tweakThetaToOppositeEndpoint * (thetaAverage - thetaPair);
      /*alert("thetaAverage="+thetaAverage+" thetaPair="+thetaPair" theta="+theta);*/
      deltaX = Math.cos(theta) * tweakPairDistance * pairDistance;
      deltaY = Math.sin(theta) * tweakPairDistance * pairDistance;
      trailingPoint.leftDirection = Array(trailingPoint.anchor[0]+deltaX, trailingPoint.anchor[1]+deltaY);
      else {
      * Use just the leading and trailing points, along with a third point added
      * at the average of all the removed points. This point will act to anchor
      * the curve at the average point. It will also allow the leading and
      * trailing points to be smooth points, allowing for a continuous
      * curve through them.
      * The inward facing direction handles for the two endpoints will be
      * shortened extensions of the outward facing direction handles for these
      * points. The length of the handles will be a multiple of the
      * distance from the direction handle to the average point.
      * For the average point, the direction handles will be parallel to the
      * angle formed by the angle between the two endpoints. The length
      * of the direction handles for this point will be a different multiple
      * of the length from each endpoint to the average point.
      var thetaAverage;
      var thetaPair;
      var tweakPairDistanceForAveraged = 0.5;
      var tweakPairDistanceForEndpoint = 0.25;
      * Since the leading and trailing points will have direction handles that
      * are parallel, make them smooth points.
      leadingPoint.pointType = PointType.SMOOTH;
      trailingPoint.pointType = PointType.SMOOTH;
      /* We will be keeping one more point, the averaged point. */
      firstRemovedIndex = 2;
      * Create new average point.
      for (j=0; j<currentPointSet.length; j++) {
      x += path.pathPoints[currentPointSet[j]].anchor[0];
      y += path.pathPoints[currentPointSet[j]].anchor[1];
      x /= currentPointSet.length;
      y /= currentPointSet.length;
      averagedPoint.anchor = Array(x, y);
      averagedPoint.leftDirection = Array( averagedPoint.anchor[0], averagedPoint.anchor[1]);
      averagedPoint.rightDirection = Array( averagedPoint.anchor[0], averagedPoint.anchor[1]);
      averagedPoint.pointType = PointType.SMOOTH;
      /* Calcualte new averaged point leftDirection */
      pairDistance = getPairDistance(leadingPoint.anchor, averagedPoint.anchor);
      theta = getPairTheta(leadingPoint.anchor, trailingPoint.anchor);
      /*alert("theta="+theta);*/
      if (theta > 0) {
      theta += Math.PI;
      else {
      theta += -Math.PI;
      deltaX = Math.cos(theta) * tweakPairDistanceForAveraged * pairDistance;
      deltaY = Math.sin(theta) * tweakPairDistanceForAveraged * pairDistance;
      averagedPoint.leftDirection = Array(averagedPoint.anchor[0]+deltaX, averagedPoint.anchor[1]+deltaY);
      /* Calcualte new averaged point rightDirection */
      pairDistance = getPairDistance(trailingPoint.anchor, averagedPoint.anchor);
      theta = getPairTheta(trailingPoint.anchor, averagedPoint.anchor);
      /*alert("theta="+theta);*/
      if (theta > 0) {
      theta += Math.PI;
      else {
      theta += -Math.PI;
      deltaX = Math.cos(theta) * tweakPairDistanceForAveraged * pairDistance;
      deltaY = Math.sin(theta) * tweakPairDistanceForAveraged * pairDistance;
      averagedPoint.rightDirection = Array(averagedPoint.anchor[0]+deltaX, averagedPoint.anchor[1]+deltaY);
      /* Calculate direction handles for leading and trailing points */
      pairDistance = getPairDistance(leadingPoint.anchor, trailingPoint.anchor);
      leftDistance = getPairDistance(leadingPoint.anchor, leadingPoint.leftDirection);
      if (leftDistance > 0) {
      theta = getPairTheta(leadingPoint.anchor, leadingPoint.leftDirection);
      /*alert("theta="+theta);*/
      if (theta > 0) {
      theta += Math.PI;
      else {
      theta += -Math.PI;
      pairDistance = getPairDistance(leadingPoint.anchor, averagedPoint.anchor);
      deltaX = Math.cos(theta) * tweakPairDistanceForEndpoint * pairDistance;
      deltaY = Math.sin(theta) * tweakPairDistanceForEndpoint * pairDistance;
      leadingPoint.rightDirection = Array(leadingPoint.anchor[0]+deltaX, leadingPoint.anchor[1]+deltaY);
      else {
      leadingPoint.rightDirection = leadingPoint.anchor;
      rightDistance = getPairDistance(trailingPoint.anchor, trailingPoint.rightDirection);
      if (rightDistance > 0) {
      theta = getPairTheta(trailingPoint.anchor, trailingPoint.rightDirection);
      if (theta > 0) {
      theta += Math.PI;
      else {
      theta += -Math.PI;
      pairDistance = getPairDistance(trailingPoint.anchor, averagedPoint.anchor);
      deltaX = Math.cos(theta) * tweakPairDistanceForEndpoint * pairDistance;
      deltaY = Math.sin(theta) * tweakPairDistanceForEndpoint * pairDistance;
      trailingPoint.leftDirection = Array(trailingPoint.anchor[0]+deltaX, trailingPoint.anchor[1]+deltaY);
      else {
      trailingPoint.leftDirection = trailingPoint.anchor;
      * Push all points other than the leading and trailing onto the pointsToRemove array
      * for later removal. We can't remove them while we are working with later sets.
      for (j=firstRemovedIndex; j<currentPointSet.length-1; j++) {
      pointsToRemove.push(currentPointSet[j]);
      else {
      * If we are only keeping one point, we will work with the leading point.
      * First, calculate the relative distances and angles of the direction handle for
      * the leadingPoint leftDirection handle and the trailingPoint rightDirection
      * handle. These values will be used to help properly construct the remaining
      * point.
      var leftDistance = getPairDistance(leadingPoint.anchor, leadingPoint.leftDirection);
      var rightDistance = getPairDistance(trailingPoint.anchor, trailingPoint.rightDirection);
      var leftTheta = getPairTheta(leadingPoint.anchor, leadingPoint.leftDirection);
      var rightTheta = getPairTheta(trailingPoint.anchor, trailingPoint.rightDirection);
      * If we are keeping the leadingPoint, calculate a relative rightDirection handle
      * based on the trailingPoint rightDistance and rightTheta. If we are keeping the
      * trailingPoint, copy its anchor and rightDirection handle to the leadingPoint,
      * and calculate a relative leftDirection handle based on the leadingPoint
      * leftDistance and leftTheta. If we are to keep neither leading or trailing point,
      * average the position of all the redundant points and calcuate direction handles
      * based on the appropriate values.
      if (keepLeadingPoint) {
      x = leadingPoint.anchor[0] + (Math.cos(rightTheta) * rightDistance);
      y = leadingPoint.anchor[1] + (Math.sin(rightTheta) * rightDistance);
      leadingPoint.rightDirection = Array(x, y);
      else if (keepTrailingPoint) {
      leadingPoint.anchor = trailingPoint.anchor;
      leadingPoint.rightDirection = trailingPoint.rightDirection;
      x = leadingPoint.anchor[0] + (Math.cos(leftTheta) * leftDistance);
      y = leadingPoint.anchor[1] + (Math.sin(leftTheta) * leftDistance);
      leadingPoint.leftDirection = Array(x, y);
      else {
      for (j=0; j<currentPointSet.length; j++) {
      x += path.pathPoints[currentPointSet[j]].anchor[0];
      y += path.pathPoints[currentPointSet[j]].anchor[1];
      x /= currentPointSet.length;
      y /= currentPointSet.length;
      leadingPoint.anchor = Array(x, y);
      x = leadingPoint.anchor[0] + (Math.cos(leftTheta) * leftDistance);
      y = leadingPoint.anchor[1] + (Math.sin(leftTheta) * leftDistance);
      leadingPoint.leftDirection = Array(x, y);
      x = leadingPoint.anchor[0] + (Math.cos(rightTheta) * rightDistance);
      y = leadingPoint.anchor[1] + (Math.sin(rightTheta) * rightDistance);
      leadingPoint.rightDirection = Array(x, y);
      * If the distance for a handle is less than half a point and rounds to zero,
      * retract that handle fully by setting that direction handle equal to the anchor
      * point. This will keep angles consistent for smooth points.
      if (Math.round(leftDistance) == 0) {
      leadingPoint.leftDirection = leadingPoint.anchor;
      if (Math.round(rightDistance) == 0) {
      leadingPoint.rightDirection = leadingPoint.anchor;
      * Handle the PointType in a minimal manner. If keeping the leadingPoint or keeping
      * the trailingPoint, keep the PointType of that point if possible. If both handles
      * are extended, measure the angles of the two direction handles. If both handles
      * have the same angle relative to the X axis within a tolerance, the PointType
      * can be SMOOTH, otherwise it must be CORNER. If the point type is SMOOTH, ensure
      * the direction handles are corrected to be exactly 180 degrees apart.
      * If not specifically keeping the leading or trailing point and only one handle is
      * extended, base the pointType on the the leadingPoint if only the left handle is
      * extended and the trailingPoint if only the right handle is extended. 
      if (Math.round(leftDistance) > 0 && Math.round(rightDistance) > 0) {
      var absdiff = Math.abs(leftTheta-rightTheta);
      var error = Math.PI - absdiff;
      /*alert("leftTheta="+leftTheta+" rightTheta="+rightTheta+" absdiff="+absdiff+" error="+error);*/
      if (Math.abs(error) < 0.02) {
      if (keepTrailingPoint) {
      leadingPoint.pointType = trailingPoint.pointType;
      else if (!keepLeadingPoint) {
      leadingPoint.pointType = PointType.SMOOTH;
      if (leadingPoint.pointType == PointType.SMOOTH) {
      if (keepTrailingPoint) {
      x = leadingPoint.anchor[0] + (Math.cos(Math.PI + rightTheta) * leftDistance);
      y = leadingPoint.anchor[1] + (Math.sin(Math.PI + rightTheta) * leftDistance);
      leadingPoint.leftDirection = Array(x, y);
      else {
      x = leadingPoint.anchor[0] + (Math.cos(Math.PI + leftTheta) * rightDistance);
      y = leadingPoint.anchor[1] + (Math.sin(Math.PI + leftTheta) * rightDistance);
      leadingPoint.rightDirection = Array(x, y);
      else {
      leadingPoint.pointType = PointType.CORNER;
      else if (keepTrailingPoint) {
      leadingPoint.pointType = trailingPoint.pointType;
      else if (!keepLeadingPoint && rightDistance > 0) {
      leadingPoint.pointType = trailingPoint.pointType;
      * Push all other points onto the pointsToRemove array for later removal. We can't
      * remove them while we are working with later sets.
      for (j=1; j<currentPointSet.length; j++) {
      pointsToRemove.push(currentPointSet[j]);
      * Sort the pointsToRemove array and then remove the points in reverse order, so the indicies
      * remain coherent during the removal.
      pointsToRemove.sort(function (a,b) { return a-b });
      for (i=pointsToRemove.length-1; i>=0; i--) {
      var pointToRemove = path.pathPoints[pointsToRemove[i]];
      pointToRemove.remove();
      if (tempPath) {
      tempPath.remove();
      if (tempLayer) {
      tempLayer.remove();
      return (pointsToRemove.length);
    * Function: selectRedundantPoints
    * Description:
    * Select redundant points on a path input as the first parameter. The
    * second input parameter should be an array of arrays containing the
    * indicies of redundant points, as returned from function
    * findRedundantPoints(). If there are redundant points, deselect all points
    * on the path and select the ANCHORPOINT of each redundant point. If there
    * are no redundant points on the path, do nothing.
    function selectRedundantPoints(path, redundantPointSets){
      var i = 0;
      var j = 0;
      if (redundantPointSets.length > 0) {
      for (i=0; i<path.pathPoints.length; i++) {
      path.pathPoints[i].selected = PathPointSelection.NOSELECTION;
      for (i=0; i<redundantPointSets.length; i++) {
      var currentPointSet = redundantPointSets[i];
      for (j=0; j<currentPointSet.length; j++) {
      path.pathPoints[currentPointSet[j]].selected = PathPointSelection.ANCHORPOINT;
    * Function: unlockPath
    * Description:
    * For a path input as the first parameter, unlock the path and any locked
    * parent object. Return an array of objects that have been unlocked.
    function unlockPath(path){
      var unlockedObjects = new Array();
      var parentObjects = new Array();
      var currentObject = path;
      var i = 0;
      while (currentObject.typename != "Document") {
      parentObjects.unshift(currentObject);
      currentObject = currentObject.parent;
      for (i=0; i<parentObjects.length; i++) {
      if (parentObjects[i].locked) {
      parentObjects[i].locked = false;
      unlockedObjects.unshift(parentObjects[i]);
      return unlockedObjects;
    * Function: lockObjects
    * Description:
    * For a set of objects as the first parameter, lock each object.
    function lockObjects(objects){
      var i = 0;
      for (i=0; i<objects.length; i++) {
      objects[i].locked = true;
    * Function: docGetSelectedPaths
    * Description:
    * Get all the selected paths for the docRef argument passed in as
    * a parameter. The second parameter is a boolean that controls if compound
    * path items are included (default true), and the third parameter is a
    * boolean that controls if locked objects are included (default false).
    * Returns an array of paths.
    function docGetSelectedPaths(docRef, includeCompound, includeLocked){
      var qualifiedPaths = new Array();
      var i = 0;
      var j = 0;
      var nextPath = null;
      var currentSelection = new Array();
      var nextSelection = docRef.selection;
      if (includeCompound == null) {
      includeCompound = true;
      if (includeLocked == null) {
      includeLocked = false;
      do {
      currentSelection = nextSelection;
      nextSelection = [];
      for(i=0; i<currentSelection.length; i++){
      var currentObject=currentSelection[i];
      if (currentObject.typename == "PathItem") {
      if (includeLocked || !(currentObject.locked ||
      currentObject.layer.locked)) {
      qualifiedPaths.push(currentObject);
      else if (currentObject.typename == "CompoundPathItem") {
      if (includeCompound &&
      (includeLocked || !(currentObject.locked ||
      currentObject.layer.locked))) {
      * For more complex compound paths (e.g. concentric circular bands),
      * in CS3 the CompoundPathItem object's pathItems array is empty.
      * Inspection of the paths in a document shows the paths contained
      * in the CompoundPathItem have groups as parents. To get around
      * this seeming bug, in addition to using the pathItems array,
      * which still contains individual paths, we also search through
      * all the groups in the document adding paths whose parent
      * is the CompoundPathItem object.
      * WARNING this takes non-negligible time in large documents.
      for (j=0; j<currentObject.pathItems.length; j++) {
      qualifiedPaths.push(currentObject.pathItems[j]);
      for (j=0; j<docRef.groupItems.length; j++) {
      if (docRef.groupItems[j].parent == currentObject) {
      nextSelection.push(docRef.groupItems[j]);
      else if (currentObject.typename == "GroupItem") {
      for (j=0; j<currentObject.pathItems.length; j++){
      nextSelection.push(currentObject.pathItems[j]);
      for (j=0; j<currentObject.compoundPathItems.length; j++){
      nextSelection.push(currentObject.compoundPathItems[j]);
      for (j=0; j<currentObject.groupItems.length; j++){
      nextSelection.push(currentObject.groupItems[j]);
      else if (currentObject.typename == "Layer") {
      for (j=0; j<currentObject.pathItems.length; j++){
      nextSelection.push(currentObject.pathItems[j]);
      for (j=0; j<currentObject.compoundPathItems.length; j++){
      nextSelection.push(currentObject.compoundPathItems[j]);
      for (j=0; j<currentObject.groupItems.length; j++){
      nextSelection.push(currentObject.groupItems[j]);
      for (j=0; j<currentObject.layers.length; j++){
      nextSelection.push(currentObject.layers[j]);
      } while (nextSelection.length > 0);
      return qualifiedPaths;
    * Function: docGetAllPaths
    * Description:
    * Get all the paths for the docRef argument passed in as a parameter.
    * The second parameter is a boolean that controls if compound path items are
    * included (default true), and the third parameter is a boolean that controls
    * if locked objects are included (default false). Returns an array of paths.
    function docGetAllPaths(docRef, includeCompound, includeLocked) {
      var qualifiedPaths = new Array();
      var i = 0;
      var nextPath = null;
      if (includeCompound == null) {
      includeCompound = true;
      if (includeLocked == null) {
      includeLocked = false;
      for (i=0; i<docRef.pathItems.length; i++) {
      nextPath = docRef.pathItems[i];
      if (!includeCompound && nextPath.parent.typename == "CompoundPathItem") {
      continue;
      if (!includeLocked && (nextPath.layer.locked == true || nextPath.locked == true)) {
      continue;
      qualifiedPaths.push(nextPath);
      return qualifiedPaths;
    * Function: roundToPrecision
    * Description:
    * Round a number input as the first parameter to a given precision. The
    * second input parameter is the precision to round to (typically a power of
    * 10, like 0.1). Returns the rounded value.
    function roundToPrecision(value, precision) {
      var result;
      result = value / precision;
      result = Math.round(result);
      result = result * precision;
      return (result);
    * Main code
    var dlgInit = new Window('dialog', 'Redundant Path Points');
    doInitDialog(dlgInit);
    var exitError;
    var tolerance = 1 * (dlgInit.tolerancePnl.editText.text);
    var doAnalyze = dlgInit.functionPnl.doAnalyze.value;
    var doRemove = dlgInit.functionPnl.doRemove.value;
    var doSelect = dlgInit.functionPnl.doSelect.value;
    var doKeepLeadingPoint = dlgInit.removalPnl.doKeepLeadingPoint.value;
    var doKeepTrailingPoint = dlgInit.removalPnl.doKeepTrailingPoint.value;
    var doKeepAveragedPoint = dlgInit.removalPnl.doKeepAveragedPoint.value;
    var includeCompound = dlgInit.optionPnl.includeCompound.value;
    var includeLocked = dlgInit.optionPnl.includeLocked.value;
    var ignoreSelected = dlgInit.selectionPnl.ignoreSelected.value;
    var anySelected = dlgInit.selectionPnl.anySelected.value;
    var allSelected = dlgInit.selectionPnl.allSelected.value;
    var docRef=app.activeDocument;
    var pathsToProcess = new Array();
    var i = 0;
    var j = 0;
    var totalPaths = 0;
    var totalPointsWithRedundancy = 0;
    var totalPointsToRemove = 0;
    var totalPointsRemoved = 0;
    var totalPointsStarting = 0;
    var totalPointsRemaining = 0;
    var totalPointsSelected = 0;
    var redundantPointSets = new Array();
    var unlockedObjects = new Array();
    try {
      if (exitError != 0) {
      throw("exit");
      exitError = 99;
      if (docRef.selection.length > 0) {
      pathsToProcess = docGetSelectedPaths(docRef, includeCompound, includeLocked);
      else {
      var doAll = confirm("Run script for all paths in document?");
      if (doAll) {
      pathsToProcess = docGetAllPaths(docRef, includeCompound, includeLocked);
      if (doSelect) {
      if (includeLocked) {
      exitError = 2;
      throw("exit");
      if (!ignoreSelected) {
      exitError = 3;
      throw("exit");
      docRef.selection = null;
      for (i=0; i<pathsToProcess.length; i++) {
      redundantPointSets = findRedundantPoints(pathsToProcess[i], tolerance, anySelected, allSelected);
      totalPaths++;
      totalPointsWithRedundancy += redundantPointSets.length;
      totalPointsToRemove += countRedundantPoints(redundantPointSets, doKeepLeadingPoint, doKeepTrailingPoint);
      totalPointsStarting += pathsToProcess[i].pathPoints.length;
      totalPointsSelected += countSelectedPoints(pathsToProcess[i]);
      if (doRemove) {
      if (includeLocked) {
      unlockedObjects = unlockPath(pathsToProcess[i]);
      else {
      unlockedObjects = [];
      totalPointsRemoved += removeRedundantPoints(pathsToProcess[i], redundantPointSets, doKeepLeadingPoint, doKeepTrailingPoint, doKeepAveragedPoint);
      if (unlockedObjects.length > 0) {
      lockObjects(unlockedObjects);
      if (doSelect) {
      selectRedundantPoints(pathsToProcess[i], redundantPointSets);
      totalPointsRemaining += pathsToProcess[i].pathPoints.length;
      var dlgResults = new Window('dialog', 'Redundant Path Points');
      doResultsDialog(dlgResults,
      totalPaths,
      totalPointsWithRedundancy,
      totalPointsToRemove,
      totalPointsRemoved,
      totalPointsStarting,
      totalPointsRemaining,
      totalPointsSelected,
      tolerance);
    catch(er)
      if (exitError == 2) {
      alert("Select function not supported in conjunction with 'Include Locked Items' option.");
      if (exitError == 3) {
      alert("Select function supported only with 'Ignore' selection restriction.");
      if (exitError == 99) {
      alert("ACK! Unexplained error\n");
    * Dialog Code
    * Function: doInitDialog
    function doInitDialog(dlgInit) {
      var defaultTolerance = 5.0;
      var maxSliderTolerance = 5;
      /* Add radio buttons to control functionality */
      dlgInit.functionPnl = dlgInit.add('panel', undefined, 'Function:');
      (dlgInit.functionPnl.doAnalyze = dlgInit.functionPnl.add('radiobutton', undefined, 'Analyze' )).helpTip = "Find and count redundant points.";
      (dlgInit.functionPnl.doRemove = dlgInit.functionPnl.add('radiobutton', undefined, 'Remove' )).helpTip = "Find and remove redundant points.";
      (dlgInit.functionPnl.doSelect = dlgInit.functionPnl.add('radiobutton', undefined, 'Select' )).helpTip = "Find and select redundant points.\nWARNING:Manual removal of selected redundant points can change the shape of your curves.\nTips:Hiding bounding box helps to see which points are selected. Modify selection as desired and rerun script to remove specific redundant points.";
      dlgInit.functionPnl.doRemove.value = true;
      dlgInit.functionPnl.orientation='row';
      /* Add radio buttons to control point selection */
      dlgInit.selectionPnl = dlgInit.add('panel', undefined, 'Point Selection State:');
      (dlgInit.selectionPnl.ignoreSelected = dlgInit.selectionPnl.add('radiobutton', undefined, 'Ignore')).helpTip="Process redundant points on a path regardless of their selection state.";
      (dlgInit.selectionPnl.allSelected = dlgInit.selectionPnl.add('radiobutton', undefined, 'All')).helpTip="Process redundant points on a path only if each of them is selected.";
      (dlgInit.selectionPnl.anySelected = dlgInit.selectionPnl.add('radiobutton', undefined, 'Any')).helpTip="Process redundant points on a path if any one of them is selected.";
      dlgInit.selectionPnl.allSelected.value = true;
      dlgInit.selectionPnl.orientation='row';
      /* Add a checkbox to control options */
      dlgInit.optionPnl = dlgInit.add('panel', undefined, 'Other Options:');
      (dlgInit.optionPnl.includeCompound = dlgInit.optionPnl.add('checkbox', undefined, 'Include Compound Path Items?')).helpTip="Work on compound path items.";
      (dlgInit.optionPnl.includeLocked = dlgInit.optionPnl.add('checkbox', undefined, 'Include Locked Items?')).helpTip="Work on locked items or items in locked layers.";
      dlgInit.optionPnl.includeCompound.value = true;
      dlgInit.optionPnl.includeLocked.value = false;
      dlgInit.optionPnl.alignChildren='left';
      dlgInit.optionPnl.orientation='column';
      /* Add a slider and edit box for user entered tolerance */
      dlgInit.tolerancePnl = dlgInit.add('panel', undefined, 'Tolerance (in PostScript points):');
      (dlgInit.tolerancePnl.slide = dlgInit.tolerancePnl.add('slider', undefined, defaultTolerance, 0.01, maxSliderTolerance)).helpTip="Use slider to set a tolerance value in hundredths of a point.";
      (dlgInit.tolerancePnl.editText = dlgInit.tolerancePnl.add('edittext', undefined, defaultTolerance)).helpTip="Enter a tolerance value. Values greater then 5.0 or more precise than 1/100 point can be manually entered here.";
      dlgInit.tolerancePnl.editText.characters = 5;
      dlgInit.tolerancePnl.orientation='row';
      dlgInit.tolerancePnl.slide.onChange = toleranceSliderChanged;
      dlgInit.tolerancePnl.editText.onChange = toleranceEditTextChanged;
      /* Add a panel control removal options */
      dlgInit.removalPnl = dlgInit.add('panel', undefined, 'Removal Options:');
      (dlgInit.removalPnl.doKeepLeadingPoint = dlgInit.removalPnl.add('checkbox', undefined, 'Keep Leading Point' )).helpTip = "Keep the leading point (lowest path index, lowest prior to origin cross for closed path).";
      (dlgInit.removalPnl.doKeepTrailingPoint = dlgInit.removalPnl.add('checkbox', undefined, 'Keep Trailing Point' )).helpTip = "Keep the trailing point (highest path index, highest following origin cross for closed path).";
      (dlgInit.removalPnl.doKeepAveragedPoint = dlgInit.removalPnl.add('checkbox', undefined, 'Keep Averaged Point' )).helpTip = "Keep an averaged point to help smooth transitions.";
      dlgInit.removalPnl.keepTips = dlgInit.removalPnl.add('statictext', undefined, 'Keeping neither will cause position of remaining point to be averaged. Keeping both will anchor two ends of a segment while removing intermediate redundant points. An averaged point helps smooth transitions.', {multiline:'true'} );
      dlgInit.removalPnl.doKeepLeadingPoint.value = false;
      dlgInit.removalPnl.doKeepTrailingPoint.value = false;
      dlgInit.removalPnl.doKeepAveragedPoint.value = false;
      dlgInit.removalPnl.alignChildren='left';
      dlgInit.removalPnl.orientation='column';
      /* Add execution buttons */
      dlgInit.executeGrp = dlgInit.add('group', undefined, 'Execute:');
      dlgInit.executeGrp.orientation='row';
      dlgInit.executeGrp.buildBtn1= dlgInit.executeGrp.add('button',undefined, 'Cancel', {name:'cancel'});
      dlgInit.executeGrp.buildBtn2 = dlgInit.executeGrp.add('button', undefined, 'OK', {name:'ok'});
      dlgInit.executeGrp.buildBtn1.onClick= initActionCanceled;
      dlgInit.executeGrp.buildBtn2.onClick= initActionOk;
      dlgInit.frameLocation = [100, 100];
      dlgInit.alignChildren='fill';
      dlgInit.show();
      return dlgInit;
    function initActionCanceled() {
      exitError = 1;
      dlgInit.hide();
    function initActionOk() {
      var proceed = true;
      exitError = 0;
      if (dlgInit.tolerancePnl.editText.text > 5.0) {
      proceed = confirm("Tolerance entered greater than 5.0 PostScript points. Proceed?");
      if (proceed) {
      dlgInit.hide();
    function toleranceSliderChanged() {
      dlgInit.tolerancePnl.editText.text = roundToPrecision(dlgInit.tolerancePnl.slide.value, 0.01);
    function toleranceEditTextChanged() {
      if (dlgInit.tolerancePnl.editText.text > 5000) {
      dlgInit.tolerancePnl.editText.text = 5000;
      dlgInit.tolerancePnl.slide.value = roundToPrecision(dlgInit.tolerancePnl.editText.text, 0.01);
    * Function: doResultsDialog
    function doResultsDialog(dlgResults,
      totalPaths,
      totalPointsWithRedundancy,
      totalPointsToRemove,
      totalPointsRemoved,
      totalPointsStarting,
      totalPointsRemaining,
      totalPointsSelected,
      tolerance) {
      /* Add static text to display results */
      dlgResults.resultsPnl = dlgResults.add('panel', undefined, 'Results:');
      dlgResults.resultsPnl.totalPaths = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPaths.txt = dlgResults.resultsPnl.totalPaths.add('statictext', undefined, 'Paths processed: ');
      dlgResults.resultsPnl.totalPaths.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPaths.val = dlgResults.resultsPnl.totalPaths.add('statictext', undefined, totalPaths);
      dlgResults.resultsPnl.totalPaths.val.characters = 10;
      dlgResults.resultsPnl.totalPaths.val.helpTip = "The number of paths processed.";
      dlgResults.resultsPnl.totalPointsSelected = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPointsSelected.txt = dlgResults.resultsPnl.totalPointsSelected.add('statictext', undefined, 'Total points selected: ');
      dlgResults.resultsPnl.totalPointsSelected.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPointsSelected.val = dlgResults.resultsPnl.totalPointsSelected.add('statictext', undefined, totalPointsSelected);
      dlgResults.resultsPnl.totalPointsSelected.val.characters = 10;
      dlgResults.resultsPnl.totalPointsSelected.val.helpTip = "The total number of points initially selected.";
      dlgResults.resultsPnl.separator0 = dlgResults.resultsPnl.add('panel');
      dlgResults.resultsPnl.totalPointsWithRedundancy = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPointsWithRedundancy.txt = dlgResults.resultsPnl.totalPointsWithRedundancy.add('statictext', undefined, 'Points with redundancy: ');
      dlgResults.resultsPnl.totalPointsWithRedundancy.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPointsWithRedundancy.val = dlgResults.resultsPnl.totalPointsWithRedundancy.add('statictext', undefined, totalPointsWithRedundancy);
      dlgResults.resultsPnl.totalPointsWithRedundancy.val.characters = 10;
      dlgResults.resultsPnl.totalPointsWithRedundancy.val.helpTip = "The number of points with redundancy.";
      dlgResults.resultsPnl.totalPointsToRemove = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPointsToRemove.txt = dlgResults.resultsPnl.totalPointsToRemove.add('statictext', undefined, 'Redundant points to remove: ');
      dlgResults.resultsPnl.totalPointsToRemove.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPointsToRemove.val = dlgResults.resultsPnl.totalPointsToRemove.add('statictext', undefined, totalPointsToRemove);
      dlgResults.resultsPnl.totalPointsToRemove.val.characters = 10;
      dlgResults.resultsPnl.totalPointsToRemove.val.helpTip = "The number of redundant points that would be removed.";
      dlgResults.resultsPnl.totalPointsRemoved = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPointsRemoved.txt = dlgResults.resultsPnl.totalPointsRemoved.add('statictext', undefined, 'Redundant points removed: ');
      dlgResults.resultsPnl.totalPointsRemoved.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPointsRemoved.val = dlgResults.resultsPnl.totalPointsRemoved.add('statictext', undefined, totalPointsRemoved);
      dlgResults.resultsPnl.totalPointsRemoved.val.characters = 10;
      dlgResults.resultsPnl.totalPointsRemoved.val.helpTip = "The number of redundant points that were removed.";
      dlgResults.resultsPnl.separator1 = dlgResults.resultsPnl.add('panel');
      dlgResults.resultsPnl.totalPointsStarting = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPointsStarting.txt = dlgResults.resultsPnl.totalPointsStarting.add('statictext', undefined, 'Total points starting: ');
      dlgResults.resultsPnl.totalPointsStarting.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPointsStarting.val = dlgResults.resultsPnl.totalPointsStarting.add('statictext', undefined, totalPointsStarting);
      dlgResults.resultsPnl.totalPointsStarting.val.characters = 10;
      dlgResults.resultsPnl.totalPointsStarting.helpTip = "The total number of points before processing.";
      dlgResults.resultsPnl.totalPointsRemaining = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPointsRemaining.txt = dlgResults.resultsPnl.totalPointsRemaining.add('statictext', undefined, 'Total points remaining: ');
      dlgResults.resultsPnl.totalPointsRemaining.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPointsRemaining.val = dlgResults.resultsPnl.totalPointsRemaining.add('statictext', undefined, totalPointsRemaining);
      dlgResults.resultsPnl.totalPointsRemaining.val.characters = 10;
      dlgResults.resultsPnl.totalPointsRemaining.val.helpTip = "The total number of points after processing.";
      dlgResults.resultsPnl.alignChildren='right';
      dlgResults.resultsPnl.orientation='column';
      dlgResults.note = dlgResults.add('group');
      dlgResults.note.txt = dlgResults.note.add('statictext', undefined, 'Combined results across paths qualified based on options');
      dlgResults.tolerance = dlgResults.add('group');
      dlgResults.tolerance.txt = dlgResults.tolerance.add('statictext', undefined, "Tolerance applied (in PostScript points): ");
      dlgResults.tolerance.val = dlgResults.tolerance.add('statictext', undefined, tolerance);
      /* Add execution buttons */
      dlgResults.executeGrp = dlgResults.add('group', undefined, 'Execute:');
      dlgResults.executeGrp.orientation='row';
      dlgResults.executeGrp.buildBtn1= dlgResults.executeGrp.add('button',undefined, 'OK', {name:'ok'});
      dlgResults.executeGrp.buildBtn1.onClick= resultsActionOk;
      dlgResults.frameLocation = [100, 100];
      dlgResults.show();
    function resultsActionOk() {
      exitError = 0;
      dlgResults.hide();

    you have said you are using cc.
    is it fully up to date?
    are you not using cc2014?
    when run from ESTK are you sure it is pointing to the correct illustrator?

  • Is there a way to: Export images from DICOM media into Illustrator?

    I am trying to find a way to automatically import sets of images from DICOM media (Digital Imaging and Communications in Medicine) into Illustrator. To be more specific I need to load up about 20 heart-slice images from DICOM CDs or any other type of archival systems into Illustrator.
    These MRI DICOM clips show slices of the heart pulsating in systole (when the heart is the smallest ) and diastole (when the heart is largest) and phases in-between (systole and diastole are two time phases of the heart cycle, represented by time numbers), at various topographical locations (these would represented by slice numbers, or space numbers).  I would like to be able to input the number of the slices (space numbers) in systole and diastole (time numbers) and then with the push of a button to import the respective jpeg images into Illustrator.
    This thread is related to a previous one “Is there a way to calculate the area of a shape?”
    I would greatly appreciate the help.
    Avi

    I played a little with live trace in CS5. Seems to do quite a good job if I had the right contrast between the blood (white stuff) and the myocardium (the dark circular wall surrounding the white round area). Picture one is the contrasted picture taken off a dicom medium (these media allow adjusting the contrast very well). Left ventricle is the smiley face on the right of image. The right ventricle is on the left, kind of D shaped. The second picture is the live trace image (with "make and expand" selection). I selected the image with the "direct selection tool (A)", then used the live trace with make and expand. The tracing can not be seen here, but it is very accurate.
    The third image is the same MRI image as in picture one without contrast adjustment. Live trace did bad - fourth picture.

  • How to type text in a circular shape around an image without warping it?

    I'm an intermediate user of Photoshop.  I've unsuccessfully wrapped text in a circular shape without distorting it.  The 'warp text' feature is does to achieve the appearance I seek. If possible, what are the steps to successfully do it in Photoshop.
    Thanks in Advance!

    To create a ring of type as seen in Fig. 6:
    1. Open a new file (File > New) with the same height as its width, perhaps ten inches square and then type the sentence that is to create the circle (Fig. 1)
    2. Converting the type line to a circle reduces its height. To compensate for that, choose Edit > Transform > Scale. Drag the type to about twice its height (Fig. 2)
    3. Choose the Move tool and shift the type line close to – but not touching – the left edge. (Fig 3)
    4. Choose the Crop tool. In the Options bar change Unconstained to 1 x 1 (Square). Then drag the right corner handle of the Crop diagonally until there is a one-letter space between the last letter of the type line and the right edge of the square. (Fig. 4)   OK
    5. Center the line vertically. (Fig 5)
    6. Choose Select > All. Then, choose Filter > Distort > Polar Coordinates. Rasterize the type when asked. Radio button should be set to Rectangular to Polar. To preview the image, adjust the percent listed below the inset illustration. Click OK. The result: Fig 6
    7. Choose Select > Deselect and, for final housekeeping, choose the Crop tool and return the Options bar to Unconstrained.
    8. Save the file in psd format so that the circle of type remains on a transparent surround and the layer may be floated onto another image.
    Remember: A rasterized image will lose sharpness with enlargement. It would be prudent to use the circle of type at same size or smaller.

  • How do I remove a shadow in Illustrator CS4?

    Hi,
    I need to take a shadow off a vector graphic in Illustrator CS4, is there a way of doing this?
    Many thanks,

    First try this. Select the small circular art on the left side and delete it. If you cannot use the lasso tool to just select that then use the layers panel to select the art and the delete it.
    Once deleted select your art and see if it reads in the Appearance panel as a group and if the groups has the effect applied to it.
    if so delete the drop shadow effect.
    If not open the layers  and elect the layer the art is one go back the appearance panle to see if it now lists the layer as the top item and see if the effect is applied to the layer if so select it and then delete it.
    if none of that works then use the direct select tool and select each elemental path, one at a time and delete the drop shadow effect using the appearance panel.
    One of these methods will work. Unless the drop shadow is actually a filter and not an effect. In that event use the direct select tool to select the select the shadow on the canvas and then delete it.

  • Drawing "wires" in Illustrator CS4?

    I have tried using Photoshop to tidy-up a scanned wiring diagram saved as a TIFF. The diagram consists of many (almost) vertical and horizontal lines (the wires) which I want to straighten and color. Some wires are two colors, so the lines need to be banded or striped in some way.
    I have never used Illustrator, but in this thread it emerged that it was the better tool for the job (there are sample images there).
    Any suggestions on how best to accomplish my task?

    Look at the online help for the basics of:
    Drawing paths and assigning strokes to them.
    Appearance Palette's Add Stroke and Add Fill commands. Understand that youi can apply more than one stroke and/or fill to a single path.
    Pattern Brushes.
    Graphic Styles.
    For wiring diagrams, use the ability to apply multiple strokes to a single path. Each stroke can have its own weight. For the diagonal stripes, use a PatternBrush, and make the PatternBrush one of the multiple strokes applied to a path. Store such combinations as Graphic Styles so they can be applied to other paths with one click.
    The sample below shows a set of Pattern Brushes I use for wiring in isometric illustrations, but the principle is the same. The Brushes would work fine for flat schematics.  Wires like 2 and 5 would not require using Brushes; they could be done by simply applying two strokes to a path in the Appearnace palette. (They are Brushes in my sample, in order to include the terminal ends.)
    Wire 4 is an example of using a Brush to create a stripe. The wire has two strokes, with a different Brush applied to each. The top stroke has the stripe Brush applied; the bottom stroke has the simple shaded Brush (with trimmed insulation ends) applied. Again, the bottom Brush would not be necessary if it were not for my intent to include the trimmed ends. In a schematic, that wire could be done with a set of three strokes: A thick stroke at the bottom to create the outer edge color; a middle stroke somewhat narrower to create the middle color; and a top stroke with the spiral stripe Brush applied.
    ...it emerged that it was the better tool for the job...
    Yes. Please don't use Photoshop for wiring diagrams. Such diagrams need to be resolution-independent vector artwork. Think of your downstream users. Wiring schematics often become large and complex, requiring large sheets with relatively small text. A nice PDF containing vector artwork can be zoomed indefinitely to trace a circuit with legible text; and the file size is usually much smaller than if it were a large raster image. (Tech illustrators hate it when technical drawings like schematics default to a dumbed-down raster format. Just makes it a royal pain to work with and modify.)
    JET

  • Animation in illustrator cs4: pan & rotate across large image while animating text?

    Hi there -
    I have a fairly large circular starmap image - it's a fantasy piece simulating an ancient painted star map with stars, ancient constellation figures, and calligraphic text. Basically a bitmap background from PShop, vector layers with stars, constellations and text. I want to export from Illustrator to Flash a number of short 'movies' of different views of this artwork panning from one point to another with possible zoom and rotation around the image as it pans. I also want to animate one or more of the constellation shapes as the movie pans, as well as adding momentary effects to some of the text.
    I'm familiar with setting up a non-panning animation in illustrator using layers as animation 'cells' and exporting to Flash. But is it possible to do this while moving across a large piece of artwork? How can I capture and export a specific 'view' which moves across the larger image and/or zooms in or out, while also animating a shape or text glow for example? Would this be accomplished with a mask set to the aspect ratio of the final movie which is moved/resized/rotated from layer to layer?
    Is this even possible in Illustrator CS4? I'm not familiar with Premier or AE, hoping to stay within Illy and Flash.
    Thanks!

    Thanks Monica,
    After researching, it looks like Sony Vegas can be used to create a freeflowing video 'fly-over' of the artwork. And then at specific points I can import and animate the Illustrator vector pieces with After Effects - just a 'bit' of a learning curve now...

  • Missing tools in Illustrator cs4

    hey,
    This problem is driving me crazy. I have Adobe Illustrator cs4 installed (win.Vista), it runs o.k but I'm missing a lot of tools- I get all the main tool groups but the groups wont open` so I have the line tool but not arc or spiral, I have warp tool but not twirl or bloat, text area but not text path and so on.
    I have tried redirecting to plugins>tools via the edit>preferences>plug-ins and scratch disks dialog, but then when I load the software I get an error notice saying that some of the plug-ins conflict with... and it doesn't work. I've also tried deleting the AIpref. file from appdata but that didn't help.
    What am I missing? this situation consumes too much of my time and sanity!
    thanx

    Let me ask a question, are you launching AI from an alias located on your desktop? Another Question did you move the Illustrator folder out of the Illustrator application folder and perhaps to a place where you could more easily launch it?
    An alias is a copy of the icon of a folder or directory of fie that links it to the original and looks like the actual originl.
    The aliases you know are My  Computer, Internet Explorer, Documents etc that you find commonly on a PCs desktop.
    This is the scenario that often takes place on a mac and probably would cause the same problem on a PC.
    Instead of creating the alias to use as a link to launch the application you either copied the application it self or you moved it to the desktop.
    What that means is that some essential links between the application are now broken such as some of the tools and menu items that reside in the Applications folders such as filters and effects, file formats and extensions.So they are not showing.
    The way to fix this is either move the application back to to the Illustrator folder and read about how to make an alias or just launch it from the Start menu or delete the copy if you have a copy of the application on the desktop and again either make a proper alias or launch from the Start menu.
    I do not know how this might effect the preferences on a PC but on the Mac it sometimes corrupts the preferences and they have to be trashed as well as correcting the problem.
    Having written all of this there was another way this can manifest itself on both a Mac and PC and you might do a google search if what I describe above does not apply to you.
    It was actually posted here about four or five months ago and it involved deleting a file.

Maybe you are looking for

  • Maximum Bitrate/Sample Rate?

    What is the maximum bitrate and sample rate(44.1/48k) that can be read by my iPod? Does it depend on whether I use mp3 or aac encoding? Can I use variable bit rate (VBR)? If I can use a 48k sample rate, would that mean using a smaller bitrate?

  • URGENT (sql query not execute)

    Hi Forum i made an application which run on JRun server. In many of my jsps i used sql query like this: " select id, name, rollno from student where add = 'jj';" and retrieve the record from resultset like this: rs.getString("id"); rs.getString("name

  • CIF of single item material master

    Is it possible to CIF single item material master (like single PPM can be CIF by R/3 transaction CFP3.) Regards, Chetan

  • Location Service in security and privacy preference pane not saved

    Hi, When I want to activate the location service inside the security and privacy preference pane, it is not save. I can check the box but if I leave the pref pane, and come back, it is still uncheck. I notice that when I wanted to activate the icloud

  • PCR fors - Request for separation

    Hi All, Version: ERP 2005 , MSS BP 1.0 We are using the standard delivered "Request for separation" PCR form in MSS. the drop down for the reasons for separation does not display  anything. These reasons are configured in the IMG and can be seen in R