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.

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