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.

192 lines
5.4 KiB

  1. import BezierEdgeBase from './util/BezierEdgeBase'
  2. class BezierEdgeStatic extends BezierEdgeBase {
  3. constructor(options, body, labelModule) {
  4. super(options, body, labelModule);
  5. }
  6. /**
  7. * Draw a line between two nodes
  8. * @param {CanvasRenderingContext2D} ctx
  9. * @param {Array<Object>} values
  10. * @param {vis.Node} viaNode
  11. * @private
  12. */
  13. _line(ctx, values, viaNode) {
  14. this._bezierCurve(ctx, values, viaNode);
  15. }
  16. getViaNode() {
  17. return this._getViaCoordinates();
  18. }
  19. /**
  20. * We do not use the to and fromPoints here to make the via nodes the same as edges without arrows.
  21. * @returns {{x: undefined, y: undefined}}
  22. * @private
  23. */
  24. _getViaCoordinates() {
  25. // Assumption: x/y coordinates in from/to always defined
  26. let xVia = undefined;
  27. let yVia = undefined;
  28. let factor = this.options.smooth.roundness;
  29. let type = this.options.smooth.type;
  30. let dx = Math.abs(this.from.x - this.to.x);
  31. let dy = Math.abs(this.from.y - this.to.y);
  32. if (type === 'discrete' || type === 'diagonalCross') {
  33. let stepX;
  34. let stepY;
  35. if (dx <= dy) {
  36. stepX = stepY = factor * dy;
  37. } else {
  38. stepX = stepY = factor * dx;
  39. }
  40. if (this.from.x > this.to.x) stepX = -stepX;
  41. if (this.from.y >= this.to.y) stepY = -stepY;
  42. xVia = this.from.x + stepX;
  43. yVia = this.from.y + stepY;
  44. if (type === "discrete") {
  45. if (dx <= dy) {
  46. xVia = dx < factor * dy ? this.from.x : xVia;
  47. } else {
  48. yVia = dy < factor * dx ? this.from.y : yVia;
  49. }
  50. }
  51. }
  52. else if (type === "straightCross") {
  53. let stepX = (1 - factor) * dx;
  54. let stepY = (1 - factor) * dy;
  55. if (dx <= dy) { // up - down
  56. stepX = 0;
  57. if (this.from.y < this.to.y) stepY = -stepY;
  58. }
  59. else { // left - right
  60. if (this.from.x < this.to.x) stepX = -stepX;
  61. stepY = 0;
  62. }
  63. xVia = this.to.x + stepX;
  64. yVia = this.to.y + stepY;
  65. }
  66. else if (type === 'horizontal') {
  67. let stepX = (1 - factor) * dx;
  68. if (this.from.x < this.to.x) stepX = -stepX;
  69. xVia = this.to.x + stepX;
  70. yVia = this.from.y;
  71. }
  72. else if (type === 'vertical') {
  73. let stepY = (1 - factor) * dy;
  74. if (this.from.y < this.to.y) stepY = -stepY;
  75. xVia = this.from.x;
  76. yVia = this.to.y + stepY;
  77. }
  78. else if (type === 'curvedCW') {
  79. dx = this.to.x - this.from.x;
  80. dy = this.from.y - this.to.y;
  81. let radius = Math.sqrt(dx * dx + dy * dy);
  82. let pi = Math.PI;
  83. let originalAngle = Math.atan2(dy, dx);
  84. let myAngle = (originalAngle + ((factor * 0.5) + 0.5) * pi) % (2 * pi);
  85. xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle);
  86. yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle);
  87. }
  88. else if (type === 'curvedCCW') {
  89. dx = this.to.x - this.from.x;
  90. dy = this.from.y - this.to.y;
  91. let radius = Math.sqrt(dx * dx + dy * dy);
  92. let pi = Math.PI;
  93. let originalAngle = Math.atan2(dy, dx);
  94. let myAngle = (originalAngle + ((-factor * 0.5) + 0.5) * pi) % (2 * pi);
  95. xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle);
  96. yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle);
  97. }
  98. else { // continuous
  99. let stepX;
  100. let stepY;
  101. if (dx <= dy) {
  102. stepX = stepY = factor * dy;
  103. } else {
  104. stepX = stepY = factor * dx;
  105. }
  106. if (this.from.x > this.to.x) stepX = -stepX;
  107. if (this.from.y >= this.to.y) stepY = -stepY;
  108. xVia = this.from.x + stepX;
  109. yVia = this.from.y + stepY;
  110. if (dx <= dy) {
  111. if (this.from.x <= this.to.x) {
  112. xVia = this.to.x < xVia ? this.to.x : xVia;
  113. }
  114. else {
  115. xVia = this.to.x > xVia ? this.to.x : xVia;
  116. }
  117. }
  118. else {
  119. if (this.from.y >= this.to.y) {
  120. yVia = this.to.y > yVia ? this.to.y : yVia;
  121. } else {
  122. yVia = this.to.y < yVia ? this.to.y : yVia;
  123. }
  124. }
  125. }
  126. return {x: xVia, y: yVia};
  127. }
  128. /**
  129. *
  130. * @param {vis.Node} nearNode
  131. * @param {CanvasRenderingContext2D} ctx
  132. * @param {Object} options
  133. * @returns {*}
  134. * @private
  135. */
  136. _findBorderPosition(nearNode, ctx, options = {}) {
  137. return this._findBorderPositionBezier(nearNode, ctx, options.via);
  138. }
  139. /**
  140. *
  141. * @param {number} x1
  142. * @param {number} y1
  143. * @param {number} x2
  144. * @param {number} y2
  145. * @param {number} x3
  146. * @param {number} y3
  147. * @param {vis.Node} viaNode
  148. * @returns {number}
  149. * @private
  150. */
  151. _getDistanceToEdge(x1, y1, x2, y2, x3, y3, viaNode = this._getViaCoordinates()) { // x3,y3 is the point
  152. return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, viaNode);
  153. }
  154. /**
  155. * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way
  156. * @param {number} percentage
  157. * @param {vis.Node} viaNode
  158. * @returns {{x: number, y: number}}
  159. * @private
  160. */
  161. getPoint(percentage, viaNode = this._getViaCoordinates()) {
  162. var t = percentage;
  163. var x = Math.pow(1 - t, 2) * this.fromPoint.x + (2 * t * (1 - t)) * viaNode.x + Math.pow(t, 2) * this.toPoint.x;
  164. var y = Math.pow(1 - t, 2) * this.fromPoint.y + (2 * t * (1 - t)) * viaNode.y + Math.pow(t, 2) * this.toPoint.y;
  165. return {x: x, y: y};
  166. }
  167. }
  168. export default BezierEdgeStatic;