src/services/bing/bing-conversions.ts
import { IMapOptions } from '../../interfaces/imap-options';
import { IBox } from '../../interfaces/ibox';
import { ILatLong } from '../../interfaces/ilatlong';
import { IMarkerOptions } from '../../interfaces/imarker-options';
import { IMarkerIconInfo } from '../../interfaces/imarker-icon-info';
import { IClusterOptions } from '../../interfaces/icluster-options';
import { IInfoWindowOptions } from '../../interfaces/iinfo-window-options';
import { IInfoWindowAction } from '../../interfaces/iinfo-window-action';
import { IPolygonOptions } from '../../interfaces/ipolygon-options';
import { IPolylineOptions } from '../../interfaces/ipolyline-options';
import { IPoint } from '../../interfaces/ipoint';
import { MapTypeId } from '../../models/map-type-id';
import { Marker } from '../../models/marker';
import { ClusterPlacementMode } from '../../models/cluster-placement-mode';
import { BingMapService } from './bing-map.service';
/**
* This class contains helperfunctions to map various interfaces used to represent options and structures into the
* corresponding Bing Maps V8 specific implementations.
*
* @export
*/
export class BingConversions {
///
/// Field declarations
///
/**
* Map option attributes that are supported for conversion to Bing Map properties
*
* @memberof BingConversions
*/
private static _mapOptionsAttributes: string[] = [
'backgroundColor',
'credentials',
'customizeOverlays',
'customMapStyle',
'disableBirdseye',
'disableKeyboardInput',
'disableMouseInput',
'disablePanning',
'disableTouchInput',
'disableUserInput',
'disableZooming',
'disableStreetside',
'enableClickableLogo',
'enableSearchLogo',
'fixedMapPosition',
'height',
'inertiaIntensity',
'navigationBarMode',
'showBreadcrumb',
'showCopyright',
'showDashboard',
'showMapTypeSelector',
'showScalebar',
'theme',
'tileBuffer',
'useInertia',
'width',
'center',
'zoom',
'mapTypeId',
'liteMode'
];
/**
* View option attributes that are supported for conversion to Bing Map properties
*
* @memberof BingConversions
*/
private static _viewOptionsAttributes: string[] = [
'animate',
'bounds',
'center',
'centerOffset',
'heading',
'labelOverlay',
'mapTypeId',
'padding',
'zoom'
];
/**
* InfoWindow option attributes that are supported for conversion to Bing Map properties
*
* @memberof BingConversions
*/
private static _infoWindowOptionsAttributes: string[] = [
'actions',
'description',
'htmlContent',
'id',
'position',
'pixelOffset',
'showCloseButton',
'showPointer',
'pushpin',
'title',
'titleClickHandler',
'typeName',
'visible',
'width',
'height'
];
/**
* Marker option attributes that are supported for conversion to Bing Map properties
*
* @memberof BingConversions
*/
private static _markerOptionsAttributes: string[] = [
'anchor',
'draggable',
'height',
'htmlContent',
'icon',
'infobox',
'state',
'title',
'textOffset',
'typeName',
'visible',
'width',
'zIndex'
];
/**
* Polygon option attributes that are supported for conversion to Bing Map Polygon properties
*
* @memberof BingConversions
*/
private static _polygonOptionsAttributes: string[] = [
'cursor',
'fillColor',
'fillOpacity',
'strokeColor',
'strokeOpacity',
'strokeWeight',
'visible'
];
/**
* Polyline option attributes that are supported for conversion to Bing Map Polyline properties
*
* @memberof BingConversions
*/
private static _polylineOptionsAttributes: string[] = [
'cursor',
'strokeColor',
'strokeOpacity',
'strokeWeight',
'visible'
];
/**
* Cluster option attributes that are supported for conversion to Bing Map properties
*
* @memberof BingConversions
*/
private static _clusterOptionsAttributes: string[] = [
'callback',
'clusteredPinCallback',
'clusteringEnabled',
'gridSize',
'layerOffset',
'placementMode',
'visible',
'zIndex'
];
///
/// Public methods
///
/**
* Maps an IInfoWindowAction to a Microsoft.Maps.IInfoboxActions
*
* @param action - Object to be mapped.
* @returns - Navtive mapped object.
*
* @memberof BingConversions
*/
public static TranslateAction(action: IInfoWindowAction): Microsoft.Maps.IInfoboxActions {
const a: Microsoft.Maps.IInfoboxActions = {
eventHandler: action.eventHandler,
label: action.label
};
return a;
}
/**
* Maps an Array of IInfoWindowAction to an Array of Microsoft.Maps.IInfoboxActions
*
* @param actions - Array of objects to be mapped.
* @returns - Array of mapped objects.
*
* @memberof BingConversions
*/
public static TranslateActions(actions: Array<IInfoWindowAction>): Array<Microsoft.Maps.IInfoboxActions> {
const a: Array<Microsoft.Maps.IInfoboxActions> = new Array<Microsoft.Maps.IInfoboxActions>();
actions.forEach(x => a.push(BingConversions.TranslateAction(x)));
return a;
}
/**
* Maps an IBox object to a Microsoft.Maps.LocationRect object.
*
* @param box - Object to be mapped.
* @returns - Mapped object.
*
* @memberof BingConversions
*/
public static TranslateBounds(box: IBox): Microsoft.Maps.LocationRect {
const r: Microsoft.Maps.LocationRect =
Microsoft.Maps.LocationRect.fromEdges(box.maxLatitude, box.minLongitude, box.minLatitude, box.maxLongitude);
return r;
}
/**
* Maps an IClusterOptions object to a Microsoft.Maps.IClusterLayerOptions object.
*
* @param options - Object to be mapped.
* @returns - Mapped object.
*
* @memberof BingConversions
*/
public static TranslateClusterOptions(options: IClusterOptions): Microsoft.Maps.IClusterLayerOptions {
const o: Microsoft.Maps.IClusterLayerOptions | any = {};
Object.keys(options)
.filter(k => BingConversions._clusterOptionsAttributes.indexOf(k) !== -1)
.forEach((k) => {
if (k === 'layerOffset') {
o.layerOffset = BingConversions.TranslatePoint(options.layerOffset);
}
if (k === 'placementMode') {
if (options.placementMode === ClusterPlacementMode.FirstPin) {
o.placementMode = Microsoft.Maps.ClusterPlacementType.FirstLocation;
}
else {
o.placementMode = Microsoft.Maps.ClusterPlacementType.MeanAverage;
}
}
else {
o[k] = (<any>options)[k];
}
});
return o;
}
/**
* Maps an IInfoWindowOptions object to a Microsoft.Maps.IInfoboxOptions object.
*
* @param options - Object to be mapped.
* @returns - Mapped object.
*
* @memberof BingConversions
*/
public static TranslateInfoBoxOptions(options: IInfoWindowOptions): Microsoft.Maps.IInfoboxOptions {
const o: Microsoft.Maps.IInfoboxOptions | any = {};
Object.keys(options)
.filter(k => BingConversions._infoWindowOptionsAttributes.indexOf(k) !== -1)
.forEach((k) => {
if (k === 'pixelOffset') {
o.offset = BingConversions.TranslatePoint(options.pixelOffset);
}
else if (k === 'position') {
o.location = BingConversions.TranslateLocation(options.position);
}
else if (k === 'actions') {
o.actions = BingConversions.TranslateActions(options.actions);
}
else {
o[k] = (<any>options)[k];
}
});
return o;
}
/**
* Maps an IMapOptions object to a Microsoft.Maps.IMapLoadOptions object.
*
* @param options - Object to be mapped.
* @returns - Mapped object.
*
* @memberof BingConversions
*/
public static TranslateLoadOptions(options: IMapOptions): Microsoft.Maps.IMapLoadOptions {
const o: Microsoft.Maps.IMapLoadOptions | any = {};
Object.keys(options)
.filter(k => {
return BingConversions._mapOptionsAttributes.indexOf(k) !== -1 || BingConversions._viewOptionsAttributes.indexOf(k) !== -1;
})
.forEach((k) => {
if (k === 'center') {
o.center = BingConversions.TranslateLocation(options.center);
}
else if (k === 'mapTypeId') {
if (options.mapTypeId === MapTypeId.hybrid) {
o.mapTypeId = Microsoft.Maps.MapTypeId.aerial;
o.labelOverlay = Microsoft.Maps.LabelOverlay.visible;
}
else if (options.mapTypeId === MapTypeId.aerial) {
o.mapTypeId = Microsoft.Maps.MapTypeId.aerial;
o.labelOverlay = Microsoft.Maps.LabelOverlay.hidden;
}
else {
o.mapTypeId = Microsoft.Maps.MapTypeId[(<any>MapTypeId)[options.mapTypeId]];
}
}
else if (k === 'bounds') {
o.bounds = BingConversions.TranslateBounds(options.bounds);
}
else {
o[k] = (<any>options)[k];
}
});
return o;
}
/**
* Maps an ILatLong object to a Microsoft.Maps.Location object.
*
* @param latlong - Object to be mapped.
* @returns - Mapped object.
*
* @memberof BingConversions
*/
public static TranslateLocation(latlong: ILatLong): Microsoft.Maps.Location {
const l: Microsoft.Maps.Location = new Microsoft.Maps.Location(latlong.latitude, latlong.longitude);
return l;
}
/**
* Maps an IMarkerOptions object to a Microsoft.Maps.IPushpinOptions object.
*
* @param options - Object to be mapped.
* @returns - The mapped object.
*
* @memberof BingConversions
*/
public static TranslateMarkerOptions(options: IMarkerOptions): Microsoft.Maps.IPushpinOptions {
const o: Microsoft.Maps.IPushpinOptions = {};
Object.keys(options)
.filter(k => BingConversions._markerOptionsAttributes.indexOf(k) !== -1)
.forEach((k) => {
if (k === 'anchor') {
o.anchor = BingConversions.TranslatePoint(options.anchor);
}
else {
(<any>o)[k] = (<any>options)[k];
}
});
return o;
}
/**
* Maps an IMapOptions object to a Microsoft.Maps.IMapOptions object.
*
* @param options - Object to be mapped.
* @returns - Mapped object.
*
* @memberof BingConversions
*/
public static TranslateOptions(options: IMapOptions): Microsoft.Maps.IMapOptions {
const o: Microsoft.Maps.IMapOptions | any = {};
Object.keys(options)
.filter(k => BingConversions._mapOptionsAttributes.indexOf(k) !== -1)
.forEach((k) => {
if (k === 'center') {
o.center = BingConversions.TranslateLocation(options.center);
}
else if (k === 'mapTypeId') {
o.mapTypeId = Microsoft.Maps.MapTypeId[(<any>MapTypeId)[options.mapTypeId]];
}
else {
o[k] = (<any>options)[k];
}
});
return o;
}
/**
* Translates an array of locations or an array or arrays of location to and array of arrays of Bing Map Locations
*
* @param paths - ILatLong based locations to convert.
* @returns - converted locations.
*
* @memberof BingConversions
*/
public static TranslatePaths(paths: Array<ILatLong> | Array<Array<ILatLong>>): Array<Array<Microsoft.Maps.Location>> {
const p: Array<Array<Microsoft.Maps.Location>> = new Array<Array<Microsoft.Maps.Location>>();
if (paths == null || !Array.isArray(paths) || paths.length === 0) {
p.push(new Array<Microsoft.Maps.Location>());
}
else if (Array.isArray(paths[0])) {
// parameter is an array or arrays
// us for loop for performance
const p1 = <Array<Array<ILatLong>>>paths;
for (let i = 0; i < p1.length; i++) {
const _p: Array<Microsoft.Maps.Location> = new Array<Microsoft.Maps.Location>();
for (let j = 0; j < p1[i].length; j++) {
_p.push(new Microsoft.Maps.Location(p1[i][j].latitude, p1[i][j].longitude));
}
p.push(_p);
}
}
else {
// parameter is a simple array....
const y: Array<Microsoft.Maps.Location> = new Array<Microsoft.Maps.Location>();
const p1 = <Array<ILatLong>>paths;
for (let i = 0; i < p1.length; i++) {
y.push(new Microsoft.Maps.Location(p1[i].latitude, p1[i].longitude));
}
p.push(y);
}
return p;
}
/**
* Maps an IPoint object to a Microsoft.Maps.Point object.
*
* @param point - Object to be mapped.
* @returns - Mapped object.
*
* @memberof BingConversions
*/
public static TranslatePoint(point: IPoint): Microsoft.Maps.Point {
const p: Microsoft.Maps.Point = new Microsoft.Maps.Point(point.x, point.y);
return p;
}
/**
* Maps an IPolygonOptions object to a Microsoft.Maps.IPolygonOptions.
*
* @param options - Object to be mapped.
* @returns - Mapped object.
*
* @memberof BingConversions
*/
public static TranslatePolygonOptions(options: IPolygonOptions): Microsoft.Maps.IPolygonOptions {
const o: Microsoft.Maps.IPolygonOptions = {};
const f: (s: string, a: number) => string = (s, a) => {
const m = /rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*\d+[\.\d+]*)*\)/g.exec(s);
if (m && m.length > 3) {
a = a > 1 ? (a / 100) : a;
return 'rgba(' + [m[1], m[2], m[3], a].join(',') + ')';
}
else if (s[0] === '#') {
const x: number = a > 1 ? a : Math.floor(a * 255);
const z: string = s.substr(1);
const r: number = parseInt(z.substr(0, 2), 16);
const g: number = parseInt(z.substr(2, 2), 16);
const b: number = parseInt(z.substr(4, 2), 16);
return 'rgba(' + [r , g, b, a].join(',') + ')';
}
else {
return s;
}
};
Object.keys(options)
.filter(k => BingConversions._polygonOptionsAttributes.indexOf(k) !== -1)
.forEach((k) => {
if (k === 'strokeWeight') {
o.strokeThickness = options.strokeWeight;
}
else if (k === 'strokeColor') {
if (options.strokeOpacity) {
o.strokeColor = f(options.strokeColor, options.strokeOpacity);
}
else {
o.strokeColor = options.strokeColor;
}
}
else if (k === 'strokeOpacity') {}
else if (k === 'fillColor') {
if (options.fillOpacity) {
o.fillColor = f(options.fillColor, options.fillOpacity);
}
else {
o.fillColor = options.fillColor;
}
}
else if (k === 'fillOpacity') {}
else {
(<any>o)[k] = (<any>options)[k];
}
});
return o;
}
/**
* Maps an IPolylineOptions object to a Microsoft.Maps.IPolylineOptions.
*
* @param options - Object to be mapped.
* @returns - Mapped object.
*
* @memberof BingConversions
*/
public static TranslatePolylineOptions(options: IPolylineOptions): Microsoft.Maps.IPolylineOptions {
const o: Microsoft.Maps.IPolylineOptions | any = {};
const f: (s: string, a: number) => string = (s, a) => {
const m = /rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*\d+[\.\d+]*)*\)/g.exec(s);
if (m && m.length > 3) {
a = a > 1 ? (a / 100) : a;
return 'rgba(' + [m[1], m[2], m[3], a].join(',') + ')';
}
else if (s[0] === '#') {
const x: number = a > 1 ? a : Math.floor(a * 255);
const z: string = s.substr(1);
const r: number = parseInt(z.substr(0, 2), 16);
const g: number = parseInt(z.substr(2, 2), 16);
const b: number = parseInt(z.substr(4, 2), 16);
return 'rgba(' + [r , g, b, a].join(',') + ')';
}
else {
return s;
}
};
Object.keys(options)
.filter(k => BingConversions._polylineOptionsAttributes.indexOf(k) !== -1)
.forEach((k) => {
if (k === 'strokeWeight') {
o.strokeThickness = options.strokeWeight;
} else if (k === 'strokeColor') {
if (options.strokeOpacity) {
o.strokeColor = f(options.strokeColor, options.strokeOpacity);
}
else {
o.strokeColor = options.strokeColor;
}
}
else if (k === 'strokeOpacity') {
}
else {
o[k] = (<any>options)[k];
}
});
return o;
}
/**
* Maps an IMapOptions object to a Microsoft.Maps.IViewOptions object.
*
* @param options - Object to be mapped.
* @returns - Mapped object.
*
* @memberof BingConversions
*/
public static TranslateViewOptions(options: IMapOptions): Microsoft.Maps.IViewOptions {
const o: Microsoft.Maps.IViewOptions | any = {};
Object.keys(options)
.filter(k => BingConversions._viewOptionsAttributes.indexOf(k) !== -1)
.forEach((k) => {
if (k === 'center') {
o.center = BingConversions.TranslateLocation(options.center);
} else if (k === 'bounds') {
o.bounds = BingConversions.TranslateBounds(options.bounds);
} else if (k === 'centerOffset') {
o.centerOffset = BingConversions.TranslatePoint(options.centerOffset);
} else if (k === 'mapTypeId') {
o.mapTypeId = Microsoft.Maps.MapTypeId[(<any>MapTypeId)[options.mapTypeId]];
} else {
o[k] = (<any>options)[k];
}
});
return o;
}
}