Revize 8dc25caa
Přidáno uživatelem Vojtěch Bartička před téměř 3 roky(ů)
Backend/Core/GraphUtils/Intersections.cs | ||
---|---|---|
1 |
using Core.Entities; |
|
2 | ||
3 |
namespace Core.GraphUtils |
|
4 |
{ |
|
5 |
public class Intersections |
|
6 |
{ |
|
7 |
public static Dictionary<AnnotationTag, List<AnnotationTag>> FindIntersections(List<AnnotationTag> tags) |
|
8 |
{ |
|
9 |
var intersections = new Dictionary<AnnotationTag, List<AnnotationTag>>(); |
|
10 | ||
11 |
for (int i = 0; i < tags.Count; i++) |
|
12 |
{ |
|
13 |
var tagWho = tags[i]; |
|
14 |
intersections[tagWho] = new(); |
|
15 |
for (int j = 0; j < tags.Count; j++) |
|
16 |
{ |
|
17 |
if (i == j) { continue; } |
|
18 |
var tagWith = tags[j]; |
|
19 | ||
20 |
if (!((tagWho.Position + tagWho.Length < tagWith.Position) || (tagWith.Position + tagWith.Length < tagWho.Position))) |
|
21 |
{ |
|
22 |
intersections[tagWho].Add(tagWith); |
|
23 |
} |
|
24 |
} |
|
25 |
} |
|
26 | ||
27 |
return intersections; |
|
28 |
} |
|
29 | ||
30 |
public static Dictionary<AnnotationTag, int> ColorGraph(Dictionary<AnnotationTag, List<AnnotationTag>> source) |
|
31 |
{ |
|
32 |
var res = ConvertToMatrix(source); |
|
33 |
var matrix = res.Item1; |
|
34 |
var tagToIntDict = res.Item2; |
|
35 |
var intToTagDict = res.Item3; |
|
36 | ||
37 |
var colors = new int[matrix.GetLength(0)]; |
|
38 |
for (int i = 0; i < colors.Length; i++) |
|
39 |
{ |
|
40 |
colors[i] = -1; |
|
41 |
} |
|
42 | ||
43 |
for (int coloredNode = 0; coloredNode < colors.Length; coloredNode++) |
|
44 |
{ |
|
45 |
var neighbours = GetNeighbours(coloredNode, matrix); |
|
46 |
var neighbourColors = GetNodeColors(neighbours, colors); |
|
47 |
colors[coloredNode] = GetLowestUnusedColor(neighbourColors); |
|
48 |
} |
|
49 | ||
50 |
var coloring = new Dictionary<AnnotationTag, int>(); |
|
51 |
for (int i = 0; i < colors.Length; i++) |
|
52 |
{ |
|
53 |
coloring[intToTagDict[i]] = colors[i]; |
|
54 |
} |
|
55 | ||
56 |
return coloring; |
|
57 |
} |
|
58 | ||
59 |
private static int GetLowestUnusedColor(List<int> colors) |
|
60 |
{ |
|
61 |
int lowestUnusedColor = 0; |
|
62 |
colors.Sort(); |
|
63 |
for (int i = 0; i < colors.Count; i++) |
|
64 |
{ |
|
65 |
if (colors[i] > i) |
|
66 |
{ |
|
67 |
lowestUnusedColor = i; |
|
68 |
break; |
|
69 |
} |
|
70 |
else |
|
71 |
{ |
|
72 |
lowestUnusedColor++; |
|
73 |
} |
|
74 |
} |
|
75 | ||
76 |
return lowestUnusedColor; |
|
77 |
} |
|
78 | ||
79 |
private static List<int> GetNodeColors(List<int> nodes, int[] colors) |
|
80 |
{ |
|
81 |
var usedColors = new List<int>(); |
|
82 |
foreach (var node in nodes) |
|
83 |
{ |
|
84 |
if (colors[node] != -1) |
|
85 |
{ |
|
86 |
usedColors.Add(colors[node]); |
|
87 |
} |
|
88 |
} |
|
89 | ||
90 |
return usedColors; |
|
91 |
} |
|
92 | ||
93 |
private static List<int> GetNeighbours(int node, int[,] matrix) |
|
94 |
{ |
|
95 |
List<int> neighbours = new(); |
|
96 |
for (int i = 0; i < matrix.GetLength(0); i++) |
|
97 |
{ |
|
98 |
if (matrix[node, i] == 1) |
|
99 |
{ |
|
100 |
neighbours.Add(i); |
|
101 |
} |
|
102 |
} |
|
103 | ||
104 |
return neighbours; |
|
105 |
} |
|
106 | ||
107 |
private static (int[,], Dictionary<AnnotationTag, int>, Dictionary<int, AnnotationTag>) ConvertToMatrix(Dictionary<AnnotationTag, List<AnnotationTag>> source) |
|
108 |
{ |
|
109 |
int[,] matrix = new int[source.Count, source.Count]; |
|
110 |
for (int i = 0; i < source.Count; i++) |
|
111 |
{ |
|
112 |
for (int j = 0; j < source.Count; j++) |
|
113 |
{ |
|
114 |
matrix[i, j] = 0; |
|
115 |
} |
|
116 |
} |
|
117 | ||
118 |
var tagToIntDict = new Dictionary<AnnotationTag, int>(); |
|
119 |
var intToTagDict = new Dictionary<int, AnnotationTag>(); |
|
120 | ||
121 |
int k = 0; |
|
122 |
foreach (var key in source.Keys) |
|
123 |
{ |
|
124 |
tagToIntDict[key] = k; |
|
125 |
intToTagDict[k] = key; |
|
126 |
k++; |
|
127 |
} |
|
128 | ||
129 |
foreach (var key in source.Keys) |
|
130 |
{ |
|
131 |
int keyInt = tagToIntDict[key]; |
|
132 |
foreach (var neighbour in source[key]) |
|
133 |
{ |
|
134 |
int neighbourInt = tagToIntDict[neighbour]; |
|
135 |
matrix[keyInt, neighbourInt] = 1; |
|
136 |
} |
|
137 |
} |
|
138 | ||
139 |
return (matrix, tagToIntDict, intToTagDict); |
|
140 |
} |
|
141 |
} |
|
142 |
} |
Backend/Core/Services/AnnotationService/AnnotationServiceEF.cs | ||
---|---|---|
15 | 15 |
using HtmlAgilityPack; |
16 | 16 |
using System.Text.RegularExpressions; |
17 | 17 |
using Newtonsoft.Json; |
18 |
using Core.GraphUtils; |
|
18 | 19 | |
19 | 20 |
namespace Core.Services.AnnotationService |
20 | 21 |
{ |
... | ... | |
293 | 294 | |
294 | 295 |
HtmlDocument doc = new HtmlDocument(); |
295 | 296 |
doc.LoadHtml(docToRender); |
296 |
var cssNode = GenerateCSS(doc, tags, new());
|
|
297 |
var cssNode = GenerateCSS(doc, tags); |
|
297 | 298 |
doc.DocumentNode.ChildNodes.Insert(0, cssNode); |
298 | 299 | |
299 | 300 |
return doc.DocumentNode.OuterHtml; |
... | ... | |
493 | 494 |
} |
494 | 495 |
} |
495 | 496 | |
496 |
private HtmlNode GenerateCSS(HtmlDocument docToEdit, List<AnnotationTag> tags, List<int> paddings)
|
|
497 |
private HtmlNode GenerateCSS(HtmlDocument docToEdit, List<AnnotationTag> tags) |
|
497 | 498 |
{ |
498 | 499 |
HtmlNode style = docToEdit.CreateElement("style"); |
499 | 500 | |
500 | 501 |
string inner = "span.annotation {border-bottom: 2px solid;}"; |
501 | 502 |
inner += "span {line-height: 30px}\n"; |
502 | 503 | |
503 |
// TODO temporary
|
|
504 |
int lastPadding = 0; |
|
504 |
var tagPaddingDict = Intersections.ColorGraph(Intersections.FindIntersections(tags));
|
|
505 | ||
505 | 506 |
foreach (var tag in tags) |
506 | 507 |
{ |
507 |
inner += $"span[{TAG_INSTANCE_ATTRIBUTE_NAME}=\"{tag.Instance}\"] {{ border-color:{tag.Tag.Color}; padding-bottom: {lastPadding % 5}px }}";
|
|
508 |
lastPadding += 2;
|
|
508 |
var padding = (tagPaddingDict[tag] + 1) * 2;
|
|
509 |
inner += $"span[{TAG_INSTANCE_ATTRIBUTE_NAME}=\"{tag.Instance}\"] {{ border-color:{tag.Tag.Color}; padding-bottom: {padding}px }}";
|
|
509 | 510 |
} |
510 | 511 | |
511 | 512 |
inner += "span[end=\"1\"] {border-end-end-radius: 0px; border-right: 1px solid darkgray}\n"; |
... | ... | |
621 | 622 |
} |
622 | 623 |
} |
623 | 624 | |
624 |
var cssNode = GenerateCSS(docToEdit, tags, new());
|
|
625 |
var cssNode = GenerateCSS(docToEdit, tags); |
|
625 | 626 |
docToEdit.DocumentNode.ChildNodes.Insert(0, cssNode); |
626 | 627 | |
627 | 628 |
return docToEdit.DocumentNode.OuterHtml; |
... | ... | |
691 | 692 |
} |
692 | 693 |
} |
693 | 694 | |
694 |
var cssNode = GenerateCSS(docToEdit, tags, new());
|
|
695 |
var cssNode = GenerateCSS(docToEdit, tags); |
|
695 | 696 |
docToEdit.DocumentNode.ChildNodes.Insert(0, cssNode); |
696 | 697 | |
697 | 698 |
return docToEdit.DocumentNode.OuterHtml; |
Také k dispozici: Unified diff
Added padding size calculation to html rendering