Construct a KML document and save it as a KMZ file.
Use case
If you need to create and save data on the fly, you can use KML to create points, lines, and polygons by sketching on the map, customizing the style, and serializing them as KML nodes in a KML Document. Once complete, you can share the KML data with others that are using a KML reading application, such as ArcGIS Earth.
How to use the sample
Select the geometry type for sketching with the first combo box. Change the
style for the KML feature using the second combo box.
Click anywhere on the map to sketch. Press ENTER to commit the sketch or ESCAPE to discard the sketch.
When finished, click the 'Save KMZ file' button to save the KML document to a KMZ file.
How it works
Create a KmlDocument
Create a KmlDataset using the KML document.
Create a KmlLayer using the KML dataset and add it to the map as an operational layer.
Create Geometry using SketchEditor.
Project that geometry to WGS84 using GeometryEngine.project.
Create a KmlGeometry object using the projected geometry.
Create a KmlPlacemark using the KML geometry.
Add the KML placemark to the KML document.
Set the KmlStyle for the KML placemark.
Save the KML document to a file using kmlDocument.saveAsAsync(Path).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*
* Copyright 2019 Esri.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/package com.esri.samples.create_and_save_kml_file;
import com.esri.arcgisruntime.ArcGISRuntimeEnvironment;
import com.esri.arcgisruntime.geometry.Geometry;
import com.esri.arcgisruntime.geometry.GeometryEngine;
import com.esri.arcgisruntime.geometry.SpatialReferences;
import com.esri.arcgisruntime.layers.KmlLayer;
import com.esri.arcgisruntime.mapping.ArcGISMap;
import com.esri.arcgisruntime.mapping.BasemapStyle;
import com.esri.arcgisruntime.mapping.view.MapView;
import com.esri.arcgisruntime.mapping.view.SketchCreationMode;
import com.esri.arcgisruntime.mapping.view.SketchEditor;
import com.esri.arcgisruntime.ogc.kml.KmlAltitudeMode;
import com.esri.arcgisruntime.ogc.kml.KmlDataset;
import com.esri.arcgisruntime.ogc.kml.KmlDocument;
import com.esri.arcgisruntime.ogc.kml.KmlGeometry;
import com.esri.arcgisruntime.ogc.kml.KmlIcon;
import com.esri.arcgisruntime.ogc.kml.KmlIconStyle;
import com.esri.arcgisruntime.ogc.kml.KmlLineStyle;
import com.esri.arcgisruntime.ogc.kml.KmlPlacemark;
import com.esri.arcgisruntime.ogc.kml.KmlPolygonStyle;
import com.esri.arcgisruntime.ogc.kml.KmlStyle;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.ComboBox;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.FileChooser;
import java.io.File;
import java.util.Arrays;
import java.util.List;
publicclassCreateAndSaveKMLFileController{
@FXMLprivate StackPane stackPane;
@FXMLprivate ColorPicker colorPicker;
@FXMLprivate ComboBox<String> pointSymbolComboBox;
@FXMLprivate ComboBox<SketchCreationMode> sketchCreationModeComboBox;
@FXMLprivate MapView mapView;
private ArcGISMap map; // keep loadable in scope to avoid garbage collectionprivate KmlDocument kmlDocument;
private SketchEditor sketchEditor;
private FileChooser fileChooser;
@FXMLpublicvoidinitialize(){
// authentication with an API key or named user is required to access basemaps and other location services String yourAPIKey = System.getProperty("apiKey");
ArcGISRuntimeEnvironment.setApiKey(yourAPIKey);
// create a map and add it to the map view map = new ArcGISMap(BasemapStyle.ARCGIS_DARK_GRAY);
mapView.setMap(map);
// create a sketch editor and add it to the map view sketchEditor = new SketchEditor();
mapView.setSketchEditor(sketchEditor);
// add geometry options for KML placemarks sketchCreationModeComboBox.getItems().addAll(SketchCreationMode.POINT, SketchCreationMode.POLYLINE, SketchCreationMode.POLYGON);
// restart the sketch editor whenever the selected creation mode changes sketchCreationModeComboBox.getSelectionModel().selectedItemProperty().addListener(o -> startSketch());
// start with POINT selected map.addDoneLoadingListener(() -> sketchCreationModeComboBox.getSelectionModel().select(0));
// show style controls relevant to the selected sketch creation mode colorPicker.visibleProperty().bind(sketchCreationModeComboBox.getSelectionModel().selectedItemProperty().isNotEqualTo(SketchCreationMode.POINT));
pointSymbolComboBox.visibleProperty().bind(sketchCreationModeComboBox.getSelectionModel().selectedItemProperty().isEqualTo(SketchCreationMode.POINT));
// set the images for the icon selection combo box List<String> iconLinks = Arrays.asList(
null, // for the default symbol"https://static.arcgis.com/images/Symbols/Shapes/BlueCircleLargeB.png",
"https://static.arcgis.com/images/Symbols/Shapes/BlueDiamondLargeB.png",
"https://static.arcgis.com/images/Symbols/Shapes/BluePin1LargeB.png",
"https://static.arcgis.com/images/Symbols/Shapes/BluePin2LargeB.png",
"https://static.arcgis.com/images/Symbols/Shapes/BlueSquareLargeB.png",
"https://static.arcgis.com/images/Symbols/Shapes/BlueStarLargeB.png");
pointSymbolComboBox.getItems().addAll(iconLinks);
pointSymbolComboBox.setCellFactory(comboBox -> new ImageURLListCell());
pointSymbolComboBox.setButtonCell(new ImageURLListCell());
pointSymbolComboBox.getSelectionModel().select(0);
// create a KML layer from a blank KML document and add it to the map kmlDocument = new KmlDocument();
var kmlDataset = new KmlDataset(kmlDocument);
var kmlLayer = new KmlLayer(kmlDataset);
map.getOperationalLayers().add(kmlLayer);
// create a file chooser to get a path for saving the KMZ file fileChooser = new FileChooser();
FileChooser.ExtensionFilter kmzFilter = new FileChooser.ExtensionFilter("KMZ files (*.kmz)", "*.kmz");
fileChooser.getExtensionFilters().add(kmzFilter);
fileChooser.setTitle("Save KMZ file:");
}
/**
* Starts the sketch editor based on the selected sketch creation mode.
*/@FXMLprivatevoidstartSketch(){
// stop the sketch editor sketchEditor.stop();
// request focus on stack pane to receive key events stackPane.requestFocus();
// start the sketch editor with the selected creation mode sketchEditor.start(sketchCreationModeComboBox.getSelectionModel().getSelectedItem());
}
/**
* Discard or commit the current sketch to a KML placemark if ESCAPE or ENTER are pressed while sketching.
*
* @param keyEvent the key event
*/@FXMLprivatevoidhandleKeyReleased(KeyEvent keyEvent){
if (keyEvent.getCode() == KeyCode.ESCAPE) {
// clear the current sketch and start a new sketch startSketch();
} elseif (keyEvent.getCode() == KeyCode.ENTER && sketchEditor.isSketchValid()) {
// project the sketched geometry to WGS84 to comply with the KML standard Geometry sketchGeometry = sketchEditor.getGeometry();
Geometry projectedGeometry = GeometryEngine.project(sketchGeometry, SpatialReferences.getWgs84());
// create a new KML placemarkvar kmlGeometry = new KmlGeometry(projectedGeometry, KmlAltitudeMode.CLAMP_TO_GROUND);
var currentKmlPlacemark = new KmlPlacemark(kmlGeometry);
// update the style of the current KML placemarkvar kmlStyle = new KmlStyle();
currentKmlPlacemark.setStyle(kmlStyle);
// set the selected style for the placemarkswitch (sketchGeometry.getGeometryType()) {
case POINT:
if (pointSymbolComboBox.getSelectionModel().getSelectedItem() != null) {
String iconURI = pointSymbolComboBox.getSelectionModel().getSelectedItem();
var kmlIcon = new KmlIcon(iconURI);
var kmlIconStyle = new KmlIconStyle(kmlIcon, 1);
kmlStyle.setIconStyle(kmlIconStyle);
}
break;
case POLYLINE:
Color polylineColor = colorPicker.getValue();
if (polylineColor != null) {
var kmlLineStyle = new KmlLineStyle(polylineColor, 8);
kmlStyle.setLineStyle(kmlLineStyle);
}
break;
case POLYGON:
Color polygonColor = colorPicker.getValue();
if (polygonColor != null) {
var kmlPolygonStyle = new KmlPolygonStyle(polygonColor);
kmlPolygonStyle.setFilled(true);
kmlPolygonStyle.setOutlined(false);
kmlStyle.setPolygonStyle(kmlPolygonStyle);
}
break;
}
// add the placemark to the kml document kmlDocument.getChildNodes().add(currentKmlPlacemark);
// start a new sketch startSketch();
}
}
/**
* Open the file chooser to save the KML Document to a KMZ file.
*/@FXMLprivatevoidhandleSaveAction(){
// get a path from the file chooser File kmzFile = fileChooser.showSaveDialog(mapView.getScene().getWindow());
if (kmzFile != null) {
// save the KML document to the file kmlDocument.saveAsAsync(kmzFile.getPath()).addDoneListener(() ->
new Alert(Alert.AlertType.INFORMATION, "KMZ file saved.").show()
);
}
}
/**
* Stops and releases all resources used in application.
*/voidterminate(){
if (mapView != null) {
mapView.dispose();
}
}
}