blob: 1d7121239f5271c8400540dec42270e4c4517bea [file] [log] [blame]
Steven Burrows1c5c8612016-10-05 13:45:13 -05001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 ONOS GUI -- Topology Node Position Module.
19 Module that helps position nodes in the topology
20 */
21
22(function () {
23 'use strict';
24
25 // Injected vars
Steven Burrows68d6f952017-03-10 13:53:35 +000026 var rs, t2mcs, t2sls, t2bgs;
Steven Burrows1c5c8612016-10-05 13:45:13 -050027
28 // Internal state;
29 var nearDist = 15;
30
31 function positionNode(node, forUpdate) {
Steven Burrows68d6f952017-03-10 13:53:35 +000032
Steven Burrows1c5c8612016-10-05 13:45:13 -050033 var meta = node.get('metaUi'),
34 x = meta && meta.x,
35 y = meta && meta.y,
Simon Hunt2521d5f2017-03-20 18:17:28 -070036 hasMeta = x !== undefined && y !== undefined,
Steven Burrows1c5c8612016-10-05 13:45:13 -050037 dim = [800, 600],
38 xy;
39
Simon Hunt2521d5f2017-03-20 18:17:28 -070040 // If the node has metaUI data attached, it indicates that the user
41 // has dragged the node to a new position on the view; so we should
42 // respect that above any script-configured position...
43 // (NOTE: This is a slightly different to the original topology code)
Steven Burrows68d6f952017-03-10 13:53:35 +000044
Simon Hunt2521d5f2017-03-20 18:17:28 -070045 if (hasMeta) {
46 node.fix(true);
47 node.px = node.x = x;
48 node.py = node.y = y;
49 return;
50 }
51
52 // Otherwise, use a precomputed location for peer regions, or
53 // LONG/LAT (or GRID) locations for regions/devices/hosts
54
55 if (node.nodeType === 'peer-region') {
Steven Burrows68d6f952017-03-10 13:53:35 +000056 var coord = [0, 0],
57 loc = {};
58
59 if (t2bgs.getBackgroundType() === 'geo') {
Steven Burrows4a1b5532017-04-28 11:08:07 -040060
61 var loc = node.get('location'),
62 type = loc.locType || loc.type;
63
64 node.set({ location: {
65 type: type.toLowerCase(),
66 lat: loc.latOrY || loc.lat,
67 lng: loc.longOrX || loc.lng
68 }});
69
Steven Burrowsa85a5d32017-04-10 09:46:27 -070070 setLongLat(node);
Steven Burrows4a1b5532017-04-28 11:08:07 -040071
Steven Burrowsa85a5d32017-04-10 09:46:27 -070072 return true;
Steven Burrows68d6f952017-03-10 13:53:35 +000073 } else {
74 loc.gridX = -20;
75 loc.gridY = 10 * node.index();
76 coord = coordFromXY(loc);
77 }
78
79 node.px = node.x = coord[0];
80 node.py = node.y = coord[1];
81
82 node.fix(true);
83 return;
84 }
85
Steven Burrows1c5c8612016-10-05 13:45:13 -050086 // If the device contains explicit LONG/LAT data, use that to position
87 if (setLongLat(node)) {
88 // Indicate we want to update cached meta data...
89 return true;
90 }
91
Steven Burrows1c5c8612016-10-05 13:45:13 -050092 // if this is a node update (not a node add).. skip randomizer
93 if (forUpdate) {
94 return;
95 }
96
97 // Note: Placing incoming unpinned nodes at exactly the same point
98 // (center of the view) causes them to explode outwards when
99 // the force layout kicks in. So, we spread them out a bit
100 // initially, to provide a more serene layout convergence.
101 // Additionally, if the node is a host, we place it near
102 // the device it is connected to.
103
104 function rand() {
105 return {
106 x: rs.randDim(dim[0]),
107 y: rs.randDim(dim[1])
108 };
109 }
110
111 function near(node) {
112 return {
113 x: node.x + nearDist + rs.spread(nearDist),
114 y: node.y + nearDist + rs.spread(nearDist)
115 };
116 }
117
118 function getDevice(cp) {
119 return rand();
120 }
121
122 xy = (node.class === 'host') ? near(getDevice(node.cp)) : rand();
123
124 if (node.class === 'sub-region') {
125 xy = rand();
126 node.x = node.px = xy.x;
127 node.y = node.py = xy.y;
128 }
129 angular.extend(node, xy);
130 }
131
132 function setLongLat(el) {
133 var loc = el.get('location'),
134 coord;
135
Simon Huntbc30e682017-02-15 18:39:23 -0800136 if (loc && loc.type === 'geo') {
Steven Burrows1c5c8612016-10-05 13:45:13 -0500137
138 if (loc.lat === 0 && loc.lng === 0) {
139 return false;
140 }
141
142 coord = coordFromLngLat(loc);
Steven Burrowsb11a8b82017-03-10 16:00:31 +0000143 el.fix(true);
Steven Burrows1c5c8612016-10-05 13:45:13 -0500144 el.x = el.px = coord[0];
145 el.y = el.py = coord[1];
146
147 return true;
148 }
Simon Huntbc30e682017-02-15 18:39:23 -0800149
Steven Burrows3db5ddb2017-02-17 15:21:20 +0000150 if (loc && loc.type === 'grid') {
151
152 if (loc.gridX === 0 && loc.gridY === 0) {
153 return false;
154 }
155
156 coord = coordFromXY(loc);
Steven Burrowsb11a8b82017-03-10 16:00:31 +0000157 el.fix(true);
Steven Burrows3db5ddb2017-02-17 15:21:20 +0000158 el.x = el.px = coord[0];
159 el.y = el.py = coord[1];
160
161 return true;
162 }
Steven Burrows1c5c8612016-10-05 13:45:13 -0500163 }
164
165 function coordFromLngLat(loc) {
166 var p = t2mcs.projection();
167 return p ? p([loc.lng, loc.lat]) : [0, 0];
168 }
169
Steven Burrows3db5ddb2017-02-17 15:21:20 +0000170 function coordFromXY(loc) {
Steven Burrowsbd402842017-03-08 21:30:38 +0000171
Steven Burrowse8a455a2017-03-16 16:58:59 +0000172 var bgWidth = t2sls.getWidth() || 100,
173 bgHeight = t2sls.getHeight() || 100;
Steven Burrowsbd402842017-03-08 21:30:38 +0000174
Steven Burrowse8a455a2017-03-16 16:58:59 +0000175 var scale = 1000 / bgWidth,
176 yOffset = (1000 - (bgHeight * scale)) / 2;
Steven Burrows3db5ddb2017-02-17 15:21:20 +0000177
Steven Burrows11162542017-02-27 21:52:56 +0000178 // 1000 is a hardcoded HTML value of the SVG element (topo2.html)
179 var x = scale * loc.gridX,
180 y = (scale * loc.gridY) + yOffset;
Steven Burrowsb43c1a92017-03-07 17:13:28 +0000181
Steven Burrows3db5ddb2017-02-17 15:21:20 +0000182 return [x, y];
183 }
184
Steven Burrows1c5c8612016-10-05 13:45:13 -0500185 angular.module('ovTopo2')
186 .factory('Topo2NodePositionService',
Simon Hunt2521d5f2017-03-20 18:17:28 -0700187 ['RandomService', 'Topo2MapConfigService',
188 'Topo2SpriteLayerService', 'Topo2BackgroundService',
Steven Burrows68d6f952017-03-10 13:53:35 +0000189 function (_rs_, _t2mcs_, _t2sls_, _t2bgs_) {
Steven Burrows1c5c8612016-10-05 13:45:13 -0500190
191 rs = _rs_;
192 t2mcs = _t2mcs_;
Steven Burrows3db5ddb2017-02-17 15:21:20 +0000193 t2sls = _t2sls_;
Steven Burrows68d6f952017-03-10 13:53:35 +0000194 t2bgs = _t2bgs_;
Steven Burrows1c5c8612016-10-05 13:45:13 -0500195
196 return {
197 positionNode: positionNode,
198 setLongLat: setLongLat
199 };
200 }
201 ]);
202})();