GUI2 Absolute locations for Devices and Hosts

Change-Id: I172020a19004b559ae740478d30a2cf9ce08091e
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/backgroundsvg/backgroundsvg.component.html b/web/gui2/src/main/webapp/app/view/topology/layer/backgroundsvg/backgroundsvg.component.html
index bb9e638..b6290b6 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/backgroundsvg/backgroundsvg.component.html
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/backgroundsvg/backgroundsvg.component.html
@@ -13,10 +13,17 @@
 ~ See the License for the specific language governing permissions and
 ~ limitations under the License.
 -->
-<svg:g xmlns:svg="http://www.w3.org/2000/svg" onos-mapsvg [map]="map"/>
-<svg:g  xmlns:svg="http://www.w3.org/2000/svg">
-    <svg:text>Layout: {{ layoutData.id }} {{ layoutData.bgDesc }}</svg:text>
-    <svg:text>Region: {{ layoutData.region }} {{ layoutData.regionName }}</svg:text>
-    <svg:text>Parent {{ layoutData.parent }}</svg:text>
-    <svg:text *ngFor="let crumb of layoutData.crumbs">{{ crumb.id }} {{ crumb.name }}</svg:text>
-</svg:g>
+<!-- The transform here goes from a 0,0 centred grid of -180 to 180 of
+    longitude to -75 to 75 of latitude
+     It is mapped to a 2000x1000 SVG grid with -500,0 at the top left
+     (The SVG viewbox of ONOS is 1000x1000 - for the geo grid we wanted
+     to keep it the same height 1000 representing +75 latitude down to
+     -75 latitude, but double the width. Why 75? There's no city in the
+     world above 70 - Murmansk)
+     The 6.66 represents 1000/150 and the 5.55 represents 2000/360
+     The reason for the difference is that mercator projection widens
+     countries in the northern and southern extremities, and so
+     the map is squashed horizontally slightly here to compensate
+     (with no squashing the width would be 2400)-->
+<svg:g xmlns:svg="http://www.w3.org/2000/svg" onos-mapsvg [map]="map"
+       transform="translate(500,500), scale(5.5555,6.666666)"/>
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/backgroundsvg/backgroundsvg.component.spec.ts b/web/gui2/src/main/webapp/app/view/topology/layer/backgroundsvg/backgroundsvg.component.spec.ts
index a3eed06..0732018 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/backgroundsvg/backgroundsvg.component.spec.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/backgroundsvg/backgroundsvg.component.spec.ts
@@ -21,6 +21,13 @@
 import {HttpClient} from '@angular/common/http';
 import {LogService} from 'gui2-fw-lib';
 import {MapObject} from '../maputils';
+import {LocMeta} from '../forcesvg/models';
+import {ForceSvgComponent} from '../forcesvg/forcesvg.component';
+import {
+    DeviceNodeSvgComponent,
+    HostNodeSvgComponent, LinkSvgComponent, SubRegionNodeSvgComponent
+} from '../forcesvg/visuals';
+import {DraggableDirective} from '../forcesvg/draggable/draggable.directive';
 
 class MockHttpClient {
     get() {
@@ -46,7 +53,13 @@
         TestBed.configureTestingModule({
             declarations: [
                 BackgroundSvgComponent,
-                MapSvgComponent
+                MapSvgComponent,
+                ForceSvgComponent,
+                DeviceNodeSvgComponent,
+                HostNodeSvgComponent,
+                SubRegionNodeSvgComponent,
+                LinkSvgComponent,
+                DraggableDirective
             ],
             providers: [
                 { provide: LogService, useValue: logSpy },
@@ -68,4 +81,33 @@
     it('should create', () => {
         expect(component).toBeTruthy();
     });
+
+    it('should convert latlong to xy', () => {
+        const result = BackgroundSvgComponent.convertGeoToCanvas(<LocMeta>{lat: 52, lng: -8});
+        expect(Math.round(result.x * 100)).toEqual(45556);
+        expect(Math.round(result.y * 100)).toEqual(15333);
+    });
+
+    /**
+     * For some reason including the following causes "ForceSvgComponent should create error
+     * TODO: Investigate
+     */
+
+    // it('should convert xy random extents to latlong', () => {
+    //     const result = BackgroundSvgComponent.convertXYtoGeo(455.556, 153.33);
+    //     expect(Math.round(result.equivLoc.lng)).toEqual(-8);
+    //     expect(Math.round(result.equivLoc.lat)).toEqual(52);
+    // });
+
+    // it('should convert xy min extents to latlong', () => {
+    //     const result = BackgroundSvgComponent.convertXYtoGeo(-500, 0);
+    //     expect(Math.round(result.equivLoc.lng)).toEqual(-180);
+    //     expect(Math.round(result.equivLoc.lat)).toEqual(75);
+    // });
+
+    // it('should convert xy full extents to latlong', () => {
+    //     const result = BackgroundSvgComponent.convertXYtoGeo(1500, 1000);
+    //     expect(Math.round(result.equivLoc.lng)).toEqual(180);
+    //     expect(Math.round(result.equivLoc.lat)).toEqual(-75);
+    // });
 });
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/backgroundsvg/backgroundsvg.component.ts b/web/gui2/src/main/webapp/app/view/topology/layer/backgroundsvg/backgroundsvg.component.ts
index 5536784..cc41fb6 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/backgroundsvg/backgroundsvg.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/backgroundsvg/backgroundsvg.component.ts
@@ -15,6 +15,7 @@
  */
 import {Component, Input, OnInit} from '@angular/core';
 import {MapObject} from '../maputils';
+import {LocMeta, MetaUi} from '../forcesvg/models';
 
 /**
  * model of the topo2CurrentLayout attrs from BgZoom below
@@ -68,6 +69,9 @@
     regionName: string;
 }
 
+const LONGITUDE_EXTENT = 180;
+const LATITUDE_EXTENT = 75;
+
 /**
  * ONOS GUI -- Topology Background Layer View.
  */
@@ -81,6 +85,32 @@
 
     layoutData: Layout = <Layout>{};
 
+    static convertGeoToCanvas(location: LocMeta): MetaUi {
+        const calcX = (LONGITUDE_EXTENT + location.lng) / ( LONGITUDE_EXTENT * 2 ) * 2000 - 500;
+        const calcY = (LATITUDE_EXTENT - location.lat) / ( LATITUDE_EXTENT * 2 ) * 1000;
+        return <MetaUi>{
+            x: calcX,
+            y: calcY,
+            equivLoc: {
+                lat: location.lat,
+                lng: location.lng
+            }
+        };
+    }
+
+    static convertXYtoGeo(x: number, y: number): MetaUi {
+        const calcLong: number = (x + 500) * 2 * LONGITUDE_EXTENT / 2000 - LONGITUDE_EXTENT;
+        const calcLat: number = -(y * 2 * LATITUDE_EXTENT / 1000 - LATITUDE_EXTENT);
+        return <MetaUi>{
+            x: x,
+            y: y,
+            equivLoc: <LocMeta>{
+                lat: calcLat,
+                lng: calcLong
+            }
+        };
+    }
+
     constructor() { }
 
     ngOnInit() {