Skip to content

Commit 1199cb6

Browse files
authored
Merge pull request #247 from Esri/query-map-image-sublayers
Query map image sublayers
2 parents 7a47d9c + 84310d9 commit 1199cb6

File tree

3 files changed

+262
-0
lines changed

3 files changed

+262
-0
lines changed
197 KB
Loading
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
/*
2+
* Copyright 2018 Esri.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
17+
package com.esri.samples.imagelayers.query_map_image_sublayer;
18+
19+
import javafx.application.Application;
20+
import javafx.geometry.Insets;
21+
import javafx.geometry.Pos;
22+
import javafx.scene.Scene;
23+
import javafx.scene.control.Alert;
24+
import javafx.scene.control.Button;
25+
import javafx.scene.control.Label;
26+
import javafx.scene.control.Spinner;
27+
import javafx.scene.layout.StackPane;
28+
import javafx.scene.layout.VBox;
29+
import javafx.stage.Stage;
30+
31+
import com.esri.arcgisruntime.concurrent.ListenableFuture;
32+
import com.esri.arcgisruntime.data.Feature;
33+
import com.esri.arcgisruntime.data.FeatureQueryResult;
34+
import com.esri.arcgisruntime.data.QueryParameters;
35+
import com.esri.arcgisruntime.data.ServiceFeatureTable;
36+
import com.esri.arcgisruntime.geometry.Point;
37+
import com.esri.arcgisruntime.geometry.SpatialReferences;
38+
import com.esri.arcgisruntime.layers.ArcGISMapImageLayer;
39+
import com.esri.arcgisruntime.layers.ArcGISMapImageSublayer;
40+
import com.esri.arcgisruntime.loadable.LoadStatus;
41+
import com.esri.arcgisruntime.mapping.ArcGISMap;
42+
import com.esri.arcgisruntime.mapping.Basemap;
43+
import com.esri.arcgisruntime.mapping.Viewpoint;
44+
import com.esri.arcgisruntime.mapping.view.Graphic;
45+
import com.esri.arcgisruntime.mapping.view.GraphicsOverlay;
46+
import com.esri.arcgisruntime.mapping.view.MapView;
47+
import com.esri.arcgisruntime.symbology.SimpleFillSymbol;
48+
import com.esri.arcgisruntime.symbology.SimpleLineSymbol;
49+
import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol;
50+
51+
public class QueryMapImageSublayerSample extends Application {
52+
53+
private MapView mapView;
54+
55+
@Override
56+
public void start(Stage stage) throws Exception {
57+
58+
try {
59+
// create a stack pane and application scene
60+
StackPane stackPane = new StackPane();
61+
Scene scene = new Scene(stackPane);
62+
scene.getStylesheets().add(getClass().getResource("/css/style.css").toExternalForm());
63+
64+
// size the stage and add a title
65+
stage.setTitle("Query Map Image Sublayer Sample");
66+
stage.setWidth(800);
67+
stage.setHeight(700);
68+
stage.setScene(scene);
69+
stage.show();
70+
71+
// create a map with a basemap and set its initial viewpoint
72+
ArcGISMap map = new ArcGISMap(Basemap.createStreetsVector());
73+
Point initialLocation = new Point(-12716000.00, 4170400.00, SpatialReferences.getWebMercator());
74+
Viewpoint viewpoint = new Viewpoint(initialLocation, 6000000);
75+
map.setInitialViewpoint(viewpoint);
76+
77+
// create and add a map image layer to the map
78+
ArcGISMapImageLayer imageLayer = new ArcGISMapImageLayer("https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer");
79+
map.getOperationalLayers().add(imageLayer);
80+
81+
// create a map view and set the map to it
82+
mapView = new MapView();
83+
mapView.setMap(map);
84+
85+
// create a graphics overlay to show the results in
86+
GraphicsOverlay graphicsOverlay = new GraphicsOverlay();
87+
mapView.getGraphicsOverlays().add(graphicsOverlay);
88+
89+
// create symbols for showing the results of each sublayer
90+
SimpleMarkerSymbol citySymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.Style.CIRCLE, 0xFFFF0000, 16);
91+
SimpleLineSymbol stateSymbol = new SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, 0xFF0000FF, 6);
92+
SimpleLineSymbol countyLineSymbol = new SimpleLineSymbol(SimpleLineSymbol.Style.DASH, 0xFF00FFFF, 2);
93+
SimpleFillSymbol countySymbol = new SimpleFillSymbol(SimpleFillSymbol.Style.DIAGONAL_CROSS, 0xFF00FFFF,
94+
countyLineSymbol);
95+
96+
// create a vbox to hold the controls
97+
VBox vBoxControl = new VBox(6);
98+
vBoxControl.setMaxSize(170, 100);
99+
vBoxControl.getStyleClass().add("panel-region");
100+
101+
// create a spinner to input the population filter
102+
Label label = new Label("Population greater than");
103+
Spinner<Integer> populationSpinner = new Spinner<>(0, 100000000, 1800000);
104+
populationSpinner.setEditable(true);
105+
106+
// create a button to execute the query, disable initially
107+
Button queryButton = new Button("Query");
108+
queryButton.setDisable(true);
109+
110+
// add the controls to the vbox
111+
vBoxControl.getChildren().addAll(label, populationSpinner, queryButton);
112+
113+
// wait until the layer is loaded before enabling the query button
114+
imageLayer.addDoneLoadingListener(() -> {
115+
if (imageLayer.getLoadStatus() == LoadStatus.LOADED) {
116+
queryButton.setDisable(false);
117+
118+
// get and load each sublayer to query
119+
ArcGISMapImageSublayer citiesSublayer = (ArcGISMapImageSublayer) imageLayer.getSublayers().get(0);
120+
ArcGISMapImageSublayer statesSublayer = (ArcGISMapImageSublayer) imageLayer.getSublayers().get(2);
121+
ArcGISMapImageSublayer countiesSublayer = (ArcGISMapImageSublayer) imageLayer.getSublayers().get(3);
122+
citiesSublayer.loadAsync();
123+
statesSublayer.loadAsync();
124+
countiesSublayer.loadAsync();
125+
126+
// query the sublayers when the button is clicked
127+
queryButton.setOnAction(e -> {
128+
129+
// clear any previous results
130+
graphicsOverlay.getGraphics().clear();
131+
132+
// create query parameters filtering based on population and the map view's current viewpoint
133+
QueryParameters populationQuery = new QueryParameters();
134+
populationQuery.setWhereClause("POP2000 > " + populationSpinner.getValue());
135+
populationQuery.setGeometry(mapView.getCurrentViewpoint(Viewpoint.Type.BOUNDING_GEOMETRY)
136+
.getTargetGeometry());
137+
138+
// query each sublayer's feature table with the query parameters and display the result features as graphics
139+
if (citiesSublayer.getLoadStatus() == LoadStatus.LOADED) {
140+
ServiceFeatureTable citiesTable = citiesSublayer.getTable();
141+
ListenableFuture<FeatureQueryResult> citiesQuery = citiesTable.queryFeaturesAsync(populationQuery);
142+
citiesQuery.addDoneListener(() -> {
143+
try {
144+
FeatureQueryResult result = citiesQuery.get();
145+
for (Feature feature : result) {
146+
Graphic cityGraphic = new Graphic(feature.getGeometry(), citySymbol);
147+
graphicsOverlay.getGraphics().add(cityGraphic);
148+
}
149+
} catch (Exception ex) {
150+
new Alert(Alert.AlertType.ERROR, "Failed to query cities").show();
151+
}
152+
});
153+
}
154+
155+
if (statesSublayer.getLoadStatus() == LoadStatus.LOADED) {
156+
ServiceFeatureTable statesTable = statesSublayer.getTable();
157+
ListenableFuture<FeatureQueryResult> statesQuery = statesTable.queryFeaturesAsync(populationQuery);
158+
statesQuery.addDoneListener(() -> {
159+
try {
160+
FeatureQueryResult result = statesQuery.get();
161+
for (Feature feature : result) {
162+
Graphic stateGraphic = new Graphic(feature.getGeometry(), stateSymbol);
163+
graphicsOverlay.getGraphics().add(stateGraphic);
164+
}
165+
} catch (Exception ex) {
166+
new Alert(Alert.AlertType.ERROR, "Failed to query states").show();
167+
}
168+
});
169+
}
170+
171+
if (countiesSublayer.getLoadStatus() == LoadStatus.LOADED) {
172+
ServiceFeatureTable countiesTable = countiesSublayer.getTable();
173+
ListenableFuture<FeatureQueryResult> countiesQuery = countiesTable.queryFeaturesAsync(populationQuery);
174+
countiesQuery.addDoneListener(() -> {
175+
try {
176+
FeatureQueryResult result = countiesQuery.get();
177+
for (Feature feature : result) {
178+
Graphic countyGraphic = new Graphic(feature.getGeometry(), countySymbol);
179+
graphicsOverlay.getGraphics().add(countyGraphic);
180+
}
181+
} catch (Exception ex) {
182+
new Alert(Alert.AlertType.ERROR, "Failed to query counties").show();
183+
}
184+
});
185+
}
186+
187+
});
188+
} else {
189+
new Alert(Alert.AlertType.ERROR, imageLayer.getLoadError().getMessage()).show();
190+
}
191+
});
192+
193+
// add the mapview and controls to the stack pane
194+
stackPane.getChildren().addAll(mapView, vBoxControl);
195+
StackPane.setAlignment(vBoxControl, Pos.TOP_LEFT);
196+
StackPane.setMargin(vBoxControl, new Insets(10, 0, 0, 10));
197+
198+
} catch (Exception e) {
199+
// on any error, display the stack trace.
200+
e.printStackTrace();
201+
}
202+
}
203+
204+
@Override
205+
public void stop() {
206+
207+
// releases resources when the application closes
208+
if (mapView != null) {
209+
mapView.dispose();
210+
}
211+
}
212+
213+
/**
214+
* Starting point of this application.
215+
*
216+
* @param args arguments to this application.
217+
*/
218+
public static void main(String[] args) {
219+
220+
Application.launch(args);
221+
}
222+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<h1>Query Map Image Sublayer</h1>
2+
3+
<p>This sample demonstrates how to execute an attribute and spatial query on the sublayers of an ArcGIS map image
4+
layer.</p>
5+
6+
<p>Sublayers of an <code>ArcGISMapImageLayer</code> may expose a <code>ServiceFeatureTable</code> through a
7+
<code>Table</code> property. This allows you to perform the same queries available when working with a table from a
8+
<code>FeatureLayer</code>: attribute query, spatial query, statistics query, query for related features, and so on.
9+
10+
<p><img src="QueryMapImageSublayer.png"></p>
11+
12+
<h2>How to use the sample:</h2>
13+
14+
<p>Specify a minimum population in the spinner and click the query button to query the sublayers. After a short time,
15+
the results for each sublayer will appear as graphics.</p>
16+
17+
<h2>How it works</h2>
18+
19+
<p>To query map image sublayers:</p>
20+
21+
<ol>
22+
<li>Create an <code>ArcGISMapImageLayer</code> using the URL of it's image service.</li>
23+
<li>After loading the layer, get its sublayers you want to query with <code>(ArcGISMapImageSublayer) layer
24+
.getSubLayers().get(index)</code>.</li>
25+
<li>Load the sublayer, and then get its <code>ServiceFeatureTable</code> with <code>sublayer.getTable()</code>.</li>
26+
<li>Create <code>QueryParameters</code>. You can use the where clause to query against a table attribute or set
27+
the parameters geometry to limit the results to an area of the map.</li>
28+
<li>Call <code>sublayerTable.queryFeaturesAsync(queryParameters)</code> to get a <code>FeatureQueryResult</code>
29+
with features matching the query.</li>
30+
<li>Iterate through the result features to use them however you wish.</li>
31+
</ol>
32+
33+
<h2>Features</h2>
34+
35+
<ul>
36+
<li>ArcGISMapImageLayer</li>
37+
<li>ArcGISMapImageSublayer</li>
38+
<li>QueryParameters</li>
39+
<li>ServiceFeatureTable</li>
40+
</ul>

0 commit comments

Comments
 (0)