001/* An actor that converts polar coordinates to a complex token.
002
003 Copyright (c) 1998-2014 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.ComplexToken;
033import ptolemy.data.DoubleToken;
034import ptolemy.data.type.BaseType;
035import ptolemy.kernel.CompositeEntity;
036import ptolemy.kernel.util.IllegalActionException;
037import ptolemy.kernel.util.NameDuplicationException;
038import ptolemy.math.Complex;
039
040///////////////////////////////////////////////////////////////////
041/// PolarToComplex
042
043/**
044
045 This actor reads two double tokens (magnitude and angle) and outputs
046 a single complex token. The output is a complex token representation of
047 the coordinates given at the inputs in polar form. The complex token
048 has two parts: the first part correspond to the real part, which is
049 magnitude * cos(angle, and the second part is the imaginary part, which is
050 magnitude * sin(angle). Note that the angle input is
051 assumed to be in radians. If either input is NaN or infinity,
052 then the output is NaN or infinity.
053
054 @author Michael Leung, Edward A. Lee, Paul Whitaker
055 @version $Id$
056 @since Ptolemy II 1.0
057 @Pt.ProposedRating Green (pwhitake)
058 @Pt.AcceptedRating Green (pwhitake)
059 */
060public class PolarToComplex extends TypedAtomicActor {
061    /** Construct an actor with the given container and name.
062     *  @param container The container.
063     *  @param name The name of this actor.
064     *  @exception IllegalActionException If the actor cannot be contained
065     *   by the proposed container.
066     *  @exception NameDuplicationException If the container already has an
067     *   actor with this name.
068     */
069    public PolarToComplex(CompositeEntity container, String name)
070            throws NameDuplicationException, IllegalActionException {
071        super(container, name);
072
073        magnitude = new TypedIOPort(this, "magnitude", true, false);
074        magnitude.setTypeEquals(BaseType.DOUBLE);
075
076        angle = new TypedIOPort(this, "angle", true, false);
077        angle.setTypeEquals(BaseType.DOUBLE);
078
079        output = new TypedIOPort(this, "output", false, true);
080        output.setTypeEquals(BaseType.COMPLEX);
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
095     type DoubleToken. */
096    public TypedIOPort angle;
097
098    /** The port for the output, which has type ComplexToken. */
099    public TypedIOPort output;
100
101    ///////////////////////////////////////////////////////////////////
102    ////                         public methods                    ////
103
104    /** Consume a double token from each input port (magnitude and angle)
105     *  and output a new complex token on the output port. The output is
106     *  a complex representation of the coordinates given at the inputs in
107     *  polar form. The input angle is assumed to be in radians. If either
108     *  input has no token, then do nothing.
109     *  @exception IllegalActionException If there is no director.
110     */
111    @Override
112    public void fire() throws IllegalActionException {
113        super.fire();
114        double magnitudeValue = ((DoubleToken) magnitude.get(0)).doubleValue();
115        double angleValue = ((DoubleToken) angle.get(0)).doubleValue();
116
117        double xValue = magnitudeValue * Math.cos(angleValue);
118        double yValue = magnitudeValue * Math.sin(angleValue);
119
120        output.send(0, new ComplexToken(new Complex(xValue, yValue)));
121    }
122
123    /** Return false if either of the input ports has no token, otherwise
124     *  return what the superclass returns (presumably true).
125     *  @exception IllegalActionException If there is no director.
126     */
127    @Override
128    public boolean prefire() throws IllegalActionException {
129        if (!magnitude.hasToken(0) || !angle.hasToken(0)) {
130            return false;
131        }
132
133        return super.prefire();
134    }
135}