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.

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