Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AUS-3964 #154

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export class CsMapService {
for (const layerModel of this.layerModelList) {
if (!UtilitiesService.layerContainsResourceType(layerModel, ResourceType.WMS) &&
!UtilitiesService.layerContainsResourceType(layerModel, ResourceType.WWW) &&
!UtilitiesService.layerContainsResourceType(layerModel, ResourceType.KML) &&
!UtilitiesService.layerContainsBboxGeographicElement(layerModel)) {
continue;
}
Expand Down Expand Up @@ -409,12 +410,15 @@ export class CsMapService {
* @returns true if a layer supports opacity, false otherwise
*/
public layerHasOpacity(layer: LayerModel): boolean {
console.log("[cs-map.service]layerHasOpacity.layer=",layer);
if (this.layerExists(layer.id)) {
if (UtilitiesService.layerContainsResourceType(layer, ResourceType.WMS) ||
UtilitiesService.layerContainsBboxGeographicElement(layer)) {
console.log("[cs-map.service]layerHasOpacity.TRUE");
return true;
}
}
console.log("[cs-map.service]layerHasOpacity.FALSE");
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import { HttpClient, HttpResponse } from '@angular/common/http';
import { LayerModel} from '../../model/data/layer.model';
import { OnlineResourceModel } from '../../model/data/onlineresource.model';
import { ResourceType } from '../../utility/constants.service';
import { SplitDirection } from 'cesium';
import { Rectangle, SplitDirection } from 'cesium';
import { GetCapsService } from '../wms/get-caps.service';
import bboxPolygon from '@turf/bbox-polygon';


/**
Expand Down Expand Up @@ -135,7 +136,26 @@ export class LayerHandlerService {
public makeCustomKMLLayerRecord(name: string, url: string, kmlDoc: {}): LayerModel {
const id = 'KML_' + name.substring(0, 10) + '_' + Math.floor(Math.random() * 10000).toString();
const itemLayer = new LayerModel();
const cswRec = this.makeCustomKMLCSWRec(name, id, url);

// if its a GroundOverlay then extract the bbox (rectangle)
let overlayRect;
var doc : any;
doc = kmlDoc;
let gos = doc.querySelector("GroundOverlay");
if (gos) {
let iconEntity = gos.querySelector("Icon");
let iconURL = iconEntity.querySelector('href').textContent;
if (iconURL.toLowerCase().startsWith("http")) {
let rectEntity = gos.querySelector("LatLonBox");
let north = rectEntity.querySelector('north').textContent;
let south = rectEntity.querySelector('south').textContent;
let east = rectEntity.querySelector('east').textContent;
let west = rectEntity.querySelector('west').textContent;
overlayRect = {west: west, south: south, east: east, north: north};
}
}

const cswRec = this.makeCustomKMLCSWRec(name, id, url, overlayRect);
itemLayer.cswRecords = [cswRec];
itemLayer['expanded'] = false;
itemLayer.id = id;
Expand Down Expand Up @@ -212,7 +232,7 @@ export class LayerHandlerService {
* @param id KML layer id
* @returns CSWRecordModel object
*/
public makeCustomKMLCSWRec(name: string, id: string, url: string): CSWRecordModel {
public makeCustomKMLCSWRec(name: string, id: string, url: string, r: any): CSWRecordModel {
const cswRec = new CSWRecordModel();
cswRec.adminArea = '';
cswRec.childRecords = {};
Expand All @@ -226,6 +246,14 @@ export class LayerHandlerService {
cswRec.description = '';
cswRec.descriptiveKeywords = {};
cswRec.geographicElements = {};
if (r) {
//cswRec.geographicElements.push(bboxPolygon([r.east, r.south, r.west, r.north]));
cswRec.geographicElements = [{type: "bbox",
eastBoundLongitude: parseFloat(r.east),
northBoundLatitude: parseFloat(r.north),
southBoundLatitude: parseFloat(r.south),
westBoundLongitude: parseFloat(r.west)}];
}
cswRec.id = id;
cswRec.name = name;
cswRec.noCache = true;
Expand Down
121 changes: 112 additions & 9 deletions projects/portal-core-ui/src/lib/service/kml/cs-kml.service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@

import { throwError as observableThrowError, Observable } from 'rxjs';
import { Injectable } from '@angular/core';
import { Inject, Injectable } from '@angular/core';
import { HttpClient, HttpResponse } from '@angular/common/http';
import { catchError, map } from 'rxjs/operators';

import { OnlineResourceModel } from '../../model/data/onlineresource.model';
import { LayerModel } from '../../model/data/layer.model';
import { LayerHandlerService } from '../cswrecords/layer-handler.service';
import { MapsManagerService } from '@auscope/angular-cesium';
import { ResourceType } from '../../utility/constants.service';
import { Constants, ResourceType } from '../../utility/constants.service';
import { RenderStatusService } from '../cesium-map/renderstatus/render-status.service';
import { KMLDocService } from './kml.service';
import { UtilitiesService } from '../../utility/utilities.service';
import { Color, ColorMaterialProperty, Rectangle } from 'cesium';

// NB: Cannot use "import { XXX, YYY, ZZZ, Color } from 'cesium';" - it prevents initialising ContextLimits.js properly
// which causes a 'DeveloperError' when trying to draw the KML
Expand All @@ -28,11 +29,14 @@ export class CsKMLService {
// Number of KML resources added for a given layer
private numberOfResourcesAdded: Map<string, number> = new Map<string, number>();

private overlayDoc: Node; // used to make a temporary copy of <GroundOverlay> for restoring to layer.kmlDoc

constructor(private layerHandlerService: LayerHandlerService,
private http: HttpClient,
private renderStatusService: RenderStatusService,
private mapsManagerService: MapsManagerService,
private kmlService: KMLDocService) {
private kmlService: KMLDocService,
@Inject('env') private env) {
}

/**
Expand All @@ -52,6 +56,55 @@ export class CsKMLService {
));
}


/**
* gets the icon from the KML if the url is http...
*
* @param kmlResource KML resource to be fetched
* @returns icon object (url and rectangle coords)
*/

private getIcon(kmlDoc: Document): any {
let result = {};
let gos = kmlDoc.querySelectorAll("GroundOverlay");
if (gos) {
gos.forEach(go => {
let iconEntity = go.querySelector("Icon");
let iconURL = iconEntity.querySelector('href').textContent;
if (iconURL.toLowerCase().startsWith("http")) {
let rectEntity = go.querySelector("LatLonBox");
let north = rectEntity.querySelector('north').textContent;
let south = rectEntity.querySelector('south').textContent;
let east = rectEntity.querySelector('east').textContent;
let west = rectEntity.querySelector('west').textContent;
result = { url: iconURL, rectangle: { north: north, south: south, east: east, west: west } };
}
});
}
return result;
}


/**
* removes the <GroundOverlay> element from the kml document
*
* @param kmlResource KML resource to be fetched
* @returns updated kml document and saves the removed nodes to overlayDoc
*/

private removeOverlay(kmlDoc: Document): Document {
let gos = kmlDoc.querySelectorAll("GroundOverlay");
if (gos) {
gos.forEach(go => {
// backup <GroundOverlay> and restore after the kml source is loaded
this.overlayDoc = go.cloneNode(true);
go.remove();
});
}
return kmlDoc;
}


/**
* Add the KML layer
* @param layer the KML layer to add to the map
Expand Down Expand Up @@ -96,11 +149,57 @@ export class CsKMLService {
// note: KML and KMZ, loaded either from a local file or url now have
// a layer.kmlDoc entry - so some of the following code is redundant
if (layer.kmlDoc) {
source.load(layer.kmlDoc).then(dataSource => {
var iconObject = this.getIcon(layer.kmlDoc);
// TODO: remove <GroundOverlay> from the kml before the sourse is loaded!!
// elements still to handle: name, description, rotation
let overlayRect;
let kmlDoc = layer.kmlDoc;
if (iconObject.rectangle) {
overlayRect = Rectangle.fromDegrees(iconObject.rectangle.west, iconObject.rectangle.south, iconObject.rectangle.east, iconObject.rectangle.north);
// remove <GroundOverlay> from KML
kmlDoc = this.removeOverlay(layer.kmlDoc);
}
source.load(kmlDoc).then(dataSource => {
if (this.cancelledLayers.indexOf(layer.id) === -1) {
viewer.dataSources.add(dataSource).then(dataSrc => {
let overlayProvider;
viewer.dataSources.add(dataSource).then(async dataSrc => {
layer.csLayers.push(dataSrc);
this.incrementLayersAdded(layer, 1);

if (!iconObject.url) {
this.incrementLayersAdded(layer, 1);
} else {
this.incrementLayersAdded(layer, 2);

const layers = viewer.scene.imageryLayers;
// Use the proxy
const proxyUrl = this.env.portalBaseUrl + Constants.PROXY_API + "?usewhitelist=false&url=" + iconObject.url;
overlayProvider = new Cesium.SingleTileImageryProvider({
url: proxyUrl,
layers: layer.name,
rectangle: overlayRect,
credit: "credit for the data source",
});

setTimeout(() => {
viewer.camera.flyTo({ destination: overlayRect });
}, 100);

setTimeout(() => {
if (overlayProvider.ready) {
try {
// restore kmlDoc, i.e. add back <GroundOverlay>
layer.kmlDoc.querySelector("Folder").appendChild(this.overlayDoc);
var newLayer = viewer.imageryLayers.addImageryProvider(overlayProvider);
layer.csLayers.push(newLayer);
} catch (error) {
// Handle error
console.log(`(timeout)There was an error while creating the imagery layer. ${error}`);
}
}
}, 2000);

}

});
}
});
Expand All @@ -114,7 +213,7 @@ export class CsKMLService {
source.load(onlineResource.url).then(dataSource => {
viewer.dataSources.add(dataSource).then(dataSrc => {
layer.csLayers.push(dataSrc);
this.incrementLayersAdded(layer, kmlOnlineResources.length);
this.incrementLayersAdded(layer, kmlOnlineResources.length);
});
});

Expand Down Expand Up @@ -176,8 +275,12 @@ export class CsKMLService {
this.cancelLayerAdded(layer.id);

const viewer = this.getViewer();
for (const dataSrc of layer.csLayers) {
viewer.dataSources.remove(dataSrc);
for (const viewerObject of layer.csLayers) {
if (viewerObject.constructor && viewerObject.constructor.name === "KmlDataSource") { viewer.dataSources.remove(viewerObject); }
if (viewerObject.constructor && viewerObject.constructor.name === "ImageryLayer") {
const layers = viewer.scene.imageryLayers;
viewer.imageryLayers.remove(viewerObject);
}
}
layer.csLayers = [];
this.renderStatusService.resetLayer(layer.id);
Expand Down
4 changes: 2 additions & 2 deletions projects/portal-core-ui/src/lib/service/kml/kml.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ export class KMLDocService {
kmlTxt = kmlTxt.replace(/\002/g, '');
// Inserts local paddle image to avoid CORS errors
// Cesium does not load proxied images for some as yet unknown reason
kmlTxt = kmlTxt.replace(/<Icon>\s*<href>.*<\/href>/g,
'<Icon>\n<href>extension/images/white-paddle.png</href>');
// kmlTxt = kmlTxt.replace(/<Icon>\s*<href>.*<\/href>/g,
// '<Icon>\n<href>extension/images/white-paddle.png</href>');
return kmlTxt;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ export class CsCSWService {
public setLayerOpacity(layer, opacity: number) {
for (const entity of layer.csLayers) {
if (entity.rectangle) {
entity.rectangle.material = new ColorMaterialProperty(Color.fromAlpha(POLYGON_COLOUR, opacity * POLYGON_ALPHA));
// NOTE: todo: GroundOverlay kml doesn't have a mertial property for the rectangle
if (entity.rectangle.material) {
entity.rectangle.material = new ColorMaterialProperty(Color.fromAlpha(POLYGON_COLOUR, opacity * POLYGON_ALPHA));
}
} else if (entity.label) {
entity.label.fillColor = Color.fromAlpha(LABEL_COLOUR, opacity);
entity.label.backgroundColor = Color.fromAlpha(LABEL_BACKGROUND_COLOUR, opacity);
Expand Down
Loading