| import EdgeBase from './EdgeBase' | |
| 
 | |
| class BezierEdgeBase extends EdgeBase { | |
|   constructor(options, body, labelModule) { | |
|     super(options, body, labelModule); | |
|   } | |
| 
 | |
|   /** | |
|    * This function uses binary search to look for the point where the bezier curve crosses the border of the node. | |
|    * | |
|    * @param nearNode | |
|    * @param ctx | |
|    * @param viaNode | |
|    * @param nearNode | |
|    * @param ctx | |
|    * @param viaNode | |
|    * @param nearNode | |
|    * @param ctx | |
|    * @param viaNode | |
|    */ | |
|   _findBorderPositionBezier(nearNode, ctx, viaNode = this._getViaCoordinates()) { | |
|     var maxIterations = 10; | |
|     var iteration = 0; | |
|     var low = 0; | |
|     var high = 1; | |
|     var pos, angle, distanceToBorder, distanceToPoint, difference; | |
|     var threshold = 0.2; | |
|     var node = this.to; | |
|     var from = false; | |
|     if (nearNode.id === this.from.id) { | |
|       node = this.from; | |
|       from = true; | |
|     } | |
| 
 | |
|     while (low <= high && iteration < maxIterations) { | |
|       var middle = (low + high) * 0.5; | |
| 
 | |
|       pos = this.getPoint(middle, viaNode); | |
|       angle = Math.atan2((node.y - pos.y), (node.x - pos.x)); | |
|       distanceToBorder = node.distanceToBorder(ctx, angle); | |
|       distanceToPoint = Math.sqrt(Math.pow(pos.x - node.x, 2) + Math.pow(pos.y - node.y, 2)); | |
|       difference = distanceToBorder - distanceToPoint; | |
|       if (Math.abs(difference) < threshold) { | |
|         break; // found | |
|       } | |
|       else if (difference < 0) { // distance to nodes is larger than distance to border --> t needs to be bigger if we're looking at the to node. | |
|         if (from === false) { | |
|           low = middle; | |
|         } | |
|         else { | |
|           high = middle; | |
|         } | |
|       } | |
|       else { | |
|         if (from === false) { | |
|           high = middle; | |
|         } | |
|         else { | |
|           low = middle; | |
|         } | |
|       } | |
| 
 | |
|       iteration++; | |
|     } | |
|     pos.t = middle; | |
| 
 | |
|     return pos; | |
|   } | |
| 
 | |
| 
 | |
| 
 | |
|   /** | |
|    * Calculate the distance between a point (x3,y3) and a line segment from | |
|    * (x1,y1) to (x2,y2). | |
|    * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment | |
|    * @param {number} x1 | |
|    * @param {number} y1 | |
|    * @param {number} x2 | |
|    * @param {number} y2 | |
|    * @param {number} x3 | |
|    * @param {number} y3 | |
|    * @private | |
|    */ | |
|   _getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via) { // x3,y3 is the point | |
|     let xVia, yVia; | |
|     xVia = via.x; | |
|     yVia = via.y; | |
|     let minDistance = 1e9; | |
|     let distance; | |
|     let i, t, x, y; | |
|     let lastX = x1; | |
|     let lastY = y1; | |
|     for (i = 1; i < 10; i++) { | |
|       t = 0.1 * i; | |
|       x = Math.pow(1 - t, 2) * x1 + (2 * t * (1 - t)) * xVia + Math.pow(t, 2) * x2; | |
|       y = Math.pow(1 - t, 2) * y1 + (2 * t * (1 - t)) * yVia + Math.pow(t, 2) * y2; | |
|       if (i > 0) { | |
|         distance = this._getDistanceToLine(lastX, lastY, x, y, x3, y3); | |
|         minDistance = distance < minDistance ? distance : minDistance; | |
|       } | |
|       lastX = x; | |
|       lastY = y; | |
|     } | |
| 
 | |
|     return minDistance; | |
|   } | |
| } | |
| 
 | |
| export default BezierEdgeBase;
 |