diff --git a/script.js b/script.js index 98d7f7d..9f18c0f 100644 --- a/script.js +++ b/script.js @@ -1,3 +1,57 @@ +/** + * Finds the intersection point between + * * a rectangle centered in point B + * with sides parallel to the x and y axes + * * a line passing through points A and B (the center of the rectangle) + * + * @param width: rectangle width + * @param height: rectangle height + * @param xB; rectangle center x coordinate + * @param yB; rectangle center y coordinate + * @param xA; point A x coordinate + * @param yA; point A y coordinate + * @author Federico Destefanis + * @see <a href="https://stackoverflow.com/a/31254199/2668213">based on</a> + */ + +function lineIntersectionOnRect(width, height, xB, yB, xA, yA) { + + var w = width / 2; + var h = height / 2; + + var dx = xA - xB; + var dy = yA - yB; + + //if A=B return B itself + if (dx == 0 && dy == 0) return { + x: xB, + y: yB + }; + + var tan_phi = h / w; + var tan_theta = Math.abs(dy / dx); + + //tell me in which quadrant the A point is + var qx = Math.sign(dx); + var qy = Math.sign(dy); + + + if (tan_theta > tan_phi) { + xI = xB + (h / tan_theta) * qx; + yI = yB + h * qy; + } else { + xI = xB + w * qx; + yI = yB + w * tan_theta * qy; + } + + return { + x: xI, + y: yI + }; + +} + + const angle_between = (x1, y1, x2, y2) => { let angle = Math.atan2(y2-y1, x2-x1); if (angle < 0) angle += 2*Math.PI @@ -28,9 +82,9 @@ const box_intersection = (angle, box_width, box_height, border_radius) => { const half_height = box_height / 2; const half_width = box_width / 2; - if (hits_border_radius(angle, box_width, box_height, border_radius)) { - return arc_border_box_intersection(angle, half_width, half_height, border_radius) - } + // if (hits_border_radius(angle, box_width, box_height, border_radius)) { + // return arc_border_box_intersection(angle, half_width, half_height, border_radius) + // } return straight_border_box_intersection(angle, half_width, half_height) } @@ -40,6 +94,7 @@ const straight_border_box_intersection = (angle, box_width, box_height) => ({ x: Math.sin(angle) * box_height, }); + const arc_border_box_intersection = (angle, box_width, box_height, border_radius) => { //TODO: return 1; @@ -48,8 +103,9 @@ const arc_border_box_intersection = (angle, box_width, box_height, border_radius const SVG_WIDTH = 960; const SVG_HEIGHT = 500; -const BOX_WIDTH = 60; -const BOX_HEIGHT = 20; +const BOX_WIDTH = 120; +const BOX_HEIGHT = 40; +const BORDER_RADIUS = 10; const MARKER_VIEWBOX = { minX: 0, @@ -74,7 +130,7 @@ const graph = { x: 250, y: 250, w: BOX_WIDTH, - h: BOX_HEIGHT + 10, + h: BOX_HEIGHT, } ], links: [ @@ -150,6 +206,7 @@ const nodes = svg .attr('class', 'node-box') .attr('width', node => node.w) .attr('height', node => node.h) + .attr('rx', BORDER_RADIUS) .attr('x', node => node.x) .attr('y', node => node.y) .attr('id', node => node.name) @@ -184,13 +241,14 @@ const force = d3 .each(link => { const markerId = generateMarkerId(link.index); + //In radians const linkAngle = angle_between( link.source.x, -link.source.y, link.target.x, -link.target.y ); - + const intersectionPoint = box_intersection( linkAngle, link.target.w, @@ -198,11 +256,20 @@ const force = d3 0 ); + const intersect = lineIntersectionOnRect(BOX_WIDTH, BOX_HEIGHT, link.source.x, link.source.y, link.target.x, link.target.y); + const marker = d3.select(`#${markerId}`) - const distance = Math.sqrt( ((intersectionPoint.x)**2) + ((intersectionPoint.y) ** 2) ); + + let distance; + + // if(hits_border_radius(linkAngle, link.target.w, link.target.h, BORDER_RADIUS)) { + // distance = Math.sqrt( ((intersectionPoint.x)**2) + ((intersectionPoint.y) ** 2) ); + // } else { + distance = Math.sqrt(Math.pow(intersect.x - link.source.x, 2) + Math.pow(intersect.y - link.source.y, 2)); + // } marker.attr('refX', _ => { const markerHeight = MARKER_VIEWBOX.maxY - MARKER_VIEWBOX.minY - return distance + markerHeight + return distance + markerHeight/2 + 2; }); });