Skip to content

Commit

Permalink
Reorganizing the computation of arrow positions and link positions fo…
Browse files Browse the repository at this point in the history
…r circle nodes
  • Loading branch information
Antonin committed Nov 30, 2019
1 parent d03ecff commit eb70936
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 12 deletions.
23 changes: 18 additions & 5 deletions src/components/graph/graph.builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import CONST from "./graph.const";

import { buildLinkPathDefinition } from "../link/link.helper";
import { getMarkerId } from "../marker/marker.helper";
import { getNormalizedNodeCoordinates } from "./graph.helper";

/**
* Get the correct node opacity in order to properly make decisions based on context such as currently highlighted node.
Expand Down Expand Up @@ -53,12 +54,16 @@ function _getNodeOpacity(node, highlightedNode, highlightedLink, config) {
*/
function buildLinkProps(link, nodes, links, config, linkCallbacks, highlightedNode, highlightedLink, transform) {
const { source, target } = link;
const x1 = nodes?.[source]?.x || 0;
const y1 = nodes?.[source]?.y || 0;
const x2 = nodes?.[target]?.x || 0;
const y2 = nodes?.[target]?.y || 0;

let x1 = nodes?.[source]?.x || 0;

let y1 = nodes?.[source]?.y || 0;

let x2 = nodes?.[target]?.x || 0;

let y2 = nodes?.[target]?.y || 0;

const type = link.type || config.link.type;
const d = buildLinkPathDefinition({ source: { x: x1, y: y1 }, target: { x: x2, y: y2 } }, type);

let mainNodeParticipates = false;

Expand Down Expand Up @@ -121,6 +126,14 @@ function buildLinkProps(link, nodes, links, config, linkCallbacks, highlightedNo
fontWeight = highlight ? config.link.highlightFontWeight : config.link.fontWeight;
}

const normalizedNodeCoordinates = getNormalizedNodeCoordinates(
{ source: { x: x1, y: y1 }, target: { x: x2, y: y2 } },
nodes,
config,
strokeWidth
);
const d = buildLinkPathDefinition(normalizedNodeCoordinates, type);

return {
className: CONST.LINK_CLASS_NAME,
d,
Expand Down
60 changes: 60 additions & 0 deletions src/components/graph/graph.helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -451,11 +451,71 @@ function updateNodeHighlightedValue(nodes, links, config, id, value = false) {
};
}

/**
* Computes the normalized vector from a vector
*
* @param {Object} vector a 2D vector with x and y components
* @param {number} vector.x x coordinate
* @param {number} vector.y y coordinate
* @returns {Object} normalized vector
*/
function normalize(vector) {
let norm = Math.sqrt(Math.pow(vector.x, 2) + Math.pow(vector.y, 2));

return { x: vector.x / norm, y: vector.y / norm };
}

/**
* Computes new node coordinates to make arrowheads point at nodes
*
* @param {Object} node - the couple of nodes we need to compute new coordinates
* @param {Object} node.source - node source
* @param {Object} node.target - node target
* @param {Object.<string, Object>} nodes - same as {@link #graphrenderer|nodes in renderGraph}.
* @param {Object} config - same as {@link #graphrenderer|config in renderGraph}.
* @param {number} strokeWidth width of the link stroke
* @returns {Object} new nodes coordinates
*
*/
function getNormalizedNodeCoordinates({ source = {}, target = {} }, nodes, config, strokeWidth) {
let { x: x1, y: y1 } = source;

let { x: x2, y: y2 } = target;

if (config.node) {
// Arrow configuration is only available for circles for now
switch (config.node.symbolType) {
case CONST.SYMBOLS.CIRCLE: {
let directionVector = normalize({ x: x2 - x1, y: y2 - y1 });

let strokeSize = strokeWidth * Math.min(config.link.markerWidth, config.link.markerHeight);

let nodeSize = nodes?.[source]?.size || config.node.size;

// cause this is a circle and A = pi * r^2
// We multiply by 0.95, because if we don't the link is not melting properly
nodeSize = Math.sqrt(nodeSize / Math.PI) * 0.95;

// Points from the source, we move them not to begin in the circle but outside
x1 += nodeSize * directionVector.x;
y1 += nodeSize * directionVector.y;
// Points from the target, we move the by the size of the radius of the circle + the size of the arrow
x2 -= (nodeSize + (config.directed ? strokeSize : 0)) * directionVector.x;
y2 -= (nodeSize + (config.directed ? strokeSize : 0)) * directionVector.y;
break;
}
}
}

return { source: { x: x1, y: y1 }, target: { x: x2, y: y2 } };
}

export {
checkForGraphConfigChanges,
checkForGraphElementsChanges,
getCenterAndZoomTransformation,
getId,
initializeGraphState,
updateNodeHighlightedValue,
getNormalizedNodeCoordinates,
};
8 changes: 3 additions & 5 deletions src/components/graph/graph.renderer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
import React from "react";

import CONST from "./graph.const";
import { MARKERS, MARKER_SMALL_SIZE, MARKER_MEDIUM_OFFSET, MARKER_LARGE_OFFSET } from "../marker/marker.const";
import { MARKERS } from "../marker/marker.const";

import Link from "../link/Link";
import Node from "../node/Node";
import Marker from "../marker/Marker";
import { buildLinkProps, buildNodeProps } from "./graph.builder";
import { getId } from "../graph/graph.helper";
import { isNodeVisible } from "./collapse.helper";
import { getMarkerSize } from "../marker/marker.helper";

/**
* Build Link components given a list of links.
Expand Down Expand Up @@ -105,10 +106,7 @@ function _renderDefs() {
return cachedDefs;
}

const small = MARKER_SMALL_SIZE;
const medium = small + (MARKER_MEDIUM_OFFSET * config.maxZoom) / 3;
const large = small + (MARKER_LARGE_OFFSET * config.maxZoom) / 3;

const { small, medium, large } = getMarkerSize(config);
const markerProps = {
markerWidth: config.link.markerWidth,
markerHeight: config.link.markerHeight,
Expand Down
39 changes: 37 additions & 2 deletions src/components/marker/marker.helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@
* @description
* Offers a series of methods to compute proper markers within a given context.
*/
import { MARKERS, SIZES, HIGHLIGHTED } from "./marker.const";
import {
MARKERS,
SIZES,
HIGHLIGHTED,
MARKER_SMALL_SIZE,
MARKER_MEDIUM_OFFSET,
MARKER_LARGE_OFFSET,
} from "./marker.const";
import CONST from "../graph/graph.const";

/**
* This function is a key template builder to access MARKERS structure.
Expand Down Expand Up @@ -93,4 +101,31 @@ function _memoizedComputeMarkerId() {
*/
const getMarkerId = _memoizedComputeMarkerId();

export { getMarkerId };
/**
* Computes the three marker sizes
*
* For supported shapes in {@link Graph/helper/getNormalizedNodeCoordinates}, the function should return 0,
* to be able to control more accurately nodes and arrows sizes and positions in directional graphs.
*
* @param {Object} config - the graph config object.
* @returns {Object} size of markers
*/
function getMarkerSize(config) {
let small = MARKER_SMALL_SIZE;

let medium = small + (MARKER_MEDIUM_OFFSET * config.maxZoom) / 3;

let large = small + (MARKER_LARGE_OFFSET * config.maxZoom) / 3;

switch (config.node.symbolType) {
case CONST.SYMBOLS.CIRCLE:
small = 0;
medium = 0;
large = 0;
break;
}

return { small: small, medium: medium, large: large };
}

export { getMarkerId, getMarkerSize };

0 comments on commit eb70936

Please sign in to comment.