chg: [events:eventGraph] Improved hull algorithm and UI

pull/7024/head
mokaddem 2021-02-17 10:58:28 +01:00
parent cc4ef95da2
commit ad92322560
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
2 changed files with 80 additions and 32 deletions

View File

@ -21,6 +21,7 @@
'fields' => array('Tag.id', 'Tag.name'),
'sort' => array('lower(Tag.name) asc'),
));
$this->__extendedEventUUIDMapping = array();
$this->__extended_view = $extended_view;
$this->__lookupTables = array(
'analysisLevels' => $this->__eventModel->analysisLevels,
@ -266,6 +267,7 @@
'node_type' => 'attribute',
);
array_push($this->__json['items'], $toPush);
$this->__extendedEventUUIDMapping[$toPush['event_id']] = '';
}
foreach ($object as $obj) {
@ -290,6 +292,7 @@
}
array_push($this->__json['items'], $toPush);
$this->__extendedEventUUIDMapping[$toPush['event_id']] = '';
foreach ($obj['ObjectReference'] as $rel) {
$toPush = array(
@ -305,6 +308,11 @@
}
}
if ($this->__extended_view) {
$this->fetchEventUUIDFromId();
$this->__json['extended_event_uuid_mapping'] = $this->__extendedEventUUIDMapping;
}
return $this->__json;
}
@ -547,4 +555,13 @@
}
return $templates;
}
public function fetchEventUUIDFromId()
{
$eventUUIDs = $this->__eventModel->find('list', [
'conditions' => ['id' => array_keys($this->__extendedEventUUIDMapping)],
'fields' => ['uuid']
]);
$this->__extendedEventUUIDMapping = $eventUUIDs;
}
}

View File

@ -75,6 +75,7 @@ class EventGraph {
this.extended_event_color_mapping = {};
this.extended_event_points = {};
this.extended_event_uuid_mapping = {};
this.network = new vis.Network(container, data, this.network_options);
this.add_unreferenced_root_node();
@ -111,7 +112,7 @@ class EventGraph {
for (var event_id in that.extended_event_points) {
if (that.extended_event_color_mapping[event_id] === undefined) {
eventGraph.extended_event_color_mapping[event_id] = stringToRGB(event_id);
eventGraph.extended_event_color_mapping[event_id] = stringToRGB(that.extended_event_uuid_mapping[event_id]);
}
var chosen_color = eventGraph.extended_event_color_mapping[event_id];
@ -677,6 +678,7 @@ class EventGraph {
if (hard) {
this.backup_connection_edges = {};
this.extended_event_points = {};
this.extended_event_uuid_mapping = {};
this.extended_event_color_mapping = {};
}
}
@ -685,6 +687,8 @@ class EventGraph {
var that = this;
that.network_loading(true, loadingText_creating);
this.extended_event_uuid_mapping = data.extended_event_uuid_mapping;
// New nodes will be automatically added
// removed references will be deleted
var node_conf;
@ -1768,26 +1772,31 @@ class MispInteraction {
* UTILS
* ========*/
function drawExtendedEventHull(ctx, nodes, color, text) {
ctx.fillStyle = color+'88';
var hull = getHullFromPoints(nodes);
ctx.fillStyle = color+'55';
ctx.strokeStyle = color+'aa';
var centroid = getCentroid(nodes);
var hull = getHullFromPoints(nodes, centroid);
var hullExtraPoints = []
hull.forEach(p => {
hullExtraPoints.push(applyAngularOffsetForCentroid(p, centroid, false))
hullExtraPoints.push(p)
hullExtraPoints.push(applyAngularOffsetForCentroid(p, centroid, true))
})
centroid = getCentroid(hullExtraPoints);
var hullFinal = getHullFromPoints(hullExtraPoints, centroid);
hullFinal.push(hullFinal[0])
var start = hull[0];
var end = hull[hull.length-1];
var prev = start;
ctx.beginPath();
ctx.moveTo(start.x, start.y);
for (var i=1; i<hull.length; i++) {
var cur = hull[i];
ctx.lineTo(cur.x,cur.y);
prev = cur;
ctx.moveTo(hullFinal[0].x, hullFinal[0].y);
for(var i=1; i<hullFinal.length; i++) {
var cp_x_mid = (hullFinal[i-1].x + hullFinal[i].x) / 2;
var cp_y_mid = (hullFinal[i-1].y + hullFinal[i].y) / 2;
var cp = applyOffsetForCentroid({x: cp_x_mid, y: cp_y_mid}, centroid, 0.2)
ctx.quadraticCurveTo(cp.x, cp.y, hullFinal[i].x, hullFinal[i].y);
ctx.stroke();
}
ctx.moveTo(end.x, end.y);
var centerX = (end.x+start.x)/2;
var centerY = (end.y+start.y)/2;
ctx.quadraticCurveTo(centerX,centerY,start.x,start.y);
ctx.fill();
var centroid = getCentroid(hull);
ctx.beginPath();
ctx.font="30px Verdana";
ctx.fillStyle = getTextColour(color);
@ -1803,10 +1812,11 @@ function orientation(p, q, r) {
}
// Implementation of Gift wrapping algorithm (jarvis march in 2D)
// Inspired from https://www.geeksforgeeks.org/convex-hull-set-1-jarviss-algorithm-or-wrapping/
function getHullFromPoints(points) {
function getHullFromPoints(points, centroid) {
var n = points.length;
var l = 0;
var hull = [];
var cur_point;
// get leftmost point
for (var i=0; i<n; i++) {
l = points[l].x > points[i].x ? l : i;
@ -1815,7 +1825,9 @@ function getHullFromPoints(points) {
var p = l;
var q;
do {
hull.push(points[p]);
cur_point = points[p]
cur_point = applyOffsetForCentroid(cur_point, centroid)
hull.push(cur_point);
q = (p+1) % n;
for (var i=0; i<n; i++) {
@ -1828,21 +1840,40 @@ function getHullFromPoints(points) {
return hull;
}
function getCentroid(coordList) {
var cx = 0;
var cy = 0;
var a = 0;
for (var i=0; i<coordList.length; i++) {
var ci = coordList[i];
var cj = i+1 == coordList.length ? coordList[0] : coordList[i+1]; // j = i+1 AND loop around
var mul = (ci.x*cj.y - cj.x*ci.y);
cx += (ci.x + cj.x)*mul;
cy += (ci.y + cj.y)*mul;
a += mul;
var centroid = {x: 0, y: 0};
coordList.forEach(function(point) {
centroid.x += point.x;
centroid.y += point.y;
})
centroid.x = centroid.x / coordList.length;
centroid.y = centroid.y / coordList.length;
return centroid;
}
function applyOffsetForCentroid(point, centroid, ratio) {
ratio = ratio === undefined ? 1.0 : ratio;
var DEFAULT_OFFSET_X = 45 * ratio;
var DEFAULT_OFFSET_Y = 22 * ratio;
var slope = (point.y - centroid.y) / (point.x - centroid.x);
var angle = Math.atan(slope);
var sign = point.x > centroid.x ? 1 : -1;
var newPoint = {
x: point.x + Math.cos(angle) * DEFAULT_OFFSET_X * sign,
y: point.y + Math.sin(angle) * DEFAULT_OFFSET_Y * sign,
}
a = a / 2;
cx = cx / (6*a);
cy = cy / (6*a);
return {x: cx, y: cy};
return newPoint;
}
function applyAngularOffsetForCentroid(point, centroid, left) {
var DEFAULT_ANGULAR_OFFSET = 2;
var DEFAULT_OFFSET = 40;
var slope = (point.y - centroid.y) / (point.x - centroid.x);
var angle = Math.atan(slope);
angle = angle + ((left ? 1 : -1) * DEFAULT_ANGULAR_OFFSET);
var sign = point.x > centroid.x ? 1 : -1
var newPoint = {
x: point.x + Math.cos(angle) * DEFAULT_OFFSET * sign,
y: point.y + Math.sin(angle) * DEFAULT_OFFSET * sign,
}
return newPoint;
}
function generate_background_shortcuts(shortcut_text) {