AI2 Component  (Version nb184)
Polygon.java
Go to the documentation of this file.
1 // -*- mode: java; c-basic-offset: 2; -*-
2 // Copyright © 2016-2020 Massachusetts Institute of Technology, All rights reserved.
3 // Released under the Apache License, Version 2.0
4 // http://www.apache.org/licenses/LICENSE-2.0
5 
6 package com.google.appinventor.components.runtime;
7 
8 import android.text.TextUtils;
9 import android.util.Log;
10 
11 import androidx.annotation.VisibleForTesting;
12 
19 
23 
35 
36 import java.util.ArrayList;
37 import java.util.LinkedList;
38 import java.util.List;
39 
40 import org.json.JSONArray;
41 import org.json.JSONException;
42 import org.locationtech.jts.geom.Geometry;
43 import org.osmdroid.util.GeoPoint;
44 
51 @DesignerComponent(version = YaVersion.POLYGON_COMPONENT_VERSION,
52  category = ComponentCategory.MAPS,
53  description = "Polygon")
54 @SimpleObject
55 public class Polygon extends PolygonBase implements MapPolygon {
56  private static final String TAG = Polygon.class.getSimpleName();
57 
58  private List<List<GeoPoint>> points = new ArrayList<List<GeoPoint>>();
59  private List<List<List<GeoPoint>>> holePoints = new ArrayList<List<List<GeoPoint>>>();
60  private boolean multipolygon = false;
61  private boolean initialized = false;
62 
63  private static final MapFeatureVisitor<Double> distanceComputation = new MapFeatureVisitor<Double>() {
64  @Override
65  public Double visit(MapMarker marker, Object... arguments) {
66  if ((Boolean) arguments[1]) {
67  return GeometryUtil.distanceBetweenCentroids(marker, (Polygon) arguments[0]);
68  } else {
69  return GeometryUtil.distanceBetweenEdges(marker, (Polygon) arguments[0]);
70  }
71  }
72 
73  @Override
74  public Double visit(MapLineString lineString, Object... arguments) {
75  if ((Boolean) arguments[1]) {
76  return GeometryUtil.distanceBetweenCentroids(lineString, (Polygon) arguments[0]);
77  } else {
78  return GeometryUtil.distanceBetweenEdges(lineString, (Polygon) arguments[0]);
79  }
80  }
81 
82  @Override
83  public Double visit(MapPolygon polygon, Object... arguments) {
84  if ((Boolean) arguments[1]) {
85  return GeometryUtil.distanceBetweenCentroids(polygon, (Polygon) arguments[0]);
86  } else {
87  return GeometryUtil.distanceBetweenEdges(polygon, (Polygon) arguments[0]);
88  }
89  }
90 
91  @Override
92  public Double visit(MapCircle circle, Object... arguments) {
93  if ((Boolean) arguments[1]) {
94  return GeometryUtil.distanceBetweenCentroids((Polygon) arguments[0], circle);
95  } else {
96  return GeometryUtil.distanceBetweenEdges((Polygon) arguments[0], circle);
97  }
98  }
99 
100  @Override
101  public Double visit(MapRectangle rectangle, Object... arguments) {
102  if ((Boolean) arguments[1]) {
103  return GeometryUtil.distanceBetweenCentroids((Polygon) arguments[0], rectangle);
104  } else {
105  return GeometryUtil.distanceBetweenEdges((Polygon) arguments[0], rectangle);
106  }
107  }
108  };
109 
111  super(container, distanceComputation);
112  container.addFeature(this);
113  }
114 
115  public void Initialize() {
116  initialized = true;
117  clearGeometry();
121  }
122 
123  @Override
125  description = "Returns the type of the feature. For polygons, this returns the text "
126  + "\"Polygon\".")
127  public String Type() {
128  return MapFactory.MapFeatureType.TYPE_POLYGON;
129  }
130 
131  @Override
133  description = "Gets or sets the sequence of points used to draw the polygon.")
134  public YailList Points() {
135  if (points.isEmpty()) {
136  return YailList.makeEmptyList();
137  } else if (multipolygon) {
138  // Return a 2-deep list of points for multipolygons
139  List<YailList> result = new LinkedList<YailList>();
140  for (List<GeoPoint> part : points) {
141  result.add(GeometryUtil.pointsListToYailList(part));
142  }
143  return YailList.makeList(result);
144  } else {
145  // Return a 1-deep list of points for simple polygons
146  return GeometryUtil.pointsListToYailList(points.get(0));
147  }
148  }
149 
156  @Override
158  public void Points(YailList points) {
159  try {
160  if (GeometryUtil.isPolygon(points)) {
161  multipolygon = false;
162  this.points.clear();
163  this.points.add(GeometryUtil.pointsFromYailList(points));
164  } else if (GeometryUtil.isMultiPolygon(points)) {
165  multipolygon = true;
166  this.points = GeometryUtil.multiPolygonFromYailList(points);
167  } else {
169  "Unable to determine the structure of the points argument.");
170  }
171  if (initialized) {
172  clearGeometry();
174  }
175  } catch(DispatchableError e) {
177  }
178  }
179 
186  @SuppressWarnings("squid:S00100")
188  @SimpleProperty(description = "Constructs a polygon from the given list of coordinates.")
189  public void PointsFromString(String pointString) {
190  if (TextUtils.isEmpty(pointString)) {
191  points = new ArrayList<List<GeoPoint>>(); // create a new list in case the user has saved a reference
193  return;
194  }
195  try {
196  JSONArray content = new JSONArray(pointString);
197  if (content.length() == 0) {
198  points = new ArrayList<List<GeoPoint>>(); // create a new list in case the user has saved a reference
199  multipolygon = false;
201  return;
202  }
203  points = GeometryUtil.multiPolygonToList(content);
204  multipolygon = points.size() > 1;
205  if (initialized) {
206  clearGeometry();
208  }
209  } catch(JSONException e) {
210  container.$form().dispatchErrorOccurredEvent(this, "PointsFromString",
211  ErrorMessages.ERROR_POLYGON_PARSE_ERROR, e.getMessage());
212  } catch(DispatchableError e) {
213  getDispatchDelegate().dispatchErrorOccurredEvent(this, "PointsFromString",
214  e.getErrorCode(), e.getArguments());
215  }
216  }
217 
218  @Override
220  description = "Gets or sets the sequence of points used to draw holes in the polygon.")
221  public YailList HolePoints() {
222  if (holePoints.isEmpty()) {
223  return YailList.makeEmptyList();
224  } else if (multipolygon) {
225  List<YailList> result = new LinkedList<YailList>();
226  for (List<List<GeoPoint>> polyholes : holePoints) {
227  result.add(GeometryUtil.multiPolygonToYailList(polyholes));
228  }
229  return YailList.makeList(result);
230  } else {
231  return GeometryUtil.multiPolygonToYailList(holePoints.get(0));
232  }
233  }
234 
241  @Override
243  public void HolePoints(YailList points) {
244  try {
245  if (points.size() == 0) {
246  holePoints = new ArrayList<List<List<GeoPoint>>>();
247  } else if (multipolygon) {
248  this.holePoints = GeometryUtil.multiPolygonHolesFromYailList(points);
249  } else if (GeometryUtil.isMultiPolygon(points)) {
250  List<List<List<GeoPoint>>> holes = new ArrayList<List<List<GeoPoint>>>();
251  holes.add(GeometryUtil.multiPolygonFromYailList(points));
252  this.holePoints = holes;
253  } else {
255  "Unable to determine the structure of the points argument.");
256  }
257  if (initialized) {
258  clearGeometry();
260  }
261  } catch(DispatchableError e) {
262  container.$form().dispatchErrorOccurredEvent(this, "HolePoints",
263  e.getErrorCode(), e.getArguments());
264  }
265  }
266 
274  @SuppressWarnings("squid:S00100")
276  @SimpleProperty(description = "Constructs holes in a polygon from a given list of coordinates per hole.")
277  public void HolePointsFromString(String pointString) {
278  if (TextUtils.isEmpty(pointString)) {
279  holePoints = new ArrayList<List<List<GeoPoint>>>(); // create a new list in case the user has saved a reference
281  return;
282  }
283  try {
284  JSONArray content = new JSONArray(pointString);
285  if (content.length() == 0) {
286  holePoints = new ArrayList<List<List<GeoPoint>>>(); // create a new list in case the user has saved a reference
288  return;
289  }
290  holePoints = GeometryUtil.multiPolygonHolesToList(content);
291  if (initialized) {
292  clearGeometry();
294  }
295  Log.d(TAG, "Points: " + points);
296  } catch(JSONException e) {
297  Log.e(TAG, "Unable to parse point string", e);
298  container.$form().dispatchErrorOccurredEvent(this, "HolePointsFromString",
299  ErrorMessages.ERROR_POLYGON_PARSE_ERROR, e.getMessage());
300  }
301  }
302 
306  @Override
307  @SimpleFunction(description = "Returns the centroid of the Polygon as a (latitude, longitude) pair.")
308  public YailList Centroid() {
309  return super.Centroid();
310  }
311 
312  @Override
313  public List<List<GeoPoint>> getPoints() {
314  return points;
315  }
316 
317  @Override
318  public List<List<List<GeoPoint>>> getHolePoints() {
319  return holePoints;
320  }
321 
322  @Override
323  public <T> T accept(MapFeatureVisitor<T> visitor, Object... arguments) {
324  return visitor.visit(this, arguments);
325  }
326 
327  @Override
328  protected Geometry computeGeometry() {
329  return GeometryUtil.createGeometry(points, holePoints);
330  }
331 
332  @Override
333  public void updatePoints(List<List<GeoPoint>> points) {
334  this.points.clear();
335  this.points.addAll(points);
336  clearGeometry();
337  }
338 
339  @Override
340  public void updateHolePoints(List<List<List<GeoPoint>>> points) {
341  this.holePoints.clear();
342  this.holePoints.addAll(points);
343  clearGeometry();
344  }
345 
346  @VisibleForTesting
347  boolean isInitialized() {
348  return initialized;
349  }
350 }
com.google.appinventor.components.runtime.util.ErrorMessages.ERROR_POLYGON_PARSE_ERROR
static final int ERROR_POLYGON_PARSE_ERROR
Definition: ErrorMessages.java:233
com.google.appinventor.components.runtime.Polygon.PointsFromString
void PointsFromString(String pointString)
Definition: Polygon.java:189
com.google.appinventor.components.runtime.util.YailList
Definition: YailList.java:26
com.google.appinventor.components.runtime.util.MapFactory.MapCircle
Definition: MapFactory.java:1028
com.google.appinventor.components.runtime.HandlesEventDispatching.dispatchErrorOccurredEvent
void dispatchErrorOccurredEvent(Component component, String functionName, int errorCode, Object... args)
com.google.appinventor.components.annotations.SimpleFunction
Definition: SimpleFunction.java:23
com.google.appinventor.components.runtime.util.MapFactory.MapFeatureContainer.addFeature
void addFeature(MapFeature feature)
com.google.appinventor.components.runtime.errors.DispatchableError
Definition: DispatchableError.java:12
com.google.appinventor.components.runtime.util.ErrorMessages
Definition: ErrorMessages.java:17
com.google.appinventor.components.runtime.util
-*- mode: java; c-basic-offset: 2; -*-
Definition: AccountChooser.java:7
com.google.appinventor.components.runtime.util.MapFactory
Definition: MapFactory.java:30
com.google.appinventor.components.runtime.Polygon.Polygon
Polygon(MapFactory.MapFeatureContainer container)
Definition: Polygon.java:110
com.google.appinventor.components.runtime.Polygon.Points
YailList Points()
Definition: Polygon.java:134
com.google.appinventor.components.runtime.Polygon.HolePoints
void HolePoints(YailList points)
Definition: Polygon.java:243
com.google.appinventor.components.runtime.util.MapFactory.MapController.updateFeaturePosition
void updateFeaturePosition(MapMarker marker)
com.google.appinventor.components.common.YaVersion
Definition: YaVersion.java:14
com.google.appinventor.components.runtime.util.MapFactory.MapController.updateFeatureHoles
void updateFeatureHoles(MapPolygon polygon)
com.google.appinventor.components.annotations.DesignerProperty
Definition: DesignerProperty.java:25
com.google.appinventor.components.runtime.util.GeometryUtil.multiPolygonFromYailList
static List< List< GeoPoint > > multiPolygonFromYailList(YailList list)
Definition: GeometryUtil.java:500
com.google.appinventor.components
com.google.appinventor.components.runtime.util.YailList.makeList
static YailList makeList(Object[] objects)
Definition: YailList.java:59
com.google.appinventor.components.runtime.util.GeometryUtil.multiPolygonHolesFromYailList
static List< List< List< GeoPoint > > > multiPolygonHolesFromYailList(YailList points)
Definition: GeometryUtil.java:509
com.google.appinventor.components.runtime.util.MapFactory.MapLineString
Definition: MapFactory.java:1373
com.google.appinventor.components.runtime.util.MapFactory.MapPolygon
Definition: MapFactory.java:1410
com.google.appinventor.components.runtime.util.GeometryUtil.pointsListToYailList
static YailList pointsListToYailList(List<? extends IGeoPoint > points)
Definition: GeometryUtil.java:84
com.google.appinventor.components.runtime.util.GeometryUtil.pointsFromYailList
static List< GeoPoint > pointsFromYailList(YailList points)
Definition: GeometryUtil.java:104
com.google.appinventor.components.runtime.Map.getController
MapController getController()
Definition: Map.java:667
com.google.appinventor.components.annotations.DesignerComponent
Definition: DesignerComponent.java:22
com.google.appinventor.components.runtime.util.GeometryUtil.distanceBetweenEdges
static double distanceBetweenEdges(MapMarker marker, MapLineString lineString)
Definition: GeometryUtil.java:249
com.google.appinventor.components.runtime.Polygon.Points
void Points(YailList points)
Definition: Polygon.java:158
com.google.appinventor.components.annotations.PropertyCategory.BEHAVIOR
BEHAVIOR
Definition: PropertyCategory.java:15
com.google.appinventor.components.runtime.util.MapFactory.MapRectangle
Definition: MapFactory.java:1099
com.google.appinventor.components.runtime.Polygon.getPoints
List< List< GeoPoint > > getPoints()
Definition: Polygon.java:313
com.google.appinventor.components.runtime.PolygonBase
Definition: PolygonBase.java:17
com.google.appinventor.components.runtime.util.GeometryUtil.distanceBetweenCentroids
static double distanceBetweenCentroids(MapMarker marker, MapLineString lineString)
Definition: GeometryUtil.java:327
com.google.appinventor.components.runtime.Component.getDispatchDelegate
HandlesEventDispatching getDispatchDelegate()
com.google.appinventor.components.runtime.Polygon.getHolePoints
List< List< List< GeoPoint > > > getHolePoints()
Definition: Polygon.java:318
com.google.appinventor.components.runtime.util.MapFactory.MapFeatureVisitor.visit
T visit(MapMarker marker, Object... arguments)
com.google.appinventor.components.runtime.Polygon.updatePoints
void updatePoints(List< List< GeoPoint >> points)
Definition: Polygon.java:333
com.google.appinventor.components.runtime.MapFeatureBase.container
MapFeatureContainer container
Definition: MapFeatureBase.java:33
com.google.appinventor.components.runtime.Polygon
Definition: Polygon.java:55
com.google.appinventor.components.runtime.MapFeatureBase.map
Map map
Definition: MapFeatureBase.java:34
com.google.appinventor.components.common.PropertyTypeConstants.PROPERTY_TYPE_TEXTAREA
static final String PROPERTY_TYPE_TEXTAREA
Definition: PropertyTypeConstants.java:248
com.google.appinventor.components.runtime.util.MapFactory.MapMarker
Definition: MapFactory.java:1205
com.google.appinventor.components.runtime.errors.DispatchableError.getArguments
Object[] getArguments()
Definition: DispatchableError.java:34
com.google.appinventor.components.runtime.util.GeometryUtil.multiPolygonHolesToList
static List< List< List< GeoPoint > > > multiPolygonHolesToList(JSONArray array)
Definition: GeometryUtil.java:525
com.google.appinventor.components.annotations.SimpleProperty
Definition: SimpleProperty.java:23
com.google.appinventor.components.runtime.util.GeometryUtil
Definition: GeometryUtil.java:41
com.google.appinventor.components.annotations.PropertyCategory
Definition: PropertyCategory.java:13
com.google.appinventor.components.runtime.util.MapFactory.MapController.updateFeatureText
void updateFeatureText(MapFeature feature)
com.google.appinventor.components.runtime.util.GeometryUtil.createGeometry
static Geometry createGeometry(GeoPoint point)
Definition: GeometryUtil.java:120
com.google.appinventor.components.runtime
Copyright 2009-2011 Google, All Rights reserved.
Definition: AccelerometerSensor.java:8
com.google.appinventor.components.runtime.Polygon.updateHolePoints
void updateHolePoints(List< List< List< GeoPoint >>> points)
Definition: Polygon.java:340
com.google.appinventor.components.runtime.Polygon.Initialize
void Initialize()
Definition: Polygon.java:115
com.google.appinventor.components.common
Definition: ComponentCategory.java:7
com.google.appinventor.components.common.ComponentCategory
Definition: ComponentCategory.java:48
com.google.appinventor.components.runtime.util.GeometryUtil.isPolygon
static boolean isPolygon(YailList points)
Definition: GeometryUtil.java:545
com.google.appinventor.components.runtime.Polygon.HolePoints
YailList HolePoints()
Definition: Polygon.java:221
com.google.appinventor.components.runtime.Form.dispatchErrorOccurredEvent
void dispatchErrorOccurredEvent(final Component component, final String functionName, final int errorNumber, final Object... messageArgs)
Definition: Form.java:1011
com.google.appinventor.components.runtime.util.MapFactory.MapFeatureType
Definition: MapFactory.java:1483
com.google.appinventor.components.annotations.SimpleObject
Definition: SimpleObject.java:23
com.google
com
com.google.appinventor.components.runtime.MapFeatureBase.clearGeometry
final synchronized void clearGeometry()
Definition: MapFeatureBase.java:430
com.google.appinventor.components.runtime.Polygon.HolePointsFromString
void HolePointsFromString(String pointString)
Definition: Polygon.java:277
com.google.appinventor.components.runtime.Polygon.Centroid
YailList Centroid()
Definition: Polygon.java:308
com.google.appinventor.components.runtime.errors
Definition: ArrayIndexOutOfBoundsError.java:7
com.google.appinventor.components.runtime.ComponentContainer.$form
Form $form()
com.google.appinventor.components.runtime.util.GeometryUtil.multiPolygonToList
static List< List< GeoPoint > > multiPolygonToList(JSONArray array)
Definition: GeometryUtil.java:478
com.google.appinventor.components.runtime.util.MapFactory.MapFeatureContainer
Definition: MapFactory.java:800
com.google.appinventor.components.runtime.util.YailList.makeEmptyList
static YailList makeEmptyList()
Definition: YailList.java:52
com.google.appinventor.components.runtime.util.GeometryUtil.multiPolygonToYailList
static YailList multiPolygonToYailList(List< List< GeoPoint >> multipolygon)
Definition: GeometryUtil.java:492
com.google.appinventor.components.runtime.util.MapFactory.MapFeatureVisitor
Definition: MapFactory.java:745
com.google.appinventor.components.common.PropertyTypeConstants
Definition: PropertyTypeConstants.java:14
com.google.appinventor.components.annotations
com.google.appinventor.components.runtime.Polygon.Type
String Type()
Definition: Polygon.java:127
com.google.appinventor.components.runtime.util.YailList.size
int size()
Definition: YailList.java:172
com.google.appinventor.components.runtime.util.GeometryUtil.isMultiPolygon
static boolean isMultiPolygon(YailList points)
Definition: GeometryUtil.java:566
com.google.appinventor
com.google.appinventor.components.runtime.errors.DispatchableError.getErrorCode
int getErrorCode()
Definition: DispatchableError.java:30
com.google.appinventor.components.runtime.Polygon.computeGeometry
Geometry computeGeometry()
Definition: Polygon.java:328