-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #123 from chrisvpeters/AUS-3960-A
AUS-3960
- Loading branch information
Showing
6 changed files
with
309 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
252 changes: 252 additions & 0 deletions
252
projects/portal-core-ui/src/lib/service/vmf/cs-vmf.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
|
||
import { throwError as observableThrowError, Observable } from 'rxjs'; | ||
import { Inject, Injectable } from '@angular/core'; | ||
import { HttpClient, HttpParams, HttpHeaders, 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 { RenderStatusService } from '../cesium-map/renderstatus/render-status.service'; | ||
import { VMFDocService } from './vmf.service'; | ||
import { UtilitiesService } from '../../utility/utilities.service'; | ||
|
||
// 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 VMF | ||
declare var Cesium; | ||
|
||
/** | ||
* Use Cesium to add layer to map. This service class adds VMF layer to the map | ||
*/ | ||
@Injectable() | ||
export class CsVMFService { | ||
|
||
// List of VMF layers that have been cancelled | ||
private cancelledLayers: Array<string> = []; | ||
// Number of VMF resources added for a given layer | ||
private numberOfResourcesAdded: Map<string, number> = new Map<string, number>(); | ||
|
||
constructor(private layerHandlerService: LayerHandlerService, | ||
private http: HttpClient, | ||
private renderStatusService: RenderStatusService, | ||
private mapsManagerService: MapsManagerService, | ||
private vmfService: VMFDocService, | ||
@Inject('env') private env) { | ||
} | ||
|
||
/** | ||
* Downloads geojson that is cropped to polygon | ||
* | ||
* @param vmfResource VMF resource to be fetched | ||
* @returns VMF geojson text | ||
*/ | ||
private getVMFFeature(url: string, polygon: string): Observable<any> { | ||
/* | ||
const body = | ||
{ | ||
"maps": "territories", | ||
"polygon_geojson": { | ||
"type": "FeatureCollection", | ||
"features": [ | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "Polygon", | ||
"coordinates": [ | ||
[[111.64, -17.61], [132.45, -8.23], [146.26, -10.53], [159.37, -24.57], [147.95, -45.25], [110.29, -34.29]] | ||
] | ||
} | ||
} | ||
] | ||
} | ||
}; | ||
*/ | ||
const body= | ||
{ | ||
"maps": "territories", | ||
"polygon_geojson": { | ||
"type": "FeatureCollection", | ||
"features": [ | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "Polygon", | ||
"coordinates": [JSON.parse(polygon)] | ||
} | ||
} | ||
] | ||
} | ||
}; | ||
return this.http.post(url, body, { | ||
headers: new HttpHeaders().set('Content-Type', 'application/json'), | ||
responseType: 'text' | ||
}).pipe(map(response => { | ||
return response; | ||
}), catchError((error: HttpResponse<any>) => { | ||
return observableThrowError(error); | ||
}),); | ||
|
||
} | ||
|
||
/** | ||
* Add the VMF layer | ||
* @param layer the VMF layer to add to the map | ||
* @param param parameters for the VMF layer | ||
*/ | ||
public addLayer(layer: LayerModel, param?: any): void { | ||
// Remove from cancelled layer list (if present) | ||
this.cancelledLayers = this.cancelledLayers.filter(l => l !== layer.id); | ||
|
||
let vmfOnlineResources: OnlineResourceModel[]; | ||
|
||
if (UtilitiesService.layerContainsResourceType(layer, ResourceType.VMF)) { | ||
vmfOnlineResources = this.layerHandlerService.getOnlineResources(layer, ResourceType.VMF); | ||
} | ||
const me = this; | ||
|
||
// Get CesiumJS viewer | ||
const viewer = this.getViewer(); | ||
const options = { | ||
camera: viewer.scene.camera, | ||
canvas: viewer.scene.canvas, | ||
}; | ||
|
||
for (const onlineResource of vmfOnlineResources) { | ||
// Tell UI that we're about to add a resource to map | ||
this.renderStatusService.addResource(layer, onlineResource); | ||
|
||
// Create data source | ||
const source = new Cesium.GeoJsonDataSource(options); | ||
// Add an event to tell us when loading is finished | ||
source.loadingEvent.addEventListener((evt, isLoading: boolean) => { | ||
if (!isLoading) { | ||
// Tell UI that we have completed updating the map | ||
me.renderStatusService.updateComplete(layer, onlineResource); | ||
} | ||
}); | ||
|
||
if (!this.numberOfResourcesAdded.get(layer.id)) { | ||
this.numberOfResourcesAdded.set(layer.id, 0); | ||
} | ||
|
||
if (UtilitiesService.layerContainsResourceType(layer, ResourceType.VMF)) { | ||
// add VMF to map | ||
|
||
//const proxyUrl = this.env.portalBaseUrl + "getViaProxy.do?usewhitelist=false&url=" + onlineResource.url; | ||
//const proxyUrl = "https://portal.auscope.org.au/" + "getViaProxy.do?usewhitelist=false&url=" + onlineResource.url; | ||
const proxyUrl = onlineResource.url; | ||
const polygon = layer["geojson"]["polygon"]; | ||
var polygonStr = "["; | ||
var delim = ","; | ||
var i = 0; | ||
for (const coord of polygon) { | ||
const lon = coord[0]; | ||
const lat = coord[1]; | ||
if (i == (polygon.length-1)) { delim = ""; } | ||
polygonStr = polygonStr + "["+lon+","+lat+"]"+delim; | ||
i = i + 1; | ||
} | ||
polygonStr = polygonStr + "]"; | ||
this.getVMFFeature(proxyUrl,polygonStr).subscribe(geojsonTxt => { | ||
// make a geojson features collection | ||
let fcTxt = '{"type": "FeatureCollection","features":' + geojsonTxt + '}'; | ||
let geojson = JSON.parse(fcTxt); | ||
|
||
source.load(geojson).then(dataSource => { | ||
if (this.cancelledLayers.indexOf(layer.id) === -1) { | ||
viewer.dataSources.add(dataSource).then(dataSrc => { | ||
|
||
//Get the array of entities | ||
const entities = dataSource.entities.values; | ||
|
||
for (let i = 0; i < entities.length; i++) { | ||
//For each entity (polygon), get the colour property and make the polygon that colour | ||
const entity = entities[i]; | ||
const properties = entity.properties; | ||
const color = properties.color; | ||
let value = color._value; | ||
// remake the color as a hex string (RGB) with opactiy first | ||
value = "0x40" + value.substring(5,7)+value.substring(3,5)+value.substring(1,3); | ||
var cesiumColor = Cesium.Color.fromRgba(value); | ||
//Set the polygon material to our color. | ||
entity.polygon.material = cesiumColor; | ||
//Remove the outlines. | ||
entity.polygon.outline = false; | ||
//Extrude the polygon | ||
entity.polygon.extrudedHeight = 1.0; | ||
} | ||
|
||
layer.csLayers.push(dataSrc); | ||
this.incrementLayersAdded(layer, vmfOnlineResources.length); | ||
}, (err) => { | ||
console.error('Unable to add viewer.dataSources VMF: ', err); | ||
}); | ||
} | ||
}, (err) => { | ||
console.error('Unable to load source.load VMF: ', err); | ||
}); | ||
}, (err) => { | ||
alert('Unable to load VMF: ' + err.message); | ||
console.error('Unable to load VMF: ', err); | ||
// Tell UI that we have completed updating the map & there was an error | ||
this.renderStatusService.updateComplete(layer, onlineResource, true); | ||
this.incrementLayersAdded(layer, vmfOnlineResources.length); | ||
}); | ||
|
||
} | ||
|
||
} | ||
} | ||
|
||
/** | ||
* Increment the number of layers added for a given LayerModel, and clear the layer from the | ||
* cancelled layer list if all layers have been added | ||
* @param layer the LayerModel | ||
* @param totalLayers total number of layers for LayerModel | ||
*/ | ||
private incrementLayersAdded(layer: LayerModel, totalLayers: number) { | ||
this.numberOfResourcesAdded.set(layer.id, this.numberOfResourcesAdded.get(layer.id) + 1); | ||
if (this.numberOfResourcesAdded.get(layer.id) === totalLayers) { | ||
this.cancelledLayers = this.cancelledLayers.filter(l => l !== layer.id); | ||
} | ||
} | ||
|
||
/** | ||
* Request cancellation of layer if it's still being added | ||
* @param layerId ID of layer | ||
*/ | ||
public cancelLayerAdded(layerId: string) { | ||
if (this.cancelledLayers.indexOf(layerId) === -1) { | ||
this.cancelledLayers.push(layerId); | ||
} | ||
} | ||
|
||
/** | ||
* Removes VMF layer from the map | ||
* @method rmLayer | ||
* @param layer the VMF layer to remove from the map. | ||
*/ | ||
public rmLayer(layer: LayerModel): void { | ||
// Request cancellation of layer if it's still being added | ||
this.cancelLayerAdded(layer.id); | ||
|
||
const viewer = this.getViewer(); | ||
for (const dataSrc of layer.csLayers) { | ||
viewer.dataSources.remove(dataSrc); | ||
} | ||
layer.csLayers = []; | ||
this.renderStatusService.resetLayer(layer.id); | ||
} | ||
|
||
/** | ||
* Fetches Cesium 'Viewer' | ||
*/ | ||
private getViewer() { | ||
return this.mapsManagerService.getMap().getCesiumViewer(); | ||
} | ||
|
||
} |
44 changes: 44 additions & 0 deletions
44
projects/portal-core-ui/src/lib/service/vmf/vmf.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { Injectable, Inject } from '@angular/core'; | ||
|
||
/** | ||
* This service class contains functions used for manipulating VMF documents | ||
*/ | ||
@Injectable({ | ||
providedIn: 'root' | ||
}) | ||
export class VMFDocService { | ||
|
||
constructor(@Inject('env') private env) { } | ||
|
||
/** | ||
* Clean VMF text by removing illegal chars and | ||
* forcing proxying of icon images to avoid CORS errors | ||
* | ||
* @param vmfTxt VMF text to be cleaned | ||
* @returns clean VMF string | ||
*/ | ||
public cleanVMF(vmfTxt: string): string { | ||
// Removes non-standard chars that can cause errors | ||
vmfTxt = vmfTxt.replace(/\016/g, ''); | ||
vmfTxt = vmfTxt.replace(/\002/g, ''); | ||
// Inserts local paddle image to avoid CORS errors | ||
// Cesium does not load proxied images for some as yet unknown reason | ||
vmfTxt = vmfTxt.replace(/<Icon>\s*<href>.*<\/href>/g, | ||
'<Icon>\n<href>extension/images/white-paddle.png</href>'); | ||
return vmfTxt; | ||
} | ||
|
||
/** | ||
* Clean VMF text by removing illegal chars | ||
* future: when cesium support proxying of images | ||
* | ||
* @param vmfTxt VMF text to be cleaned | ||
* @returns clean VMF string | ||
*/ | ||
public cleanKMZ(vmfTxt: string): string { | ||
// Removes non-standard chars that can cause errors | ||
vmfTxt = vmfTxt.replace(/\016/g, ''); | ||
vmfTxt = vmfTxt.replace(/\002/g, ''); | ||
return vmfTxt; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters