vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
7.7 KiB

  1. /**
  2. * Created by Alex on 3/20/2015.
  3. */
  4. import BezierBaseEdge from './util/bezierBaseEdge'
  5. class BezierEdgeStatic extends BezierBaseEdge {
  6. constructor(options, body, labelModule) {
  7. super(options, body, labelModule);
  8. }
  9. cleanup() {}
  10. /**
  11. * Draw a line between two nodes
  12. * @param {CanvasRenderingContext2D} ctx
  13. * @private
  14. */
  15. _line(ctx) {
  16. // draw a straight line
  17. ctx.beginPath();
  18. ctx.moveTo(this.from.x, this.from.y);
  19. var via = this._getViaCoordinates();
  20. // fallback to normal straight edges
  21. if (via.x === undefined) {
  22. ctx.lineTo(this.to.x, this.to.y);
  23. ctx.stroke();
  24. return undefined;
  25. }
  26. else {
  27. ctx.quadraticCurveTo(via.x, via.y, this.to.x, this.to.y);
  28. ctx.stroke();
  29. return via;
  30. }
  31. }
  32. _getViaCoordinates() {
  33. let xVia = undefined;
  34. let yVia = undefined;
  35. let factor = this.options.smooth.roundness;
  36. let type = this.options.smooth.type;
  37. let dx = Math.abs(this.from.x - this.to.x);
  38. let dy = Math.abs(this.from.y - this.to.y);
  39. if (type == 'discrete' || type == 'diagonalCross') {
  40. if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) {
  41. if (this.from.y > this.to.y) {
  42. if (this.from.x < this.to.x) {
  43. xVia = this.from.x + factor * dy;
  44. yVia = this.from.y - factor * dy;
  45. }
  46. else if (this.from.x > this.to.x) {
  47. xVia = this.from.x - factor * dy;
  48. yVia = this.from.y - factor * dy;
  49. }
  50. }
  51. else if (this.from.y < this.to.y) {
  52. if (this.from.x < this.to.x) {
  53. xVia = this.from.x + factor * dy;
  54. yVia = this.from.y + factor * dy;
  55. }
  56. else if (this.from.x > this.to.x) {
  57. xVia = this.from.x - factor * dy;
  58. yVia = this.from.y + factor * dy;
  59. }
  60. }
  61. if (type == "discrete") {
  62. xVia = dx < factor * dy ? this.from.x : xVia;
  63. }
  64. }
  65. else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) {
  66. if (this.from.y > this.to.y) {
  67. if (this.from.x < this.to.x) {
  68. xVia = this.from.x + factor * dx;
  69. yVia = this.from.y - factor * dx;
  70. }
  71. else if (this.from.x > this.to.x) {
  72. xVia = this.from.x - factor * dx;
  73. yVia = this.from.y - factor * dx;
  74. }
  75. }
  76. else if (this.from.y < this.to.y) {
  77. if (this.from.x < this.to.x) {
  78. xVia = this.from.x + factor * dx;
  79. yVia = this.from.y + factor * dx;
  80. }
  81. else if (this.from.x > this.to.x) {
  82. xVia = this.from.x - factor * dx;
  83. yVia = this.from.y + factor * dx;
  84. }
  85. }
  86. if (type == "discrete") {
  87. yVia = dy < factor * dx ? this.from.y : yVia;
  88. }
  89. }
  90. }
  91. else if (type == "straightCross") {
  92. if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { // up - down
  93. xVia = this.from.x;
  94. if (this.from.y < this.to.y) {
  95. yVia = this.to.y - (1 - factor) * dy;
  96. }
  97. else {
  98. yVia = this.to.y + (1 - factor) * dy;
  99. }
  100. }
  101. else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { // left - right
  102. if (this.from.x < this.to.x) {
  103. xVia = this.to.x - (1 - factor) * dx;
  104. }
  105. else {
  106. xVia = this.to.x + (1 - factor) * dx;
  107. }
  108. yVia = this.from.y;
  109. }
  110. }
  111. else if (type == 'horizontal') {
  112. if (this.from.x < this.to.x) {
  113. xVia = this.to.x - (1 - factor) * dx;
  114. }
  115. else {
  116. xVia = this.to.x + (1 - factor) * dx;
  117. }
  118. yVia = this.from.y;
  119. }
  120. else if (type == 'vertical') {
  121. xVia = this.from.x;
  122. if (this.from.y < this.to.y) {
  123. yVia = this.to.y - (1 - factor) * dy;
  124. }
  125. else {
  126. yVia = this.to.y + (1 - factor) * dy;
  127. }
  128. }
  129. else if (type == 'curvedCW') {
  130. dx = this.to.x - this.from.x;
  131. dy = this.from.y - this.to.y;
  132. let radius = Math.sqrt(dx * dx + dy * dy);
  133. let pi = Math.PI;
  134. let originalAngle = Math.atan2(dy, dx);
  135. let myAngle = (originalAngle + ((factor * 0.5) + 0.5) * pi) % (2 * pi);
  136. xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle);
  137. yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle);
  138. }
  139. else if (type == 'curvedCCW') {
  140. dx = this.to.x - this.from.x;
  141. dy = this.from.y - this.to.y;
  142. let radius = Math.sqrt(dx * dx + dy * dy);
  143. let pi = Math.PI;
  144. let originalAngle = Math.atan2(dy, dx);
  145. let myAngle = (originalAngle + ((-factor * 0.5) + 0.5) * pi) % (2 * pi);
  146. xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle);
  147. yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle);
  148. }
  149. else { // continuous
  150. if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) {
  151. if (this.from.y > this.to.y) {
  152. if (this.from.x < this.to.x) {
  153. xVia = this.from.x + factor * dy;
  154. yVia = this.from.y - factor * dy;
  155. xVia = this.to.x < xVia ? this.to.x : xVia;
  156. }
  157. else if (this.from.x > this.to.x) {
  158. xVia = this.from.x - factor * dy;
  159. yVia = this.from.y - factor * dy;
  160. xVia = this.to.x > xVia ? this.to.x : xVia;
  161. }
  162. }
  163. else if (this.from.y < this.to.y) {
  164. if (this.from.x < this.to.x) {
  165. xVia = this.from.x + factor * dy;
  166. yVia = this.from.y + factor * dy;
  167. xVia = this.to.x < xVia ? this.to.x : xVia;
  168. }
  169. else if (this.from.x > this.to.x) {
  170. xVia = this.from.x - factor * dy;
  171. yVia = this.from.y + factor * dy;
  172. xVia = this.to.x > xVia ? this.to.x : xVia;
  173. }
  174. }
  175. }
  176. else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) {
  177. if (this.from.y > this.to.y) {
  178. if (this.from.x < this.to.x) {
  179. xVia = this.from.x + factor * dx;
  180. yVia = this.from.y - factor * dx;
  181. yVia = this.to.y > yVia ? this.to.y : yVia;
  182. }
  183. else if (this.from.x > this.to.x) {
  184. xVia = this.from.x - factor * dx;
  185. yVia = this.from.y - factor * dx;
  186. yVia = this.to.y > yVia ? this.to.y : yVia;
  187. }
  188. }
  189. else if (this.from.y < this.to.y) {
  190. if (this.from.x < this.to.x) {
  191. xVia = this.from.x + factor * dx;
  192. yVia = this.from.y + factor * dx;
  193. yVia = this.to.y < yVia ? this.to.y : yVia;
  194. }
  195. else if (this.from.x > this.to.x) {
  196. xVia = this.from.x - factor * dx;
  197. yVia = this.from.y + factor * dx;
  198. yVia = this.to.y < yVia ? this.to.y : yVia;
  199. }
  200. }
  201. }
  202. }
  203. return {x: xVia, y: yVia};
  204. }
  205. _findBorderPosition(nearNode, ctx, options) {
  206. return this._findBorderPositionBezier(nearNode, ctx, options.via);
  207. }
  208. _getDistanceToEdge(x1, y1, x2, y2, x3, y3, via = this._getViaCoordinates()) { // x3,y3 is the point
  209. return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via);
  210. }
  211. /**
  212. * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way
  213. * @param percentage
  214. * @param via
  215. * @returns {{x: number, y: number}}
  216. * @private
  217. */
  218. getPoint(percentage, via = this._getViaCoordinates()) {
  219. var t = percentage;
  220. var x = Math.pow(1 - t, 2) * this.from.x + (2 * t * (1 - t)) * via.x + Math.pow(t, 2) * this.to.x;
  221. var y = Math.pow(1 - t, 2) * this.from.y + (2 * t * (1 - t)) * via.y + Math.pow(t, 2) * this.to.y;
  222. return {x: x, y: y};
  223. }
  224. }
  225. export default BezierEdgeStatic;