001/* An actor that converts polar coordinates to Cartesian coordinates.
002
003 Copyright (c) 1998-2015 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028package ptolemy.actor.lib.conversions;
029
030import ptolemy.actor.TypedAtomicActor;
031import ptolemy.actor.TypedIOPort;
032import ptolemy.data.DoubleToken;
033import ptolemy.data.Token;
034import ptolemy.data.type.BaseType;
035import ptolemy.kernel.CompositeEntity;
036import ptolemy.kernel.util.IllegalActionException;
037import ptolemy.kernel.util.NameDuplicationException;
038
039///////////////////////////////////////////////////////////////////
040/// PolarToCartesian
041
042/**
043
044 This actor reads two double tokens (magnitude and angle) and outputs
045 two new double tokens (x and y). The outputs are a Cartesian representation
046 of the pair given at the inputs in polar form, where
047 x = magnitude * cos(angle) and y = magnitude * sin(angle).
048 Note that the angle input is assumed to be in radians. If either input
049 is NaN or infinity, then the outputs are NaN or infinity.
050
051 @author Michael Leung, Edward A. Lee, Paul Whitaker
052 @version $Id$
053 @since Ptolemy II 1.0
054 @Pt.ProposedRating Green (pwhitake)
055 @Pt.AcceptedRating Green (pwhitake)
056 */
057public class PolarToCartesian extends TypedAtomicActor {
058    /** Construct an actor with the given container and name.
059     *  @param container The container.
060     *  @param name The name of this actor.
061     *  @exception IllegalActionException If the actor cannot be contained
062     *   by the proposed container.
063     *  @exception NameDuplicationException If the container already has an
064     *   actor with this name.
065     */
066    public PolarToCartesian(CompositeEntity container, String name)
067            throws NameDuplicationException, IllegalActionException {
068        super(container, name);
069
070        magnitude = new TypedIOPort(this, "magnitude", true, false);
071        magnitude.setTypeEquals(BaseType.DOUBLE);
072
073        angle = new TypedIOPort(this, "angle", true, false);
074        angle.setTypeEquals(BaseType.DOUBLE);
075
076        x = new TypedIOPort(this, "x", false, true);
077        x.setTypeEquals(BaseType.DOUBLE);
078
079        y = new TypedIOPort(this, "y", false, true);
080        y.setTypeEquals(BaseType.DOUBLE);
081
082        _attachText("_iconDescription",
083                "<svg>\n" + "<polygon points=\"-15,-15 15,15 15,-15 -15,15\" "
084                        + "style=\"fill:white\"/>\n" + "</svg>\n");
085    }
086
087    ///////////////////////////////////////////////////////////////////
088    ////                         public variables                  ////
089
090    /** The input port for the magnitude component, which has type
091     DoubleToken. */
092    public TypedIOPort magnitude;
093
094    /** The input port for the angle component (in radians), which has type
095     DoubleToken. */
096    public TypedIOPort angle;
097
098    /** The output port for the x coordinate, which has type DoubleToken. */
099    public TypedIOPort x;
100
101    /** The output port for the y coordinate, which has type DoubleToken. */
102    public TypedIOPort y;
103
104    ///////////////////////////////////////////////////////////////////
105    ////                         public methods                    ////
106
107    /** Consume a double token from each of the two input ports (magnitude
108     *  and angle) and output a double token on each of the two output ports
109     *  (x and y). The output is a Cartesian representation of the coordinates
110     *  given at the inputs in polar form. The angle is in radians.
111     *  @exception IllegalActionException If there is no director.
112     */
113    @Override
114    public void fire() throws IllegalActionException {
115        super.fire();
116        DoubleToken magnitudeValue = (DoubleToken) magnitude.get(0);
117        double angleValue = ((DoubleToken) angle.get(0)).doubleValue();
118
119        // Perform multiplication using Token methods so as to preserve units of length.
120        Token xValue = magnitudeValue
121                .multiply(new DoubleToken(Math.cos(angleValue)));
122        Token yValue = magnitudeValue
123                .multiply(new DoubleToken(Math.sin(angleValue)));
124
125        x.send(0, xValue);
126        y.send(0, yValue);
127    }
128
129    /** Return false if either of the input ports has no token, otherwise
130     *  return what the superclass returns (presumably true).
131     *  @exception IllegalActionException If there is no director.
132     */
133    @Override
134    public boolean prefire() throws IllegalActionException {
135        if (!magnitude.hasToken(0) || !angle.hasToken(0)) {
136            return false;
137        }
138
139        return super.prefire();
140    }
141}