Rift.IO OSM R1 Initial Submission
[osm/UI.git] / skyquake / plugins / composer / src / src / libraries / graph / math.js
1
2 /*
3 *
4 * Copyright 2016 RIFT.IO Inc
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19 /**
20 * Created by onvelocity on 9/1/15.
21 */
22
23 import Position from './Position'
24
25 const angleOfLine = function (x1, y1, x2, y2) {
26
27 const y = y2 - y1;
28 const x = x2 - x1;
29
30 const rad = Math.atan2(y, x);
31 const deg = Math.abs(rad * 180 / Math.PI);
32
33 let addDeg = 0;
34
35 if (rad <= 0) {
36 addDeg = 360;
37 }
38
39 // - addDeg bc atan2 returns -π to π where -π is the upper side of rectangle
40 // - 360 bc our ui grid system has zero in upper left corner not lower left
41 return Math.abs(Math.abs(deg - addDeg) - 360);
42
43 };
44
45 const angleBetweenPositions = function (src, dst) {
46 if (!src instanceof Position) {
47 throw new ReferenceError('require a position instance');
48 }
49 if (!dst instanceof Position) {
50 throw new ReferenceError('require a position instance');
51 }
52 const srcCenter = src.centerPoint();
53 const dstCenter = dst.centerPoint();
54 return angleOfLine(srcCenter.x, srcCenter.y, dstCenter.x, dstCenter.y);
55 };
56
57 const distanceBetweenPositions = function (src, dst) {
58 if (!src instanceof Position) {
59 throw new ReferenceError('require a position instance');
60 }
61 if (!dst instanceof Position) {
62 throw new ReferenceError('require a position instance');
63 }
64 const srcCenter = src.centerPoint();
65 const dstCenter = dst.centerPoint();
66 const x = Math.pow(dstCenter.x - srcCenter.x, 2);
67 const y = Math.pow(dstCenter.y - srcCenter.y, 2);
68 const distance = Math.sqrt((x) + (y));
69 if (isNaN(distance)) {
70 console.log('nan distance', srcCenter, dstCenter);
71 }
72 return distance;
73 };
74
75 const rectangleAnglesFromCenter = function (position) {
76 /* given a rectangle defined by a Position, determine the angle of each corner from center.
77 // note: 0˚ is on x-axis; angles are given counterclockwise from x-axis
78 // for example:
79 // the line AB(0, 0, 5, 0) would have angle 0˚
80 // the line AC(0, 0, 0, 5) would have angle 90˚
81 // the line BC(5, 0, 0, 5) would have angle 135˚
82 // the line BA(5, 0, 0, 0) would have angle 180˚
83 */
84 if (!position instanceof Position) {
85 throw new ReferenceError('require a Position instance');
86 }
87 const center = position.centerPoint();
88 return [
89 angleOfLine(center.x, center.y, position.right, position.top),
90 angleOfLine(center.x, center.y, position.left, position.top),
91 angleOfLine(center.x, center.y, position.left, position.bottom),
92 angleOfLine(center.x, center.y, position.right, position.bottom)
93 ];
94 };
95
96 const edgeLocation = function (rectangleInclinations) {
97 /* given the angle of a line, determine which edge of the rectangle the line should attach. */
98 let inclinations = rectangleInclinations;
99 if (rectangleInclinations instanceof Position) {
100 inclinations = rectangleAnglesFromCenter(rectangleInclinations);
101 }
102 return angle => {
103 angle = parseFloat(angle);
104 if (angle >= inclinations[3]) {
105 return 'right';
106 }
107 if (angle >= 270) {
108 return 'bottom-right';
109 }
110 if (angle >= inclinations[2]) {
111 return 'bottom-left';
112 }
113 if (angle >= inclinations[1]) {
114 return 'left';
115 }
116 if (angle >= 90) {
117 return 'top-left';
118 }
119 if (angle >= inclinations[0]) {
120 return 'top-right';
121 }
122 return 'right';
123 };
124 };
125
126 const upperLowerEdgeLocation = function (angle) {
127 angle = parseFloat(angle);
128 if (angle > 270) {
129 return 'bottom-right';
130 }
131 if (angle > 180) {
132 return 'bottom-left';
133 }
134 if (angle > 90) {
135 return 'top-left';
136 }
137 return 'top-right';
138 };
139
140 export default {
141 angleOfLine: angleOfLine,
142 angleBetweenPositions: angleBetweenPositions,
143 distanceBetweenPositions: distanceBetweenPositions,
144 anglesFromCenter: rectangleAnglesFromCenter,
145 edgeLocation: edgeLocation,
146 upperLowerEdgeLocation: upperLowerEdgeLocation
147 }