📄 kmlreflector.java
字号:
String filter = (String) requestParams.get("FEATUREID");
filters = new ArrayList();
for ( int i = 0; i < layers.length; i++ ) {
filters.add(filter);
}
filterKey = "featureid";
}
if ( filters != null && filters.size() != layers.length) {
throw (IOException) new IOException().initCause(
new ServiceException( layers.length + " layers specified, but " + filters.size() + " filters")
);
}
//set the content disposition
StringBuffer filename = new StringBuffer();
for ( int i = 0; i < layers.length; i++ ) {
String name = layers[i].getName();
//strip off prefix
int j = name.indexOf(':');
if ( j > -1 ) {
name = name.substring( j + 1 );
}
filename.append(name + "_");
}
filename.setLength(filename.length()-1);
response.setHeader("Content-Disposition",
"attachment; filename=" + filename.toString() + ".kml");
// we use the mandatory SRS value of 4326 (lat/lon)
serviceRequest.setFormat(KML_MIME_TYPE); // output mime type of KML
StringBuffer sb = new StringBuffer();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
sb.append("<kml xmlns=\"http://earth.google.com/kml/2.0\">\n");
sb.append("<Folder>\n");
String proxifiedBaseUrl = RequestUtils.baseURL(request);
GeoServer gs = (GeoServer)GeoServerExtensions.extensions(GeoServer.class).get(0);
proxifiedBaseUrl = RequestUtils.proxifiedBaseURL(proxifiedBaseUrl,gs.getProxyBaseUrl());
Envelope layerbbox = null;
// make a network link for every layer
for (int i = 0; i < layers.length; i++) {
//if (layers[i].getType() == MapLayerInfo.TYPE_VECTOR) {
String style = "&styles=" + layers[i].getDefaultStyle().getName();
if ((styles != null) && (styles.length >= (i + 1))) { // if the user specified styles
style = "&styles=" + styles[i].getName(); // use them, else we use the default style
}
String filter = (String) (filters != null ? filters.get(i) : null);
if ( filter != null ) {
filter = "&" + filterKey + "=" + filter;
}
else {
filter = "";
}
if (serviceRequest.getSuperOverlay()) {
Envelope bbox = serviceRequest.getBbox();
sb.append("<NetworkLink>\n");
sb.append("<name>" + layers[0].getName() + "</name>\n");
sb.append("<Region>");
sb.append("<LatLonAltBox>");
sb.append("<north>" + bbox.getMaxY() + "</north>");
sb.append("<south>" + bbox.getMinY() + "</south>");
sb.append("<east>" + bbox.getMaxX() + "</east>");
sb.append("<west>" + bbox.getMinX() + "</west>");
sb.append("</LatLonAltBox>");
sb.append("<Lod>");
sb.append("<minLodPixels>256</minLodPixels>");
sb.append("<maxLodPixels>-1</maxLodPixels>");
sb.append("</Lod>");
sb.append("</Region>");
sb.append("<Link>\n");
sb.append("<href><![CDATA[" + proxifiedBaseUrl
+ "/wms?service=WMS&request=GetMap&format=application/vnd.google-earth.kml+XML"
+ "&width=" + WIDTH + "&height=" + HEIGHT + "&srs=" + SRS + "&layers="
+ layers[i].getName() + style + "&bbox=" + (String) requestParams.get("BBOX")
+ filter
+ "&legend=" + String.valueOf(serviceRequest.getLegend())
+ "&superoverlay=true]]></href>\n");
sb.append("<viewRefreshMode>onRegion</viewRefreshMode>\n");
sb.append("</Link>\n");
sb.append("</NetworkLink>\n");
} else {
// Envelope le = (layers[i].getFeature() == null ? layers[i].getBoundingBox() : layers[i].getFeature().getLatLongBoundingBox());
Envelope le = layers[i].getLatLongBoundingBox();
if (layerbbox == null){
layerbbox = new Envelope(le);
} else {
layerbbox.expandToInclude(le);
}
sb.append("<NetworkLink>\n");
sb.append(getLookAt(le));
sb.append("<name>" + layers[i].getName() + "</name>\n");
sb.append("<open>1</open>\n");
sb.append("<visibility>1</visibility>\n");
sb.append("<Url>\n");
sb.append("<href><![CDATA[" + proxifiedBaseUrl
+ "/wms?service=WMS&request=GetMap&format=application/vnd.google-earth.kmz+XML"
+ "&width=" + WIDTH + "&height=" + HEIGHT + "&srs=" + SRS + "&layers="
+ layers[i].getName() + style + filter // optional
+ "&KMScore=" + serviceRequest.getKMScore() + "&KMAttr="
+ String.valueOf(serviceRequest.getKMattr()) + "&legend="
+ String.valueOf(serviceRequest.getLegend()) + "]]></href>\n");
sb.append("<viewRefreshMode>onStop</viewRefreshMode>\n");
sb.append("<viewRefreshTime>" + REFRESH + "</viewRefreshTime>\n");
sb.append("</Url>\n");
sb.append("</NetworkLink>\n");
}
}
sb.append(getLookAt(layerbbox));
sb.append("</Folder>\n");
sb.append("</kml>\n");
byte[] kml_b = sb.toString().getBytes();
out.write(kml_b);
out.flush();
}
private String getLookAt(Envelope e){
double lon1 = e.getMinX();
double lat1 = e.getMinY();
double lon2 = e.getMaxX();
double lat2 = e.getMaxY();
double R_EARTH = 6.371 * 1000000; // meters
double VIEWER_WIDTH = 22 * Math.PI / 180; // The field of view of the google maps camera, in radians
double[] p1 = getRect(lon1, lat1, R_EARTH);
double[] p2 = getRect(lon2, lat2, R_EARTH);
double[] midpoint = new double[]{
(p1[0] + p2[0])/2,
(p1[1] + p2[1])/2,
(p1[2] + p2[2])/2
};
midpoint = getGeographic(midpoint[0], midpoint[1], midpoint[2]);
// averaging the longitudes; using the rectangular coordinates makes the calculated center tend toward the corner that's closer to the equator.
midpoint[0] = ((lon1 + lon2)/2);
double distance = distance(p1, p2);
double height = distance/ (2 * Math.tan(VIEWER_WIDTH));
LOGGER.fine("lat1: " + lat1 + "; lon1: " + lon1);
LOGGER.fine("lat2: " + lat2 + "; lon2: " + lon2);
LOGGER.fine("latmid: " + midpoint[1] + "; lonmid: " + midpoint[0]);
return "<LookAt id=\"geoserver\">" +
" <longitude>" + ((lon1 + lon2)/2) + "</longitude> <!-- kml:angle180 -->" +
" <latitude>"+midpoint[1]+"</latitude> <!-- kml:angle90 -->" +
" <altitude>0</altitude> <!-- double --> " +
" <range>"+distance+"</range> <!-- double -->" +
" <tilt>0</tilt> <!-- float -->" +
" <heading>0</heading> <!-- float -->" +
" <altitudeMode>clampToGround</altitudeMode> " +
" <!--kml:altitudeModeEnum:clampToGround, relativeToGround, absolute -->" +
"</LookAt>";
}
private double[] getRect(double lat, double lon, double radius){
double theta = (90 - lat) * Math.PI/180;
double phi = (90 - lon) * Math.PI/180;
double x = radius * Math.sin(phi) * Math.cos(theta);
double y = radius * Math.sin(phi) * Math.sin(theta);
double z = radius * Math.cos(phi);
return new double[]{x, y, z};
}
private double[] getGeographic(double x, double y, double z){
double theta, phi, radius;
radius = distance(new double[]{x, y, z}, new double[]{0,0,0});
theta = Math.atan2(Math.sqrt(x * x + y * y) , z);
phi = Math.atan2(y , x);
double lat = 90 - (theta * 180 / Math.PI);
double lon = 90 - (phi * 180 / Math.PI);
return new double[]{(lon > 180 ? lon - 360 : lon), lat, radius};
}
private double distance(double[] p1, double[] p2){
double dx = p1[0] - p2[0];
double dy = p1[1] - p2[1];
double dz = p1[2] - p2[2];
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -