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.

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