mirror of https://github.com/MISP/MISP
chg: [events:eventGraph] Improved hull algorithm and UI
parent
cc4ef95da2
commit
ad92322560
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue