Atan2

i have no clue how to use this function. i'm trying to code the math for potential fields for a bot program for a class and the potential field write up i'm basing my math off uses the atan2 because it gives the correct angle of the quadrant.
"Find the angle between the agent and the goal 'angle' = arctan(dy/dx). (I use the atan2 function
because it gives you the angle in the correct quadrant.)"
but have no clue how to call the atan2 on this because atan2 requires two doubles, not one like atan. the api for atan2 didn't help either. any help is appreciated.
the write up on potential fields is here:
http://cs.boisestate.edu/~tim/courses/fall08/225/potentialfields/PfieldsTutorial.pdf

darkambivalence wrote:
overrule... wrote:
darkambivalence wrote:
lol. i'm retarded. thanks. is there a way i can mark both posts correct? i want you guys to get some sort or credit or something for wasting your time with this stupid question. lol.Well, the only requirement is that you kiss my feet. I'll wash them of course.
And then that you reveal the company you work for. And where you get your paycheck from. And if you please explain why we should do for free what you're getting paid to do.except you didn't help me. and this is for a class, so i'm not getting paid for it. no one is required to help me. but i appreciate those that do.What class? I want to know the level of university stupidity I'm helping out at.
And you still have to kiss my feet.

Similar Messages

  • Problem using atan2 function

    Hi everyone, I'm developing an application that needs to calculate the angle between two vectors. While this is fairly simple, you just need to use the Math.atan2() function, i am having a few problems.
    Here's a code snippet:
    alpha = (Math.atan2((tx*ry)-(rx*ty), (tx*rx)+(ty*ry)) % (2*Math.PI)) ;Strangely enough, this gives me the following error: "The method atan2(double, double) is undefined for type Math"
    This should only occur if the method atan2 weren't implemented in the Math library.. but from the javadoc and the GIS it definitively is!
    I'm confused and stuck, any ideas? (i'm using jdk 1.6.0_07)

    This is a GWT application and therefore the rest of the code doesn't matters. I'll post it anyway, but if i take that simple line using the atan2, i can run the gwt application without problems nor errors. If i use the atan2 it doesn't presents any error in the IDE, but when i try to run the GWT application, it gives me exactly the error described previously:
    " The method atan2(double, double) is undefined for the type Math"
    Here's the code:
    /* the mouse vector 1 */
                tx = x - aux_obj.getCenterX();
                ty = y - aux_obj.getCenterY();
                /* the rotation vector. i.e. the fixed vector that will be used as origin composed by the subtraction of the object center with the rotation point */
                rx = lastPosition[0] - aux_obj.getCenterX();
                ry = lastPosition[1] - aux_obj.getCenterY();
                lenght = Math.sqrt((tx*tx) + (ty*ty));
                tx = tx / lenght;
                ty = ty / lenght;
                lenght = Math.sqrt((rx*rx) + (ry*ry));
                rx = rx / lenght;
                ry = ry / lenght;
                alpha = (java.lang.Math.atan2((tx*ry)-(rx*ty), (tx*rx)+(ty*ry)) % (2*Math.PI)) ;
                Window.alert("alpha:"+alpha);I think there's no big reason why this shouldn't work.. maybe it's the gwt library that doesn't finds the math class when it's trying to compile the java code..

  • Atan2 equivalent in a Formula Node?

    Does anyone have an atan2 (2-input inverse arctangent) equivalent for use in a Formula Node? I was surprised to see that such a common function wasn't supported in Formula Nodes. Without it, my easily readable Formula Node equations get junked and become a nightmare of LabVIEW math symbols. Is there a way to call the atan2 VI (or any other VI for that matter) from within a Formula Node?

    Hello,
    You are correct, this function is not supported in Formula Nodes, and there is not a way to call VIs from formula nodes. However, the below solution might be what you need:
    Is this the correct definition of atan2:
    if y = atan2(a,b), then tan(y) = (a/b)
    If so, could we define a and b, and use the formula node function atan(a/b)? This may not be the most elegant solution, but it seems like it would do the trick with minimal headache. I attached a VI showing this idea.
    Hope this helps!
    Liz Fausak
    National Instruments
    Attachments:
    atan2FNode.vi ‏10 KB
    61atan2FNode.vi ‏10 KB
    60atan2FNode.vi ‏8 KB

  • ATAN2  geometric function and pasing DECFLOAT34 in Sin, cos and Tan.

    Hello,
    1) Is there any macro,Function module  or any way to use atan2 is a variation of the arctangent function in ABAP
    atan2 is available in C, C++, java but i don't seem to find it in ABAP.
    Further details : --- http://en.wikipedia.org/wiki/Atan2
    2) The current limitation for Sin , Cos and tan  geometric functions is Float.
    I am looking for a way to pass a double (DECFLOAT34) into SIn or Cos.
    I do not want to lose the accuracy by using Float.
    Can this be done ?
    Regards,
    Ajay Kulkarni

    Hello Alvaro,
    I have written the following code for atan2 accordingly but it is not as accurate as i wan't it to be.
    The results are not accurate.
    Regards,
    Ajay K
    method ATAN2.
      DATA :
           xsqr TYPE DECFLOAT34,
           ysqr TYPE DECFLOAT34,
           xysqr TYPE DECFLOAT34,
           xysqrt TYPE DECFLOAT34,
           tempa TYPE DECFLOAT34,
           tempb TYPE DECFLOAT34,
           tempc TYPE DECFLOAT34,
           x TYPE DECFLOAT34,
           y TYPE DECFLOAT34,
           atan2 TYPE f.
      data tempb_float TYPE f.
      data tempd_float TYPE f.
    x = iv_x.
    y = iv_y.
    if x = 0 and y = 0.
    ans not defined
    ELSE.
        xsqr = x * x .
        ysqr = y * y .
        xysqr = xsqr + ysqr.
        xysqrt = sqrt( xysqr ).
        tempa = xysqrt - x.
        tempb = tempa / y .
        tempb_float = tempb.
        tempd_float = atan( tempb_float ).
        tempc = 2 * tempd_float.
        ev_atan2 = tempc.
    ENDIF.
    endmethod.

  • How to Calculate the angle of gradient? With atan2()????

    Hi,
    my Problem is I have 2 Points and I have to calculate the angle of gradient of the line between those two points.
    I tried it like this:
    Point2D.Double p = new Point2D.Double(5.0,4.0),                               q = new Point2D.Double(2.0,2.0);          
         double angle = Math.atan2((p.y - q.y), (p.x - q.x));
         double calc=Math.toDegrees(angle);
         System.out.println("calc: "+calc);
    but if I switching the values of the two points the Result is a other but I need a Method that returns me always the angle of gradient.
    Can anyone help me?
    Thanks

    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    import java.text.*;
    import javax.swing.*;
    public class TrigTest
        public static void main(String[] args)
            TrigPanel trigPanel = new TrigPanel();
            JFrame f = new JFrame("Click on the panel");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.getContentPane().add(trigPanel.getTopPanel(), "North");
            f.getContentPane().add(trigPanel);
            f.getContentPane().add(trigPanel.getBottomPanel(), "South");
            f.setSize(400,300);
            f.setLocation(400,300);
            f.setVisible(true);
    class TrigPanel extends JPanel
        Point originP, endP;
        double degrees;
        JLabel
            slopeLabel,       // slope = rise/run
            angleLabel,       // anti-clockwise angle from abcissa (3 o'clock)
            relativeLabel;    // angle relative to horizontal
        NumberFormat nf;
        public TrigPanel()
            originP = new Point();
            endP = new Point();
            nf = NumberFormat.getInstance();
            nf.setMaximumFractionDigits(1);
            setBackground(Color.white);
            addMouseListener(new PointSelector());
        public void paintComponent(Graphics g)
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                RenderingHints.VALUE_ANTIALIAS_ON);
            int width = getWidth();
            int height = getHeight();
            int dia = Math.min(width, height)*3/5;
            originP.x = width/2;
            originP.y = height/2;
            // abcissa
            g2.draw(new Line2D.Double(originP.x, originP.y, width*4/5, originP.y));
            // line from origin to selected point
            g2.draw(new Line2D.Double(originP, endP));
            // angle arc from abcissa to selected line
            Ellipse2D e = new Ellipse2D.Double(originP.x - dia/2,
                                               originP.y - dia/2,
                                               dia, dia);
            g2.draw(new Arc2D.Double(e.getBounds(), 0, degrees, Arc2D.OPEN));
            // arrow head
            if(degrees > 10)
                double x = originP.x + (dia/2)*Math.cos(Math.toRadians(degrees));
                double y = originP.y - (dia/2)*Math.sin(Math.toRadians(degrees));
                //g2.fill(new Ellipse2D.Double(x - 1, y - 1, 2, 2));  // tip marker
                double x1 = x + 5*Math.cos(Math.toRadians(degrees - 60));
                double y1 = y - 5*Math.sin(Math.toRadians(degrees - 60));
                double x2 = x + 5*Math.cos(Math.toRadians(degrees - 120));
                double y2 = y - 5*Math.sin(Math.toRadians(degrees - 120));
                g2.draw(new Line2D.Double(x, y, x1, y1));
                g2.draw(new Line2D.Double(x, y, x2, y2));
            // origin
            g2.setPaint(Color.red);
            g2.fill(new Ellipse2D.Double(originP.x - 1, originP.y - 1, 2, 2));
        private class PointSelector extends MouseAdapter
            public PointSelector()
                endP = originP;
            public void mousePressed(MouseEvent e)
                endP = e.getPoint();
                computeSlope();
                computeAngles();
                repaint();
        private void computeSlope()
            double deltaY = endP.y - originP.y;
            double deltaX = originP.x - endP.x;
            double slope = deltaY / deltaX;
            slopeLabel.setText(nf.format(slope));
        private void computeAngles()
            double y = originP.y - endP.y;
            double x = endP.x - originP.x;
            // angle from abcissa
            double atan2 = Math.atan2(y, x);
            degrees = Math.toDegrees(atan2);
            if(degrees < 0)
                degrees += 360;
            angleLabel.setText(nf.format(degrees));
            // angle relative to horizontal - unsigned
            double atan = Math.atan(y/x);
            double relative = Math.abs(Math.toDegrees(atan));
            relativeLabel.setText(nf.format(relative));
        public JPanel getTopPanel()
            slopeLabel = new JLabel("");
            angleLabel = new JLabel("");
            setLabelSize(slopeLabel);
            setLabelSize(angleLabel);
            JPanel panel = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(2,2,2,2);
            gbc.weightx = 1.0;
            addLabels(new JLabel("slope"), slopeLabel, panel, gbc);
            addLabels(new JLabel("angle"), angleLabel, panel, gbc);
            return panel;
        public JPanel getBottomPanel()
            relativeLabel = new JLabel("");
            setLabelSize(relativeLabel);
            JPanel panel = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(2,2,2,2);
            addLabels(new JLabel("angle relative to horizontal"),
                                  relativeLabel, panel, gbc);
            return panel;
        private void setLabelSize(JLabel label)
            label.setPreferredSize(new Dimension(50, 25));
        private void addLabels(JLabel label1, JLabel label2,
                               JPanel panel, GridBagConstraints gbc)
            gbc.anchor = gbc.EAST;
            panel.add(label1, gbc);
            gbc.anchor = gbc.WEST;
            panel.add(label2, gbc);
    }

  • ATAN2 CORE in LabVIEW?

    I am just about to use LabVIEW FPGA for the first time and in the intended application I will need to implement a function that approximates to the ATAN2(a,b) function.
    I know that I could use an IP CORE and insert into a HDL Node, but since I dont understand VHDL and I like to understand what is going on in my code I would prefer to write the function in LabVIEW.
    Does anyone have or know of an ATAN2 function that has been implemented in LabVIEW for FPGA targets.
    I am using LV 8.0 with FPGA module 8.0. The hardware taget is PCI 7831R.
    Thanks in Advance
    Simon Pettman
    Dynamic Engineering System Architects

    The only thing I have found that might be implemented is a summation function
    for x^2 < 1
    atan(x) = x- (x^3/3) + (x^5/5) - (x^7/7) + ...
    for x>1
    atan(x) = pi/2 - 1/x + (1/(3x^3)) - (1/(5x^5)) + (1/(7x^7)) - ...
    for x<-1
    atan(x) = -pi/2 - 1/x + (1/(3x^3)) - (1/(5x^5)) + (1/(7x^7)) - ...
    Randall Pursley

  • Math.atan2 Code Explanation Help

    Hello guys
    This is a piece of code from AS3 Making Things Move
    I tried to understand how this code works, but failed
    Please explain this code
    Thanks in advance

    There are two fetches to deal with the no records found situation.
    the basic idea is
    fetch
    while found loop
    ... do some processing ...
    fetch
    end loop
    If the first fetch doesn't result in a record the loop is not being executed,inside the loop the %notfound situation doesn't have to be trapped anymore.
    This is why the if inside the loop is redundant.
    Other than that this code is an example of slow by slow processing, introducing 3GL techniques, processing records, instead of SETS.
    The person responsible for this code ought to be fired.
    Sybrand Bakker
    Senior Oracle DBA

  • 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?

  • How can I get  the part image from a rectangle region?

    hi,
    I'm trying to draw a rectagle region on a picture with mouse and crop it. but the rectangle is not vertical along x-axis.that is to say, there is a angle between x-axis and the base of the rectangle. I don't know , how can I do it. Can someone give me some tip or some java-code. Thank you very much in advance.

    I completely misunderstood your question. As I read it again it seems clear and straight-forward. I'm sorry. Let's see if this is closer.
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    import java.awt.image.BufferedImage;
    import java.io.*;
    import java.net.*;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    import javax.swing.event.MouseInputAdapter;
    public class CropImage
        BufferedImage original;
        CropPanel cropPanel;
        CropSelector selector;
        public CropImage()
            original = getImage();
            cropPanel = new CropPanel(original);
            selector = new CropSelector(cropPanel);
            cropPanel.addMouseListener(selector);
            cropPanel.addMouseMotionListener(selector);
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.getContentPane().add(getUIPanel(), "North");
            f.getContentPane().add(new JScrollPane(cropPanel));
            f.setSize(400,400);
            f.setLocation(200,200);
            f.setVisible(true);
        private BufferedImage getImage()
            String fileName = "images/coyote.jpg";
            BufferedImage image = null;
            try
                URL url = getClass().getResource(fileName);
                image = ImageIO.read(url);
            catch(MalformedURLException mue)
                System.err.println("url: " + mue.getMessage());
            catch(IOException ioe)
                System.err.println("read: " + ioe.getMessage());
            return image;
        private JPanel getUIPanel()
            final JButton
                mask    = new JButton("mask"),
                crop    = new JButton("crop"),
                restore = new JButton("restore");
            ActionListener l = new ActionListener()
                public void actionPerformed(ActionEvent e)
                    JButton button = (JButton)e.getSource();
                    if(button == mask)
                        selector.mask();
                    if(button == crop)
                        selector.crop();
                    if(button == restore)
                        cropPanel.restore(original);
            mask.addActionListener(l);
            crop.addActionListener(l);
            restore.addActionListener(l);
            JPanel panel = new JPanel();
            panel.add(mask);
            panel.add(crop);
            panel.add(restore);
            return panel;
        public static void main(String[] args)
            new CropImage();
    class CropPanel extends JPanel
        BufferedImage image;
        Dimension size;
        GeneralPath clip;
        Point[] corners;
        Area mask;
        boolean showMask;
        Color bgColor;
        public CropPanel(BufferedImage bi)
            image = bi;
            setSize();
            clip = new GeneralPath();
            showMask = false;
            bgColor = getBackground();
        protected void paintComponent(Graphics g)
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                RenderingHints.VALUE_ANTIALIAS_ON);
            int w = getWidth();
            int h = getHeight();
            int x = (w - size.width)/2;
            int y = (h - size.height)/2;
            g2.drawImage(image, x, y, this);
            if(showMask)
                g2.setPaint(getBackground());
                g2.fill(mask);
            else
                g2.setPaint(Color.red);
                g2.draw(clip);
        public Dimension getPreferredSize()
            return size;
        public void setClip(Point[] p)
            corners = p;
            clip.reset();
            clip.moveTo(p[0].x, p[0].y);
            clip.lineTo(p[1].x, p[1].y);
            clip.lineTo(p[2].x, p[2].y);
            clip.lineTo(p[3].x, p[3].y);
            clip.closePath();
            repaint();
        public void clearClip()
            clip.reset();
            repaint();
        public void setMask(Area area)
            mask = area;
            showMask = true;
            repaint();
        public void setImage(BufferedImage image)
            this.image = image;
            setSize();
            showMask = false;
            clip.reset();
            repaint();
            revalidate();
        public void restore(BufferedImage image)
            setBackground(bgColor);
            setImage(image);
        private void setSize()
            size = new Dimension(image.getWidth(), image.getHeight());
    class CropSelector extends MouseInputAdapter
        CropPanel cropPanel;
        Point start, end;
        public CropSelector(CropPanel cp)
            cropPanel = cp;
        public void mask()
            Dimension d = cropPanel.getSize();
            Rectangle r = new Rectangle(0, 0, d.width, d.height);
            Area mask = new Area(r);
            Area port = new Area(cropPanel.clip);
            mask.subtract(port);
            cropPanel.setMask(mask);
        public void crop()
            Point[] p = cropPanel.corners;
            int w = p[2].x - p[0].x;
            int h = p[1].y - p[3].y;
            BufferedImage cropped = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2 = cropped.createGraphics();
            g2.translate(-p[0].x, -p[3].y);
            cropPanel.paint(g2);
            g2.dispose();
            cropPanel.setBackground(Color.pink);
            cropPanel.setImage(cropped);
        public void mousePressed(MouseEvent e)
            if(e.getClickCount() == 2)
                cropPanel.clearClip();
            start = e.getPoint();
        public void mouseDragged(MouseEvent e)
            end = e.getPoint();
            // locate high and low points of rectangle from start
            int dy = end.y - start.y;
            int dx = end.x - start.x;
            double theta = Math.atan2(dy, dx);
            double spoke = start.distance(end)/2;
            double side = Math.sqrt(spoke*spoke + spoke*spoke);
            Point[] corners = new Point[4];           // counter-clockwise
            corners[0] = start;                       // left
            int x = (int)(start.x + side * Math.cos(theta + Math.PI/4));
            int y = (int)(start.y + side * Math.sin(theta + Math.PI/4));
            corners[1] = new Point(x, y);             // bottom
            corners[2] = end;                         // right
            x = (int)(start.x + side * Math.cos(theta - Math.PI/4));
            y = (int)(start.y + side * Math.sin(theta - Math.PI/4));
            corners[3] = new Point(x, y);             // top
            cropPanel.setClip(corners);
    }

  • How to change draw dashed line with arrowhead (not straight)?

    Hi friends,
    The following code sinept draws an arrowed line from a given point to the other point. I want to know how it can changed to be dashed line as well? I would appreciate it if anybody help me for doing such changes.
    Thanks in advance,
    Reza_mp
    import javax.swing.*;
    import java.awt.*;
    import java.util.ArrayList;
    public class ArrowExample extends JFrame
        enum ArrowHead {
            HEIGHT(10), WIDTH(10);
            int n;
            ArrowHead(int n) {this.n = n;}
            public int value() {return n;}
        java.util.List<Arrow> arrows;
        BasicStroke stroke;
        private class Arrow {
            Point start;
            Point end;
            Polygon arrowHead;
            public Arrow(Point start, Point end) {
                this.start = start;
                this.end = end;
                double direction = Math.atan2(end.y - start.y, end.x - start.x);
                System.out.println(direction * 180/Math.PI);
                arrowHead = new Polygon();
                arrowHead.addPoint(0, 0);
                Point p1 = rotate(ArrowHead.WIDTH.value()/2, ArrowHead.HEIGHT.value(), direction);
                arrowHead.addPoint(p1.x, p1.y);
                Point p2 = rotate(-ArrowHead.WIDTH.value()/2, ArrowHead.HEIGHT.value(), direction);
                arrowHead.addPoint(p2.x, p2.y);
                arrowHead.addPoint(0, 0);
                arrowHead.translate(end.x, end.y);
            public Point rotate(int x, int y, double dir) {
                Point p = new Point();
                double r = Math.sqrt(x*x + y*y);
                double theta = Math.atan2(y, x);
                p.setLocation(Math.round(r*Math.cos(theta + dir + Math.PI/2)),
                              Math.round(r*Math.sin(theta + dir + Math.PI/2)));
                return p;
            public void draw(Graphics2D g) {
                g.drawLine(start.x, start.y, end.x, end.y);
                g.drawPolygon(arrowHead);
                g.fillPolygon(arrowHead);
        public ArrowExample() {
            super("Arrows");
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            JPanel p = new JPanel() {
                protected void paintComponent(Graphics g) {
                    super.paintComponent(g);
                    Graphics2D g2d = (Graphics2D)g;
                    Stroke oldStroke = g2d.getStroke();
                    Color oldColor = g2d.getColor();
                    g2d.setStroke(stroke);
                    g2d.setColor(Color.black);
                    for (Arrow a : arrows)
                        a.draw(g2d);
                    g2d.setStroke(oldStroke);
                    g2d.setColor(oldColor);
            p.setBackground(Color.white);
            add(p, BorderLayout.CENTER);
            stroke = new BasicStroke(3);
            arrows = new ArrayList<Arrow>();
            arrows.add(new Arrow(new Point(10,10), new Point(100,100)));
            arrows.add(new Arrow(new Point(300,10), new Point(300,100)));
            arrows.add(new Arrow(new Point(450,450), new Point(400,100)));
            pack();
            setSize(500, 500);
        public static void main(String[] args) {
            setDefaultLookAndFeelDecorated(true);
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new ArrowExample().setVisible(true);
    }

    Change the draw method as follows:
            public void draw(Graphics2D g) {
                Stroke s = g.getStroke();
                g.setStroke( new BasicStroke( 3.0f, BasicStroke.CAP_BUTT,
                   BasicStroke.JOIN_MITER, 1.0f, new float[] { 10.0f, 10.0f }, 0.0f ) );
                g.drawLine(start.x, start.y, end.x, end.y);
                g.setStroke( s );
                g.drawPolygon(arrowHead);
                g.fillPolygon(arrowHead);
            }

  • How do I get a movie clip to follow the cursor?

    Hi guys,
    What I want:
    Is a simple action where I have my company logo in the middle of the screen and it follows the cursor (not over the whole screen but within invisible borders).
    What I use:
    I have Flash Pro CS5, code is Actionscript 3.0 and my company logo has been converted to a movie clip.
    What didn't work:
    So I watched 2 different tutorials on how to do this and both didn't work.
    With the first one I used this code:
    function gradientOver(event:MouseEvent):void{
              logomc.visible=true;
              function reportStageMouse(event:MouseEvent):void{
                        var myStageX:Number=Math.round(event.stageX);
                        var myStageY:Number=Math.round(event.stageY);
                        var xTween:Tween=new Tween(logomc,"x", Strong.easeOut, logomc.x, myStageX, 1, true);
                        var yTween:Tween=new Tween(logomc,"y", Strong.easeOut, logomc.y, myStageY, 1, true);
              stage.addEventListener(MouseEvent.MOUSE_MOVE,reportStageMouse);
    function gradientOut(event:MouseEvent):void{
              logomc.visible=false;
    function gradientClick(event:MouseEvent):void{
              logomc.visible=false;
    gradient.addEventListener(MouseEvent.ROLL_OVER,gradientOver);
    gradient.addEventListener(MouseEvent.ROLL_OUT,gradientOut);
    gradient.addEventListener(MouseEvent.CLICK,gradientClick);
    And with the second one I had to make a border by drawing an oval shape, turn it into a movie clip and put my logo inside of it. Then I used this code:
    stage.addEventListener("mouseMove", arjun);
    function arjun(e:MouseEvent):void
              var var1 = mouseY - followins.y;
              var var2 = mouseX - followins.x;
              var radiusR = Math.atan2(var1,var2);
              var degreeR = radiusR / (Math.PI / 180);
              followins.rotation = degreeR;

    Thanks
    stage.addEventListener(MouseEvent.MOUSE_MOVE, hideCursor);
    function hideCursor(e:MouseEvent):void{
    logomc.startDrag(true);
    Mouse.hide(true);
    so I used this code and it didn't work. I first try'd it on the main timeline and then inside the logo's own timeline and even inside the backgrounds own timeline.
    no luck so far..

  • How can I use XStream to persist complicated Java Object  to XML & backward

    Dear Sir:
    I met a problem as demo in my code below when i use XTream to persist my Java Object;
    How can I use XStream to persist complicated Java Object to XML & backward??
    See
    [1] main code
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.ArrayList;
    import com.thoughtworks.xstream.XStream;
    import com.thoughtworks.xstream.io.xml.DomDriver;
    public class PhoneList {
         ArrayList<PhoneNumber> phones;
         ArrayList<Person> person;
         private PhoneList myphonelist ;
         private LocationTest location;
         private PhoneList(String name) {
         phones = new ArrayList<PhoneNumber>();
         person = new ArrayList<Person>();
         public ArrayList<PhoneNumber> getphones() {
              return phones;
         public ArrayList<Person> getperson() {
              return person;
         public void addPhoneNumber(PhoneNumber b1) {
              this.phones.add(b1);
         public void removePhoneNumber(PhoneNumber b1) {
              this.phones.remove(b1);
         public void addPerson(Person p1) {
              this.person.add(p1);
         public void removePerson(Person p1) {
              this.person.remove(p1);
         public void BuildList(){
              location = new LocationTest();
              XStream xstream = new XStream();
              myphonelist = new PhoneList("PhoneList");
              Person joe = new Person("Joe, Wallace");
              joe.setPhone(new PhoneNumber(123, "1234-456"));
              joe.setFax(new PhoneNumber(123, "9999-999"));
              Person geo= new Person("George Nixson");
              geo.setPhone(new PhoneNumber(925, "228-9999"));
              geo.getPhone().setLocationTest(location);          
              myphonelist.addPerson(joe);
              myphonelist.addPerson(geo);
         public PhoneList(){
              XStream xstream = new XStream();
              BuildList();
              saveStringToFile("C:\\temp\\test\\PhoneList.xml",convertToXML(myphonelist));
         public void saveStringToFile(String fileName, String saveString) {
              BufferedWriter bw = null;
              try {
                   bw = new BufferedWriter(
                             new FileWriter(fileName));
                   try {
                        bw.write(saveString);
                   finally {
                        bw.close();
              catch (IOException ex) {
                   ex.printStackTrace();
              //return saved;
         public String getStringFromFile(String fileName) {
              BufferedReader br = null;
              StringBuilder sb = new StringBuilder();
              try {
                   br = new BufferedReader(
                             new FileReader(fileName));
                   try {
                        String s;
                        while ((s = br.readLine()) != null) {
                             // add linefeed (\n) back since stripped by readline()
                             sb.append(s + "\n");
                   finally {
                        br.close();
              catch (Exception ex) {
                   ex.printStackTrace();
              return sb.toString();
         public  String convertToXML(PhoneList phonelist) {
              XStream xstream = new  XStream(new DomDriver());
              xstream.setMode(xstream.ID_REFERENCES) ;
              return xstream.toXML(phonelist);
         public static void main(String[] args) {
              new PhoneList();
    }[2].
    import java.io.Serializable;
    import javax.swing.JFrame;
    public class PhoneNumber implements Serializable{
           private      String      phone;
           private      String      fax;
           private      int      code;
           private      String      number;
           private      String      address;
           private      String      school;
           private      LocationTest      location;
           public PhoneNumber(int i, String str) {
                setCode(i);
                setNumber(str);
                address = "4256, Washington DC, USA";
                school = "Washington State University";
         public Object getPerson() {
              return null;
         public void setPhone(String phone) {
              this.phone = phone;
         public String getPhone() {
              return phone;
         public void setFax(String fax) {
              this.fax = fax;
         public String getFax() {
              return fax;
         public void setCode(int code) {
              this.code = code;
         public int getCode() {
              return code;
         public void setNumber(String number) {
              this.number = number;
         public String getNumber() {
              return number;
         public void setLocationTest(LocationTest bd) {
              this.location = bd;
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.getContentPane().add(location);
            f.getContentPane().add(location.getControls(), "Last");
            f.setSize(400,400);
            f.setLocation(200,200);
            f.setVisible(true);
         public LocationTest getLocationTest() {
              return location;
         }[3].
    package test.temp;
    import java.io.Serializable;
    public class Person implements Serializable{
         private String           fullname;
           @SuppressWarnings("unused")
         private PhoneNumber      phone;
           @SuppressWarnings("unused")
         private PhoneNumber      fax;
         public Person(){
         public Person(String fname){
                fullname=fname;           
         public void setPhone(PhoneNumber phoneNumber) {
              phone = phoneNumber;
         public void setFax(PhoneNumber phoneNumber) {
              fax = phoneNumber;
         public PhoneNumber getPhone() {
              return phone ;
         public PhoneNumber getFax() {
              return fax;
        public String getName() {
            return fullname ;
        public void setName(String name) {
            this.fullname      = name;
        public String toString() {
            return getName();
    }[4]. LocationTest.java
    package test.temp;
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    import javax.swing.*;
    import javax.swing.event.*;
    public class LocationTest extends JPanel implements ChangeListener
        Ellipse2D.Double ball;
        Line2D.Double    line;
        JSlider          translate;
        double           lastTheta = 0;
        public void stateChanged(ChangeEvent e)
            JSlider slider = (JSlider)e.getSource();
            String name = slider.getName();
            int value = slider.getValue();
            if(name.equals("rotation"))
                tilt(Math.toRadians(value));
            else if(name.equals("translate"))
                moveBall(value);
            repaint();
        protected void paintComponent(Graphics g)
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                RenderingHints.VALUE_ANTIALIAS_ON);
            if(ball == null)
                initGeom();
            g2.setPaint(Color.green.darker());
            g2.draw(line);
            g2.setPaint(Color.red);
            g2.fill(ball);
        private void initGeom()
            int w = getWidth();
            int h = getHeight();
            int DIA = 30;
            int padFromEnd = 5;
            line = new Line2D.Double(w/4, h*15/16, w*3/4, h*15/16);
            double x = line.x2 - padFromEnd - DIA;
            double y = line.y2 - DIA;
            ball = new Ellipse2D.Double(x, y, DIA, DIA);
            // update translate slider values
            int max = (int)line.getP1().distance(line.getP2());
            translate.setMaximum(max);
            translate.setValue(max-padFromEnd);
        private void tilt(double theta)
            // rotate line from left end
            Point2D pivot = line.getP1();
            double lineLength = pivot.distance(line.getP2());
            Point2D.Double p2 = new Point2D.Double();
            p2.x = pivot.getX() + lineLength*Math.cos(theta);
            p2.y = pivot.getY() + lineLength*Math.sin(theta);
            line.setLine(pivot, p2);
            // find angle from pivot to ball center relative to line
            // ie, ball center -> pivot -> line end
            double cx = ball.getCenterX();
            double cy = ball.getCenterY();
            double pivotToCenter = pivot.distance(cx, cy);
            // angle of ball to horizon
            double dy = cy - pivot.getY();
            double dx = cx - pivot.getX();
            // relative angle phi = ball_to_horizon - last line_to_horizon
            double phi = Math.atan2(dy, dx) - lastTheta;
            // rotate ball from pivot
            double x = pivot.getX() + pivotToCenter*Math.cos(theta+phi);
            double y = pivot.getY() + pivotToCenter*Math.sin(theta+phi);
            ball.setFrameFromCenter(x, y, x+ball.width/2, y+ball.height/2);
            lastTheta = theta;  // save theta for next time
        private void moveBall(int distance)
            Point2D pivot = line.getP1();
            // ball touches line at distance from pivot
            double contactX = pivot.getX() + distance*Math.cos(lastTheta);
            double contactY = pivot.getY() + distance*Math.sin(lastTheta);
            // find new center location of ball
            // angle lambda = lastTheta - 90 degrees (anti-clockwise)
            double lambda = lastTheta - Math.PI/2;
            double x = contactX + (ball.width/2)*Math.cos(lambda);
            double y = contactY + (ball.height/2)*Math.sin(lambda);
            ball.setFrameFromCenter(x, y, x+ball.width/2, y+ball.height/2);
        JPanel getControls()
            JSlider rotate = getSlider("rotation angle", "rotation", -90, 0, 0, 5, 15);
            translate = getSlider("distance from end",  "translate", 0, 100, 100,25, 50);
            JPanel panel = new JPanel(new GridLayout(0,1));
            panel.add(rotate);
            panel.add(translate);
            return panel;
        private JSlider getSlider(String title, String name, int min, int max,
                                  int value, int minorSpace, int majorSpace)
            JSlider slider = new JSlider(JSlider.HORIZONTAL, min, max, value);
            slider.setBorder(BorderFactory.createTitledBorder(title));
            slider.setName(name);
            slider.setPaintTicks(true);
            slider.setMinorTickSpacing(minorSpace);
            slider.setMajorTickSpacing(majorSpace);
            slider.setPaintLabels(true);
            slider.addChangeListener(this);
            return slider;
    }OK, My questions are:
    [1]. what I generated XML by XSTream is very complicated, especially for object LocationTest, Can we make it as simple as others such as Person object??
    [2]. after I run it, LocationTest will popup and a red ball in a panel will dsiplay, after I change red ball's position, I hope to persist it to xml, then when I read it back, I hope to get same picture, ie, red ball stiil in old position, How to do that??
    Thanks a lot!!

    Positive feedback? Then please take this in a positive way: if you want to work on persisting Java objects into XML, then GUI programming is irrelevant to that goal. The 1,000 lines of code you posted there appeared to me to have a whole lot of GUI code in it. You should produce a smaller (much smaller) example of what you want to do. Calling the working code from your GUI program should come later.

  • Math library not generating errno values or SIGFPE on Intel!!

    Hello. I posted this a long while back and got no responses, so I decided to ask again. I am writing a calculator, and it is not very nice for testing if I have to wind up with this:
    <pre style="width: 600px; background-color: #F0F0F0">$ hoc
    sqrt(-4)
    nan
    atan2(0,0)
    0
    pow(-4, 1/2)
    nan
    1e4000 * 1e4000
    inf
    (-1e4000) * (1e40000)
    -inf
    1e-40000
    0
    </pre>
    My program handles SIGFPE and there is a function errcheck() that checks the value of errno. It seems like the atan2(), pow(), and sqrt() functions do not assign to errno like they should. I'm running on an Intel Mac, and it makes making sure this calculator works right a big pain. Does anyone PLEASE know how to fix this? THANKS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    What x-bc does is: convert long function names (sin(), ...) to the short ones (s(), ...), save the final result in a temporary file, and just pipe bc -lq (include math library, no GNU bc banner) redirecting standard input to that temporary file over to their GTK+ text box. There's something that has to do with GNU bc then, and that results in a weird value (1) in my testing...
    PS - The file is src/main_window.cc; function int main_window::executeBc() - on version 2.0: lines 376 through 408. The code that does converting long to short is unknown to me.
    Message was edited by: andlabs
    Message was edited by: andlabs

  • Logic error in rotating a bot towards a target (switch from -180 to 180 and vice versa causes error)

    Hi,
    I am making a Bot class. This function rotateTo makes the bot rotate towards some coordinates, xTarget and yTarget.
    There are two targetRadians lines because it is easier to read for me.
    The target radians shows the angle of the target from the bot where the bot angle is this.angleRot.
    if the bot-angle minus the target-angle (it says in radians but is actually in degrees) is less than 0 it turns right and if it is greater than or equal to 0 then it turns left.
    public function rotateTo(xTarget, yTarget):Void {
                        targetRadians = Math.atan2(yTarget-this.yPos, xTarget-this.xPos);
                        targetRadians = Math.round(radiansToDegrees(targetRadians));
                        trace(targetRadians);
                                  if (this.angleRot-targetRadians<0) {
                                            turnBot(5);
                                  } else {
                                            turnBot(-5);
    This basically works. The bot rotates towards the target at 5 degrees per frame.
    The angle setup is that if the target x, y is below the bot x, y, the target angle is about 90, if it's to the right its about 0, if its above it's about -90 but as the angle is decreased to -180 from above to the left of the bot, when it goes below the bot (and to the left) the target angle switches to 180.
    So something like: with the bot in the middle and the target being located at one of the numbers;
              -90
    -180               -1
    180               1
               90
    The fact the target angle switches from -180 to 180 or 180 to -180 confuses the bot and the bot decides to turn ALL the way the opposite direction BECAUSE;
    if the bot angle is 160 and target angle is 175, the bot angle increases because target is greater than bot angle. If the target angle changes to -180, bot angle decreases even though it's more efficient to change from 160 to -180 through increasing the bot angle as at 180 it changes to -180. I just cannot work out the logic to use to make this work though.
    Any suggestions? Thanks.

    Hey I got it to work finally:
    public function rotateTo(xTarget, yTarget):Void {
                        targetRotation = Math.atan2((yTarget-this.yPos), xTarget-this.xPos)*180/Math.PI;
                        if (this.angleRot-targetRotation>180) {
                                  this.angleRot -= 360;
                        } else if (this.angleRot-targetRotation<-180) {
                                  this.angleRot += 360;
                        if (this.angleRot-targetRotation<0) {
                                  turnBot(5);
                        } else {
                                  turnBot(-5);
    so basically I added a couple of if statements before the main business.... I don't really have a coherent explanation for the fix but it works!

  • Atan in jdk1.1.8 doesn't work. help

    I am creating a program which simulate the effect of gravity on a object (for a game). For this I am working with jdk1.1.8. (not by choice). But for some reason the movement of the object just turns around. I believed that de method Math.atan2 was wrong so i have rewritten it and it worked better. But the method atan most likely doesn't work either because it is not perfect yet. Does anyone know or have an implementation of de atan method in java that works so i can use it? Because I don't know how the method works.
    maybe i am wrong here but it is basicly the only solution to my problem. if give the code of the bullet class with it. maybe anyone sees the problem there:
    import java.io.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.*;
    public class Bullet extends Thread
         public static boolean running = false;
         private double x, y;
         private double width=10, height=10;
         private double weight=10;
         private double travelAngle = toRadians(45);
         private double speed=5;
         private Attraction hello;
         private Planet[] planets;
         private int planetCount=0;
         Bullet(Attraction hello, int x, int y, int angle, Planet[] planets)
              this.hello = hello;
              this.x = x;
              this.y = y;
              this.travelAngle = toRadians(angle);
              this.planets = planets;
              this.planetCount = planets.length;
              running = true;
         public void run()
              double px=0, py=0, g=0;//comes from the planet
              //variable for the calculation
              Planet p = null;
              double dx=0, dy=0, dx2=0, dy2=0, fdx=0, fdy=0, totalfdx=0, totalfdy=0;
              double forceAngle=0;
              double d=0, gd=0, force=0;
              double oldx = 0;
              double oldy = 0;
              int drawSteps = 0; //for smooth drawing
              double dxSteps=0, dySteps=0;
              double oldspeed = speed;
              while(running)
                   oldspeed = speed;
                   totalfdx=0;
                   totalfdy=0;
                   oldx = x;
                   oldy = y;
                   dx = Math.cos(travelAngle)*speed;//the normal translation for x without the gravity effect
                   dy = Math.sin(travelAngle)*speed;//the normal translation for y without the gravity effect
                   x+=dx;//new x from the normal translation
                   y+=dy;//new y from the normal translation
                   for(int i = 0; i<planetCount; i++)
                        p = planets;
                        px = p.getX();//x coordinate of the planet
                        py = p.getY();//y coordinate of the planet
                        g = p.getGravity();//gravity of the planet
                        dx2 = px - x; //the x-difference between the bullet and the planet
                        dy2 = py - y; //the y-difference between the bullet and the planet
                        //System.out.println(dx2 + " "+ dy2);
                        d = Math.sqrt(dx2*dx2+dy2*dy2); //the direct distance between the bullet and the planet
                        //System.out.println("distance " + d);
                        gd = g/d; //the effect of the gravity at the distance of the bullet
                        //System.out.println("gravitydistance" + gd);
                        force = gd*weight; //the forcepull on the object from the planet
                        forceAngle = atan2(dy2,dx2);//the angle of the force with the y-axis
                        //System.out.println("force " + force + " distance " + d);
                        fdx = force * Math.sin(forceAngle);//the force pull distance for x
                        fdy = force * Math.cos(forceAngle);//the force pull distance for y
                        //System.out.println(fdx + " " + fdy);
                        totalfdx += fdx;
                        totalfdy += fdy;
                   x = x+totalfdx;//new x
                   y = y+totalfdy;//new y
                   //System.out.println("Angle" + toDegrees(travelAngle));
                   travelAngle = atan2( (x-oldx), (y-oldy) );
                   speed = Math.sqrt((x-oldx)*(x-oldx) + (y-oldy)*(y-oldy));
                   if(oldx>x)
                        System.out.println("Turning point");
                   System.out.println(oldspeed + " " + speed);
                   //System.out.println("x=> " + x + " y=> " + y);
                   drawSteps = (int)(speed+1);
                   dxSteps = (x-oldx)/drawSteps;
                   dySteps = (y-oldy)/drawSteps;
                   x = oldx + dxSteps;
                   y = oldy + dySteps;
                   hello.repaint((int)x,(int)y, (int)width, (int)height);
                   for(int i = 0; i<drawSteps; i++)
                        x+=dxSteps;
                        y+=dySteps;
                        hello.repaint((int)(x-dxSteps), (int)(y-dySteps), (int)(width+width), (int)(height+height));
                        try
                             sleep(30);
                        catch(Exception e){}
                   hello.repaint((int)x,(int)y, (int)width, (int)height);
                   //hello.repaint();
                   try
                        sleep(100);
                   catch(Exception e){}
                   System.out.flush();
                   for(int i = 0; i<planetCount; i++)
                        p = planets[i];
                        if(p.contains(x,y))
                             System.out.println("Boom");
                             running = false;
              System.out.println("Bullet Stopped");
         public void draw(Graphics g)
         g.setColor(Color.cyan);
              g.fillRect((int)Math.round(x-width/2), (int)Math.round(y-height/2), (int)width, (int)height);
         public void move(boolean left, boolean right)
              if(left)
                   x--;
                   hello.repaint(x, y-2, width+5, height+5);
              if(right)
                   x++;
                   hello.repaint(x+1, y-2, width+5, height+5);
         public double toRadians(double angle)
              return (angle/180*Math.PI);
         private double toDegrees(double angle)
              return (angle/Math.PI*180);
         private double atan2(double a, double b)
              if(a>0)
                   if(b<0)
                        return (Math.atan(b/a)+(2*Math.PI));
                   return Math.atan(b/a);
              else if(a<0)
                   return (Math.atan(b/a)+Math.PI);
              else if(a==0 && b>0)
                   return ((Math.PI)/2);
              else if(a==0 && b<0)
                   return ((3*Math.PI)/2);
              else
                   return 0;

    I have allready tested my code to the max en I have redone the calculations about 4 times, because I couldn't believe the fault was in the method atan or atan2 from sun. But since my calculations should work in theorie (worked it out with a math teacher) it's the only options I could think of.
    [qoute]
    I haven't looked up in the API docs how atan2 is supposed to work, but I noticed these two lines in your code:
    forceAngle = atan2(dy2,dx2);//the angle of the force with the y-axis
    travelAngle = atan2( (x-oldx), (y-oldy) );
    In one place you use Y and X as the parameters and in the other case you use X and Y. They can't both be right.
    [qoute]
    In this case it is. because the forceangle is opposite the x-axis and thus the two must be reversed. (travelangle is opposite the y-axis).
    I have also tried to reverse them (for both) but the effect got worse :)
    Thanks anyway.

Maybe you are looking for

  • Adobe Portfolio setop

    I have Adobe Acrobat 9 Standard. I have gone through downloading the required add-ones from http://www.adobe.com/support/downloads/thankyou.jsp?ftpID=4006&fileID=3743 On the setup helpme page it suggested that once I have moved all the downloaded fil

  • Amount calculations based on customer

    For example given the following situation (letu2019s assume it is AR): Customer     Doc num     Item     Doc date     Clearing date      Value      DS0     Clearing Date - Doc date 9000000010     900000017     1     01.05.2010     31.05.2010         

  • JSP after a few requests = core dump

    hi, i am running web logic 8.1 on a solaris box. After a few request(loading a few pages) it prints out illegal instruction to the console and shuts down. A sure way to crash my site is to click a bunch of links at once which I think is overloading t

  • 11.5 SR4 xMii Installation

    Greetings: I have tried setting up 11.5 xMii on Windows XP Professional. Have installed 11.5 SR1, 2, 3 & 4 patches - in that order. After installation I am facing the following issue: - the session variables in irpt files are not being interpreted /

  • Trying to update to 8.0

    i'm trying to complete the software update but i keep receiving the message 'the feature you are trying to use is on a network resource that is unavailable'. however, i have attempted to uninstall the programs and i am also receiving an error message