001/*
002 * Copyright (c) 1998-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.geon;
031
032import java.util.Vector;
033
034import nl.skybound.awt.DoublePolygon;
035import ptolemy.actor.TypedAtomicActor;
036import ptolemy.actor.TypedIOPort;
037import ptolemy.data.ArrayToken;
038import ptolemy.data.DoubleToken;
039import ptolemy.data.ObjectToken;
040import ptolemy.data.StringToken;
041import ptolemy.data.Token;
042import ptolemy.data.type.ArrayType;
043import ptolemy.data.type.BaseType;
044import ptolemy.kernel.CompositeEntity;
045import ptolemy.kernel.util.IllegalActionException;
046import ptolemy.kernel.util.NameDuplicationException;
047
048//////////////////////////////////////////////////////////////////////////
049//// PointInPolygonXY
050/**
051 * This actor receives an array of polygons and regions and a classification
052 * point. It returns an array of all the regions the point falls in.
053 * 
054 * @author Efrat Jaeger
055 * @version $Id: PointinPolygonXY.java 24234 2010-05-06 05:21:26Z welker $
056 * @since Ptolemy II 3.0.2
057 */
058public class PointinPolygonXY extends TypedAtomicActor {
059
060        /**
061         * Construct an actor with the given container and name.
062         * 
063         * @param container
064         *            The container.
065         * @param name
066         *            The name of this actor.
067         * @exception IllegalActionException
068         *                If the actor cannot be contained by the proposed
069         *                container.
070         * @exception NameDuplicationException
071         *                If the container already has an actor with this name.
072         */
073        public PointinPolygonXY(CompositeEntity container, String name)
074                        throws NameDuplicationException, IllegalActionException {
075
076                super(container, name);
077
078                // Set the type constraint.
079                region = new TypedIOPort(this, "region", false, true);
080                region.setTypeEquals(new ArrayType(BaseType.STRING));
081                point = new TypedIOPort(this, "point", true, false); // input point
082                point.setTypeEquals(new ArrayType(BaseType.DOUBLE));
083                polygonRegions = new TypedIOPort(this, "polygonRegions", true, false); // Polygon
084                                                                                                                                                                // coordinates
085                                                                                                                                                                // and
086                                                                                                                                                                // regions
087                polygonRegions.setTypeEquals(BaseType.GENERAL);
088
089                _attachText("_iconDescription", "<svg>\n"
090                                + "<polygon points=\"-15,-2 0,-15 15,-2 11,15 -11,15\" "
091                                + "style=\"fill:white\"/>\n"
092                                + "<circle cx=\"3\" cy=\"4\" r=\"1\""
093                                + "style=\"fill:black\"/>\n" + "</svg>\n");
094
095        }
096
097        // /////////////////////////////////////////////////////////////////
098        // // ports and parameters ////
099
100        /**
101         * A classification point.
102         */
103        public TypedIOPort point;
104
105        /**
106         * A set of polygons and their region names.
107         */
108        public TypedIOPort polygonRegions;
109
110        /**
111         * The point's region.
112         */
113        public TypedIOPort region;
114
115        // /////////////////////////////////////////////////////////////////
116        // // public methods ////
117
118        /**
119         * Receive a set of polygons and a classification point and returns the
120         * point region along with a URL for browser display of the point in the
121         * polygon.
122         * 
123         * @exception IllegalActionException
124         *                If there's no director.
125         */
126        public void fire() throws IllegalActionException {
127                if (polygonRegions.hasToken(0) && point.hasToken(0)) {
128                        ObjectToken obj1 = (ObjectToken) polygonRegions.get(0);
129                        PolygonUtil polygons[] = (PolygonUtil[]) obj1.getValue();
130                        ArrayToken arrayToken = (ArrayToken) point.get(0);
131                        double x = ((DoubleToken) arrayToken.getElement(0)).doubleValue();
132                        double y = ((DoubleToken) arrayToken.getElement(1)).doubleValue();
133                        // Point2D.Double p = (Point2D.Double) obj2.getValue();
134                        // double x = p.getX();
135                        // double y = p.getY();
136                        Vector result = new Vector();
137                        for (int j = 0; j < polygons.length; j++) {
138                                DoublePolygon P = polygons[j].getPolygon();
139                                arrayLen = P.npoints;
140                                String _region = polygons[j].getRegion();
141                                if (_isPolygonVertex(P, x, y) || _onPolygonEdge(P, x, y)
142                                                || P.contains(x, y)) {
143                                        result.add(new StringToken(_region)); // FIX ME!!! TAKE CARE
144                                                                                                                        // OF MULTIPLE
145                                                                                                                        // REGIONS AND NO
146                                                                                                                        // REGION!!!
147                                }
148                        }
149                        Token[] regions = null;
150                        if (result.size() > 0) {
151                                regions = new Token[result.size()];
152                                result.toArray(regions);
153                        } else {
154                                regions = new Token[1];
155                                regions[0] = new StringToken("");
156                        }
157                        region.broadcast(new ArrayToken(regions));
158                }
159        }
160
161        // /////////////////////////////////////////////////////////////////
162        // // private methods ////
163
164        /*
165         * Checking whether the given point is one of the polygon's vertices.
166         */
167        private boolean _isPolygonVertex(DoublePolygon P, double x, double y) {
168                for (int i = 0; i < arrayLen; i++) {
169                        if (P.xpoints[i] == x && P.ypoints[i] == y)
170                                return true;
171                }
172                return false;
173        }
174
175        /*
176         * Checking whether the given point is one of the polygon's edges.
177         */
178        private boolean _onPolygonEdge(DoublePolygon P, double x, double y) {
179                double x1, x2, y1, y2;
180                for (int i = 0; i < arrayLen; i++) {
181                        x1 = P.xpoints[i];
182                        x2 = P.xpoints[(i + 1) % arrayLen];
183                        y1 = P.ypoints[i];
184                        y2 = P.ypoints[(i + 1) % arrayLen];
185                        if (((x1 <= x && x <= x2) || (x2 <= x && x <= x1)) && // x and y are
186                                                                                                                                        // between
187                                                                                                                                        // x1,x2 and
188                                                                                                                                        // y1,y2
189                                        ((y1 <= y && y <= y2) || (y2 <= y && y <= y1))) {
190                                if (((y - y1) / (x - x1)) == ((y - y2) / (x - x2)))
191                                        return true;
192                        }
193                }
194                return false;
195        }
196
197        /*
198         * Adding the classification point to the SVG file for display purposes.
199         */
200        /*
201         * private void _addRegionToSVG(String svgFile, String region) { try { //
202         * System.out.println("SVG File: " + svgFile); File svg = new File(svgFile);
203         * BufferedReader br = new BufferedReader(new FileReader(svg)); String line;
204         * String toFile = ""; String extraLine; if (region.length() > 20) { int tmp
205         * = result.indexOf(" ",15); extraLine =
206         * "<text x= '315' y='70' fill='blue' text-anchor='middle' style='font-size: 12pt; font-family: serif; ' >"
207         * + region.substring(0,tmp) + "</text>"; extraLine +=
208         * "<text x= '315' y='90' fill='blue' text-anchor='middle' style='font-size: 12pt; font-family: serif; ' >"
209         * + region.substring(tmp+1) + "</text>"; } else { extraLine =
210         * "<text x= '315' y='70' fill='blue' text-anchor='middle' style='font-size: 12pt; font-family: serif; ' >"
211         * + region + "</text>"; } // System.out.println("Extra line" + extraLine);
212         * while ( (line = br.readLine()) != null) { int ind =
213         * line.toLowerCase().indexOf("<text"); if (ind != -1) { //
214         * System.out.println("Inside extra line"); toFile += line.substring(0, ind)
215         * + "\n"; toFile += extraLine + "\n"; toFile += line.substring(ind) + "\n";
216         * } else toFile += line + "\n"; } br.close();
217         * 
218         * // System.out.println(toFile); BufferedWriter out = new
219         * BufferedWriter(new FileWriter(svg)); out.write(toFile); out.close(); }
220         * catch (IOException e) { MessageHandler.error("Error opening file", e); }
221         * }
222         */
223        // /////////////////////////////////////////////////////////////////
224        // // private members ////
225        // private double x, y;
226        // private String id;
227        private int arrayLen;
228}